diff options
| author | Wez Furlong <wez@php.net> | 2005-01-07 05:27:27 +0000 | 
|---|---|---|
| committer | Wez Furlong <wez@php.net> | 2005-01-07 05:27:27 +0000 | 
| commit | e6c282a76639fe4b6e9166210b4f338b83df44e7 (patch) | |
| tree | 6b0cb08f8b1efc397477efcfff0bbffaedbe0f36 /ext/pdo_sqlite/sqlite | |
| parent | 02d6b65c672835f27fd2b160338ab05f1dfca3a1 (diff) | |
| download | php-git-e6c282a76639fe4b6e9166210b4f338b83df44e7.tar.gz | |
jumbo commit; implement sqlstate error codes.
Bundle sqlite3
Diffstat (limited to 'ext/pdo_sqlite/sqlite')
97 files changed, 102316 insertions, 0 deletions
diff --git a/ext/pdo_sqlite/sqlite/Makefile.in b/ext/pdo_sqlite/sqlite/Makefile.in new file mode 100644 index 0000000000..3136476bcf --- /dev/null +++ b/ext/pdo_sqlite/sqlite/Makefile.in @@ -0,0 +1,586 @@ +#!/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 = @TARGET_CC@ @TARGET_CFLAGS@ -I. -I${TOP}/src -DNDEBUG + +# Some standard variables and programs +# +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +INSTALL = @INSTALL@ +LIBTOOL = ./libtool +RELEASE = @ALLOWRELEASE@ + +# libtool compile/link/install +LTCOMPILE = $(LIBTOOL) --mode=compile $(TCC) +LTLINK = $(LIBTOOL) --mode=link $(TCC) +LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) + +# Compiler options needed for programs that use the TCL library. +# +TCL_FLAGS = @TARGET_TCL_INC@ + +# The library that programs using TCL must link against. +# +LIBTCL = @TARGET_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 +# +THREADSAFE = -DTHREADSAFE=@THREADSAFE@ + +# The pthreads library if needed +# +LIBPTHREAD=@TARGET_THREAD_LIB@ + +# 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@ + +# You should not have to change anything below this line +############################################################################### + +# Object files for the SQLite library. +# +LIBOBJ = attach.lo auth.lo btree.lo build.lo date.lo delete.lo \ +         expr.lo func.lo hash.lo insert.lo \ +         main.lo opcodes.lo os_mac.lo os_unix.lo os_win.lo \ +         pager.lo parse.lo pragma.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 vdbemem.lo \ +         where.lo utf.lo legacy.lo + +# All of the source code files. +# +SRC = \ +  $(TOP)/src/attach.c \ +  $(TOP)/src/auth.c \ +  $(TOP)/src/btree.c \ +  $(TOP)/src/btree.h \ +  $(TOP)/src/build.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/legacy.c \ +  $(TOP)/src/main.c \ +  $(TOP)/src/os_mac.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/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/vdbemem.c \ +  $(TOP)/src/vdbeInt.h \ +  $(TOP)/src/where.c + +# Source code to the test files. +# +TESTSRC = \ +  $(TOP)/src/btree.c \ +  $(TOP)/src/func.c \ +  $(TOP)/src/os_mac.c \ +  $(TOP)/src/os_unix.c \ +  $(TOP)/src/os_win.c \ +  $(TOP)/src/pager.c \ +  $(TOP)/src/pragma.c \ +  $(TOP)/src/printf.c \ +  $(TOP)/src/test1.c \ +  $(TOP)/src/test2.c \ +  $(TOP)/src/test3.c \ +  $(TOP)/src/test4.c \ +  $(TOP)/src/test5.c \ +  $(TOP)/src/utf.c \ +  $(TOP)/src/util.c \ +  $(TOP)/src/vdbe.c \ +  $(TOP)/src/md5.c + +# Header files used by all library source files. +# +HDR = \ +   sqlite3.h  \ +   $(TOP)/src/btree.h \ +   config.h \ +   $(TOP)/src/hash.h \ +   opcodes.h \ +   $(TOP)/src/os.h \ +   $(TOP)/src/os_common.h \ +   $(TOP)/src/os_mac.h \ +   $(TOP)/src/os_unix.h \ +   $(TOP)/src/os_win.h \ +   $(TOP)/src/sqliteInt.h  \ +   $(TOP)/src/vdbe.h \ +   parse.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@TARGET_EXEEXT@ + +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 +4 | tail -1 \ +          | awk '{print $$5,$$6}' >last_change + +libsqlite3.la:	$(LIBOBJ) +	$(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \ +		${RELEASE} -rpath $(libdir) -version-info "8:6:8" + +libtclsqlite3.la:	tclsqlite.lo libsqlite3.la +	$(LTLINK) -o libtclsqlite3.la tclsqlite.lo \ +		libsqlite3.la $(LIBTCL) $(LIBPTHREAD) -rpath $(libdir)/sqlite \ +		-version-info "8:6:8" + +sqlite3@TARGET_EXEEXT@:	$(TOP)/src/shell.c libsqlite3.la sqlite3.h +	$(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ +		-o sqlite3 $(TOP)/src/shell.c libsqlite3.la $(LIBREADLINE) + +# 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) $(VDBEHDR)  +	rm -rf tsrc +	mkdir -p tsrc +	cp $(SRC) $(VDBEHDR) tsrc +	rm tsrc/sqlite.h.in tsrc/parse.y +	cp parse.c opcodes.c tsrc +	cp $(TOP)/sqlite3.def tsrc + +# Rules to build the LEMON compiler generator +# +lemon@BUILD_EXEEXT@:	$(TOP)/tool/lemon.c $(TOP)/tool/lempar.c +	$(BCC) -o lemon $(TOP)/tool/lemon.c +	cp $(TOP)/tool/lempar.c . + + +# Rules to build individual files +# +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 + +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 + +# The config.h file will contain a single #define that tells us how +# many bytes are in a pointer.  This only works if a pointer is the +# same size on the host as it is on the target.  If you are cross-compiling +# to a target with a different pointer size, you'll need to manually +# configure the config.h file. +# +config.h:	 +	echo '#include <stdio.h>' >temp.c +	echo 'int main(){printf(' >>temp.c +	echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c +	echo 'exit(0);}' >>temp.c +	$(BCC) -o temp temp.c +	./temp >config.h +	echo >>config.h +	rm -f temp.c temp + +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 + +legacy.lo:	$(TOP)/src/legacy.c $(HDR) +	$(LTCOMPILE) -c $(TOP)/src/legacy.c + +main.lo:	$(TOP)/src/main.c $(HDR) +	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.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 +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c + +opcodes.h:	parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk +	cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h + +os_mac.lo:	$(TOP)/src/os_mac.c $(HDR) +	$(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_mac.c + +os_unix.lo:	$(TOP)/src/os_unix.c $(HDR) +	$(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_unix.c + +os_win.lo:	$(TOP)/src/os_win.c $(HDR) +	$(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_win.c + +parse.lo:	parse.c $(HDR) +	$(LTCOMPILE) -c parse.c + +parse.h:	parse.c + +parse.c:	$(TOP)/src/parse.y lemon@BUILD_EXEEXT@ +	cp $(TOP)/src/parse.y . +	./lemon parse.y + +pragma.lo:	$(TOP)/src/pragma.c $(HDR) +	$(LTCOMPILE) $(TCL_FLAGS) -c $(TOP)/src/pragma.c + +printf.lo:	$(TOP)/src/printf.c $(HDR) +	$(LTCOMPILE) $(TCL_FLAGS) -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--/`cat ${TOP}/VERSION`/ \ +                 $(TOP)/src/sqlite.h.in >sqlite3.h + +table.lo:	$(TOP)/src/table.c $(HDR) +	$(LTCOMPILE) -c $(TOP)/src/table.c + +tclsqlite.lo:	$(TOP)/src/tclsqlite.c $(HDR) +	$(LTCOMPILE) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c + +tokenize.lo:	$(TOP)/src/tokenize.c $(HDR) +	$(LTCOMPILE) -c $(TOP)/src/tokenize.c + +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 + +vdbemem.lo:	$(TOP)/src/vdbemem.c $(VDBEHDR) +	$(LTCOMPILE) -c $(TOP)/src/vdbemem.c + +where.lo:	$(TOP)/src/where.c $(HDR) +	$(LTCOMPILE) -c $(TOP)/src/where.c + +tclsqlite-sh.lo:	$(TOP)/src/tclsqlite.c $(HDR) +	$(LTCOMPILE) $(TCL_FLAGS) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite3:	tclsqlite-sh.lo libsqlite3.la +	$(LTLINK) $(TCL_FLAGS) -o tclsqlite3 tclsqlite-sh.lo \ +		 libsqlite3.la $(LIBTCL) + +testfixture@TARGET_EXEEXT@:	$(TOP)/src/tclsqlite.c libtclsqlite3.la libsqlite3.la $(TESTSRC) +	$(LTLINK) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1\ +                $(THREADSAFE) $(TEMP_STORE)\ +                -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ +		libtclsqlite3.la libsqlite3.la $(LIBTCL) + +crashtest@TARGET_EXEEXT@:	$(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) $(TOP)/src/os_test.c +	$(LTLINK) $(TCL_FLAGS) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \ +		-o crashtest \ +		$(TESTSRC) $(TOP)/src/os_test.c $(TOP)/src/tclsqlite.c \ +		libsqlite3.la $(LIBTCL) $(THREADLIB) + + + +fulltest:	testfixture@TARGET_EXEEXT@ sqlite3@TARGET_EXEEXT@ crashtest@TARGET_EXEEXT@ +	./testfixture $(TOP)/test/all.test + +test:	testfixture@TARGET_EXEEXT@ sqlite3@TARGET_EXEEXT@ +	./testfixture $(TOP)/test/quick.test + + +# Rules used to build documentation +# +arch.html:	$(TOP)/www/arch.tcl +	tclsh $(TOP)/www/arch.tcl >arch.html + +arch2.gif:	$(TOP)/www/arch2.gif +	cp $(TOP)/www/arch2.gif . + +c_interface.html:	$(TOP)/www/c_interface.tcl +	tclsh $(TOP)/www/c_interface.tcl >c_interface.html + +capi3.html:	$(TOP)/www/capi3.tcl +	tclsh $(TOP)/www/capi3.tcl >capi3.html + +capi3ref.html:	$(TOP)/www/capi3ref.tcl +	tclsh $(TOP)/www/capi3ref.tcl >capi3ref.html + +changes.html:	$(TOP)/www/changes.tcl +	tclsh $(TOP)/www/changes.tcl >changes.html + +copyright.html:	$(TOP)/www/copyright.tcl +	tclsh $(TOP)/www/copyright.tcl >copyright.html + +copyright-release.html:	$(TOP)/www/copyright-release.html +	cp $(TOP)/www/copyright-release.html . + +copyright-release.pdf:	$(TOP)/www/copyright-release.pdf +	cp $(TOP)/www/copyright-release.pdf . + +common.tcl:	$(TOP)/www/common.tcl +	cp $(TOP)/www/common.tcl . + +conflict.html:	$(TOP)/www/conflict.tcl +	tclsh $(TOP)/www/conflict.tcl >conflict.html + +datatypes.html:	$(TOP)/www/datatypes.tcl +	tclsh $(TOP)/www/datatypes.tcl >datatypes.html + +datatype3.html:	$(TOP)/www/datatype3.tcl +	tclsh $(TOP)/www/datatype3.tcl >datatype3.html + +docs.html:	$(TOP)/www/docs.tcl +	tclsh $(TOP)/www/docs.tcl >docs.html + +download.html:	$(TOP)/www/download.tcl +	mkdir -p doc +	tclsh $(TOP)/www/download.tcl >download.html + +faq.html:	$(TOP)/www/faq.tcl +	tclsh $(TOP)/www/faq.tcl >faq.html + +fileformat.html:	$(TOP)/www/fileformat.tcl +	tclsh $(TOP)/www/fileformat.tcl >fileformat.html + +formatchng.html:	$(TOP)/www/formatchng.tcl +	tclsh $(TOP)/www/formatchng.tcl >formatchng.html + +index.html:	$(TOP)/www/index.tcl last_change +	tclsh $(TOP)/www/index.tcl >index.html + +lang.html:	$(TOP)/www/lang.tcl +	tclsh $(TOP)/www/lang.tcl >lang.html + +lockingv3.html:	$(TOP)/www/lockingv3.tcl +	tclsh $(TOP)/www/lockingv3.tcl >lockingv3.html + +oldnews.html:	$(TOP)/www/oldnews.tcl +	tclsh $(TOP)/www/oldnews.tcl >oldnews.html + +omitted.html:	$(TOP)/www/omitted.tcl +	tclsh $(TOP)/www/omitted.tcl >omitted.html + +opcode.html:	$(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c +	tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html + +mingw.html:	$(TOP)/www/mingw.tcl +	tclsh $(TOP)/www/mingw.tcl >mingw.html + +nulls.html:	$(TOP)/www/nulls.tcl +	tclsh $(TOP)/www/nulls.tcl >nulls.html + +quickstart.html:	$(TOP)/www/quickstart.tcl +	tclsh $(TOP)/www/quickstart.tcl >quickstart.html + +speed.html:	$(TOP)/www/speed.tcl +	tclsh $(TOP)/www/speed.tcl >speed.html + +sqlite.gif:	$(TOP)/art/SQLite.gif +	cp $(TOP)/art/SQLite.gif sqlite.gif + +sqlite.html:	$(TOP)/www/sqlite.tcl +	tclsh $(TOP)/www/sqlite.tcl >sqlite.html + +support.html:	$(TOP)/www/support.tcl +	tclsh $(TOP)/www/support.tcl >support.html + +tclsqlite.html:	$(TOP)/www/tclsqlite.tcl +	tclsh $(TOP)/www/tclsqlite.tcl >tclsqlite.html + +vdbe.html:	$(TOP)/www/vdbe.tcl +	tclsh $(TOP)/www/vdbe.tcl >vdbe.html + +version3.html:	$(TOP)/www/version3.tcl +	tclsh $(TOP)/www/version3.tcl >version3.html + + +# Files to be published on the website. +# +DOC = \ +  arch.html \ +  arch2.gif \ +  c_interface.html \ +  capi3.html \ +  capi3ref.html \ +  changes.html \ +  copyright.html \ +  copyright-release.html \ +  copyright-release.pdf \ +  conflict.html \ +  datatypes.html \ +  datatype3.html \ +  docs.html \ +  download.html \ +  faq.html \ +  fileformat.html \ +  formatchng.html \ +  index.html \ +  lang.html \ +  lockingv3.html \ +  mingw.html \ +  nulls.html \ +  oldnews.html \ +  omitted.html \ +  opcode.html \ +  quickstart.html \ +  speed.html \ +  sqlite.gif \ +  sqlite.html \ +  support.html \ +  tclsqlite.html \ +  vdbe.html \ +  version3.html + +doc:	common.tcl $(DOC) +	mkdir -p doc +	mv $(DOC) doc + +install:	sqlite3 libsqlite3.la sqlite3.h +	$(INSTALL) -d $(DESTDIR)$(libdir) +	$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) +	$(INSTALL) -d $(DESTDIR)$(exec_prefix)/bin +	$(LTINSTALL) sqlite3 $(DESTDIR)$(exec_prefix)/bin +	$(INSTALL) -d $(DESTDIR)$(prefix)/include +	$(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(prefix)/include +	$(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig;  +	$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(libdir)/pkgconfig;  + +clean:	 +	rm -f *.lo *.la *.o sqlite3@TARGET_EXEEXT@ libsqlite3.la +	rm -f sqlite3.h opcodes.* +	rm -rf .libs .deps  +	rm -f lemon@BUILD_EXEEXT@ lempar.c parse.* sqlite*.tar.gz +	rm -f $(PUBLISH) +	rm -f *.da *.bb *.bbg gmon.out +	rm -f testfixture@TARGET_EXEEXT@ test.db +	rm -rf doc +	rm -f common.tcl +	rm -f sqlite3.dll sqlite3.lib + +# +# Windows section; all this funky .dll stuff ;-) +# +dll: sqlite3.dll + +REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o) + +sqlite3.dll: $(LIBOBJ) $(TOP)/sqlite3.def +	dllwrap --dllname sqlite3.dll --def $(TOP)/sqlite3.def $(REAL_LIBOBJ) +	strip sqlite3.dll + +#target for dll import libraries +implib: sqlite3.lib  + +#make Borland C++ and/or Microsoft VC import library for the dll +#   ignore any errors (usually due to missing programs) +sqlite3.lib: sqlite3.dll +	-implib -a sqlite3.lib sqlite3.dll +	-lib /machine:i386 /def:$(TOP)/sqlite3.def  + +distclean:	clean +	rm -f config.log config.status libtool Makefile config.h diff --git a/ext/pdo_sqlite/sqlite/Makefile.linux-gcc b/ext/pdo_sqlite/sqlite/Makefile.linux-gcc new file mode 100644 index 0000000000..aa5ced6ab5 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/Makefile.linux-gcc @@ -0,0 +1,112 @@ +#!/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 =  + +#### 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 + +#### 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 + +#### 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 + +#### 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 + +#### Should the database engine assume text is coded as UTF-8 or iso8859? +# +# ENCODING  = UTF8 +ENCODING = ISO8859 + +# You should not have to change anything below this line +############################################################################### +include $(TOP)/main.mk diff --git a/ext/pdo_sqlite/sqlite/README b/ext/pdo_sqlite/sqlite/README new file mode 100644 index 0000000000..be1fa31568 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/README @@ -0,0 +1,34 @@ +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. + +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/ext/pdo_sqlite/sqlite/VERSION b/ext/pdo_sqlite/sqlite/VERSION new file mode 100644 index 0000000000..67786e246e --- /dev/null +++ b/ext/pdo_sqlite/sqlite/VERSION @@ -0,0 +1 @@ +3.0.8 diff --git a/ext/pdo_sqlite/sqlite/aclocal.m4 b/ext/pdo_sqlite/sqlite/aclocal.m4 new file mode 100644 index 0000000000..852eb3134b --- /dev/null +++ b/ext/pdo_sqlite/sqlite/aclocal.m4 @@ -0,0 +1,5913 @@ +# generated automatically by aclocal 1.8.2 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +# 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 47 AC_PROG_LIBTOOL +# Debian $Rev: 192 $ + + +# 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 s/^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 M$VC, +# 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 "$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="\$RANLIB -t \$oldlib~$old_postinstall_cmds" +    ;; +  *) +    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +    ;; +  esac +  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# 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 + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _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"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _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 <<EOF +[$]* +EOF +  exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +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 +  ;; +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}? :&$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 +     if test ! -s conftest.err; 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 compiler 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 +     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 +  testring="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; +    ;; + + *) +    # 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"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ +	       = "XX$testring") >/dev/null 2>&1 && +	    new_result=`expr "X$testring" : ".*" 2>&1` && +	    lt_cv_sys_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. +    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 <<EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    exit (status); +}] +EOF +  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then +    (./conftest; exit; ) 2>/dev/null +    lt_status=$? +    case x$lt_status in +      x$lt_dlno_uscore) $1 ;; +      x$lt_dlneed_uscore) $2 ;; +      x$lt_unknown|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" +    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 +      LDFLAGS="$LDFLAGS $link_static_flag" +      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}? :&$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 +     if test ! -s out/conftest.err; then +       _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes +     fi +   fi +   chmod u+w . +   $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=".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<name>.so +      # instead of lib<name>.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 +  ;; + +bsdi4*) +  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=".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' +    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 +    ;; + +  *) +    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='$(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*) +  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +  version_type=freebsd-$objformat +  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 +      ;; +  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 +    ;; +  *) # from 3.2 on +    shlibpath_overrides_runpath=no +    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='.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='.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='.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' +  ;; + +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 +    ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf` +    sys_lib_dlsearch_path_spec="/lib /usr/lib $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 +  need_lib_prefix=no +  need_version=yes +  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=".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" +  ;; + +sco3.2v5*) +  version_type=osf +  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 +  ;; + +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.2uw2* | sysv4.3* | sysv5*) +  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 +  ;; + +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 +])# 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 + +  # 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"; 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 dll's +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 <<EOF 1>&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 GNU ld's only accept -v. +      # Break only if it was the GNU/non-GNU ld that we prefer. +      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in +      *GNU* | *'with BFD'*) +	test "$with_gnu_ld" != no && break +	;; +      *) +	test "$with_gnu_ld" != yes && break +	;; +      esac +    fi +  done +  IFS="$lt_save_ifs" +else +  lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then +  AC_MSG_RESULT($LD) +else +  AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +])# AC_PROG_LD + + +# AC_PROG_LD_GNU +# -------------- +AC_DEFUN([AC_PROG_LD_GNU], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) +  lt_cv_prog_gnu_ld=yes +  ;; +*) +  lt_cv_prog_gnu_ld=no +  ;; +esac]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# AC_PROG_LD_GNU + + +# AC_PROG_LD_RELOAD_FLAG +# ---------------------- +# find reload flag for linker +#   -- PORTME Some linkers may need a different reload flag. +AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], +[AC_CACHE_CHECK([for $LD option to reload object files], +  lt_cv_ld_reload_flag, +  [lt_cv_ld_reload_flag='-r']) +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' +])# AC_PROG_LD_RELOAD_FLAG + + +# AC_DEPLIBS_CHECK_METHOD +# ----------------------- +# how to check for library dependencies +#  -- PORTME fill in with the dynamic library characteristics +AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +[AC_CACHE_CHECK([how to recognise dependent libraries], +lt_cv_deplibs_check_method, +[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 +  ;; + +bsdi4*) +  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*) +  # 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='win32_libid' +  ;; + +mingw* | pw32*) +  # Base MSYS/MinGW do not provide the 'file' command needed by +  # 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) +  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)/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 +  ;; + +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* | knetbsd*-gnu) +  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*) +  lt_cv_file_magic_cmd=/usr/bin/file +  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` +  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' +  else +    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' +  fi +  ;; + +osf3* | osf4* | osf5*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +sco3.2v5*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +solaris*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +  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 +    ;; +  esac +  ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | 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_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do +    IFS="$lt_save_ifs" +    test -z "$ac_dir" && ac_dir=. +    tmp_nm="$ac_dir/${ac_tool_prefix}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" +  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 LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  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 LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  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 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. +# 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([AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + + +# 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 + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then +  case $host_os in +  sco3.2v5*) +    _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' +    ;; +  esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then +  AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) +  if echo "$old_CC $old_CFLAGS " | grep "[[ 	]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ 	]]" >/dev/null; then : +  else +    AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) +    _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no +  fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], +  _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), +  $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), +  [], +  [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +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($1) + +# Report which librarie types wil 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*) +  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then +    test "$enable_shared" = yes && enable_static=no +  fi +  ;; +  darwin* | rhapsody*) +  if test "$GCC" = yes; then +    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +    case "$host_os" in +    rhapsody* | darwin1.[[012]]) +      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' +      ;; +    *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	_LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[[012]]) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +            ;; +          10.*) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' +            ;; +        esac +      fi +      ;; +    esac +    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 ld's +    _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}' +    _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)='-all_load $convenience' +    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes +  else +    _LT_AC_TAGVAR(ld_shlibs, $1)=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([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_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=cc + +# 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 + +# 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 +  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 +  unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# 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' +    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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	# -bexpall does not export symbols beginning with underscore (_) +	_LT_AC_TAGVAR(always_export_symbols, $1)=yes +	# Exported symbols can be pulled into shared objects from archives +	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' +	_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes +	# This is similar to how AIX traditionally builds it's shared libraries. +	_LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' +      fi +    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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000 ${wl}--out-implib,$lib' +    else +      _LT_AC_TAGVAR(ld_shlibs, $1)=no +    fi +  ;; + +  darwin* | rhapsody*) +  if test "$GXX" = yes; then +    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +    case "$host_os" in +    rhapsody* | darwin1.[[012]]) +      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' +      ;; +    *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	_LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[[012]]) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +            ;; +          10.*) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' +            ;; +        esac +      fi +      ;; +    esac +    lt_int_apple_cc_single_mod=no +    output_verbose_link_cmd='echo' +    if $CC -dumpspecs 2>&1 | grep '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 ${wl}-bind_at_load -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 ${wl}-bind_at_load $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 ld's +    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 ${wl}-bind_at_load -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}' +    _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)='-all_load $convenience' +    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes +  else +    _LT_AC_TAGVAR(ld_shlibs, $1)=no +  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) +    # 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) | egrep "\-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 +      case "$host_cpu" in +      hppa*64*) +	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' +	_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' +	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: +        ;; +      ia64*) +	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' +        ;; +      *) +	_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' +        ;; +      esac +    fi +    case "$host_cpu" in +    hppa*64*) +      _LT_AC_TAGVAR(hardcode_direct, $1)=no +      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +      ;; +    ia64*) +      _LT_AC_TAGVAR(hardcode_direct, $1)=no +      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, +					      # but as the default +					      # location of the library. +      ;; +    *) +      _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*|ia64*) +	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' +	  ;; +	*) +	  _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 +	    ia64*|hppa*64*) +	      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' +	      ;; +	    *) +	      _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 +    ;; +  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 ${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}${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 +	_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +	_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' +	_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' +	;; +      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* | knetbsd*-gnu) +    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::"' +    ;; +  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 ${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}${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 ${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 $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}${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 +    ;; +  sco*) +    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +    case $cc_basename in +      CC) +	# 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 +    ;; +  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(no_undefined_flag, $1)=' -zdefs' +	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -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} -nolib ${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. +	    # Supported since Solaris 2.6 (maybe 2.5.1?) +	    _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' +	    ;; +	esac +	_LT_AC_TAGVAR(link_all_deplibs, $1)=yes + +	# 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 -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + +	# 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 +    ;; +  sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) +    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +    ;; +  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_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($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 <<EOF +int a; +void foo (void) { a = 0; } +EOF +],[$1],[CXX],[cat > conftest.$ac_ext <<EOF +class Foo +{ +public: +  Foo (void) { a = 0; } +private: +  int a; +}; +EOF +],[$1],[F77],[cat > conftest.$ac_ext <<EOF +      subroutine foo +      implicit none +      integer*4 a +      a=0 +      return +      end +EOF +],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF +public class foo { +  private int a; +  public void bar (void) { +    a = 0; +  } +}; +EOF +]) +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); 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 "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then +	     _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" +	   else +	     _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${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 "$_LT_AC_TAGVAR(postdeps, $1)"; then +	   _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}" +	 else +	   _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${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 "$_LT_AC_TAGVAR(predep_objects, $1)"; then +	   _LT_AC_TAGVAR(predep_objects, $1)="$p" +	 else +	   _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p" +	 fi +       else +	 if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then +	   _LT_AC_TAGVAR(postdep_objects, $1)="$p" +	 else +	   _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p" +	 fi +       fi +       ;; + +    *) ;; # Ignore the rest. + +    esac +  done + +  # Clean up. +  rm -f a.out a.exe +else +  echo "libtool.m4: error: problem compiling $1 test program" +fi + +$rm -f confest.$objext + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac +])# AC_LIBTOOL_POSTDEP_PREDEP + +# AC_LIBTOOL_LANG_F77_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_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) +AC_DEFUN([_LT_AC_LANG_F77_CONFIG], +[AC_REQUIRE([AC_PROG_F77]) +AC_LANG_PUSH(Fortran 77) + +_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_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 + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$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. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +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*) +  test "$enable_shared" = yes && enable_static=no +  ;; +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]) + +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$G77" +_LT_AC_TAGVAR(LD, $1)="$LD" + +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_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_F77_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_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_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$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. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +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($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# -------------------------- +# Ensure that the configuration vars for the Windows resource 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_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$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. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars.  Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# 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 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 \ +    _LT_AC_TAGVAR(compiler, $1) \ +    _LT_AC_TAGVAR(CC, $1) \ +    _LT_AC_TAGVAR(LD, $1) \ +    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ +    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ +    _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ +    _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ +    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ +    _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ +    _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ +    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ +    _LT_AC_TAGVAR(old_archive_cmds, $1) \ +    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ +    _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) \ +    _LT_AC_TAGVAR(archive_cmds, $1) \ +    _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ +    _LT_AC_TAGVAR(postinstall_cmds, $1) \ +    _LT_AC_TAGVAR(postuninstall_cmds, $1) \ +    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ +    _LT_AC_TAGVAR(allow_undefined_flag, $1) \ +    _LT_AC_TAGVAR(no_undefined_flag, $1) \ +    _LT_AC_TAGVAR(export_symbols_cmds, $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_automatic, $1) \ +    _LT_AC_TAGVAR(module_cmds, $1) \ +    _LT_AC_TAGVAR(module_expsym_cmds, $1) \ +    _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ +    _LT_AC_TAGVAR(exclude_expsyms, $1) \ +    _LT_AC_TAGVAR(include_expsyms, $1); do + +    case $var in +    _LT_AC_TAGVAR(old_archive_cmds, $1) | \ +    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ +    _LT_AC_TAGVAR(archive_cmds, $1) | \ +    _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ +    _LT_AC_TAGVAR(module_cmds, $1) | \ +    _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ +    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ +    _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ +    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 + +ifelse([$1], [], +  [cfgfile="${ofile}T" +  trap "$rm \"$cfgfile\"; exit 1" 1 2 15 +  $rm -f "$cfgfile" +  AC_MSG_NOTICE([creating $ofile])], +  [cfgfile="$ofile"]) + +  cat <<__EOF__ >> "$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 <gord@gnu.ai.mit.edu>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# 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 + +# 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 + +# 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='$shrext' + +# 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 the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# 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'" +  ;; +irix* | nonstopux*) +  symcode='[[BCDEGRST]]' +  ;; +osf*) +  symcode='[[BCDEGQRST]]' +  ;; +solaris* | sysv5*) +  symcode='[[BDRT]]' +  ;; +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 + +  # 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 <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + +  if AC_TRY_EVAL(ac_compile); then +    # Now try to grab the symbols. +    nlist=conftest.nm +    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $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 <<EOF > 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 <<EOF >> 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)= +      ;; +    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 +	;; +      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) +	# 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)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_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)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" +	    case "$host_cpu" in +	    hppa*64*|ia64*) +	      # +Z the default +	      ;; +	    *) +	      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' +	      ;; +	    esac +	    ;; +	  *) +	    ;; +	esac +	;; +      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) +	    # 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' +	    ;; +	  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* | knetbsd*-gnu) +	;; +      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*) +	;; +      sco*) +	case $cc_basename in +	  CC) +	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' +	    ;; +	  *) +	    ;; +	esac +	;; +      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 +	;; +      unixware*) +	;; +      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' +      ;; + +    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 +      ;; + +    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 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' +        ;; +      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' +      ;; + +    sco3.2v5*) +      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' +      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' +      ;; + +    solaris*) +      _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' +      ;; + +    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* | sysv5*) +      _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 +      ;; + +    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 +]) + + +# 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 '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[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= + +  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 +    ;; +  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}' + +    # 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 <<EOF 1>&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 <kc5tja@dolphin.openprojects.net> 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 <jrb3@best.com> 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 '\''/^[[BCDGS]] /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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000  ${wl}--out-implib,$lib' +      else +	ld_shlibs=no +      fi +      ;; + +    netbsd* | knetbsd*-gnu) +      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* | sysv5*) +      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then +	_LT_AC_TAGVAR(ld_shlibs, $1)=no +	cat <<EOF 1>&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 +      ;; + +    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 +      ;; + +  linux*) +    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then +        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' +	_LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" +      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 +        _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 $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' +      else +        _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" +      fi +    else +      _LT_AC_TAGVAR(ld_shlibs, $1)=no +    fi +    ;; + +    *) +      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)" = yes; then +      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 +    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 "$link_static_flag"; 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' +      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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	  # -bexpall does not export symbols beginning with underscore (_) +	  _LT_AC_TAGVAR(always_export_symbols, $1)=yes +	  # Exported symbols can be pulled into shared objects from archives +	  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' +	  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes +	  # This is similar to how AIX traditionally builds it's shared libraries. +	  _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${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 +      ;; + +    bsdi4*) +      _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=".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' +      fix_srcfile_path='`cygpath -w "$srcfile"`' +      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes +      ;; + +    darwin* | rhapsody*) +    if test "$GXX" = yes ; then +      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +      case "$host_os" in +      rhapsody* | darwin1.[[012]]) +	_LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' +	;; +      *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	_LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[[012]]) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' +            ;; +          10.*) +            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' +            ;; +        esac +      fi +	;; +      esac +    	lt_int_apple_cc_single_mod=no +    	output_verbose_link_cmd='echo' +    	if $CC -dumpspecs 2>&1 | grep '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 ${wl}-bind_at_load -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 ${wl}-bind_at_load $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 ld's +        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 ${wl}-bind_at_load -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}' +      _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)='-all_load $convenience' +      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes +    else +      _LT_AC_TAGVAR(ld_shlibs, $1)=no +    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) +      _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* | hpux11*) +      if test "$GCC" = yes -a "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*|ia64*) +	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -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*|ia64*) +	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	*) +	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	esac +      fi +      if test "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*) +	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' +	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' +	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: +	  _LT_AC_TAGVAR(hardcode_direct, $1)=no +	  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +	  ;; +	ia64*) +	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' +	  _LT_AC_TAGVAR(hardcode_direct, $1)=no +	  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + +	  # 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(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 +	  ;; +	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* | knetbsd*-gnu) +      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(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 ${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)=: +      ;; + +    sco3.2v5*) +      _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)='${wl}-Bexport' +      runpath_var=LD_RUN_PATH +      hardcode_runpath_var=yes +      ;; + +    solaris*) +      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' +      if test "$GCC" = yes; then +	_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 +	_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]].*) ;; +      *) # Supported since Solaris 2.6 (maybe 2.5.1?) +	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; +      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.2uw2*) +      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' +      _LT_AC_TAGVAR(hardcode_direct, $1)=yes +      _LT_AC_TAGVAR(hardcode_minus_L, $1)=no +      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +      hardcode_runpath_var=yes +      runpath_var=LD_RUN_PATH +      ;; + +   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[[78]]* | unixware7*) +      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' +      if test "$GCC" = yes; then +	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      else +	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      fi +      runpath_var='LD_RUN_PATH' +      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +      ;; + +    sysv5*) +      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' +      # $CC -shared without GNU ld will not create a library from C++ +      # object files and a static libstdc++, better avoid it by now +      _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' +      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +      runpath_var='LD_RUN_PATH' +      ;; + +    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 + +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 + +# +# 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) +        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 <windows.h> +# #undef WIN32_LEAN_AND_MEAN +# #include <stdio.h> +# +# #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 <cygwin/cygwin_dll.h> +# 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 && break +  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/ext/pdo_sqlite/sqlite/config.guess b/ext/pdo_sqlite/sqlite/config.guess new file mode 100644 index 0000000000..e8c6fc0c33 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/config.guess @@ -0,0 +1,1432 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +#   2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2004-01-05' + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>.  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 <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +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 0 ;; +    --version | -v ) +       echo "$version" ; exit 0 ;; +    --help | --h* | -h ) +       echo "$usage"; exit 0 ;; +    -- )     # 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 -q "$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 ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +	PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +    *:NetBSD:*:*) +	# NetBSD (nbsd) targets should (where applicable) match one or +	# more of the 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 ;; +	    *) 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 0 ;; +    amiga:OpenBSD:*:*) +	echo m68k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    arc:OpenBSD:*:*) +	echo mipsel-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    hp300:OpenBSD:*:*) +	echo m68k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    mac68k:OpenBSD:*:*) +	echo m68k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    macppc:OpenBSD:*:*) +	echo powerpc-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    mvme68k:OpenBSD:*:*) +	echo m68k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    mvme88k:OpenBSD:*:*) +	echo m88k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    mvmeppc:OpenBSD:*:*) +	echo powerpc-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    pegasos:OpenBSD:*:*) +	echo powerpc-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    pmax:OpenBSD:*:*) +	echo mipsel-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    sgi:OpenBSD:*:*) +	echo mipseb-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    sun3:OpenBSD:*:*) +	echo m68k-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    wgrisc:OpenBSD:*:*) +	echo mipsel-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    *:OpenBSD:*:*) +	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} +	exit 0 ;; +    alpha:OSF1:*:*) +	if test $UNAME_RELEASE = "V4.0"; then +		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` +	fi +	# 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 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/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` +	exit 0 ;; +    Alpha*:OpenVMS:*:*) +	echo alpha-hp-vms +	exit 0 ;; +    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 0 ;; +    21064:Windows_NT:50:3) +	echo alpha-dec-winnt3.5 +	exit 0 ;; +    Amiga*:UNIX_System_V:4.0:*) +	echo m68k-unknown-sysv4 +	exit 0;; +    *:[Aa]miga[Oo][Ss]:*:*) +	echo ${UNAME_MACHINE}-unknown-amigaos +	exit 0 ;; +    *:[Mm]orph[Oo][Ss]:*:*) +	echo ${UNAME_MACHINE}-unknown-morphos +	exit 0 ;; +    *:OS/390:*:*) +	echo i370-ibm-openedition +	exit 0 ;; +    *:OS400:*:*) +        echo powerpc-ibm-os400 +	exit 0 ;; +    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) +	echo arm-acorn-riscix${UNAME_RELEASE} +	exit 0;; +    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) +	echo hppa1.1-hitachi-hiuxmpp +	exit 0;; +    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 0 ;; +    NILE*:*:*:dcosx) +	echo pyramid-pyramid-svr4 +	exit 0 ;; +    DRS?6000:unix:4.0:6*) +	echo sparc-icl-nx6 +	exit 0 ;; +    DRS?6000:UNIX_SV:4.2*:7*) +	case `/usr/bin/uname -p` in +	    sparc) echo sparc-icl-nx7 && exit 0 ;; +	esac ;; +    sun4H:SunOS:5.*:*) +	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` +	exit 0 ;; +    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) +	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` +	exit 0 ;; +    i86pc:SunOS:5.*:*) +	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` +	exit 0 ;; +    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 0 ;; +    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 0 ;; +    sun3*:SunOS:*:*) +	echo m68k-sun-sunos${UNAME_RELEASE} +	exit 0 ;; +    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 0 ;; +    aushp:SunOS:*:*) +	echo sparc-auspex-sunos${UNAME_RELEASE} +	exit 0 ;; +    # 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 0 ;; +    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) +	echo m68k-atari-mint${UNAME_RELEASE} +        exit 0 ;; +    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) +        echo m68k-atari-mint${UNAME_RELEASE} +	exit 0 ;; +    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) +        echo m68k-milan-mint${UNAME_RELEASE} +        exit 0 ;; +    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) +        echo m68k-hades-mint${UNAME_RELEASE} +        exit 0 ;; +    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) +        echo m68k-unknown-mint${UNAME_RELEASE} +        exit 0 ;; +    powerpc:machten:*:*) +	echo powerpc-apple-machten${UNAME_RELEASE} +	exit 0 ;; +    RISC*:Mach:*:*) +	echo mips-dec-mach_bsd4.3 +	exit 0 ;; +    RISC*:ULTRIX:*:*) +	echo mips-dec-ultrix${UNAME_RELEASE} +	exit 0 ;; +    VAX*:ULTRIX*:*:*) +	echo vax-dec-ultrix${UNAME_RELEASE} +	exit 0 ;; +    2020:CLIX:*:* | 2430:CLIX:*:*) +	echo clipper-intergraph-clix${UNAME_RELEASE} +	exit 0 ;; +    mips:*:*:UMIPS | mips:*:*:RISCos) +	eval $set_cc_for_build +	sed 's/^	//' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h>  /* 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 \ +	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ +	  && exit 0 +	echo mips-mips-riscos${UNAME_RELEASE} +	exit 0 ;; +    Motorola:PowerMAX_OS:*:*) +	echo powerpc-motorola-powermax +	exit 0 ;; +    Motorola:*:4.3:PL8-*) +	echo powerpc-harris-powermax +	exit 0 ;; +    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) +	echo powerpc-harris-powermax +	exit 0 ;; +    Night_Hawk:Power_UNIX:*:*) +	echo powerpc-harris-powerunix +	exit 0 ;; +    m88k:CX/UX:7*:*) +	echo m88k-harris-cxux7 +	exit 0 ;; +    m88k:*:4*:R4*) +	echo m88k-motorola-sysv4 +	exit 0 ;; +    m88k:*:3*:R3*) +	echo m88k-motorola-sysv3 +	exit 0 ;; +    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 0 ;; +    M88*:DolphinOS:*:*)	# DolphinOS (SVR3) +	echo m88k-dolphin-sysv3 +	exit 0 ;; +    M88*:*:R3*:*) +	# Delta 88k system running SVR3 +	echo m88k-motorola-sysv3 +	exit 0 ;; +    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) +	echo m88k-tektronix-sysv3 +	exit 0 ;; +    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) +	echo m68k-tektronix-bsd +	exit 0 ;; +    *:IRIX*:*:*) +	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` +	exit 0 ;; +    ????????: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 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX ' +    i*86:AIX:*:*) +	echo i386-ibm-aix +	exit 0 ;; +    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 0 ;; +    *: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 <sys/systemcfg.h> + +		main() +			{ +			if (!__power_pc()) +				exit(1); +			puts("powerpc-ibm-aix3.2.5"); +			exit(0); +			} +EOF +		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 +		echo rs6000-ibm-aix3.2.5 +	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 0 ;; +    *: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 0 ;; +    *:AIX:*:*) +	echo rs6000-ibm-aix +	exit 0 ;; +    ibmrt:4.4BSD:*|romp-ibm:BSD:*) +	echo romp-ibm-bsd4.4 +	exit 0 ;; +    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and +	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to +	exit 0 ;;                           # report: romp-ibm BSD 4.3 +    *:BOSX:*:*) +	echo rs6000-bull-bosx +	exit 0 ;; +    DPX/2?00:B.O.S.:*:*) +	echo m68k-bull-sysv3 +	exit 0 ;; +    9000/[34]??:4.3bsd:1.*:*) +	echo m68k-hp-bsd +	exit 0 ;; +    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) +	echo m68k-hp-bsd4.4 +	exit 0 ;; +    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 <stdlib.h> +              #include <unistd.h> + +              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 +	    # avoid double evaluation of $set_cc_for_build +	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build +	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null +	    then +		HP_ARCH="hppa2.0w" +	    else +		HP_ARCH="hppa64" +	    fi +	fi +	echo ${HP_ARCH}-hp-hpux${HPUX_REV} +	exit 0 ;; +    ia64:HP-UX:*:*) +	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` +	echo ia64-hp-hpux${HPUX_REV} +	exit 0 ;; +    3050*:HI-UX:*:*) +	eval $set_cc_for_build +	sed 's/^	//' << EOF >$dummy.c +	#include <unistd.h> +	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 && $dummy && exit 0 +	echo unknown-hitachi-hiuxwe2 +	exit 0 ;; +    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) +	echo hppa1.1-hp-bsd +	exit 0 ;; +    9000/8??:4.3bsd:*:*) +	echo hppa1.0-hp-bsd +	exit 0 ;; +    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) +	echo hppa1.0-hp-mpeix +	exit 0 ;; +    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) +	echo hppa1.1-hp-osf +	exit 0 ;; +    hp8??:OSF1:*:*) +	echo hppa1.0-hp-osf +	exit 0 ;; +    i*86:OSF1:*:*) +	if [ -x /usr/sbin/sysversion ] ; then +	    echo ${UNAME_MACHINE}-unknown-osf1mk +	else +	    echo ${UNAME_MACHINE}-unknown-osf1 +	fi +	exit 0 ;; +    parisc*:Lites*:*:*) +	echo hppa1.1-hp-lites +	exit 0 ;; +    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) +	echo c1-convex-bsd +        exit 0 ;; +    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) +	if getsysinfo -f scalar_acc +	then echo c32-convex-bsd +	else echo c2-convex-bsd +	fi +        exit 0 ;; +    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) +	echo c34-convex-bsd +        exit 0 ;; +    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) +	echo c38-convex-bsd +        exit 0 ;; +    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) +	echo c4-convex-bsd +        exit 0 ;; +    CRAY*Y-MP:*:*:*) +	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' +	exit 0 ;; +    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 0 ;; +    CRAY*TS:*:*:*) +	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' +	exit 0 ;; +    CRAY*T3E:*:*:*) +	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' +	exit 0 ;; +    CRAY*SV1:*:*:*) +	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' +	exit 0 ;; +    *:UNICOS/mp:*:*) +	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' +	exit 0 ;; +    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 0 ;; +    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 0 ;; +    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) +	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} +	exit 0 ;; +    sparc*:BSD/OS:*:*) +	echo sparc-unknown-bsdi${UNAME_RELEASE} +	exit 0 ;; +    *:BSD/OS:*:*) +	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} +	exit 0 ;; +    *:FreeBSD:*:*) +	# Determine whether the default compiler uses glibc. +	eval $set_cc_for_build +	sed 's/^	//' << EOF >$dummy.c +	#include <features.h> +	#if __GLIBC__ >= 2 +	LIBC=gnu +	#else +	LIBC= +	#endif +EOF +	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` +	# GNU/KFreeBSD systems have a "k" prefix to indicate we are using +	# FreeBSD's kernel, but not the complete OS. +	case ${LIBC} in gnu) kernel_only='k' ;; esac +	echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} +	exit 0 ;; +    i*:CYGWIN*:*) +	echo ${UNAME_MACHINE}-pc-cygwin +	exit 0 ;; +    i*:MINGW*:*) +	echo ${UNAME_MACHINE}-pc-mingw32 +	exit 0 ;; +    i*:PW*:*) +	echo ${UNAME_MACHINE}-pc-pw32 +	exit 0 ;; +    x86:Interix*:[34]*) +	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' +	exit 0 ;; +    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) +	echo i${UNAME_MACHINE}-pc-mks +	exit 0 ;; +    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 0 ;; +    i*:UWIN*:*) +	echo ${UNAME_MACHINE}-pc-uwin +	exit 0 ;; +    p*:CYGWIN*:*) +	echo powerpcle-unknown-cygwin +	exit 0 ;; +    prep*:SunOS:5.*:*) +	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` +	exit 0 ;; +    *:GNU:*:*) +	# the GNU system +	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` +	exit 0 ;; +    *: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 0 ;; +    i*86:Minix:*:*) +	echo ${UNAME_MACHINE}-pc-minix +	exit 0 ;; +    arm*:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    cris:Linux:*:*) +	echo cris-axis-linux-gnu +	exit 0 ;; +    ia64:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    m68*:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    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 | grep ^CPU=` +	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 +	;; +    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 | grep ^CPU=` +	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 +	;; +    ppc:Linux:*:*) +	echo powerpc-unknown-linux-gnu +	exit 0 ;; +    ppc64:Linux:*:*) +	echo powerpc64-unknown-linux-gnu +	exit 0 ;; +    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="libc1" ; else LIBC="" ; fi +	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} +	exit 0 ;; +    parisc:Linux:*:* | hppa:Linux:*:*) +	# Look for CPU level +	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in +	  PA7*) echo hppa1.1-unknown-linux-gnu ;; +	  PA8*) echo hppa2.0-unknown-linux-gnu ;; +	  *)    echo hppa-unknown-linux-gnu ;; +	esac +	exit 0 ;; +    parisc64:Linux:*:* | hppa64:Linux:*:*) +	echo hppa64-unknown-linux-gnu +	exit 0 ;; +    s390:Linux:*:* | s390x:Linux:*:*) +	echo ${UNAME_MACHINE}-ibm-linux +	exit 0 ;; +    sh64*:Linux:*:*) +    	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    sh*:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    sparc:Linux:*:* | sparc64:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu +	exit 0 ;; +    x86_64:Linux:*:*) +	echo x86_64-unknown-linux-gnu +	exit 0 ;; +    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-gnu" +		;; +	  a.out-i386-linux) +		echo "${UNAME_MACHINE}-pc-linux-gnuaout" +		exit 0 ;; +	  coff-i386) +		echo "${UNAME_MACHINE}-pc-linux-gnucoff" +		exit 0 ;; +	  "") +		# Either a pre-BFD a.out linker (linux-gnuoldld) or +		# one that does not give us useful --help. +		echo "${UNAME_MACHINE}-pc-linux-gnuoldld" +		exit 0 ;; +	esac +	# Determine whether the default compiler is a.out or elf +	eval $set_cc_for_build +	sed 's/^	//' << EOF >$dummy.c +	#include <features.h> +	#ifdef __ELF__ +	# ifdef __GLIBC__ +	#  if __GLIBC__ >= 2 +	LIBC=gnu +	#  else +	LIBC=gnulibc1 +	#  endif +	# else +	LIBC=gnulibc1 +	# endif +	#else +	#ifdef __INTEL_COMPILER +	LIBC=gnu +	#else +	LIBC=gnuaout +	#endif +	#endif +	#ifdef __dietlibc__ +	LIBC=dietlibc +	#endif +EOF +	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` +	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 +	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 +	;; +    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 0 ;; +    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 0 ;; +    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 0 ;; +    i*86:XTS-300:*:STOP) +	echo ${UNAME_MACHINE}-unknown-stop +	exit 0 ;; +    i*86:atheos:*:*) +	echo ${UNAME_MACHINE}-unknown-atheos +	exit 0 ;; +	i*86:syllable:*:*) +	echo ${UNAME_MACHINE}-pc-syllable +	exit 0 ;; +    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) +	echo i386-unknown-lynxos${UNAME_RELEASE} +	exit 0 ;; +    i*86:*DOS:*:*) +	echo ${UNAME_MACHINE}-pc-msdosdjgpp +	exit 0 ;; +    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 0 ;; +    i*86:*:5:[78]*) +	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 0 ;; +    i*86:*:3.2:*) +	if test -f /usr/options/cb.name; then +		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` +		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL +	elif /bin/uname -X 2>/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 0 ;; +    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 0 ;; +    Intel:Mach:3*:*) +	echo i386-pc-mach3 +	exit 0 ;; +    paragon:*:*:*) +	echo i860-intel-osf1 +	exit 0 ;; +    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 0 ;; +    mini*:CTIX:SYS*5:*) +	# "miniframe" +	echo m68010-convergent-sysv +	exit 0 ;; +    mc68k:UNIX:SYSTEM5:3.51m) +	echo m68k-convergent-sysv +	exit 0 ;; +    M680?0:D-NIX:5.3:*) +	echo m68k-diab-dnix +	exit 0 ;; +    M68*:*:R3V[567]*:*) +	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; +    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) +	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 0 +	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ +	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; +    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) +        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ +          && echo i486-ncr-sysv4 && exit 0 ;; +    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) +	echo m68k-unknown-lynxos${UNAME_RELEASE} +	exit 0 ;; +    mc68030:UNIX_System_V:4.*:*) +	echo m68k-atari-sysv4 +	exit 0 ;; +    TSUNAMI:LynxOS:2.*:*) +	echo sparc-unknown-lynxos${UNAME_RELEASE} +	exit 0 ;; +    rs6000:LynxOS:2.*:*) +	echo rs6000-unknown-lynxos${UNAME_RELEASE} +	exit 0 ;; +    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) +	echo powerpc-unknown-lynxos${UNAME_RELEASE} +	exit 0 ;; +    SM[BE]S:UNIX_SV:*:*) +	echo mips-dde-sysv${UNAME_RELEASE} +	exit 0 ;; +    RM*:ReliantUNIX-*:*:*) +	echo mips-sni-sysv4 +	exit 0 ;; +    RM*:SINIX-*:*:*) +	echo mips-sni-sysv4 +	exit 0 ;; +    *: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 0 ;; +    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort +                      # says <Richard.M.Bartel@ccMail.Census.GOV> +        echo i586-unisys-sysv4 +        exit 0 ;; +    *:UNIX_System_V:4*:FTX*) +	# From Gerald Hewes <hewes@openmarket.com>. +	# How about differentiating between stratus architectures? -djm +	echo hppa1.1-stratus-sysv4 +	exit 0 ;; +    *:*:*:FTX*) +	# From seanf@swdc.stratus.com. +	echo i860-stratus-sysv4 +	exit 0 ;; +    *:VOS:*:*) +	# From Paul.Green@stratus.com. +	echo hppa1.1-stratus-vos +	exit 0 ;; +    mc68*:A/UX:*:*) +	echo m68k-apple-aux${UNAME_RELEASE} +	exit 0 ;; +    news*:NEWS-OS:6*:*) +	echo mips-sony-newsos6 +	exit 0 ;; +    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 0 ;; +    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only. +	echo powerpc-be-beos +	exit 0 ;; +    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only. +	echo powerpc-apple-beos +	exit 0 ;; +    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible. +	echo i586-pc-beos +	exit 0 ;; +    SX-4:SUPER-UX:*:*) +	echo sx4-nec-superux${UNAME_RELEASE} +	exit 0 ;; +    SX-5:SUPER-UX:*:*) +	echo sx5-nec-superux${UNAME_RELEASE} +	exit 0 ;; +    SX-6:SUPER-UX:*:*) +	echo sx6-nec-superux${UNAME_RELEASE} +	exit 0 ;; +    Power*:Rhapsody:*:*) +	echo powerpc-apple-rhapsody${UNAME_RELEASE} +	exit 0 ;; +    *:Rhapsody:*:*) +	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} +	exit 0 ;; +    *:Darwin:*:*) +	case `uname -p` in +	    *86) UNAME_PROCESSOR=i686 ;; +	    powerpc) UNAME_PROCESSOR=powerpc ;; +	esac +	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} +	exit 0 ;; +    *: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 0 ;; +    *:QNX:*:4*) +	echo i386-pc-qnx +	exit 0 ;; +    NSR-?:NONSTOP_KERNEL:*:*) +	echo nsr-tandem-nsk${UNAME_RELEASE} +	exit 0 ;; +    *:NonStop-UX:*:*) +	echo mips-compaq-nonstopux +	exit 0 ;; +    BS2000:POSIX*:*:*) +	echo bs2000-siemens-sysv +	exit 0 ;; +    DS/*:UNIX_System_V:*:*) +	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} +	exit 0 ;; +    *: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 0 ;; +    *:TOPS-10:*:*) +	echo pdp10-unknown-tops10 +	exit 0 ;; +    *:TENEX:*:*) +	echo pdp10-unknown-tenex +	exit 0 ;; +    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) +	echo pdp10-dec-tops20 +	exit 0 ;; +    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) +	echo pdp10-xkl-tops20 +	exit 0 ;; +    *:TOPS-20:*:*) +	echo pdp10-unknown-tops20 +	exit 0 ;; +    *:ITS:*:*) +	echo pdp10-unknown-its +	exit 0 ;; +    SEI:*:*:SEIUX) +        echo mips-sei-seiux${UNAME_RELEASE} +	exit 0 ;; +    *:DRAGONFLY:*:*) +	echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE} +	exit 0 ;; +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 <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#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 <sys/param.h> +  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"); 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 <sys/param.h> +#  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 && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# 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 0 ;; +    c2*) +	if getsysinfo -f scalar_acc +	then echo c32-convex-bsd +	else echo c2-convex-bsd +	fi +	exit 0 ;; +    c34*) +	echo c34-convex-bsd +	exit 0 ;; +    c38*) +	echo c38-convex-bsd +	exit 0 ;; +    c4*) +	echo c4-convex-bsd +	exit 0 ;; +    esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + +    ftp://ftp.gnu.org/pub/gnu/config/ + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> 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/ext/pdo_sqlite/sqlite/config.sub b/ext/pdo_sqlite/sqlite/config.sub new file mode 100644 index 0000000000..463186dbfd --- /dev/null +++ b/ext/pdo_sqlite/sqlite/config.sub @@ -0,0 +1,1537 @@ +#! /bin/sh +# Configuration validation subroutine script. +#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +#   2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2004-01-05' + +# 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 <config-patches@gnu.org>.  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 <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +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 0 ;; +    --version | -v ) +       echo "$version" ; exit 0 ;; +    --help | --h* | -h ) +       echo "$usage"; exit 0 ;; +    -- )     # 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 0;; + +    * ) +       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-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) +		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 +		;; +	-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/'` +		;; +	-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 \ +	| c4x | clipper \ +	| d10v | d30v | dlx | dsp16xx \ +	| fr30 | frv \ +	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ +	| i370 | i860 | i960 | ia64 \ +	| ip2k | iq2000 \ +	| m32r | m68000 | m68k | m88k | mcore \ +	| mips | mipsbe | mipseb | mipsel | mipsle \ +	| mips16 \ +	| mips64 | mips64el \ +	| mips64vr | mips64vrel \ +	| mips64orion | mips64orionel \ +	| mips64vr4100 | mips64vr4100el \ +	| mips64vr4300 | mips64vr4300el \ +	| mips64vr5000 | mips64vr5000el \ +	| mipsisa32 | mipsisa32el \ +	| mipsisa32r2 | mipsisa32r2el \ +	| mipsisa64 | mipsisa64el \ +	| mipsisa64r2 | mipsisa64r2el \ +	| mipsisa64sb1 | mipsisa64sb1el \ +	| mipsisa64sr71k | mipsisa64sr71kel \ +	| mipstx39 | mipstx39el \ +	| mn10200 | mn10300 \ +	| msp430 \ +	| ns16k | ns32k \ +	| openrisc | or32 \ +	| pdp10 | pdp11 | pj | pjl \ +	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ +	| pyramid \ +	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ +	| sh64 | sh64le \ +	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ +	| strongarm \ +	| tahoe | thumb | tic4x | tic80 | tron \ +	| v850 | v850e \ +	| we32k \ +	| x86 | xscale | 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) +		;; + +	# 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-* \ +	| bs2000-* \ +	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ +	| clipper-* | cydra-* \ +	| d10v-* | d30v-* | dlx-* \ +	| elxsi-* \ +	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ +	| h8300-* | h8500-* \ +	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ +	| i*86-* | i860-* | i960-* | ia64-* \ +	| ip2k-* | iq2000-* \ +	| m32r-* \ +	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ +	| m88110-* | m88k-* | mcore-* \ +	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ +	| mips16-* \ +	| mips64-* | mips64el-* \ +	| mips64vr-* | mips64vrel-* \ +	| mips64orion-* | mips64orionel-* \ +	| mips64vr4100-* | mips64vr4100el-* \ +	| mips64vr4300-* | mips64vr4300el-* \ +	| mips64vr5000-* | mips64vr5000el-* \ +	| mipsisa32-* | mipsisa32el-* \ +	| mipsisa32r2-* | mipsisa32r2el-* \ +	| mipsisa64-* | mipsisa64el-* \ +	| mipsisa64r2-* | mipsisa64r2el-* \ +	| mipsisa64sb1-* | mipsisa64sb1el-* \ +	| mipsisa64sr71k-* | mipsisa64sr71kel-* \ +	| mipstx39-* | mipstx39el-* \ +	| msp430-* \ +	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ +	| orion-* \ +	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ +	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ +	| pyramid-* \ +	| romp-* | rs6000-* \ +	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ +	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ +	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ +	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ +	| tahoe-* | thumb-* \ +	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ +	| tron-* \ +	| v850-* | v850e-* | vax-* \ +	| we32k-* \ +	| x86-* | x86_64-* | xps100-* | xscale-* | 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 +		;; +	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 +		;; +	crds | unos) +		basic_machine=m68k-crds +		;; +	cris | cris-* | etrax*) +		basic_machine=cris-axis +		;; +	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 +		;; +	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 +		;; +	mips3*-*) +		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` +		;; +	mips3*) +		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown +		;; +	mmix*) +		basic_machine=mmix-knuth +		os=-mmixware +		;; +	monitor) +		basic_machine=m68k-rom68k +		os=-coff +		;; +	morphos) +		basic_machine=powerpc-unknown +		os=-morphos +		;; +	msdos) +		basic_machine=i386-pc +		os=-msdos +		;; +	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 +		;; +	nv1) +		basic_machine=nv1-cray +		os=-unicosmp +		;; +	nsr-tandem) +		basic_machine=nsr-tandem +		;; +	op50n-* | op60c-*) +		basic_machine=hppa1.1-oki +		os=-proelf +		;; +	or32 | or32-*) +		basic_machine=or32-unknown +		os=-coff +		;; +	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 +		;; +	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 +		;; +	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 +		;; +	sei) +		basic_machine=mips-sei +		os=-seiux +		;; +	sequent) +		basic_machine=i386-sequent +		;; +	sh) +		basic_machine=sh-hitachi +		os=-hms +		;; +	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 +		;; +	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 +		;; +	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 +		;; +	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) +		basic_machine=sh-unknown +		;; +	sh64) +		basic_machine=sh64-unknown +		;; +	sparc | sparcv9 | sparcv9b) +		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* | -netbsd* | -openbsd* | -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-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*) +	# 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* \ +	      | -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 +		;; +	-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 +	*-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 +		;; +	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 +		;; +	*-ibm) +		os=-aix +		;; +	*-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 0 + +# 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/ext/pdo_sqlite/sqlite/configure b/ext/pdo_sqlite/sqlite/configure new file mode 100755 index 0000000000..183977d168 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/configure @@ -0,0 +1,21639 @@ +#! /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 <<EOF +$* +EOF +  exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +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 <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +#  include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +#  include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +#  include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#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 program_prefix VERSION BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN TARGET_EXEEXT TARGET_LIBS TARGET_TCL_LIBS TARGET_TCL_INC TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE 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-releasemode           Support libtool link to release mode +  --enable-tempstore     Use an in-ram database for temporary tables (never,no,yes,always) + +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 + +Some influential environment variables: +  CC          C compiler command +  CFLAGS      C compiler flags +  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a +              nonstandard directory <lib dir> +  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have +              headers in a nonstandard directory <include dir> +  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$ + +######### +# 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 </dev/null >&5\"") >&5 +  (eval $ac_compiler --version </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 +  (eval $ac_compiler -v </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 +  (eval $ac_compiler -V </dev/null >&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 <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* 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 <stdlib.h> +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 && break +  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 + +fi + +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 GNU ld's only accept -v. +      # Break only if it was the GNU/non-GNU ld that we prefer. +      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in +      *GNU* | *'with BFD'*) +	test "$with_gnu_ld" != no && break +	;; +      *) +	test "$with_gnu_ld" != yes && break +	;; +      esac +    fi +  done +  IFS="$lt_save_ifs" +else +  lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then +  echo "$as_me:$LINENO: result: $LD" >&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 ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) +  lt_cv_prog_gnu_ld=yes +  ;; +*) +  lt_cv_prog_gnu_ld=no +  ;; +esac +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&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' + +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_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do +    IFS="$lt_save_ifs" +    test -z "$ac_dir" && ac_dir=. +    tmp_nm="$ac_dir/${ac_tool_prefix}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" +  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 +  ;; + +bsdi4*) +  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*) +  # 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='win32_libid' +  ;; + +mingw* | pw32*) +  # Base MSYS/MinGW do not provide the 'file' command needed by +  # 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) +  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)/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 +  ;; + +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* | knetbsd*-gnu) +  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*) +  lt_cv_file_magic_cmd=/usr/bin/file +  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` +  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' +  else +    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' +  fi +  ;; + +osf3* | osf4* | osf5*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +sco3.2v5*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +solaris*) +  lt_cv_deplibs_check_method=pass_all +  ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +  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 +    ;; +  esac +  ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | 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"} + +# 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 3055 "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 +  ;; + +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 <limits.h> to <assert.h> if __STDC__ is defined, since +  # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#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 <ac_nonexistent.h> +_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 <limits.h> to <assert.h> if __STDC__ is defined, since +  # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#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 <ac_nonexistent.h> +_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 <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.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_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 <string.h> + +_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 <stdlib.h> + +_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 <ctype.h> +#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 </dev/null >&5\"") >&5 +  (eval $ac_compiler --version </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 +  (eval $ac_compiler -v </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 +  (eval $ac_compiler -V </dev/null >&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 <stdlib.h> +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 + +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 <limits.h> to <assert.h> if __STDC__ is defined, since +  # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#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 <ac_nonexistent.h> +_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 <limits.h> to <assert.h> if __STDC__ is defined, since +  # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#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 <ac_nonexistent.h> +_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 + + +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:4518:" \ +     "checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 +  (eval $ac_compiler --version </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 +  (eval $ac_compiler -v </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 +  (eval $ac_compiler -V </dev/null >&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 +  testring="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; +    ;; + + *) +    # 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"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ +	       = "XX$testring") >/dev/null 2>&1 && +	    new_result=`expr "X$testring" : ".*" 2>&1` && +	    lt_cv_sys_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. +    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 the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# 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'" +  ;; +irix* | nonstopux*) +  symcode='[BCDEGRST]' +  ;; +osf*) +  symcode='[BCDEGQRST]' +  ;; +solaris* | sysv5*) +  symcode='[BDRT]' +  ;; +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 + +  # 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 <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + +  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 +    # 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 <<EOF > 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 <<EOF >> 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 s/^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 M$VC, +# 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 "$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="\$RANLIB -t \$oldlib~$old_postinstall_cmds" +    ;; +  *) +    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +    ;; +  esac +  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# 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 <<EOF 1>&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 <<EOF 1>&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 + +# 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"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# +# Check for any special shared library compilation flags. +# +lt_prog_cc_shlib= +if test "$GCC" = no; then +  case $host_os in +  sco3.2v5*) +    lt_prog_cc_shlib='-belf' +    ;; +  esac +fi +if test -n "$lt_prog_cc_shlib"; then +  { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 +echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} +  if echo "$old_CC $old_CFLAGS " | grep "[ 	]$lt_prog_cc_shlib[ 	]" >/dev/null; then : +  else +    { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 +echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} +    lt_cv_prog_cc_can_build_shared=no +  fi +fi + + +# +# Check to make sure the static flag actually works. +# +echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static 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_prog_compiler_static" +   printf "$lt_simple_link_test_code" > conftest.$ac_ext +   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then +     # The compiler 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 +     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 + + + + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:5552: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:5556: \$? = $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 +     if test ! -s conftest.err; 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' +      ;; + +    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 +      ;; + +    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 in +      icc* | ecc*) +	lt_prog_compiler_wl='-Wl,' +	lt_prog_compiler_pic='-KPIC' +	lt_prog_compiler_static='-static' +        ;; +      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' +      ;; + +    sco3.2v5*) +      lt_prog_compiler_pic='-Kpic' +      lt_prog_compiler_static='-dn' +      ;; + +    solaris*) +      lt_prog_compiler_wl='-Wl,' +      lt_prog_compiler_pic='-KPIC' +      lt_prog_compiler_static='-Bstatic' +      ;; + +    sunos4*) +      lt_prog_compiler_wl='-Qoption ld ' +      lt_prog_compiler_pic='-PIC' +      lt_prog_compiler_static='-Bstatic' +      ;; + +    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +      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 +      ;; + +    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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:5785: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:5789: \$? = $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 +     if test ! -s conftest.err; 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 + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:5845: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>out/conftest.err) +   ac_status=$? +   cat out/conftest.err >&5 +   echo "$as_me:5849: \$? = $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 +     if test ! -s out/conftest.err; then +       lt_cv_prog_compiler_c_o=yes +     fi +   fi +   chmod u+w . +   $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= + +  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 +    ;; +  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}' + +    # 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 <<EOF 1>&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 <kc5tja@dolphin.openprojects.net> 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 <jrb3@best.com> 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 '\''/^[BCDGS] /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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000  ${wl}--out-implib,$lib' +      else +	ld_shlibs=no +      fi +      ;; + +    netbsd* | knetbsd*-gnu) +      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* | sysv5*) +      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then +	ld_shlibs=no +	cat <<EOF 1>&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 +      ;; + +    sunos4*) +      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' +      wlarc= +      hardcode_direct=yes +      hardcode_shlibpath_var=no +      ;; + +  linux*) +    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then +        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' +	archive_cmds="$tmp_archive_cmds" +      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="$tmp_archive_cmds" +      fi +    else +      ld_shlibs=no +    fi +    ;; + +    *) +      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" = yes; then +      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 +    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 "$link_static_flag"; 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' +      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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	  # -bexpall does not export symbols beginning with underscore (_) +	  always_export_symbols=yes +	  # Exported symbols can be pulled into shared objects from archives +	  whole_archive_flag_spec=' ' +	  archive_cmds_need_lc=yes +	  # This is similar to how AIX traditionally builds it's shared libraries. +	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${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 +      ;; + +    bsdi4*) +      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=".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*) +    if test "$GXX" = yes ; then +      archive_cmds_need_lc=no +      case "$host_os" in +      rhapsody* | darwin1.[012]) +	allow_undefined_flag='-undefined suppress' +	;; +      *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	allow_undefined_flag='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[012]) +            allow_undefined_flag='-flat_namespace -undefined suppress' +            ;; +          10.*) +            allow_undefined_flag='-undefined dynamic_lookup' +            ;; +        esac +      fi +	;; +      esac +    	lt_int_apple_cc_single_mod=no +    	output_verbose_link_cmd='echo' +    	if $CC -dumpspecs 2>&1 | grep '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='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +    	else +        archive_cmds='$CC -r ${wl}-bind_at_load -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='$CC ${wl}-bind_at_load $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 ld's +        if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +          archive_expsym_cmds='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='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -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='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}' +      hardcode_direct=no +      hardcode_automatic=yes +      hardcode_shlibpath_var=unsupported +      whole_archive_flag_spec='-all_load $convenience' +      link_all_deplibs=yes +    else +      ld_shlibs=no +    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) +      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* | hpux11*) +      if test "$GCC" = yes -a "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*|ia64*) +	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -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*|ia64*) +	  archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	*) +	  archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	esac +      fi +      if test "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*) +	  hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' +	  hardcode_libdir_flag_spec_ld='+b $libdir' +	  hardcode_libdir_separator=: +	  hardcode_direct=no +	  hardcode_shlibpath_var=no +	  ;; +	ia64*) +	  hardcode_libdir_flag_spec='-L$libdir' +	  hardcode_direct=no +	  hardcode_shlibpath_var=no + +	  # hardcode_minus_L: Not really in the search PATH, +	  # but as the default location of the library. +	  hardcode_minus_L=yes +	  ;; +	*) +	  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 +	  ;; +	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* | knetbsd*-gnu) +      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' +	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 ${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=: +      ;; + +    sco3.2v5*) +      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' +      hardcode_shlibpath_var=no +      export_dynamic_flag_spec='${wl}-Bexport' +      runpath_var=LD_RUN_PATH +      hardcode_runpath_var=yes +      ;; + +    solaris*) +      no_undefined_flag=' -z text' +      if test "$GCC" = yes; then +	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 +	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].*) ;; +      *) # Supported since Solaris 2.6 (maybe 2.5.1?) +	whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; +      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.2uw2*) +      archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' +      hardcode_direct=yes +      hardcode_minus_L=no +      hardcode_shlibpath_var=no +      hardcode_runpath_var=yes +      runpath_var=LD_RUN_PATH +      ;; + +   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[78]* | unixware7*) +      no_undefined_flag='${wl}-z ${wl}text' +      if test "$GCC" = yes; then +	archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      else +	archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      fi +      runpath_var='LD_RUN_PATH' +      hardcode_shlibpath_var=no +      ;; + +    sysv5*) +      no_undefined_flag=' -z text' +      # $CC -shared without GNU ld will not create a library from C++ +      # object files and a static libstdc++, better avoid it by now +      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' +      hardcode_libdir_flag_spec= +      hardcode_shlibpath_var=no +      runpath_var='LD_RUN_PATH' +      ;; + +    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 + +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 + +# +# 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 +        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=".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<name>.so +      # instead of lib<name>.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 +  ;; + +bsdi4*) +  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=".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' +    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 +    ;; + +  *) +    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='$(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*) +  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +  version_type=freebsd-$objformat +  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 +      ;; +  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 +    ;; +  *) # from 3.2 on +    shlibpath_overrides_runpath=no +    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='.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='.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='.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' +  ;; + +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 +    ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` +    sys_lib_dlsearch_path_spec="/lib /usr/lib $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 +  need_lib_prefix=no +  need_version=yes +  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=".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" +  ;; + +sco3.2v5*) +  version_type=osf +  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 +  ;; + +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.2uw2* | sysv4.3* | sysv5*) +  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 +  ;; + +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 + +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 <limits.h> declares shl_load. +   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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 <limits.h> declares dlopen. +   For example, HP-UX 11i <limits.h> declares gettimeofday.  */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, +    which can conflict with char dlopen (); below. +    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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" +    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 <<EOF +#line 8029 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 +      LDFLAGS="$LDFLAGS $link_static_flag" +      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 <<EOF +#line 8127 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 librarie types wil 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*) +  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then +    test "$enable_shared" = yes && enable_static=no +  fi +  ;; +  darwin* | rhapsody*) +  if test "$GCC" = yes; then +    archive_cmds_need_lc=no +    case "$host_os" in +    rhapsody* | darwin1.[012]) +      allow_undefined_flag='-undefined suppress' +      ;; +    *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	allow_undefined_flag='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[012]) +            allow_undefined_flag='-flat_namespace -undefined suppress' +            ;; +          10.*) +            allow_undefined_flag='-undefined dynamic_lookup' +            ;; +        esac +      fi +      ;; +    esac +    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 ld's +    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}' +    hardcode_direct=no +    hardcode_automatic=yes +    hardcode_shlibpath_var=unsupported +    whole_archive_flag_spec='-all_load $convenience' +    link_all_deplibs=yes +  else +    ld_shlibs=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 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 <gord@gnu.ai.mit.edu>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# 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 + +# 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 + +# 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='$shrext' + +# 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 + +  # 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"; 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_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=cc + +# 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"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# 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 +  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 +  unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# 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 GNU ld's only accept -v. +      # Break only if it was the GNU/non-GNU ld that we prefer. +      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in +      *GNU* | *'with BFD'*) +	test "$with_gnu_ld" != no && break +	;; +      *) +	test "$with_gnu_ld" != yes && break +	;; +      esac +    fi +  done +  IFS="$lt_save_ifs" +else +  lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then +  echo "$as_me:$LINENO: result: $LD" >&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 ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) +  lt_cv_prog_gnu_ld=yes +  ;; +*) +  lt_cv_prog_gnu_ld=no +  ;; +esac +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&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' +    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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	# -bexpall does not export symbols beginning with underscore (_) +	always_export_symbols_CXX=yes +	# Exported symbols can be pulled into shared objects from archives +	whole_archive_flag_spec_CXX=' ' +	archive_cmds_need_lc_CXX=yes +	# This is similar to how AIX traditionally builds it's shared libraries. +	archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' +      fi +    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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000 ${wl}--out-implib,$lib' +    else +      ld_shlibs_CXX=no +    fi +  ;; + +  darwin* | rhapsody*) +  if test "$GXX" = yes; then +    archive_cmds_need_lc_CXX=no +    case "$host_os" in +    rhapsody* | darwin1.[012]) +      allow_undefined_flag_CXX='-undefined suppress' +      ;; +    *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	allow_undefined_flag_CXX='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[012]) +            allow_undefined_flag_CXX='-flat_namespace -undefined suppress' +            ;; +          10.*) +            allow_undefined_flag_CXX='-undefined dynamic_lookup' +            ;; +        esac +      fi +      ;; +    esac +    lt_int_apple_cc_single_mod=no +    output_verbose_link_cmd='echo' +    if $CC -dumpspecs 2>&1 | grep '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 ${wl}-bind_at_load -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 ${wl}-bind_at_load $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 ld's +    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 ${wl}-bind_at_load -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}' +    hardcode_direct_CXX=no +    hardcode_automatic_CXX=yes +    hardcode_shlibpath_var_CXX=unsupported +    whole_archive_flag_spec_CXX='-all_load $convenience' +    link_all_deplibs_CXX=yes +  else +    ld_shlibs_CXX=no +  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 +    ;; +  freebsd12*) +    # 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) +    # 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) | egrep "\-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 +      case "$host_cpu" in +      hppa*64*) +	hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' +	hardcode_libdir_flag_spec_ld_CXX='+b $libdir' +	hardcode_libdir_separator_CXX=: +        ;; +      ia64*) +	hardcode_libdir_flag_spec_CXX='-L$libdir' +        ;; +      *) +	hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' +	hardcode_libdir_separator_CXX=: +	export_dynamic_flag_spec_CXX='${wl}-E' +        ;; +      esac +    fi +    case "$host_cpu" in +    hppa*64*) +      hardcode_direct_CXX=no +      hardcode_shlibpath_var_CXX=no +      ;; +    ia64*) +      hardcode_direct_CXX=no +      hardcode_shlibpath_var_CXX=no +      hardcode_minus_L_CXX=yes # Not in the search PATH, +					      # but as the default +					      # location of the library. +      ;; +    *) +      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*|ia64*) +	  archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' +	  ;; +	*) +	  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 +	    ia64*|hppa*64*) +	      archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' +	      ;; +	    *) +	      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 +    ;; +  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 ${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}${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 +	archive_cmds_need_lc_CXX=no +	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' +	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' +	;; +      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* | knetbsd*-gnu) +    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::"' +    ;; +  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 ${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}${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 ${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 $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}${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 +    ;; +  sco*) +    archive_cmds_need_lc_CXX=no +    case $cc_basename in +      CC) +	# FIXME: insert proper C++ library support +	ld_shlibs_CXX=no +	;; +      *) +	# FIXME: insert proper C++ library support +	ld_shlibs_CXX=no +	;; +    esac +    ;; +  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++ +	no_undefined_flag_CXX=' -zdefs' +	archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -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} -nolib ${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. +	    # Supported since Solaris 2.6 (maybe 2.5.1?) +	    whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' +	    ;; +	esac +	link_all_deplibs_CXX=yes + +	# 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 -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + +	# 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 +    ;; +  sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) +    archive_cmds_need_lc_CXX=no +    ;; +  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 <<EOF +class Foo +{ +public: +  Foo (void) { a = 0; } +private: +  int a; +}; +EOF + +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 +  # 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 + +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= +      ;; +    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 +	;; +      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) +	# FreeBSD uses GNU C++ +	;; +      hpux9* | hpux10* | hpux11*) +	case $cc_basename in +	  CC) +	    lt_prog_compiler_wl_CXX='-Wl,' +	    lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_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="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" +	    case "$host_cpu" in +	    hppa*64*|ia64*) +	      # +Z the default +	      ;; +	    *) +	      lt_prog_compiler_pic_CXX='+Z' +	      ;; +	    esac +	    ;; +	  *) +	    ;; +	esac +	;; +      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) +	    # Intel C++ +	    lt_prog_compiler_wl_CXX='-Wl,' +	    lt_prog_compiler_pic_CXX='-KPIC' +	    lt_prog_compiler_static_CXX='-static' +	    ;; +	  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* | knetbsd*-gnu) +	;; +      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*) +	;; +      sco*) +	case $cc_basename in +	  CC) +	    lt_prog_compiler_pic_CXX='-fPIC' +	    ;; +	  *) +	    ;; +	esac +	;; +      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 +	;; +      unixware*) +	;; +      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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:10306: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:10310: \$? = $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 +     if test ! -s conftest.err; 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 + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:10366: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>out/conftest.err) +   ac_status=$? +   cat out/conftest.err >&5 +   echo "$as_me:10370: \$? = $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 +     if test ! -s out/conftest.err; then +       lt_cv_prog_compiler_c_o_CXX=yes +     fi +   fi +   chmod u+w . +   $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 '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[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 + +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 + +# +# 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 +        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=".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<name>.so +      # instead of lib<name>.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 +  ;; + +bsdi4*) +  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=".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' +    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 +    ;; + +  *) +    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='$(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*) +  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +  version_type=freebsd-$objformat +  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 +      ;; +  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 +    ;; +  *) # from 3.2 on +    shlibpath_overrides_runpath=no +    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='.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='.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='.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' +  ;; + +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 +    ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` +    sys_lib_dlsearch_path_spec="/lib /usr/lib $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 +  need_lib_prefix=no +  need_version=yes +  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=".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" +  ;; + +sco3.2v5*) +  version_type=osf +  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 +  ;; + +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.2uw2* | sysv4.3* | sysv5*) +  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 +  ;; + +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 + +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 + +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_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 +  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 <limits.h> declares shl_load. +   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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_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 +  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_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 +  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 <limits.h> declares dlopen. +   For example, HP-UX 11i <limits.h> declares gettimeofday.  */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, +    which can conflict with char dlopen (); below. +    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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_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 +  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_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 +  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_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 +  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_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 +  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" +    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 <<EOF +#line 11727 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 +      LDFLAGS="$LDFLAGS $link_static_flag" +      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 <<EOF +#line 11825 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 + + +# 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 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 + +# 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 + +# 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='$shrext' + +# 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"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +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*) +  test "$enable_shared" = yes && enable_static=no +  ;; +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 + +test "$ld_shlibs_F77" = no && can_build_shared=no + +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' +      ;; + +    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 +      ;; + +    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 in +      icc* | ecc*) +	lt_prog_compiler_wl_F77='-Wl,' +	lt_prog_compiler_pic_F77='-KPIC' +	lt_prog_compiler_static_F77='-static' +        ;; +      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' +      ;; + +    sco3.2v5*) +      lt_prog_compiler_pic_F77='-Kpic' +      lt_prog_compiler_static_F77='-dn' +      ;; + +    solaris*) +      lt_prog_compiler_wl_F77='-Wl,' +      lt_prog_compiler_pic_F77='-KPIC' +      lt_prog_compiler_static_F77='-Bstatic' +      ;; + +    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* | sysv5*) +      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 +      ;; + +    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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:12652: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:12656: \$? = $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 +     if test ! -s conftest.err; 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 + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:12712: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>out/conftest.err) +   ac_status=$? +   cat out/conftest.err >&5 +   echo "$as_me:12716: \$? = $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 +     if test ! -s out/conftest.err; then +       lt_cv_prog_compiler_c_o_F77=yes +     fi +   fi +   chmod u+w . +   $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= + +  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 +    ;; +  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}' + +    # 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 <<EOF 1>&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 <kc5tja@dolphin.openprojects.net> 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 <jrb3@best.com> 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 '\''/^[BCDGS] /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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000  ${wl}--out-implib,$lib' +      else +	ld_shlibs=no +      fi +      ;; + +    netbsd* | knetbsd*-gnu) +      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* | sysv5*) +      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then +	ld_shlibs_F77=no +	cat <<EOF 1>&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 +      ;; + +    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 +      ;; + +  linux*) +    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then +        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' +	archive_cmds_F77="$tmp_archive_cmds" +      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_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 $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' +      else +        archive_expsym_cmds_F77="$tmp_archive_cmds" +      fi +    else +      ld_shlibs_F77=no +    fi +    ;; + +    *) +      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" = yes; then +      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 +    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 "$link_static_flag"; 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' +      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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	  # -bexpall does not export symbols beginning with underscore (_) +	  always_export_symbols_F77=yes +	  # Exported symbols can be pulled into shared objects from archives +	  whole_archive_flag_spec_F77=' ' +	  archive_cmds_need_lc_F77=yes +	  # This is similar to how AIX traditionally builds it's shared libraries. +	  archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${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 +      ;; + +    bsdi4*) +      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=".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='`cygpath -w "$srcfile"`' +      enable_shared_with_static_runtimes_F77=yes +      ;; + +    darwin* | rhapsody*) +    if test "$GXX" = yes ; then +      archive_cmds_need_lc_F77=no +      case "$host_os" in +      rhapsody* | darwin1.[012]) +	allow_undefined_flag_F77='-undefined suppress' +	;; +      *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	allow_undefined_flag_F77='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[012]) +            allow_undefined_flag_F77='-flat_namespace -undefined suppress' +            ;; +          10.*) +            allow_undefined_flag_F77='-undefined dynamic_lookup' +            ;; +        esac +      fi +	;; +      esac +    	lt_int_apple_cc_single_mod=no +    	output_verbose_link_cmd='echo' +    	if $CC -dumpspecs 2>&1 | grep '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_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +    	else +        archive_cmds_F77='$CC -r ${wl}-bind_at_load -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_F77='$CC ${wl}-bind_at_load $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 ld's +        if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +          archive_expsym_cmds_F77='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_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -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_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}' +      hardcode_direct_F77=no +      hardcode_automatic_F77=yes +      hardcode_shlibpath_var_F77=unsupported +      whole_archive_flag_spec_F77='-all_load $convenience' +      link_all_deplibs_F77=yes +    else +      ld_shlibs_F77=no +    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) +      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* | hpux11*) +      if test "$GCC" = yes -a "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*|ia64*) +	  archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -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*|ia64*) +	  archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	*) +	  archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	esac +      fi +      if test "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*) +	  hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' +	  hardcode_libdir_flag_spec_ld_F77='+b $libdir' +	  hardcode_libdir_separator_F77=: +	  hardcode_direct_F77=no +	  hardcode_shlibpath_var_F77=no +	  ;; +	ia64*) +	  hardcode_libdir_flag_spec_F77='-L$libdir' +	  hardcode_direct_F77=no +	  hardcode_shlibpath_var_F77=no + +	  # hardcode_minus_L: Not really in the search PATH, +	  # but as the default location of the library. +	  hardcode_minus_L_F77=yes +	  ;; +	*) +	  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 +	  ;; +	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* | knetbsd*-gnu) +      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' +	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 ${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=: +      ;; + +    sco3.2v5*) +      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' +      hardcode_shlibpath_var_F77=no +      export_dynamic_flag_spec_F77='${wl}-Bexport' +      runpath_var=LD_RUN_PATH +      hardcode_runpath_var=yes +      ;; + +    solaris*) +      no_undefined_flag_F77=' -z text' +      if test "$GCC" = yes; then +	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 +	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].*) ;; +      *) # Supported since Solaris 2.6 (maybe 2.5.1?) +	whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; +      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.2uw2*) +      archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' +      hardcode_direct_F77=yes +      hardcode_minus_L_F77=no +      hardcode_shlibpath_var_F77=no +      hardcode_runpath_var=yes +      runpath_var=LD_RUN_PATH +      ;; + +   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[78]* | unixware7*) +      no_undefined_flag_F77='${wl}-z ${wl}text' +      if test "$GCC" = yes; then +	archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      else +	archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      fi +      runpath_var='LD_RUN_PATH' +      hardcode_shlibpath_var_F77=no +      ;; + +    sysv5*) +      no_undefined_flag_F77=' -z text' +      # $CC -shared without GNU ld will not create a library from C++ +      # object files and a static libstdc++, better avoid it by now +      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' +      hardcode_libdir_flag_spec_F77= +      hardcode_shlibpath_var_F77=no +      runpath_var='LD_RUN_PATH' +      ;; + +    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 + +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 + +# +# 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 +        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=".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<name>.so +      # instead of lib<name>.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 +  ;; + +bsdi4*) +  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=".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' +    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 +    ;; + +  *) +    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='$(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*) +  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +  version_type=freebsd-$objformat +  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 +      ;; +  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 +    ;; +  *) # from 3.2 on +    shlibpath_overrides_runpath=no +    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='.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='.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='.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' +  ;; + +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 +    ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` +    sys_lib_dlsearch_path_spec="/lib /usr/lib $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 +  need_lib_prefix=no +  need_version=yes +  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=".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" +  ;; + +sco3.2v5*) +  version_type=osf +  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 +  ;; + +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.2uw2* | sysv4.3* | sysv5*) +  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 +  ;; + +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 + +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 + +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 + + + +# 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 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 + +# 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 + +# 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='$shrext' + +# 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"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:14746: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:14750: \$? = $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 +     if test ! -s conftest.err; 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' +      ;; + +    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 +      ;; + +    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 in +      icc* | ecc*) +	lt_prog_compiler_wl_GCJ='-Wl,' +	lt_prog_compiler_pic_GCJ='-KPIC' +	lt_prog_compiler_static_GCJ='-static' +        ;; +      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' +      ;; + +    sco3.2v5*) +      lt_prog_compiler_pic_GCJ='-Kpic' +      lt_prog_compiler_static_GCJ='-dn' +      ;; + +    solaris*) +      lt_prog_compiler_wl_GCJ='-Wl,' +      lt_prog_compiler_pic_GCJ='-KPIC' +      lt_prog_compiler_static_GCJ='-Bstatic' +      ;; + +    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* | sysv5*) +      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 +      ;; + +    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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:14979: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>conftest.err) +   ac_status=$? +   cat conftest.err >&5 +   echo "$as_me:14983: \$? = $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 +     if test ! -s conftest.err; 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 + +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}? :&$lt_compiler_flag :; t' \ +   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ +   -e 's:$: $lt_compiler_flag:'` +   (eval echo "\"\$as_me:15039: $lt_compile\"" >&5) +   (eval "$lt_compile" 2>out/conftest.err) +   ac_status=$? +   cat out/conftest.err >&5 +   echo "$as_me:15043: \$? = $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 +     if test ! -s out/conftest.err; then +       lt_cv_prog_compiler_c_o_GCJ=yes +     fi +   fi +   chmod u+w . +   $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= + +  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 +    ;; +  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}' + +    # 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 <<EOF 1>&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 <kc5tja@dolphin.openprojects.net> 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 <jrb3@best.com> 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 '\''/^[BCDGS] /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}--image-base=0x10000000 ${wl}--out-implib,$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}--image-base=0x10000000  ${wl}--out-implib,$lib' +      else +	ld_shlibs=no +      fi +      ;; + +    netbsd* | knetbsd*-gnu) +      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* | sysv5*) +      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then +	ld_shlibs_GCJ=no +	cat <<EOF 1>&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 +      ;; + +    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 +      ;; + +  linux*) +    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then +        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' +	archive_cmds_GCJ="$tmp_archive_cmds" +      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_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 $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' +      else +        archive_expsym_cmds_GCJ="$tmp_archive_cmds" +      fi +    else +      ld_shlibs_GCJ=no +    fi +    ;; + +    *) +      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" = yes; then +      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 +    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 "$link_static_flag"; 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' +      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 $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${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 $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_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' +	  # -bexpall does not export symbols beginning with underscore (_) +	  always_export_symbols_GCJ=yes +	  # Exported symbols can be pulled into shared objects from archives +	  whole_archive_flag_spec_GCJ=' ' +	  archive_cmds_need_lc_GCJ=yes +	  # This is similar to how AIX traditionally builds it's shared libraries. +	  archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${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 +      ;; + +    bsdi4*) +      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=".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='`cygpath -w "$srcfile"`' +      enable_shared_with_static_runtimes_GCJ=yes +      ;; + +    darwin* | rhapsody*) +    if test "$GXX" = yes ; then +      archive_cmds_need_lc_GCJ=no +      case "$host_os" in +      rhapsody* | darwin1.[012]) +	allow_undefined_flag_GCJ='-undefined suppress' +	;; +      *) # Darwin 1.3 on +      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +      	allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' +      else +        case ${MACOSX_DEPLOYMENT_TARGET} in +          10.[012]) +            allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' +            ;; +          10.*) +            allow_undefined_flag_GCJ='-undefined dynamic_lookup' +            ;; +        esac +      fi +	;; +      esac +    	lt_int_apple_cc_single_mod=no +    	output_verbose_link_cmd='echo' +    	if $CC -dumpspecs 2>&1 | grep '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_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +    	else +        archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -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_GCJ='$CC ${wl}-bind_at_load $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 ld's +        if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +          archive_expsym_cmds_GCJ='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_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -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_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}' +      hardcode_direct_GCJ=no +      hardcode_automatic_GCJ=yes +      hardcode_shlibpath_var_GCJ=unsupported +      whole_archive_flag_spec_GCJ='-all_load $convenience' +      link_all_deplibs_GCJ=yes +    else +      ld_shlibs_GCJ=no +    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) +      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* | hpux11*) +      if test "$GCC" = yes -a "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*|ia64*) +	  archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -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*|ia64*) +	  archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	*) +	  archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +	  ;; +	esac +      fi +      if test "$with_gnu_ld" = no; then +	case "$host_cpu" in +	hppa*64*) +	  hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' +	  hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' +	  hardcode_libdir_separator_GCJ=: +	  hardcode_direct_GCJ=no +	  hardcode_shlibpath_var_GCJ=no +	  ;; +	ia64*) +	  hardcode_libdir_flag_spec_GCJ='-L$libdir' +	  hardcode_direct_GCJ=no +	  hardcode_shlibpath_var_GCJ=no + +	  # hardcode_minus_L: Not really in the search PATH, +	  # but as the default location of the library. +	  hardcode_minus_L_GCJ=yes +	  ;; +	*) +	  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 +	  ;; +	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* | knetbsd*-gnu) +      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' +	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 ${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=: +      ;; + +    sco3.2v5*) +      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' +      hardcode_shlibpath_var_GCJ=no +      export_dynamic_flag_spec_GCJ='${wl}-Bexport' +      runpath_var=LD_RUN_PATH +      hardcode_runpath_var=yes +      ;; + +    solaris*) +      no_undefined_flag_GCJ=' -z text' +      if test "$GCC" = yes; then +	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 +	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].*) ;; +      *) # Supported since Solaris 2.6 (maybe 2.5.1?) +	whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; +      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.2uw2*) +      archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' +      hardcode_direct_GCJ=yes +      hardcode_minus_L_GCJ=no +      hardcode_shlibpath_var_GCJ=no +      hardcode_runpath_var=yes +      runpath_var=LD_RUN_PATH +      ;; + +   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[78]* | unixware7*) +      no_undefined_flag_GCJ='${wl}-z ${wl}text' +      if test "$GCC" = yes; then +	archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      else +	archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' +      fi +      runpath_var='LD_RUN_PATH' +      hardcode_shlibpath_var_GCJ=no +      ;; + +    sysv5*) +      no_undefined_flag_GCJ=' -z text' +      # $CC -shared without GNU ld will not create a library from C++ +      # object files and a static libstdc++, better avoid it by now +      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' +      hardcode_libdir_flag_spec_GCJ= +      hardcode_shlibpath_var_GCJ=no +      runpath_var='LD_RUN_PATH' +      ;; + +    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 + +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 + +# +# 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 +        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=".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<name>.so +      # instead of lib<name>.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 +  ;; + +bsdi4*) +  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=".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' +    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 +    ;; + +  *) +    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='$(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*) +  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +  version_type=freebsd-$objformat +  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 +      ;; +  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 +    ;; +  *) # from 3.2 on +    shlibpath_overrides_runpath=no +    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='.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='.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='.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' +  ;; + +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 +    ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` +    sys_lib_dlsearch_path_spec="/lib /usr/lib $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 +  need_lib_prefix=no +  need_version=yes +  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=".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" +  ;; + +sco3.2v5*) +  version_type=osf +  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 +  ;; + +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.2uw2* | sysv4.3* | sysv5*) +  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 +  ;; + +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 + +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 + +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 <limits.h> declares shl_load. +   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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 <limits.h> declares dlopen. +   For example, HP-UX 11i <limits.h> declares gettimeofday.  */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, +    which can conflict with char dlopen (); below. +    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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" +    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 <<EOF +#line 17223 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 +      LDFLAGS="$LDFLAGS $link_static_flag" +      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 <<EOF +#line 17321 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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); */ +    } + +    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; ) 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_unknown|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 + + +# 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 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 + +# 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 + +# 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='$shrext' + +# 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"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +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 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 + +# 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 + +# 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='$shrext' + +# 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' + + +######### +# Set up an appropriate program prefix +# +if test "$program_prefix" = "NONE"; then +  program_prefix="" +fi + + +if test -f VERSION; then +  VERSION=`cat VERSION` +  echo "Version set to $VERSION" +fi + + +######### +# 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. +# +default_build_cflags="-g" +if test "$config_BUILD_CC" = ""; then +  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 </dev/null >&5\"") >&5 +  (eval $ac_compiler --version </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 +  (eval $ac_compiler -v </dev/null >&5) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 +  (eval $ac_compiler -V </dev/null >&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_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 <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* 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 <stdlib.h> +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 + +  if test "$cross_compiling" = "yes"; then +    { { echo "$as_me:$LINENO: error: unable to find a compiler for building build tools" >&5 +echo "$as_me: error: unable to find a compiler for building build tools" >&2;} +   { (exit 1); exit 1; }; } +  fi +  BUILD_CC=$CC +  default_build_cflags=$CFLAGS +else +  BUILD_CC=$config_BUILD_CC +  echo "$as_me:$LINENO: checking host compiler" >&5 +echo $ECHO_N "checking host compiler... $ECHO_C" >&6 +  CC=$BUILD_CC +  echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6 +fi +echo "$as_me:$LINENO: checking switches for the host compiler" >&5 +echo $ECHO_N "checking switches for the host compiler... $ECHO_C" >&6 +if test "$config_BUILD_CFLAGS" != ""; then +  CFLAGS=$config_BUILD_CFLAGS +  BUILD_CFLAGS=$config_BUILD_CFLAGS +else +  BUILD_CFLAGS=$default_build_cflags +fi +echo "$as_me:$LINENO: result: $BUILD_CFLAGS" >&5 +echo "${ECHO_T}$BUILD_CFLAGS" >&6 +if test "$config_BUILD_LIBS" != ""; then +  BUILD_LIBS=$config_BUILD_LIBS +fi + + + + +########## +# Locate a compiler that converts C code into *.o files that run on +# the target machine. +# +echo "$as_me:$LINENO: checking target compiler" >&5 +echo $ECHO_N "checking target compiler... $ECHO_C" >&6 +if test "$config_TARGET_CC" != ""; then +  TARGET_CC=$config_TARGET_CC +else +  TARGET_CC=$BUILD_CC +fi +echo "$as_me:$LINENO: result: $TARGET_CC" >&5 +echo "${ECHO_T}$TARGET_CC" >&6 +echo "$as_me:$LINENO: checking switches on the target compiler" >&5 +echo $ECHO_N "checking switches on the target compiler... $ECHO_C" >&6 +if test "$config_TARGET_CFLAGS" != ""; then +  TARGET_CFLAGS=$config_TARGET_CFLAGS +else +  TARGET_CFLAGS=$BUILD_CFLAGS +fi +echo "$as_me:$LINENO: result: $TARGET_CFLAGS" >&5 +echo "${ECHO_T}$TARGET_CFLAGS" >&6 +echo "$as_me:$LINENO: checking target linker" >&5 +echo $ECHO_N "checking target linker... $ECHO_C" >&6 +if test "$config_TARGET_LINK" = ""; then +  TARGET_LINK=$TARGET_CC +else +  TARGET_LINK=$config_TARGET_LINK +fi +echo "$as_me:$LINENO: result: $TARGET_LINK" >&5 +echo "${ECHO_T}$TARGET_LINK" >&6 +echo "$as_me:$LINENO: checking switches on the target compiler" >&5 +echo $ECHO_N "checking switches on the target compiler... $ECHO_C" >&6 +if test "$config_TARGET_TFLAGS" != ""; then +  TARGET_TFLAGS=$config_TARGET_TFLAGS +else +  TARGET_TFLAGS=$BUILD_CFLAGS +fi +if test "$config_TARGET_RANLIB" != ""; then +  TARGET_RANLIB=$config_TARGET_RANLIB +else +  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 + +  TARGET_RANLIB=$RANLIB +fi +if test "$config_TARGET_AR" != ""; then +  TARGET_AR=$config_TARGET_AR +else +  TARGET_AR='ar cr' +fi +echo "$as_me:$LINENO: result: $TARGET_TFLAGS" >&5 +echo "${ECHO_T}$TARGET_TFLAGS" >&6 + + + + + + + +# Set the $cross variable if we are cross-compiling.  Make +# it 0 if we are not. +# +echo "$as_me:$LINENO: checking if host and target compilers are the same" >&5 +echo $ECHO_N "checking if host and target compilers are the same... $ECHO_C" >&6 +if test "$BUILD_CC" = "$TARGET_CC"; then +  cross=0 +  echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +  cross=1 +  echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +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=no +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 +  THREADSAFE=0 +  echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else +  THREADSAFE=1 +  echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +if test "$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 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 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=yes +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 +  ;; +  * ) +    TEMP_STORE=2 +    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 "$cross" = "0"; then +  TARGET_EXEEXT=$BUILD_EXEEXT +else +  TARGET_EXEEXT=$config_TARGET_EXEEXT +fi +if test "$TARGET_EXEEXT" = ".exe"; then +  OS_UNIX=0 +  OS_WIN=1 +  tclsubdir=win +  TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" +else +  OS_UNIX=1 +  OS_WIN=0 +  tclsubdir=unix +  TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1" +fi + + + + + + +########## +# Extract generic linker options from the environment. +# +if test "$config_TARGET_LIBS" != ""; then +  TARGET_LIBS=$config_TARGET_LIBS +else +  TARGET_LIBS="" +fi + + +########## +# Figure out what C libraries are required to compile Tcl programs. +# +if test "$config_TARGET_TCL_LIBS" != ""; then +  TARGET_TCL_LIBS="$config_TARGET_TCL_LIBS" +else +  if test "$with_tcl" != ""; then +    extra=`echo $with_tcl/$tclsubdir/libtcl8*.a` +  fi +  CC=$TARGET_CC +  echo "$as_me:$LINENO: checking for sin" >&5 +echo $ECHO_N "checking for sin... $ECHO_C" >&6 +if test "${ac_cv_func_sin+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 sin to an innocuous variant, in case <limits.h> declares sin. +   For example, HP-UX 11i <limits.h> declares gettimeofday.  */ +#define sin innocuous_sin + +/* System header to define __stub macros and hopefully few prototypes, +    which can conflict with char sin (); below. +    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef sin + +/* 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 sin (); +/* 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_sin) || defined (__stub___sin) +choke me +#else +char (*f) () = sin; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != sin; +  ; +  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_sin=yes +else +  echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_sin=no +fi +rm -f conftest.err conftest.$ac_objext \ +      conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5 +echo "${ECHO_T}$ac_cv_func_sin" >&6 +if test $ac_cv_func_sin = yes; then +  LIBS="" +else +  LIBS="-lm" +fi + + +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 +  cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + +  LIBS="-ldl $LIBS" + +fi + +  otherlibs=$LIBS +  if test "$extra" != ""; then +    LIBS=$extra +  else +    LIBS="" +    echo "$as_me:$LINENO: checking for library containing Tcl_Init" >&5 +echo $ECHO_N "checking for library containing Tcl_Init... $ECHO_C" >&6 +if test "${ac_cv_search_Tcl_Init+set}" = set; then +  echo $ECHO_N "(cached) $ECHO_C" >&6 +else +  ac_func_search_save_LIBS=$LIBS +ac_cv_search_Tcl_Init=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 Tcl_Init (); +int +main () +{ +Tcl_Init (); +  ; +  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_Tcl_Init="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_Tcl_Init" = no; then +  for ac_lib in         tcl8.4 tcl8.3 tcl84 tcl83 tcl; do +    LIBS="-l$ac_lib $otherlibs $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 Tcl_Init (); +int +main () +{ +Tcl_Init (); +  ; +  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_Tcl_Init="-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_Tcl_Init" >&5 +echo "${ECHO_T}$ac_cv_search_Tcl_Init" >&6 +if test "$ac_cv_search_Tcl_Init" != no; then +  test "$ac_cv_search_Tcl_Init" = "none required" || LIBS="$ac_cv_search_Tcl_Init $LIBS" + +fi + +  fi +  TARGET_TCL_LIBS="$LIBS $otherlibs" +fi + + +########## +# Figure out where to get the TCL header files. +# +echo "$as_me:$LINENO: checking TCL header files" >&5 +echo $ECHO_N "checking TCL header files... $ECHO_C" >&6 +found=no +if test "$config_TARGET_TCL_INC" != ""; then +  TARGET_TCL_INC=$config_TARGET_TCL_INC +  found=yes +else +  if test "$with_tcl" != ""; then +    TARGET_TCL_INC="-I$with_tcl/generic -I$with_tcl/$tclsubdir" +    found=yes +  else +    TARGET_TCL_INC="" +    found=no +  fi +fi +if test "$found" = "yes"; then +  echo "$as_me:$LINENO: result: $TARGET_TCL_INC" >&5 +echo "${ECHO_T}$TARGET_TCL_INC" >&6 +else +  echo "$as_me:$LINENO: result: not specified: still searching..." >&5 +echo "${ECHO_T}not specified: still searching..." >&6 +  if test "${ac_cv_header_tcl_h+set}" = set; then +  echo "$as_me:$LINENO: checking for tcl.h" >&5 +echo $ECHO_N "checking for tcl.h... $ECHO_C" >&6 +if test "${ac_cv_header_tcl_h+set}" = set; then +  echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_tcl_h" >&5 +echo "${ECHO_T}$ac_cv_header_tcl_h" >&6 +else +  # Is the header compilable? +echo "$as_me:$LINENO: checking tcl.h usability" >&5 +echo $ECHO_N "checking tcl.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 <tcl.h> +_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 tcl.h presence" >&5 +echo $ECHO_N "checking tcl.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 <tcl.h> +_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: tcl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: tcl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: tcl.h: proceeding with the compiler's result" >&2;} +    ac_header_preproc=yes +    ;; +  no:yes:* ) +    { echo "$as_me:$LINENO: WARNING: tcl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: tcl.h: present but cannot be compiled" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h:     check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: tcl.h:     check for missing prerequisite headers?" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: tcl.h: see the Autoconf documentation" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h:     section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: tcl.h:     section \"Present But Cannot Be Compiled\"" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: tcl.h: proceeding with the preprocessor's result" >&2;} +    { echo "$as_me:$LINENO: WARNING: tcl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: tcl.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 tcl.h" >&5 +echo $ECHO_N "checking for tcl.h... $ECHO_C" >&6 +if test "${ac_cv_header_tcl_h+set}" = set; then +  echo $ECHO_N "(cached) $ECHO_C" >&6 +else +  ac_cv_header_tcl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_tcl_h" >&5 +echo "${ECHO_T}$ac_cv_header_tcl_h" >&6 + +fi +if test $ac_cv_header_tcl_h = yes; then +  found=yes +fi + + +fi +if test "$found" = "no"; then +  for dir in /usr/local /usr/X11 /usr/X11R6 /usr/pkg /usr/contrib /usr; do +    as_ac_File=`echo "ac_cv_file_$dir/include/tcl.h" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $dir/include/tcl.h" >&5 +echo $ECHO_N "checking for $dir/include/tcl.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/include/tcl.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_TCL_INC="-I$dir/include" +      break +    fi +  done +fi +if test "$found" = "no"; then +  TARGET_TCL_INC="-DNO_TCL=1" +fi + + +########## +# Figure out what C libraries are required to compile programs +# that use "readline()" library. +# +if test "$config_TARGET_READLINE_LIBS" != ""; then +  TARGET_READLINE_LIBS="$config_TARGET_READLINE_LIBS" +else +  CC=$TARGET_CC +  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" + +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 +  cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + +  LIBS="-lreadline $LIBS" + +fi + +  TARGET_READLINE_LIBS="$LIBS" +fi + + +########## +# Figure out where to get the READLINE header files. +# +echo "$as_me:$LINENO: checking readline header files" >&5 +echo $ECHO_N "checking readline header files... $ECHO_C" >&6 +found=no +if test "$config_TARGET_READLINE_INC" != ""; then +  TARGET_READLINE_INC=$config_TARGET_READLINE_INC +  found=yes +fi +if test "$found" = "yes"; then +  echo "$as_me:$LINENO: result: $TARGET_READLINE_INC" >&5 +echo "${ECHO_T}$TARGET_READLINE_INC" >&6 +else +  echo "$as_me:$LINENO: result: not specified: still searching..." >&5 +echo "${ECHO_T}not specified: still searching..." >&6 +  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 <readline.h> +_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 <readline.h> +_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 +fi + + +fi +if test "$found" = "no"; then +  for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do +    as_ac_File=`echo "ac_cv_file_$dir/include/readline.h" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $dir/include/readline.h" >&5 +echo $ECHO_N "checking for $dir/include/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/include/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/include" +      break +    fi +    as_ac_File=`echo "ac_cv_file_$dir/include/readline/readline.h" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $dir/include/readline/readline.h" >&5 +echo $ECHO_N "checking for $dir/include/readline/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/include/readline/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/include/readline" +      break +    fi +  done +fi +if test "$found" = "yes"; then +  if test "$TARGET_READLINE_LIBS" = ""; then +    TARGET_HAVE_READLINE=0 +  else +    TARGET_HAVE_READLINE=1 +  fi +else +  TARGET_HAVE_READLINE=0 +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 <limits.h> declares usleep. +   For example, HP-UX 11i <limits.h> declares gettimeofday.  */ +#define usleep innocuous_usleep + +/* System header to define __stub macros and hopefully few prototypes, +    which can conflict with char usleep (); below. +    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since +    <limits.h> exists even on freestanding compilers.  */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#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 + + +######### +# 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 <bug-autoconf@gnu.org>." +_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,@program_prefix@,$program_prefix,;t t +s,@VERSION@,$VERSION,;t t +s,@BUILD_CC@,$BUILD_CC,;t t +s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t +s,@BUILD_LIBS@,$BUILD_LIBS,;t t +s,@TARGET_CC@,$TARGET_CC,;t t +s,@TARGET_CFLAGS@,$TARGET_CFLAGS,;t t +s,@TARGET_LINK@,$TARGET_LINK,;t t +s,@TARGET_LFLAGS@,$TARGET_LFLAGS,;t t +s,@TARGET_RANLIB@,$TARGET_RANLIB,;t t +s,@TARGET_AR@,$TARGET_AR,;t t +s,@THREADSAFE@,$THREADSAFE,;t t +s,@TARGET_THREAD_LIB@,$TARGET_THREAD_LIB,;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,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t +s,@TARGET_LIBS@,$TARGET_LIBS,;t t +s,@TARGET_TCL_LIBS@,$TARGET_TCL_LIBS,;t t +s,@TARGET_TCL_INC@,$TARGET_TCL_INC,;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,@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/ext/pdo_sqlite/sqlite/configure.ac b/ext/pdo_sqlite/sqlite/configure.ac new file mode 100644 index 0000000000..20cd5a8ccd --- /dev/null +++ b/ext/pdo_sqlite/sqlite/configure.ac @@ -0,0 +1,540 @@ +# +# This file describes a "configure" script that is used to build +# makefiles for a particular platform.  Process this file using  +# Autoconf version 1.13 in order to generate that script.  All  +# lines of this file up to the AC_INIT macro are ignored. +# +# 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. +# +#    TARGET_CC +# +#        The name of a command that runs on the build platform +#        and converts C source files into *.o files for the +#        target platform.  In other words, the cross-compiler. +# +#    TARGET_CFLAGS +# +#        Switches that the target compiler needs to turn C source files +#        into *.o files.  Do not include TARGET_TCL_INC in this list. +#        Makefiles might add additional switches such as "-I.". +# +#    TARGET_TCL_LIBS +# +#        This is the library directives passed to the target linker +#        that cause the executable to link against Tcl.  This might +#        be a switch like "-ltcl8.0" or pathnames of library file +#        like "../../src/libtcl8.0.a". +# +#    TARGET_TCL_INC +# +#        This variables define the directory that contain header +#        files for Tcl.  If the compiler is able to find <tcl.h> +#        on its own, then this can be blank. +# +#    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 <readline.h> on its own, then this can be blank. +# +#    TARGET_LINK +# +#        The name of the linker that combines *.o files generated +#        by TARGET_CC into executables for the target platform. +# +#    TARGET_LIBS +# +#        Additional libraries or other switch that the target linker needs +#        to build an executable on the target.  Do not include +#        on this list any libraries in TARGET_TCL_LIBS and +#        TARGET_READLINE_LIBS, etc. +# +#    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. +# +# If you have a Tcl/Tk/BLT source distribution available, then the +# files in that distribution will be used instead of any other +# Tcl/Tk/BLT files the script might discover if you tell the configure +# script about the source tree.  Use commandline options: +# +#         --with-tcl=PATH  --with-tk=PATH  --with-blt=PATH +# +# Or set environment variables config_WITH_TCL, config_WITH_TK, or +# config_WITH_BLT. +# +# 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$ + +######### +# Programs needed +# +AC_PROG_LIBTOOL +AC_PROG_INSTALL + +######### +# Set up an appropriate program prefix +# +if test "$program_prefix" = "NONE"; then +  program_prefix="" +fi +AC_SUBST(program_prefix) + +if test -f VERSION; then +  VERSION=`cat VERSION` +  echo "Version set to $VERSION" +fi +AC_SUBST(VERSION) + +######### +# 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, +  [  --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. +# +default_build_cflags="-g" +if test "$config_BUILD_CC" = ""; then +  AC_PROG_CC +  if test "$cross_compiling" = "yes"; then +    AC_MSG_ERROR([unable to find a compiler for building build tools]) +  fi +  BUILD_CC=$CC +  default_build_cflags=$CFLAGS +else +  BUILD_CC=$config_BUILD_CC +  AC_MSG_CHECKING([host compiler]) +  CC=$BUILD_CC +  AC_MSG_RESULT($BUILD_CC) +fi +AC_MSG_CHECKING([switches for the host compiler]) +if test "$config_BUILD_CFLAGS" != ""; then +  CFLAGS=$config_BUILD_CFLAGS +  BUILD_CFLAGS=$config_BUILD_CFLAGS +else +  BUILD_CFLAGS=$default_build_cflags +fi +AC_MSG_RESULT($BUILD_CFLAGS) +if test "$config_BUILD_LIBS" != ""; then +  BUILD_LIBS=$config_BUILD_LIBS +fi +AC_SUBST(BUILD_CC) +AC_SUBST(BUILD_CFLAGS) +AC_SUBST(BUILD_LIBS) + +########## +# Locate a compiler that converts C code into *.o files that run on +# the target machine. +# +AC_MSG_CHECKING([target compiler]) +if test "$config_TARGET_CC" != ""; then +  TARGET_CC=$config_TARGET_CC +else +  TARGET_CC=$BUILD_CC +fi +AC_MSG_RESULT($TARGET_CC) +AC_MSG_CHECKING([switches on the target compiler]) +if test "$config_TARGET_CFLAGS" != ""; then +  TARGET_CFLAGS=$config_TARGET_CFLAGS +else +  TARGET_CFLAGS=$BUILD_CFLAGS +fi +AC_MSG_RESULT($TARGET_CFLAGS) +AC_MSG_CHECKING([target linker]) +if test "$config_TARGET_LINK" = ""; then +  TARGET_LINK=$TARGET_CC +else +  TARGET_LINK=$config_TARGET_LINK +fi +AC_MSG_RESULT($TARGET_LINK) +AC_MSG_CHECKING([switches on the target compiler]) +if test "$config_TARGET_TFLAGS" != ""; then +  TARGET_TFLAGS=$config_TARGET_TFLAGS +else +  TARGET_TFLAGS=$BUILD_CFLAGS +fi +if test "$config_TARGET_RANLIB" != ""; then +  TARGET_RANLIB=$config_TARGET_RANLIB +else +  AC_PROG_RANLIB +  TARGET_RANLIB=$RANLIB +fi +if test "$config_TARGET_AR" != ""; then +  TARGET_AR=$config_TARGET_AR +else +  TARGET_AR='ar cr' +fi +AC_MSG_RESULT($TARGET_TFLAGS) +AC_SUBST(TARGET_CC) +AC_SUBST(TARGET_CFLAGS) +AC_SUBST(TARGET_LINK) +AC_SUBST(TARGET_LFLAGS) +AC_SUBST(TARGET_RANLIB) +AC_SUBST(TARGET_AR) + +# Set the $cross variable if we are cross-compiling.  Make +# it 0 if we are not. +# +AC_MSG_CHECKING([if host and target compilers are the same]) +if test "$BUILD_CC" = "$TARGET_CC"; then +  cross=0 +  AC_MSG_RESULT(yes) +else +  cross=1 +  AC_MSG_RESULT(no) +fi + +########## +# Do we want to support multithreaded use of sqlite +# +AC_ARG_ENABLE(threadsafe,  +[  --enable-threadsafe           Support threadsafe operation],,enable_threadsafe=no) +AC_MSG_CHECKING([whether to support threadsafe operation]) +if test "$enable_threadsafe" = "no"; then +  THREADSAFE=0 +  AC_MSG_RESULT([no]) +else +  THREADSAFE=1 +  AC_MSG_RESULT([yes]) +fi +AC_SUBST(THREADSAFE) + +if test "$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 support release +# +AC_ARG_ENABLE(releasemode,  +[  --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 VERSION`" +  AC_MSG_RESULT([yes]) +fi +AC_SUBST(ALLOWRELEASE) + +########## +# Do we want temporary databases in memory +# +AC_ARG_ENABLE(tempstore,  +[  --enable-tempstore     Use an in-ram database for temporary tables (never,no,yes,always)],,enable_tempstore=yes) +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]) +  ;; +  * )  +    TEMP_STORE=2 +    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 "$cross" = "0"; then +  TARGET_EXEEXT=$BUILD_EXEEXT +else +  TARGET_EXEEXT=$config_TARGET_EXEEXT +fi +if test "$TARGET_EXEEXT" = ".exe"; then +  OS_UNIX=0 +  OS_WIN=1 +  tclsubdir=win +  TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" +else +  OS_UNIX=1 +  OS_WIN=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(TARGET_EXEEXT) + +########## +# Extract generic linker options from the environment. +# +if test "$config_TARGET_LIBS" != ""; then +  TARGET_LIBS=$config_TARGET_LIBS +else +  TARGET_LIBS="" +fi +AC_SUBST(TARGET_LIBS) + +########## +# Figure out what C libraries are required to compile Tcl programs. +# +if test "$config_TARGET_TCL_LIBS" != ""; then +  TARGET_TCL_LIBS="$config_TARGET_TCL_LIBS" +else +  if test "$with_tcl" != ""; then +    extra=`echo $with_tcl/$tclsubdir/libtcl8*.a` +  fi +  CC=$TARGET_CC +  AC_CHECK_FUNC(sin, LIBS="", LIBS="-lm") +  AC_CHECK_LIB(dl, dlopen) +  otherlibs=$LIBS +  if test "$extra" != ""; then +    LIBS=$extra +  else  +    LIBS="" +    AC_SEARCH_LIBS(Tcl_Init, dnl +        tcl8.4 tcl8.3 tcl84 tcl83 tcl,,,$otherlibs) +  fi +  TARGET_TCL_LIBS="$LIBS $otherlibs" +fi +AC_SUBST(TARGET_TCL_LIBS) + +########## +# Figure out where to get the TCL header files. +# +AC_MSG_CHECKING([TCL header files]) +found=no +if test "$config_TARGET_TCL_INC" != ""; then +  TARGET_TCL_INC=$config_TARGET_TCL_INC +  found=yes +else +  if test "$with_tcl" != ""; then +    TARGET_TCL_INC="-I$with_tcl/generic -I$with_tcl/$tclsubdir" +    found=yes +  else +    TARGET_TCL_INC="" +    found=no +  fi +fi +if test "$found" = "yes"; then +  AC_MSG_RESULT($TARGET_TCL_INC) +else +  AC_MSG_RESULT(not specified: still searching...) +  AC_CHECK_HEADER(tcl.h, [found=yes]) +fi +if test "$found" = "no"; then +  for dir in /usr/local /usr/X11 /usr/X11R6 /usr/pkg /usr/contrib /usr; do +    AC_CHECK_FILE($dir/include/tcl.h, found=yes) +    if test "$found" = "yes"; then +      TARGET_TCL_INC="-I$dir/include" +      break +    fi +  done +fi +if test "$found" = "no"; then +  TARGET_TCL_INC="-DNO_TCL=1" +fi +AC_SUBST(TARGET_TCL_INC) + +########## +# Figure out what C libraries are required to compile programs +# that use "readline()" library. +# +if test "$config_TARGET_READLINE_LIBS" != ""; then +  TARGET_READLINE_LIBS="$config_TARGET_READLINE_LIBS" +else +  CC=$TARGET_CC +  LIBS="" +  AC_SEARCH_LIBS(tgetent, [readline ncurses curses termcap]) +  AC_CHECK_LIB([readline], [readline]) +  TARGET_READLINE_LIBS="$LIBS" +fi +AC_SUBST(TARGET_READLINE_LIBS) + +########## +# Figure out where to get the READLINE header files. +# +AC_MSG_CHECKING([readline header files]) +found=no +if test "$config_TARGET_READLINE_INC" != ""; then +  TARGET_READLINE_INC=$config_TARGET_READLINE_INC +  found=yes +fi +if test "$found" = "yes"; then +  AC_MSG_RESULT($TARGET_READLINE_INC) +else +  AC_MSG_RESULT(not specified: still searching...) +  AC_CHECK_HEADER(readline.h, [found=yes]) +fi +if test "$found" = "no"; then +  for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do +    AC_CHECK_FILE($dir/include/readline.h, found=yes) +    if test "$found" = "yes"; then +      TARGET_READLINE_INC="-I$dir/include" +      break +    fi +    AC_CHECK_FILE($dir/include/readline/readline.h, found=yes) +    if test "$found" = "yes"; then +      TARGET_READLINE_INC="-I$dir/include/readline" +      break +    fi +  done +fi +if test "$found" = "yes"; then +  if test "$TARGET_READLINE_LIBS" = ""; then +    TARGET_HAVE_READLINE=0 +  else +    TARGET_HAVE_READLINE=1 +  fi +else +  TARGET_HAVE_READLINE=0 +fi +AC_SUBST(TARGET_READLINE_INC) +AC_SUBST(TARGET_HAVE_READLINE) + +######### +# Figure out whether or not we have a "usleep()" function. +# +AC_CHECK_FUNC(usleep, [TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_USLEEP=1"]) + +######### +# Generate the output files. +# +AC_OUTPUT([ +Makefile +sqlite3.pc +]) diff --git a/ext/pdo_sqlite/sqlite/install-sh b/ext/pdo_sqlite/sqlite/install-sh new file mode 100755 index 0000000000..e9de23842d --- /dev/null +++ b/ext/pdo_sqlite/sqlite/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/ext/pdo_sqlite/sqlite/ltmain.sh b/ext/pdo_sqlite/sqlite/ltmain.sh new file mode 100644 index 0000000000..4b9f940539 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/ltmain.sh @@ -0,0 +1,6399 @@ +# 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 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# 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 "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then +  # used as fallback echo +  shift +  cat <<EOF +$* +EOF +  exit 0 +fi + +# The name of this program. +progname=`$echo "$0" | ${SED} 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.2 +TIMESTAMP=" (1.1220.2.60 2004/01/25 12:25:08) Debian$Rev: 192 $" + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# 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' +# test EBCDIC or ASCII +case `echo A|tr A '\301'` in + A) # EBCDIC based system +  SP2NL="tr '\100' '\n'" +  NL2SP="tr '\r\n' '\100\100'" +  ;; + *) # Assume ASCII based system +  SP2NL="tr '\040' '\012'" +  NL2SP="tr '\015\012' '\040\040'" +  ;; +esac + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +# We save the old values to restore during execute mode. +if test "${LC_ALL+set}" = set; then +  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL +fi +if test "${LANG+set}" = set; then +  save_LANG="$LANG"; LANG=C; export LANG +fi + +# Make sure IFS has a sensible default +: ${IFS=" 	 +"} + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then +  $echo "$modename: not configured to build any kind of library" 1>&2 +  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2 +  exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# 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. +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 | \ +      grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then +      win32_nmres=`eval $NM -f posix -A $1 | \ +	sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` +      if test "X$win32_nmres" = "Ximport" ; then +        win32_libid_type="x86 archive import" +      else +        win32_libid_type="x86 archive static" +      fi +    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 +} + +# End of Shell function definitions +##################################### + +# 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 1 +	;; +      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$" < "$0" > /dev/null; then +	  taglist="$taglist $tagname" +	  # Evaluate the configuration. +	  eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`" +	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) 2003  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 0 +    ;; + +  --config) +    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 +    # 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" < "$0" +    done +    exit 0 +    ;; + +  --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 0 +    ;; + +  --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 ;; +  --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 1 +    ;; + +  *) +    nonopt="$arg" +    break +    ;; +  esac +done + +if test -n "$prevopt"; then +  $echo "$modename: option \`$prevopt' requires an argument" 1>&2 +  $echo "$help" 1>&2 +  exit 1 +fi + +# 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 1 +  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 1 +	  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, so we specify it 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 1 +      ;; +    target) +      $echo "$modename: you must specify a target with \`-o'" 1>&2 +      exit 1 +      ;; +    *) +      # 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 1 +      ;; +    esac + +    # 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. +    if test -n "$available_tags" && test -z "$tagname"; then +      case $base_compile 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` "*) ;; +      # 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$" < "$0" > /dev/null; then +	    # Evaluate the configuration. +	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" +	    case "$base_compile " in +	    "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) +	      # 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 1 +#        else +#          $echo "$modename: using $tagname tagged configuration" +	fi +	;; +      esac +    fi + +    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 + +    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 1 +    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 1" 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 1" 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 "$0" "$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 1 +      fi +      $echo $srcfile > "$lockfile" +    fi + +    if test -n "$fix_srcfile_path"; then +      eval srcfile=\"$fix_srcfile_path\" +    fi + +    $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 <<EOF +# $libobj - a libtool object file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +EOF + +    # Only build a PIC object if we are building libtool libraries. +    if test "$build_libtool_libs" = yes; then +      # Without this assignment, base_compile gets emptied. +      fbsd_hideous_sh_bug=$base_compile + +      if test "$pic_mode" != no; then +	command="$base_compile $srcfile $pic_flag" +      else +	# Don't build PIC code +	command="$base_compile $srcfile" +      fi + +      if test ! -d "${xdir}$objdir"; then +	$show "$mkdir ${xdir}$objdir" +	$run $mkdir ${xdir}$objdir +	status=$? +	if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then +	  exit $status +	fi +      fi + +      if test -z "$output_obj"; then +	# Place PIC objects in $objdir +	command="$command -o $lobj" +      fi + +      $run $rm "$lobj" "$output_obj" + +      $show "$command" +      if $run eval "$command"; then : +      else +	test -n "$output_obj" && $run $rm $removelist +	exit 1 +      fi + +      if test "$need_locks" = warn && +	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then +	$echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together.  If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + +	$run $rm $removelist +	exit 1 +      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 <<EOF +pic_object='$objdir/$objname' + +EOF + +      # Allow error messages only from the first compilation. +      if test "$suppress_opt" = yes; then +        suppress_output=' >/dev/null 2>&1' +      fi +    else +      # No PIC object so indicate it doesn't exist in the libtool +      # object file. +      test -z "$run" && cat >> ${libobj}T <<EOF +pic_object=none + +EOF +    fi + +    # Only build a position-dependent object if we build old libraries. +    if test "$build_old_libs" = yes; then +      if test "$pic_mode" != yes; then +	# Don't build PIC code +	command="$base_compile $srcfile" +      else +	command="$base_compile $srcfile $pic_flag" +      fi +      if test "$compiler_c_o" = yes; then +	command="$command -o $obj" +      fi + +      # Suppress compiler output if we already did a PIC compilation. +      command="$command$suppress_output" +      $run $rm "$obj" "$output_obj" +      $show "$command" +      if $run eval "$command"; then : +      else +	$run $rm $removelist +	exit 1 +      fi + +      if test "$need_locks" = warn && +	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then +	$echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together.  If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + +	$run $rm $removelist +	exit 1 +      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 <<EOF +# Name of the non-PIC object. +non_pic_object='$objname' + +EOF +    else +      # 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 <<EOF +# Name of the non-PIC object. +non_pic_object=none + +EOF +    fi + +    $run $mv "${libobj}T" "${libobj}" + +    # Unlock the critical section if it was locked +    if test "$need_locks" != no; then +      $run $rm "$lockfile" +    fi + +    exit 0 +    ;; + +  # libtool link mode +  link | relink) +    modename="$modename: link" +    case $host in +    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) +      # It is impossible to link a dll without this setting, and +      # we shouldn't force the makefile maintainer to figure out +      # which system we are compiling for in order to pass an extra +      # flag for every libtool invocation. +      # allow_undefined=no + +      # FIXME: Unfortunately, there are problems with the above when trying +      # to make a dll which has undefined symbols, in which case not +      # even a static library is built.  For now, we need to specify +      # -no-undefined on the libtool link line when we can be certain +      # that all symbols are satisfied, otherwise we get a static library. +      allow_undefined=yes +      ;; +    *) +      allow_undefined=yes +      ;; +    esac +    libtool_args="$nonopt" +    base_compile="$nonopt $@" +    compile_command="$nonopt" +    finalize_command="$nonopt" + +    compile_rpath= +    finalize_rpath= +    compile_shlibpath= +    finalize_shlibpath= +    convenience= +    old_convenience= +    deplibs= +    old_deplibs= +    compiler_flags= +    linker_flags= +    dllsearchpath= +    lib_search_path=`pwd` +    inst_prefix_dir= + +    avoid_version=no +    dlfiles= +    dlprefiles= +    dlself=no +    export_dynamic=no +    export_symbols= +    export_symbols_regex= +    generated= +    libobjs= +    ltlibs= +    module=no +    no_install=no +    objs= +    non_pic_objects= +    precious_files_regex= +    prefer_static_libs=no +    preload=no +    prev= +    prevarg= +    release= +    rpath= +    xrpath= +    perm_rpath= +    temp_rpath= +    thread_safe=no +    vinfo= +    vinfo_number=no + +    # 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 link +    # command doesn't match the default compiler. +    if test -n "$available_tags" && test -z "$tagname"; then +      case $base_compile 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` "*) ;; +      # 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$" < "$0" > /dev/null; then +	    # Evaluate the configuration. +	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" +	    case $base_compile in +	    "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) +	      # The compiler in $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 1 +#       else +#         $echo "$modename: using $tagname tagged configuration" +	fi +	;; +      esac +    fi + +    # We need to know -static, to get the right output filenames. +    for arg +    do +      case $arg in +      -all-static | -static) +	if test "X$arg" = "X-all-static"; then +	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then +	    $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 +	  fi +	  if test -n "$link_static_flag"; then +	    dlopen_self=$dlopen_self_static +	  fi +	else +	  if test -z "$pic_flag" && test -n "$link_static_flag"; then +	    dlopen_self=$dlopen_self_static +	  fi +	fi +	build_libtool_libs=no +	build_old_libs=yes +	prefer_static_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 1 +	  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 1 +		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 +		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 1 +		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 1 +	  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 1 +	    ;; +	  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 +	  ;; +	*) +	  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 1 +	fi +	if test "X$arg" = "X-export-symbols"; then +	  prev=expsyms +	else +	  prev=expsyms_regex +	fi +	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 +	    exit 1 +	  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*) +	  case :$dllsearchpath: in +	  *":$dir:"*) ;; +	  *) dllsearchpath="$dllsearchpath:$dir";; +	  esac +	  ;; +	esac +	continue +	;; + +      -l*) +	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then +	  case $host in +	  *-*-cygwin* | *-*-pw32* | *-*-beos*) +	    # These systems don't actually have a C or math library (as such) +	    continue +	    ;; +	  *-*-mingw* | *-*-os2*) +	    # These systems don't actually have a C library (as such) +	    test "X$arg" = "X-lc" && continue +	    ;; +	  *-*-openbsd* | *-*-freebsd*) +	    # 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 +	  esac +	elif test "X$arg" = "X-lc_r"; then +	 case $host in +	 *-*-openbsd* | *-*-freebsd*) +	   # Do not include libc_r directly, use -pthread flag. +	   continue +	   ;; +	 esac +	fi +	deplibs="$deplibs $arg" +	continue +	;; + +     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) +	deplibs="$deplibs $arg" +	continue +	;; + +      -module) +	module=yes +	continue +	;; + +      # gcc -m* arguments should be passed to the linker via $compiler_flags +      # in order to pass architecture information to the linker +      # (e.g. 32 vs 64-bit).  This may also be accomplished via -Wl,-mfoo +      # but this is not reliable with gcc because gcc may use -mfoo to +      # select a different linker, different libraries, etc, while +      # -Wl,-mfoo simply passes -mfoo to the linker. +      -m*) +	# 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" +        if test "$with_gcc" = "yes" ; then +          compiler_flags="$compiler_flags $arg" +        fi +        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 1 +	  ;; +	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 1 +	  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 +	  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 1 +	  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 1 +    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 +      status=$? +      if test "$status" -ne 0 && test ! -d "$output_objdir"; then +	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 1 +      ;; +    *.$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 duplcations 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 +    notinst_path= # paths that contain 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 1 +	    ;; +	  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 +	    deplibs="$deplib $deplibs" +	  fi +	  continue +	  ;; +	-l*) +	  if test "$linkmode" != lib && test "$linkmode" != prog; then +	    $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 +	    continue +	  fi +	  if test "$pass" = conv; then +	    deplibs="$deplib $deplibs" +	    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 $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" +	      newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` +	    else +	      compile_deplibs="$deplib $compile_deplibs" +	      finalize_deplibs="$deplib $finalize_deplibs" +	    fi +	    ;; +	  *) +	    $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) +	    if test "$deplibs_check_method" != pass_all; 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'" 1>&2 +	  exit 1 +	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 1 +	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 + +	# 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 1 +	    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 1 +	  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 1 +	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 1 +	  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 +	else +	  dir="$ladir/$objdir" +	  absdir="$abs_ladir/$objdir" +	  # Remove this search path later +	  notinst_path="$notinst_path $abs_ladir" +	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 1 +	  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"; then +	      # Make sure the rpath contains only unique directories. +	      case "$temp_rpath " in +	      *" $dir "*) ;; +	      *" $absdir "*) ;; +	      *) temp_rpath="$temp_rpath $dir" ;; +	      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 +	if test -n "$library_names" && +	   { test "$prefer_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* ) 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 | grep "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 1 +	    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 +	    convenience="$convenience $dir/$old_library" +	    old_convenience="$old_convenience $dir/$old_library" +	    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 1 +		  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 +	      *" $depdepl "*) ;; +	      *) deplibs="$deplibs $depdepl" ;; +	      esac	       +	      case " $deplibs " in +	      *" $path "*) ;; +	      *) deplibs="$deplibs $path" ;; +	      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\" +	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 1 +	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\" +	  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 1 +	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 1 +	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]) ;; +	*) +	  $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 +	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2 +	  exit 1 +	  ;; +	esac + +	case $revision in +	0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; +	*) +	  $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 +	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2 +	  exit 1 +	  ;; +	esac + +	case $age in +	0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; +	*) +	  $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 +	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2 +	  exit 1 +	  ;; +	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 1 +	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="-compatibility_version $minor_current -current_version $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 1 +	  ;; +	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 echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 +	       then +		 continue +	       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*) +	    # Do not include libc due to us having libc/libc_r. +	    test "X$arg" = "X-lc" && continue +	    ;; + 	  *) +	    # 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 <<EOF +	  int main() { return 0; } +EOF +	  $rm conftest +	  $LTCC -o conftest conftest.c $deplibs +	  if test "$?" -eq 0 ; then +	    ldd_output=`ldd conftest` +	    for i in $deplibs; do +	      name="`expr $i : '-l\(.*\)'`" +	      # If $name is empty we are operating on a -L argument. +              if test "$name" != "" && test "$name" -ne "0"; then +		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then +		  case " $predeps $postdeps " in +		  *" $i "*) +		    newdeplibs="$newdeplibs $i" +		    i="" +		    ;; +		  esac +	        fi +		if test -n "$i" ; then +		  libname=`eval \\$echo \"$libname_spec\"` +		  deplib_matches=`eval \\$echo \"$library_names_spec\"` +		  set dummy $deplib_matches +		  deplib_match=$2 +		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then +		    newdeplibs="$newdeplibs $i" +		  else +		    droppeddeps=yes +		    $echo +		    $echo "*** Warning: dynamic linker does not accept needed library $i." +		    $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 I believe you do not have" +		    $echo "*** because a test_compile did reveal that the linker did not use it for" +		    $echo "*** its dynamic dependency list that programs get resolved with at runtime." +		  fi +		fi +	      else +		newdeplibs="$newdeplibs $i" +	      fi +	    done +	  else +	    # Error occurred in the first compile.  Let's try to salvage +	    # the situation: Compile a separate program for each library. +	    for i in $deplibs; do +	      name="`expr $i : '-l\(.*\)'`" +	      # If $name is empty we are operating on a -L argument. +              if test "$name" != "" && test "$name" != "0"; then +		$rm conftest +		$LTCC -o conftest conftest.c $i +		# Did it work? +		if test "$?" -eq 0 ; then +		  ldd_output=`ldd conftest` +		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then +		    case " $predeps $postdeps " in +		    *" $i "*) +		      newdeplibs="$newdeplibs $i" +		      i="" +		      ;; +		    esac +		  fi +		  if test -n "$i" ; then +		    libname=`eval \\$echo \"$libname_spec\"` +		    deplib_matches=`eval \\$echo \"$library_names_spec\"` +		    set dummy $deplib_matches +		    deplib_match=$2 +		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then +		      newdeplibs="$newdeplibs $i" +		    else +		      droppeddeps=yes +		      $echo +		      $echo "*** Warning: dynamic linker does not accept needed library $i." +		      $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 a test_compile did reveal that the linker did not use this one" +		      $echo "*** as a dynamic dependency that programs can get resolved with at runtime." +		    fi +		  fi +		else +		  droppeddeps=yes +		  $echo +		  $echo "*** Warning!  Library $i is needed by this library but I was not able to" +		  $echo "***  make it link in!  You will probably need to install it or some" +		  $echo "*** library that it depends on before this library will be fully" +		  $echo "*** functional.  Installing it before continuing would be even better." +		fi +	      else +		newdeplibs="$newdeplibs $i" +	      fi +	    done +	  fi +	  ;; +	file_magic*) +	  set dummy $deplibs_check_method +	  file_magic_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 "$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 +		      # 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 +		      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 + +      # 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\" +	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" +	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=: +	      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" +	    $show "${rm}r $gentop" +	    $run ${rm}r "$gentop" +	    $show "$mkdir $gentop" +	    $run $mkdir "$gentop" +	    status=$? +	    if test "$status" -ne 0 && test ! -d "$gentop"; then +	      exit $status +	    fi +	    generated="$generated $gentop" + +	    for xlib in $convenience; do +	      # Extract the objects. +	      case $xlib in +	      [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; +	      *) xabs=`pwd`"/$xlib" ;; +	      esac +	      xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` +	      xdir="$gentop/$xlib" + +	      $show "${rm}r $xdir" +	      $run ${rm}r "$xdir" +	      $show "$mkdir $xdir" +	      $run $mkdir "$xdir" +	      status=$? +	      if test "$status" -ne 0 && test ! -d "$xdir"; then +		exit $status +	      fi +	      # We will extract separately just the conflicting names and we will no +	      # longer touch any unique names. It is faster to leave these extract +	      # automatically by $AR in one run. +	      $show "(cd $xdir && $AR x $xabs)" +	      $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? +	      if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then +		: +	      else +		$echo "$modename: warning: object name conflicts; renaming object files" 1>&2 +		$echo "$modename: warning: to ensure that they will not overwrite" 1>&2 +		$AR t "$xabs" | sort | uniq -cd | while read -r count name +		do +		  i=1 +		  while test "$i" -le "$count" +		  do +		   # Put our $i before any first dot (extension) +		   # Never overwrite any file +		   name_to="$name" +		   while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" +		   do +		     name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` +		   done +		   $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" +		   $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? +		   i=`expr $i + 1` +		  done +		done +	      fi + +	      libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` +	    done +	  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" : ".*"` && +	   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 + +	  # 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/$save_output-${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" : ".*"` && +		 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/$save_output-${k}.$objext +	      k=`expr $k + 1` +	      output=$output_objdir/$save_output-${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 reloadale object files +	  # after they are used. +	  i=0 +	  while test "$i" -lt "$k" +	  do +	    i=`expr $i + 1` +	    delfiles="$delfiles $output_objdir/$save_output-${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" +	    eval cmd=\"$cmd\" +	    $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" || 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 $? +	  exit 0 +	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 1 +	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" +	  $show "${rm}r $gentop" +	  $run ${rm}r "$gentop" +	  $show "$mkdir $gentop" +	  $run $mkdir "$gentop" +	  status=$? +	  if test "$status" -ne 0 && test ! -d "$gentop"; then +	    exit $status +	  fi +	  generated="$generated $gentop" + +	  for xlib in $convenience; do +	    # Extract the objects. +	    case $xlib in +	    [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; +	    *) xabs=`pwd`"/$xlib" ;; +	    esac +	    xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` +	    xdir="$gentop/$xlib" + +	    $show "${rm}r $xdir" +	    $run ${rm}r "$xdir" +	    $show "$mkdir $xdir" +	    $run $mkdir "$xdir" +	    status=$? +	    if test "$status" -ne 0 && test ! -d "$xdir"; then +	      exit $status +	    fi +	    # We will extract separately just the conflicting names and we will no +	    # longer touch any unique names. It is faster to leave these extract +	    # automatically by $AR in one run. +	    $show "(cd $xdir && $AR x $xabs)" +	    $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? +	    if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then +	      : +	    else +	      $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 +	      $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 +	      $AR t "$xabs" | sort | uniq -cd | while read -r count name +	      do +		i=1 +		while test "$i" -le "$count" +		do +		 # Put our $i before any first dot (extension) +		 # Never overwrite any file +		 name_to="$name" +		 while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" +		 do +		   name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` +		 done +		 $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" +		 $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? +		 i=`expr $i + 1` +		done +	      done +	    fi + +	    reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` +	  done +	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 0 +      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 0 +      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 0 +      ;; + +    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 + +      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*) +	  case :$dllsearchpath: in +	  *":$libdir:"*) ;; +	  *) dllsearchpath="$dllsearchpath:$libdir";; +	  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/$output.exp" +	      $run $rm $export_symbols +	      $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' +	    else +	      $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' +	      $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' +	      $run eval 'mv "$nlist"T "$nlist"' +	    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 >/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. */ +const struct { +  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 -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" +	  $run eval '(cd $output_objdir && $LTCC -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. +	  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}%"` +	  ;; +	*) +	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 +	  exit 1 +	  ;; +	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" +	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 $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 0 +      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 $0 --fallback-echo"; then +	case $0 in +	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; +	*) qecho="$SHELL `pwd`/$0 --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* ) +	    cwrappersource=`$echo ${objdir}/lt-${output}.c` +	    cwrapper=`$echo ${output}.exe` +	    $rm $cwrappersource $cwrapper +	    trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15 + +	    cat > $cwrappersource <<EOF + +/* $cwrappersource - temporary wrapper executable 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 executable should never be moved out of the build directory. +   If it is, it will not operate correctly. + +   Currently, it simply execs the wrapper *script* "/bin/sh $output", +   but could eventually absorb all of the scripts functionality and +   exec $objdir/$outputname directly. +*/ +EOF +	    cat >> $cwrappersource<<"EOF" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> + +#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 '/' +#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 +#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 */ + +#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ +  if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +char * basename (const char *name); +char * fnqualify(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 ((char *) basename (argv[0])); +  newargz = XMALLOC(char *, argc+2); +EOF + +	    cat >> $cwrappersource <<EOF +  newargz[0] = "$SHELL"; +EOF + +	    cat >> $cwrappersource <<"EOF" +  newargz[1] = fnqualify(argv[0]); +  /* 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; +EOF + +	    cat >> $cwrappersource <<EOF +  execv("$SHELL",newargz); +EOF + +	    cat >> $cwrappersource <<"EOF" +} + +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 +; +} + +char * +basename (const char *name) +{ +  const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) +  /* Skip over the disk name in MSDOS pathnames. */ +  if (isalpha (name[0]) && name[1] == ':')  +    name += 2; +#endif + +  for (base = name; *name; name++) +    if (IS_DIR_SEPARATOR (*name)) +      base = name + 1; +  return (char *) base; +} + +char *  +fnqualify(const char *path) +{ +  size_t size; +  char *p; +  char tmp[LT_PATHMAX + 1]; + +  assert(path != NULL); + +  /* Is it qualified already? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) +  if (isalpha (path[0]) && path[1] == ':') +    return xstrdup (path); +#endif +  if (IS_DIR_SEPARATOR (path[0])) +    return xstrdup (path); + +  /* prepend the current directory */ +  /* doesn't handle '~' */ +  if (getcwd (tmp, LT_PATHMAX) == NULL) +    lt_fatal ("getcwd failed"); +  size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ +  p = XMALLOC(char, size); +  sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); +  return p; +} + +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 -s -o $cwrapper $cwrappersource +	  ;; +	esac +	$rm $output +	trap "$rm $output; exit 1" 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. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +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 1 +      fi +    fi + +    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || +    { $rm \"\$progdir/\$program\"; +      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } +    $rm \"\$progdir/\$file\" +  fi" +	else +	  $echo >> $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. +" +	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 1 +    fi +  else +    # The program doesn't exist. +    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 +    \$echo \"This script is just a wrapper for \$program.\" 1>&2 +    $echo \"See the $PACKAGE documentation for more information.\" 1>&2 +    exit 1 +  fi +fi\ +" +	chmod +x $output +      fi +      exit 0 +      ;; +    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" +	$show "${rm}r $gentop" +	$run ${rm}r "$gentop" +	$show "$mkdir $gentop" +	$run $mkdir "$gentop" +	status=$? +	if test "$status" -ne 0 && test ! -d "$gentop"; then +	  exit $status +	fi +	generated="$generated $gentop" + +	# Add in members from convenience archives. +	for xlib in $addlibs; do +	  # Extract the objects. +	  case $xlib in +	  [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; +	  *) xabs=`pwd`"/$xlib" ;; +	  esac +	  xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` +	  xdir="$gentop/$xlib" + +	  $show "${rm}r $xdir" +	  $run ${rm}r "$xdir" +	  $show "$mkdir $xdir" +	  $run $mkdir "$xdir" +	  status=$? +	  if test "$status" -ne 0 && test ! -d "$xdir"; then +	    exit $status +	  fi +	  # We will extract separately just the conflicting names and we will no +	  # longer touch any unique names. It is faster to leave these extract +	  # automatically by $AR in one run. +	  $show "(cd $xdir && $AR x $xabs)" +	  $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? +	  if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then +	    : +	  else +	    $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 +	    $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 +	    $AR t "$xabs" | sort | uniq -cd | while read -r count name +	    do +	      i=1 +	      while test "$i" -le "$count" +	      do +	       # Put our $i before any first dot (extension) +	       # Never overwrite any file +	       name_to="$name" +	       while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" +	       do +		 name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` +	       done +	       $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" +	       $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? +	       i=`expr $i + 1` +	      done +	    done +	  fi + +	  oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` +	done +      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 +	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 +	  # GNU ar 2.10+ was changed to match POSIX; thus no paths are +	  # encoded into archives.  This makes 'ar r' malfunction in +	  # this piecewise linking case whenever conflicting object +	  # names appear in distinct ar calls; check, warn and compensate. +	    if (for obj in $save_oldobjs +	    do +	      $echo "X$obj" | $Xsed -e 's%^.*/%%' +	    done | sort | sort -uc >/dev/null 2>&1); then +	    : +	  else +	    $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 +	    $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 +	    AR_FLAGS=cq +	  fi +	  # 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" : ".*"` && +	       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 $0 $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 1 +		fi +		newdependency_libs="$newdependency_libs $libdir/$name" +		;; +	      *) newdependency_libs="$newdependency_libs $deplib" ;; +	      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 1 +	      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 1 +	      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 +	  $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 0 +    ;; + +  # 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" | $Xsed | 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) prev="-f" ;; +      -g) prev="-g" ;; +      -m) prev="-m" ;; +      -o) prev="-o" ;; +      -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 1 +    fi + +    if test -n "$prev"; then +      $echo "$modename: the \`$prev' option requires an argument" 1>&2 +      $echo "$help" 1>&2 +      exit 1 +    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 1 +    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 1 +      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 1 +	  ;; +	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 1 +	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 1 +	  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 1 +	  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. +	    for linkname +	    do +	      if test "$linkname" != "$realname"; then +		$show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" +		$run eval "(cd $destdir && $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" || 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 1 +	  ;; +	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 0 +	;; + +      *) +	# 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= + +	  # To insure that "foo" is sourced, and not "foo.exe", +	  # finese the cygwin/MSYS system by explicitly sourcing "foo." +	  # which disallows the automatic-append-.exe behavior. +	  case $build in +	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; +	  *) wrapperdot=${wrapper} ;; +	  esac +	  # If there is no directory component, then add one. +	  case $file in +	  */* | *\\*) . ${wrapperdot} ;; +	  *) . ./${wrapperdot} ;; +	  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 1 +	  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= +	  # To insure that "foo" is sourced, and not "foo.exe", +	  # finese the cygwin/MSYS system by explicitly sourcing "foo." +	  # which disallows the automatic-append-.exe behavior. +	  case $build in +	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; +	  *) wrapperdot=${wrapper} ;; +	  esac +	  # If there is no directory component, then add one. +	  case $file in +	  */* | *\\*) . ${wrapperdot} ;; +	  *) . ./${wrapperdot} ;; +	  esac + +	  outputname= +	  if test "$fast_install" = no && test -n "$relink_command"; then +	    if test "$finalize" = yes && test -z "$run"; then +	      tmpdir="/tmp" +	      test -n "$TMPDIR" && tmpdir="$TMPDIR" +	      tmpdir="$tmpdir/libtool-$$" +	      if $mkdir "$tmpdir" && chmod 700 "$tmpdir"; then : +	      else +		$echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 +		continue +	      fi +	      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 anyways +	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 $0 $preserve_args --finish$current_libdirs' +    else +      exit 0 +    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 0 + +    $echo "----------------------------------------------------------------------" +    $echo "Libraries have been installed in:" +    for libdir in $libdirs; do +      $echo "   $libdir" +    done +    $echo +    $echo "If you ever happen to want to link against installed libraries" +    $echo "in a given directory, LIBDIR, you must either use libtool, and" +    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" +    $echo "flag during linking and do at least one of the following:" +    if test -n "$shlibpath_var"; then +      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable" +      $echo "     during execution" +    fi +    if test -n "$runpath_var"; then +      $echo "   - add LIBDIR to the \`$runpath_var' environment variable" +      $echo "     during linking" +    fi +    if test -n "$hardcode_libdir_flag_spec"; then +      libdir=LIBDIR +      eval flag=\"$hardcode_libdir_flag_spec\" + +      $echo "   - use the \`$flag' linker flag" +    fi +    if test -n "$admincmds"; then +      $echo "   - have your system administrator run these commands:$admincmds" +    fi +    if test -f /etc/ld.so.conf; then +      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" +    fi +    $echo +    $echo "See any operating system documentation about shared libraries for" +    $echo "more information, such as the ld(1) and ld.so(8) manual pages." +    $echo "----------------------------------------------------------------------" +    exit 0 +    ;; + +  # 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 1 +    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 1 +      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 1 +	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 1 +	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 0 +    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 1 +    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" +	  test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + +	  if test "$mode" = uninstall; then +	    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. +	  fi +	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 1 +    ;; +  esac + +  if test -z "$exec_cmd"; then +    $echo "$modename: invalid operation mode \`$mode'" 1>&2 +    $echo "$generic_help" 1>&2 +    exit 1 +  fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then +  eval exec $exec_cmd +  exit 1 +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 <bug-libtool@gnu.org>." +  exit 0 +  ;; + +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 1 +  ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries.  Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them.  This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration.  But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/ext/pdo_sqlite/sqlite/main.mk b/ext/pdo_sqlite/sqlite/main.mk new file mode 100644 index 0000000000..e79e0926ba --- /dev/null +++ b/ext/pdo_sqlite/sqlite/main.mk @@ -0,0 +1,533 @@ +############################################################################### +# 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. +# +# USLEEP           If the target operating system supports the "usleep()" system +#                  call, then define the HAVE_USLEEP macro for all C modules. +# +# THREADSAFE       If you want the SQLite library to be safe for use within a  +#                  multi-threaded program, then define the following macro +#                  appropriately: +# +# 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. +# +# ENCODING         "UTF8" or "ISO8859" +# +# 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) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src + +# Object files for the SQLite library. +# +LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \ +         expr.o func.o hash.o insert.o \ +         main.o opcodes.o os_mac.o os_unix.o os_win.o \ +         pager.o parse.o pragma.o printf.o random.o \ +         select.o table.o tclsqlite.o tokenize.o trigger.o \ +         update.o util.o vacuum.o \ +         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \ +         where.o utf.o legacy.o + +# All of the source code files. +# +SRC = \ +  $(TOP)/src/attach.c \ +  $(TOP)/src/auth.c \ +  $(TOP)/src/btree.c \ +  $(TOP)/src/btree.h \ +  $(TOP)/src/build.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/legacy.c \ +  $(TOP)/src/main.c \ +  $(TOP)/src/os_mac.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/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/vdbemem.c \ +  $(TOP)/src/vdbeInt.h \ +  $(TOP)/src/where.c + +# Source code to the test files. +# +TESTSRC = \ +  $(TOP)/src/btree.c \ +  $(TOP)/src/func.c \ +  $(TOP)/src/os_mac.c \ +  $(TOP)/src/os_unix.c \ +  $(TOP)/src/os_win.c \ +  $(TOP)/src/pager.c \ +  $(TOP)/src/pragma.c \ +  $(TOP)/src/printf.c \ +  $(TOP)/src/test1.c \ +  $(TOP)/src/test2.c \ +  $(TOP)/src/test3.c \ +  $(TOP)/src/test4.c \ +  $(TOP)/src/test5.c \ +  $(TOP)/src/utf.c \ +  $(TOP)/src/util.c \ +  $(TOP)/src/vdbe.c \ +  $(TOP)/src/md5.c + +# Header files used by all library source files. +# +HDR = \ +   sqlite3.h  \ +   $(TOP)/src/btree.h \ +   config.h \ +   $(TOP)/src/hash.h \ +   opcodes.h \ +   $(TOP)/src/os.h \ +   $(TOP)/src/os_common.h \ +   $(TOP)/src/os_mac.h \ +   $(TOP)/src/os_unix.h \ +   $(TOP)/src/os_win.h \ +   $(TOP)/src/sqliteInt.h  \ +   $(TOP)/src/vdbe.h \ +   parse.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 config.h libsqlite3.a sqlite3$(EXE) + +# 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 +4 | tail -1 \ +          | awk '{print $$5,$$6}' >last_change + +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) $(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) $(VDBEHDR) opcodes.c +	rm -rf tsrc +	mkdir tsrc +	cp $(SRC) $(VDBEHDR) tsrc +	rm tsrc/sqlite.h.in tsrc/parse.y +	cp parse.c opcodes.c tsrc +	cp $(TOP)/sqlite3.def tsrc + +# 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 files +# +attach.o:	$(TOP)/src/attach.c $(HDR) +	$(TCCX) -c $(TOP)/src/attach.c + +auth.o:	$(TOP)/src/auth.c $(HDR) +	$(TCCX) -c $(TOP)/src/auth.c + +btree.o:	$(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h +	$(TCCX) -c $(TOP)/src/btree.c + +build.o:	$(TOP)/src/build.c $(HDR) +	$(TCCX) -c $(TOP)/src/build.c + +# The config.h file will contain a single #define that tells us how +# many bytes are in a pointer.  This only works if a pointer is the +# same size on the host as it is on the target.  If you are cross-compiling +# to a target with a different pointer size, you'll need to manually +# configure the config.h file. +# +config.h:	 +	echo '#include <stdio.h>' >temp.c +	echo 'int main(){printf(' >>temp.c +	echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c +	echo 'exit(0);}' >>temp.c +	$(BCC) -o temp temp.c +	./temp >config.h +	echo >>config.h +	rm -f temp.c temp + +date.o:	$(TOP)/src/date.c $(HDR) +	$(TCCX) -c $(TOP)/src/date.c + +delete.o:	$(TOP)/src/delete.c $(HDR) +	$(TCCX) -c $(TOP)/src/delete.c + +expr.o:	$(TOP)/src/expr.c $(HDR) +	$(TCCX) -c $(TOP)/src/expr.c + +func.o:	$(TOP)/src/func.c $(HDR) +	$(TCCX) -c $(TOP)/src/func.c + +hash.o:	$(TOP)/src/hash.c $(HDR) +	$(TCCX) -c $(TOP)/src/hash.c + +insert.o:	$(TOP)/src/insert.c $(HDR) +	$(TCCX) -c $(TOP)/src/insert.c + +legacy.o:	$(TOP)/src/legacy.c $(HDR) +	$(TCCX) -c $(TOP)/src/legacy.c + +main.o:	$(TOP)/src/main.c $(HDR) +	$(TCCX) -c $(TOP)/src/main.c + +pager.o:	$(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h +	$(TCCX) -c $(TOP)/src/pager.c + +opcodes.o:	opcodes.c +	$(TCCX) -c opcodes.c + +opcodes.c:	opcodes.h $(TOP)/mkopcodec.awk +	sort -n +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c + +opcodes.h:	parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk +	cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h + +os_mac.o:	$(TOP)/src/os_mac.c $(HDR) +	$(TCCX) -c $(TOP)/src/os_mac.c + +os_unix.o:	$(TOP)/src/os_unix.c $(HDR) +	$(TCCX) -c $(TOP)/src/os_unix.c + +os_win.o:	$(TOP)/src/os_win.c $(HDR) +	$(TCCX) -c $(TOP)/src/os_win.c + +parse.o:	parse.c $(HDR) +	$(TCCX) -c parse.c + +parse.h:	parse.c + +parse.c:	$(TOP)/src/parse.y lemon +	cp $(TOP)/src/parse.y . +	./lemon parse.y + +pragma.o:	$(TOP)/src/pragma.c $(HDR) +	$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c + +printf.o:	$(TOP)/src/printf.c $(HDR) +	$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/printf.c + +random.o:	$(TOP)/src/random.c $(HDR) +	$(TCCX) -c $(TOP)/src/random.c + +select.o:	$(TOP)/src/select.c $(HDR) +	$(TCCX) -c $(TOP)/src/select.c + +sqlite3.h:	$(TOP)/src/sqlite.h.in  +	sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \ +            -e s/--ENCODING--/$(ENCODING)/ \ +                 $(TOP)/src/sqlite.h.in >sqlite3.h + +table.o:	$(TOP)/src/table.c $(HDR) +	$(TCCX) -c $(TOP)/src/table.c + +tclsqlite.o:	$(TOP)/src/tclsqlite.c $(HDR) +	$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c + +tokenize.o:	$(TOP)/src/tokenize.c $(HDR) +	$(TCCX) -c $(TOP)/src/tokenize.c + +trigger.o:	$(TOP)/src/trigger.c $(HDR) +	$(TCCX) -c $(TOP)/src/trigger.c + +update.o:	$(TOP)/src/update.c $(HDR) +	$(TCCX) -c $(TOP)/src/update.c + +utf.o:	$(TOP)/src/utf.c $(HDR) +	$(TCCX) -c $(TOP)/src/utf.c + +util.o:	$(TOP)/src/util.c $(HDR) +	$(TCCX) -c $(TOP)/src/util.c + +vacuum.o:	$(TOP)/src/vacuum.c $(HDR) +	$(TCCX) -c $(TOP)/src/vacuum.c + +vdbe.o:	$(TOP)/src/vdbe.c $(VDBEHDR) +	$(TCCX) -c $(TOP)/src/vdbe.c + +vdbeapi.o:	$(TOP)/src/vdbeapi.c $(VDBEHDR) +	$(TCCX) -c $(TOP)/src/vdbeapi.c + +vdbeaux.o:	$(TOP)/src/vdbeaux.c $(VDBEHDR) +	$(TCCX) -c $(TOP)/src/vdbeaux.c + +vdbemem.o:	$(TOP)/src/vdbemem.c $(VDBEHDR) +	$(TCCX) -c $(TOP)/src/vdbemem.c + +where.o:	$(TOP)/src/where.c $(HDR) +	$(TCCX) -c $(TOP)/src/where.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) + +testfixture$(EXE):	$(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) +	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture$(EXE) \ +		$(TESTSRC) $(TOP)/src/tclsqlite.c \ +		libsqlite3.a $(LIBTCL) $(THREADLIB) + +crashtest:	$(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) $(TOP)/src/os_test.c +	$(TCCX) $(TCL_FLAGS) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \ +		-o crashtest \ +		$(TESTSRC) $(TOP)/src/os_test.c $(TOP)/src/tclsqlite.c \ +		libsqlite3.a $(LIBTCL) $(THREADLIB) + +fulltest:	testfixture$(EXE) sqlite3$(EXE) crashtest +	./testfixture$(EXE) $(TOP)/test/all.test + +test:	testfixture$(EXE) sqlite3$(EXE) +	./testfixture$(EXE) $(TOP)/test/quick.test + +sqlite3_analyzer$(EXE):	$(TOP)/src/tclsqlite.c libsqlite3.a $(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) -DTCLSH=2 -DSQLITE_TEST=1 -static -o \ + 		sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ +		libsqlite3.a $(LIBTCL) $(THREADLIB) + +# Rules used to build documentation +# +arch.html:	$(TOP)/www/arch.tcl +	tclsh $(TOP)/www/arch.tcl >arch.html + +arch.png:	$(TOP)/www/arch.png +	cp $(TOP)/www/arch.png . + +c_interface.html:	$(TOP)/www/c_interface.tcl +	tclsh $(TOP)/www/c_interface.tcl >c_interface.html + +capi3.html:	$(TOP)/www/capi3.tcl +	tclsh $(TOP)/www/capi3.tcl >capi3.html + +capi3ref.html:	$(TOP)/www/capi3ref.tcl +	tclsh $(TOP)/www/capi3ref.tcl >capi3ref.html + +changes.html:	$(TOP)/www/changes.tcl +	tclsh $(TOP)/www/changes.tcl >changes.html + +copyright.html:	$(TOP)/www/copyright.tcl +	tclsh $(TOP)/www/copyright.tcl >copyright.html + +copyright-release.html:	$(TOP)/www/copyright-release.html +	cp $(TOP)/www/copyright-release.html . + +copyright-release.pdf:	$(TOP)/www/copyright-release.pdf +	cp $(TOP)/www/copyright-release.pdf . + +common.tcl:	$(TOP)/www/common.tcl +	cp $(TOP)/www/common.tcl . + +conflict.html:	$(TOP)/www/conflict.tcl +	tclsh $(TOP)/www/conflict.tcl >conflict.html + +datatypes.html:	$(TOP)/www/datatypes.tcl +	tclsh $(TOP)/www/datatypes.tcl >datatypes.html + +datatype3.html:	$(TOP)/www/datatype3.tcl +	tclsh $(TOP)/www/datatype3.tcl >datatype3.html + +docs.html:	$(TOP)/www/docs.tcl +	tclsh $(TOP)/www/docs.tcl >docs.html + +download.html:	$(TOP)/www/download.tcl +	mkdir -p doc +	tclsh $(TOP)/www/download.tcl >download.html + +faq.html:	$(TOP)/www/faq.tcl +	tclsh $(TOP)/www/faq.tcl >faq.html + +fileformat.html:	$(TOP)/www/fileformat.tcl +	tclsh $(TOP)/www/fileformat.tcl >fileformat.html + +formatchng.html:	$(TOP)/www/formatchng.tcl +	tclsh $(TOP)/www/formatchng.tcl >formatchng.html + +index.html:	$(TOP)/www/index.tcl last_change +	tclsh $(TOP)/www/index.tcl >index.html + +lang.html:	$(TOP)/www/lang.tcl +	tclsh $(TOP)/www/lang.tcl >lang.html + +lockingv3.html:	$(TOP)/www/lockingv3.tcl +	tclsh $(TOP)/www/lockingv3.tcl >lockingv3.html + +oldnews.html:	$(TOP)/www/oldnews.tcl +	tclsh $(TOP)/www/oldnews.tcl >oldnews.html + +omitted.html:	$(TOP)/www/omitted.tcl +	tclsh $(TOP)/www/omitted.tcl >omitted.html + +opcode.html:	$(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c +	tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html + +mingw.html:	$(TOP)/www/mingw.tcl +	tclsh $(TOP)/www/mingw.tcl >mingw.html + +nulls.html:	$(TOP)/www/nulls.tcl +	tclsh $(TOP)/www/nulls.tcl >nulls.html + +quickstart.html:	$(TOP)/www/quickstart.tcl +	tclsh $(TOP)/www/quickstart.tcl >quickstart.html + +speed.html:	$(TOP)/www/speed.tcl +	tclsh $(TOP)/www/speed.tcl >speed.html + +sqlite.gif:	$(TOP)/art/SQLite.gif +	cp $(TOP)/art/SQLite.gif sqlite.gif + +sqlite.html:	$(TOP)/www/sqlite.tcl +	tclsh $(TOP)/www/sqlite.tcl >sqlite.html + +support.html:	$(TOP)/www/support.tcl +	tclsh $(TOP)/www/support.tcl >support.html + +tclsqlite.html:	$(TOP)/www/tclsqlite.tcl +	tclsh $(TOP)/www/tclsqlite.tcl >tclsqlite.html + +vdbe.html:	$(TOP)/www/vdbe.tcl +	tclsh $(TOP)/www/vdbe.tcl >vdbe.html + +version3.html:	$(TOP)/www/version3.tcl +	tclsh $(TOP)/www/version3.tcl >version3.html + + +# Files to be published on the website. +# +DOC = \ +  arch.html \ +  arch.png \ +  c_interface.html \ +  capi3.html \ +  capi3ref.html \ +  changes.html \ +  copyright.html \ +  copyright-release.html \ +  copyright-release.pdf \ +  conflict.html \ +  datatypes.html \ +  datatype3.html \ +  docs.html \ +  download.html \ +  faq.html \ +  fileformat.html \ +  formatchng.html \ +  index.html \ +  lang.html \ +  lockingv3.html \ +  mingw.html \ +  nulls.html \ +  oldnews.html \ +  omitted.html \ +  opcode.html \ +  quickstart.html \ +  speed.html \ +  sqlite.gif \ +  sqlite.html \ +  support.html \ +  tclsqlite.html \ +  vdbe.html \ +  version3.html + +doc:	common.tcl $(DOC) +	mkdir -p doc +	mv $(DOC) doc + +# 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 +	rm -f $(PUBLISH) +	rm -f *.da *.bb *.bbg gmon.out +	rm -rf tsrc diff --git a/ext/pdo_sqlite/sqlite/mkdll.sh b/ext/pdo_sqlite/sqlite/mkdll.sh new file mode 100644 index 0000000000..bad8619f3e --- /dev/null +++ b/ext/pdo_sqlite/sqlite/mkdll.sh @@ -0,0 +1,42 @@ +#!/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 target_source +cd tsrc +PATH=$PATH:/opt/mingw/bin +TCLDIR=/home/drh/tcltk/846/win/846win +TCLSTUBLIB=$TCLDIR/libtcl84stub.a +OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1 -DTHREADSAFE=1' +CC="i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR" +rm shell.c +for i in *.c; do +  CMD="$CC -c $i" +  echo $CMD +  $CMD +done +echo 'EXPORTS' >tclsqlite3.def +echo 'Tclsqlite3_Init' >>tclsqlite3.def +echo 'Sqlite3_Init' >>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 *.o $TCLSTUBLIB +i386-mingw32msvc-strip tclsqlite3.dll +rm tclsqlite.o +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 *.o +i386-mingw32msvc-strip sqlite3.dll +cd .. diff --git a/ext/pdo_sqlite/sqlite/mkopcodec.awk b/ext/pdo_sqlite/sqlite/mkopcodec.awk new file mode 100644 index 0000000000..6119272bd7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/mkopcodec.awk @@ -0,0 +1,22 @@ +#!/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.h script for details. */" +  print "const char *const sqlite3OpcodeNames[] = { \"?\"," +} +/^#define OP_/ { +  sub("OP_","",$2) +  print "  \"" $2 "\"," +} +END { +  print "};" +} diff --git a/ext/pdo_sqlite/sqlite/mkopcodeh.awk b/ext/pdo_sqlite/sqlite/mkopcodeh.awk new file mode 100644 index 0000000000..ead07d5ff9 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/mkopcodeh.awk @@ -0,0 +1,48 @@ +#!/usr/bin/awk -f +# +# 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. +# + +# Remember the TK_ values from the parse.h file +/^#define TK_/ { +  tk[$2] = $3 +} + +# Scan for "case OP_aaaa:" lines in the vdbe.c file +/^case OP_/ { +  name = $2 +  gsub(/:/,"",name) +  gsub("\r","",name) +  op[name] = -1 +  for(i=3; i<NF-2; i++){ +    if($i=="same" && $(i+1)=="as"){ +      op[name] = tk[$(i+2)] +      used[op[name]] = 1 +    } +  } +} + +# Assign numbers to all opcodes and output the result. +END { +  cnt = 0 +  print "/* Automatically generated.  Do not edit */" +  print "/* See the mkopcodeh.awk script for details */" +  for(name in op){ +    if( op[name]<0 ){ +      cnt++ +      while( used[cnt] ) cnt++ +      op[name] = cnt +    } +    printf "#define %-30s %d\n", name, op[name] +  } +} diff --git a/ext/pdo_sqlite/sqlite/mkso.sh b/ext/pdo_sqlite/sqlite/mkso.sh new file mode 100644 index 0000000000..9da593bfb6 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/mkso.sh @@ -0,0 +1,27 @@ +#!/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. +# +make target_source +cd tsrc +rm shell.c +TCLDIR=/home/drh/tcltk/846/linux/846linux +TCLSTUBLIB=$TCLDIR/libtclstub8.4g.a +OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1' +for i in *.c; do +  CMD="cc -fPIC $OPTS -O2 -I. -I$TCLDIR -c $i" +  echo $CMD +  $CMD +done +echo gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so +gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so +strip tclsqlite3.so +rm tclsqlite.c tclsqlite.o +echo gcc -shared *.o -o sqlite3.so +gcc -shared *.o -o sqlite3.so +strip sqlite3.so +cd .. diff --git a/ext/pdo_sqlite/sqlite/publish.sh b/ext/pdo_sqlite/sqlite/publish.sh new file mode 100644 index 0000000000..7c45550bba --- /dev/null +++ b/ext/pdo_sqlite/sqlite/publish.sh @@ -0,0 +1,113 @@ +#!/bin/sh +# +# This script is used to compile SQLite and all its documentation and +# ship everything up to the SQLite website.  This script will only work +# on the system "zadok" at the Hwaci offices.  But others might find +# the script useful as an example. +# + +# 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` + +# Start by building an sqlite shell for linux. +# +make clean +make sqlite3 +strip sqlite3 +mv sqlite3 sqlite3-$VERS.bin +gzip sqlite3-$VERS.bin +mv sqlite3-$VERS.bin.gz doc + +# Build a source archive useful for windows. +# +make target_source +cd tsrc +zip ../doc/sqlite-source-$VERSW.zip * +cd .. + +# Build the sqlite.so and tclsqlite.so shared libraries +# under Linux +# +. $srcdir/mkso.sh +cd tsrc +mv tclsqlite3.so tclsqlite-$VERS.so +gzip tclsqlite-$VERS.so +mv tclsqlite-$VERS.so.gz ../doc +mv sqlite3.so sqlite-$VERS.so +gzip sqlite-$VERS.so +mv sqlite-$VERS.so.gz ../doc +cd .. + +# Build the tclsqlite3.dll and sqlite3.dll shared libraries. +# +. $srcdir/mkdll.sh +cd tsrc +echo zip ../doc/tclsqlite-$VERSW.zip tclsqlite3.dll +zip ../doc/tclsqlite-$VERSW.zip tclsqlite3.dll +echo zip ../doc/sqlitedll-$VERSW.zip sqlite3.dll sqlite3.def +zip ../doc/sqlitedll-$VERSW.zip sqlite3.dll sqlite3.def +cd .. + +# Build the sqlite.exe executable for windows. +# +make target_source +cd tsrc +rm tclsqlite.c +OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1' +i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR *.c -o sqlite3.exe +zip ../doc/sqlite-$VERSW.zip sqlite3.exe +cd .. + +# Construct a tarball of the source tree +# +ORIGIN=`pwd` +cd $srcdir +cd .. +EXCLUDE=`find sqlite -print | grep CVS | sed 's,^, --exclude ,'` +tar czf $ORIGIN/doc/sqlite-$VERS.tar.gz $EXCLUDE sqlite +cd $ORIGIN + +# +# Build RPMS (binary) and Source RPM +# + +# Make sure we are properly setup to build RPMs +# +echo "%HOME %{expand:%%(cd; pwd)}" > $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 diff --git a/ext/pdo_sqlite/sqlite/spec.template b/ext/pdo_sqlite/sqlite/spec.template new file mode 100644 index 0000000000..24c5eaebb8 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/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/ext/pdo_sqlite/sqlite/sqlite.1 b/ext/pdo_sqlite/sqlite/sqlite.1 new file mode 100644 index 0000000000..e35358ec61 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/sqlite.1 @@ -0,0 +1,203 @@ +.\"                                      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 SQLITE 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 <n>    insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +sqlite \- A command line interface for SQLite +.SH SYNOPSIS +.B sqlite +.RI [ options ] " filename " [ SQL ] +.SS SUMMARY +.PP +sqlite is a terminal-based front-end to the SQLite library. It enables +you to type in queries interactively, issue them to SQLite and see the +results. Alternatively, you can specify SQL code on the command-line. In +addition it provides a number of meta-commands. + +.SH DESCRIPTION +This manual page documents briefly the +.B sqlite +command. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +.SS GETTING STARTED +.PP +To start the sqlite program, just type "sqlite" followed by the name +the file that holds the SQLite database. If the file does not exist, a +new one is created automatically. The sqlite program will then prompt +you to enter SQL. Type in SQL statements (terminated by a semicolon), +press "Enter" and the SQL will be executed. + +For example, to create a new SQLite database named "ex1" with a single +table named "tbl1", you might do this: +.sp +.nf +$ sqlite ex1 +SQLite version 2.0.0 +Enter ".help" for instructions +sqlite> create table tbl1(one varchar(10), two smallint); +sqlite> insert into tbl1 values('hello!',10); +sqlite> insert into tbl1 values('goodbye', 20); +sqlite> select * from tbl1; +hello!|10 +goodbye|20 +sqlite> +.sp +.fi + +.SS SQLITE META-COMMANDS +.PP +Most of the time, sqlite just reads lines of input and passes them on +to the SQLite library for execution. But if an input line begins with +a dot ("."), then that line is intercepted and interpreted by the +sqlite program itself. These "dot commands" are typically used to +change the output format of queries, or to execute certain prepackaged +query statements. + +For a listing of the available dot commands, you can enter ".help" at +any time. For example: +.sp +.nf +.cc | +sqlite> .help +.dump ?TABLE? ...      Dump the database in an 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. +                       "off" will revert to the output mode that was +                       previously in effect +.header(s) ON|OFF      Turn display of headers on or off +.help                  Show this message +.indices TABLE         Show names of all indices on TABLE +.mode MODE             Set mode to one of "line(s)", "column(s)", +                       "insert", "list", or "html" +.mode insert TABLE     Generate SQL insert statements for TABLE +.nullvalue STRING      Print STRING instead of nothing for NULL data +.output FILENAME       Send output to FILENAME +.output stdout         Send output to the screen +.prompt MAIN CONTINUE  Replace the standard prompts +                       "sqlite > " and "   ...> " +                       with the strings MAIN and CONTINUE +                       CONTINUE is optional. +.quit                  Exit this program +.read FILENAME         Execute SQL in FILENAME +.reindex ?TABLE?       Rebuild indices +.schema ?TABLE?        Show the CREATE statements +.separator STRING      Change separator string for "list" mode +.show                  Show the current values for the following: +                       .echo +                       .explain +                       .mode +                       .nullvalue +                       .output +                       .separator +                       .width +.tables ?PATTERN?      List names of tables matching a 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 +The program has the following options: +.TP +.BI \-init\ file +Read in and process 'file', which contains "dot commands". +You can use this file to initialize display settings. +.TP +.B \-html +Set output mode to HTML. +.TP +.B \-list +Set output mode to 'list'. +.TP +.B \-line +Set output mode to 'line'. +.TP +.B \-column +Set output mode to 'column'. +.TP +.BI \-separator\  separator +Specify which output field separator for 'list' mode to use. +Default is '|'. +.TP +.BI \-nullvalue\  string +When a null is encountered, print 'string'. Default is no string. +.TP +.B \-[no]header +Turn headers on or off. Default is off. +.TP +.B \-echo +Print commands before execution. + + +.SH OUTPUT MODE +The SQLite program has different output modes, which define the way +the output (from queries) is formatted. + +In 'list' mode, which is the default, one record per line is output, +each field separated by the separator specified with the +\fB-separator\fP option or \fB.separator\fP command. + +In 'line' mode, each column is output on its own line, records are +separated by blank lines. + +In HTML mode, an XHTML table is generated. + +In 'column' mode, one record per line is output, aligned neatly in colums. + +.SH INIT FILE +sqlite can be initialized using resource files. These can be combined with +command line arguments to set up sqlite exactly the way you want it. +Initialization proceeds as follows: + +o The defaults of + +.sp +.nf +.cc | +mode            = LIST +separator       = "|" +main prompt     = "sqlite> " +continue prompt = "   ...> " +|cc . +.sp +.fi + +are established. + +o If a file .sqliterc can be found in the user's home directory, it is +read and processed. It should only contain "dot commands".  If the +file is not found or cannot be read, processing continues without +notification. + +o If a file is specified on the command line with the -init option, it +is processed in the same manner as .sqliterc + +o All other command line options are processed + +o The database is opened and you are now ready to begin. + +.SH SEE ALSO +http://www.hwaci.com/sw/sqlite/ +.br +The sqlite-doc package +.SH AUTHOR +This manual page was originally written by Andreas Rottmann +<rotty@debian.org>, for the Debian GNU/Linux system (but may be used +by others). diff --git a/ext/pdo_sqlite/sqlite/sqlite.pc.in b/ext/pdo_sqlite/sqlite/sqlite.pc.in new file mode 100644 index 0000000000..16ed41c3d9 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/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/ext/pdo_sqlite/sqlite/sqlite3.def b/ext/pdo_sqlite/sqlite/sqlite3.def new file mode 100644 index 0000000000..0a4b793113 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/sqlite3.def @@ -0,0 +1,91 @@ +EXPORTS +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_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_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_commit_hook +sqlite3_complete +sqlite3_complete16 +sqlite3_create_collation +sqlite3_create_collation16 +sqlite3_create_function +sqlite3_create_function16 +sqlite3_data_count +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_exec +sqlite3_finalize +sqlite3_free +sqlite3_free_table +sqlite3_get_auxdata +sqlite3_get_table +sqlite3_interrupt +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_mprintf +sqlite3_open +sqlite3_open16 +sqlite3_prepare +sqlite3_prepare16 +sqlite3_progress_handler +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_set_authorizer +sqlite3_set_auxdata +sqlite3_snprintf +sqlite3_step +sqlite3_total_changes +sqlite3_trace +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_vmprintf diff --git a/ext/pdo_sqlite/sqlite/sqlite3.pc.in b/ext/pdo_sqlite/sqlite/sqlite3.pc.in new file mode 100644 index 0000000000..13d80a0b20 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/sqlite3.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} -lsqlite3 +Cflags: -I${includedir} diff --git a/ext/pdo_sqlite/sqlite/src/attach.c b/ext/pdo_sqlite/sqlite/src/attach.c new file mode 100644 index 0000000000..2f0899865c --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/attach.c @@ -0,0 +1,329 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" + +/* +** This routine is called by the parser to process an ATTACH statement: +** +**     ATTACH DATABASE filename AS dbname +** +** The pFilename and pDbname arguments are the tokens that define the +** filename and dbname in the ATTACH statement. +*/ +void sqlite3Attach( +  Parse *pParse,       /* The parser context */ +  Token *pFilename,    /* Name of database file */ +  Token *pDbname,      /* Name of the database to use internally */ +  int keyType,         /* 0: no key.  1: TEXT,  2: BLOB */ +  Token *pKey          /* Text of the key for keytype 1 and 2 */ +){ +  Db *aNew; +  int rc, i; +  char *zFile, *zName; +  sqlite3 *db; +  Vdbe *v; + +  v = sqlite3GetVdbe(pParse); +  if( !v ) return; +  sqlite3VdbeAddOp(v, OP_Halt, 0, 0); +  if( pParse->explain ) return; +  db = pParse->db; +  if( db->nDb>=MAX_ATTACHED+2 ){ +    sqlite3ErrorMsg(pParse, "too many attached databases - max %d",  +       MAX_ATTACHED); +    pParse->rc = SQLITE_ERROR; +    return; +  } + +  if( !db->autoCommit ){ +    sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction"); +    pParse->rc = SQLITE_ERROR; +    return; +  } + +  zFile = sqlite3NameFromToken(pFilename);; +  if( zFile==0 ) return; +#ifndef SQLITE_OMIT_AUTHORIZATION +  if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ +    sqliteFree(zFile); +    return; +  } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + +  zName = sqlite3NameFromToken(pDbname); +  if( zName==0 ) return; +  for(i=0; i<db->nDb; i++){ +    char *z = db->aDb[i].zName; +    if( z && sqlite3StrICmp(z, zName)==0 ){ +      sqlite3ErrorMsg(pParse, "database %z is already in use", zName); +      pParse->rc = SQLITE_ERROR; +      sqliteFree(zFile); +      return; +    } +  } + +  if( db->aDb==db->aDbStatic ){ +    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); +    if( aNew==0 ) return; +    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); +  }else{ +    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); +    if( aNew==0 ) return; +  } +  db->aDb = aNew; +  aNew = &db->aDb[db->nDb++]; +  memset(aNew, 0, sizeof(*aNew)); +  sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); +  sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); +  sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); +  sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); +  aNew->zName = zName; +  aNew->safety_level = 3; +  rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); +  if( rc ){ +    sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); +  } +#if SQLITE_HAS_CODEC +  { +    extern int sqlite3CodecAttach(sqlite3*, int, void*, int); +    char *zKey; +    int nKey; +    if( keyType==0 ){ +      /* No key specified.  Use the key from the main database */ +      extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); +      sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); +    }else if( keyType==1 ){ +      /* Key specified as text */ +      zKey = sqlite3NameFromToken(pKey); +      nKey = strlen(zKey); +    }else{ +      /* Key specified as a BLOB */ +      char *zTemp; +      assert( keyType==2 ); +      pKey->z++; +      pKey->n--; +      zTemp = sqlite3NameFromToken(pKey); +      zKey = sqlite3HexToBlob(zTemp); +      sqliteFree(zTemp); +    } +    sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); +    if( keyType ){ +      sqliteFree(zKey); +    } +  } +#endif +  sqliteFree(zFile); +  db->flags &= ~SQLITE_Initialized; +  if( pParse->nErr==0 && rc==SQLITE_OK ){ +    rc = sqlite3ReadSchema(pParse); +  } +  if( rc ){ +    int i = db->nDb - 1; +    assert( i>=2 ); +    if( db->aDb[i].pBt ){ +      sqlite3BtreeClose(db->aDb[i].pBt); +      db->aDb[i].pBt = 0; +    } +    sqlite3ResetInternalSchema(db, 0); +    if( 0==pParse->nErr ){ +      pParse->nErr++; +      pParse->rc = SQLITE_ERROR; +    } +  } +} + +/* +** This routine is called by the parser to process a DETACH statement: +** +**    DETACH DATABASE dbname +** +** The pDbname argument is the name of the database in the DETACH statement. +*/ +void sqlite3Detach(Parse *pParse, Token *pDbname){ +  int i; +  sqlite3 *db; +  Vdbe *v; +  Db *pDb = 0; + +  v = sqlite3GetVdbe(pParse); +  if( !v ) return; +  sqlite3VdbeAddOp(v, OP_Halt, 0, 0); +  if( pParse->explain ) return; +  db = pParse->db; +  for(i=0; i<db->nDb; i++){ +    pDb = &db->aDb[i]; +    if( pDb->pBt==0 || pDb->zName==0 ) continue; +    if( strlen(pDb->zName)!=pDbname->n ) continue; +    if( sqlite3StrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break; +  } +  if( i>=db->nDb ){ +    sqlite3ErrorMsg(pParse, "no such database: %T", pDbname); +    return; +  } +  if( i<2 ){ +    sqlite3ErrorMsg(pParse, "cannot detach database %T", pDbname); +    return; +  } +  if( !db->autoCommit ){ +    sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction"); +    pParse->rc = SQLITE_ERROR; +    return; +  } +#ifndef SQLITE_OMIT_AUTHORIZATION +  if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ +    return; +  } +#endif /* SQLITE_OMIT_AUTHORIZATION */ +  sqlite3BtreeClose(pDb->pBt); +  pDb->pBt = 0; +  sqlite3ResetInternalSchema(db, 0); +} + +/* +** 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; i<pList->nSrc; i++, pItem++){ +    if( pItem->zDatabase==0 ){ +      pItem->zDatabase = sqliteStrDup(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( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; +    if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; +  } +  return 0; +} +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; i<pList->nExpr; i++, pItem++){ +    if( sqlite3FixExpr(pFix, pItem->pExpr) ){ +      return 1; +    } +  } +  return 0; +} +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; +} diff --git a/ext/pdo_sqlite/sqlite/src/auth.c b/ext/pdo_sqlite/sqlite/src/auth.c new file mode 100644 index 0000000000..b251eacfdf --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/auth.c @@ -0,0 +1,223 @@ +/* +** 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$ +*/ +#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 +){ +  db->xAuth = xAuth; +  db->pAuthArg = pArg; +  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 */ +  SrcList *pTabList     /* All table that pExpr might refer to */ +){ +  sqlite3 *db = pParse->db; +  int rc; +  Table *pTab;          /* 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 */ + +  if( db->xAuth==0 ) return; +  assert( pExpr->op==TK_COLUMN ); +  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){ +    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; +  } +  if( iSrc>=0 && iSrc<pTabList->nSrc ){ +    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; +  }else{ +    return; +  } +  if( pTab==0 ) return; +  if( pExpr->iColumn>=0 ){ +    assert( pExpr->iColumn<pTab->nCol ); +    zCol = pTab->aCol[pExpr->iColumn].zName; +  }else if( pTab->iPKey>=0 ){ +    assert( pTab->iPKey<pTab->nCol ); +    zCol = pTab->aCol[pTab->iPKey].zName; +  }else{ +    zCol = "ROWID"; +  } +  assert( pExpr->iDb<db->nDb ); +  zDBase = db->aDb[pExpr->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 || pExpr->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. */ +  if( db->init.busy ){ +    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/ext/pdo_sqlite/sqlite/src/btree.c b/ext/pdo_sqlite/sqlite/src/btree.c new file mode 100644 index 0000000000..fe8754e01d --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/btree.c @@ -0,0 +1,4462 @@ +/* +** 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$ +** +** 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) | Ptr(N+1) | +**   ---------------------------------------------------------------- +** +** 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+1) and its subpages have values greater than Key(N).  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+1) 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 more +** than once within the same second.  This counter, together with the +** modification time of the file, 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 area 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+1) 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 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 <assert.h> + + +/* 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; + +/* +** This is a magic string that appears at the beginning of every +** SQLite database in order to identify the file as a real database. +**                                  123456789 123456 */ +static const char zMagicHeader[] = "SQLite format 3"; + +/* +** Page type flags.  An ORed combination of these flags appear as the +** first byte 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. +*/ +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 Btree.maxLocal or Btree.maxLeaf */ +  u16 minLocal;        /* Copy of Btree.minLocal or Btree.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]; +  struct Btree *pBt;   /* Pointer back to BTree structure */ +  u8 *aData;           /* Pointer back to the start of the page */ +  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) + +/* +** Everything we need to know about an open database +*/ +struct Btree { +  Pager *pPager;        /* The page cache */ +  BtCursor *pCursor;    /* A list of all open cursors */ +  MemPage *pPage1;      /* First page of the database */ +  u8 inTrans;           /* True if a transaction is in progress */ +  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 */ +  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 */ +}; +typedef Btree Bt; + +/* +** Btree.inTrans may take one of the following values. +*/ +#define TRANS_NONE  0 +#define TRANS_READ  1 +#define TRANS_WRITE 2 + +/* +** 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 */ +  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 in the BTree. +** The entry is identified by its MemPage and the index in +** MemPage.aCell[] of the entry. +*/ +struct BtCursor { +  Btree *pBt;               /* The Btree to which this cursor belongs */ +  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 isValid;               /* TRUE if points to a valid entry */ +  u8 status;                /* Set to SQLITE_ABORT if cursors is invalidated */ +}; + +/* +** Forward declaration +*/ +static int checkReadLocks(Btree*,Pgno,BtCursor*); + + +/* +** Read or write a two- and four-byte big-endian integer values. +*/ +static u32 get2byte(unsigned char *p){ +  return (p[0]<<8) | p[1]; +} +static u32 get4byte(unsigned char *p){ +  return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} +static void put2byte(unsigned char *p, u32 v){ +  p[0] = v>>8; +  p[1] = v; +} +static void put4byte(unsigned char *p, u32 v){ +  p[0] = v>>24; +  p[1] = v>>16; +  p[2] = v>>8; +  p[3] = v; +} + +/* +** 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  sqlite3GetVarint32 +#define putVarint    sqlite3PutVarint + +/* +** 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. +*/ +static u8 *findCell(MemPage *pPage, int iCell){ +  u8 *data = pPage->aData; +  assert( iCell>=0 ); +  assert( iCell<get2byte(&data[pPage->hdrOffset+3]) ); +  return data + get2byte(&data[pPage->cellOffset+2*iCell]); +} + +/* +** This a more complex version of findCell() that works for +** pages that do contain overflow cells.  See insert +*/ +static u8 *findOverflowCell(MemPage *pPage, int iCell){ +  int i; +  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.  parseCell() takes a cell index +** as the second argument and parseCellPtr() takes a pointer to the +** body of the cell as its second argument. +*/ +static void parseCellPtr( +  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 */ + +  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; +  } +  n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); +  pInfo->nHeader = n; +  pInfo->nData = nPayload; +  if( !pPage->intKey ){ +    nPayload += pInfo->nKey; +  } +  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; +  } +} +static void parseCell( +  MemPage *pPage,         /* Page containing the cell */ +  int iCell,              /* The cell index.  First cell is 0 */ +  CellInfo *pInfo         /* Fill in this structure */ +){ +  parseCellPtr(pPage, findCell(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; +  parseCell(pPage, iCell, &info); +  return info.nSize; +} +#endif +static int cellSizePtr(MemPage *pPage, u8 *pCell){ +  CellInfo info; +  parseCellPtr(pPage, pCell, &info); +  return info.nSize; +} + +/* +** Do sanity checking on a page.  Throw an exception if anything is +** not right. +** +** This routine is used for internal error checking only.  It is omitted +** from most builds. +*/ +#if defined(BTREE_DEBUG) && !defined(NDEBUG) && 0 +static void _pageIntegrity(MemPage *pPage){ +  int usableSize; +  u8 *data; +  int i, j, idx, c, pc, hdr, nFree; +  int cellOffset; +  int nCell, cellLimit; +  u8 *used; + +  used = sqliteMallocRaw( pPage->pBt->pageSize ); +  if( used==0 ) return; +  usableSize = pPage->pBt->usableSize; +  assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] ); +  hdr = pPage->hdrOffset; +  assert( hdr==(pPage->pgno==1 ? 100 : 0) ); +  assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); +  c = pPage->aData[hdr]; +  if( pPage->isInit ){ +    assert( pPage->leaf == ((c & PTF_LEAF)!=0) ); +    assert( pPage->zeroData == ((c & PTF_ZERODATA)!=0) ); +    assert( pPage->leafData == ((c & PTF_LEAFDATA)!=0) ); +    assert( pPage->intKey == ((c & (PTF_INTKEY|PTF_LEAFDATA))!=0) ); +    assert( pPage->hasData == +             !(pPage->zeroData || (!pPage->leaf && pPage->leafData)) ); +    assert( pPage->cellOffset==pPage->hdrOffset+12-4*pPage->leaf ); +    assert( pPage->nCell = get2byte(&pPage->aData[hdr+3]) ); +  } +  data = pPage->aData; +  memset(used, 0, usableSize); +  for(i=0; i<hdr+10-pPage->leaf*4; i++) used[i] = 1; +  nFree = 0; +  pc = get2byte(&data[hdr+1]); +  while( pc ){ +    int size; +    assert( pc>0 && pc<usableSize-4 ); +    size = get2byte(&data[pc+2]); +    assert( pc+size<=usableSize ); +    nFree += size; +    for(i=pc; i<pc+size; i++){ +      assert( used[i]==0 ); +      used[i] = 1; +    } +    pc = get2byte(&data[pc]); +  } +  idx = 0; +  nCell = get2byte(&data[hdr+3]); +  cellLimit = get2byte(&data[hdr+5]); +  assert( pPage->isInit==0  +         || pPage->nFree==nFree+data[hdr+7]+cellLimit-(cellOffset+2*nCell) ); +  cellOffset = pPage->cellOffset; +  for(i=0; i<nCell; i++){ +    int size; +    pc = get2byte(&data[cellOffset+2*i]); +    assert( pc>0 && pc<usableSize-4 ); +    size = cellSize(pPage, &data[pc]); +    assert( pc+size<=usableSize ); +    for(j=pc; j<pc+size; j++){ +      assert( used[j]==0 ); +      used[j] = 1; +    } +  } +  for(i=cellOffset+2*nCell; i<cellimit; i++){ +    assert( used[i]==0 ); +    used[i] = 1; +  } +  nFree = 0; +  for(i=0; i<usableSize; i++){ +    assert( used[i]<=1 ); +    if( used[i]==0 ) nFree++; +  } +  assert( nFree==data[hdr+7] ); +  sqliteFree(used); +} +#define pageIntegrity(X) _pageIntegrity(X) +#else +# define pageIntegrity(X) +#endif + +/* +** Defragment the page given.  All Cells are moved to the +** beginning of the page and all free space is collected  +** into one big FreeBlk at the end of the page. +*/ +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( sqlite3pager_iswriteable(pPage->aData) ); +  assert( pPage->pBt!=0 ); +  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); +  assert( pPage->nOverflow==0 ); +  temp = sqliteMalloc( pPage->pBt->pageSize ); +  if( temp==0 ) return SQLITE_NOMEM; +  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; i<nCell; i++){ +    u8 *pAddr;     /* The i-th cell pointer */ +    pAddr = &data[cellOffset + i*2]; +    pc = get2byte(pAddr); +    assert( pc<pPage->pBt->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); +  sqliteFree(temp); +  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( sqlite3pager_iswriteable(data) ); +  assert( pPage->pBt ); +  if( nByte<4 ) nByte = 4; +  if( pPage->nFree<nByte || pPage->nOverflow>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( size<nByte+4 ){ +          memcpy(&data[addr], &data[pc], 2); +          data[hdr+7] = nFrag + size - nByte; +          return pc; +        }else{ +          put2byte(&data[pc+2], size-nByte); +          return pc + size - nByte; +        } +      } +      addr = pc; +    } +  } + +  /* Allocate memory from the gap in between the cell pointer array +  ** and the cell content area. +  */ +  top = get2byte(&data[hdr+5]); +  nCell = get2byte(&data[hdr+3]); +  cellOffset = pPage->cellOffset; +  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( sqlite3pager_iswriteable(data) ); +  assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); +  assert( (start + size)<=pPage->pBt->usableSize ); +  if( size<4 ) size = 4; + +  /* Add the space back into the linked list of freeblocks */ +  hdr = pPage->hdrOffset; +  addr = hdr + 1; +  while( (pbegin = get2byte(&data[addr]))<start && pbegin>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){ +  Btree *pBt;     /* A copy of pPage->pBt */ + +  assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); +  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. +*/ +static int initPage( +  MemPage *pPage,        /* The page to be initialized */ +  MemPage *pParent       /* The parent.  Might be NULL */ +){ +  int pc;            /* Address of a freeblock within pPage->aData[] */ +  int i;             /* Loop counter */ +  int hdr;           /* Offset to beginning of page header */ +  u8 *data;          /* Equal to pPage->aData */ +  Btree *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( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); +  assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); +  if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ +    /* The parent page should never change unless the file is corrupt */ +    return SQLITE_CORRUPT; /* bkpt-CORRUPT */ +  } +  if( pPage->isInit ) return SQLITE_OK; +  if( pPage->pParent==0 && pParent!=0 ){ +    pPage->pParent = pParent; +    sqlite3pager_ref(pParent->aData); +  } +  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-CORRUPT */ +  } +  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-CORRUPT */ +  } + +  /* Compute the total free space on the page */ +  pc = get2byte(&data[hdr+1]); +  nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); +  i = 0; +  while( pc>0 ){ +    int next, size; +    if( pc>usableSize-4 ){ +      /* Free block is off the page */ +      return SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +    } +    if( i++>SQLITE_MAX_PAGE_SIZE/4 ){ +      /* The free block list forms an infinite loop */ +      return SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +    } +    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-CORRUPT */ +    } +    nFree += size; +    pc = next; +  } +  pPage->nFree = nFree; +  if( nFree>=usableSize ){ +    /* Free space cannot exceed total page size */ +    return SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +  } + +  pPage->isInit = 1; +  pageIntegrity(pPage); +  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; +  Btree *pBt = pPage->pBt; +  int hdr = pPage->hdrOffset; +  int first; + +  assert( sqlite3pager_pagenumber(data)==pPage->pgno ); +  assert( &data[pBt->pageSize] == (unsigned char*)pPage ); +  assert( sqlite3pager_iswriteable(data) ); +  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; +  pageIntegrity(pPage); +} + +/* +** Get a page from the pager.  Initialize the MemPage.pBt and +** MemPage.aData elements if needed. +*/ +static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ +  int rc; +  unsigned char *aData; +  MemPage *pPage; +  rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData); +  if( rc ) return rc; +  pPage = (MemPage*)&aData[pBt->pageSize]; +  pPage->aData = aData; +  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 +** getPage() and initPage(). +*/ +static int getAndInitPage( +  Btree *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; +  if( pgno==0 ){ +    return SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +  } +  rc = getPage(pBt, pgno, ppPage); +  if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ +    rc = initPage(*ppPage, pParent); +  } +  return rc; +} + +/* +** Release a MemPage.  This should be called once for each prior +** call to getPage. +*/ +static void releasePage(MemPage *pPage){ +  if( pPage ){ +    assert( pPage->aData ); +    assert( pPage->pBt ); +    assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); +    sqlite3pager_unref(pPage->aData); +  } +} + +/* +** 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(void *pData, int pageSize){ +  MemPage *pPage = (MemPage*)&((char*)pData)[pageSize]; +  if( pPage->pParent ){ +    MemPage *pParent = pPage->pParent; +    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(void *pData, int pageSize){ +  MemPage *pPage = (MemPage*)&((char*)pData)[pageSize]; +  if( pPage->isInit ){ +    pPage->isInit = 0; +    initPage(pPage, pPage->pParent); +  } +} + +/* +** 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. +*/ +int sqlite3BtreeOpen( +  const char *zFilename,  /* Name of the file containing the BTree database */ +  Btree **ppBtree,        /* Pointer to new Btree object written here */ +  int flags               /* Options */ +){ +  Btree *pBt; +  int rc; +  int nReserve; +  unsigned char zDbHeader[100]; + +  /* +  ** 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 ); +  assert( sizeof(u64)==8 ); +  assert( sizeof(u32)==4 ); +  assert( sizeof(u16)==2 ); +  assert( sizeof(Pgno)==4 ); +  assert( sizeof(ptr)==sizeof(char*) ); +  assert( sizeof(uptr)==sizeof(ptr) ); + +  pBt = sqliteMalloc( sizeof(*pBt) ); +  if( pBt==0 ){ +    *ppBtree = 0; +    return SQLITE_NOMEM; +  } +  rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, +                        (flags & BTREE_OMIT_JOURNAL)==0); +  if( rc!=SQLITE_OK ){ +    if( pBt->pPager ) sqlite3pager_close(pBt->pPager); +    sqliteFree(pBt); +    *ppBtree = 0; +    return rc; +  } +  sqlite3pager_set_destructor(pBt->pPager, pageDestructor); +  sqlite3pager_set_reiniter(pBt->pPager, pageReinit); +  pBt->pCursor = 0; +  pBt->pPage1 = 0; +  pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager); +  sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader); +  pBt->pageSize = get2byte(&zDbHeader[16]); +  if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE ){ +    pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE; +    pBt->maxEmbedFrac = 64;   /* 25% */ +    pBt->minEmbedFrac = 32;   /* 12.5% */ +    pBt->minLeafFrac = 32;    /* 12.5% */ +    nReserve = 0; +  }else{ +    nReserve = zDbHeader[20]; +    pBt->maxEmbedFrac = zDbHeader[21]; +    pBt->minEmbedFrac = zDbHeader[22]; +    pBt->minLeafFrac = zDbHeader[23]; +    pBt->pageSizeFixed = 1; +  } +  pBt->usableSize = pBt->pageSize - nReserve; +  sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); +  *ppBtree = pBt; +  return SQLITE_OK; +} + +/* +** Close an open database and invalidate all cursors. +*/ +int sqlite3BtreeClose(Btree *pBt){ +  while( pBt->pCursor ){ +    sqlite3BtreeCloseCursor(pBt->pCursor); +  } +  sqlite3pager_close(pBt->pPager); +  sqliteFree(pBt); +  return SQLITE_OK; +} + +/* +** Change the busy handler callback function. +*/ +int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ +  sqlite3pager_set_busyhandler(pBt->pPager, pHandler); +  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 *pBt, int mxPage){ +  sqlite3pager_set_cachesize(pBt->pPager, mxPage); +  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. +*/ +int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ +  sqlite3pager_set_safety_level(pBt->pPager, level); +  return SQLITE_OK; +} + +/* +** Change the default pages size and the number of reserved bytes per page. +*/ +int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ +  if( pBt->pageSizeFixed ){ +    return SQLITE_READONLY; +  } +  if( nReserve<0 ){ +    nReserve = pBt->pageSize - pBt->usableSize; +  } +  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ){ +    pBt->pageSize = pageSize; +    sqlite3pager_set_pagesize(pBt->pPager, pageSize); +  } +  pBt->usableSize = pBt->pageSize - nReserve; +  return SQLITE_OK; +} + +/* +** Return the currently defined page size +*/ +int sqlite3BtreeGetPageSize(Btree *pBt){ +  return pBt->pageSize; +} +int sqlite3BtreeGetReserve(Btree *pBt){ +  return pBt->pageSize - pBt->usableSize; +} + +/* +** 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.  SQLITE_PROTOCOL is returned +** if there is a locking protocol violation. +*/ +static int lockBtree(Btree *pBt){ +  int rc; +  MemPage *pPage1; +  if( pBt->pPage1 ) return SQLITE_OK; +  rc = getPage(pBt, 1, &pPage1); +  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( sqlite3pager_pagecount(pBt->pPager)>0 ){ +    u8 *page1 = pPage1->aData; +    if( memcmp(page1, zMagicHeader, 16)!=0 ){ +      goto page1_init_failed; +    } +    if( page1[18]>1 || page1[19]>1 ){ +      goto page1_init_failed; +    } +    pBt->pageSize = get2byte(&page1[16]); +    pBt->usableSize = pBt->pageSize - page1[20]; +    if( pBt->usableSize<500 ){ +      goto page1_init_failed; +    } +    pBt->maxEmbedFrac = page1[21]; +    pBt->minEmbedFrac = page1[22]; +    pBt->minLeafFrac = page1[23]; +  } + +  /* 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; +} + +/* +** 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(Btree *pBt){ +  if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ +    if( pBt->pPage1->aData==0 ){ +      MemPage *pPage = pBt->pPage1; +      pPage->aData = &((char*)pPage)[-pBt->pageSize]; +      pPage->pBt = pBt; +      pPage->pgno = 1; +    } +    releasePage(pBt->pPage1); +    pBt->pPage1 = 0; +    pBt->inStmt = 0; +  } +} + +/* +** Create a new database by initializing the first page of the +** file. +*/ +static int newDatabase(Btree *pBt){ +  MemPage *pP1; +  unsigned char *data; +  int rc; +  if( sqlite3pager_pagecount(pBt->pPager)>0 ) return SQLITE_OK; +  pP1 = pBt->pPage1; +  assert( pP1!=0 ); +  data = pP1->aData; +  rc = sqlite3pager_write(data); +  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; +  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 +** upgrade 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 wrflag is true, then nMaster specifies the maximum length of +** a master journal file name supplied later via sqlite3BtreeSync(). +** This is so that appropriate space can be allocated in the journal file +** when it is created.. +*/ +int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ +  int rc = SQLITE_OK; + +  /* 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( pBt->inTrans==TRANS_WRITE ||  +      (pBt->inTrans==TRANS_READ && !wrflag) ){ +    return SQLITE_OK; +  } +  if( pBt->readOnly && wrflag ){ +    return SQLITE_READONLY; +  } + +  if( pBt->pPage1==0 ){ +    rc = lockBtree(pBt); +  } + +  if( rc==SQLITE_OK && wrflag ){ +    rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1); +    if( rc==SQLITE_OK ){ +      rc = newDatabase(pBt); +    } +  } + +  if( rc==SQLITE_OK ){ +    pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); +    if( wrflag ) pBt->inStmt = 0; +  }else{ +    unlockBtreeIfUnused(pBt); +  } +  return rc; +} + +/* +** Commit the transaction currently in progress. +** +** This will release the write lock on the database file.  If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeCommit(Btree *pBt){ +  int rc = SQLITE_OK; +  if( pBt->inTrans==TRANS_WRITE ){ +    rc = sqlite3pager_commit(pBt->pPager); +  } +  pBt->inTrans = TRANS_NONE; +  pBt->inStmt = 0; +  unlockBtreeIfUnused(pBt); +  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. +*/ +static int countWriteCursors(Btree *pBt){ +  BtCursor *pCur; +  int r = 0; +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ +    if( pCur->wrFlag ) r++; +  } +  return r; +} +#endif + +#if 0 +/* +** Invalidate all cursors +*/ +static void invalidateCursors(Btree *pBt){ +  BtCursor *pCur; +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ +    MemPage *pPage = pCur->pPage; +    if( pPage /* && !pPage->isInit */ ){ +      pageIntegrity(pPage); +      releasePage(pPage); +      pCur->pPage = 0; +      pCur->isValid = 0; +      pCur->status = SQLITE_ABORT; +    } +  } +} +#endif + +#ifdef SQLITE_TEST +/* +** Print debugging information about all cursors to standard output. +*/ +void sqlite3BtreeCursorList(Btree *pBt){ +  BtCursor *pCur; +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ +    MemPage *pPage = pCur->pPage; +    char *zMode = pCur->wrFlag ? "rw" : "ro"; +    sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", +       pCur, pCur->pgnoRoot, zMode, +       pPage ? pPage->pgno : 0, pCur->idx, +       pCur->isValid ? "" : " eof" +    ); +  } +} +#endif + +/* +** 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 *pBt){ +  int rc = SQLITE_OK; +  MemPage *pPage1; +  if( pBt->inTrans==TRANS_WRITE ){ +    rc = sqlite3pager_rollback(pBt->pPager); +    /* The rollback may have destroyed the pPage1->aData value.  So +    ** call getPage() on page 1 again to make sure pPage1->aData is +    ** set correctly. */ +    if( getPage(pBt, 1, &pPage1)==SQLITE_OK ){ +      releasePage(pPage1); +    } +    assert( countWriteCursors(pBt)==0 ); +  } +  pBt->inTrans = TRANS_NONE; +  pBt->inStmt = 0; +  unlockBtreeIfUnused(pBt); +  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 *pBt){ +  int rc; +  if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager); +  pBt->inStmt = 1; +  return rc; +} + + +/* +** Commit the statment subtransaction currently in progress.  If no +** subtransaction is active, this is a no-op. +*/ +int sqlite3BtreeCommitStmt(Btree *pBt){ +  int rc; +  if( pBt->inStmt && !pBt->readOnly ){ +    rc = sqlite3pager_stmt_commit(pBt->pPager); +  }else{ +    rc = SQLITE_OK; +  } +  pBt->inStmt = 0; +  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 *pBt){ +  int rc; +  if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK; +  rc = sqlite3pager_stmt_rollback(pBt->pPager); +  assert( countWriteCursors(pBt)==0 ); +  pBt->inStmt = 0; +  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, n1<n2 ? n1 : n2); +  if( c==0 ){ +    c = n1 - n2; +  } +  return c; +} + +/* +** Create a new cursor for the BTree whose root is on the page +** iTable.  The act of acquiring a cursor gets a read lock on  +** the database file. +** +** If wrFlag==0, then the cursor can only be used for reading. +** If wrFlag==1, then the cursor can be used for reading or for +** writing if other conditions for writing are also met.  These +** are the conditions that must be met in order for writing to +** be allowed: +** +** 1:  The cursor must have been opened with wrFlag==1 +** +** 2:  No other cursors may be open with wrFlag==0 on the same table +** +** 3:  The database must be writable (not on read-only media) +** +** 4:  There must be an active transaction. +** +** Condition 2 warrants further discussion.  If any cursor is opened +** on a table with wrFlag==0, that prevents all other cursors from +** writing to that table.  This is a kind of "read-lock".  When a cursor +** is opened with wrFlag==0 it is guaranteed that the table will not +** change as long as the cursor is open.  This allows the cursor to +** do a sequential scan of the table without having to worry about +** entries being inserted or deleted during the scan.  Cursors should +** be opened with wrFlag==0 only if this read-lock property is needed. +** That is to say, cursors should be opened with wrFlag==0 only if they +** intend to use the sqlite3BtreeNext() system call.  All other cursors +** should be opened with wrFlag==1 even if they never really intend +** to write. +**  +** No checking is done to make sure that page iTable really is the +** root page of a b-tree.  If it is not, then the cursor acquired +** will not work correctly. +** +** The comparison function must be logically the same for every cursor +** on a particular table.  Changing the comparison function will result +** in incorrect operations.  If the comparison function is NULL, a +** default comparison function is used.  The comparison function is +** always ignored for INTKEY tables. +*/ +int sqlite3BtreeCursor( +  Btree *pBt,                                 /* 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; +  BtCursor *pCur; + +  *ppCur = 0; +  if( wrFlag ){ +    if( pBt->readOnly ){ +      return SQLITE_READONLY; +    } +    if( checkReadLocks(pBt, iTable, 0) ){ +      return SQLITE_LOCKED; +    } +  } +  if( pBt->pPage1==0 ){ +    rc = lockBtree(pBt); +    if( rc!=SQLITE_OK ){ +      return rc; +    } +  } +  pCur = sqliteMallocRaw( sizeof(*pCur) ); +  if( pCur==0 ){ +    rc = SQLITE_NOMEM; +    goto create_cursor_exception; +  } +  pCur->pgnoRoot = (Pgno)iTable; +  if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ +    rc = SQLITE_EMPTY; +    pCur->pPage = 0; +    goto create_cursor_exception; +  } +  pCur->pPage = 0;  /* For exit-handler, in case getAndInitPage() fails. */ +  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); +  if( rc!=SQLITE_OK ){ +    goto create_cursor_exception; +  } +  pCur->xCompare = xCmp ? xCmp : dfltCompare; +  pCur->pArg = pArg; +  pCur->pBt = pBt; +  pCur->wrFlag = wrFlag; +  pCur->idx = 0; +  memset(&pCur->info, 0, sizeof(pCur->info)); +  pCur->pNext = pBt->pCursor; +  if( pCur->pNext ){ +    pCur->pNext->pPrev = pCur; +  } +  pCur->pPrev = 0; +  pBt->pCursor = pCur; +  pCur->isValid = 0; +  pCur->status = SQLITE_OK; +  *ppCur = pCur; +  return SQLITE_OK; + +create_cursor_exception: +  if( pCur ){ +    releasePage(pCur->pPage); +    sqliteFree(pCur); +  } +  unlockBtreeIfUnused(pBt); +  return rc; +} + +#if 0  /* Not Used */ +/* +** Change the value of the comparison function used by a cursor. +*/ +void sqlite3BtreeSetCompare( +  BtCursor *pCur,     /* The cursor to whose comparison function is changed */ +  int(*xCmp)(void*,int,const void*,int,const void*), /* New comparison func */ +  void *pArg          /* First argument to xCmp() */ +){ +  pCur->xCompare = xCmp ? xCmp : dfltCompare; +  pCur->pArg = pArg; +} +#endif + +/* +** Close a cursor.  The read lock on the database file is released +** when the last cursor is closed. +*/ +int sqlite3BtreeCloseCursor(BtCursor *pCur){ +  Btree *pBt = pCur->pBt; +  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); +  sqliteFree(pCur); +  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. +*/ +static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){ +  memcpy(pTempCur, pCur, sizeof(*pCur)); +  pTempCur->pNext = 0; +  pTempCur->pPrev = 0; +  if( pTempCur->pPage ){ +    sqlite3pager_ref(pTempCur->pPage->aData); +  } +} + +/* +** Delete a temporary cursor such as was made by the CreateTemporaryCursor() +** function above. +*/ +static void releaseTempCursor(BtCursor *pCur){ +  if( pCur->pPage ){ +    sqlite3pager_unref(pCur->pPage->aData); +  } +} + +/* +** Make sure the BtCursor.info field of the given cursor is valid. +** If it is not already valid, call parseCell() 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 parseCell(). +*/ +static void getCellInfo(BtCursor *pCur){ +  if( pCur->info.nSize==0 ){ +    parseCell(pCur->pPage, pCur->idx, &pCur->info); +  }else{ +#ifndef NDEBUG +    CellInfo info; +    memset(&info, 0, sizeof(info)); +    parseCell(pCur->pPage, pCur->idx, &info); +    assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); +#endif +  } +} + +/* +** 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){ +  if( !pCur->isValid ){ +    *pSize = 0; +  }else{ +    getCellInfo(pCur); +    *pSize = pCur->info.nKey; +  } +  return SQLITE_OK; +} + +/* +** 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){ +  if( !pCur->isValid ){ +    /* Not pointing at a valid entry - set *pSize to 0. */ +    *pSize = 0; +  }else{ +    getCellInfo(pCur); +    *pSize = pCur->info.nData; +  } +  return SQLITE_OK; +} + +/* +** Read payload information from the entry that the pCur cursor is +** pointing to.  Begin reading the payload at "offset" and read +** a total of "amt" bytes.  Put the result in zBuf. +** +** This routine does not make a distinction between key and data. +** It just reads bytes from the payload area.  Data might appear +** on the main page or be scattered out on multiple overflow pages. +*/ +static int getPayload( +  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 */ +){ +  unsigned char *aPayload; +  Pgno nextPage; +  int rc; +  MemPage *pPage; +  Btree *pBt; +  int ovflSize; +  u32 nKey; + +  assert( pCur!=0 && pCur->pPage!=0 ); +  assert( pCur->isValid ); +  pBt = pCur->pBt; +  pPage = pCur->pPage; +  pageIntegrity(pPage); +  assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); +  getCellInfo(pCur); +  aPayload = pCur->info.pCell; +  aPayload += pCur->info.nHeader; +  if( pPage->intKey ){ +    nKey = 0; +  }else{ +    nKey = pCur->info.nKey; +  } +  assert( offset>=0 ); +  if( skipKey ){ +    offset += nKey; +  } +  if( offset+amt > nKey+pCur->info.nData ){ +    return SQLITE_ERROR; +  } +  if( offset<pCur->info.nLocal ){ +    int a = amt; +    if( a+offset>pCur->info.nLocal ){ +      a = pCur->info.nLocal - offset; +    } +    memcpy(pBuf, &aPayload[offset], a); +    if( a==amt ){ +      return SQLITE_OK; +    } +    offset = 0; +    pBuf += a; +    amt -= a; +  }else{ +    offset -= pCur->info.nLocal; +  } +  ovflSize = pBt->usableSize - 4; +  if( amt>0 ){ +    nextPage = get4byte(&aPayload[pCur->info.nLocal]); +    while( amt>0 && nextPage ){ +      rc = sqlite3pager_get(pBt->pPager, nextPage, (void**)&aPayload); +      if( rc!=0 ){ +        return rc; +      } +      nextPage = get4byte(aPayload); +      if( offset<ovflSize ){ +        int a = amt; +        if( a + offset > ovflSize ){ +          a = ovflSize - offset; +        } +        memcpy(pBuf, &aPayload[offset+4], a); +        offset = 0; +        amt -= a; +        pBuf += a; +      }else{ +        offset -= ovflSize; +      } +      sqlite3pager_unref(aPayload); +    } +  } + +  if( amt>0 ){ +    return SQLITE_CORRUPT; /* bkpt-CORRUPT */ +  } +  return SQLITE_OK; +} + +/* +** 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){ +  if( pCur->isValid==0 ){ +    return pCur->status; +  } +  assert( pCur->pPage!=0 ); +  assert( pCur->pPage->intKey==0 ); +  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); +  return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); +} + +/* +** 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){ +  if( !pCur->isValid ){ +    return pCur->status ? pCur->status : SQLITE_INTERNAL; +  } +  assert( pCur->pPage!=0 ); +  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); +  return getPayload(pCur, offset, amt, pBuf, 1); +} + +/* +** 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 getPayload() 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; +  Btree *pBt; +  u32 nKey; +  int nLocal; + +  assert( pCur!=0 && pCur->pPage!=0 ); +  assert( pCur->isValid ); +  pBt = pCur->pBt; +  pPage = pCur->pPage; +  pageIntegrity(pPage); +  assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); +  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. +** +** 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){ +  return (const void*)fetchPayload(pCur, pAmt, 0); +} +const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ +  return (const void*)fetchPayload(pCur, pAmt, 1); +} + + +/* +** 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; +  Btree *pBt = pCur->pBt; + +  assert( pCur->isValid ); +  rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); +  if( rc ) return rc; +  pageIntegrity(pNewPage); +  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-CORRUPT */ +  } +  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. +*/ +static int isRootPage(MemPage *pPage){ +  MemPage *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. +*/ +static void moveToParent(BtCursor *pCur){ +  Pgno oldPgno; +  MemPage *pParent; +  MemPage *pPage; +  int idxParent; + +  assert( pCur->isValid ); +  pPage = pCur->pPage; +  assert( pPage!=0 ); +  assert( !isRootPage(pPage) ); +  pageIntegrity(pPage); +  pParent = pPage->pParent; +  assert( pParent!=0 ); +  pageIntegrity(pParent); +  idxParent = pPage->idxParent; +  sqlite3pager_ref(pParent->aData); +  oldPgno = pPage->pgno; +  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; +  Btree *pBt = pCur->pBt; + +  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0); +  if( rc ){ +    pCur->isValid = 0; +    return rc; +  } +  releasePage(pCur->pPage); +  pageIntegrity(pRoot); +  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->isValid = 1; +    rc = moveToChild(pCur, subpage); +  } +  pCur->isValid = pCur->pPage->nCell>0; +  return rc; +} + +/* +** Move the cursor down to the left-most leaf entry beneath the +** entry to which it is currently pointing. +*/ +static int moveToLeftmost(BtCursor *pCur){ +  Pgno pgno; +  int rc; +  MemPage *pPage; + +  assert( pCur->isValid ); +  while( !(pPage = pCur->pPage)->leaf ){ +    assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); +    pgno = get4byte(findCell(pPage, pCur->idx)); +    rc = moveToChild(pCur, pgno); +    if( rc ) return rc; +  } +  return SQLITE_OK; +} + +/* +** 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*. +*/ +static int moveToRightmost(BtCursor *pCur){ +  Pgno pgno; +  int rc; +  MemPage *pPage; + +  assert( pCur->isValid ); +  while( !(pPage = pCur->pPage)->leaf ){ +    pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); +    pCur->idx = pPage->nCell; +    rc = moveToChild(pCur, pgno); +    if( rc ) return rc; +  } +  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; +  if( pCur->status ){ +    return pCur->status; +  } +  rc = moveToRoot(pCur); +  if( rc ) return rc; +  if( pCur->isValid==0 ){ +    assert( pCur->pPage->nCell==0 ); +    *pRes = 1; +    return SQLITE_OK; +  } +  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; +  if( pCur->status ){ +    return pCur->status; +  } +  rc = moveToRoot(pCur); +  if( rc ) return rc; +  if( pCur->isValid==0 ){ +    assert( pCur->pPage->nCell==0 ); +    *pRes = 1; +    return SQLITE_OK; +  } +  assert( pCur->isValid ); +  *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 nKey.  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, const void *pKey, i64 nKey, int *pRes){ +  int rc; + +  if( pCur->status ){ +    return pCur->status; +  } +  rc = moveToRoot(pCur); +  if( rc ) return rc; +  assert( pCur->pPage ); +  assert( pCur->pPage->isInit ); +  if( pCur->isValid==0 ){ +    *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; +    pageIntegrity(pPage); +    while( lwr<=upr ){ +      void *pCellKey; +      i64 nCellKey; +      pCur->idx = (lwr+upr)/2; +      pCur->info.nSize = 0; +      sqlite3BtreeKeySize(pCur, &nCellKey); +      if( pPage->intKey ){ +        if( nCellKey<nKey ){ +          c = -1; +        }else if( nCellKey>nKey ){ +          c = +1; +        }else{ +          c = 0; +        } +      }else{ +        int available; +        pCellKey = (void *)fetchPayload(pCur, &available, 0); +        if( available>=nCellKey ){ +          c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); +        }else{ +          pCellKey = sqliteMallocRaw( nCellKey ); +          if( pCellKey==0 ) return SQLITE_NOMEM; +          rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); +          c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); +          sqliteFree(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; +      } +    } +    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->idx<pCur->pPage->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){ +  return pCur->isValid==0; +} + +/* +** 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. +*/ +int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ +  int rc; +  MemPage *pPage = pCur->pPage; + +  assert( pRes!=0 ); +  if( pCur->isValid==0 ){ +    *pRes = 1; +    return SQLITE_OK; +  } +  assert( pPage->isInit ); +  assert( pCur->idx<pPage->nCell ); +  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( isRootPage(pPage) ){ +        *pRes = 1; +        pCur->isValid = 0; +        return SQLITE_OK; +      } +      moveToParent(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; +} + +/* +** 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. +*/ +int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ +  int rc; +  Pgno pgno; +  MemPage *pPage; +  if( pCur->isValid==0 ){ +    *pRes = 1; +    return SQLITE_OK; +  } +  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( isRootPage(pPage) ){ +        pCur->isValid = 0; +        *pRes = 1; +        return SQLITE_OK; +      } +      moveToParent(pCur); +      pPage = pCur->pPage; +    } +    pCur->idx--; +    pCur->info.nSize = 0; +    if( pPage->leafData ){ +      rc = sqlite3BtreePrevious(pCur, pRes); +    }else{ +      rc = SQLITE_OK; +    } +  } +  *pRes = 0; +  return rc; +} + +/* +** 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 )\ +                        { sqlite3DebugPrintf X; fflush(stdout); } +#else +# define TRACE(X) +#endif +int sqlite3_btree_trace=0;  /* True to enable tracing */ + +/* +** Allocate a new page from the database file. +** +** The new page is marked as dirty.  (In other words, sqlite3pager_write() +** has already been called on the new page.)  The new page has also +** been referenced and the calling routine is responsible for calling +** sqlite3pager_unref() 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 sqlite3pager_unref() 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. +*/ +static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){ +  MemPage *pPage1; +  int rc; +  int n;     /* Number of pages on the freelist */ +  int k;     /* Number of leaves on the trunk of the freelist */ + +  pPage1 = pBt->pPage1; +  n = get4byte(&pPage1->aData[36]); +  if( n>0 ){ +    /* There are pages on the freelist.  Reuse one of those pages. */ +    MemPage *pTrunk; +    rc = sqlite3pager_write(pPage1->aData); +    if( rc ) return rc; +    put4byte(&pPage1->aData[36], n-1); +    rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk); +    if( rc ) return rc; +    rc = sqlite3pager_write(pTrunk->aData); +    if( rc ){ +      releasePage(pTrunk); +      return rc; +    } +    k = get4byte(&pTrunk->aData[4]); +    if( k==0 ){ +      /* The trunk has no leaves.  So extract the trunk page itself and +      ** use it as the newly allocated page */ +      *pPgno = get4byte(&pPage1->aData[32]); +      memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); +      *ppPage = pTrunk; +      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 */ +      return SQLITE_CORRUPT; /* bkpt-CORRUPT */ +    }else{ +      /* Extract a leaf from the trunk */ +      int closest; +      unsigned char *aData = pTrunk->aData; +      if( nearby>0 ){ +        int i, dist; +        closest = 0; +        dist = get4byte(&aData[8]) - nearby; +        if( dist<0 ) dist = -dist; +        for(i=1; i<k; i++){ +          int d2 = get4byte(&aData[8+i*4]) - nearby; +          if( d2<0 ) d2 = -d2; +          if( d2<dist ) closest = i; +        } +      }else{ +        closest = 0; +      } +      *pPgno = get4byte(&aData[8+closest*4]); +      if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){ +        /* Free page off the end of the file */ +        return SQLITE_CORRUPT; /* bkpt-CORRUPT */ +      } +      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( closest<k-1 ){ +        memcpy(&aData[8+closest*4], &aData[4+k*4], 4); +      } +      put4byte(&aData[4], k-1); +      rc = getPage(pBt, *pPgno, ppPage); +      releasePage(pTrunk); +      if( rc==SQLITE_OK ){ +        sqlite3pager_dont_rollback((*ppPage)->aData); +        rc = sqlite3pager_write((*ppPage)->aData); +      } +    } +  }else{ +    /* There are no pages on the freelist, so create a new page at the +    ** end of the file */ +    *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1; +    rc = getPage(pBt, *pPgno, ppPage); +    if( rc ) return rc; +    rc = sqlite3pager_write((*ppPage)->aData); +    TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); +  } +  return rc; +} + +/* +** Add a page of the database file to the freelist. +** +** sqlite3pager_unref() is NOT called for pPage. +*/ +static int freePage(MemPage *pPage){ +  Btree *pBt = pPage->pBt; +  MemPage *pPage1 = pBt->pPage1; +  int rc, n, k; + +  /* Prepare the page for freeing */ +  assert( pPage->pgno>1 ); +  pPage->isInit = 0; +  releasePage(pPage->pParent); +  pPage->pParent = 0; + +  /* Increment the free page count on pPage1 */ +  rc = sqlite3pager_write(pPage1->aData); +  if( rc ) return rc; +  n = get4byte(&pPage1->aData[36]); +  put4byte(&pPage1->aData[36], n+1); + +  if( n==0 ){ +    /* This is the first free page */ +    rc = sqlite3pager_write(pPage->aData); +    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 = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk); +    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 = sqlite3pager_write(pPage->aData); +      if( rc ) return rc; +      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{ +      /* Add the newly freed page as a leaf on the current trunk */ +      rc = sqlite3pager_write(pTrunk->aData); +      if( rc ) return rc; +      put4byte(&pTrunk->aData[4], k+1); +      put4byte(&pTrunk->aData[8+k*4], pPage->pgno); +      sqlite3pager_dont_write(pBt->pPager, pPage->pgno); +      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){ +  Btree *pBt = pPage->pBt; +  CellInfo info; +  Pgno ovflPgno; +  int rc; + +  parseCellPtr(pPage, pCell, &info); +  if( info.iOverflow==0 ){ +    return SQLITE_OK;  /* No overflow pages. Return without doing anything */ +  } +  ovflPgno = get4byte(&pCell[info.iOverflow]); +  while( ovflPgno!=0 ){ +    MemPage *pOvfl; +    rc = getPage(pBt, ovflPgno, &pOvfl); +    if( rc ) return rc; +    ovflPgno = get4byte(pOvfl->aData); +    rc = freePage(pOvfl); +    if( rc ) return rc; +    sqlite3pager_unref(pOvfl->aData); +  } +  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 *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; +  Btree *pBt = pPage->pBt; +  Pgno pgnoOvfl = 0; +  int nHeader; +  CellInfo info; + +  /* Fill in the header. */ +  nHeader = 0; +  if( !pPage->leaf ){ +    nHeader += 4; +  } +  if( pPage->hasData ){ +    nHeader += putVarint(&pCell[nHeader], nData); +  }else{ +    nData = 0; +  } +  nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); +  parseCellPtr(pPage, pCell, &info); +  assert( info.nHeader==nHeader ); +  assert( info.nKey==nKey ); +  assert( info.nData==nData ); +   +  /* Fill in the payload */ +  nPayload = nData; +  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 ){ +      rc =  allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl); +      if( rc ){ +        releasePage(pToRelease); +        clearCell(pPage, pCell); +        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( n>nSrc ) n = nSrc; +    memcpy(pPayload, pSrc, 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 void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ +  MemPage *pThis; +  unsigned char *aData; + +  if( pgno==0 ) return; +  assert( pBt->pPager!=0 ); +  aData = sqlite3pager_lookup(pBt->pPager, pgno); +  if( aData ){ +    pThis = (MemPage*)&aData[pBt->pageSize]; +    assert( pThis->aData==aData ); +    if( pThis->isInit ){ +      if( pThis->pParent!=pNewParent ){ +        if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData); +        pThis->pParent = pNewParent; +        if( pNewParent ) sqlite3pager_ref(pNewParent->aData); +      } +      pThis->idxParent = idx; +    } +    sqlite3pager_unref(aData); +  } +} + +/* +** 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 void reparentChildPages(MemPage *pPage){ +  int i; +  Btree *pBt; + +  if( pPage->leaf ) return; +  pBt = pPage->pBt; +  for(i=0; i<pPage->nCell; i++){ +    reparentPage(pBt, get4byte(findCell(pPage,i)), pPage, i); +  } +  reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), pPage, i); +  pPage->idxShift = 0; +} + +/* +** 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 && idx<pPage->nCell ); +  assert( sz==cellSize(pPage, idx) ); +  assert( sqlite3pager_iswriteable(pPage->aData) ); +  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; i<pPage->nCell; 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. +*/ +static void 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 */ +){ +  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( sqlite3pager_iswriteable(pPage->aData) ); +  if( pPage->nOverflow || sz+2>pPage->nFree ){ +    if( pTemp ){ +      memcpy(pTemp, pCell, sz); +      pCell = pTemp; +    } +    j = pPage->nOverflow++; +    assert( j<sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0]) ); +    pPage->aOvfl[j].pCell = pCell; +    pPage->aOvfl[j].idx = i; +    pPage->nFree = 0; +  }else{ +    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 ){ +      defragmentPage(pPage); +      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], pCell, sz); +    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; +    pageIntegrity(pPage); +  } +} + +/* +** 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 ); +  totalSize = 0; +  for(i=0; i<nCell; i++){ +    totalSize += aSize[i]; +  } +  assert( totalSize+2*nCell<=pPage->nFree ); +  assert( pPage->nCell==0 ); +  cellptr = pPage->cellOffset; +  data = pPage->aData; +  hdr = pPage->hdrOffset; +  put2byte(&data[hdr+3], nCell); +  cellbody = allocateSpace(pPage, totalSize); +  assert( cellbody>0 ); +  assert( pPage->nFree >= 2*nCell ); +  pPage->nFree -= 2*nCell; +  for(i=0; i<nCell; i++){ +    put2byte(&data[cellptr], cellbody); +    memcpy(&data[cellbody], apCell[i], aSize[i]); +    cellptr += 2; +    cellbody += aSize[i]; +  } +  assert( cellbody==pPage->pBt->usableSize ); +  pPage->nCell = nCell; +} + +/* +** 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 + +/* +** 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*); + +/* +** 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 */ +  Btree *pBt;                  /* The whole database */ +  int nCell = 0;               /* Number of cells in aCell[] */ +  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[] */ +  int mxCellPerPage;           /* Maximum number of cells in one page */ +  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[] */ +  int idxDiv[NB];              /* Indices of divider cells in pParent */ +  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;                 /* 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 */ + +  /*  +  ** Find the parent page. +  */ +  assert( pPage->isInit ); +  assert( sqlite3pager_iswriteable(pPage->aData) ); +  pBt = pPage->pBt; +  pParent = pPage->pParent; +  sqlite3pager_write(pParent->aData); +  assert( pParent ); +  TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); + +  /* +  ** Allocate space for memory structures +  */ +  mxCellPerPage = MX_CELL(pBt); +  apCell = sqliteMallocRaw(  +       (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int)) +     + sizeof(MemPage)*NB +     + pBt->pageSize*(5+NB) +  ); +  if( apCell==0 ){ +    return SQLITE_NOMEM; +  } +  szCell = (int*)&apCell[(mxCellPerPage+2)*NB]; +  aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB]; +  for(i=1; i<NB; i++){ +    aCopy[i] = &aCopy[i-1][pBt->pageSize+sizeof(MemPage)]; +  } +  aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)]; +   +  /* +  ** 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==sqlite3pager_pagenumber(pPage->aData) ); +    for(idx=0; idx<pParent->nCell; idx++){ +      if( get4byte(findCell(pParent, idx))==pgno ){ +        break; +      } +    } +    assert( idx<pParent->nCell +             || 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; +  sqlite3pager_ref(pParent->aData); + +  /* +  ** 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; i<NB; i++, k++){ +    if( k<pParent->nCell ){ +      idxDiv[i] = k; +      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++; +  } + +  /* +  ** 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; i<nOld; i++){ +    MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize]; +    p->aData = &((u8*)p)[-pBt->pageSize]; +    memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage)); +    p->aData = &((u8*)p)[-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; i<nOld; i++){ +    MemPage *pOld = apCopy[i]; +    int limit = pOld->nCell+pOld->nOverflow; +    for(j=0; j<limit; j++){ +      apCell[nCell] = findOverflowCell(pOld, j); +      szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); +      nCell++; +    } +    if( i<nOld-1 ){ +      int sz = cellSizePtr(pParent, apDiv[i]); +      if( leafData ){ +        /* With the LEAFDATA flag, pParent cells hold only INTKEYs that +        ** are duplicates of keys on the child pages.  We need to remove +        ** the divider cells from pParent, but the dividers cells are not +        ** added to apCell[] because they are duplicates of child cells. +        */ +        dropCell(pParent, nxDiv, sz); +      }else{ +        u8 *pTemp; +        szCell[nCell] = sz; +        pTemp = &aSpace[iSpace]; +        iSpace += sz; +        assert( iSpace<=pBt->pageSize*5 ); +        memcpy(pTemp, apDiv[i], sz); +        apCell[nCell] = pTemp+leafCorrection; +        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 ); +        } +        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<nCell; i++){ +    subtotal += szCell[i] + 2; +    if( subtotal > 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; +    while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){ +      szRight += szCell[d] + 2; +      szLeft -= szCell[r] + 2; +      cntNew[i-1]--; +      r = cntNew[i-1] - 1; +      d = r + 1 - leafData; +    } +    szNew[i] = szRight; +    szNew[i-1] = szLeft; +  } +  assert( cntNew[0]>0 ); + +  /* +  ** Allocate k new pages.  Reuse old pages where possible. +  */ +  assert( pPage->pgno>1 ); +  pageFlags = pPage->aData[0]; +  for(i=0; i<k; i++){ +    MemPage *pNew; +    if( i<nOld ){ +      pNew = apNew[i] = apOld[i]; +      pgnoNew[i] = pgnoOld[i]; +      apOld[i] = 0; +      sqlite3pager_write(pNew->aData); +    }else{ +      rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1]); +      if( rc ) goto balance_cleanup; +      apNew[i] = pNew; +    } +    nNew++; +    zeroPage(pNew, pageFlags); +  } + +  /* Free any old pages that were not reused as new pages. +  */ +  while( i<nOld ){ +    rc = freePage(apOld[i]); +    if( rc ) goto balance_cleanup; +    releasePage(apOld[i]); +    apOld[i] = 0; +    i++; +  } + +  /* +  ** Put the new pages in accending order.  This helps to +  ** keep entries in the disk file in order so that a scan +  ** of the table is a linear scan through the file.  That +  ** in turn helps the operating system to deliver pages +  ** from the disk more rapidly. +  ** +  ** An O(n^2) insertion sort algorithm is used, but since +  ** n is never more than NB (a small constant), that should +  ** not be a problem. +  ** +  ** When NB==3, this one optimization makes the database +  ** about 25% faster for large insertions and deletions. +  */ +  for(i=0; i<k-1; i++){ +    int minV = pgnoNew[i]; +    int minI = i; +    for(j=i+1; j<k; j++){ +      if( pgnoNew[j]<(unsigned)minV ){ +        minI = j; +        minV = pgnoNew[j]; +      } +    } +    if( minI>i ){ +      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; i<nNew; i++){ +    MemPage *pNew = apNew[i]; +    assert( pNew->pgno==pgnoNew[i] ); +    assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); +    j = cntNew[i]; +    assert( pNew->nCell>0 ); +    assert( pNew->nOverflow==0 ); +    if( i<nNew-1 && j<nCell ){ +      u8 *pCell; +      u8 *pTemp; +      int sz; +      pCell = apCell[j]; +      sz = szCell[j] + leafCorrection; +      if( !pNew->leaf ){ +        memcpy(&pNew->aData[8], pCell, 4); +        pTemp = 0; +      }else if( leafData ){ +        CellInfo info; +        j--; +        parseCellPtr(pNew, apCell[j], &info); +        pCell = &aSpace[iSpace]; +        fillInCell(pParent, pCell, 0, info.nKey, 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 ); +      } +      insertCell(pParent, nxDiv, pCell, sz, pTemp); +      put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); +      j++; +      nxDiv++; +    } +  } +  assert( j==nCell ); +  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; i<nNew; i++){ +    reparentChildPages(apNew[i]); +  } +  reparentChildPages(pParent); + +  /* +  ** Balance the parent page.  Note that the current page (pPage) might +  ** have been added to the freelist is it might no longer be initialized. +  ** But the parent page will always be initialized. +  */ +  assert( pParent->isInit ); +  /* assert( pPage->isInit ); // No! pPage might have been added to freelist */ +  /* pageIntegrity(pPage);    // No! pPage might have been added to freelist */  +  rc = balance(pParent); +   +  /* +  ** Cleanup before returning. +  */ +balance_cleanup: +  sqliteFree(apCell); +  for(i=0; i<nOld; i++){ +    releasePage(apOld[i]); +  } +  for(i=0; i<nNew; i++){ +    releasePage(apNew[i]); +  } +  releasePage(pParent); +  TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n", +          pPage->pgno, 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 */ +  Btree *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 ); +  pBt = pPage->pBt; +  mxCellPerPage = MX_CELL(pBt); +  apCell = sqliteMallocRaw( 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<=sqlite3pager_pagecount(pPage->pBt->pPager) ); +    rc = getPage(pPage->pBt, pgnoChild, &pChild); +    if( rc ) goto end_shallow_balance; +    if( pPage->pgno==1 ){ +      rc = initPage(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; i<pChild->nCell; i++){ +          apCell[i] = findCell(pChild,i); +          szCell[i] = cellSizePtr(pChild, apCell[i]); +        } +        assemblePage(pPage, pChild->nCell, apCell, szCell); +        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 = initPage(pPage, 0); +      assert( rc==SQLITE_OK ); +      freePage(pChild); +      TRACE(("BALANCE: transfer child %d into root %d\n", +              pChild->pgno, pPage->pgno)); +    } +    reparentChildPages(pPage); +    releasePage(pChild); +  } +end_shallow_balance: +  sqliteFree(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 */ +  Btree *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; +  rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno); +  if( rc ) return rc; +  assert( sqlite3pager_iswriteable(pChild->aData) ); +  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); +  rc = initPage(pChild, pPage); +  if( rc ) return rc; +  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)); +  rc = balance_nonroot(pChild); +  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 rc = SQLITE_OK; +  if( pPage->pParent==0 ){ +    if( pPage->nOverflow>0 ){ +      rc = balance_deeper(pPage); +    } +    if( pPage->nCell==0 ){ +      rc = balance_shallower(pPage); +    } +  }else{ +    if( pPage->nOverflow>0 || 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 other than pExclude were opened with  +** wrFlag==0 then this routine returns SQLITE_LOCKED.  If all +** cursors that point to pgnoRoot were opened with wrFlag==1 +** then this routine returns SQLITE_OK. +** +** In addition to checking for read-locks (where a read-lock  +** means a cursor opened with wrFlag==0) this routine also moves +** all cursors other than pExclude so that they are pointing to the  +** first Cell on 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 *pBt, Pgno pgnoRoot, BtCursor *pExclude){ +  BtCursor *p; +  for(p=pBt->pCursor; p; p=p->pNext){ +    if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue; +    if( p->wrFlag==0 ) return SQLITE_LOCKED; +    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 rc; +  int loc; +  int szNew; +  MemPage *pPage; +  Btree *pBt = pCur->pBt; +  unsigned char *oldCell; +  unsigned char *newCell = 0; + +  if( pCur->status ){ +    return pCur->status;  /* A rollback destroyed this cursor */ +  } +  if( pBt->inTrans!=TRANS_WRITE ){ +    /* Must start a transaction before doing an insert */ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  assert( !pBt->readOnly ); +  if( !pCur->wrFlag ){ +    return SQLITE_PERM;   /* Cursor not open for writing */ +  } +  if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ +    return SQLITE_LOCKED; /* The table pCur points to has a read lock */ +  } +  rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc); +  if( rc ) 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 ); +  rc = sqlite3pager_write(pPage->aData); +  if( rc ) return rc; +  newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); +  if( newCell==0 ) return SQLITE_NOMEM; +  rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew); +  if( rc ) goto end_insert; +  assert( szNew==cellSizePtr(pPage, newCell) ); +  assert( szNew<=MX_CELL_SIZE(pBt) ); +  if( loc==0 && pCur->isValid ){ +    int szOld; +    assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); +    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 ); +  } +  insertCell(pPage, pCur->idx, newCell, szNew, 0); +  rc = balance(pPage); +  /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ +  /* fflush(stdout); */ +  moveToRoot(pCur); +end_insert: +  sqliteFree(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 *pBt = pCur->pBt; + +  assert( pPage->isInit ); +  if( pCur->status ){ +    return pCur->status;  /* A rollback destroyed this cursor */ +  } +  if( pBt->inTrans!=TRANS_WRITE ){ +    /* Must start a transaction before doing a delete */ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  assert( !pBt->readOnly ); +  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(pBt, pCur->pgnoRoot, pCur) ){ +    return SQLITE_LOCKED; /* The table pCur points to has a read lock */ +  } +  rc = sqlite3pager_write(pPage->aData); +  if( rc ) return rc; +  pCell = findCell(pPage, pCur->idx); +  if( !pPage->leaf ){ +    pgnoChild = get4byte(pCell); +  } +  clearCell(pPage, pCell); +  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 szNext; +    int notUsed; +    unsigned char *tempCell; +    assert( !pPage->leafData ); +    getTempCursor(pCur, &leafCur); +    rc = sqlite3BtreeNext(&leafCur, ¬Used); +    if( rc!=SQLITE_OK ){ +      if( rc!=SQLITE_NOMEM ){ +        rc = SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +      } +      return rc; +    } +    rc = sqlite3pager_write(leafCur.pPage->aData); +    if( rc ) return rc; +    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 = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); +    if( tempCell==0 ) return SQLITE_NOMEM; +    insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell); +    put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); +    rc = balance(pPage); +    sqliteFree(tempCell); +    if( rc ) return rc; +    dropCell(leafCur.pPage, leafCur.idx, szNext); +    rc = balance(leafCur.pPage); +    releaseTempCursor(&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); +  } +  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 +*/ +int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ +  MemPage *pRoot; +  Pgno pgnoRoot; +  int rc; +  if( pBt->inTrans!=TRANS_WRITE ){ +    /* Must start a transaction first */ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  if( pBt->readOnly ){ +    return SQLITE_READONLY; +  } +  rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1); +  if( rc ) return rc; +  assert( sqlite3pager_iswriteable(pRoot->aData) ); +  zeroPage(pRoot, flags | PTF_LEAF); +  sqlite3pager_unref(pRoot->aData); +  *piTable = (int)pgnoRoot; +  return SQLITE_OK; +} + +/* +** Erase the given database page and all its children.  Return +** the page to the freelist. +*/ +static int clearDatabasePage( +  Btree *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; +  int rc; +  unsigned char *pCell; +  int i; + +  rc = getAndInitPage(pBt, pgno, &pPage, pParent); +  if( rc ) return rc; +  rc = sqlite3pager_write(pPage->aData); +  if( rc ) return rc; +  for(i=0; i<pPage->nCell; i++){ +    pCell = findCell(pPage, i); +    if( !pPage->leaf ){ +      rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); +      if( rc ) return rc; +    } +    rc = clearCell(pPage, pCell); +    if( rc ) return rc; +  } +  if( !pPage->leaf ){ +    rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1); +    if( rc ) return rc; +  } +  if( freePageFlag ){ +    rc = freePage(pPage); +  }else{ +    zeroPage(pPage, pPage->aData[0] | PTF_LEAF); +  } +  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 *pBt, int iTable){ +  int rc; +  BtCursor *pCur; +  if( pBt->inTrans!=TRANS_WRITE ){ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ +    if( pCur->pgnoRoot==(Pgno)iTable ){ +      if( pCur->wrFlag==0 ) return SQLITE_LOCKED; +      moveToRoot(pCur); +    } +  } +  rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); +  if( rc ){ +    sqlite3BtreeRollback(pBt); +  } +  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. +*/ +int sqlite3BtreeDropTable(Btree *pBt, int iTable){ +  int rc; +  MemPage *pPage; +  BtCursor *pCur; +  if( pBt->inTrans!=TRANS_WRITE ){ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ +    if( pCur->pgnoRoot==(Pgno)iTable ){ +      return SQLITE_LOCKED;  /* Cannot drop a table that has a cursor */ +    } +  } +  rc = getPage(pBt, (Pgno)iTable, &pPage); +  if( rc ) return rc; +  rc = sqlite3BtreeClearTable(pBt, iTable); +  if( rc ) return rc; +  if( iTable>1 ){ +    rc = freePage(pPage); +  }else{ +    zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); +  } +  releasePage(pPage); +  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 *pBt, int idx, u32 *pMeta){ +  int rc; +  unsigned char *pP1; + +  assert( idx>=0 && idx<=15 ); +  rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1); +  if( rc ) return rc; +  *pMeta = get4byte(&pP1[36 + idx*4]); +  sqlite3pager_unref(pP1); + +  /* The current implementation is unable to handle writes to an autovacuumed +  ** database.  So make such a database readonly. */ +  if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; + +  return SQLITE_OK; +} + +/* +** Write meta-information back into the database.  Meta[0] is +** read-only and may not be written. +*/ +int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ +  unsigned char *pP1; +  int rc; +  assert( idx>=1 && idx<=15 ); +  if( pBt->inTrans!=TRANS_WRITE ){ +    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; +  } +  assert( pBt->pPage1!=0 ); +  pP1 = pBt->pPage1->aData; +  rc = sqlite3pager_write(pP1); +  if( rc ) return rc; +  put4byte(&pP1[36 + idx*4], iMeta); +  return SQLITE_OK; +} + +/* +** Return the flag byte at the beginning of the page that the cursor +** is currently pointing to. +*/ +int sqlite3BtreeFlags(BtCursor *pCur){ +  MemPage *pPage = pCur->pPage; +  return pPage ? pPage->aData[pPage->hdrOffset] : 0; +} + +/* +** Print a disassembly of the given page on standard output.  This routine +** is used for debugging and testing only. +*/ +#ifdef SQLITE_TEST +int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ +  int rc; +  MemPage *pPage; +  int i, j, c; +  int nFree; +  u16 idx; +  int hdr; +  int nCell; +  int isInit; +  unsigned char *data; +  char range[20]; +  unsigned char payload[20]; + +  rc = getPage(pBt, (Pgno)pgno, &pPage); +  isInit = pPage->isInit; +  if( pPage->isInit==0 ){ +    initPage(pPage, 0); +  } +  if( rc ){ +    return rc; +  } +  hdr = pPage->hdrOffset; +  data = pPage->aData; +  c = data[hdr]; +  pPage->intKey = (c & (PTF_INTKEY|PTF_LEAFDATA))!=0; +  pPage->zeroData = (c & PTF_ZERODATA)!=0; +  pPage->leafData = (c & PTF_LEAFDATA)!=0; +  pPage->leaf = (c & PTF_LEAF)!=0; +  pPage->hasData = !(pPage->zeroData || (!pPage->leaf && pPage->leafData)); +  nCell = get2byte(&data[hdr+3]); +  sqlite3DebugPrintf("PAGE %d:  flags=0x%02x  frag=%d   parent=%d\n", pgno, +    data[hdr], data[hdr+7],  +    (pPage->isInit && pPage->pParent) ? pPage->pParent->pgno : 0); +  assert( hdr == (pgno==1 ? 100 : 0) ); +  idx = hdr + 12 - pPage->leaf*4; +  for(i=0; i<nCell; i++){ +    CellInfo info; +    Pgno child; +    unsigned char *pCell; +    int sz; +    int addr; + +    addr = get2byte(&data[idx + 2*i]); +    pCell = &data[addr]; +    parseCellPtr(pPage, pCell, &info); +    sz = info.nSize; +    sprintf(range,"%d..%d", addr, addr+sz-1); +    if( pPage->leaf ){ +      child = 0; +    }else{ +      child = get4byte(pCell); +    } +    sz = info.nData; +    if( !pPage->intKey ) sz += info.nKey; +    if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1; +    memcpy(payload, &pCell[info.nHeader], sz); +    for(j=0; j<sz; j++){ +      if( payload[j]<0x20 || payload[j]>0x7f ) payload[j] = '.'; +    } +    payload[sz] = 0; +    sqlite3DebugPrintf( +      "cell %2d: i=%-10s chld=%-4d nk=%-4lld nd=%-4d payload=%s\n", +      i, range, child, info.nKey, info.nData, payload +    ); +  } +  if( !pPage->leaf ){ +    sqlite3DebugPrintf("right_child: %d\n", get4byte(&data[hdr+8])); +  } +  nFree = 0; +  i = 0; +  idx = get2byte(&data[hdr+1]); +  while( idx>0 && idx<pPage->pBt->usableSize ){ +    int sz = get2byte(&data[idx+2]); +    sprintf(range,"%d..%d", idx, idx+sz-1); +    nFree += sz; +    sqlite3DebugPrintf("freeblock %2d: i=%-10s size=%-4d total=%d\n", +       i, range, sz, nFree); +    idx = get2byte(&data[idx]); +    i++; +  } +  if( idx!=0 ){ +    sqlite3DebugPrintf("ERROR: next freeblock index out of range: %d\n", idx); +  } +  if( recursive && !pPage->leaf ){ +    for(i=0; i<nCell; i++){ +      unsigned char *pCell = findCell(pPage, i); +      sqlite3BtreePageDump(pBt, get4byte(pCell), 1); +      idx = get2byte(pCell); +    } +    sqlite3BtreePageDump(pBt, get4byte(&data[hdr+8]), 1); +  } +  pPage->isInit = isInit; +  sqlite3pager_unref(data); +  fflush(stdout); +  return SQLITE_OK; +} +#endif + +#ifdef SQLITE_TEST +/* +** Fill aResult[] with information about the entry and page that the +** cursor is pointing to. +**  +**   aResult[0] =  The page number +**   aResult[1] =  The entry number +**   aResult[2] =  Total number of entries on this page +**   aResult[3] =  Cell size (local payload + header) +**   aResult[4] =  Number of free bytes on this page +**   aResult[5] =  Number of free blocks on the page +**   aResult[6] =  Total payload size (local + overflow) +**   aResult[7] =  Header size in bytes +**   aResult[8] =  Local payload size +**   aResult[9] =  Parent page number +** +** This routine is used for testing and debugging only. +*/ +int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ +  int cnt, idx; +  MemPage *pPage = pCur->pPage; +  BtCursor tmpCur; + +  pageIntegrity(pPage); +  assert( pPage->isInit ); +  getTempCursor(pCur, &tmpCur); +  while( upCnt-- ){ +    moveToParent(&tmpCur); +  } +  pPage = tmpCur.pPage; +  pageIntegrity(pPage); +  aResult[0] = sqlite3pager_pagenumber(pPage->aData); +  assert( aResult[0]==pPage->pgno ); +  aResult[1] = tmpCur.idx; +  aResult[2] = pPage->nCell; +  if( tmpCur.idx>=0 && tmpCur.idx<pPage->nCell ){ +    getCellInfo(&tmpCur); +    aResult[3] = tmpCur.info.nSize; +    aResult[6] = tmpCur.info.nData; +    aResult[7] = tmpCur.info.nHeader; +    aResult[8] = tmpCur.info.nLocal; +  }else{ +    aResult[3] = 0; +    aResult[6] = 0; +    aResult[7] = 0; +    aResult[8] = 0; +  } +  aResult[4] = pPage->nFree; +  cnt = 0; +  idx = get2byte(&pPage->aData[pPage->hdrOffset+1]); +  while( idx>0 && idx<pPage->pBt->usableSize ){ +    cnt++; +    idx = get2byte(&pPage->aData[idx]); +  } +  aResult[5] = cnt; +  if( pPage->pParent==0 || isRootPage(pPage) ){ +    aResult[9] = 0; +  }else{ +    aResult[9] = pPage->pParent->pgno; +  } +  releaseTempCursor(&tmpCur); +  return SQLITE_OK; +} +#endif + +/* +** Return the pager associated with a BTree.  This routine is used for +** testing and debugging only. +*/ +Pager *sqlite3BtreePager(Btree *pBt){ +  return pBt->pPager; +} + +/* +** 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 { +  Btree *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 */ +  char *zErrMsg; /* An error message.  NULL of no errors seen. */ +}; + +/* +** Append a message to the error message string. +*/ +static void checkAppendMsg( +  IntegrityCk *pCheck, +  char *zMsg1, +  const char *zFormat, +  ... +){ +  va_list ap; +  char *zMsg2; +  va_start(ap, zFormat); +  zMsg2 = sqlite3VMPrintf(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); +    sqliteFree(zOld); +  }else{ +    sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0); +  } +  sqliteFree(zMsg2); +} + +/* +** 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; +} + +/* +** 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 ){ +    unsigned char *pOvfl; +    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( sqlite3pager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){ +      checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); +      break; +    } +    if( isFreeList ){ +      int n = get4byte(&pOvfl[4]); +      if( n>pCheck->pBt->usableSize/4-8 ){ +        checkAppendMsg(pCheck, zContext, +           "freelist leaf count too big on page %d", iPage); +        N--; +      }else{ +        for(i=0; i<n; i++){ +          checkRef(pCheck, get4byte(&pOvfl[8+i*4]), zContext); +        } +        N -= n; +      } +    } +    iPage = get4byte(pOvfl); +    sqlite3pager_unref(pOvfl); +  } +} + +/* +** 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 */ +  char *zLowerBound,    /* All keys should be greater than this, if not NULL */ +  int nLower,           /* Number of characters in zLowerBound */ +  char *zUpperBound,    /* All keys should be less than this, if not NULL */ +  int nUpper            /* Number of characters in zUpperBound */ +){ +  MemPage *pPage; +  int i, rc, depth, d2, pgno, cnt; +  int hdr, cellStart; +  int nCell; +  u8 *data; +  BtCursor cur; +  Btree *pBt; +  int maxLocal, usableSize; +  char zContext[100]; +  char *hit; + +  /* Check that the page exists +  */ +  cur.pBt = pBt = pCheck->pBt; +  usableSize = pBt->usableSize; +  if( iPage==0 ) return 0; +  if( checkRef(pCheck, iPage, zParentContext) ) return 0; +  if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){ +    checkAppendMsg(pCheck, zContext, +       "unable to get the page. error code=%d", rc); +    return 0; +  } +  maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal; +  if( (rc = initPage(pPage, pParent))!=0 ){ +    checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc); +    releasePage(pPage); +    return 0; +  } + +  /* Check out all the cells. +  */ +  depth = 0; +  cur.pPage = pPage; +  for(i=0; i<pPage->nCell; i++){ +    u8 *pCell; +    int sz; +    CellInfo info; + +    /* Check payload overflow pages +    */ +    sprintf(zContext, "On tree page %d cell %d: ", iPage, i); +    pCell = findCell(pPage,i); +    parseCellPtr(pPage, pCell, &info); +    sz = info.nData; +    if( !pPage->intKey ) sz += info.nKey; +    if( sz>info.nLocal ){ +      int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); +      checkList(pCheck, 0, get4byte(&pCell[info.iOverflow]),nPage,zContext); +    } + +    /* Check sanity of left child page. +    */ +    if( !pPage->leaf ){ +      pgno = get4byte(pCell); +      d2 = checkTreePage(pCheck,pgno,pPage,zContext,0,0,0,0); +      if( i>0 && d2!=depth ){ +        checkAppendMsg(pCheck, zContext, "Child page depth differs"); +      } +      depth = d2; +    } +  } +  if( !pPage->leaf ){ +    pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); +    sprintf(zContext, "On page %d at right child: ", iPage); +    checkTreePage(pCheck, pgno, pPage, zContext,0,0,0,0); +  } +  +  /* Check for complete coverage of the page +  */ +  data = pPage->aData; +  hdr = pPage->hdrOffset; +  hit = sqliteMalloc( 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<nCell; i++){ +      int pc = get2byte(&data[cellStart+i*2]); +      int size = cellSizePtr(pPage, &data[pc]); +      int j; +      for(j=pc+size-1; j>=pc; j--) hit[j]++; +    } +    for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000;  +           cnt++){ +      int size = get2byte(&data[i+2]); +      int j; +      for(j=i+size-1; j>=i; j--) hit[j]++; +      i = get2byte(&data[i]); +    } +    for(i=cnt=0; i<usableSize; i++){ +      if( hit[i]==0 ){ +        cnt++; +      }else if( hit[i]>1 ){ +        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); +    } +  } +  sqliteFree(hit); + +  releasePage(pPage); +  return depth+1; +} + +/* +** 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 *pBt, int *aRoot, int nRoot){ +  int i; +  int nRef; +  IntegrityCk sCheck; + +  nRef = *sqlite3pager_stats(pBt->pPager); +  if( lockBtree(pBt)!=SQLITE_OK ){ +    return sqliteStrDup("Unable to acquire a read lock on the database"); +  } +  sCheck.pBt = pBt; +  sCheck.pPager = pBt->pPager; +  sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager); +  if( sCheck.nPage==0 ){ +    unlockBtreeIfUnused(pBt); +    return 0; +  } +  sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); +  for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } +  i = PENDING_BYTE/pBt->pageSize + 1; +  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; i<nRoot; i++){ +    if( aRoot[i]==0 ) continue; +    checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0); +  } + +  /* Make sure every page in the file is referenced +  */ +  for(i=1; i<=sCheck.nPage; i++){ +    if( sCheck.anRef[i]==0 ){ +      checkAppendMsg(&sCheck, 0, "Page %d is never used", i); +    } +  } + +  /* Make sure this analysis did not leave any unref() pages +  */ +  unlockBtreeIfUnused(pBt); +  if( nRef != *sqlite3pager_stats(pBt->pPager) ){ +    checkAppendMsg(&sCheck, 0,  +      "Outstanding page count goes from %d to %d during this analysis", +      nRef, *sqlite3pager_stats(pBt->pPager) +    ); +  } + +  /* Clean  up and report errors. +  */ +  sqliteFree(sCheck.anRef); +  return sCheck.zErrMsg; +} + +/* +** Return the full pathname of the underlying database file. +*/ +const char *sqlite3BtreeGetFilename(Btree *pBt){ +  assert( pBt->pPager!=0 ); +  return sqlite3pager_filename(pBt->pPager); +} + +/* +** Return the pathname of the directory that contains the database file. +*/ +const char *sqlite3BtreeGetDirname(Btree *pBt){ +  assert( pBt->pPager!=0 ); +  return sqlite3pager_dirname(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. +*/ +const char *sqlite3BtreeGetJournalname(Btree *pBt){ +  assert( pBt->pPager!=0 ); +  return sqlite3pager_journalname(pBt->pPager); +} + +/* +** 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. +*/ +int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ +  int rc = SQLITE_OK; +  Pgno i, nPage, nToPage; + +  if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){ +    return SQLITE_ERROR; +  } +  if( pBtTo->pCursor ) return SQLITE_BUSY; +  nToPage = sqlite3pager_pagecount(pBtTo->pPager); +  nPage = sqlite3pager_pagecount(pBtFrom->pPager); +  for(i=1; rc==SQLITE_OK && i<=nPage; i++){ +    void *pPage; +    rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage); +    if( rc ) break; +    rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage); +    if( rc ) break; +    sqlite3pager_unref(pPage); +  } +  for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ +    void *pPage; +    rc = sqlite3pager_get(pBtTo->pPager, i, &pPage); +    if( rc ) break; +    rc = sqlite3pager_write(pPage); +    sqlite3pager_unref(pPage); +    sqlite3pager_dont_write(pBtTo->pPager, i); +  } +  if( !rc && nPage<nToPage ){ +    rc = sqlite3pager_truncate(pBtTo->pPager, nPage); +  } +  if( rc ){ +    sqlite3BtreeRollback(pBtTo); +  } +  return rc;   +} + +/* +** Return non-zero if a transaction is active. +*/ +int sqlite3BtreeIsInTrans(Btree *pBt){ +  return (pBt && (pBt->inTrans==TRANS_WRITE)); +} + +/* +** Return non-zero if a statement transaction is active. +*/ +int sqlite3BtreeIsInStmt(Btree *pBt){ +  return (pBt && pBt->inStmt); +} + +/* +** 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 sqlite3BtreeSync(Btree *pBt, const char *zMaster){ +  if( pBt->inTrans==TRANS_WRITE ){ +    return sqlite3pager_sync(pBt->pPager, zMaster); +  } +  return SQLITE_OK; +} diff --git a/ext/pdo_sqlite/sqlite/src/btree.h b/ext/pdo_sqlite/sqlite/src/btree.h new file mode 100644 index 0000000000..48524aefc1 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/btree.h @@ -0,0 +1,124 @@ +/* +** 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$ +*/ +#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 + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; + + +int sqlite3BtreeOpen( +  const char *zFilename,   /* Name of database file to open */ +  Btree **,                /* Return open Btree* here */ +  int flags                /* Flags */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +*/ +#define BTREE_OMIT_JOURNAL  1  /* Do not use journal.  No argument */ +#define BTREE_MEMORY        2  /* In-memory DB.  No argument */ + +int sqlite3BtreeClose(Btree*); +int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*); +int sqlite3BtreeSetCacheSize(Btree*,int); +int sqlite3BtreeSetSafetyLevel(Btree*,int); +int sqlite3BtreeSetPageSize(Btree*,int,int); +int sqlite3BtreeGetPageSize(Btree*); +int sqlite3BtreeGetReserve(Btree*); +int sqlite3BtreeBeginTrans(Btree*,int); +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 sqlite3BtreeSync(Btree*, const char *zMaster); + +const char *sqlite3BtreeGetFilename(Btree *); +const char *sqlite3BtreeGetDirname(Btree *); +const char *sqlite3BtreeGetJournalname(Btree *); +int sqlite3BtreeCopyFile(Btree *, 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 sqlite3BtreeClearTable(Btree*, int); +int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); +int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); + +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 */ +); + +void sqlite3BtreeSetCompare( +  BtCursor *, +  int(*)(void*,int,const void*,int,const void*), +  void* +); + +int sqlite3BtreeCloseCursor(BtCursor*); +int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes); +int sqlite3BtreeDelete(BtCursor*); +int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, +                                  const void *pData, int nData); +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*); +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); +struct Pager *sqlite3BtreePager(Btree*); + + +#ifdef SQLITE_TEST +int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +void sqlite3BtreeCursorList(Btree*); +int sqlite3BtreePageDump(Btree*, int, int recursive); +#endif + + +#endif /* _BTREE_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/build.c b/ext/pdo_sqlite/sqlite/src/build.c new file mode 100644 index 0000000000..3e5e08a541 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/build.c @@ -0,0 +1,2564 @@ +/* +** 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 +**     PRAGMA +** +** $Id$ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* +** This routine is called when a new SQL statement is beginning to +** be parsed.  Check to see if the schema for the database needs +** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables. +** If it does, then read it. +*/ +void sqlite3BeginParse(Parse *pParse, int explainFlag){ +  pParse->explain = explainFlag; +  pParse->nVar = 0; +} + +/* +** 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; + +  if( sqlite3_malloc_failed ) return; + +  /* Begin by generating some termination code at the end of the +  ** vdbe program +  */ +  db = pParse->db; +  v = sqlite3GetVdbe(pParse); +  if( v ){ +    sqlite3VdbeAddOp(v, OP_Halt, 0, 0); + +    /* 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; +      sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v)); +      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ +        if( (mask & pParse->cookieMask)==0 ) continue; +        sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); +        sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); +      } +      sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); +    } + +    /* Add a No-op that contains the complete text of the compiled SQL +    ** statement as its P3 argument.  This does not change the functionality +    ** of the program.  +    ** +    ** This is used to implement sqlite3_trace() functionality. +    */ +    sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql); +  } + + +  /* Get the VDBE program ready for execution +  */ +  if( v && pParse->nErr==0 ){ +    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; +    sqlite3VdbeTrace(v, trace); +    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, +                         pParse->nTab+3, pParse->explain); +    pParse->rc = pParse->nErr ? SQLITE_ERROR : 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->nAgg = 0; +  pParse->nVar = 0; +  pParse->cookieMask = 0; +  pParse->cookieGoto = 0; +} + +/* +** 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 ); +  assert( (db->flags & SQLITE_Initialized) || db->init.busy ); +  for(i=0; i<db->nDb; 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].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, const char *zName, const char *zDbase){ +  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 ){ +    if( zDbase ){ +      sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); +    }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){ +      sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", +         zName, zDbase); +    }else{ +      sqlite3ErrorMsg(pParse, "no such table: %s", 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; +  assert( (db->flags & SQLITE_Initialized) || db->init.busy ); +  for(i=0; i<db->nDb; i++){ +    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */ +    if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; +    p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); +    if( p ) break; +  } +  return p; +} + +/* +** Reclaim the memory used by an index +*/ +static void freeIndex(Index *p){ +  sqliteFree(p->zColAff); +  sqliteFree(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(sqlite3 *db, Index *p){ +  Index *pOld; + +  assert( db!=0 && p->zName!=0 ); +  pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, +                          strlen(p->zName)+1, 0); +  if( pOld!=0 && pOld!=p ){ +    sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, +                     strlen(pOld->zName)+1, pOld); +  } +  freeIndex(p); +} + +/* +** Unlink the given index from its table, then remove +** the index from the index hash table and free its memory +** structures. +*/ +void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ +  Index *pIndex; +  int len; + +  len = strlen(zIdxName); +  pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, 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){ +  HashElem *pElem; +  Hash temp1; +  Hash temp2; +  int i, j; + +  assert( iDb>=0 && iDb<db->nDb ); +  db->flags &= ~SQLITE_Initialized; +  for(i=iDb; i<db->nDb; i++){ +    Db *pDb = &db->aDb[i]; +    temp1 = pDb->tblHash; +    temp2 = pDb->trigHash; +    sqlite3HashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); +    sqlite3HashClear(&pDb->aFKey); +    sqlite3HashClear(&pDb->idxHash); +    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ +      Trigger *pTrigger = sqliteHashData(pElem); +      sqlite3DeleteTrigger(pTrigger); +    } +    sqlite3HashClear(&temp2); +    sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); +    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ +      Table *pTab = sqliteHashData(pElem); +      sqlite3DeleteTable(db, pTab); +    } +    sqlite3HashClear(&temp1); +    DbClearProperty(db, i, DB_SchemaLoaded); +    if( iDb>0 ) return; +  } +  assert( iDb==0 ); +  db->flags &= ~SQLITE_InternChanges; + +  /* If one or more of the auxiliary database files has been closed, +  ** then remove then 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; i<db->nDb; 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; i<db->nDb; i++){ +    struct Db *pDb = &db->aDb[i]; +    if( pDb->pBt==0 ){ +      sqliteFree(pDb->zName); +      pDb->zName = 0; +      continue; +    } +    if( j<i ){ +      db->aDb[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])); +    sqliteFree(db->aDb); +    db->aDb = db->aDbStatic; +  } +} + +/* +** This routine is called whenever a rollback occurs.  If there were +** schema changes during the transaction, then we have to reset the +** internal hash tables and reload them from disk. +*/ +void sqlite3RollbackInternalChanges(sqlite3 *db){ +  if( db->flags & SQLITE_InternChanges ){ +    sqlite3ResetInternalSchema(db, 0); +  } +} + +/* +** 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 ); +  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){ +    sqliteFree(pCol->zName); +    sqliteFree(pCol->zDflt); +    sqliteFree(pCol->zType); +  } +  sqliteFree(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. +** +** Indices associated with the table are unlinked from the "db" +** data structure if db!=NULL.  If db==NULL, indices attached to +** the table are deleted, but it is assumed they have already been +** unlinked. +*/ +void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ +  Index *pIndex, *pNext; +  FKey *pFKey, *pNextFKey; + +  if( pTable==0 ) return; + +  /* Delete all indices associated with this table +  */ +  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ +    pNext = pIndex->pNext; +    assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); +    sqliteDeleteIndex(db, pIndex); +  } + +  /* Delete all foreign keys associated with this table.  The keys +  ** should have already been unlinked from the db->aFKey hash table  +  */ +  for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ +    pNextFKey = pFKey->pNextFrom; +    assert( pTable->iDb<db->nDb ); +    assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, +                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); +    sqliteFree(pFKey); +  } + +  /* Delete the Table structure itself. +  */ +  sqliteResetColumnNames(pTable); +  sqliteFree(pTable->zName); +  sqliteFree(pTable->zColAff); +  sqlite3SelectDelete(pTable->pSelect); +  sqliteFree(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 && iDb<db->nDb ); +  assert( zTabName && zTabName[0] ); +  pDb = &db->aDb[iDb]; +  p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0); +  if( p ){ +    for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ +      int nTo = strlen(pF1->zTo) + 1; +      pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo); +      if( pF2==pF1 ){ +        sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo); +      }else{ +        while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } +        if( pF2 ){ +          pF2->pNextTo = pF1->pNextTo; +        } +      } +    } +    sqlite3DeleteTable(db, 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 really 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(Token *pName){ +  char *zName; +  if( pName ){ +    zName = sqliteStrNDup(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(Vdbe *v, int iDb){ +  sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); +  sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); +  sqlite3VdbeAddOp(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 findDb(sqlite3 *db, Token *pName){ +  int i; +  Db *pDb; +  for(pDb=db->aDb, i=0; i<db->nDb; i++, pDb++){ +    if( pName->n==strlen(pDb->zName) &&  +        0==sqlite3StrNICmp(pDb->zName, pName->z, pName->n) ){ +      return i; +    } +  } +  return -1; +} + +/* 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 = findDb(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 && 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 +** pStart token is the CREATE and pName is 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 *pStart,   /* The "CREATE" token */ +  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 */ +){ +  Table *pTable; +  Index *pIdx; +  char *zName; +  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( isTemp && iDb>1 ){ +    /* If creating a temp table, the name may not be qualified */ +    sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); +    pParse->nErr++; +    return; +  } +  if( isTemp ) iDb = 1; + +  pParse->sNameToken = *pName; +  zName = sqlite3NameFromToken(pName); +  if( zName==0 ) return; +  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ +    sqliteFree(zName); +    return; +  } +  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) ){ +      sqliteFree(zName); +      return; +    } +    if( isView ){ +      if( isTemp ){ +        code = SQLITE_CREATE_TEMP_VIEW; +      }else{ +        code = SQLITE_CREATE_VIEW; +      } +    }else{ +      if( isTemp ){ +        code = SQLITE_CREATE_TEMP_TABLE; +      }else{ +        code = SQLITE_CREATE_TABLE; +      } +    } +    if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ +      sqliteFree(zName); +      return; +    } +  } +#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. +  */ +  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return; +  pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); +  if( pTable ){ +    sqlite3ErrorMsg(pParse, "table %T already exists", pName); +    sqliteFree(zName); +    return; +  } +  if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 &&  +      ( iDb==0 || !db->init.busy) ){ +    sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); +    sqliteFree(zName); +    return; +  } +  pTable = sqliteMalloc( sizeof(Table) ); +  if( pTable==0 ){ +    pParse->rc = SQLITE_NOMEM; +    pParse->nErr++; +    sqliteFree(zName); +    return; +  } +  pTable->zName = zName; +  pTable->nCol = 0; +  pTable->aCol = 0; +  pTable->iPKey = -1; +  pTable->pIndex = 0; +  pTable->iDb = iDb; +  if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); +  pParse->pNewTable = pTable; + +  /* 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 ){ +    sqlite3BeginWriteOperation(pParse, 0, iDb); +    /* Every time a new table is created the file-format +    ** and encoding meta-values are set in the database, in +    ** case this is the first table created. +    */ +    sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); +    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); +    sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); +    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); + +    sqlite3OpenMasterTable(v, iDb); +    sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); +    sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +    sqlite3VdbeAddOp(v, OP_String8, 0, 0); +    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 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; +  z = sqlite3NameFromToken(pName); +  if( z==0 ) return; +  for(i=0; i<p->nCol; i++){ +    if( sqlite3StrICmp(z, p->aCol[i].zName)==0 ){ +      sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); +      sqliteFree(z); +      return; +    } +  } +  if( (p->nCol & 0x7)==0 ){ +    Column *aNew; +    aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); +    if( aNew==0 ) 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; +  pCol->pColl = pParse->db->pDfltColl; +  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; +} + +/* +** 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 *pFirst, Token *pLast){ +  Table *p; +  int i, j; +  int n; +  char *z, **pz; +  Column *pCol; +  if( (p = pParse->pNewTable)==0 ) return; +  i = p->nCol-1; +  if( i<0 ) return; +  pCol = &p->aCol[i]; +  pz = &pCol->zType; +  n = pLast->n + (pLast->z - pFirst->z); +  assert( pCol->zType==0 ); +  z = pCol->zType = sqlite3MPrintf("%.*s", n, pFirst->z); +  if( z==0 ) return; +  for(i=j=0; z[i]; i++){ +    int c = z[i]; +    if( isspace(c) ) continue; +    z[j++] = c; +  } +  z[j] = 0; +  pCol->affinity = sqlite3AffinityType(z, n); +} + +/* +** The given token is the default value for the last column added to +** the table currently under construction.  If "minusFlag" is true, it +** means the value token was preceded by a minus sign. +** +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. +*/ +void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){ +  Table *p; +  int i; +  char *z; +  if( (p = pParse->pNewTable)==0 ) return; +  i = p->nCol-1; +  if( i<0 ) return; +  assert( p->aCol[i].zDflt==0 ); +  z = p->aCol[i].zDflt = sqlite3MPrintf("%s%T", minusFlag ? "-" : "", pVal); +  sqlite3Dequote(z); +} + +/* +** 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 row id.  (Exception: +** For backwards compatibility with older databases, do not do this +** if the file format version number is less than 1.)  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, ExprList *pList, int onError){ +  Table *pTab = pParse->pNewTable; +  char *zType = 0; +  int iCol = -1, i; +  if( pTab==0 ) 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; i<pList->nExpr; i++){ +      for(iCol=0; iCol<pTab->nCol; iCol++){ +        if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ +          break; +        } +      } +      if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1; +    } +    if( pList->nExpr>1 ) iCol = -1; +  } +  if( iCol>=0 && iCol<pTab->nCol ){ +    zType = pTab->aCol[iCol].zType; +  } +  if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ +    pTab->iPKey = iCol; +    pTab->keyConf = onError; +  }else{ +    sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); +    pList = 0; +  } + +primary_key_exit: +  sqlite3ExprListDelete(pList); +  return; +} + +/* +** Set the collation function of the most recently parsed table column +** to the CollSeq given. +*/ +void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){ +  Table *p; +  Index *pIdx; +  CollSeq *pColl; +  int i; + +  if( (p = pParse->pNewTable)==0 ) return; +  i = p->nCol-1; + +  pColl = sqlite3LocateCollSeq(pParse, zType, nType); +  p->aCol[i].pColl = pColl; + +  /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", +  ** 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->keyInfo.aColl[0] = pColl; +  } +} + +/* +** 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 = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 ); +    if( pColl ){ +      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; +      sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); +    } +  } +  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. +*/ +CollSeq *sqlite3FindCollSeq( +  sqlite3 *db, +  u8 enc, +  const char *zName, +  int nName, +  int create +){ +  CollSeq *pColl = findCollSeqEntry(db, zName, nName, create); +  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); +  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); +  if( pColl ) pColl += enc-1; +  return pColl; +} + +/* +** 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 = sqliteStrNDup(zName, nName); +    if( !zExternal ) return; +    db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal); +    sqliteFree(zExternal); +  } +  if( db->xCollNeeded16 ){ +    char const *zExternal; +    sqlite3_value *pTmp = sqlite3GetTransientValue(db); +    sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); +    zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); +    if( !zExternal ) return; +    db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal); +  } +} + +/* +** 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(Parse *pParse, CollSeq *pColl){ +  CollSeq *pColl2; +  char *z = pColl->zName; +  int n = strlen(z); +  sqlite3 *db = pParse->db; +  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)); +      return SQLITE_OK; +    } +  } +  if( pParse->nErr==0 ){ +    sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", n, z); +  } +  pParse->nErr++; +  return SQLITE_ERROR; +} + +/* +** 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 && !pColl->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(pParse->db, pColl->zName, strlen(pColl->zName)); +    if( !pColl->xCmp && synthCollSeq(pParse, pColl) ){ +      return SQLITE_ERROR; +    } +  } +  return SQLITE_OK; +} + +/* +** Call sqlite3CheckCollSeq() for all collating sequences in an index, +** in order to verify that all the necessary collating sequences are +** loaded. +*/ +int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ +  if( pIdx ){ +    int i; +    for(i=0; i<pIdx->nColumn; i++){ +      if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){ +        return SQLITE_ERROR; +      } +    } +  } +  return SQLITE_OK; +} + +/* +** 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. +*/ +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ +  u8 enc = pParse->db->enc; +  u8 initbusy = pParse->db->init.busy; +  CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, initbusy); +  if( nName<0 ) nName = strlen(zName); +  if( !initbusy && (!pColl || !pColl->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(pParse->db, zName, nName); +    pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0); +    if( pColl && !pColl->xCmp ){ +      /* There may be a version of the collation sequence that requires +      ** translation between encodings. Search for it with synthCollSeq(). +      */ +      if( synthCollSeq(pParse, pColl) ){ +        return 0; +      } +    } +  } + +  /* If nothing has been found, write the error message into pParse */ +  if( !initbusy && (!pColl || !pColl->xCmp) ){ +    if( pParse->nErr==0 ){ +      sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); +    } +    pColl = 0; +  } +  return pColl; +} + + + +/* +** Scan the column type name zType (length nType) and return the +** associated affinity type. +*/ +char sqlite3AffinityType(const char *zType, int nType){ +  int n, i; +  static const struct { +    const char *zSub;  /* Keywords substring to search for */ +    char nSub;         /* length of zSub */ +    char affinity;     /* Affinity to return if it matches */ +  } substrings[] = { +    {"INT",  3, SQLITE_AFF_INTEGER}, +    {"CHAR", 4, SQLITE_AFF_TEXT}, +    {"CLOB", 4, SQLITE_AFF_TEXT}, +    {"TEXT", 4, SQLITE_AFF_TEXT}, +    {"BLOB", 4, SQLITE_AFF_NONE}, +  }; + +  if( nType==0 ){ +    return SQLITE_AFF_NONE; +  } +  for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){ +    int c1 = substrings[i].zSub[0]; +    int c2 = tolower(c1); +    int limit = nType - substrings[i].nSub; +    const char *z = substrings[i].zSub; +    for(n=0; n<=limit; n++){ +      int c = zType[n]; +      if( (c==c1 || c==c2) +             && 0==sqlite3StrNICmp(&zType[n], z, substrings[i].nSub) ){ +        return substrings[i].affinity; +      } +    } +  } +  return SQLITE_AFF_NUMERIC; +} + +/* +** 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(sqlite3 *db, Vdbe *v, int iDb){ +  sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].schema_cookie+1, 0); +  sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); +} + +/* +** 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(Table *p){ +  int i, k, n; +  char *zStmt; +  char *zSep, *zSep2, *zEnd, *z; +  Column *pCol; +  n = 0; +  for(pCol = p->aCol, i=0; i<p->nCol; 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 = sqliteMallocRaw( n ); +  if( zStmt==0 ) return 0; +  strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE "); +  k = strlen(zStmt); +  identPut(zStmt, &k, p->zName); +  zStmt[k++] = '('; +  for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){ +    strcpy(&zStmt[k], zSep); +    k += strlen(&zStmt[k]); +    zSep = zSep2; +    identPut(zStmt, &k, pCol->zName); +    if( (z = pCol->zType)!=0 ){ +      zStmt[k++] = ' '; +      strcpy(&zStmt[k], z); +      k += strlen(z); +    } +  } +  strcpy(&zStmt[k], 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 changes, 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, Token *pEnd, Select *pSelect){ +  Table *p; +  sqlite3 *db = pParse->db; + +  if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return; +  p = pParse->pNewTable; +  if( p==0 ) return; + +  assert( !db->init.busy || !pSelect ); + +  /* 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; + +    v = sqlite3GetVdbe(pParse); +    if( v==0 ) return; + +    if( p->pSelect==0 ){ +      /* A regular table */ +      sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); +    }else{ +      /* A view */ +      sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +    } + +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); + +    /* 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. +    */ +    if( pSelect ){ +      Table *pSelTab; +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); +      sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); +      pParse->nTab = 2; +      sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); +      sqlite3VdbeAddOp(v, OP_Close, 1, 0); +      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(0, pSelTab); +      } +    } +   +    sqlite3OpenMasterTable(v, p->iDb); + +    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view",P3_STATIC); +    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0); +    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0); +    sqlite3VdbeAddOp(v, OP_Pull, 3, 0); + +    if( pSelect ){ +      char *z = createTableStmt(p); +      n = z ? strlen(z) : 0; +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeChangeP3(v, -1, z, n); +      sqliteFree(z); +    }else{ +      if( p->pSelect ){ +        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE VIEW ", P3_STATIC); +      }else{ +        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE TABLE ", P3_STATIC); +      } +      assert( pEnd!=0 ); +      n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n); +      sqlite3VdbeAddOp(v, OP_Concat, 0, 0); +    } +    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); +    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); +    sqlite3ChangeCookie(db, v, p->iDb); +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); +    sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, +        sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); +  } + +  /* Add the table to the in-memory representation of the database. +  */ +  if( db->init.busy && pParse->nErr==0 ){ +    Table *pOld; +    FKey *pFKey;  +    Db *pDb = &db->aDb[p->iDb]; +    pOld = sqlite3HashInsert(&pDb->tblHash, p->zName, strlen(p->zName)+1, p); +    if( pOld ){ +      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */ +      return; +    } +    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ +      int nTo = strlen(pFKey->zTo) + 1; +      pFKey->pNextTo = sqlite3HashFind(&pDb->aFKey, pFKey->zTo, nTo); +      sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey); +    } +    pParse->pNewTable = 0; +    db->nTable++; +    db->flags |= SQLITE_InternChanges; +  } +} + +/* +** 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 */ +){ +  Table *p; +  int n; +  const unsigned char *z; +  Token sEnd; +  DbFixer sFix; +  Token *pName; + +  sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1); +  p = pParse->pNewTable; +  if( p==0 || pParse->nErr ){ +    sqlite3SelectDelete(pSelect); +    return; +  } +  sqlite3TwoPartName(pParse, pName1, pName2, &pName); +  if( sqlite3FixInit(&sFix, pParse, p->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(pSelect); +  sqlite3SelectDelete(pSelect); +  if( !pParse->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, &sEnd, 0); +  return; +} + +/* +** 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){ +  ExprList *pEList; +  Select *pSel; +  Table *pSelTab; +  int nErr = 0; + +  assert( pTable ); + +  /* 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; +  } + +  /* If we get this far, it means we need to compute the table names. +  */ +  assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */ +  pSel = pTable->pSelect; + +  /* Note that the call to sqlite3ResultSetOfSelect() will expand any +  ** "*" elements in this list.  But we will need to restore the list +  ** back to its original configuration afterwards, so we save a copy of +  ** the original in pEList. +  */ +  pEList = pSel->pEList; +  pSel->pEList = sqlite3ExprListDup(pEList); +  if( pSel->pEList==0 ){ +    pSel->pEList = pEList; +    return 1;  /* Malloc failed */ +  } +  pTable->nCol = -1; +  pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); +  if( pSelTab ){ +    assert( pTable->aCol==0 ); +    pTable->nCol = pSelTab->nCol; +    pTable->aCol = pSelTab->aCol; +    pSelTab->nCol = 0; +    pSelTab->aCol = 0; +    sqlite3DeleteTable(0, pSelTab); +    DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); +  }else{ +    pTable->nCol = 0; +    nErr++; +  } +  sqlite3SelectUnbind(pSel); +  sqlite3ExprListDelete(pSel->pEList); +  pSel->pEList = pEList; +  return nErr;   +} + +/* +** 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].tblHash); i; i=sqliteHashNext(i)){ +    Table *pTab = sqliteHashData(i); +    if( pTab->pSelect ){ +      sqliteResetColumnNames(pTab); +    } +  } +  DbClearProperty(db, idx, DB_UnresetViews); +} + +/* +** 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){ +  Table *pTab; +  Vdbe *v; +  int base; +  sqlite3 *db = pParse->db; +  int iDb; + +  if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table; +  assert( pName->nSrc==1 ); +  pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); + +  if( pTab==0 ) goto exit_drop_table; +  iDb = pTab->iDb; +  assert( iDb>=0 && iDb<db->nDb ); +#ifndef SQLITE_OMIT_AUTHORIZATION +  { +    int code; +    const char *zTab = SCHEMA_TABLE(pTab->iDb); +    const char *zDb = db->aDb[pTab->iDb].zName; +    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ +      goto exit_drop_table; +    } +    if( isView ){ +      if( iDb==1 ){ +        code = SQLITE_DROP_TEMP_VIEW; +      }else{ +        code = SQLITE_DROP_VIEW; +      } +    }else{ +      if( iDb==1 ){ +        code = SQLITE_DROP_TEMP_TABLE; +      }else{ +        code = SQLITE_DROP_TABLE; +      } +    } +    if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){ +      goto exit_drop_table; +    } +    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ +      goto exit_drop_table; +    } +  } +#endif +  if( pTab->readOnly ){ +    sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); +    pParse->nErr++; +    goto exit_drop_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; +  } + +  /* Generate code to remove the table from the master table +  ** on disk. +  */ +  v = sqlite3GetVdbe(pParse); +  if( v ){ +    static const VdbeOpList dropTable[] = { +      { OP_Rewind,     0, ADDR(13), 0}, +      { OP_String8,    0, 0,        0}, /* 1 */ +      { OP_MemStore,   1, 1,        0}, +      { OP_MemLoad,    1, 0,        0}, /* 3 */ +      { OP_Column,     0, 2,        0}, /* sqlite_master.tbl_name */ +      { OP_Ne,         0, ADDR(12), 0}, +      { OP_String8,    0, 0,        "trigger"}, +      { OP_Column,     0, 2,        0}, /* sqlite_master.type */ +      { OP_Eq,         0, ADDR(12), 0}, +      { OP_Delete,     0, 0,        0}, +      { OP_Rewind,     0, ADDR(13), 0}, +      { OP_Goto,       0, ADDR(3),  0}, +      { OP_Next,       0, ADDR(3),  0}, /* 12 */ +    }; +    Index *pIdx; +    Trigger *pTrigger; +    sqlite3BeginWriteOperation(pParse, 0, pTab->iDb); + +    /* 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->iDb==pTab->iDb || pTrigger->iDb==1 ); +      sqlite3DropTriggerPtr(pParse, pTrigger, 1); +      pTrigger = pTrigger->pNext; +    } + +    /* 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. +    */ +    sqlite3OpenMasterTable(v, pTab->iDb); +    base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); +    sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0); +    sqlite3ChangeCookie(db, v, pTab->iDb); +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); +    if( !isView ){ +      sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb); +      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +        sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); +      } +    } +    sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0); +  } +  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. */ +){ +  Table *p = pParse->pNewTable; +  int nByte; +  int i; +  int nCol; +  char *z; +  FKey *pFKey = 0; + +  assert( pTo!=0 ); +  if( p==0 || pParse->nErr ) 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; i<pToCol->nExpr; i++){ +      nByte += strlen(pToCol->a[i].zName) + 1; +    } +  } +  pFKey = sqliteMalloc( 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; i<nCol; i++){ +      int j; +      for(j=0; j<p->nCol; 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; i<nCol; i++){ +      int n = strlen(pToCol->a[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: +  sqliteFree(pFKey); +  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){ +  Table *pTab; +  FKey *pFKey; +  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; +  pFKey->isDeferred = isDeferred; +} + +/* +** Create a new index for an SQL table.  pIndex is the name of the index  +** and pTable 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 a CREATE TABLE statement */ +  Token *pEnd      /* The ")" that closes the CREATE INDEX statement */ +){ +  Table *pTab = 0; /* Table to be indexed */ +  Index *pIndex = 0; /* The index to be created */ +  char *zName = 0; +  int i, j; +  Token nullId;    /* Fake token for an empty ID list */ +  DbFixer sFix;    /* For assigning database names to pTable */ +  int isTemp;      /* True for a temporary index */ +  sqlite3 *db = pParse->db; + +  int iDb;          /* Index of the database that is being written */ +  Token *pName = 0; /* Unqualified name of the index to create */ + +  if( pParse->nErr || sqlite3_malloc_failed ) 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; + +    /* If the index name was unqualified, check if the the table +    ** is a temp table. If so, set the database to 1. +    */ +    pTab = sqlite3SrcListLookup(pParse, pTblName); +    if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){ +      iDb = 1; +    } + +    if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && +        sqlite3FixSrcList(&sFix, pTblName) +    ){ +      goto exit_create_index; +    } +    pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName,  +        pTblName->a[0].zDatabase); +    if( !pTab ) goto exit_create_index; +    assert( iDb==pTab->iDb ); +  }else{ +    assert( pName==0 ); +    pTab =  pParse->pNewTable; +    iDb = pTab->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; +  } +  if( pTab->pSelect ){ +    sqlite3ErrorMsg(pParse, "views may not be indexed"); +    goto exit_create_index; +  } +  isTemp = pTab->iDb==1; + +  /* +  ** 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(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 ){ +      Index *pISameName;    /* Another index with the same name */ +      Table *pTSameName;    /* A table with same name as the index */ +      if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; +      if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){ +        sqlite3ErrorMsg(pParse, "index %s already exists", zName); +        goto exit_create_index; +      } +      if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){ +        sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); +        goto exit_create_index; +      } +    } +  }else if( pName==0 ){ +    char zBuf[30]; +    int n; +    Index *pLoop; +    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} +    sprintf(zBuf,"_%d",n); +    zName = 0; +    sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0); +    if( zName==0 ) goto exit_create_index; +  } + +  /* Check for authorization to create an index. +  */ +#ifndef SQLITE_OMIT_AUTHORIZATION +  { +    const char *zDb = db->aDb[pTab->iDb].zName; +    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ +      goto exit_create_index; +    } +    i = SQLITE_CREATE_INDEX; +    if( isTemp ) 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 = pTab->aCol[pTab->nCol-1].zName; +    nullId.n = strlen(nullId.z); +    pList = sqlite3ExprListAppend(0, 0, &nullId); +    if( pList==0 ) goto exit_create_index; +  } + +  /*  +  ** Allocate the index structure.  +  */ +  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + +                        (sizeof(int) + sizeof(CollSeq*))*pList->nExpr ); +  if( pIndex==0 ) goto exit_create_index; +  pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr]; +  pIndex->zName = (char*)&pIndex->aiColumn[pList->nExpr]; +  strcpy(pIndex->zName, zName); +  pIndex->pTable = pTab; +  pIndex->nColumn = pList->nExpr; +  pIndex->onError = onError; +  pIndex->autoIndex = pName==0; +  pIndex->iDb = iDb; + +  /* 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; i<pList->nExpr; i++){ +    for(j=0; j<pTab->nCol; j++){ +      if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; +    } +    if( j>=pTab->nCol ){ +      sqlite3ErrorMsg(pParse, "table %s has no column named %s", +        pTab->zName, pList->a[i].zName); +      goto exit_create_index; +    } +    pIndex->aiColumn[i] = j; +    if( pList->a[i].pExpr ){ +      assert( pList->a[i].pExpr->pColl ); +      pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl; +    }else{ +      pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl; +    } +    assert( pIndex->keyInfo.aColl[i] ); +    if( !db->init.busy &&  +        sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i])  +    ){ +      goto exit_create_index; +    } +  } +  pIndex->keyInfo.nField = pList->nExpr; + +  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; k<pIdx->nColumn; k++){ +        if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; +        if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) 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(&db->aDb[pIndex->iDb].idxHash,  +                         pIndex->zName, strlen(pIndex->zName)+1, pIndex); +    if( p ){ +      assert( p==pIndex );  /* Malloc must have failed */ +      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 ){ +    int n; +    Vdbe *v; +    int lbl1, lbl2; + +    v = sqlite3GetVdbe(pParse); +    if( v==0 ) goto exit_create_index; +    if( pTblName!=0 ){ +      sqlite3BeginWriteOperation(pParse, 0, iDb); +      sqlite3OpenMasterTable(v, iDb); +    } +    sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); +    sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC); +    sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0); +    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); +    sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0); +    if( pTblName ){ +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); +      sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0, +                     (char*)&pIndex->keyInfo, P3_KEYINFO); +    } +    sqlite3VdbeAddOp(v, OP_String8, 0, 0); +    if( pStart && pEnd ){ +      if( onError==OE_None ){ +        sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", P3_STATIC); +      }else{ +        sqlite3VdbeChangeP3(v, -1, "CREATE UNIQUE INDEX ", P3_STATIC); +      } +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      n = Addr(pEnd->z) - Addr(pName->z) + 1; +      sqlite3VdbeChangeP3(v, -1, pName->z, n); +      sqlite3VdbeAddOp(v, OP_Concat, 0, 0); +    } +    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); +    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); +    if( pTblName ){ +      sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); +      sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum); +      /* VdbeComment((v, "%s", pTab->zName)); */ +      sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol); +      lbl2 = sqlite3VdbeMakeLabel(v); +      sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2); +      lbl1 = sqlite3VdbeCurrentAddr(v); +      sqlite3GenerateIndexKey(v, pIndex, 2); +      sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, +                      "indexed columns are not unique", P3_STATIC); +      sqlite3VdbeAddOp(v, OP_Next, 2, lbl1); +      sqlite3VdbeResolveLabel(v, lbl2); +      sqlite3VdbeAddOp(v, OP_Close, 2, 0); +      sqlite3VdbeAddOp(v, OP_Close, 1, 0); +      sqlite3ChangeCookie(db, v, iDb); +      sqlite3VdbeAddOp(v, OP_Close, 0, 0); +      sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, +         sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC); +    } +  } + +  /* 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); +  sqliteFree(zName); +  return; +} + +/* +** This routine will drop an existing named index.  This routine +** implements the DROP INDEX statement. +*/ +void sqlite3DropIndex(Parse *pParse, SrcList *pName){ +  Index *pIndex; +  Vdbe *v; +  sqlite3 *db = pParse->db; + +  if( pParse->nErr || sqlite3_malloc_failed ) return; +  assert( pName->nSrc==1 ); +  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return; +  pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); +  if( pIndex==0 ){ +    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; +  } +#ifndef SQLITE_OMIT_AUTHORIZATION +  { +    int code = SQLITE_DROP_INDEX; +    Table *pTab = pIndex->pTable; +    const char *zDb = db->aDb[pIndex->iDb].zName; +    const char *zTab = SCHEMA_TABLE(pIndex->iDb); +    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ +      goto exit_drop_index; +    } +    if( pIndex->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 ){ +    static const VdbeOpList dropIndex[] = { +      { OP_Rewind,     0, ADDR(9), 0},  +      { OP_String8,    0, 0,       0}, /* 1 */ +      { OP_MemStore,   1, 1,       0}, +      { OP_MemLoad,    1, 0,       0}, /* 3 */ +      { OP_Column,     0, 1,       0}, +      { OP_Eq,         0, ADDR(8), 0}, +      { OP_Next,       0, ADDR(3), 0}, +      { OP_Goto,       0, ADDR(9), 0}, +      { OP_Delete,     0, 0,       0}, /* 8 */ +    }; +    int base; + +    sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb); +    sqlite3OpenMasterTable(v, pIndex->iDb); +    base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); +    sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); +    sqlite3ChangeCookie(db, v, pIndex->iDb); +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); +    sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); +    sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0); +  } + +exit_drop_index: +  sqlite3SrcListDelete(pName); +} + +/* +** 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(IdList *pList, Token *pToken){ +  if( pList==0 ){ +    pList = sqliteMalloc( sizeof(IdList) ); +    if( pList==0 ) return 0; +    pList->nAlloc = 0; +  } +  if( pList->nId>=pList->nAlloc ){ +    struct IdList_item *a; +    pList->nAlloc = pList->nAlloc*2 + 5; +    a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); +    if( a==0 ){ +      sqlite3IdListDelete(pList); +      return 0; +    } +    pList->a = a; +  } +  memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); +  pList->a[pList->nId].zName = sqlite3NameFromToken(pToken); +  pList->nId++; +  return pList; +} + +/* +** 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(A,B,0); +** +** Then B is a table name and the database name is unspecified.  If called +** like this: +** +**         sqlite3SrcListAppend(A,B,C); +** +** Then C is the table name and B is the database name. +*/ +SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ +  struct SrcList_item *pItem; +  if( pList==0 ){ +    pList = sqliteMalloc( sizeof(SrcList) ); +    if( pList==0 ) return 0; +    pList->nAlloc = 1; +  } +  if( pList->nSrc>=pList->nAlloc ){ +    SrcList *pNew; +    pList->nAlloc *= 2; +    pNew = sqliteRealloc(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(pTable); +  pItem->zDatabase = sqlite3NameFromToken(pDatabase); +  pItem->iCursor = -1; +  pList->nSrc++; +  return pList; +} + +/* +** Assign cursors to all tables in a SrcList +*/ +void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ +  int i; +  for(i=0; i<pList->nSrc; i++){ +    if( pList->a[i].iCursor<0 ){ +      pList->a[i].iCursor = pParse->nTab++; +    } +  } +} + +/* +** Add an alias to the last identifier on the given identifier list. +*/ +void sqlite3SrcListAddAlias(SrcList *pList, Token *pToken){ +  if( pList && pList->nSrc>0 ){ +    pList->a[pList->nSrc-1].zAlias = sqlite3NameFromToken(pToken); +  } +} + +/* +** Delete an IdList. +*/ +void sqlite3IdListDelete(IdList *pList){ +  int i; +  if( pList==0 ) return; +  for(i=0; i<pList->nId; i++){ +    sqliteFree(pList->a[i].zName); +  } +  sqliteFree(pList->a); +  sqliteFree(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; i<pList->nId; i++){ +    if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; +  } +  return -1; +} + +/* +** 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; i<pList->nSrc; i++, pItem++){ +    sqliteFree(pItem->zDatabase); +    sqliteFree(pItem->zName); +    sqliteFree(pItem->zAlias); +    if( pItem->pTab && pItem->pTab->isTransient ){ +      sqlite3DeleteTable(0, pItem->pTab); +    } +    sqlite3SelectDelete(pItem->pSelect); +    sqlite3ExprDelete(pItem->pOn); +    sqlite3IdListDelete(pItem->pUsing); +  } +  sqliteFree(pList); +} + +/* +** 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 || sqlite3_malloc_failed ) return; +  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; + +  v = sqlite3GetVdbe(pParse); +  if( !v ) return; +  if( type!=TK_DEFERRED ){ +    for(i=0; i<db->nDb; i++){ +      sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); +    } +  } +  sqlite3VdbeAddOp(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 || sqlite3_malloc_failed ) return; +  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; + +  v = sqlite3GetVdbe(pParse); +  if( v ){ +    sqlite3VdbeAddOp(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 || sqlite3_malloc_failed ) return; +  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; + +  v = sqlite3GetVdbe(pParse); +  if( v ){ +    sqlite3VdbeAddOp(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. +*/ +static int sqlite3OpenTempDatabase(Parse *pParse){ +  sqlite3 *db = pParse->db; +  if( db->aDb[1].pBt==0 && !pParse->explain ){ +    int rc = sqlite3BtreeFactory(db, 0, 0, MAX_PAGES, &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; +    } +    if( db->flags & !db->autoCommit ){ +      rc = sqlite3BtreeBeginTrans(db->aDb[1].pBt, 1); +      if( rc!=SQLITE_OK ){ +        sqlite3ErrorMsg(pParse, "unable to get a write lock on " +          "the temporary database file"); +        pParse->rc = rc; +        return 1; +      } +    } +  } +  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 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0)+1; +  } +  if( iDb>=0 ){ +    assert( iDb<db->nDb ); +    assert( db->aDb[iDb].pBt!=0 || iDb==1 ); +    assert( iDb<32 ); +    mask = 1<<iDb; +    if( (pParse->cookieMask & mask)==0 ){ +      pParse->cookieMask |= mask; +      pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie; +      if( 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<<iDb; +  if( setStatement ){ +    sqlite3VdbeAddOp(v, OP_Statement, iDb, 0); +  } +  if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){ +    sqlite3BeginWriteOperation(pParse, setStatement, 1); +  } +} + +/*  +** Return the transient sqlite3_value object used for encoding conversions +** during SQL compilation. +*/ +sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){ +  if( !db->pValue ){ +    db->pValue = sqlite3ValueNew(); +  } +  return db->pValue; +} diff --git a/ext/pdo_sqlite/sqlite/src/date.c b/ext/pdo_sqlite/sqlite/src/date.c new file mode 100644 index 0000000000..634e81d5ed --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/date.c @@ -0,0 +1,893 @@ +/* +** 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$ +** +** NOTES: +** +** 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 "os.h" +#include <ctype.h> +#include <stdlib.h> +#include <assert.h> +#include <time.h> + +#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) ){ +        return cnt; +      } +      val = val*10 + *zDate - '0'; +      zDate++; +    } +    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ +      return cnt; +    } +    *pVal = val; +    zDate++; +    cnt++; +  }while( nextC ); +  return cnt; +} + +/* +** Read text from z[] and convert into a floating point number.  Return +** the number of digits converted. +*/ +static int getValue(const char *z, double *pR){ +  const char *zEnd; +  *pR = sqlite3AtoF(z, &zEnd); +  return zEnd - z; +} + +/* +** 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; +  p->validYMD = 0; +  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->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) ){ 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(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; +    if( sqlite3OsCurrentTime(&r)==0 ){ +      p->rJD = r; +      p->validJD = 1; +      return 0; +    } +    return 1; +  }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ +    p->rJD = sqlite3AtoF(zDate, 0); +    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; +  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; +  struct tm *pTm; +  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; +  sqlite3OsEnterMutex(); +  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; +  sqlite3OsLeaveMutex(); +  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; n<sizeof(zBuf)-1 && zMod[n]; n++){ +    z[n] = tolower(zMod[n]); +  } +  z[n] = 0; +  switch( z[0] ){ +    case 'l': { +      /*    localtime +      ** +      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to +      ** show local time. +      */ +      if( strcmp(z, "localtime")==0 ){ +        computeJD(p); +        p->rJD += 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); +      if( n<=0 ) break; +      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. +*/ +static int isDate(int argc, sqlite3_value **argv, DateTime *p){ +  int i; +  if( argc==0 ) return 1; +  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ||  +      parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1; +  for(i=1; i<argc; i++){ +    if( SQLITE_NULL==sqlite3_value_type(argv[i]) ||  +        parseModifier(sqlite3_value_text(argv[i]), p) ) return 1; +  } +  return 0; +} + + +/* +** The following routines implement the various date and time functions +** of SQLite. +*/ + +/* +**    julianday( TIMESTRING, MOD, MOD, ...) +** +** Return the julian day number of the date specified in the arguments +*/ +static void juliandayFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  DateTime x; +  if( isDate(argc, argv, &x)==0 ){ +    computeJD(&x); +    sqlite3_result_double(context, x.rJD); +  } +} + +/* +**    datetime( TIMESTRING, MOD, MOD, ...) +** +** Return YYYY-MM-DD HH:MM:SS +*/ +static void datetimeFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  DateTime x; +  if( isDate(argc, argv, &x)==0 ){ +    char zBuf[100]; +    computeYMD_HMS(&x); +    sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m, +           (int)(x.s)); +    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +  } +} + +/* +**    time( TIMESTRING, MOD, MOD, ...) +** +** Return HH:MM:SS +*/ +static void timeFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  DateTime x; +  if( isDate(argc, argv, &x)==0 ){ +    char zBuf[100]; +    computeHMS(&x); +    sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); +    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +  } +} + +/* +**    date( TIMESTRING, MOD, MOD, ...) +** +** Return YYYY-MM-DD +*/ +static void dateFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  DateTime x; +  if( isDate(argc, argv, &x)==0 ){ +    char zBuf[100]; +    computeYMD(&x); +    sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); +    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +  } +} + +/* +**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...) +** +** Return a string described by FORMAT.  Conversions as follows: +** +**   %d  day of month +**   %f  ** fractional seconds  SS.SSS +**   %H  hour 00-24 +**   %j  day of year 000-366 +**   %J  ** Julian day number +**   %m  month 01-12 +**   %M  minute 00-59 +**   %s  seconds since 1970-01-01 +**   %S  seconds 00-59 +**   %w  day of week 0-6  sunday==0 +**   %W  week of year 00-53 +**   %Y  year 0000-9999 +**   %%  % +*/ +static void strftimeFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  DateTime x; +  int n, i, j; +  char *z; +  const char *zFmt = sqlite3_value_text(argv[0]); +  char zBuf[100]; +  if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return; +  for(i=0, n=1; zFmt[i]; i++, n++){ +    if( zFmt[i]=='%' ){ +      switch( zFmt[i+1] ){ +        case 'd': +        case 'H': +        case 'm': +        case 'M': +        case 'S': +        case 'W': +          n++; +          /* fall thru */ +        case 'w': +        case '%': +          break; +        case 'f': +          n += 8; +          break; +        case 'j': +          n += 3; +          break; +        case 'Y': +          n += 8; +          break; +        case 's': +        case 'J': +          n += 50; +          break; +        default: +          return;  /* ERROR.  return a NULL */ +      } +      i++; +    } +  } +  if( n<sizeof(zBuf) ){ +    z = zBuf; +  }else{ +    z = sqliteMalloc( n ); +    if( z==0 ) 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':  sprintf(&z[j],"%02d",x.D); j+=2; break; +        case 'f': { +          int s = x.s; +          int ms = (x.s - s)*1000.0; +          sprintf(&z[j],"%02d.%03d",s,ms); +          j += strlen(&z[j]); +          break; +        } +        case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break; +        case 'W': /* Fall thru */ +        case 'j': { +          int n;             /* Number of days since 1st day of year */ +          DateTime y = x; +          y.validJD = 0; +          y.M = 1; +          y.D = 1; +          computeJD(&y); +          n = x.rJD - y.rJD; +          if( zFmt[i]=='W' ){ +            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */ +            wd = ((int)(x.rJD+0.5)) % 7; +            sprintf(&z[j],"%02d",(n+7-wd)/7); +            j += 2; +          }else{ +            sprintf(&z[j],"%03d",n+1); +            j += 3; +          } +          break; +        } +        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break; +        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break; +        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break; +        case 's': { +          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5)); +          j += strlen(&z[j]); +          break; +        } +        case 'S':  sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break; +        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break; +        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break; +        case '%':  z[j++] = '%'; break; +      } +    } +  } +  z[j] = 0; +  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); +  if( z!=zBuf ){ +    sqliteFree(z); +  } +} + + +#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ + +/* +** 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    }, +  }; +  int i; + +  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ +    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, +        SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); +  } +#endif +} diff --git a/ext/pdo_sqlite/sqlite/src/delete.c b/ext/pdo_sqlite/sqlite/src/delete.c new file mode 100644 index 0000000000..866da61d92 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/delete.c @@ -0,0 +1,419 @@ +/* +** 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 DELETE FROM statements. +** +** $Id$ +*/ +#include "sqliteInt.h" + +/* +** Look up every table that is named in pSrc.  If any table is not found, +** add an error message to pParse->zErrMsg 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; i<pSrc->nSrc; i++, pItem++){ +    pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); +    pItem->pTab = pTab; +  } +  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 ){ +    sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); +    return 1; +  } +  if( !viewOk && pTab->pSelect ){ +    sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); +    return 1; +  } +  return 0; +} + +/* +** Generate code that will open a table for reading. +*/ +void sqlite3OpenTableForReading( +  Vdbe *v,        /* Generate code into this VDBE */ +  int iCur,       /* The cursor number of the table */ +  Table *pTab     /* The table to be opened */ +){ +  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); +  sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); +  VdbeComment((v, "# %s", pTab->zName)); +  sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); +} + + +/* +** Process a DELETE FROM statement. +*/ +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 */ +  int isView;            /* True if attempting to delete from a view */ +  AuthContext sContext;  /* Authorization context */ + +  int row_triggers_exist = 0;  /* True if any triggers exist */ +  int before_triggers;         /* True if there are BEFORE triggers */ +  int after_triggers;          /* True if there are AFTER triggers */ +  int oldIdx = -1;             /* Cursor for the OLD table of AFTER triggers */ + +  sContext.pParse = 0; +  if( pParse->nErr || sqlite3_malloc_failed ){ +    pTabList = 0; +    goto delete_from_cleanup; +  } +  db = pParse->db; +  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; +  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,  +                         TK_DELETE, TK_BEFORE, TK_ROW, 0); +  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,  +                         TK_DELETE, TK_AFTER, TK_ROW, 0); +  row_triggers_exist = before_triggers || after_triggers; +  isView = pTab->pSelect!=0; +  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ +    goto delete_from_cleanup; +  } +  assert( pTab->iDb<db->nDb ); +  zDb = db->aDb[pTab->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( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ +    goto delete_from_cleanup; +  } + +  /* Allocate a cursor used to store the old.* data for a trigger. +  */ +  if( row_triggers_exist ){  +    oldIdx = pParse->nTab++; +  } + +  /* Resolve the column names in all the expressions. +  */ +  assert( pTabList->nSrc==1 ); +  iCur = pTabList->a[0].iCursor = pParse->nTab++; +  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ +    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; +  } +  sqlite3VdbeCountChanges(v); +  sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); + +  /* If we are trying to delete from a view, construct that view into +  ** a temporary table. +  */ +  if( isView ){ +    Select *pView = sqlite3SelectDup(pTab->pSelect); +    sqlite3Select(pParse, pView, SRT_TempTable, iCur, 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 ){ +    sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +  } + +  /* 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 && !row_triggers_exist ){ +    if( db->flags & SQLITE_CountRows ){ +      /* If counting rows deleted, just count the total number of +      ** entries in the table. */ +      int endOfLoop = sqlite3VdbeMakeLabel(v); +      int addr; +      if( !isView ){ +        sqlite3OpenTableForReading(v, iCur, pTab); +      } +      sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); +      addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); +      sqlite3VdbeAddOp(v, OP_Next, iCur, addr); +      sqlite3VdbeResolveLabel(v, endOfLoop); +      sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +    } +    if( !isView ){ +      sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); +      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +        sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); +      } +    } +  } + +  /* The usual case: There is a WHERE clause so we have to scan through +  ** the table and pick which records to delete. +  */ +  else{ +    /* Ensure all required collation sequences are available. */ +    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +      if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ +        goto delete_from_cleanup; +      } +    } + +    /* Begin the database scan +    */ +    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0); +    if( pWInfo==0 ) goto delete_from_cleanup; + +    /* Remember the key of every item to be deleted. +    */ +    sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); +    if( db->flags & SQLITE_CountRows ){ +      sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); +    } + +    /* End the database scan loop. +    */ +    sqlite3WhereEnd(pWInfo); + +    /* Open the pseudo-table used to store OLD if there are triggers. +    */ +    if( row_triggers_exist ){ +      sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); +      sqlite3VdbeAddOp(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. +    */ +    sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); +    end = sqlite3VdbeMakeLabel(v); + +    /* This is the beginning of the delete loop when there are +    ** row triggers. +    */ +    if( row_triggers_exist ){ +      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      if( !isView ){ +        sqlite3OpenTableForReading(v, iCur, pTab); +      } +      sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); +      sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); +      sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); +      sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0); +      if( !isView ){ +        sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +      } + +      sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,  +          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, +	  addr); +    } + +    if( !isView ){ +      /* Open cursors for the table we are deleting from and all its +      ** indices.  If there are row triggers, this happens inside the +      ** OP_ListRead loop because the cursor have to all be closed +      ** before the trigger fires.  If there are no row triggers, the +      ** cursors are opened only once on the outside the loop. +      */ +      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); + +      /* This is the beginning of the delete loop when there are no +      ** row triggers */ +      if( !row_triggers_exist ){  +        addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); +      } + +      /* Delete the row */ +      sqlite3GenerateRowDelete(db, v, pTab, iCur, 1); +    } + +    /* If there are row triggers, close all cursors then invoke +    ** the AFTER triggers +    */ +    if( row_triggers_exist ){ +      if( !isView ){ +        for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ +          sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); +        } +        sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +      } +      sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,  +          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, +	  addr); +    } + +    /* End of the delete loop */ +    sqlite3VdbeAddOp(v, OP_Goto, 0, addr); +    sqlite3VdbeResolveLabel(v, end); +    sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); + +    /* Close the cursors after the loop if there are no row triggers */ +    if( !row_triggers_exist ){ +      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ +        sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); +      } +      sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +    } +  } + +  /* +  ** Return the number of rows that were deleted. +  */ +  if( db->flags & SQLITE_CountRows ){ +    sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +    sqlite3VdbeSetNumCols(v, 1); +    sqlite3VdbeSetColName(v, 0, "rows deleted", P3_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 on the top +**       of the stack. +** +** 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( +  sqlite3 *db,       /* The database containing the index */ +  Vdbe *v,           /* Generate code into this VDBE */ +  Table *pTab,       /* Table containing the row to be deleted */ +  int iCur,          /* Cursor number for the table */ +  int count          /* Increment the row change counter */ +){ +  int addr; +  addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); +  sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); +  sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); +  sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); +} + +/* +** 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( +  sqlite3 *db,       /* The database containing the index */ +  Vdbe *v,           /* Generate code into this VDBE */ +  Table *pTab,       /* Table containing the row to be deleted */ +  int iCur,          /* Cursor number for the table */ +  char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ +){ +  int i; +  Index *pIdx; + +  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ +    if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; +    sqlite3GenerateIndexKey(v, pIdx, iCur); +    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0); +  } +} + +/* +** 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. +*/ +void sqlite3GenerateIndexKey( +  Vdbe *v,           /* Generate code into this VDBE */ +  Index *pIdx,       /* The index for which to generate a key */ +  int iCur           /* Cursor number for the pIdx->pTable table */ +){ +  int j; +  Table *pTab = pIdx->pTable; + +  sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); +  for(j=0; j<pIdx->nColumn; j++){ +    int idx = pIdx->aiColumn[j]; +    if( idx==pTab->iPKey ){ +      sqlite3VdbeAddOp(v, OP_Dup, j, 0); +    }else{ +      sqlite3VdbeAddOp(v, OP_Column, iCur, idx); +    } +  } +  sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24)); +  sqlite3IndexAffinityStr(v, pIdx); +} diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c new file mode 100644 index 0000000000..2da3645b9b --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/expr.c @@ -0,0 +1,1927 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* +** 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){ +  if( pExpr->op==TK_AS ){ +    return sqlite3ExprAffinity(pExpr->pLeft); +  } +  if( pExpr->op==TK_SELECT ){ +    return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); +  } +  return pExpr->affinity; +} + +/* +** 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 ){ +    pColl = pExpr->pColl; +    if( pExpr->op==TK_AS && !pColl ){ +      return sqlite3ExprCollSeq(pParse, pExpr->pLeft); +    } +  } +  if( sqlite3CheckCollSeq(pParse, pColl) ){  +    pColl = 0; +  } +  return pColl; +} + +/* +** pExpr is the left operand of a comparison operator.  aff2 is the +** type affinity of the right 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 or +    ** integer affinity, use that. Otherwise use no affinity. +    */ +    if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ +      return SQLITE_AFF_INTEGER; +    }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ +      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_NUMERIC;  // Ticket #805 */ +    return SQLITE_AFF_NONE; +  }else{ +    /* One side is a column, the other is not. Use the columns affinity. */ +    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_NUMERIC; +  } +  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); +  return  +    (aff==SQLITE_AFF_NONE) || +    (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || +    (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || +    (aff==idx_affinity); +} + +/* +** Return the P1 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +** If jumpIfNull is true, then set the low byte of the returned +** P1 value to tell the opcode to jump if either expression +** evaluates to NULL. +*/ +static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ +  char aff = sqlite3ExprAffinity(pExpr2); +  return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0); +} + +/* +** 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. +*/ +static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){ +  CollSeq *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 dest,         /* Jump here if true.  */ +  int jumpIfNull    /* If true, jump if either operand is NULL */ +){ +  int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull); +  CollSeq *p3 = binaryCompareCollSeq(pParse, pLeft, pRight); +  return sqlite3VdbeOp3(pParse->pVdbe, opcode, p1, dest, (void*)p3, P3_COLLSEQ); +} + +/* +** Construct a new expression node and return a pointer to it.  Memory +** for this node is obtained from sqliteMalloc().  The calling function +** is responsible for making sure the node eventually gets freed. +*/ +Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){ +  Expr *pNew; +  pNew = sqliteMalloc( sizeof(Expr) ); +  if( pNew==0 ){ +    /* When malloc fails, we leak memory from pLeft and pRight */ +    return 0; +  } +  pNew->op = op; +  pNew->pLeft = pLeft; +  pNew->pRight = pRight; +  if( pToken ){ +    assert( pToken->dyn==0 ); +    pNew->span = pNew->token = *pToken; +  }else if( pLeft && pRight ){ +    sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); +  } +  return pNew; +} + +/* +** Join two expressions using an AND operator.  If either expression is +** NULL, then just return the other expression. +*/ +Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){ +  if( pLeft==0 ){ +    return pRight; +  }else if( pRight==0 ){ +    return pLeft; +  }else{ +    return sqlite3Expr(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( !sqlite3_malloc_failed && 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 + Addr(pRight->z) - Addr(pLeft->z); +    }else{ +      pExpr->span.z = 0; +    } +  } +} + +/* +** Construct a new expression node for a function with multiple +** arguments. +*/ +Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ +  Expr *pNew; +  pNew = sqliteMalloc( sizeof(Expr) ); +  if( pNew==0 ){ +    /* sqlite3ExprListDelete(pList); // Leak pList when malloc fails */ +    return 0; +  } +  pNew->op = TK_FUNCTION; +  pNew->pList = pList; +  if( pToken ){ +    assert( pToken->dyn==0 ); +    pNew->token = *pToken; +  }else{ +    pNew->token.z = 0; +  } +  pNew->span = pNew->token; +  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; +  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(&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; i<pParse->nVarExpr; 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 = sqliteRealloc(pParse->apVarExpr, +                       pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); +      } +      if( !sqlite3_malloc_failed ){ +        assert( pParse->apVarExpr!=0 ); +        pParse->apVarExpr[pParse->nVarExpr++] = pExpr; +      } +    } +  }  +} + +/* +** Recursively delete an expression tree. +*/ +void sqlite3ExprDelete(Expr *p){ +  if( p==0 ) return; +  if( p->span.dyn ) sqliteFree((char*)p->span.z); +  if( p->token.dyn ) sqliteFree((char*)p->token.z); +  sqlite3ExprDelete(p->pLeft); +  sqlite3ExprDelete(p->pRight); +  sqlite3ExprListDelete(p->pList); +  sqlite3SelectDelete(p->pSelect); +  sqliteFree(p); +} + + +/* +** 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(Expr *p){ +  Expr *pNew; +  if( p==0 ) return 0; +  pNew = sqliteMallocRaw( sizeof(*p) ); +  if( pNew==0 ) return 0; +  memcpy(pNew, p, sizeof(*pNew)); +  if( p->token.z!=0 ){ +    pNew->token.z = sqliteStrDup(p->token.z); +    pNew->token.dyn = 1; +  }else{ +    assert( pNew->token.z==0 ); +  } +  pNew->span.z = 0; +  pNew->pLeft = sqlite3ExprDup(p->pLeft); +  pNew->pRight = sqlite3ExprDup(p->pRight); +  pNew->pList = sqlite3ExprListDup(p->pList); +  pNew->pSelect = sqlite3SelectDup(p->pSelect); +  return pNew; +} +void sqlite3TokenCopy(Token *pTo, Token *pFrom){ +  if( pTo->dyn ) sqliteFree((char*)pTo->z); +  if( pFrom->z ){ +    pTo->n = pFrom->n; +    pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); +    pTo->dyn = 1; +  }else{ +    pTo->z = 0; +  } +} +ExprList *sqlite3ExprListDup(ExprList *p){ +  ExprList *pNew; +  struct ExprList_item *pItem, *pOldItem; +  int i; +  if( p==0 ) return 0; +  pNew = sqliteMalloc( sizeof(*pNew) ); +  if( pNew==0 ) return 0; +  pNew->nExpr = pNew->nAlloc = p->nExpr; +  pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); +  if( pItem==0 ){ +    sqliteFree(pNew); +    return 0; +  }  +  pOldItem = p->a; +  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ +    Expr *pNewExpr, *pOldExpr; +    pItem->pExpr = pNewExpr = sqlite3ExprDup(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(&pNewExpr->span, &pOldExpr->span); +    } +    assert( pNewExpr==0 || pNewExpr->span.z!=0  +            || pOldExpr->span.z==0 || sqlite3_malloc_failed ); +    pItem->zName = sqliteStrDup(pOldItem->zName); +    pItem->sortOrder = pOldItem->sortOrder; +    pItem->isAgg = pOldItem->isAgg; +    pItem->done = 0; +  } +  return pNew; +} +SrcList *sqlite3SrcListDup(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 = sqliteMallocRaw( nByte ); +  if( pNew==0 ) return 0; +  pNew->nSrc = pNew->nAlloc = p->nSrc; +  for(i=0; i<p->nSrc; i++){ +    struct SrcList_item *pNewItem = &pNew->a[i]; +    struct SrcList_item *pOldItem = &p->a[i]; +    pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); +    pNewItem->zName = sqliteStrDup(pOldItem->zName); +    pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); +    pNewItem->jointype = pOldItem->jointype; +    pNewItem->iCursor = pOldItem->iCursor; +    pNewItem->pTab = 0; +    pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); +    pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); +    pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing); +  } +  return pNew; +} +IdList *sqlite3IdListDup(IdList *p){ +  IdList *pNew; +  int i; +  if( p==0 ) return 0; +  pNew = sqliteMallocRaw( sizeof(*pNew) ); +  if( pNew==0 ) return 0; +  pNew->nId = pNew->nAlloc = p->nId; +  pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); +  if( pNew->a==0 ) return 0; +  for(i=0; i<p->nId; i++){ +    struct IdList_item *pNewItem = &pNew->a[i]; +    struct IdList_item *pOldItem = &p->a[i]; +    pNewItem->zName = sqliteStrDup(pOldItem->zName); +    pNewItem->idx = pOldItem->idx; +  } +  return pNew; +} +Select *sqlite3SelectDup(Select *p){ +  Select *pNew; +  if( p==0 ) return 0; +  pNew = sqliteMallocRaw( sizeof(*p) ); +  if( pNew==0 ) return 0; +  pNew->isDistinct = p->isDistinct; +  pNew->pEList = sqlite3ExprListDup(p->pEList); +  pNew->pSrc = sqlite3SrcListDup(p->pSrc); +  pNew->pWhere = sqlite3ExprDup(p->pWhere); +  pNew->pGroupBy = sqlite3ExprListDup(p->pGroupBy); +  pNew->pHaving = sqlite3ExprDup(p->pHaving); +  pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy); +  pNew->op = p->op; +  pNew->pPrior = sqlite3SelectDup(p->pPrior); +  pNew->nLimit = p->nLimit; +  pNew->nOffset = p->nOffset; +  pNew->zSelect = 0; +  pNew->iLimit = -1; +  pNew->iOffset = -1; +  pNew->ppOpenTemp = 0; +  return pNew; +} + + +/* +** Add a new element to the end of an expression list.  If pList is +** initially NULL, then create a new expression list. +*/ +ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ +  if( pList==0 ){ +    pList = sqliteMalloc( sizeof(ExprList) ); +    if( pList==0 ){ +      /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ +      return 0; +    } +    assert( pList->nAlloc==0 ); +  } +  if( pList->nAlloc<=pList->nExpr ){ +    pList->nAlloc = pList->nAlloc*2 + 4; +    pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); +    if( pList->a==0 ){ +      /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ +      pList->nExpr = pList->nAlloc = 0; +      return pList; +    } +  } +  assert( pList->a!=0 ); +  if( pExpr || pName ){ +    struct ExprList_item *pItem = &pList->a[pList->nExpr++]; +    memset(pItem, 0, sizeof(*pItem)); +    pItem->pExpr = pExpr; +    pItem->zName = sqlite3NameFromToken(pName); +  } +  return pList; +} + +/* +** 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; i<pList->nExpr; i++, pItem++){ +    sqlite3ExprDelete(pItem->pExpr); +    sqliteFree(pItem->zName); +  } +  sqliteFree(pList->a); +  sqliteFree(pList); +} + +/* +** Walk an expression tree.  Return 1 if the expression is constant +** and 0 if it involves 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 sqlite3ExprIsConstant(Expr *p){ +  switch( p->op ){ +    case TK_ID: +    case TK_COLUMN: +    case TK_DOT: +    case TK_FUNCTION: +      return 0; +    case TK_NULL: +    case TK_STRING: +    case TK_BLOB: +    case TK_INTEGER: +    case TK_FLOAT: +    case TK_VARIABLE: +      return 1; +    default: { +      if( p->pLeft && !sqlite3ExprIsConstant(p->pLeft) ) return 0; +      if( p->pRight && !sqlite3ExprIsConstant(p->pRight) ) return 0; +      if( p->pList ){ +        int i; +        for(i=0; i<p->pList->nExpr; i++){ +          if( !sqlite3ExprIsConstant(p->pList->a[i].pExpr) ) return 0; +        } +      } +      return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); +    } +  } +  return 0; +} + +/* +** If the given expression 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(p->token.z, pValue) ){ +        return 1; +      } +      break; +    } +    case TK_STRING: { +      const u8 *z = (u8*)p->token.z; +      int n = p->token.n; +      if( n>0 && z[0]=='-' ){ z++; n--; } +      while( n>0 && *z && isdigit(*z) ){ z++; n--; } +      if( n==0 && sqlite3GetInt32(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. */ +  SrcList *pSrcList,   /* List of tables used to resolve column names */ +  ExprList *pEList,    /* List of expressions used to resolve "AS" */ +  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 */ + +  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ +  zDb = sqlite3NameFromToken(pDbToken); +  zTab = sqlite3NameFromToken(pTableToken); +  zCol = sqlite3NameFromToken(pColumnToken); +  if( sqlite3_malloc_failed ){ +    return 1;  /* Leak memory (zDb and zTab) if malloc fails */ +  } +  assert( zTab==0 || pEList==0 ); + +  pExpr->iTable = -1; +  for(i=0; i<pSrcList->nSrc; i++){ +    struct SrcList_item *pItem = &pSrcList->a[i]; +    Table *pTab = pItem->pTab; +    Column *pCol; + +    if( pTab==0 ) continue; +    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[pTab->iDb].zName, zDb)!=0 ){ +          continue; +        } +      } +    } +    if( 0==(cntTab++) ){ +      pExpr->iTable = pItem->iCursor; +      pExpr->iDb = pTab->iDb; +    } +    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ +      if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ +        cnt++; +        pExpr->iTable = pItem->iCursor; +        pExpr->iDb = pTab->iDb; +        /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ +        pExpr->iColumn = j==pTab->iPKey ? -1 : j; +        pExpr->affinity = pTab->aCol[j].affinity; +        pExpr->pColl = pTab->aCol[j].pColl; +        break; +      } +    } +  } + +  /* 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; +    if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){ +      pExpr->iTable = pTriggerStack->newIdx; +      assert( pTriggerStack->pTab ); +      pTab = pTriggerStack->pTab; +    }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab) == 0 ){ +      pExpr->iTable = pTriggerStack->oldIdx; +      assert( pTriggerStack->pTab ); +      pTab = pTriggerStack->pTab; +    } + +    if( pTab ){  +      int j; +      Column *pCol = pTab->aCol; +       +      pExpr->iDb = pTab->iDb; +      cntTab++; +      for(j=0; j < pTab->nCol; j++, pCol++) { +        if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ +          cnt++; +          pExpr->iColumn = j==pTab->iPKey ? -1 : j; +          pExpr->affinity = pTab->aCol[j].affinity; +          pExpr->pColl = pTab->aCol[j].pColl; +          break; +        } +      } +    } +  } + +  /* +  ** 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!=0 ){ +    for(j=0; j<pEList->nExpr; j++){ +      char *zAs = pEList->a[j].zName; +      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ +        assert( pExpr->pLeft==0 && pExpr->pRight==0 ); +        pExpr->op = TK_AS; +        pExpr->iColumn = j; +        pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr); +        sqliteFree(zCol); +        assert( zTab==0 && zDb==0 ); +        return 0; +      } +    }  +  } + +  /* +  ** 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. +  */ +  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ +    sqliteFree(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 ){ +    char *z = 0; +    char *zErr; +    zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; +    if( zDb ){ +      sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, 0); +    }else if( zTab ){ +      sqlite3SetString(&z, zTab, ".", zCol, 0); +    }else{ +      z = sqliteStrDup(zCol); +    } +    sqlite3ErrorMsg(pParse, zErr, z); +    sqliteFree(z); +  } + +  /* Clean up and return +  */ +  sqliteFree(zDb); +  sqliteFree(zTab); +  sqliteFree(zCol); +  sqlite3ExprDelete(pExpr->pLeft); +  pExpr->pLeft = 0; +  sqlite3ExprDelete(pExpr->pRight); +  pExpr->pRight = 0; +  pExpr->op = TK_COLUMN; +  sqlite3AuthRead(pParse, pExpr, pSrcList); +  return cnt!=1; +} + +/* +** 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. +** +** We also check for instances of the IN operator.  IN comes in two +** forms: +** +**           expr IN (exprlist) +** and +**           expr IN (SELECT ...) +** +** The first form is handled by creating a set holding the list +** of allowed values.  The second form causes the SELECT to generate  +** a temporary table. +** +** This routine also looks for scalar SELECTs that are part of an expression. +** If it finds any, it generates code to write the value of that select +** into a memory cell. +** +** Unknown columns or tables provoke an error.  The function returns +** the number of errors seen and leaves an error message on pParse->zErrMsg. +*/ +int sqlite3ExprResolveIds( +  Parse *pParse,     /* The parser context */ +  SrcList *pSrcList, /* List of tables used to resolve column names */ +  ExprList *pEList,  /* List of expressions used to resolve "AS" */ +  Expr *pExpr        /* The expression to be analyzed. */ +){ +  int i; + +  if( pExpr==0 || pSrcList==0 ) return 0; +  for(i=0; i<pSrcList->nSrc; i++){ +    assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab ); +  } +  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 columnd. +    */ +    case TK_ID: { +      if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){ +        return 1; +      } +      break;  +    } +   +    /* 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; + +      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; +      } +      if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){ +        return 1; +      } +      break; +    } + +    case TK_IN: { +      char affinity; +      Vdbe *v = sqlite3GetVdbe(pParse); +      KeyInfo keyInfo; +      int addr;        /* Address of OP_OpenTemp instruction */ + +      if( v==0 ) return 1; +      if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ +        return 1; +      } +      affinity = sqlite3ExprAffinity(pExpr->pLeft); + +      /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)' +      ** expression it is handled the same way. A temporary table is  +      ** filled with single-field index keys representing the results +      ** from the SELECT or the <exprlist>. +      ** +      ** 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 = sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 0); +      memset(&keyInfo, 0, sizeof(keyInfo)); +      keyInfo.nField = 1; +      sqlite3VdbeAddOp(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. +        */ +        int iParm = pExpr->iTable +  (((int)affinity)<<16); +        ExprList *pEList; +        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); +        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0); +        pEList = pExpr->pSelect->pEList; +        if( pEList && pEList->nExpr>0 ){  +          keyInfo.aColl[0] = binaryCompareCollSeq(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 <expr> is a column, then use +        ** that columns affinity when building index keys. If <expr> is not +        ** a column, use numeric affinity. +        */ +        int i; +        if( !affinity ){ +          affinity = SQLITE_AFF_NUMERIC; +        } +        keyInfo.aColl[0] = pExpr->pLeft->pColl; + +        /* Loop through each expression in <exprlist>. */ +        for(i=0; i<pExpr->pList->nExpr; i++){ +          Expr *pE2 = pExpr->pList->a[i].pExpr; + +          /* Check that the expression is constant and valid. */ +          if( !sqlite3ExprIsConstant(pE2) ){ +            sqlite3ErrorMsg(pParse, +              "right-hand side of IN operator must be constant"); +            return 1; +          } +          if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){ +            return 1; +          } + +          /* Evaluate the expression and insert it into the temp table */ +          sqlite3ExprCode(pParse, pE2); +          sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); +          sqlite3VdbeAddOp(v, OP_String8, 0, 0); +          sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0); +        } +      } +      sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO); + +      break; +    } + +    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. +      */ +      pExpr->iColumn = pParse->nMem++; +      if(sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0)){ +        return 1; +      } +      break; +    } + +    /* For all else, just recursively walk the tree */ +    default: { +      if( pExpr->pLeft +      && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ +        return 1; +      } +      if( pExpr->pRight  +      && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){ +        return 1; +      } +      if( pExpr->pList ){ +        int i; +        ExprList *pList = pExpr->pList; +        for(i=0; i<pList->nExpr; i++){ +          Expr *pArg = pList->a[i].pExpr; +          if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pArg) ){ +            return 1; +          } +        } +      } +    } +  } +  return 0; +} + +/* +** pExpr is a node that defines a function of some kind.  It might +** be a syntactic function like "count(x)" or it might be a function +** that implements an operator, like "a LIKE b".   +** +** This routine makes *pzName point to the name of the function and  +** *pnName hold the number of characters in the function name. +*/ +static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ +  switch( pExpr->op ){ +    case TK_FUNCTION: { +      *pzName = pExpr->token.z; +      *pnName = pExpr->token.n; +      break; +    } +    case TK_LIKE: { +      *pzName = "like"; +      *pnName = 4; +      break; +    } +    case TK_GLOB: { +      *pzName = "glob"; +      *pnName = 4; +      break; +    } +    default: { +      *pzName = "can't happen"; +      *pnName = 12; +      break; +    } +  } +} + +/* +** Error check the functions in an expression.  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 pIsAgg is not null and this expression is an aggregate function +** (like count(*) or max(value)) then write a 1 into *pIsAgg. +*/ +int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ +  int nErr = 0; +  if( pExpr==0 ) return 0; +  switch( pExpr->op ){ +    case TK_GLOB: +    case TK_LIKE: +    case TK_FUNCTION: { +      int n = pExpr->pList ? pExpr->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 nId;                    /* Number of characters in function name */ +      const char *zId;            /* The function name. */ +      FuncDef *pDef; +      int enc = pParse->db->enc; + +      getFunctionName(pExpr, &zId, &nId); +      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; +      } +      if( is_agg && !allowAgg ){ +        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId); +        nErr++; +        is_agg = 0; +      }else if( no_such_func ){ +        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); +        nErr++; +      }else if( wrong_num_args ){ +        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", +             nId, zId); +        nErr++; +      } +      if( is_agg ){ +        pExpr->op = TK_AGG_FUNCTION; +        if( pIsAgg ) *pIsAgg = 1; +      } +      for(i=0; nErr==0 && i<n; i++){ +        nErr = sqlite3ExprCheck(pParse, pExpr->pList->a[i].pExpr, +                               allowAgg && !is_agg, pIsAgg); +      } +      /* FIX ME:  Compute pExpr->affinity based on the expected return +      ** type of the function  +      */ +    } +    default: { +      if( pExpr->pLeft ){ +        nErr = sqlite3ExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg); +      } +      if( nErr==0 && pExpr->pRight ){ +        nErr = sqlite3ExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg); +      } +      if( nErr==0 && pExpr->pList ){ +        int n = pExpr->pList->nExpr; +        int i; +        for(i=0; nErr==0 && i<n; i++){ +          Expr *pE2 = pExpr->pList->a[i].pExpr; +          nErr = sqlite3ExprCheck(pParse, pE2, allowAgg, pIsAgg); +        } +      } +      break; +    } +  } +  return nErr; +} + +/* +** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck(). +** +** This routine is provided as a convenience since it is very common +** to call ResolveIds() and Check() back to back. +*/ +int sqlite3ExprResolveAndCheck( +  Parse *pParse,     /* The parser context */ +  SrcList *pSrcList, /* List of tables used to resolve column names */ +  ExprList *pEList,  /* List of expressions used to resolve "AS" */ +  Expr *pExpr,       /* The expression to be analyzed. */ +  int allowAgg,      /* True to allow aggregate expressions */ +  int *pIsAgg        /* Set to TRUE if aggregates are found */ +){ +  if( pExpr==0 ) return 0; +  if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){ +    return 1; +  } +  return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg); +} + +/* +** Generate an instruction that will put the integer describe by +** text z[0..n-1] on the stack. +*/ +static void codeInteger(Vdbe *v, const char *z, int n){ +  int i; +  if( sqlite3GetInt32(z, &i) ){ +    sqlite3VdbeAddOp(v, OP_Integer, i, 0); +  }else if( sqlite3FitsIn64Bits(z) ){ +    sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n); +  }else{ +    sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n); +  } +} + +/* +** Generate code into the current Vdbe to evaluate the given +** expression and leave the result on the top of stack. +** +** 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 sqlite3ExprCode(Parse *pParse, Expr *pExpr){ +  Vdbe *v = pParse->pVdbe; +  int op; +  if( v==0 || pExpr==0 ) return; +  op = pExpr->op; +  switch( op ){ +    case TK_COLUMN: { +      if( pParse->useAgg ){ +        sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); +      }else if( pExpr->iColumn>=0 ){ +        sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); +#ifndef NDEBUG +        if( pExpr->span.z && pExpr->span.n>0 && pExpr->span.n<100 ){ +          VdbeComment((v, "# %T", &pExpr->span)); +        } +#endif +      }else{ +        sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0); +      } +      break; +    } +    case TK_INTEGER: { +      codeInteger(v, pExpr->token.z, pExpr->token.n); +      break; +    } +    case TK_FLOAT: +    case TK_STRING: { +      assert( TK_FLOAT==OP_Real ); +      assert( TK_STRING==OP_String8 ); +      sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n); +      sqlite3VdbeDequoteP3(v, -1); +      break; +    } +    case TK_BLOB: { +      assert( TK_BLOB==OP_HexBlob ); +      sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1); +      sqlite3VdbeDequoteP3(v, -1); +      break; +    } +    case TK_NULL: { +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      break; +    } +    case TK_VARIABLE: { +      sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); +      if( pExpr->token.n>1 ){ +        sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); +      } +      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 ); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3ExprCode(pParse, pExpr->pRight); +      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); +      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 ); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3ExprCode(pParse, pExpr->pRight); +      sqlite3VdbeAddOp(v, op, 0, 0); +      break; +    } +    case TK_UMINUS: { +      Expr *pLeft = pExpr->pLeft; +      assert( pLeft ); +      if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ +        Token *p = &pLeft->token; +        char *z = sqliteMalloc( p->n + 2 ); +        sprintf(z, "-%.*s", p->n, p->z); +        if( pLeft->op==TK_FLOAT ){ +          sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); +        }else{ +          codeInteger(v, z, p->n+1); +        } +        sqliteFree(z); +        break; +      } +      /* Fall through into TK_NOT */ +    } +    case TK_BITNOT: +    case TK_NOT: { +      assert( TK_BITNOT==OP_BitNot ); +      assert( TK_NOT==OP_Not ); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3VdbeAddOp(v, op, 0, 0); +      break; +    } +    case TK_ISNULL: +    case TK_NOTNULL: { +      int dest; +      assert( TK_ISNULL==OP_IsNull ); +      assert( TK_NOTNULL==OP_NotNull ); +      sqlite3VdbeAddOp(v, OP_Integer, 1, 0); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      dest = sqlite3VdbeCurrentAddr(v) + 2; +      sqlite3VdbeAddOp(v, op, 1, dest); +      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); +      break; +    } +    case TK_AGG_FUNCTION: { +      sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); +      break; +    } +    case TK_GLOB: +    case TK_LIKE: +    case TK_FUNCTION: { +      ExprList *pList = pExpr->pList; +      int nExpr = pList ? pList->nExpr : 0; +      FuncDef *pDef; +      int nId; +      const char *zId; +      int p2 = 0; +      int i; +      u8 enc = pParse->db->enc; +      CollSeq *pColl = 0; +      getFunctionName(pExpr, &zId, &nId); +      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); +      assert( pDef!=0 ); +      nExpr = sqlite3ExprCodeExprList(pParse, pList); +      for(i=0; i<nExpr && i<32; i++){ +        if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ +          p2 |= (1<<i); +        } +        if( pDef->needCollSeq && !pColl ){ +          pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); +        } +      } +      if( pDef->needCollSeq ){ +        if( !pColl ) pColl = pParse->db->pDfltColl;  +        sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); +      } +      sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF); +      break; +    } +    case TK_SELECT: { +      sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); +      VdbeComment((v, "# load subquery result")); +      break; +    } +    case TK_IN: { +      int addr; +      char affinity; + +      /* Figure out the affinity to use to create a key from the results +      ** of the expression. affinityStr stores a static string suitable for +      ** P3 of OP_MakeRecord. +      */ +      affinity = comparisonAffinity(pExpr); + +      sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + +      /* Code the <expr> from "<expr> IN (...)". The temporary table +      ** pExpr->iTable contains the values that make up the (...) set. +      */ +      sqlite3ExprCode(pParse, pExpr->pLeft); +      addr = sqlite3VdbeCurrentAddr(v); +      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4);            /* addr + 0 */ +      sqlite3VdbeAddOp(v, OP_Pop, 2, 0); +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); +      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);   /* addr + 4 */ +      sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); +      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);                  /* addr + 6 */ + +      break; +    } +    case TK_BETWEEN: { +      Expr *pLeft = pExpr->pLeft; +      struct ExprList_item *pLItem = pExpr->pList->a; +      Expr *pRight = pLItem->pExpr; +      sqlite3ExprCode(pParse, pLeft); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      sqlite3ExprCode(pParse, pRight); +      codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0); +      sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +      pLItem++; +      pRight = pLItem->pExpr; +      sqlite3ExprCode(pParse, pRight); +      codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); +      sqlite3VdbeAddOp(v, OP_And, 0, 0); +      break; +    } +    case TK_UPLUS: +    case TK_AS: { +      sqlite3ExprCode(pParse, pExpr->pLeft); +      break; +    } +    case TK_CASE: { +      int expr_end_label; +      int jumpInst; +      int addr; +      int nExpr; +      int i; +      ExprList *pEList; +      struct ExprList_item *aListelem; + +      assert(pExpr->pList); +      assert((pExpr->pList->nExpr % 2) == 0); +      assert(pExpr->pList->nExpr > 0); +      pEList = pExpr->pList; +      aListelem = pEList->a; +      nExpr = pEList->nExpr; +      expr_end_label = sqlite3VdbeMakeLabel(v); +      if( pExpr->pLeft ){ +        sqlite3ExprCode(pParse, pExpr->pLeft); +      } +      for(i=0; i<nExpr; i=i+2){ +        sqlite3ExprCode(pParse, aListelem[i].pExpr); +        if( pExpr->pLeft ){ +          sqlite3VdbeAddOp(v, OP_Dup, 1, 1); +          jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr, +                                 OP_Ne, 0, 1); +          sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +        }else{ +          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0); +        } +        sqlite3ExprCode(pParse, aListelem[i+1].pExpr); +        sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); +        addr = sqlite3VdbeCurrentAddr(v); +        sqlite3VdbeChangeP2(v, jumpInst, addr); +      } +      if( pExpr->pLeft ){ +        sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      } +      if( pExpr->pRight ){ +        sqlite3ExprCode(pParse, pExpr->pRight); +      }else{ +        sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      } +      sqlite3VdbeResolveLabel(v, expr_end_label); +      break; +    } +    case TK_RAISE: { +      if( !pParse->trigStack ){ +        sqlite3ErrorMsg(pParse, +                       "RAISE() may only be used within a trigger-program"); +	return; +      } +      if( pExpr->iColumn!=OE_Ignore ){ +         assert( pExpr->iColumn==OE_Rollback || +                 pExpr->iColumn == OE_Abort || +                 pExpr->iColumn == OE_Fail ); +         sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, +                        pExpr->token.z, pExpr->token.n); +         sqlite3VdbeDequoteP3(v, -1); +      } else { +         assert( pExpr->iColumn == OE_Ignore ); +         sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); +         sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); +         VdbeComment((v, "# raise(IGNORE)")); +      } +    } +    break; +  } +} + +/* +** Generate code that pushes the value of every element of the given +** expression list onto the stack. +** +** Return the number of elements pushed onto the stack. +*/ +int sqlite3ExprCodeExprList( +  Parse *pParse,     /* Parsing context */ +  ExprList *pList    /* The expression list to be coded */ +){ +  struct ExprList_item *pItem; +  int i, n; +  Vdbe *v; +  if( pList==0 ) return 0; +  v = sqlite3GetVdbe(pParse); +  n = pList->nExpr; +  for(pItem=pList->a, i=0; i<n; i++, pItem++){ +    sqlite3ExprCode(pParse, pItem->pExpr); +  } +  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 true. +** +** 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; +  if( v==0 || pExpr==0 ) return; +  op = pExpr->op; +  switch( op ){ +    case TK_AND: { +      int d2 = sqlite3VdbeMakeLabel(v); +      sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !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 ); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3ExprCode(pParse, pExpr->pRight); +      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); +      break; +    } +    case TK_ISNULL: +    case TK_NOTNULL: { +      assert( TK_ISNULL==OP_IsNull ); +      assert( TK_NOTNULL==OP_NotNull ); +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3VdbeAddOp(v, op, 1, dest); +      break; +    } +    case TK_BETWEEN: { +      /* The expression "x BETWEEN y AND z" is implemented as: +      ** +      ** 1 IF (x < y) GOTO 3 +      ** 2 IF (x <= z) GOTO <dest> +      ** 3 ... +      */ +      int addr; +      Expr *pLeft = pExpr->pLeft; +      Expr *pRight = pExpr->pList->a[0].pExpr; +      sqlite3ExprCode(pParse, pLeft); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      sqlite3ExprCode(pParse, pRight); +      addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); + +      pRight = pExpr->pList->a[1].pExpr; +      sqlite3ExprCode(pParse, pRight); +      codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); + +      sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      break; +    } +    default: { +      sqlite3ExprCode(pParse, pExpr); +      sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest); +      break; +    } +  } +} + +/* +** 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 true or fall through if jumpIfNull is false. +*/ +void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ +  Vdbe *v = pParse->pVdbe; +  int op = 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); +      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: { +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3ExprCode(pParse, pExpr->pRight); +      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); +      break; +    } +    case TK_ISNULL: +    case TK_NOTNULL: { +      sqlite3ExprCode(pParse, pExpr->pLeft); +      sqlite3VdbeAddOp(v, op, 1, dest); +      break; +    } +    case TK_BETWEEN: { +      /* The expression is "x BETWEEN y AND z". It is implemented as: +      ** +      ** 1 IF (x >= y) GOTO 3 +      ** 2 GOTO <dest> +      ** 3 IF (x > z) GOTO <dest> +      */ +      int addr; +      Expr *pLeft = pExpr->pLeft; +      Expr *pRight = pExpr->pList->a[0].pExpr; +      sqlite3ExprCode(pParse, pLeft); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +      sqlite3ExprCode(pParse, pRight); +      addr = sqlite3VdbeCurrentAddr(v); +      codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull); + +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      sqlite3VdbeAddOp(v, OP_Goto, 0, dest); +      pRight = pExpr->pList->a[1].pExpr; +      sqlite3ExprCode(pParse, pRight); +      codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull); +      break; +    } +    default: { +      sqlite3ExprCode(pParse, pExpr); +      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest); +      break; +    } +  } +} + +/* +** 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. +*/ +int sqlite3ExprCompare(Expr *pA, Expr *pB){ +  int i; +  if( pA==0 ){ +    return pB==0; +  }else if( pB==0 ){ +    return 0; +  } +  if( pA->op!=pB->op ) 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; i<pA->pList->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->token.z ){ +    if( pB->token.z==0 ) return 0; +    if( pB->token.n!=pA->token.n ) return 0; +    if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; +  } +  return 1; +} + +/* +** Add a new element to the pParse->aAgg[] array and return its index. +*/ +static int appendAggInfo(Parse *pParse){ +  if( (pParse->nAgg & 0x7)==0 ){ +    int amt = pParse->nAgg + 8; +    AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); +    if( aAgg==0 ){ +      return -1; +    } +    pParse->aAgg = aAgg; +  } +  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); +  return pParse->nAgg++; +} + +/* +** 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 sqlite3ExprResolveIds() and sqlite3ExprCheck(). +** +** If errors are seen, leave an error message in zErrMsg and return +** the number of errors. +*/ +int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){ +  int i; +  AggExpr *aAgg; +  int nErr = 0; + +  if( pExpr==0 ) return 0; +  switch( pExpr->op ){ +    case TK_COLUMN: { +      aAgg = pParse->aAgg; +      for(i=0; i<pParse->nAgg; i++){ +        if( aAgg[i].isAgg ) continue; +        if( aAgg[i].pExpr->iTable==pExpr->iTable +         && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ +          break; +        } +      } +      if( i>=pParse->nAgg ){ +        i = appendAggInfo(pParse); +        if( i<0 ) return 1; +        pParse->aAgg[i].isAgg = 0; +        pParse->aAgg[i].pExpr = pExpr; +      } +      pExpr->iAgg = i; +      break; +    } +    case TK_AGG_FUNCTION: { +      aAgg = pParse->aAgg; +      for(i=0; i<pParse->nAgg; i++){ +        if( !aAgg[i].isAgg ) continue; +        if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ +          break; +        } +      } +      if( i>=pParse->nAgg ){ +        u8 enc = pParse->db->enc; +        i = appendAggInfo(pParse); +        if( i<0 ) return 1; +        pParse->aAgg[i].isAgg = 1; +        pParse->aAgg[i].pExpr = pExpr; +        pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db, +             pExpr->token.z, pExpr->token.n, +             pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); +      } +      pExpr->iAgg = i; +      break; +    } +    default: { +      if( pExpr->pLeft ){ +        nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pLeft); +      } +      if( nErr==0 && pExpr->pRight ){ +        nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pRight); +      } +      if( nErr==0 && pExpr->pList ){ +        int n = pExpr->pList->nExpr; +        int i; +        for(i=0; nErr==0 && i<n; i++){ +          nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr); +        } +      } +      break; +    } +  } +  return nErr; +} + +/* +** 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 = sqliteMalloc(sizeof(*pBest)+nName+1)) ){ +    pBest->nArg = nArg; +    pBest->pNext = pFirst; +    pBest->zName = (char*)&pBest[1]; +    pBest->iPrefEnc = enc; +    memcpy(pBest->zName, zName, nName); +    pBest->zName[nName] = 0; +    sqlite3HashInsert(&db->aFunc, pBest->zName, nName, (void*)pBest); +  } + +  if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ +    return pBest; +  } +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/src/func.c b/ext/pdo_sqlite/sqlite/src/func.c new file mode 100644 index 0000000000..f61bdae3fd --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/func.c @@ -0,0 +1,1018 @@ +/* +** 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$ +*/ +#include <ctype.h> +#include <math.h> +#include <stdlib.h> +#include <assert.h> +#include "sqliteInt.h" +#include "vdbeInt.h" +#include "os.h" + +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<argc; i++){ +    if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return; +    if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=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 char *z = sqlite3_value_text(argv[0]); +      for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } +      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 ) iVal = iVal * -1; +      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 * -1.0; +      sqlite3_result_double(context, rVal); +      break; +    } +  } +} + +/* +** Implementation of the substr() function +*/ +static void substrFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  const char *z; +  const char *z2; +  int i; +  int p1, p2, len; + +  assert( argc==3 ); +  z = sqlite3_value_text(argv[0]); +  if( z==0 ) return; +  p1 = sqlite3_value_int(argv[1]); +  p2 = sqlite3_value_int(argv[2]); +  for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; } +  if( p1<0 ){ +    p1 += len; +    if( p1<0 ){ +      p2 += p1; +      p1 = 0; +    } +  }else if( p1>0 ){ +    p1--; +  } +  if( p1+p2>len ){ +    p2 = len-p1; +  } +  for(i=0; i<p1 && z[i]; i++){ +    if( (z[i]&0xc0)==0x80 ) p1++; +  } +  while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; } +  for(; i<p1+p2 && z[i]; i++){ +    if( (z[i]&0xc0)==0x80 ) p2++; +  } +  while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } +  if( p2<0 ) p2 = 0; +  sqlite3_result_text(context, &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[100]; +  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( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; +  r = sqlite3_value_double(argv[0]); +  sprintf(zBuf,"%.*f",n,r); +  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} + +/* +** Implementation of the upper() and lower() SQL functions. +*/ +static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +  unsigned char *z; +  int i; +  if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; +  z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); +  if( z==0 ) return; +  strcpy(z, sqlite3_value_text(argv[0])); +  for(i=0; z[i]; i++){ +    z[i] = toupper(z[i]); +  } +  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); +  sqliteFree(z); +} +static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +  unsigned char *z; +  int i; +  if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; +  z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); +  if( z==0 ) return; +  strcpy(z, sqlite3_value_text(argv[0])); +  for(i=0; z[i]; i++){ +    z[i] = tolower(z[i]); +  } +  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); +  sqliteFree(z); +} + +/* +** 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; i<argc; i++){ +    if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ +      sqlite3_result_value(context, argv[i]); +      break; +    } +  } +} + +/* +** Implementation of random().  Return a random integer.   +*/ +static void randomFunc( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  int r; +  sqlite3Randomness(sizeof(r), &r); +  sqlite3_result_int(context, r); +} + +/* +** 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; +}; +static const struct compareInfo globInfo = { '*', '?', '[', 0 }; +static const struct compareInfo likeInfo = { '%', '_',   0, 1 }; + +/* +** X is a pointer to the first byte of a UTF-8 character.  Increment +** X so that it points to the next character.  This only works right +** if X points to a well-formed UTF-8 string. +*/ +#define sqliteNextChar(X)  while( (0xc0&*++(X))==0x80 ){} +#define sqliteCharVal(X)   sqlite3ReadUtf8(X) + + +/* +** 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 +*/ +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 */ +){ +  register int c; +  int invert; +  int seen; +  int c2; +  u8 matchOne = pInfo->matchOne; +  u8 matchAll = pInfo->matchAll; +  u8 matchSet = pInfo->matchSet; +  u8 noCase = pInfo->noCase;  + +  while( (c = *zPattern)!=0 ){ +    if( c==matchAll ){ +      while( (c=zPattern[1]) == matchAll || c == matchOne ){ +        if( c==matchOne ){ +          if( *zString==0 ) return 0; +          sqliteNextChar(zString); +        } +        zPattern++; +      } +      if( c==0 ) return 1; +      if( c==matchSet ){ +        while( *zString && patternCompare(&zPattern[1],zString,pInfo)==0 ){ +          sqliteNextChar(zString); +        } +        return *zString!=0; +      }else{ +        while( (c2 = *zString)!=0 ){ +          if( noCase ){ +            c2 = sqlite3UpperToLower[c2]; +            c = sqlite3UpperToLower[c]; +            while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; } +          }else{ +            while( c2 != 0 && c2 != c ){ c2 = *++zString; } +          } +          if( c2==0 ) return 0; +          if( patternCompare(&zPattern[1],zString,pInfo) ) return 1; +          sqliteNextChar(zString); +        } +        return 0; +      } +    }else if( c==matchOne ){ +      if( *zString==0 ) return 0; +      sqliteNextChar(zString); +      zPattern++; +    }else if( c==matchSet ){ +      int prior_c = 0; +      seen = 0; +      invert = 0; +      c = sqliteCharVal(zString); +      if( c==0 ) return 0; +      c2 = *++zPattern; +      if( c2=='^' ){ invert = 1; c2 = *++zPattern; } +      if( c2==']' ){ +        if( c==']' ) seen = 1; +        c2 = *++zPattern; +      } +      while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){ +        if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ +          zPattern++; +          c2 = sqliteCharVal(zPattern); +          if( c>=prior_c && c<=c2 ) seen = 1; +          prior_c = 0; +        }else if( c==c2 ){ +          seen = 1; +          prior_c = c2; +        }else{ +          prior_c = c2; +        } +        sqliteNextChar(zPattern); +      } +      if( c2==0 || (seen ^ invert)==0 ) return 0; +      sqliteNextChar(zString); +      zPattern++; +    }else{ +      if( noCase ){ +        if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0; +      }else{ +        if( c != *zString ) return 0; +      } +      zPattern++; +      zString++; +    } +  } +  return *zString==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 the pointer retrieved by via a call to sqlite3_user_data() is +** not NULL, then this function uses UTF-16. Otherwise UTF-8. +*/ +static void likeFunc( +  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]); +  if( zA && zB ){ +    sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo)); +  } +} + +/* +** Implementation of the glob() SQL function.  This function implements +** the build-in GLOB operator.  The first argument to the function is the +** string and the second argument is the pattern.  So, the SQL statements: +** +**       A GLOB B +** +** is implemented as glob(A,B). +*/ +static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){ +  const unsigned char *zA = sqlite3_value_text(argv[0]); +  const unsigned char *zB = sqlite3_value_text(argv[1]); +  if( zA && zB ){ +    sqlite3_result_int(context, patternCompare(zA, zB, &globInfo)); +  } +} + +/* +** 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); +} + +/* +** 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: { +      static const char hexdigits[] = {  +        '0', '1', '2', '3', '4', '5', '6', '7', +        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'  +      }; +      char *zText = 0; +      int nBlob = sqlite3_value_bytes(argv[0]); +      char const *zBlob = sqlite3_value_blob(argv[0]); + +      zText = (char *)sqliteMalloc((2*nBlob)+4);  +      if( !zText ){ +        sqlite3_result_error(context, "out of memory", -1); +      }else{ +        int i; +        for(i=0; i<nBlob; i++){ +          zText[(i*2)+2] = hexdigits[(zBlob[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); +        sqliteFree(zText); +      } +      break; +    } +    case SQLITE_TEXT: { +      int i,j,n; +      const char *zArg = sqlite3_value_text(argv[0]); +      char *z; + +      for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } +      z = sqliteMalloc( i+n+3 ); +      if( z==0 ) return; +      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, SQLITE_TRANSIENT); +      sqliteFree(z); +    } +  } +} + +#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]); +  for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} +  if( zIn[i] ){ +    zResult[0] = toupper(zIn[i]); +    for(j=1; j<4 && zIn[i]; i++){ +      int code = iCode[zIn[i]&0x7f]; +      if( code>0 ){ +        zResult[j++] = code + '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 + +#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]; +  if( argc>=1 ){ +    iMin = sqlite3_value_int(argv[0]); +    if( iMin<0 ) iMin = 0; +    if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; +  }else{ +    iMin = 1; +  } +  if( argc>=2 ){ +    iMax = sqlite3_value_int(argv[1]); +    if( iMax<iMin ) iMax = iMin; +    if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; +  }else{ +    iMax = 50; +  } +  n = iMin; +  if( iMax>iMin ){ +    sqlite3Randomness(sizeof(r), &r); +    r &= 0x7fffffff; +    n += r%(iMax + 1 - iMin); +  } +  assert( n<sizeof(zBuf) ); +  sqlite3Randomness(n, zBuf); +  for(i=0; i<n; i++){ +    zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; +  } +  zBuf[n] = 0; +  sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); +} +#endif /* SQLITE_TEST */ + +#ifdef SQLITE_TEST +/* +** The following two SQL functions are used to test returning a text +** result with a destructor. Function 'test_destructor' takes one argument +** and returns the same argument interpreted as TEXT. A destructor is +** passed with the sqlite3_result_text() call. +** +** SQL function 'test_destructor_count' returns the number of outstanding  +** allocations made by 'test_destructor'; +** +** WARNING: Not threadsafe. +*/ +static int test_destructor_count_var = 0; +static void destructor(void *p){ +  char *zVal = (char *)p; +  assert(zVal); +  zVal--; +  sqliteFree(zVal); +  test_destructor_count_var--; +} +static void test_destructor( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  char *zVal; +  int len; +  sqlite3 *db = sqlite3_user_data(pCtx); +  +  test_destructor_count_var++; +  assert( nArg==1 ); +  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; +  len = sqlite3ValueBytes(argv[0], db->enc);  +  zVal = sqliteMalloc(len+3); +  zVal[len] = 0; +  zVal[len-1] = 0; +  assert( zVal ); +  zVal++; +  memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len); +  if( db->enc==SQLITE_UTF8 ){ +    sqlite3_result_text(pCtx, zVal, -1, destructor); +  }else if( db->enc==SQLITE_UTF16LE ){ +    sqlite3_result_text16le(pCtx, zVal, -1, destructor); +  }else{ +    sqlite3_result_text16be(pCtx, zVal, -1, destructor); +  } +} +static void test_destructor_count( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  sqlite3_result_int(pCtx, test_destructor_count_var); +} +#endif /* SQLITE_TEST */ + +#ifdef SQLITE_TEST +/* +** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() +** interface. +** +** The test_auxdata() SQL function attempts to register each of its arguments +** as auxiliary data.  If there are no prior registrations of aux data for +** that argument (meaning the argument is not a constant or this is its first +** call) then the result for that argument is 0.  If there is a prior +** registration, the result for that argument is 1.  The overall result +** is the individual argument results separated by spaces. +*/ +static void free_test_auxdata(void *p) {sqliteFree(p);} +static void test_auxdata( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  int i; +  char *zRet = sqliteMalloc(nArg*2); +  if( !zRet ) return; +  for(i=0; i<nArg; i++){ +    char const *z = sqlite3_value_text(argv[i]); +    if( z ){ +      char *zAux = sqlite3_get_auxdata(pCtx, i); +      if( zAux ){ +        zRet[i*2] = '1'; +        if( strcmp(zAux, z) ){ +          sqlite3_result_error(pCtx, "Auxilary data corruption", -1); +          return; +        } +      }else{ +        zRet[i*2] = '0'; +        zAux = sqliteStrDup(z); +        sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); +      } +      zRet[i*2+1] = ' '; +    } +  } +  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); +} +#endif /* SQLITE_TEST */ + +/* +** An instance of the following structure holds the context of a +** sum() or avg() aggregate computation. +*/ +typedef struct SumCtx SumCtx; +struct SumCtx { +  double sum;     /* Sum of terms */ +  int cnt;        /* Number of elements summed */ +}; + +/* +** Routines used to compute the sum or average. +*/ +static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ +  SumCtx *p; +  if( argc<1 ) return; +  p = sqlite3_aggregate_context(context, sizeof(*p)); +  if( p && SQLITE_NULL!=sqlite3_value_type(argv[0]) ){ +    p->sum += sqlite3_value_double(argv[0]); +    p->cnt++; +  } +} +static void sumFinalize(sqlite3_context *context){ +  SumCtx *p; +  p = sqlite3_aggregate_context(context, sizeof(*p)); +  sqlite3_result_double(context, p ? p->sum : 0.0); +} +static void avgFinalize(sqlite3_context *context){ +  SumCtx *p; +  p = sqlite3_aggregate_context(context, sizeof(*p)); +  if( p && p->cnt>0 ){ +    sqlite3_result_double(context, p->sum/(double)p->cnt); +  } +} + +/* +** An instance of the following structure holds the context of a +** variance or standard deviation computation. +*/ +typedef struct StdDevCtx StdDevCtx; +struct StdDevCtx { +  double sum;     /* Sum of terms */ +  double sum2;    /* Sum of the squares of terms */ +  int cnt;        /* Number of terms counted */ +}; + +#if 0   /* Omit because math library is required */ +/* +** Routines used to compute the standard deviation as an aggregate. +*/ +static void stdDevStep(sqlite3_context *context, int argc, const char **argv){ +  StdDevCtx *p; +  double x; +  if( argc<1 ) return; +  p = sqlite3_aggregate_context(context, sizeof(*p)); +  if( p && argv[0] ){ +    x = sqlite3AtoF(argv[0], 0); +    p->sum += x; +    p->sum2 += x*x; +    p->cnt++; +  } +} +static void stdDevFinalize(sqlite3_context *context){ +  double rN = sqlite3_aggregate_count(context); +  StdDevCtx *p = sqlite3_aggregate_context(context, sizeof(*p)); +  if( p && p->cnt>1 ){ +    double rCnt = cnt; +    sqlite3_set_result_double(context,  +       sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0))); +  } +} +#endif + +/* +** The following structure keeps track of state information for the +** count() aggregate function. +*/ +typedef struct CountCtx CountCtx; +struct CountCtx { +  int 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, sizeof(*p)); +  sqlite3_result_int(context, p ? p->n : 0); +} + +/* +** This function tracks state information for the min() and max() +** aggregate functions. +*/ +typedef struct MinMaxCtx MinMaxCtx; +struct MinMaxCtx { +  char *z;         /* The best so far */ +  char zBuf[28];   /* Space that can be used for storage */ +}; + +/* +** 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)==(void *)-1)?1: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, sizeof(Mem)); +  if( pRes->flags ){ +    sqlite3_result_value(context, pRes); +  } +  sqlite3VdbeMemRelease(pRes); +} + + +/* +** 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;           /* 0: none.  1: db  2: (-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, 2, SQLITE_UTF8,    1, minmaxFunc }, +    { "max",                0, 2, SQLITE_UTF8,    1, 0          }, +    { "typeof",             1, 0, SQLITE_UTF8,    0, typeofFunc }, +    { "length",             1, 0, SQLITE_UTF8,    0, lengthFunc }, +    { "substr",             3, 0, SQLITE_UTF8,    0, substrFunc }, +    { "substr",             3, 0, SQLITE_UTF16LE, 0, sqlite3utf16Substr }, +    { "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          }, +    { "ifnull",             2, 0, SQLITE_UTF8,    1, ifnullFunc }, +    { "random",            -1, 0, SQLITE_UTF8,    0, randomFunc }, +    { "like",               2, 0, SQLITE_UTF8,    0, likeFunc   }, +    { "glob",               2, 0, SQLITE_UTF8,    0, globFunc   }, +    { "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, 1, SQLITE_UTF8,    0, last_insert_rowid }, +    { "changes",            0, 1, SQLITE_UTF8,    0, changes    }, +    { "total_changes",      0, 1, SQLITE_UTF8,    0, total_changes }, +#ifdef SQLITE_SOUNDEX +    { "soundex",            1, 0, SQLITE_UTF8, 0, soundexFunc}, +#endif +#ifdef SQLITE_TEST +    { "randstr",               2, 0, SQLITE_UTF8, 0, randStr    }, +    { "test_destructor",       1, 1, 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}, +#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, 2, 1, minmaxStep,   minMaxFinalize }, +    { "sum",    1, 0, 0, sumStep,      sumFinalize    }, +    { "avg",    1, 0, 0, sumStep,      avgFinalize    }, +    { "count",  0, 0, 0, countStep,    countFinalize  }, +    { "count",  1, 0, 0, countStep,    countFinalize  }, +#if 0 +    { "stddev", 1, 0, stdDevStep,   stdDevFinalize }, +#endif +  }; +  int i; + +  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ +    void *pArg = 0; +    switch( aFuncs[i].argType ){ +      case 1: pArg = db; break; +      case 2: pArg = (void *)(-1); break; +    } +    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, +        aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0); +    if( aFuncs[i].needCollSeq ){ +      FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,  +          strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0); +      if( pFunc && aFuncs[i].needCollSeq ){ +        pFunc->needCollSeq = 1; +      } +    } +  } +  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ +    void *pArg = 0; +    switch( aAggs[i].argType ){ +      case 1: pArg = db; break; +      case 2: pArg = (void *)(-1); break; +    } +    sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,  +        pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); +    if( aAggs[i].needCollSeq ){ +      FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName, +          strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0); +      if( pFunc && aAggs[i].needCollSeq ){ +        pFunc->needCollSeq = 1; +      } +    } +  } +  sqlite3RegisterDateTimeFunctions(db); +} diff --git a/ext/pdo_sqlite/sqlite/src/hash.c b/ext/pdo_sqlite/sqlite/src/hash.c new file mode 100644 index 0000000000..23e2e19748 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/hash.c @@ -0,0 +1,380 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include <assert.h> + +/* 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 ) sqliteFree(pH->ht); +  pH->ht = 0; +  pH->htsize = 0; +  while( elem ){ +    HashElem *next_elem = elem->next; +    if( pH->copyKey && elem->pKey ){ +      sqliteFree(elem->pKey); +    } +    sqliteFree(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<pKey2 ) return -1; +  return 1; +} +#endif + +/* +** Hash and comparison functions when the mode is SQLITE_HASH_STRING +*/ +static int strHash(const void *pKey, int nKey){ +  return sqlite3HashNoCase((const char*)pKey, nKey);  +} +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 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 *)sqliteMalloc( new_size*sizeof(struct _ht) ); +  if( new_ht==0 ) return; +  if( pH->ht ) sqliteFree(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 ){ +    sqliteFree(elem->pKey); +  } +  sqliteFree( elem ); +  pH->count--; +} + +/* 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){ +  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 *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; +    } +    return old_data; +  } +  if( data==0 ) return 0; +  new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) ); +  if( new_elem==0 ) return data; +  if( pH->copyKey && pKey!=0 ){ +    new_elem->pKey = sqliteMallocRaw( nKey ); +    if( new_elem->pKey==0 ){ +      sqliteFree(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; +      sqliteFree(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/ext/pdo_sqlite/sqlite/src/hash.h b/ext/pdo_sqlite/sqlite/src/hash.h new file mode 100644 index 0000000000..cf004ddc53 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/hash.h @@ -0,0 +1,109 @@ +/* +** 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$ +*/ +#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 */ +  HashElem *first;        /* The first element of the array */ +  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: +** +**   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); +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/ext/pdo_sqlite/sqlite/src/insert.c b/ext/pdo_sqlite/sqlite/src/insert.c new file mode 100644 index 0000000000..65cbdc8ff1 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/insert.c @@ -0,0 +1,1018 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" + +/* +** Set P3 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 +**  ------------------------------ +**  'n'            NUMERIC +**  'i'            INTEGER +**  't'            TEXT +**  'o'            NONE +*/ +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; +    pIdx->zColAff = (char *)sqliteMalloc(pIdx->nColumn+1); +    if( !pIdx->zColAff ){ +      return; +    } +    for(n=0; n<pIdx->nColumn; n++){ +      pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; +    } +    pIdx->zColAff[pIdx->nColumn] = '\0'; +  } +  +  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0); +} + +/* +** Set P3 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 +**  ------------------------------ +**  'n'            NUMERIC +**  'i'            INTEGER +**  't'            TEXT +**  'o'            NONE +*/ +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; + +    zColAff = (char *)sqliteMalloc(pTab->nCol+1); +    if( !zColAff ){ +      return; +    } + +    for(i=0; i<pTab->nCol; i++){ +      zColAff[i] = pTab->aCol[i].affinity; +    } +    zColAff[pTab->nCol] = '\0'; + +    pTab->zColAff = zColAff; +  } + +  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0); +} + + +/* +** 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 three 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 <table> and its indices +**         puts VALUES clause expressions onto the stack +**         write the resulting record into <table> +**         cleanup +** +** If the statement is of the form +** +**   INSERT INTO <table> SELECT ... +** +** And the SELECT clause does not read from <table> at any time, then +** the generated code follows this template: +** +**         goto B +**      A: setup for the SELECT +**         loop over the tables in the SELECT +**           gosub C +**         end loop +**         cleanup after the SELECT +**         goto D +**      B: open write cursor to <table> and its indices +**         goto A +**      C: insert the select result into <table> +**         return +**      D: cleanup +** +** The third 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 <table> and its indices +**         loop over the intermediate table +**           transfer values form intermediate table into <table> +**         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 */ +){ +  Table *pTab;          /* The table to insert into */ +  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 base = 0;         /* VDBE Cursor number for pTab */ +  int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ +  sqlite3 *db;          /* The main database structure */ +  int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */ +  int endOfLoop;        /* Label for the end of the insertion loop */ +  int useTempTable;     /* Store SELECT results in intermediate table */ +  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */ +  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 iCntMem = 0;      /* Memory cell used for the row counter */ +  int isView;           /* True if attempting to insert into a view */ + +  int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ +  int before_triggers;        /* True if there are BEFORE triggers */ +  int after_triggers;         /* True if there are AFTER triggers */ +  int newIdx = -1;            /* Cursor for the NEW table */ + +  if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; +  db = pParse->db; + +  /* 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; +  } +  assert( pTab->iDb<db->nDb ); +  zDb = db->aDb[pTab->iDb].zName; +  if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ +    goto insert_cleanup; +  } + +  /* Ensure that: +  *  (a) the table is not read-only,  +  *  (b) that if it is a view then ON INSERT triggers exist +  */ +  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT,  +                                       TK_BEFORE, TK_ROW, 0); +  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT, +                                       TK_AFTER, TK_ROW, 0); +  row_triggers_exist = before_triggers || after_triggers; +  isView = pTab->pSelect!=0; +  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ +    goto insert_cleanup; +  } +  if( pTab==0 ) goto insert_cleanup; + +  /* If pTab is really a view, make sure it has been initialized. +  */ +  if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ +    goto insert_cleanup; +  } + +  /* Ensure all required collation sequences are available. */ +  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +    if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ +      goto insert_cleanup; +    } +  } + +  /* Allocate a VDBE +  */ +  v = sqlite3GetVdbe(pParse); +  if( v==0 ) goto insert_cleanup; +  sqlite3VdbeCountChanges(v); +  sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb); + +  /* if there are row triggers, allocate a temp table for new.* references. */ +  if( row_triggers_exist ){ +    newIdx = pParse->nTab++; +  } + +  /* 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 +    */ +    int rc, iInitCode; +    iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); +    iSelectLoop = sqlite3VdbeCurrentAddr(v); +    iInsertBlock = sqlite3VdbeMakeLabel(v); +    rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0,0); +    if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; +    iCleanup = sqlite3VdbeMakeLabel(v); +    sqlite3VdbeAddOp(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( row_triggers_exist ){ +      useTempTable = 1; +    }else{ +      int addr = 0; +      useTempTable = 0; +      while( useTempTable==0 ){ +        VdbeOp *pOp; +        addr = sqlite3VdbeFindOp(v, addr, OP_OpenRead, pTab->tnum); +        if( addr==0 ) break; +        pOp = sqlite3VdbeGetOp(v, addr-2); +        if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){ +          useTempTable = 1; +        } +      } +    } + +    if( useTempTable ){ +      /* Generate the subroutine that SELECT calls to process each row of +      ** the result.  Store the result in a temporary table +      */ +      srcTab = pParse->nTab++; +      sqlite3VdbeResolveLabel(v, iInsertBlock); +      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); +      sqlite3TableAffinityStr(v, pTab); +      sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0); +      sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +      sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0); +      sqlite3VdbeAddOp(v, OP_Return, 0, 0); + +      /* 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. +      */ +      sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); +      sqlite3VdbeAddOp(v, OP_OpenTemp, srcTab, 0); +      sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn); +      sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); +      sqlite3VdbeResolveLabel(v, iCleanup); +    }else{ +      sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); +    } +  }else{ +    /* This is the case if the data for the INSERT is coming from a VALUES +    ** clause +    */ +    SrcList dummy; +    assert( pList!=0 ); +    srcTab = -1; +    useTempTable = 0; +    assert( pList ); +    nColumn = pList->nExpr; +    dummy.nSrc = 0; +    for(i=0; i<nColumn; i++){ +      if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){ +        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( pColumn==0 && nColumn!=pTab->nCol ){ +    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; i<pColumn->nId; i++){ +      pColumn->a[i].idx = -1; +    } +    for(i=0; i<pColumn->nId; i++){ +      for(j=0; j<pTab->nCol; 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 ){ +    keyColumn = pTab->iPKey; +  } + +  /* Open the temp table for FOR EACH ROW triggers +  */ +  if( row_triggers_exist ){ +    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); +  } +     +  /* Initialize the count of rows to be inserted +  */ +  if( db->flags & SQLITE_CountRows ){ +    iCntMem = pParse->nMem++; +    sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +    sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1); +  } + +  /* Open tables and indices if there are no row triggers */ +  if( !row_triggers_exist ){ +    base = pParse->nTab; +    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); +  } + +  /* 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); +    sqlite3VdbeAddOp(v, OP_Rewind, srcTab, iBreak); +    iCont = sqlite3VdbeCurrentAddr(v); +  }else if( pSelect ){ +    sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); +    sqlite3VdbeResolveLabel(v, iInsertBlock); +  } + +  /* Run the BEFORE and INSTEAD OF triggers, if there are any +  */ +  endOfLoop = sqlite3VdbeMakeLabel(v); +  if( before_triggers ){ + +    /* 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 +    */ +    if( keyColumn<0 ){ +      sqlite3VdbeAddOp(v, OP_Integer, -1, 0); +    }else if( useTempTable ){ +      sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); +    }else if( pSelect ){ +      sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); +    }else{ +      sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); +      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      sqlite3VdbeAddOp(v, OP_Integer, -1, 0); +      sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); +    } + +    /* Create the new column data +    */ +    for(i=0; i<pTab->nCol; i++){ +      if( pColumn==0 ){ +        j = i; +      }else{ +        for(j=0; j<pColumn->nId; j++){ +          if( pColumn->a[j].idx==i ) break; +        } +      } +      if( pColumn && j>=pColumn->nId ){ +        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); +      }else if( useTempTable ){ +        sqlite3VdbeAddOp(v, OP_Column, srcTab, j);  +      }else if( pSelect ){ +        sqlite3VdbeAddOp(v, OP_Dup, nColumn-j-1, 1); +      }else{ +        sqlite3ExprCode(pParse, pList->a[j].pExpr); +      } +    } +    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); + +    /* 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); +    } +    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); + +    /* Fire BEFORE or INSTEAD OF triggers */ +    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab,  +        newIdx, -1, onError, endOfLoop) ){ +      goto insert_cleanup; +    } +  } + +  /* If any triggers exists, the opening of tables and indices is deferred +  ** until now. +  */ +  if( row_triggers_exist && !isView ){ +    base = pParse->nTab; +    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); +  } + +  /* Push the record number for the new entry onto the stack.  The +  ** record number is a randomly generate integer created by NewRecno +  ** 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( keyColumn>=0 ){ +      if( useTempTable ){ +        sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); +      }else if( pSelect ){ +        sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); +      }else{ +        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); +      } +      /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno +      ** to generate a unique primary key value. +      */ +      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      sqlite3VdbeAddOp(v, OP_NewRecno, base, 0); +      sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); +    }else{ +      sqlite3VdbeAddOp(v, OP_NewRecno, base, 0); +    } + +    /* Push onto the stack, data for all columns of the new entry, beginning +    ** with the first column. +    */ +    for(i=0; i<pTab->nCol; 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. */ +        sqlite3VdbeAddOp(v, OP_String8, 0, 0); +        continue; +      } +      if( pColumn==0 ){ +        j = i; +      }else{ +        for(j=0; j<pColumn->nId; j++){ +          if( pColumn->a[j].idx==i ) break; +        } +      } +      if( pColumn && j>=pColumn->nId ){ +        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); +      }else if( useTempTable ){ +        sqlite3VdbeAddOp(v, OP_Column, srcTab, j);  +      }else if( pSelect ){ +        sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j, 1); +      }else{ +        sqlite3ExprCode(pParse, pList->a[j].pExpr); +      } +    } + +    /* Generate code to check constraints and generate index keys and +    ** do the insertion. +    */ +    sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, +                                   0, onError, endOfLoop); +    sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, +                            after_triggers ? newIdx : -1); +  } + +  /* Update the count of rows that are inserted +  */ +  if( (db->flags & SQLITE_CountRows)!=0 ){ +    sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0); +  } + +  if( row_triggers_exist ){ +    /* Close all tables opened */ +    if( !isView ){ +      sqlite3VdbeAddOp(v, OP_Close, base, 0); +      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ +        sqlite3VdbeAddOp(v, OP_Close, idx+base, 0); +      } +    } + +    /* Code AFTER triggers */ +    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,  +          onError, endOfLoop) ){ +      goto insert_cleanup; +    } +  } + +  /* The bottom of the loop, if the data source is a SELECT statement +  */ +  sqlite3VdbeResolveLabel(v, endOfLoop); +  if( useTempTable ){ +    sqlite3VdbeAddOp(v, OP_Next, srcTab, iCont); +    sqlite3VdbeResolveLabel(v, iBreak); +    sqlite3VdbeAddOp(v, OP_Close, srcTab, 0); +  }else if( pSelect ){ +    sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); +    sqlite3VdbeAddOp(v, OP_Return, 0, 0); +    sqlite3VdbeResolveLabel(v, iCleanup); +  } + +  if( !row_triggers_exist ){ +    /* Close all tables opened */ +    sqlite3VdbeAddOp(v, OP_Close, base, 0); +    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ +      sqlite3VdbeAddOp(v, OP_Close, idx+base, 0); +    } +  } + +  /* +  ** Return the number of rows inserted. +  */ +  if( db->flags & SQLITE_CountRows ){ +    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); +    sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +    sqlite3VdbeSetNumCols(v, 1); +    sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); +  } + +insert_cleanup: +  sqlite3SrcListDelete(pTabList); +  if( pList ) sqlite3ExprListDelete(pList); +  if( pSelect ) sqlite3SelectDelete(pSelect); +  sqlite3IdListDelete(pColumn); +} + +/* +** Generate code to do a constraint check prior to an INSERT or an UPDATE. +** +** When this routine is called, the stack contains (from bottom to top) +** the following values: +** +**    1.  The recno 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. +** +**    2.  The recno 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 old recno shown as entry (1) above is omitted unless both isUpdate +** and recnoChng are 1.  isUpdate is true for UPDATEs and false for +** INSERTs and recnoChng is true if the record number is being changed. +** +** The code generated by this routine pushes additional entries onto +** the stack which are the keys for new index entries for the new record. +** The order of index keys is the same as the order of the indices on +** the pTable->pIndex list.  A key is only created for index i if  +** aIdxUsed!=0 and aIdxUsed[i]!=0. +** +** 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 "base".  All indices of pTab must also have open +** read/write cursors with cursor number base+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 aIdxUsed[i]==0. +** +** If the isUpdate flag is true, it means that the "base" cursor is +** initially pointing to an entry that is being updated.  The isUpdate +** flag causes extra code to be generated so that the "base" cursor +** is still pointing at the same entry after the routine returns. +** Without the isUpdate flag, the "base" cursor might be moved. +*/ +void sqlite3GenerateConstraintChecks( +  Parse *pParse,      /* The parser context */ +  Table *pTab,        /* the table into which we are inserting */ +  int base,           /* Index of a read/write cursor pointing at pTab */ +  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */ +  int recnoChng,      /* True if the record number will change */ +  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 addr; +  int extra; +  int iCur; +  Index *pIdx; +  int seenReplace = 0; +  int jumpInst1=0, jumpInst2; +  int contAddr; +  int hasTwoRecnos = (isUpdate && recnoChng); + +  v = sqlite3GetVdbe(pParse); +  assert( v!=0 ); +  assert( pTab->pSelect==0 );  /* This table is not a VIEW */ +  nCol = pTab->nCol; + +  /* Test all NOT NULL constraints. +  */ +  for(i=0; i<nCol; i++){ +    if( i==pTab->iPKey ){ +      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].zDflt==0 ){ +      onError = OE_Abort; +    } +    sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1); +    addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0); +    switch( onError ){ +      case OE_Rollback: +      case OE_Abort: +      case OE_Fail: { +        char *zMsg = 0; +        sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); +        sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, +                        " may not be NULL", (char*)0); +        sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC); +        break; +      } +      case OE_Ignore: { +        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); +        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); +        break; +      } +      case OE_Replace: { +        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); +        sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0); +        break; +      } +      default: assert(0); +    } +    sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); +  } + +  /* Test all CHECK constraints +  */ +  /**** TBD ****/ + +  /* 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( recnoChng ){ +    onError = pTab->keyConf; +    if( overrideError!=OE_Default ){ +      onError = overrideError; +    }else if( onError==OE_Default ){ +      onError = OE_Abort; +    } +     +    if( isUpdate ){ +      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); +      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); +      jumpInst1 = sqlite3VdbeAddOp(v, OP_Eq, 0, 0); +    } +    sqlite3VdbeAddOp(v, OP_Dup, nCol, 1); +    jumpInst2 = sqlite3VdbeAddOp(v, OP_NotExists, base, 0); +    switch( onError ){ +      default: { +        onError = OE_Abort; +        /* Fall thru into the next case */ +      } +      case OE_Rollback: +      case OE_Abort: +      case OE_Fail: { +        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, +                         "PRIMARY KEY must be unique", P3_STATIC); +        break; +      } +      case OE_Replace: { +        sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0); +        if( isUpdate ){ +          sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1); +          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); +        } +        seenReplace = 1; +        break; +      } +      case OE_Ignore: { +        assert( seenReplace==0 ); +        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); +        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); +        break; +      } +    } +    contAddr = sqlite3VdbeCurrentAddr(v); +    sqlite3VdbeChangeP2(v, jumpInst2, contAddr); +    if( isUpdate ){ +      sqlite3VdbeChangeP2(v, jumpInst1, contAddr); +      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); +      sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); +    } +  } + +  /* 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. +  */ +  extra = -1; +  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ +    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */ +    extra++; + +    /* Create a key for accessing the index entry */ +    sqlite3VdbeAddOp(v, OP_Dup, nCol+extra, 1); +    for(i=0; i<pIdx->nColumn; i++){ +      int idx = pIdx->aiColumn[i]; +      if( idx==pTab->iPKey ){ +        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); +      }else{ +        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); +      } +    } +    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24)); +    sqlite3IndexAffinityStr(v, pIdx); + +    /* 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 */ +    sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1); +    jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); + +    /* Generate code that executes if the new index entry is not unique */ +    switch( onError ){ +      case OE_Rollback: +      case OE_Abort: +      case OE_Fail: { +        int j, n1, n2; +        char zErrMsg[200]; +        strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column "); +        n1 = strlen(zErrMsg); +        for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){ +          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; +          n2 = strlen(zCol); +          if( j>0 ){ +            strcpy(&zErrMsg[n1], ", "); +            n1 += 2; +          } +          if( n1+n2>sizeof(zErrMsg)-30 ){ +            strcpy(&zErrMsg[n1], "..."); +            n1 += 3; +            break; +          }else{ +            strcpy(&zErrMsg[n1], zCol); +            n1 += n2; +          } +        } +        strcpy(&zErrMsg[n1],  +            pIdx->nColumn>1 ? " are not unique" : " is not unique"); +        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0); +        break; +      } +      case OE_Ignore: { +        assert( seenReplace==0 ); +        sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0); +        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); +        break; +      } +      case OE_Replace: { +        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0); +        if( isUpdate ){ +          sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1); +          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); +        } +        seenReplace = 1; +        break; +      } +      default: assert(0); +    } +    contAddr = sqlite3VdbeCurrentAddr(v); +    assert( contAddr<(1<<24) ); +#if NULL_DISTINCT_FOR_UNIQUE +    sqlite3VdbeChangeP2(v, jumpInst1, contAddr | (1<<24)); +#endif +    sqlite3VdbeChangeP2(v, jumpInst2, contAddr); +  } +} + +/* +** This routine generates code to finish the INSERT or UPDATE operation +** that was started by a prior call to sqlite3GenerateConstraintChecks. +** The stack must contain keys for all active indices followed by data +** and the recno for the new entry.  This routine creates the new +** entries in all indices and in the main table. +** +** 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 base,           /* Index of a read/write cursor pointing at pTab */ +  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */ +  int recnoChng,      /* 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 i; +  Vdbe *v; +  int nIdx; +  Index *pIdx; +  int pik_flags; + +  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( aIdxUsed && aIdxUsed[i]==0 ) continue; +    sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0); +  } +  sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); +  sqlite3TableAffinityStr(v, pTab); +  if( newIdx>=0 ){ +    sqlite3VdbeAddOp(v, OP_Dup, 1, 0); +    sqlite3VdbeAddOp(v, OP_Dup, 1, 0); +    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); +  } +  pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); +  sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags); +   +  if( isUpdate && recnoChng ){ +    sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +  } +} + +/* +** Generate code that will open cursors for a table and for all +** indices of that table.  The "base" parameter is the cursor number used +** for the table.  Indices are opened on subsequent cursors. +*/ +void sqlite3OpenTableAndIndices( +  Parse *pParse,   /* Parsing context */ +  Table *pTab,     /* Table to be opened */ +  int base,        /* Cursor number assigned to the table */ +  int op           /* OP_OpenRead or OP_OpenWrite */ +){ +  int i; +  Index *pIdx; +  Vdbe *v = sqlite3GetVdbe(pParse); +  assert( v!=0 ); +  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); +  sqlite3VdbeAddOp(v, op, base, pTab->tnum); +  VdbeComment((v, "# %s", pTab->zName)); +  sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); +  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ +    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); +    sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, +                   (char*)&pIdx->keyInfo, P3_KEYINFO); +  } +  if( pParse->nTab<=base+i ){ +    pParse->nTab = base+i; +  } +} diff --git a/ext/pdo_sqlite/sqlite/src/legacy.c b/ext/pdo_sqlite/sqlite/src/legacy.c new file mode 100644 index 0000000000..f575f1f0ce --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/legacy.c @@ -0,0 +1,138 @@ +/* +** 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$ +*/ + +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> + +/* +** 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 nChange = 0; +  int nCallback; + +  if( zSql==0 ) return SQLITE_OK; +  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); +    if( rc!=SQLITE_OK ){ +      if( pStmt ) sqlite3_finalize(pStmt); +      continue; +    } +    if( !pStmt ){ +      /* this happens for a comment or white-space */ +      zSql = zLeftover; +      continue; +    } + +    db->nChange += nChange; +    nCallback = 0; + +    nCol = sqlite3_column_count(pStmt); +    azCols = sqliteMalloc(2*nCol*sizeof(const char *)); +    if( nCol && !azCols ){ +      rc = SQLITE_NOMEM; +      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; i<nCol; i++){ +            azCols[i] = (char *)sqlite3_column_name(pStmt, i); +          } +          nCallback++; +        } +        if( rc==SQLITE_ROW ){ +          azVals = &azCols[nCol]; +          for(i=0; i<nCol; i++){ +            azVals[i] = (char *)sqlite3_column_text(pStmt, i); +          } +        } +        if( xCallback(pArg, nCol, azVals, azCols) ){ +          rc = SQLITE_ABORT; +          goto exec_out; +        } +      } + +      if( rc!=SQLITE_ROW ){ +        rc = sqlite3_finalize(pStmt); +        pStmt = 0; +        if( db->pVdbe==0 ){ +          nChange = db->nChange; +        } +        if( rc!=SQLITE_SCHEMA ){ +          nRetry = 0; +          zSql = zLeftover; +          while( isspace((unsigned char)zSql[0]) ) zSql++; +        } +        break; +      } +    } + +    sqliteFree(azCols); +    azCols = 0; +  } + +exec_out: +  if( pStmt ) sqlite3_finalize(pStmt); +  if( azCols ) sqliteFree(azCols); + +  if( sqlite3_malloc_failed ){ +    rc = SQLITE_NOMEM; +  } +  if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ +    *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); +    if( *pzErrMsg ){ +      strcpy(*pzErrMsg, sqlite3_errmsg(db)); +    } +  }else if( pzErrMsg ){ +    *pzErrMsg = 0; +  } + +  return rc; +} diff --git a/ext/pdo_sqlite/sqlite/src/main.c b/ext/pdo_sqlite/sqlite/src/main.c new file mode 100644 index 0000000000..0ae7e1b263 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/main.c @@ -0,0 +1,1346 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> + +/* +** The following constant value is used by the SQLITE_BIGENDIAN and +** SQLITE_LITTLEENDIAN macros. +*/ +const int sqlite3one = 1; + +/* +** Fill the InitData structure with an error message that indicates +** that the database is corrupt. +*/ +static void corruptSchema(InitData *pData, const char *zExtra){ +  if( !sqlite3_malloc_failed ){ +    sqlite3SetString(pData->pzErrMsg, "malformed database schema", +       zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); +  } +} + +/* +** 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.  NULL for trigger or view. +**     argv[2] = SQL text for the CREATE statement. +**     argv[3] = "1" for temporary files, "0" for main database, "2" or more +**               for auxiliary database files. +** +*/ +int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ +  InitData *pData = (InitData*)pInit; +  sqlite3 *db = pData->db; +  int iDb; + +  assert( argc==4 ); +  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */ +  if( argv[1]==0 || argv[3]==0 ){ +    corruptSchema(pData, 0); +    return 1; +  } +  iDb = atoi(argv[3]); +  assert( iDb>=0 && iDb<db->nDb ); +  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; +    if( SQLITE_OK!=rc ){ +      corruptSchema(pData, zErr); +      sqlite3_free(zErr); +      return rc; +    } +  }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; +  char const *azArg[5]; +  char zDbNum[30]; +  int meta[10]; +  InitData initData; +  char const *zMasterSchema; +  char const *zMasterName; + +  /* +  ** 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" +     ")" +  ; +  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" +     ")" +  ; + +  assert( iDb>=0 && iDb<db->nDb ); + +  /* 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( iDb==1 ){ +    zMasterSchema = temp_master_schema; +    zMasterName = TEMP_MASTER_NAME; +  }else{ +    zMasterSchema = master_schema; +    zMasterName = MASTER_NAME; +  } + +  /* Construct the schema tables.  */ +  sqlite3SafetyOff(db); +  azArg[0] = zMasterName; +  azArg[1] = "1"; +  azArg[2] = zMasterSchema; +  sprintf(zDbNum, "%d", iDb); +  azArg[3] = zDbNum; +  azArg[4] = 0; +  initData.db = db; +  initData.pzErrMsg = pzErrMsg; +  rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0); +  if( rc!=SQLITE_OK ){ +    sqlite3SafetyOn(db); +    return rc; +  } +  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); +  if( pTab ){ +    pTab->readOnly = 1; +  } +  sqlite3SafetyOn(db); + +  /* Create a cursor to hold the database open +  */ +  if( db->aDb[iDb].pBt==0 ){ +    if( iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded); +    return SQLITE_OK; +  } +  rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); +  if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ +    sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); +    return rc; +  } + +  /* 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 3:UTF-16 LE 4:UTF-16 BE +  **    meta[5] +  **    meta[6]    +  **    meta[7] +  **    meta[8] +  **    meta[9] +  ** +  ** Note: The hash 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 && i<sizeof(meta)/sizeof(meta[0]); i++){ +      rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, (u32 *)&meta[i]); +    } +    if( rc ){ +      sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); +      sqlite3BtreeCloseCursor(curMain); +      return rc; +    } +  }else{ +    memset(meta, 0, sizeof(meta)); +  } +  db->aDb[iDb].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 db->enc. */ +      db->enc = (u8)meta[4]; +      db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0); +    }else{ +      /* If opening an attached database, the encoding much match db->enc */ +      if( meta[4]!=db->enc ){ +        sqlite3BtreeCloseCursor(curMain); +        sqlite3SetString(pzErrMsg, "attached databases must use the same" +            " text encoding as main database", (char*)0); +        return SQLITE_ERROR; +      } +    } +  } + +  size = meta[2]; +  if( size==0 ){ size = MAX_PAGES; } +  db->aDb[iDb].cache_size = size; + +  if( iDb==0 ){ +    db->file_format = meta[1]; +    if( db->file_format==0 ){ +      /* This happens if the database was initially empty */ +      db->file_format = 1; +    } +  } + +  /* +  **  file_format==1    Version 3.0.0. +  */ +  if( meta[1]>1 ){ +    sqlite3BtreeCloseCursor(curMain); +    sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); +    return SQLITE_ERROR; +  } + +  sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); + +  /* 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( +        "SELECT name, rootpage, sql, %s FROM '%q'.%s", +        zDbNum, db->aDb[iDb].zName, zMasterName); +    sqlite3SafetyOff(db); +    rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); +    sqlite3SafetyOn(db); +    sqliteFree(zSql); +    sqlite3BtreeCloseCursor(curMain); +  } +  if( sqlite3_malloc_failed ){ +    sqlite3SetString(pzErrMsg, "out of memory", (char*)0); +    rc = SQLITE_NOMEM; +    sqlite3ResetInternalSchema(db, 0); +  } +  if( rc==SQLITE_OK ){ +    DbSetProperty(db, iDb, DB_SchemaLoaded); +  }else{ +    sqlite3ResetInternalSchema(db, iDb); +  } +  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 the database is initialized, the SQLITE_Initialized +** bit is set in the flags field of the sqlite structure.  +*/ +int sqlite3Init(sqlite3 *db, char **pzErrMsg){ +  int i, rc; +   +  if( db->init.busy ) return SQLITE_OK; +  assert( (db->flags & SQLITE_Initialized)==0 ); +  rc = SQLITE_OK; +  db->init.busy = 1; +  for(i=0; rc==SQLITE_OK && i<db->nDb; 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. +  */ +  if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ +    rc = sqlite3InitOne(db, 1, pzErrMsg); +    if( rc ){ +      sqlite3ResetInternalSchema(db, 1); +    } +  } + +  db->init.busy = 0; +  if( rc==SQLITE_OK ){ +    db->flags |= SQLITE_Initialized; +    sqlite3CommitInternalChanges(db); +  } + +  if( rc!=SQLITE_OK ){ +    db->flags &= ~SQLITE_Initialized; +  } +  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; +  if( !db->init.busy ){ +    if( (db->flags & SQLITE_Initialized)==0 ){ +      rc = sqlite3Init(db, &pParse->zErrMsg); +    } +  } +  assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy ); +  if( rc!=SQLITE_OK ){ +    pParse->rc = rc; +    pParse->nErr++; +  } +  return rc; +} + +/* +** The version of the library +*/ +const char rcsid3[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; +const char sqlite3_version[] = SQLITE_VERSION; +const char *sqlite3_libversion(void){ return sqlite3_version; } + +/* +** This is the default collating function named "BINARY" which is always +** available. +*/ +static int binaryCollatingFunc( +  void *NotUsed, +  int nKey1, const void *pKey1, +  int nKey2, const void *pKey2 +){ +  int rc, n; +  n = nKey1<nKey2 ? nKey1 : nKey2; +  rc = memcmp(pKey1, pKey2, n); +  if( rc==0 ){ +    rc = nKey1 - nKey2; +  } +  return rc; +} + +/* +** Another built-in collating sequence: NOCASE.  +** +** This collating sequence is intended to be used for "case independant +** comparison". SQLite's knowledge of upper and lower case equivalents +** extends only to the 26 characters used in the English language. +** +** At the moment there is only a UTF-8 implementation. +*/ +static int nocaseCollatingFunc( +  void *NotUsed, +  int nKey1, const void *pKey1, +  int nKey2, const void *pKey2 +){ +  int r = sqlite3StrNICmp( +      (const char *)pKey1, (const char *)pKey2, (nKey1<nKey2)?nKey1:nKey2); +  if( 0==r ){ +    r = nKey1-nKey2; +  } +  return r; +} + +/* +** Return the ROWID of the most recent insert +*/ +sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ +  return db->lastRowid; +} + +/* +** 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( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } + +  /* If there are any outstanding VMs, return SQLITE_BUSY. */ +  if( db->pVdbe ){ +    sqlite3Error(db, SQLITE_BUSY,  +        "Unable to close due to unfinalised statements"); +    return SQLITE_BUSY; +  } +  assert( !sqlite3SafetyCheck(db) ); + +  /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database +  ** cannot be opened for some reason. So this routine needs to run in +  ** that case. But maybe there should be an extra magic value for the +  ** "failed to open" state. +  */ +  if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ +    /* printf("DID NOT CLOSE\n"); fflush(stdout); */ +    return SQLITE_ERROR; +  } + +  for(j=0; j<db->nDb; j++){ +    struct Db *pDb = &db->aDb[j]; +    if( pDb->pBt ){ +      sqlite3BtreeClose(pDb->pBt); +      pDb->pBt = 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; +      sqliteFree(pFunc); +    } +  } + +  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ +    CollSeq *pColl = (CollSeq *)sqliteHashData(i); +    sqliteFree(pColl); +  } +  sqlite3HashClear(&db->aCollSeq); + +  sqlite3HashClear(&db->aFunc); +  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ +  if( db->pValue ){ +    sqlite3ValueFree(db->pValue); +  } +  if( db->pErr ){ +    sqlite3ValueFree(db->pErr); +  } + +  db->magic = SQLITE_MAGIC_ERROR; +  sqliteFree(db); +  return SQLITE_OK; +} + +/* +** Rollback all database files. +*/ +void sqlite3RollbackAll(sqlite3 *db){ +  int i; +  for(i=0; i<db->nDb; i++){ +    if( db->aDb[i].pBt ){ +      sqlite3BtreeRollback(db->aDb[i].pBt); +      db->aDb[i].inTrans = 0; +    } +  } +  sqlite3ResetInternalSchema(db, 0); +} + +/* +** Return a static string that describes the kind of error specified in the +** argument. +*/ +const char *sqlite3ErrStr(int rc){ +  const char *z; +  switch( rc ){ +    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_INTERNAL:   z = "internal SQLite implementation flaw";   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_NOTFOUND:   z = "table or record not found";             break; +    case SQLITE_FULL:       z = "database is full";                      break; +    case SQLITE_CANTOPEN:   z = "unable to open database file";          break; +    case SQLITE_PROTOCOL:   z = "database locking protocol failure";     break; +    case SQLITE_EMPTY:      z = "table contains no data";                break; +    case SQLITE_SCHEMA:     z = "database schema has changed";           break; +    case SQLITE_TOOBIG:     z = "too much data for one table row";       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 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 *Timeout,           /* Maximum amount of time to wait */ + int count                /* Number of times table has been busy */ +){ +#if SQLITE_MIN_SLEEP_MS==1 +  static const char delays[] = +     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50,  50, 100}; +  static const short int totals[] = +     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228, 287}; +# define NDELAY (sizeof(delays)/sizeof(delays[0])) +  ptr timeout = (ptr)Timeout; +  ptr delay, prior; + +  if( count <= NDELAY ){ +    delay = delays[count-1]; +    prior = totals[count-1]; +  }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(delay); +  return 1; +#else +  int timeout = (int)Timeout; +  if( (count+1)*1000 > timeout ){ +    return 0; +  } +  sqlite3OsSleep(1000); +  return 1; +#endif +} + +/* +** 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 +){ +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  db->busyHandler.xFunc = xBusy; +  db->busyHandler.pArg = pArg; +  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( !sqlite3SafetyCheck(db) ){ +    if( nOps>0 ){ +      db->xProgress = xProgress; +      db->nProgressOps = nOps; +      db->pProgressArg = pArg; +    }else{ +      db->xProgress = 0; +      db->nProgressOps = 0; +      db->pProgressArg = 0; +    } +  } +} +#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 ){ +    sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)(ptr)ms); +  }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( !sqlite3SafetyCheck(db) ){ +    db->flags |= SQLITE_Interrupt; +  } +} + +/* +** Windows systems should call this routine to free memory that +** is returned in the in the errmsg parameter of sqlite3_open() when +** SQLite is a DLL.  For some reason, it does not work to call free() +** directly. +** +** Note that we need to call free() not sqliteFree() here. +*/ +void sqlite3_free(char *p){ free(p); } + +/* +** Create new user functions. +*/ +int sqlite3_create_function( +  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; + +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  if( zFunctionName==0 || +      (xFunc && (xFinal || xStep)) ||  +      (!xFunc && (xFinal && !xStep)) || +      (!xFunc && (!xFinal && xStep)) || +      (nArg<-1 || nArg>127) || +      (255<(nName = strlen(zFunctionName))) ){ +    return SQLITE_ERROR; +  } +   +  /* 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 = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF8, +         pUserData, xFunc, xStep, xFinal); +    if( rc!=SQLITE_OK ) return rc; +    rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF16LE, +        pUserData, xFunc, xStep, xFinal); +    if( rc!=SQLITE_OK ) return rc; +    enc = SQLITE_UTF16BE; +  } + +  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); +  if( p==0 ) return SQLITE_NOMEM; +  p->xFunc = xFunc; +  p->xStep = xStep; +  p->xFinalize = xFinal; +  p->pUserData = pUserData; +  return SQLITE_OK; +} +int sqlite3_create_function16( +  sqlite3 *db, +  const void *zFunctionName, +  int nArg, +  int eTextRep, +  void *pUserData, +  void (*xFunc)(sqlite3_context*,int,sqlite3_value**), +  void (*xStep)(sqlite3_context*,int,sqlite3_value**), +  void (*xFinal)(sqlite3_context*) +){ +  int rc; +  char const *zFunc8; +  sqlite3_value *pTmp; + +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  pTmp = sqlite3GetTransientValue(db); +  sqlite3ValueSetStr(pTmp, -1, zFunctionName, SQLITE_UTF16NATIVE,SQLITE_STATIC); +  zFunc8 = sqlite3ValueText(pTmp, SQLITE_UTF8); + +  if( !zFunc8 ){ +    return SQLITE_NOMEM; +  } +  rc = sqlite3_create_function(db, zFunc8, nArg, eTextRep,  +      pUserData, xFunc, xStep, xFinal); +  return rc; +} + +/* +** 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 +** sqlite3_exec(). +*/ +void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ +  void *pOld = db->pTraceArg; +  db->xTrace = xTrace; +  db->pTraceArg = pArg; +  return pOld; +} + +/*** EXPERIMENTAL *** +** +** Register a function to be invoked when a transaction comments. +** If either 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 = db->pCommitArg; +  db->xCommitCallback = xCallback; +  db->pCommitArg = pArg; +  return pOld; +} + + +/* +** 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 for temporary use only and is deleted as soon as the connection +** is closed. +** +** A temporary database can be either a disk file (that is automatically +** deleted when the file is closed) or a set of red-black trees held 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 */ +  Btree **ppBtree           /* Pointer to new Btree object written here */ +){ +  int btree_flags = 0; +  int rc; +   +  assert( ppBtree != 0); +  if( omitJournal ){ +    btree_flags |= BTREE_OMIT_JOURNAL; +  } +  if( zFilename==0 ){ +#ifndef TEMP_STORE +# define TEMP_STORE 1 +#endif +#if TEMP_STORE==0 +    /* Do nothing */ +#endif +#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 +  } + +  rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags); +  if( rc==SQLITE_OK ){ +    sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); +    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( sqlite3_malloc_failed ){ +    return sqlite3ErrStr(SQLITE_NOMEM); +  } +  if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ +    return sqlite3ErrStr(SQLITE_MISUSE); +  } +  z = sqlite3_value_text(db->pErr); +  if( z==0 ){ +    z = sqlite3ErrStr(db->errCode); +  } +  return z; +} + +/* +** 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( sqlite3_malloc_failed ){ +    return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); +  } +  if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ +    return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); +  } +  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); +  } +  return z; +} + +/* +** Return the most recent error code generated by an SQLite routine. +*/ +int sqlite3_errcode(sqlite3 *db){ +  if( sqlite3_malloc_failed ){ +    return SQLITE_NOMEM; +  } +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  return db->errCode; +} + +/* +** 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; + +  for(iDb=0; allOk && iDb<db->nDb; 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].schema_cookie ){ +        allOk = 0; +      } +      sqlite3BtreeCloseCursor(curTemp); +    } +  } +  return allOk; +} + +/* +** Compile the UTF-8 encoded SQL statement zSql into a statement handle. +*/ +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 */ +){ +  Parse sParse; +  char *zErrMsg = 0; +  int rc = SQLITE_OK; + +  if( sqlite3_malloc_failed ){ +    return SQLITE_NOMEM; +  } + +  assert( ppStmt ); +  *ppStmt = 0; +  if( sqlite3SafetyOn(db) ){ +    return SQLITE_MISUSE; +  } + +  memset(&sParse, 0, sizeof(sParse)); +  sParse.db = db; +  sqlite3RunParser(&sParse, zSql, &zErrMsg); + +  if( sqlite3_malloc_failed ){ +    rc = SQLITE_NOMEM; +    sqlite3RollbackAll(db); +    sqlite3ResetInternalSchema(db, 0); +    db->flags &= ~SQLITE_InTrans; +    goto prepare_out; +  } +  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; +  if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){ +    sParse.rc = SQLITE_SCHEMA; +  } +  if( sParse.rc==SQLITE_SCHEMA ){ +    sqlite3ResetInternalSchema(db, 0); +  } +  if( pzTail ) *pzTail = sParse.zTail; +  rc = sParse.rc; + +  if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ +    sqlite3VdbeSetNumCols(sParse.pVdbe, 5); +    sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); +    sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); +    sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); +    sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); +    sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); +  }  + +prepare_out: +  if( sqlite3SafetyOff(db) ){ +    rc = SQLITE_MISUSE; +  } +  if( rc==SQLITE_OK ){ +    *ppStmt = (sqlite3_stmt*)sParse.pVdbe; +  }else if( sParse.pVdbe ){ +    sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); +  } + +  if( zErrMsg ){ +    sqlite3Error(db, rc, "%s", zErrMsg); +    sqliteFree(zErrMsg); +  }else{ +    sqlite3Error(db, rc, 0); +  } +  return rc; +} + +/* +** Compile the UTF-16 encoded SQL statement zSql into a statement handle. +*/ +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 */ +){ +  /* 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 const *zSql8 = 0; +  char const *zTail8 = 0; +  int rc; +  sqlite3_value *pTmp; + +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  pTmp = sqlite3GetTransientValue(db); +  sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); +  zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); +  if( !zSql8 ){ +    sqlite3Error(db, SQLITE_NOMEM, 0); +    return SQLITE_NOMEM; +  } +  rc = sqlite3_prepare(db, zSql8, -1, 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); +  } +  +  return rc; +} + +/* +** 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. The fourth argument, "def_enc" is one of the TEXT_* +** macros from sqliteInt.h. If we end up creating a new database file +** (not opening an existing one), the text encoding of the database +** will be set to this value. +*/ +static int openDatabase( +  const char *zFilename, /* Database filename UTF-8 encoded */ +  sqlite3 **ppDb         /* OUT: Returned database handle */ +){ +  sqlite3 *db; +  int rc, i; +  char *zErrMsg = 0; + +  /* Allocate the sqlite data structure */ +  db = sqliteMalloc( sizeof(sqlite3) ); +  if( db==0 ) goto opendb_out; +  db->priorNewRowid = 0; +  db->magic = SQLITE_MAGIC_BUSY; +  db->nDb = 2; +  db->aDb = db->aDbStatic; +  db->enc = SQLITE_UTF8; +  db->autoCommit = 1; +  /* db->flags |= SQLITE_ShortColNames; */ +  sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); +  sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); +  for(i=0; i<db->nDb; i++){ +    sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); +    sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); +    sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); +    sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); +  } +   +  /* 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. +  */ +  sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binaryCollatingFunc); +  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16LE, 0,binaryCollatingFunc); +  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16BE, 0,binaryCollatingFunc); +  db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0); +  if( !db->pDfltColl ){ +    rc = db->errCode; +    assert( rc!=SQLITE_OK ); +    db->magic = SQLITE_MAGIC_CLOSED; +    goto opendb_out; +  } + +  /* Also add a UTF-8 case-insensitive collation sequence. */ +  sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); + +  /* Open the backend database driver */ +  rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); +  if( rc!=SQLITE_OK ){ +    sqlite3Error(db, rc, 0); +    db->magic = SQLITE_MAGIC_CLOSED; +    goto opendb_out; +  } +  db->aDb[0].zName = "main"; +  db->aDb[1].zName = "temp"; + +  /* 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].safety_level = 3; +  db->aDb[1].safety_level = 1; + +  /* 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. +  */ +  sqlite3RegisterBuiltinFunctions(db); +  if( rc==SQLITE_OK ){ +    sqlite3Error(db, SQLITE_OK, 0); +    db->magic = SQLITE_MAGIC_OPEN; +  }else{ +    sqlite3Error(db, rc, "%s", zErrMsg, 0); +    if( zErrMsg ) sqliteFree(zErrMsg); +    db->magic = SQLITE_MAGIC_CLOSED; +  } + +opendb_out: +  if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){ +    sqlite3Error(db, SQLITE_NOMEM, 0); +  } +  *ppDb = db; +  return sqlite3_errcode(db); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open( +  const char *zFilename,  +  sqlite3 **ppDb  +){ +  return openDatabase(zFilename, ppDb); +} + +/* +** 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 */ +  int rc = SQLITE_NOMEM; +  sqlite3_value *pVal; + +  assert( ppDb ); +  *ppDb = 0; +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); +  zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); +  if( zFilename8 ){ +    rc = openDatabase(zFilename8, ppDb); +    if( rc==SQLITE_OK && *ppDb ){ +      sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); +    } +  } +  if( pVal ){ +    sqlite3ValueFree(pVal); +  } + +  return rc; +} + +/* +** The following routine destroys a virtual machine that is created by +** the sqlite3_compile() routine. The integer returned is an SQLITE_ +** success/failure code that describes the result of executing the virtual +** machine. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt){ +  int rc; +  if( pStmt==0 ){ +    rc = SQLITE_OK; +  }else{ +    rc = sqlite3VdbeFinalize((Vdbe*)pStmt); +  } +  return rc; +} + +/* +** Terminate the current execution of an SQL statement and reset it +** back to its starting state so that it can be reused. A success code from +** the prior execution is returned. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_reset(sqlite3_stmt *pStmt){ +  int rc; +  if( pStmt==0 ){ +    rc = SQLITE_OK; +  }else{ +    rc = sqlite3VdbeReset((Vdbe*)pStmt); +    sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); +  } +  return rc; +} + +/* +** 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*) +){ +  CollSeq *pColl; +  int rc = SQLITE_OK; +   +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } + +  /* 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( enc==SQLITE_UTF16 ){ +    enc = SQLITE_UTF16NATIVE; +  } + +  if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){ +    sqlite3Error(db, SQLITE_ERROR,  +        "Param 3 to sqlite3_create_collation() must be one of " +        "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" +    ); +    return SQLITE_ERROR; +  } +  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); +  if( 0==pColl ){ +   rc = SQLITE_NOMEM; +  }else{ +    pColl->xCmp = xCompare; +    pColl->pUser = pCtx; +    pColl->enc = enc; +  } +  sqlite3Error(db, rc, 0); +  return rc; +} + +/* +** 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*) +){ +  char const *zName8; +  sqlite3_value *pTmp; +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  pTmp = sqlite3GetTransientValue(db); +  sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC); +  zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8); +  return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare); +} + +/* +** 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*) +){ +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  db->xCollNeeded = xCollNeeded; +  db->xCollNeeded16 = 0; +  db->pCollNeededArg = pCollNeededArg; +  return SQLITE_OK; +} + +/* +** 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*) +){ +  if( sqlite3SafetyCheck(db) ){ +    return SQLITE_MISUSE; +  } +  db->xCollNeeded = 0; +  db->xCollNeeded16 = xCollNeeded16; +  db->pCollNeededArg = pCollNeededArg; +  return SQLITE_OK; +} diff --git a/ext/pdo_sqlite/sqlite/src/md5.c b/ext/pdo_sqlite/sqlite/src/md5.c new file mode 100644 index 0000000000..32fcb6b680 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/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 <tcl.h> +#include <string.h> +#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<<s | 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; i<argc; i++){ +    const char *zData = sqlite3_value_text(argv[i]); +    if( zData ){ +      MD5Update(p, zData, strlen(zData)); +    } +  } +} +static void md5finalize(sqlite3_context *context){ +  MD5Context *p; +  unsigned char digest[16]; +  char zBuf[33]; +  p = sqlite3_aggregate_context(context, sizeof(*p)); +  MD5Final(digest,p); +  DigestToBase16(digest, zBuf); +  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +void Md5_Register(sqlite3 *db){ +  sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,  +      md5step, md5finalize); +} diff --git a/ext/pdo_sqlite/sqlite/src/opcodes.c b/ext/pdo_sqlite/sqlite/src/opcodes.c new file mode 100644 index 0000000000..b6f012198d --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/opcodes.c @@ -0,0 +1,128 @@ +/* Automatically generated.  Do not edit */ +/* See the mkopcodec.h script for details. */ +const char *const sqlite3OpcodeNames[] = { "?", +  "ContextPop", +  "IntegrityCk", +  "DropTrigger", +  "DropIndex", +  "Recno", +  "KeyAsData", +  "Delete", +  "MoveGt", +  "VerifyCookie", +  "Push", +  "Dup", +  "Blob", +  "IdxGT", +  "IdxRecno", +  "RowKey", +  "PutStrKey", +  "IsUnique", +  "SetNumColumns", +  "IdxIsNull", +  "NullRow", +  "OpenPseudo", +  "OpenWrite", +  "OpenRead", +  "Transaction", +  "AutoCommit", +  "Pop", +  "Halt", +  "Vacuum", +  "ListRead", +  "RowData", +  "NotExists", +  "MoveLe", +  "SetCookie", +  "Variable", +  "AggNext", +  "AggReset", +  "Sort", +  "IdxDelete", +  "ResetCount", +  "OpenTemp", +  "IdxColumn", +  "Integer", +  "AggSet", +  "CreateIndex", +  "IdxPut", +  "MoveLt", +  "Return", +  "MemLoad", +  "SortNext", +  "IdxLT", +  "Rewind", +  "AddImm", +  "AggFunc", +  "AggInit", +  "MemIncr", +  "ListReset", +  "Clear", +  "Or", +  "And", +  "Not", +  "PutIntKey", +  "If", +  "Callback", +  "IsNull", +  "NotNull", +  "Ne", +  "Eq", +  "Gt", +  "Le", +  "Lt", +  "Ge", +  "BitAnd", +  "BitOr", +  "ShiftLeft", +  "ShiftRight", +  "Add", +  "Subtract", +  "Multiply", +  "Divide", +  "Remainder", +  "Concat", +  "Negative", +  "SortReset", +  "BitNot", +  "String8", +  "SortPut", +  "Last", +  "NotFound", +  "MakeRecord", +  "String", +  "Goto", +  "AggFocus", +  "DropTable", +  "Column", +  "Noop", +  "AggGet", +  "CreateTable", +  "NewRecno", +  "Found", +  "Distinct", +  "Close", +  "Statement", +  "IfNot", +  "Pull", +  "MemStore", +  "Next", +  "Prev", +  "MoveGe", +  "MustBeInt", +  "ForceInt", +  "CollSeq", +  "Gosub", +  "ContextPush", +  "ListRewind", +  "ListWrite", +  "ParseSchema", +  "Destroy", +  "IdxGE", +  "FullKey", +  "ReadCookie", +  "AbsValue", +  "Real", +  "HexBlob", +  "Function", +}; diff --git a/ext/pdo_sqlite/sqlite/src/opcodes.h b/ext/pdo_sqlite/sqlite/src/opcodes.h new file mode 100644 index 0000000000..7b792c5a11 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/opcodes.h @@ -0,0 +1,126 @@ +/* Automatically generated.  Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_ContextPop                  1 +#define OP_IntegrityCk                 2 +#define OP_DropTrigger                 3 +#define OP_DropIndex                   4 +#define OP_Recno                       5 +#define OP_KeyAsData                   6 +#define OP_Delete                      7 +#define OP_MoveGt                      8 +#define OP_VerifyCookie                9 +#define OP_Push                        10 +#define OP_Dup                         11 +#define OP_Blob                        12 +#define OP_IdxGT                       13 +#define OP_IdxRecno                    14 +#define OP_RowKey                      15 +#define OP_PutStrKey                   16 +#define OP_IsUnique                    17 +#define OP_SetNumColumns               18 +#define OP_Eq                          67 +#define OP_IdxIsNull                   19 +#define OP_NullRow                     20 +#define OP_OpenPseudo                  21 +#define OP_OpenWrite                   22 +#define OP_OpenRead                    23 +#define OP_Transaction                 24 +#define OP_AutoCommit                  25 +#define OP_Negative                    82 +#define OP_Pop                         26 +#define OP_Halt                        27 +#define OP_Vacuum                      28 +#define OP_ListRead                    29 +#define OP_RowData                     30 +#define OP_NotExists                   31 +#define OP_MoveLe                      32 +#define OP_SetCookie                   33 +#define OP_Variable                    34 +#define OP_AggNext                     35 +#define OP_AggReset                    36 +#define OP_Sort                        37 +#define OP_IdxDelete                   38 +#define OP_ResetCount                  39 +#define OP_OpenTemp                    40 +#define OP_IdxColumn                   41 +#define OP_NotNull                     65 +#define OP_Ge                          71 +#define OP_Remainder                   80 +#define OP_Divide                      79 +#define OP_Integer                     42 +#define OP_AggSet                      43 +#define OP_CreateIndex                 44 +#define OP_IdxPut                      45 +#define OP_MoveLt                      46 +#define OP_And                         59 +#define OP_ShiftLeft                   74 +#define OP_Real                        122 +#define OP_Return                      47 +#define OP_MemLoad                     48 +#define OP_SortNext                    49 +#define OP_IdxLT                       50 +#define OP_Rewind                      51 +#define OP_Gt                          68 +#define OP_AddImm                      52 +#define OP_Subtract                    77 +#define OP_AggFunc                     53 +#define OP_AggInit                     54 +#define OP_MemIncr                     55 +#define OP_ListReset                   56 +#define OP_Clear                       57 +#define OP_PutIntKey                   61 +#define OP_IsNull                      64 +#define OP_If                          62 +#define OP_Callback                    63 +#define OP_SortReset                   83 +#define OP_SortPut                     86 +#define OP_Last                        87 +#define OP_NotFound                    88 +#define OP_MakeRecord                  89 +#define OP_BitAnd                      72 +#define OP_Add                         76 +#define OP_HexBlob                     123 +#define OP_String                      90 +#define OP_Goto                        91 +#define OP_AggFocus                    92 +#define OP_DropTable                   93 +#define OP_Column                      94 +#define OP_Noop                        95 +#define OP_Not                         60 +#define OP_Le                          69 +#define OP_BitOr                       73 +#define OP_Multiply                    78 +#define OP_String8                     85 +#define OP_AggGet                      96 +#define OP_CreateTable                 97 +#define OP_NewRecno                    98 +#define OP_Found                       99 +#define OP_Distinct                    100 +#define OP_Close                       101 +#define OP_Statement                   102 +#define OP_IfNot                       103 +#define OP_Pull                        104 +#define OP_MemStore                    105 +#define OP_Next                        106 +#define OP_Prev                        107 +#define OP_MoveGe                      108 +#define OP_Lt                          70 +#define OP_Ne                          66 +#define OP_MustBeInt                   109 +#define OP_ForceInt                    110 +#define OP_ShiftRight                  75 +#define OP_CollSeq                     111 +#define OP_Gosub                       112 +#define OP_ContextPush                 113 +#define OP_ListRewind                  114 +#define OP_ListWrite                   115 +#define OP_ParseSchema                 116 +#define OP_Destroy                     117 +#define OP_IdxGE                       118 +#define OP_FullKey                     119 +#define OP_ReadCookie                  120 +#define OP_BitNot                      84 +#define OP_AbsValue                    121 +#define OP_Or                          58 +#define OP_Function                    124 +#define OP_Concat                      81 diff --git a/ext/pdo_sqlite/sqlite/src/os.h b/ext/pdo_sqlite/sqlite/src/os.h new file mode 100644 index 0000000000..fc478baa93 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os.h @@ -0,0 +1,197 @@ +/* +** 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. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows or MacOS. +** +** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. +**      The MacOS build is designed to use CodeWarrior (tested with v8) +*/ +#if !defined(OS_UNIX) && !defined(OS_TEST) +# ifndef OS_WIN +#  ifndef OS_MAC +#    if defined(__MACOS__) +#      define OS_MAC 1 +#      define OS_WIN 0 +#      define OS_UNIX 0 +#    elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +#      define OS_MAC 0 +#      define OS_WIN 1 +#      define OS_UNIX 0 +#    else +#      define OS_MAC 0 +#      define OS_WIN 0 +#      define OS_UNIX 1 +#    endif +#  else +#    define OS_WIN 0 +#    define OS_UNIX 0 +#  endif +# else +#  define OS_MAC 0 +#  define OS_UNIX 0 +# endif +#else +# define OS_MAC 0 +# ifndef OS_WIN +#  define OS_WIN 0 +# endif +#endif + +/* +** Invoke the appropriate operating-system specific header file. +*/ +#if OS_TEST +# include "os_test.h" +#endif +#if OS_UNIX +# include "os_unix.h" +#endif +#if OS_WIN +# include "os_win.h" +#endif +#if OS_MAC +# include "os_mac.h" +#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 -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. +*/ +#ifndef TEMP_FILE_PREFIX +# define TEMP_FILE_PREFIX "sqlite_" +#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 os.h so that Unix can use the same +** byte ranges for locking.  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. +** +*/ +#define PENDING_BYTE      0x40000000  /* First byte past the 1GB boundary */ +/* #define PENDING_BYTE     0x5400   // Page 20 - for testing */ +#define RESERVED_BYTE     (PENDING_BYTE+1) +#define SHARED_FIRST      (PENDING_BYTE+2) +#define SHARED_SIZE       510 + + +int sqlite3OsDelete(const char*); +int sqlite3OsFileExists(const char*); +int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); +int sqlite3OsOpenExclusive(const char*, OsFile*, int); +int sqlite3OsOpenReadOnly(const char*, OsFile*); +int sqlite3OsOpenDirectory(const char*, OsFile*); +int sqlite3OsSyncDirectory(const char*); +int sqlite3OsTempFileName(char*); +int sqlite3OsClose(OsFile*); +int sqlite3OsRead(OsFile*, void*, int amt); +int sqlite3OsWrite(OsFile*, const void*, int amt); +int sqlite3OsSeek(OsFile*, i64 offset); +int sqlite3OsSync(OsFile*); +int sqlite3OsTruncate(OsFile*, i64 size); +int sqlite3OsFileSize(OsFile*, i64 *pSize); +int sqlite3OsRandomSeed(char*); +int sqlite3OsSleep(int ms); +int sqlite3OsCurrentTime(double*); +int sqlite3OsFileModTime(OsFile*, double*); +void sqlite3OsEnterMutex(void); +void sqlite3OsLeaveMutex(void); +char *sqlite3OsFullPathname(const char*); +int sqlite3OsLock(OsFile*, int); +int sqlite3OsUnlock(OsFile*, int); +int sqlite3OsCheckReservedLock(OsFile *id); + +#endif /* _SQLITE_OS_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/os_common.h b/ext/pdo_sqlite/sqlite/src/os_common.h new file mode 100644 index 0000000000..94311b9604 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_common.h @@ -0,0 +1,107 @@ +/* +** 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 + + +int sqlite3_os_trace = 0; +#ifdef SQLITE_DEBUG +static int last_page = 0; +#define SEEK(X)           last_page=(X) +#define TRACE1(X)         if( sqlite3_os_trace ) sqlite3DebugPrintf(X) +#define TRACE2(X,Y)       if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) +#define TRACE3(X,Y,Z)     if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) +#define TRACE4(X,Y,Z,A)   if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A) +#define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B) +#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C) +#define TRACE7(X,Y,Z,A,B,C,D) \ +    if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D) +#else +#define SEEK(X) +#define TRACE1(X) +#define TRACE2(X,Y) +#define TRACE3(X,Y,Z) +#define TRACE4(X,Y,Z,A) +#define TRACE5(X,Y,Z,A,B) +#define TRACE6(X,Y,Z,A,B,C) +#define TRACE7(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_pending = 0; +int sqlite3_diskfull_pending = 0; +#define SimulateIOError(A)  \ +   if( sqlite3_io_error_pending ) \ +     if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; } +static void local_ioerr(){ +  sqlite3_io_error_pending = 0;  /* Really just a place to set a breakpoint */ +} +#define SimulateDiskfullError \ +   if( sqlite3_diskfull_pending ) \ +     if( sqlite3_diskfull_pending-- == 1 ){ local_ioerr(); return SQLITE_FULL; } +#else +#define SimulateIOError(A) +#define SimulateDiskfullError +#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/ext/pdo_sqlite/sqlite/src/os_mac.c b/ext/pdo_sqlite/sqlite/src/os_mac.c new file mode 100644 index 0000000000..f84c168d4a --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_mac.c @@ -0,0 +1,738 @@ +/* +** 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 classic mac.  Mac OS X +** uses the os_unix.c file, not this one. +*/ +#include "sqliteInt.h" +#include "os.h" +#if OS_MAC               /* This file used on classic mac only */ + +#include <extras.h> +#include <path2fss.h> +#include <TextUtils.h> +#include <FinderRegistry.h> +#include <Folders.h> +#include <Timer.h> +#include <OSUtils.h> + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# include <Multiprocessing.h> +# define SQLITE_MACOS_MULTITASKING 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Delete the named file +*/ +int sqlite3OsDelete(const char *zFilename){ +  unlink(zFilename); +  return SQLITE_OK; +} + +/* +** Return TRUE if the named file exists. +*/ +int sqlite3OsFileExists(const char *zFilename){ +  return access(zFilename, 0)==0; +} + +/* +** Attempt to open a file for both reading and writing.  If that +** fails, try opening it read-only.  If the file does not exist, +** try to create it. +** +** On success, a handle for the open file is written to *id +** and *pReadonly is set to 0 if the file was opened for reading and +** writing or 1 if the file was opened read-only.  The function returns +** SQLITE_OK. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id and *pReadonly unchanged. +*/ +int sqlite3OsOpenReadWrite( +  const char *zFilename, +  OsFile *id, +  int *pReadonly +){ +  FSSpec fsSpec; +# ifdef _LARGE_FILE +  HFSUniStr255 dfName; +  FSRef fsRef; +  if( __path2fss(zFilename, &fsSpec) != noErr ){ +    if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) +      return SQLITE_CANTOPEN; +  } +  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) +    return SQLITE_CANTOPEN; +  FSGetDataForkName(&dfName); +  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, +                 fsRdWrShPerm, &(id->refNum)) != noErr ){ +    if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, +                   fsRdWrPerm, &(id->refNum)) != noErr ){ +      if (FSOpenFork(&fsRef, dfName.length, dfName.unicode, +                   fsRdPerm, &(id->refNum)) != noErr ) +        return SQLITE_CANTOPEN; +      else +        *pReadonly = 1; +    } else +      *pReadonly = 0; +  } else +    *pReadonly = 0; +# else +  __path2fss(zFilename, &fsSpec); +  if( !sqlite3OsFileExists(zFilename) ){ +    if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) +      return SQLITE_CANTOPEN; +  } +  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){ +    if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){ +      if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) +        return SQLITE_CANTOPEN; +      else +        *pReadonly = 1; +    } else +      *pReadonly = 0; +  } else +    *pReadonly = 0; +# endif +  if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ +    id->refNumRF = -1; +  } +  id->locked = 0; +  id->delOnClose = 0; +  OpenCounter(+1); +  return SQLITE_OK; +} + + +/* +** Attempt to open a new file for exclusive access by this process. +** The file will be opened for both reading and writing.  To avoid +** a potential security problem, we do not allow the file to have +** previously existed.  Nor do we allow the file to be a symbolic +** link. +** +** If delFlag is true, then make arrangements to automatically delete +** the file when it is closed. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +  FSSpec fsSpec; +# ifdef _LARGE_FILE +  HFSUniStr255 dfName; +  FSRef fsRef; +  __path2fss(zFilename, &fsSpec); +  if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) +    return SQLITE_CANTOPEN; +  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) +    return SQLITE_CANTOPEN; +  FSGetDataForkName(&dfName); +  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, +                 fsRdWrPerm, &(id->refNum)) != noErr ) +    return SQLITE_CANTOPEN; +# else +  __path2fss(zFilename, &fsSpec); +  if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) +    return SQLITE_CANTOPEN; +  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ) +    return SQLITE_CANTOPEN; +# endif +  id->refNumRF = -1; +  id->locked = 0; +  id->delOnClose = delFlag; +  if (delFlag) +    id->pathToDel = sqlite3OsFullPathname(zFilename); +  OpenCounter(+1); +  return SQLITE_OK; +} + +/* +** Attempt to open a new file for read-only access. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +  FSSpec fsSpec; +# ifdef _LARGE_FILE +  HFSUniStr255 dfName; +  FSRef fsRef; +  if( __path2fss(zFilename, &fsSpec) != noErr ) +    return SQLITE_CANTOPEN; +  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) +    return SQLITE_CANTOPEN; +  FSGetDataForkName(&dfName); +  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, +                 fsRdPerm, &(id->refNum)) != noErr ) +    return SQLITE_CANTOPEN; +# else +  __path2fss(zFilename, &fsSpec); +  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) +    return SQLITE_CANTOPEN; +# endif +  if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ +    id->refNumRF = -1; +  } +  id->locked = 0; +  id->delOnClose = 0; +  OpenCounter(+1); +  return SQLITE_OK; +} + +/* +** Attempt to open a file descriptor for the directory that contains a +** file.  This file descriptor can be used to fsync() the directory +** in order to make sure the creation of a new file is actually written +** to disk. +** +** This routine is only meaningful for Unix.  It is a no-op under +** windows since windows does not support hard links. +** +** On success, a handle for a previously open file is at *id is +** updated with the new directory file descriptor and SQLITE_OK is +** returned. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id unchanged. +*/ +int sqlite3OsOpenDirectory( +  const char *zDirname, +  OsFile *id +){ +  return SQLITE_OK; +} + +/* +** Create a temporary file name in zBuf.  zBuf must be big enough to +** hold at least SQLITE_TEMPNAME_SIZE characters. +*/ +int sqlite3OsTempFileName(char *zBuf){ +  static char zChars[] = +    "abcdefghijklmnopqrstuvwxyz" +    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +    "0123456789"; +  int i, j; +  char zTempPath[SQLITE_TEMPNAME_SIZE]; +  char zdirName[32]; +  CInfoPBRec infoRec; +  Str31 dirName; +  memset(&infoRec, 0, sizeof(infoRec)); +  memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE); +  if( FindFolder(kOnSystemDisk, kTemporaryFolderType,  kCreateFolder, +       &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){ +    infoRec.dirInfo.ioNamePtr = dirName; +    do{ +      infoRec.dirInfo.ioFDirIndex = -1; +      infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID; +      if( PBGetCatInfoSync(&infoRec) == noErr ){ +        CopyPascalStringToC(dirName, zdirName); +        i = strlen(zdirName); +        memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath)); +        strcpy(zTempPath, zdirName); +        zTempPath[i] = ':'; +      }else{ +        *zTempPath = 0; +        break; +      } +    } while( infoRec.dirInfo.ioDrDirID != fsRtDirID ); +  } +  if( *zTempPath == 0 ) +    getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24); +  for(;;){ +    sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zTempPath); +    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; +    if( !sqlite3OsFileExists(zBuf) ) break; +  } +  return SQLITE_OK;  +} + +/* +** Close a file. +*/ +int sqlite3OsClose(OsFile *id){ +  if( id->refNumRF!=-1 ) +    FSClose(id->refNumRF); +# ifdef _LARGE_FILE +  FSCloseFork(id->refNum); +# else +  FSClose(id->refNum); +# endif +  if( id->delOnClose ){ +    unlink(id->pathToDel); +    sqliteFree(id->pathToDel); +  } +  OpenCounter(-1); +  return SQLITE_OK; +} + +/* +** 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 sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +  int got; +  SimulateIOError(SQLITE_IOERR); +  TRACE2("READ %d\n", last_page); +# ifdef _LARGE_FILE +  FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got); +# else +  got = amt; +  FSRead(id->refNum, &got, pBuf); +# endif +  if( got==amt ){ +    return SQLITE_OK; +  }else{ +    return SQLITE_IOERR; +  } +} + +/* +** Write data from a buffer into a file.  Return SQLITE_OK on success +** or some other error code on failure. +*/ +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +  OSErr oserr; +  int wrote = 0; +  SimulateIOError(SQLITE_IOERR); +  TRACE2("WRITE %d\n", last_page); +  while( amt>0 ){ +# ifdef _LARGE_FILE +    oserr = FSWriteFork(id->refNum, fsAtMark, 0, +                        (ByteCount)amt, pBuf, (ByteCount*)&wrote); +# else +    wrote = amt; +    oserr = FSWrite(id->refNum, &wrote, pBuf); +# endif +    if( wrote == 0 || oserr != noErr) +      break; +    amt -= wrote; +    pBuf = &((char*)pBuf)[wrote]; +  } +  if( oserr != noErr || amt>wrote ){ +    return SQLITE_FULL; +  } +  return SQLITE_OK; +} + +/* +** Move the read/write pointer in a file. +*/ +int sqlite3OsSeek(OsFile *id, off_t offset){ +  off_t curSize; +  SEEK(offset/1024 + 1); +  if( sqlite3OsFileSize(id, &curSize) != SQLITE_OK ){ +    return SQLITE_IOERR; +  } +  if( offset >= curSize ){ +    if( sqlite3OsTruncate(id, offset+1) != SQLITE_OK ){ +      return SQLITE_IOERR; +    } +  } +# ifdef _LARGE_FILE +  if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){ +# else +  if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){ +# endif +    return SQLITE_IOERR; +  }else{ +    return SQLITE_OK; +  } +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** 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. +*/ +int sqlite3OsSync(OsFile *id){ +# ifdef _LARGE_FILE +  if( FSFlushFork(id->refNum) != noErr ){ +# else +  ParamBlockRec params; +  memset(¶ms, 0, sizeof(ParamBlockRec)); +  params.ioParam.ioRefNum = id->refNum; +  if( PBFlushFileSync(¶ms) != noErr ){ +# endif +    return SQLITE_IOERR; +  }else{ +    return SQLITE_OK; +  } +} + +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ +  SimulateIOError(SQLITE_IOERR); +  return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +int sqlite3OsTruncate(OsFile *id, off_t nByte){ +  SimulateIOError(SQLITE_IOERR); +# ifdef _LARGE_FILE +  if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){ +# else +  if( SetEOF(id->refNum, nByte) != noErr ){ +# endif +    return SQLITE_IOERR; +  }else{ +    return SQLITE_OK; +  } +} + +/* +** Determine the current size of a file in bytes +*/ +int sqlite3OsFileSize(OsFile *id, off_t *pSize){ +# ifdef _LARGE_FILE +  if( FSGetForkSize(id->refNum, pSize) != noErr){ +# else +  if( GetEOF(id->refNum, pSize) != noErr ){ +# endif +    return SQLITE_IOERR; +  }else{ +    return SQLITE_OK; +  } +} + +/* +** Windows file locking notes:  [similar issues apply to MacOS] +** +** 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. +** (This is a design error on the part of Windows, but there is nothing +** we can do about that.)  So the region used for locking is at the +** end of the file where it is unlikely to ever interfere with an +** actual read attempt. +** +** A database read 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. +** A database write lock is obtained by locking all bytes in the range. +** There can only be one writer. +** +** A lock is obtained on the first byte of the lock range before acquiring +** either a read lock or a write lock.  This prevents two processes from +** attempting to get a lock at a same time.  The semantics of  +** sqlite3OsReadLock() require that if there is already a write lock, that +** lock is converted into a read lock atomically.  The lock on the first +** byte allows us to drop the old write lock and get the read lock without +** another process jumping into the middle and messing us up.  The same +** argument applies to sqlite3OsWriteLock(). +** +** 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. +** +** Note: On MacOS we use the resource fork for locking. +** +** The following #defines specify the range of bytes used for locking. +** N_LOCKBYTE is the number of bytes available for doing the locking. +** The first byte used to hold the lock while the lock is changing does +** not count toward this number.  FIRST_LOCKBYTE is the address of +** the first byte in the range of bytes used for locking. +*/ +#define N_LOCKBYTE       10239 +#define FIRST_LOCKBYTE   (0x000fffff - N_LOCKBYTE) + +/* +** Change the status of the lock on the file "id" to be a readlock. +** If the file was write locked, then this reduces the lock to a read. +** If the file was read locked, then this acquires a new read lock. +** +** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this +** library was compiled with large file support (LFS) but LFS is not +** available on the host, then an SQLITE_NOLFS is returned. +*/ +int sqlite3OsReadLock(OsFile *id){ +  int rc; +  if( id->locked>0 || id->refNumRF == -1 ){ +    rc = SQLITE_OK; +  }else{ +    int lk; +    OSErr res; +    int cnt = 5; +    ParamBlockRec params; +    sqlite3Randomness(sizeof(lk), &lk); +    lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; +    memset(¶ms, 0, sizeof(params)); +    params.ioParam.ioRefNum = id->refNumRF; +    params.ioParam.ioPosMode = fsFromStart; +    params.ioParam.ioPosOffset = FIRST_LOCKBYTE; +    params.ioParam.ioReqCount = 1; +    while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ +      UInt32 finalTicks; +      Delay(1, &finalTicks); /* 1/60 sec */ +    } +    if( res == noErr ){ +      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; +      params.ioParam.ioReqCount = N_LOCKBYTE; +      PBUnlockRangeSync(¶ms); +      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk; +      params.ioParam.ioReqCount = 1; +      res = PBLockRangeSync(¶ms); +      params.ioParam.ioPosOffset = FIRST_LOCKBYTE; +      params.ioParam.ioReqCount = 1; +      PBUnlockRangeSync(¶ms); +    } +    if( res == noErr ){ +      id->locked = lk; +      rc = SQLITE_OK; +    }else{ +      rc = SQLITE_BUSY; +    } +  } +  return rc; +} + +/* +** Change the lock status to be an exclusive or write lock.  Return +** SQLITE_OK on success and SQLITE_BUSY on a failure.  If this +** library was compiled with large file support (LFS) but LFS is not +** available on the host, then an SQLITE_NOLFS is returned. +*/ +int sqlite3OsWriteLock(OsFile *id){ +  int rc; +  if( id->locked<0 || id->refNumRF == -1 ){ +    rc = SQLITE_OK; +  }else{ +    OSErr res; +    int cnt = 5; +    ParamBlockRec params; +    memset(¶ms, 0, sizeof(params)); +    params.ioParam.ioRefNum = id->refNumRF; +    params.ioParam.ioPosMode = fsFromStart; +    params.ioParam.ioPosOffset = FIRST_LOCKBYTE; +    params.ioParam.ioReqCount = 1; +    while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ +      UInt32 finalTicks; +      Delay(1, &finalTicks); /* 1/60 sec */ +    } +    if( res == noErr ){ +      params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked; +      params.ioParam.ioReqCount = 1; +      if( id->locked==0  +            || PBUnlockRangeSync(¶ms)==noErr ){ +        params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; +        params.ioParam.ioReqCount = N_LOCKBYTE; +        res = PBLockRangeSync(¶ms); +      }else{ +        res = afpRangeNotLocked; +      } +      params.ioParam.ioPosOffset = FIRST_LOCKBYTE; +      params.ioParam.ioReqCount = 1; +      PBUnlockRangeSync(¶ms); +    } +    if( res == noErr ){ +      id->locked = -1; +      rc = SQLITE_OK; +    }else{ +      rc = SQLITE_BUSY; +    } +  } +  return rc; +} + +/* +** Unlock the given file descriptor.  If the file descriptor was +** not previously locked, then this routine is a no-op.  If this +** library was compiled with large file support (LFS) but LFS is not +** available on the host, then an SQLITE_NOLFS is returned. +*/ +int sqlite3OsUnlock(OsFile *id){ +  int rc; +  ParamBlockRec params; +  memset(¶ms, 0, sizeof(params)); +  params.ioParam.ioRefNum = id->refNumRF; +  params.ioParam.ioPosMode = fsFromStart; +  if( id->locked==0 || id->refNumRF == -1 ){ +    rc = SQLITE_OK; +  }else if( id->locked<0 ){ +    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; +    params.ioParam.ioReqCount = N_LOCKBYTE; +    PBUnlockRangeSync(¶ms); +    rc = SQLITE_OK; +    id->locked = 0; +  }else{ +    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked; +    params.ioParam.ioReqCount = 1; +    PBUnlockRangeSync(¶ms); +    rc = SQLITE_OK; +    id->locked = 0; +  } +  return rc; +} + +/* +** Get information to seed the random number generator.  The seed +** is written into the buffer zBuf[256].  The calling function must +** supply a sufficiently large buffer. +*/ +int sqlite3OsRandomSeed(char *zBuf){ +  /* 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, 256); +#if !defined(SQLITE_TEST) +  { +    int pid; +    Microseconds((UnsignedWide*)zBuf); +    pid = getpid(); +    memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid)); +  } +#endif +  return SQLITE_OK; +} + +/* +** Sleep for a little while.  Return the amount of time slept. +*/ +int sqlite3OsSleep(int ms){ +  UInt32 finalTicks; +  UInt32 ticks = (((UInt32)ms+16)*3)/50;  /* 1/60 sec per tick */ +  Delay(ticks, &finalTicks); +  return (int)((ticks*50)/3); +} + +/* +** Static variables used for thread synchronization +*/ +static int inMutex = 0; +#ifdef SQLITE_MACOS_MULTITASKING +  static MPCriticalRegionID criticalRegion; +#endif + +/* +** The following pair of routine implement mutual exclusion for +** multi-threaded processes.  Only a single thread is allowed to +** executed code that is surrounded by EnterMutex() and LeaveMutex(). +** +** SQLite uses only a single Mutex.  There is not much critical +** code and what little there is executes quickly and without blocking. +*/ +void sqlite3OsEnterMutex(){ +#ifdef SQLITE_MACOS_MULTITASKING +  static volatile int notInit = 1; +  if( notInit ){ +    if( notInit == 2 ) /* as close as you can get to thread safe init */ +      MPYield(); +    else{ +      notInit = 2; +      MPCreateCriticalRegion(&criticalRegion); +      notInit = 0; +    } +  } +  MPEnterCriticalRegion(criticalRegion, kDurationForever); +#endif +  assert( !inMutex ); +  inMutex = 1; +} +void sqlite3OsLeaveMutex(){ +  assert( inMutex ); +  inMutex = 0; +#ifdef SQLITE_MACOS_MULTITASKING +  MPExitCriticalRegion(criticalRegion); +#endif +} + +/* +** Turn a relative pathname into a full pathname.  Return a pointer +** to the full pathname stored in space obtained from sqliteMalloc(). +** The calling function is responsible for freeing this space once it +** is no longer needed. +*/ +char *sqlite3OsFullPathname(const char *zRelative){ +  char *zFull = 0; +  if( zRelative[0]==':' ){ +    char zBuf[_MAX_PATH+1]; +    sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]), +                    (char*)0); +  }else{ +    if( strchr(zRelative, ':') ){ +      sqlite3SetString(&zFull, zRelative, (char*)0); +    }else{ +    char zBuf[_MAX_PATH+1]; +      sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0); +    } +  } +  return zFull; +} + +/* +** 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 sqlite3OsCurrentTime(double *prNow){ +  *prNow = 0.0;   /**** FIX ME *****/ +#ifdef SQLITE_TEST +  if( sqlite3_current_time ){ +    *prNow = sqlite3_current_time/86400.0 + 2440587.5; +  } +#endif +  return 0; +} + +#endif /* OS_MAC */ diff --git a/ext/pdo_sqlite/sqlite/src/os_mac.h b/ext/pdo_sqlite/sqlite/src/os_mac.h new file mode 100644 index 0000000000..5b60f81837 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_mac.h @@ -0,0 +1,41 @@ +/* +** 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 of classic Mac. +** OS X uses the os_unix.h file, not this one. +*/ +#ifndef _SQLITE_OS_MAC_H_ +#define _SQLITE_OS_MAC_H_ + + +#include <unistd.h> +#include <Files.h> +#define SQLITE_TEMPNAME_SIZE _MAX_PATH +#define SQLITE_MIN_SLEEP_MS 17 + +/* +** 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 class Mac. +*/ +typedef struct OsFile OsFile; +struct OsFile { +  SInt16 refNum;           /* Data fork/file reference number */ +  SInt16 refNumRF;         /* Resource fork reference number (for locking) */ +  int locked;              /* 0: unlocked, <0: write lock, >0: read lock */ +  int delOnClose;          /* True if file is to be deleted on close */ +  char *pathToDel;         /* Name of file to delete on close */ +}; + + +#endif /* _SQLITE_OS_MAC_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/os_test.c b/ext/pdo_sqlite/sqlite/src/os_test.c new file mode 100644 index 0000000000..0e292bc428 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_test.c @@ -0,0 +1,461 @@ +/* +** 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)<filesize ){ +      int len = BLOCKSIZE; +      rc = sqlite3RealSeek(&pFile->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; i<pFile->nBlk; 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( 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; i++){ +    int off = 0; +    int len = 0; + + +    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); +    } + +    if( i<pFile->nBlk && 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*BLOCKSIZE<end; i++){ +    u8 *pBlk; +    int off = 0; +    int len = 0; + +    /* Make sure the block is in the cache */ +    rc = cacheBlock(pFile, i); +    if( rc!=SQLITE_OK ) return rc; + +    /* Write into the cache */ +    pBlk = pFile->apBlk[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->nMaxWrite<end ){ +    pFile->nMaxWrite = 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 rc; +  /* printf("SYNC %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */ +  rc = writeCache(*id); +  if( rc!=SQLITE_OK ) return rc; +  rc = sqlite3RealSync(&(*id)->fd); +  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/ext/pdo_sqlite/sqlite/src/os_test.h b/ext/pdo_sqlite/sqlite/src/os_test.h new file mode 100644 index 0000000000..256eaaf17a --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_test.h @@ -0,0 +1,39 @@ +/* +** 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 + +/* 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/ext/pdo_sqlite/sqlite/src/os_unix.c b/ext/pdo_sqlite/sqlite/src/os_unix.c new file mode 100644 index 0000000000..94fca70199 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_unix.c @@ -0,0 +1,1276 @@ +/* +** 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" +#include "os.h" +#if OS_UNIX              /* This file is used on unix only */ + + +#include <time.h> +#include <errno.h> +#include <unistd.h> +#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 its DOS - what did you expect? +*/ +#ifdef __DJGPP__ +# define fcntl(A,B,C) 0 +#endif + +/* +** 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 <pthread.h> +# define SQLITE_UNIX_THREADS 1 +#endif + + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +#if defined(THREADSAFE) && THREADSAFE && defined(__linux__) +#define getpid pthread_self +#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 OsFile 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 OsFile 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 OsFile structure contains +** a pointer to an openCnt structure.  There is one openCnt structure +** per open inode, which means that multiple OsFiles can point to a single +** openCnt.  When an attempt is made to close an OsFile, if there are +** other OsFiles 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 also +** set to zero if we compile without threading support. +*/ +struct lockKey { +  dev_t dev;       /* Device number */ +  ino_t ino;       /* Inode number */ +#ifdef SQLITE_UNIX_THREADS +  pthread_t tid;   /* Thread ID or zero if threads cannot 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 OsFile +** structure contains a pointer to an instance of this object and this +** object keeps a count of the number of OsFiles 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 table maps inodes and process IDs 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_UNIX_THREADS +/* +** 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. +*/ +static int threadsOverrideEachOthersLocks = -1; + +/* +** 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 */ +}; + +/* +** 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(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_UNIX_THREADS */ + +/* +** Release a lockInfo structure previously allocated by findLockInfo(). +*/ +static void releaseLockInfo(struct lockInfo *pLock){ +  pLock->nRef--; +  if( pLock->nRef==0 ){ +    sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); +    sqliteFree(pLock); +  } +} + +/* +** Release a openCnt structure previously allocated by findLockInfo(). +*/ +static void releaseOpenCnt(struct openCnt *pOpen){ +  pOpen->nRef--; +  if( pOpen->nRef==0 ){ +    sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); +    sqliteFree(pOpen->aPending); +    sqliteFree(pOpen); +  } +} + +/* +** Given a file descriptor, locate lockInfo and openCnt structures that +** describes that file descriptor.  Create a new ones if necessary.  The +** return values might be unset 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; +#ifdef SQLITE_UNIX_THREADS +  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 = sqliteMallocRaw( sizeof(*pLock) ); +    if( pLock==0 ) return 1; +    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 ); +      sqliteFree(pLock); +      return 1; +    } +  }else{ +    pLock->nRef++; +  } +  *ppLock = pLock; +  pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); +  if( pOpen==0 ){ +    struct openCnt *pOld; +    pOpen = sqliteMallocRaw( sizeof(*pOpen) ); +    if( pOpen==0 ){ +      releaseLockInfo(pLock); +      return 1; +    } +    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 ); +      sqliteFree(pOpen); +      releaseLockInfo(pLock); +      return 1; +    } +  }else{ +    pOpen->nRef++; +  } +  *ppOpen = pOpen; +  return 0; +} + +/* +** Delete the named file +*/ +int sqlite3OsDelete(const char *zFilename){ +  unlink(zFilename); +  return SQLITE_OK; +} + +/* +** Return TRUE if the named file exists. +*/ +int sqlite3OsFileExists(const char *zFilename){ +  return access(zFilename, 0)==0; +} + +/* +** Attempt to open a file for both reading and writing.  If that +** fails, try opening it read-only.  If the file does not exist, +** try to create it. +** +** On success, a handle for the open file is written to *id +** and *pReadonly is set to 0 if the file was opened for reading and +** writing or 1 if the file was opened read-only.  The function returns +** SQLITE_OK. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id and *pReadonly unchanged. +*/ +int sqlite3OsOpenReadWrite( +  const char *zFilename, +  OsFile *id, +  int *pReadonly +){ +  int rc; +  assert( !id->isOpen ); +  id->dirfd = -1; +  id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); +  if( id->h<0 ){ +#ifdef EISDIR +    if( errno==EISDIR ){ +      return SQLITE_CANTOPEN; +    } +#endif +    id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); +    if( id->h<0 ){ +      return SQLITE_CANTOPEN;  +    } +    *pReadonly = 1; +  }else{ +    *pReadonly = 0; +  } +  sqlite3OsEnterMutex(); +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen); +  sqlite3OsLeaveMutex(); +  if( rc ){ +    close(id->h); +    return SQLITE_NOMEM; +  } +  id->locktype = 0; +  id->isOpen = 1; +  TRACE3("OPEN    %-3d %s\n", id->h, zFilename); +  OpenCounter(+1); +  return SQLITE_OK; +} + + +/* +** Attempt to open a new file for exclusive access by this process. +** The file will be opened for both reading and writing.  To avoid +** a potential security problem, we do not allow the file to have +** previously existed.  Nor do we allow the file to be a symbolic +** link. +** +** If delFlag is true, then make arrangements to automatically delete +** the file when it is closed. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +  int rc; +  assert( !id->isOpen ); +  if( access(zFilename, 0)==0 ){ +    return SQLITE_CANTOPEN; +  } +  id->dirfd = -1; +  id->h = open(zFilename, +                O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); +  if( id->h<0 ){ +    return SQLITE_CANTOPEN; +  } +  sqlite3OsEnterMutex(); +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen); +  sqlite3OsLeaveMutex(); +  if( rc ){ +    close(id->h); +    unlink(zFilename); +    return SQLITE_NOMEM; +  } +  id->locktype = 0; +  id->isOpen = 1; +  if( delFlag ){ +    unlink(zFilename); +  } +  TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename); +  OpenCounter(+1); +  return SQLITE_OK; +} + +/* +** Attempt to open a new file for read-only access. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +  int rc; +  assert( !id->isOpen ); +  id->dirfd = -1; +  id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); +  if( id->h<0 ){ +    return SQLITE_CANTOPEN; +  } +  sqlite3OsEnterMutex(); +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen); +  sqlite3OsLeaveMutex(); +  if( rc ){ +    close(id->h); +    return SQLITE_NOMEM; +  } +  id->locktype = 0; +  id->isOpen = 1; +  TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename); +  OpenCounter(+1); +  return SQLITE_OK; +} + +/* +** Attempt to open a file descriptor for the directory that contains a +** file.  This file descriptor can be used to fsync() the directory +** in order to make sure the creation of a new file is actually written +** to disk. +** +** This routine is only meaningful for Unix.  It is a no-op under +** windows since windows does not support hard links. +** +** On success, a handle for a previously open file is at *id is +** updated with the new directory file descriptor and SQLITE_OK is +** returned. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id unchanged. +*/ +int sqlite3OsOpenDirectory( +  const char *zDirname, +  OsFile *id +){ +  if( !id->isOpen ){ +    /* Do not open the directory if the corresponding file is not already +    ** open. */ +    return SQLITE_CANTOPEN; +  } +  assert( id->dirfd<0 ); +  id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644); +  if( id->dirfd<0 ){ +    return SQLITE_CANTOPEN;  +  } +  TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); +  return SQLITE_OK; +} + +/* +** 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. +*/ +const char *sqlite3_temp_directory = 0; + +/* +** Create a temporary file name in zBuf.  zBuf must be big enough to +** hold at least SQLITE_TEMPNAME_SIZE characters. +*/ +int sqlite3OsTempFileName(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 = "."; +  azDirs[0] = sqlite3_temp_directory; +  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ +    if( azDirs[i]==0 ) continue; +    if( stat(azDirs[i], &buf) ) continue; +    if( !S_ISDIR(buf.st_mode) ) continue; +    if( access(azDirs[i], 07) ) continue; +    zDir = azDirs[i]; +    break; +  } +  do{ +    sprintf(zBuf, "%s/"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;  +} + +/* +** 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 sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +  int got; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  TIMER_START; +  got = read(id->h, pBuf, amt); +  TIMER_END; +  TRACE4("READ    %-3d %7d %d\n", id->h, last_page, TIMER_ELAPSED); +  SEEK(0); +  /* if( got<0 ) got = 0; */ +  if( got==amt ){ +    return SQLITE_OK; +  }else{ +    return SQLITE_IOERR; +  } +} + +/* +** Write data from a buffer into a file.  Return SQLITE_OK on success +** or some other error code on failure. +*/ +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +  int wrote = 0; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  SimulateDiskfullError; +  TIMER_START; +  while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){ +    amt -= wrote; +    pBuf = &((char*)pBuf)[wrote]; +  } +  TIMER_END; +  TRACE4("WRITE   %-3d %7d %d\n", id->h, last_page, TIMER_ELAPSED); +  SEEK(0); +  if( amt>0 ){ +    return SQLITE_FULL; +  } +  return SQLITE_OK; +} + +/* +** Move the read/write pointer in a file. +*/ +int sqlite3OsSeek(OsFile *id, i64 offset){ +  assert( id->isOpen ); +  SEEK(offset/1024 + 1); +  lseek(id->h, offset, SEEK_SET); +  return SQLITE_OK; +} + +/* +** The fsync() system call does not work as advertised on many +** unix systems.  The following procedure is an attempt to make +** it work better. +*/ +static int full_fsync(int fd){ +  int rc; +#ifdef F_FULLFSYNC +  rc = fcntl(fd, F_FULLFSYNC, 0); +  if( rc ) rc = fsync(fd); +#else +  rc = fsync(fd); +#endif +  return rc; +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** 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. +*/ +int sqlite3OsSync(OsFile *id){ +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  TRACE2("SYNC    %-3d\n", id->h); +  if( full_fsync(id->h) ){ +    return SQLITE_IOERR; +  } +  if( id->dirfd>=0 ){ +    TRACE2("DIRSYNC %-3d\n", id->dirfd); +    full_fsync(id->dirfd); +    close(id->dirfd);  /* Only need to sync once, so close the directory */ +    id->dirfd = -1;    /* when we are done. */ +  } +  return SQLITE_OK; +} + +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ +  int fd; +  int r; +  SimulateIOError(SQLITE_IOERR); +  fd = open(zDirname, O_RDONLY|O_BINARY, 0644); +  TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname); +  if( fd<0 ){ +    return SQLITE_CANTOPEN;  +  } +  r = fsync(fd); +  close(fd); +  return ((r==0)?SQLITE_OK:SQLITE_IOERR); +} + +/* +** Truncate an open file to a specified size +*/ +int sqlite3OsTruncate(OsFile *id, i64 nByte){ +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Determine the current size of a file in bytes +*/ +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +  struct stat buf; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  if( fstat(id->h, &buf)!=0 ){ +    return SQLITE_IOERR; +  } +  *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. +*/ +int sqlite3OsCheckReservedLock(OsFile *id){ +  int r = 0; + +  assert( id->isOpen ); +  sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ + +  /* Check if a thread in this process holds such a lock */ +  if( id->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(id->h, F_GETLK, &lock); +    if( lock.l_type!=F_UNLCK ){ +      r = 1; +    } +  } +   +  sqlite3OsLeaveMutex(); +  TRACE3("TEST WR-LOCK %d %d\n", id->h, r); + +  return r; +} + +#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 + +/* +** 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. +*/ +int sqlite3OsLock(OsFile *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; +  struct lockInfo *pLock = id->pLock; +  struct flock lock; +  int s; + +  assert( id->isOpen ); +  TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype),  +      locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt +      ,getpid() ); + +  /* 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( id->locktype>=locktype ){ +    TRACE3("LOCK %d %s ok (already held)\n", id->h, locktypeName(locktype)); +    return SQLITE_OK; +  } + +  /* Make sure the locking sequence is correct +  */ +  assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); +  assert( locktype!=PENDING_LOCK ); +  assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + +  /* This mutex is needed because id->pLock is shared across threads +  */ +  sqlite3OsEnterMutex(); + +  /* If some thread using this PID has a lock via a different OsFile* +  ** handle that precludes the requested lock, return BUSY. +  */ +  if( (id->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( id->locktype==0 ); +    assert( pLock->cnt>0 ); +    id->locktype = SHARED_LOCK; +    pLock->cnt++; +    id->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 && id->locktype<PENDING_LOCK) +  ){ +    lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK); +    lock.l_start = PENDING_BYTE; +    s = fcntl(id->h, F_SETLK, &lock); +    if( s ){ +      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(id->h, F_SETLK, &lock); + +    /* Drop the temporary PENDING lock */ +    lock.l_start = PENDING_BYTE; +    lock.l_len = 1L; +    lock.l_type = F_UNLCK; +    fcntl(id->h, F_SETLK, &lock); +    if( s ){ +      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; +    }else{ +      id->locktype = SHARED_LOCK; +      id->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!=id->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(id->h, F_SETLK, &lock); +    if( s ){ +      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; +    } +  } +   +  if( rc==SQLITE_OK ){ +    id->locktype = locktype; +    pLock->locktype = locktype; +  }else if( locktype==EXCLUSIVE_LOCK ){ +    id->locktype = PENDING_LOCK; +    pLock->locktype = PENDING_LOCK; +  } + +end_lock: +  sqlite3OsLeaveMutex(); +  TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype),  +      rc==SQLITE_OK ? "ok" : "failed"); +  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, this routine +** might return SQLITE_IOERR instead of SQLITE_OK. +*/ +int sqlite3OsUnlock(OsFile *id, int locktype){ +  struct lockInfo *pLock; +  struct flock lock; +  int rc = SQLITE_OK; + +  assert( id->isOpen ); +  TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype,  +      id->pLock->locktype, id->pLock->cnt, getpid()); + +  assert( locktype<=SHARED_LOCK ); +  if( id->locktype<=locktype ){ +    return SQLITE_OK; +  } +  sqlite3OsEnterMutex(); +  pLock = id->pLock; +  assert( pLock->cnt!=0 ); +  if( id->locktype>SHARED_LOCK ){ +    assert( pLock->locktype==id->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(id->h, F_SETLK, &lock)!=0 ){ +        /* This should never happen */ +        rc = SQLITE_IOERR; +      } +    } +    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 ); +    fcntl(id->h, F_SETLK, &lock); +    pLock->locktype = SHARED_LOCK; +  } +  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; +      fcntl(id->h, F_SETLK, &lock); +      pLock->locktype = NO_LOCK; +    } + +    /* 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 = id->pOpen; +    pOpen->nLock--; +    assert( pOpen->nLock>=0 ); +    if( pOpen->nLock==0 && pOpen->nPending>0 ){ +      int i; +      for(i=0; i<pOpen->nPending; i++){ +        close(pOpen->aPending[i]); +      } +      sqliteFree(pOpen->aPending); +      pOpen->nPending = 0; +      pOpen->aPending = 0; +    } +  } +  sqlite3OsLeaveMutex(); +  id->locktype = locktype; +  return rc; +} + +/* +** Close a file. +*/ +int sqlite3OsClose(OsFile *id){ +  if( !id->isOpen ) return SQLITE_OK; +  sqlite3OsUnlock(id, NO_LOCK); +  if( id->dirfd>=0 ) close(id->dirfd); +  id->dirfd = -1; +  sqlite3OsEnterMutex(); +  if( id->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 = id->pOpen; +    pOpen->nPending++; +    aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) ); +    if( aNew==0 ){ +      /* If a malloc fails, just leak the file descriptor */ +    }else{ +      pOpen->aPending = aNew; +      pOpen->aPending[pOpen->nPending-1] = id->h; +    } +  }else{ +    /* There are no outstanding locks so we can close the file immediately */ +    close(id->h); +  } +  releaseLockInfo(id->pLock); +  releaseOpenCnt(id->pOpen); +  sqlite3OsLeaveMutex(); +  id->isOpen = 0; +  TRACE2("CLOSE   %-3d\n", id->h); +  OpenCounter(-1); +  return SQLITE_OK; +} + +/* +** Get information to seed the random number generator.  The seed +** is written into the buffer zBuf[256].  The calling function must +** supply a sufficiently large buffer. +*/ +int sqlite3OsRandomSeed(char *zBuf){ +  /* 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, 256); +#if !defined(SQLITE_TEST) +  { +    int pid; +    time((time_t*)zBuf); +    pid = getpid(); +    memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); +  } +#endif +  return SQLITE_OK; +} + +/* +** Sleep for a little while.  Return the amount of time slept. +*/ +int sqlite3OsSleep(int ms){ +#if defined(HAVE_USLEEP) && HAVE_USLEEP +  usleep(ms*1000); +  return ms; +#else +  sleep((ms+999)/1000); +  return 1000*((ms+999)/1000); +#endif +} + +/* +** Static variables used for thread synchronization +*/ +static int inMutex = 0; +#ifdef SQLITE_UNIX_THREADS +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* +** The following pair of routine implement mutual exclusion for +** multi-threaded processes.  Only a single thread is allowed to +** executed code that is surrounded by EnterMutex() and LeaveMutex(). +** +** SQLite uses only a single Mutex.  There is not much critical +** code and what little there is executes quickly and without blocking. +*/ +void sqlite3OsEnterMutex(){ +#ifdef SQLITE_UNIX_THREADS +  pthread_mutex_lock(&mutex); +#endif +  assert( !inMutex ); +  inMutex = 1; +} +void sqlite3OsLeaveMutex(){ +  assert( inMutex ); +  inMutex = 0; +#ifdef SQLITE_UNIX_THREADS +  pthread_mutex_unlock(&mutex); +#endif +} + +/* +** Turn a relative pathname into a full pathname.  Return a pointer +** to the full pathname stored in space obtained from sqliteMalloc(). +** The calling function is responsible for freeing this space once it +** is no longer needed. +*/ +char *sqlite3OsFullPathname(const char *zRelative){ +  char *zFull = 0; +  if( zRelative[0]=='/' ){ +    sqlite3SetString(&zFull, zRelative, (char*)0); +  }else{ +    char zBuf[5000]; +    sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative, +                    (char*)0); +  } +  return zFull; +} + +/* +** 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 sqlite3OsCurrentTime(double *prNow){ +  time_t t; +  time(&t); +  *prNow = t/86400.0 + 2440587.5; +#ifdef SQLITE_TEST +  if( sqlite3_current_time ){ +    *prNow = sqlite3_current_time/86400.0 + 2440587.5; +  } +#endif +  return 0; +} + +#if 0 /* NOT USED */ +/* +** Find the time that the file was last modified.  Write the +** modification time and date as a Julian Day number into *prNow and +** return SQLITE_OK.  Return SQLITE_ERROR if the modification +** time cannot be found. +*/ +int sqlite3OsFileModTime(OsFile *id, double *prNow){ +  int rc; +  struct stat statbuf; +  if( fstat(id->h, &statbuf)==0 ){ +    *prNow = statbuf.st_mtime/86400.0 + 2440587.5; +    rc = SQLITE_OK; +  }else{ +    rc = SQLITE_ERROR; +  } +  return rc; +} +#endif /* NOT USED */ + +#endif /* OS_UNIX */ diff --git a/ext/pdo_sqlite/sqlite/src/os_unix.h b/ext/pdo_sqlite/sqlite/src/os_unix.h new file mode 100644 index 0000000000..72f818befe --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_unix.h @@ -0,0 +1,89 @@ +/* +** 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 <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +/* +** 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 */ +  int dirfd;                /* File descriptor for the directory */ +}; + +/* +** 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 + + +#endif /* _SQLITE_OS_UNIX_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/os_win.c b/ext/pdo_sqlite/sqlite/src/os_win.c new file mode 100644 index 0000000000..f6e3e3ea83 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os_win.c @@ -0,0 +1,747 @@ +/* +** 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" +#include "os.h" +#if OS_WIN               /* This file is used for windows only */ + +#include <winbase.h> + +/* +** 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" + +/* +** Delete the named file +*/ +int sqlite3OsDelete(const char *zFilename){ +  DeleteFileA(zFilename); +  TRACE2("DELETE \"%s\"\n", zFilename); +  return SQLITE_OK; +} + +/* +** Return TRUE if the named file exists. +*/ +int sqlite3OsFileExists(const char *zFilename){ +  return GetFileAttributesA(zFilename) != 0xffffffff; +} + +/* +** Attempt to open a file for both reading and writing.  If that +** fails, try opening it read-only.  If the file does not exist, +** try to create it. +** +** On success, a handle for the open file is written to *id +** and *pReadonly is set to 0 if the file was opened for reading and +** writing or 1 if the file was opened read-only.  The function returns +** SQLITE_OK. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id and *pReadonly unchanged. +*/ +int sqlite3OsOpenReadWrite( +  const char *zFilename, +  OsFile *id, +  int *pReadonly +){ +  HANDLE h; +  assert( !id->isOpen ); +  h = CreateFileA(zFilename, +     GENERIC_READ | GENERIC_WRITE, +     FILE_SHARE_READ | FILE_SHARE_WRITE, +     NULL, +     OPEN_ALWAYS, +     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, +     NULL +  ); +  if( h==INVALID_HANDLE_VALUE ){ +    h = CreateFileA(zFilename, +       GENERIC_READ, +       FILE_SHARE_READ, +       NULL, +       OPEN_ALWAYS, +       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, +       NULL +    ); +    if( h==INVALID_HANDLE_VALUE ){ +      return SQLITE_CANTOPEN; +    } +    *pReadonly = 1; +  }else{ +    *pReadonly = 0; +  } +  id->h = h; +  id->locktype = NO_LOCK; +  id->sharedLockByte = 0; +  id->isOpen = 1; +  OpenCounter(+1); +  TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); +  return SQLITE_OK; +} + + +/* +** Attempt to open a new file for exclusive access by this process. +** The file will be opened for both reading and writing.  To avoid +** a potential security problem, we do not allow the file to have +** previously existed.  Nor do we allow the file to be a symbolic +** link. +** +** If delFlag is true, then make arrangements to automatically delete +** the file when it is closed. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +  HANDLE h; +  int fileflags; +  assert( !id->isOpen ); +  if( delFlag ){ +    fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS  +                     | FILE_FLAG_DELETE_ON_CLOSE; +  }else{ +    fileflags = FILE_FLAG_RANDOM_ACCESS; +  } +  h = CreateFileA(zFilename, +     GENERIC_READ | GENERIC_WRITE, +     0, +     NULL, +     CREATE_ALWAYS, +     fileflags, +     NULL +  ); +  if( h==INVALID_HANDLE_VALUE ){ +    return SQLITE_CANTOPEN; +  } +  id->h = h; +  id->locktype = NO_LOCK; +  id->sharedLockByte = 0; +  id->isOpen = 1; +  OpenCounter(+1); +  TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); +  return SQLITE_OK; +} + +/* +** Attempt to open a new file for read-only access. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +  HANDLE h; +  assert( !id->isOpen ); +  h = CreateFileA(zFilename, +     GENERIC_READ, +     0, +     NULL, +     OPEN_EXISTING, +     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, +     NULL +  ); +  if( h==INVALID_HANDLE_VALUE ){ +    return SQLITE_CANTOPEN; +  } +  id->h = h; +  id->locktype = NO_LOCK; +  id->sharedLockByte = 0; +  id->isOpen = 1; +  OpenCounter(+1); +  TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); +  return SQLITE_OK; +} + +/* +** Attempt to open a file descriptor for the directory that contains a +** file.  This file descriptor can be used to fsync() the directory +** in order to make sure the creation of a new file is actually written +** to disk. +** +** This routine is only meaningful for Unix.  It is a no-op under +** windows since windows does not support hard links. +** +** On success, a handle for a previously open file is at *id is +** updated with the new directory file descriptor and SQLITE_OK is +** returned. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id unchanged. +*/ +int sqlite3OsOpenDirectory( +  const char *zDirname, +  OsFile *id +){ +  return SQLITE_OK; +} + +/* +** 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. +*/ +const char *sqlite3_temp_directory = 0; + +/* +** Create a temporary file name in zBuf.  zBuf must be big enough to +** hold at least SQLITE_TEMPNAME_SIZE characters. +*/ +int sqlite3OsTempFileName(char *zBuf){ +  static char zChars[] = +    "abcdefghijklmnopqrstuvwxyz" +    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +    "0123456789"; +  int i, j; +  char zTempPath[SQLITE_TEMPNAME_SIZE]; +  if( sqlite3_temp_directory ){ +    strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); +    zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; +  }else{ +    GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); +  } +  for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} +  zTempPath[i] = 0; +  for(;;){ +    sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); +    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; +    if( !sqlite3OsFileExists(zBuf) ) break; +  } +  TRACE2("TEMP FILENAME: %s\n", zBuf); +  return SQLITE_OK;  +} + +/* +** Close a file. +*/ +int sqlite3OsClose(OsFile *id){ +  if( id->isOpen ){ +    TRACE2("CLOSE %d\n", id->h); +    CloseHandle(id->h); +    OpenCounter(-1); +    id->isOpen = 0; +  } +  return SQLITE_OK; +} + +/* +** 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 sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +  DWORD got; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  TRACE3("READ %d lock=%d\n", id->h, id->locktype); +  if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ +    got = 0; +  } +  if( got==(DWORD)amt ){ +    return SQLITE_OK; +  }else{ +    return SQLITE_IOERR; +  } +} + +/* +** Write data from a buffer into a file.  Return SQLITE_OK on success +** or some other error code on failure. +*/ +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +  int rc; +  DWORD wrote; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  SimulateDiskfullError; +  TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); +  while( amt>0 && (rc = WriteFile(id->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; +} + +/* +** Move the read/write pointer in a file. +*/ +int sqlite3OsSeek(OsFile *id, i64 offset){ +  LONG upperBits = offset>>32; +  LONG lowerBits = offset & 0xffffffff; +  DWORD rc; +  assert( id->isOpen ); +  SEEK(offset/1024 + 1); +  rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); +  TRACE3("SEEK %d %lld\n", id->h, offset); +  return SQLITE_OK; +} + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +int sqlite3OsSync(OsFile *id){ +  assert( id->isOpen ); +  TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); +  if( FlushFileBuffers(id->h) ){ +    return SQLITE_OK; +  }else{ +    return SQLITE_IOERR; +  } +} + +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ +  SimulateIOError(SQLITE_IOERR); +  return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +int sqlite3OsTruncate(OsFile *id, i64 nByte){ +  LONG upperBits = nByte>>32; +  assert( id->isOpen ); +  TRACE3("TRUNCATE %d %lld\n", id->h, nByte); +  SimulateIOError(SQLITE_IOERR); +  SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); +  SetEndOfFile(id->h); +  return SQLITE_OK; +} + +/* +** Determine the current size of a file in bytes +*/ +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +  DWORD upperBits, lowerBits; +  assert( id->isOpen ); +  SimulateIOError(SQLITE_IOERR); +  lowerBits = GetFileSize(id->h, &upperBits); +  *pSize = (((i64)upperBits)<<32) + lowerBits; +  return SQLITE_OK; +} + +/* +** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. +** 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. +*/ +static int isNT(void){ +  static int osType = 0;   /* 0=unknown 1=win95 2=winNT */ +  if( osType==0 ){ +    OSVERSIONINFO sInfo; +    sInfo.dwOSVersionInfoSize = sizeof(sInfo); +    GetVersionEx(&sInfo); +    osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; +  } +  return osType==2; +} + +/* +** Acquire a reader lock. +** Different API routines are called depending on whether or not this +** is Win95 or WinNT. +*/ +static int getReadLock(OsFile *id){ +  int res; +  if( isNT() ){ +    OVERLAPPED ovlp; +    ovlp.Offset = SHARED_FIRST; +    ovlp.OffsetHigh = 0; +    ovlp.hEvent = 0; +    res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp); +  }else{ +    int lk; +    sqlite3Randomness(sizeof(lk), &lk); +    id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); +    res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); +  } +  return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock(OsFile *id){ +  int res; +  if( isNT() ){ +    res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); +  }else{ +    res = UnlockFile(id->h, SHARED_FIRST + id->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 sqlite3OsUnlock() 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 sqlite3OsLock(OsFile *id, int locktype){ +  int rc = SQLITE_OK;    /* Return code from subroutines */ +  int res = 1;           /* Result of a windows lock call */ +  int newLocktype;       /* Set id->locktype to this value before exiting */ +  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + +  assert( id->isOpen ); +  TRACE5("LOCK %d %d was %d(%d)\n", +          id->h, locktype, id->locktype, id->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( id->locktype>=locktype ){ +    return SQLITE_OK; +  } + +  /* Make sure the locking sequence is correct +  */ +  assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); +  assert( locktype!=PENDING_LOCK ); +  assert( locktype!=RESERVED_LOCK || id->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 = id->locktype; +  if( id->locktype==NO_LOCK +   || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) +  ){ +    int cnt = 3; +    while( cnt-->0 && (res = LockFile(id->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. +      */ +      TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); +      Sleep(1); +    } +    gotPendingLock = res; +  } + +  /* Acquire a shared lock +  */ +  if( locktype==SHARED_LOCK && res ){ +    assert( id->locktype==NO_LOCK ); +    res = getReadLock(id); +    if( res ){ +      newLocktype = SHARED_LOCK; +    } +  } + +  /* Acquire a RESERVED lock +  */ +  if( locktype==RESERVED_LOCK && res ){ +    assert( id->locktype==SHARED_LOCK ); +    res = LockFile(id->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( id->locktype>=SHARED_LOCK ); +    res = unlockReadLock(id); +    TRACE2("unreadlock = %d\n", res); +    res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); +    if( res ){ +      newLocktype = EXCLUSIVE_LOCK; +    }else{ +      TRACE2("error-code = %d\n", GetLastError()); +    } +  } + +  /* If we are holding a PENDING lock that ought to be released, then +  ** release it now. +  */ +  if( gotPendingLock && locktype==SHARED_LOCK ){ +    UnlockFile(id->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{ +    TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, +           locktype, newLocktype); +    rc = SQLITE_BUSY; +  } +  id->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. +*/ +int sqlite3OsCheckReservedLock(OsFile *id){ +  int rc; +  assert( id->isOpen ); +  if( id->locktype>=RESERVED_LOCK ){ +    rc = 1; +    TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); +  }else{ +    rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); +    if( rc ){ +      UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); +    } +    rc = !rc; +    TRACE3("TEST WR-LOCK %d %d (remote)\n", id->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 sqlite3OsUnlock(OsFile *id, int locktype){ +  int type; +  int rc = SQLITE_OK; +  assert( id->isOpen ); +  assert( locktype<=SHARED_LOCK ); +  TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, +          id->locktype, id->sharedLockByte); +  type = id->locktype; +  if( type>=EXCLUSIVE_LOCK ){ +    UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); +    if( locktype==SHARED_LOCK && !getReadLock(id) ){ +      /* This should never happen.  We should always be able to +      ** reacquire the read lock */ +      rc = SQLITE_IOERR; +    } +  } +  if( type>=RESERVED_LOCK ){ +    UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); +  } +  if( locktype==NO_LOCK && type>=SHARED_LOCK ){ +    unlockReadLock(id); +  } +  if( type>=PENDING_LOCK ){ +    UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); +  } +  id->locktype = locktype; +  return rc; +} + +/* +** Get information to seed the random number generator.  The seed +** is written into the buffer zBuf[256].  The calling function must +** supply a sufficiently large buffer. +*/ +int sqlite3OsRandomSeed(char *zBuf){ +  /* 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, 256); +  GetSystemTime((LPSYSTEMTIME)zBuf); +  return SQLITE_OK; +} + +/* +** Sleep for a little while.  Return the amount of time slept. +*/ +int sqlite3OsSleep(int ms){ +  Sleep(ms); +  return ms; +} + +/* +** Static variables used for thread synchronization +*/ +static int inMutex = 0; +#ifdef SQLITE_W32_THREADS +  static CRITICAL_SECTION cs; +#endif + +/* +** The following pair of routine implement mutual exclusion for +** multi-threaded processes.  Only a single thread is allowed to +** executed code that is surrounded by EnterMutex() and LeaveMutex(). +** +** SQLite uses only a single Mutex.  There is not much critical +** code and what little there is executes quickly and without blocking. +*/ +void sqlite3OsEnterMutex(){ +#ifdef SQLITE_W32_THREADS +  static int isInit = 0; +  while( !isInit ){ +    static long lock = 0; +    if( InterlockedIncrement(&lock)==1 ){ +      InitializeCriticalSection(&cs); +      isInit = 1; +    }else{ +      Sleep(1); +    } +  } +  EnterCriticalSection(&cs); +#endif +  assert( !inMutex ); +  inMutex = 1; +} +void sqlite3OsLeaveMutex(){ +  assert( inMutex ); +  inMutex = 0; +#ifdef SQLITE_W32_THREADS +  LeaveCriticalSection(&cs); +#endif +} + +/* +** Turn a relative pathname into a full pathname.  Return a pointer +** to the full pathname stored in space obtained from sqliteMalloc(). +** The calling function is responsible for freeing this space once it +** is no longer needed. +*/ +char *sqlite3OsFullPathname(const char *zRelative){ +  char *zNotUsed; +  char *zFull; +  int nByte; +  nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1; +  zFull = sqliteMalloc( nByte ); +  if( zFull==0 ) return 0; +  GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed); +  return zFull; +} + +/* +** 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 sqlite3OsCurrentTime(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; +  GetSystemTimeAsFileTime( &ft ); +  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; +} + +/* +** Find the time that the file was last modified.  Write the +** modification time and date as a Julian Day number into *prNow and +** return SQLITE_OK.  Return SQLITE_ERROR if the modification +** time cannot be found. +*/ +int sqlite3OsFileModTime(OsFile *id, double *prMTime){ +  int rc; +  FILETIME ft; +  /* FILETIME structure is a 64-bit value representing the number of  +  ** 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).  +  */ +  if( GetFileTime(id->h, 0, 0, &ft) ){ +    double t; +    t = ((double)ft.dwHighDateTime) * 4294967296.0;  +    *prMTime = (t + ft.dwLowDateTime)/864000000000.0 + 2305813.5; +    rc = SQLITE_OK; +  }else{ +    rc = SQLITE_ERROR; +  } +  return rc; +} + +#endif /* OS_WIN */ diff --git a/ext/pdo_sqlite/sqlite/src/os_win.h b/ext/pdo_sqlite/sqlite/src/os_win.h new file mode 100644 index 0000000000..baf937b211 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/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 <windows.h> +#include <winbase.h> + +/* +** 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/ext/pdo_sqlite/sqlite/src/pager.c b/ext/pdo_sqlite/sqlite/src/pager.c new file mode 100644 index 0000000000..a374562bc7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/pager.c @@ -0,0 +1,3205 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include "pager.h" +#include <assert.h> +#include <string.h> + +/* +** Macros for troubleshooting.  Normally turned off +*/ +#if 0 +#define TRACE1(X)       sqlite3DebugPrintf(X) +#define TRACE2(X,Y)     sqlite3DebugPrintf(X,Y) +#define TRACE3(X,Y,Z)   sqlite3DebugPrintf(X,Y,Z) +#define TRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) +#else +#define TRACE1(X) +#define TRACE2(X,Y) +#define TRACE3(X,Y,Z) +#define TRACE4(X,Y,Z,W) +#endif + + +/* +** 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 the +**                       journal file and the transaction will be +**                       committed. +** +** The page cache comes up in PAGER_UNLOCK.  The first time a +** sqlite3pager_get() 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 sqlite3pager_write() is called, the state transitions to +** PAGER_RESERVED.  (Note that sqlite_page_write() can only be +** called on an outstanding page which means that the pager must +** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) +** The transition to PAGER_EXCLUSIVE occurs when before any changes +** are made to the database file.  After an sqlite3pager_rollback() +** or sqlite_pager_commit(), the state goes back to PAGER_SHARED. +*/ +#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 + +/* +** 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 sqlite3pager_write() on a page prior to making +** any modifications to that page.  The first time sqlite3pager_write() +** 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 sqlite3pager_write() is called and +** is cleared again when the page content is written back to the original +** database file. +*/ +typedef struct PgHdr PgHdr; +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 */ +  PgHdr *pNextFree, *pPrevFree;  /* Freelist of pages where nRef==0 */ +  PgHdr *pNextAll;               /* A list of all pages */ +  PgHdr *pNextStmt, *pPrevStmt;  /* List of pages in the statement journal */ +  u8 inJournal;                  /* TRUE if has been written to journal */ +  u8 inStmt;                     /* TRUE if in the statement subjournal */ +  u8 dirty;                      /* TRUE if we need to write back changes */ +  u8 needSync;                   /* Sync journal before writing this page */ +  u8 alwaysRollback;             /* Disable dont_rollback() for this page */ +  short int nRef;                /* Number of users of this page */ +  PgHdr *pDirty;                 /* Dirty pages sorted by PgHdr.pgno */ +  /* pPager->pageSize bytes of page data follow this header */ +  /* Pager.nExtra bytes of local data follow the page data */ +}; + +/* +** 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 */ +}; + +/* +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); } +#else +# define CODEC(P,D,N,X) +#endif + +/* +** Convert a pointer to a PgHdr into a pointer to its data +** and back again. +*/ +#define PGHDR_TO_DATA(P)  ((void*)(&(P)[1])) +#define DATA_TO_PGHDR(D)  (&((PgHdr*)(D))[-1]) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) +#define PGHDR_TO_HIST(P,PGR)  \ +            ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) + +/* +** How big to make the hash table used for locating in-memory pages +** by page number. +*/ +#define N_PG_HASH 2048 + +/* +** Hash a page number +*/ +#define pager_hash(PN)  ((PN)&(N_PG_HASH-1)) + +/* +** A open page cache is an instance of the following structure. +*/ +struct Pager { +  char *zFilename;            /* Name of the database file */ +  char *zJournal;             /* Name of the journal file */ +  char *zDirectory;           /* Directory hold database and journal files */ +  OsFile fd, jfd;             /* File descriptors for database and journal */ +  OsFile stfd;                /* File descriptor for the statement subjournal*/ +  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() */ +  i64 stmtJSize;              /* Size of journal 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 */ +  void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ +  void (*xReiniter)(void*,int);   /* Call this routine when reloading pages */ +  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 */ +  int nHit, nMiss, nOvfl;     /* Cache hits, missing, and LRU overflows */ +  void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ +  void *pCodecArg;            /* First argument to xCodec() */ +  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 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 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ +  u8 errMask;                 /* One of several kinds of errors */ +  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 dont_rollback() for all pages */ +  u8 memDb;                   /* True to inhibit all file I/O */ +  u8 *aInJournal;             /* One bit for each page in the database file */ +  u8 *aInStmt;                /* One bit for each page in the database */ +  u8 setMaster;               /* True if a m-j name has been written to jrnl */ +  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */ +  PgHdr *pFirst, *pLast;      /* List of free pages */ +  PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */ +  PgHdr *pAll;                /* List of all pages */ +  PgHdr *pStmt;               /* List of pages in the statement subjournal */ +  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 */ +  int sectorSize;             /* Assumed sector size during rollback */ +  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */ +}; + +/* +** These are bits that can be set in Pager.errMask. +*/ +#define PAGER_ERR_FULL     0x01  /* a write() failed */ +#define PAGER_ERR_MEM      0x02  /* malloc() failed */ +#define PAGER_ERR_LOCK     0x04  /* error in the locking protocol */ +#define PAGER_ERR_CORRUPT  0x08  /* database or journal corruption */ +#define PAGER_ERR_DISK     0x10  /* general disk I/O error - bad hard drive? */ + +/* +** 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) + +#define PAGER_SECTOR_SIZE 512 + +/* +** 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)) + +/* +** Enable reference count tracking (for debugging) here: +*/ +#ifdef SQLITE_TEST +  int pager3_refinfo_enable = 0; +  static void pager_refinfo(PgHdr *p){ +    static int cnt = 0; +    if( !pager3_refinfo_enable ) return; +    sqlite3DebugPrintf( +       "REFCNT: %4d addr=%p nRef=%d\n", +       p->pgno, PGHDR_TO_DATA(p), p->nRef +    ); +    cnt++;   /* Something to set a breakpoint on */ +  } +# define REFINFO(X)  pager_refinfo(X) +#else +# define REFINFO(X) +#endif + +/* +** 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(OsFile *fd, u32 *pRes){ +  u32 res; +  int rc; +  rc = sqlite3OsRead(fd, &res, sizeof(res)); +  if( rc==SQLITE_OK ){ +    unsigned char ac[4]; +    memcpy(ac, &res, 4); +    res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; +  } +  *pRes = res; +  return rc; +} + +/* +** 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(OsFile *fd, u32 val){ +  unsigned char ac[4]; +  ac[0] = (val>>24) & 0xff; +  ac[1] = (val>>16) & 0xff; +  ac[2] = (val>>8) & 0xff; +  ac[3] = val & 0xff; +  return sqlite3OsWrite(fd, ac, 4); +} + +/* +** Write the 32-bit integer 'val' into the page identified by page header +** 'p' at offset 'offset'. +*/ +static void store32bits(u32 val, PgHdr *p, int offset){ +  unsigned char *ac; +  ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; +  ac[0] = (val>>24) & 0xff; +  ac[1] = (val>>16) & 0xff; +  ac[2] = (val>>8) & 0xff; +  ac[3] = val & 0xff; +} + +/* +** Read a 32-bit integer at offset 'offset' from the page identified by +** page header 'p'. +*/ +static u32 retrieve32bits(PgHdr *p, int offset){ +  unsigned char *ac; +  ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; +  return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; +} + + +/* +** Convert the bits in the pPager->errMask into an approprate +** return code. +*/ +static int pager_errcode(Pager *pPager){ +  int rc = SQLITE_OK; +  if( pPager->errMask & PAGER_ERR_LOCK )    rc = SQLITE_PROTOCOL; +  if( pPager->errMask & PAGER_ERR_DISK )    rc = SQLITE_IOERR; +  if( pPager->errMask & PAGER_ERR_FULL )    rc = SQLITE_FULL; +  if( pPager->errMask & PAGER_ERR_MEM )     rc = SQLITE_NOMEM; +  if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; +  return rc; +} + +/* +** 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 obtained from sqliteMalloc(). *pzMaster is +** set to point at the memory and SQLITE_OK returned. The caller must +** sqliteFree() *pzMaster. +** +** If no master journal file name is present *pzMaster is set to 0 and +** SQLITE_OK returned. +*/ +static int readMasterJournal(OsFile *pJrnl, char **pzMaster){ +  int rc; +  u32 len; +  i64 szJ; +  u32 cksum; +  int i; +  unsigned char aMagic[8]; /* A buffer to hold the magic header */ + +  *pzMaster = 0; + +  rc = sqlite3OsFileSize(pJrnl, &szJ); +  if( rc!=SQLITE_OK || szJ<16 ) return rc; + +  rc = sqlite3OsSeek(pJrnl, szJ-16); +  if( rc!=SQLITE_OK ) return rc; +  +  rc = read32bits(pJrnl, &len); +  if( rc!=SQLITE_OK ) return rc; + +  rc = read32bits(pJrnl, &cksum); +  if( rc!=SQLITE_OK ) return rc; + +  rc = sqlite3OsRead(pJrnl, aMagic, 8); +  if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; + +  rc = sqlite3OsSeek(pJrnl, szJ-16-len); +  if( rc!=SQLITE_OK ) return rc; + +  *pzMaster = (char *)sqliteMalloc(len+1); +  if( !*pzMaster ){ +    return SQLITE_NOMEM; +  } +  rc = sqlite3OsRead(pJrnl, *pzMaster, len); +  if( rc!=SQLITE_OK ){ +    sqliteFree(*pzMaster); +    *pzMaster = 0; +    return rc; +  } + +  /* See if the checksum matches the master journal name */ +  for(i=0; i<len; i++){ +    cksum -= (*pzMaster)[i]; +  } +  if( cksum ){ +    /* If the checksum doesn't add up, then one or more of the disk sectors +    ** containing the master journal filename is corrupted. This means +    ** definitely roll back, so just return SQLITE_OK and report a (nul) +    ** master-journal filename. +    */ +    sqliteFree(*pzMaster); +    *pzMaster = 0; +  } +  (*pzMaster)[len] = '\0'; +    +  return SQLITE_OK; +} + +/* +** Seek the journal file descriptor to the next sector boundary where a +** journal header may be read or written. Pager.journalOff is updated with +** the new seek offset. +** +** i.e for a sector size of 512: +** +** Input Offset              Output Offset +** --------------------------------------- +** 0                         0 +** 512                       512 +** 100                       512 +** 2000                      2048 +**  +*/ +static int seekJournalHdr(Pager *pPager){ +  i64 offset = 0; +  i64 c = pPager->journalOff; +  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)<JOURNAL_HDR_SZ(pPager) ); +  pPager->journalOff = offset; +  return sqlite3OsSeek(&pPager->jfd, pPager->journalOff); +} + +/* +** 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){ + +  int rc = seekJournalHdr(pPager); +  if( rc ) return rc; + +  pPager->journalHdr = pPager->journalOff; +  if( pPager->stmtHdrOff==0 ){ +    pPager->stmtHdrOff = pPager->journalHdr; +  } +  pPager->journalOff += JOURNAL_HDR_SZ(pPager); + +  /* FIX ME:  +  ** +  ** Possibly for a pager not in no-sync mode, the journal magic should not +  ** be written until nRec is filled in as part of next syncJournal().  +  ** +  ** Actually maybe the whole journal header should be delayed until that +  ** point. Think about this. +  */ +  rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + +  if( rc==SQLITE_OK ){ +    /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ +    rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); +  } +  if( rc==SQLITE_OK ){ +    /* The random check-hash initialiser */  +    sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); +    rc = write32bits(&pPager->jfd, pPager->cksumInit); +  } +  if( rc==SQLITE_OK ){ +    /* The initial database size */ +    rc = write32bits(&pPager->jfd, pPager->dbSize); +  } +  if( rc==SQLITE_OK ){ +    /* The assumed sector size for this process */ +    rc = write32bits(&pPager->jfd, pPager->sectorSize); +  } + +  /* The journal header has been written successfully. Seek the journal +  ** file descriptor to the end of the journal header sector. +  */ +  if( rc==SQLITE_OK ){ +    sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1); +    rc = sqlite3OsWrite(&pPager->jfd, "\000", 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 */ + +  rc = seekJournalHdr(pPager); +  if( rc ) return rc; + +  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ +    return SQLITE_DONE; +  } + +  rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic)); +  if( rc ) return rc; + +  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ +    return SQLITE_DONE; +  } + +  rc = read32bits(&pPager->jfd, pNRec); +  if( rc ) return rc; + +  rc = read32bits(&pPager->jfd, &pPager->cksumInit); +  if( rc ) return rc; + +  rc = read32bits(&pPager->jfd, 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, (u32 *)&pPager->sectorSize); +  if( rc ) return rc; + +  pPager->journalOff += JOURNAL_HDR_SZ(pPager); +  rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); +  return rc; +} + + +/* +** 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. +*/ +static int writeMasterJournal(Pager *pPager, const char *zMaster){ +  int rc; +  int len;  +  int i;  +  u32 cksum = 0;  + +  if( !zMaster || pPager->setMaster) return SQLITE_OK; +  pPager->setMaster = 1; + +  len = strlen(zMaster); +  for(i=0; i<len; i++){ +    cksum += zMaster[i]; +  } + +  /* If in full-sync mode, advance to the next disk sector before writing +  ** the master journal name. This is in case the previous page written to +  ** the journal has already been synced. +  */ +  if( pPager->fullSync ){ +    rc = seekJournalHdr(pPager); +    if( rc!=SQLITE_OK ) return rc; +  } +  pPager->journalOff += (len+20); + +  rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager)); +  if( rc!=SQLITE_OK ) return rc; + +  rc = sqlite3OsWrite(&pPager->jfd, zMaster, len); +  if( rc!=SQLITE_OK ) return rc; + +  rc = write32bits(&pPager->jfd, len); +  if( rc!=SQLITE_OK ) return rc; + +  rc = write32bits(&pPager->jfd, cksum); +  if( rc!=SQLITE_OK ) return rc; + +  rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); +  pPager->needSync = 1; +  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 sqlite3pager_stmt_commit() +** 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; +  if( pPg->inStmt ) return; +  assert( pPg->pPrevStmt==0 && pPg->pNextStmt==0 ); +  pPg->pPrevStmt = 0; +  if( pPager->pStmt ){ +    pPager->pStmt->pPrevStmt = pPg; +  } +  pPg->pNextStmt = pPager->pStmt; +  pPager->pStmt = pPg; +  pPg->inStmt = 1; +} +static void page_remove_from_stmt_list(PgHdr *pPg){ +  if( !pPg->inStmt ) return; +  if( pPg->pPrevStmt ){ +    assert( pPg->pPrevStmt->pNextStmt==pPg ); +    pPg->pPrevStmt->pNextStmt = pPg->pNextStmt; +  }else{ +    assert( pPg->pPager->pStmt==pPg ); +    pPg->pPager->pStmt = pPg->pNextStmt; +  } +  if( pPg->pNextStmt ){ +    assert( pPg->pNextStmt->pPrevStmt==pPg ); +    pPg->pNextStmt->pPrevStmt = pPg->pPrevStmt; +  } +  pPg->pNextStmt = 0; +  pPg->pPrevStmt = 0; +  pPg->inStmt = 0; +} + +/* +** 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 = pPager->aHash[pager_hash(pgno)]; +  while( p && p->pgno!=pgno ){ +    p = p->pNextHash; +  } +  return p; +} + +/* +** Unlock the database and 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; +  for(pPg=pPager->pAll; pPg; pPg=pNext){ +    pNext = pPg->pNextAll; +    sqliteFree(pPg); +  } +  pPager->pFirst = 0; +  pPager->pFirstSynced = 0; +  pPager->pLast = 0; +  pPager->pAll = 0; +  memset(pPager->aHash, 0, sizeof(pPager->aHash)); +  pPager->nPage = 0; +  if( pPager->state>=PAGER_RESERVED ){ +    sqlite3pager_rollback(pPager); +  } +  sqlite3OsUnlock(&pPager->fd, NO_LOCK); +  pPager->state = PAGER_UNLOCK; +  pPager->dbSize = -1; +  pPager->nRef = 0; +  assert( pPager->journalOpen==0 ); +} + +/* +** When this routine is called, the pager has the journal file open and +** a RESERVED or EXCLUSIVE lock on the database.  This routine releases +** the database lock and acquires a SHARED lock in its place.  The journal +** file is deleted and closed. +** +** 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_unwritelock(Pager *pPager){ +  PgHdr *pPg; +  int rc; +  assert( !pPager->memDb ); +  if( pPager->state<PAGER_RESERVED ){ +    return SQLITE_OK; +  } +  sqlite3pager_stmt_commit(pPager); +  if( pPager->stmtOpen ){ +    sqlite3OsClose(&pPager->stfd); +    pPager->stmtOpen = 0; +  } +  if( pPager->journalOpen ){ +    sqlite3OsClose(&pPager->jfd); +    pPager->journalOpen = 0; +    sqlite3OsDelete(pPager->zJournal); +    sqliteFree( pPager->aInJournal ); +    pPager->aInJournal = 0; +    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ +      pPg->inJournal = 0; +      pPg->dirty = 0; +      pPg->needSync = 0; +    } +    pPager->dirtyCache = 0; +    pPager->nRec = 0; +  }else{ +    assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); +  } +  rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); +  pPager->state = PAGER_SHARED; +  pPager->origDbSize = 0; +  pPager->setMaster = 0; +  return 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, Pgno pgno, const char *aData){ +  u32 cksum = pPager->cksumInit; +  int i = pPager->pageSize-200; +  while( i>0 ){ +    cksum += aData[i]; +    i -= 200; +  } +  return cksum; +} + +/* +** 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, OsFile *jfd, 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[SQLITE_MAX_PAGE_SIZE];  /* Temp storage for a page */ + +  rc = read32bits(jfd, &pgno); +  if( rc!=SQLITE_OK ) return rc; +  rc = sqlite3OsRead(jfd, &aData, pPager->pageSize); +  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, &cksum); +    if( rc ) return rc; +    pPager->journalOff += 4; +    if( pager_cksum(pPager, pgno, 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. +  ** +  ** If in EXCLUSIVE state, then we update the pager cache if it exists +  ** and the main file. The page is then marked not dirty. +  */ +  pPg = pager_lookup(pPager, pgno); +  assert( pPager->state>=PAGER_EXCLUSIVE || pPg ); +  TRACE3("PLAYBACK %d page %d\n", pPager->fd.h, pgno); +  if( pPager->state>=PAGER_EXCLUSIVE ){ +    sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); +    rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize); +  } +  if( pPg ){ +    /* No page should ever be 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. +    */ +    void *pData; +    assert( pPg->nRef==0 || pPg->pgno==1 ); +    pData = PGHDR_TO_DATA(pPg); +    memcpy(pData, aData, pPager->pageSize); +    if( pPager->xDestructor ){  /*** FIX ME:  Should this be xReinit? ***/ +      pPager->xDestructor(pData, pPager->pageSize); +    } +    if( pPager->state>=PAGER_EXCLUSIVE ){ +      pPg->dirty = 0; +      pPg->needSync = 0; +    } +    CODEC(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. +** +** 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(const char *zMaster){ +  int rc; +  int master_open = 0; +  OsFile master; +  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. +  */ +  memset(&master, 0, sizeof(master)); +  rc = sqlite3OsOpenReadOnly(zMaster, &master); +  if( rc!=SQLITE_OK ) goto delmaster_out; +  master_open = 1; +  rc = sqlite3OsFileSize(&master, &nMasterJournal); +  if( rc!=SQLITE_OK ) goto delmaster_out; + +  if( nMasterJournal>0 ){ +    char *zJournal; +    char *zMasterPtr = 0; + +    /* Load the entire master journal file into space obtained from +    ** sqliteMalloc() and pointed to by zMasterJournal.  +    */ +    zMasterJournal = (char *)sqliteMalloc(nMasterJournal); +    if( !zMasterJournal ){ +      rc = SQLITE_NOMEM; +      goto delmaster_out; +    } +    rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal); +    if( rc!=SQLITE_OK ) goto delmaster_out; + +    zJournal = zMasterJournal; +    while( (zJournal-zMasterJournal)<nMasterJournal ){ +      if( sqlite3OsFileExists(zJournal) ){ +        /* One of the journals pointed to by the master journal exists. +        ** Open it and check if it points at the master journal. If +        ** so, return without deleting the master journal file. +        */ +        OsFile journal; + +        memset(&journal, 0, sizeof(journal)); +        rc = sqlite3OsOpenReadOnly(zJournal, &journal); +        if( rc!=SQLITE_OK ){ +          goto delmaster_out; +        } + +        rc = readMasterJournal(&journal, &zMasterPtr); +        sqlite3OsClose(&journal); +        if( rc!=SQLITE_OK ){ +          goto delmaster_out; +        } + +        if( zMasterPtr && !strcmp(zMasterPtr, zMaster) ){ +          /* We have a match. Do not delete the master journal file. */ +          goto delmaster_out; +        } +      } +      zJournal += (strlen(zJournal)+1); +    } +  } +   +  sqlite3OsDelete(zMaster); + +delmaster_out: +  if( zMasterJournal ){ +    sqliteFree(zMasterJournal); +  }   +  if( master_open ){ +    sqlite3OsClose(&master); +  } +  return rc; +} + +/* +** Make every page in the cache agree with what is on disk.  In other words, +** reread the disk to reset the state of the cache. +** +** This routine is called after a rollback in which some of the dirty cache +** pages had never been written out to disk.  We need to roll back the +** cache content and the easiest way to do that is to reread the old content +** back from the disk. +*/ +static int pager_reload_cache(Pager *pPager){ +  PgHdr *pPg; +  int rc = SQLITE_OK; +  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ +    char zBuf[SQLITE_MAX_PAGE_SIZE]; +    if( !pPg->dirty ) continue; +    if( (int)pPg->pgno <= pPager->origDbSize ){ +      sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); +      rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize); +      TRACE3("REFETCH %d page %d\n", pPager->fd.h, pPg->pgno); +      if( rc ) break; +      CODEC(pPager, zBuf, pPg->pgno, 2); +    }else{ +      memset(zBuf, 0, pPager->pageSize); +    } +    if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){ +      memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize); +      if( pPager->xReiniter ){ +        pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize); +      }else{ +        memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); +      } +    } +    pPg->needSync = 0; +    pPg->dirty = 0; +  } +  return rc; +} + +/* +** Truncate the main file of the given pager to the number of pages +** indicated. +*/ +static int pager_truncate(Pager *pPager, int nPage){ +  return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage); +} + +/* +** 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){ +  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 ){ +    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. +  */ +  rc = readMasterJournal(&pPager->jfd, &zMaster); +  assert( rc!=SQLITE_DONE ); +  if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ +    sqliteFree(zMaster); +    zMaster = 0; +    if( rc==SQLITE_DONE ) rc = SQLITE_OK; +    goto end_playback; +  } +  sqlite3OsSeek(&pPager->jfd, 0); +  pPager->journalOff = 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 this is the first header read from the journal, truncate the +    ** database file back to it's original size. +    */ +    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ +      assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); +      rc = pager_truncate(pPager, mxPg); +      if( rc!=SQLITE_OK ){ +        goto end_playback; +      } +      pPager->dbSize = mxPg; +    } + +    /* rc = sqlite3OsSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ +    if( rc!=SQLITE_OK ) goto end_playback; +   +    /* Copy original pages out of the journal and back into the database file. +    */ +    for(i=0; i<nRec; i++){ +      rc = pager_playback_one_page(pPager, &pPager->jfd, 1); +      if( rc!=SQLITE_OK ){ +        if( rc==SQLITE_DONE ){ +          rc = SQLITE_OK; +          pPager->journalOff = szJ; +          break; +        }else{ +          goto end_playback; +        } +      } +    } +  } + +  /* Pages that have been written to the journal but never synced +  ** where not restored by the loop above.  We have to restore those +  ** pages by reading them back from the original database. +  */ +  assert( rc==SQLITE_OK ); +  pager_reload_cache(pPager); + +end_playback: +  if( rc==SQLITE_OK ){ +    rc = pager_unwritelock(pPager); +  } +  if( zMaster ){ +    /* If there was a master journal and this routine will return true, +    ** see if it is possible to delete the master journal. If errors  +    ** occur during this process, ignore them. +    */ +    if( rc==SQLITE_OK ){ +      pager_delmaster(zMaster); +    } +    sqliteFree(zMaster); +  } + +  /* The Pager.sectorSize variable may have been updated while rolling +  ** back a journal created by a process with a different PAGER_SECTOR_SIZE +  ** value. Reset it to the correct value for this process. +  */ +  pPager->sectorSize = PAGER_SECTOR_SIZE; +  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 to the first journal header written +  ** this statement transaction, 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); +  pPager->dbSize = pPager->stmtSize; + +  /* Figure out how many records are in the statement journal. +  */ +  assert( pPager->stmtInUse && pPager->journalOpen ); +  sqlite3OsSeek(&pPager->stfd, 0); +  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=nRec-1; i>=0; i--){ +    rc = pager_playback_one_page(pPager, &pPager->stfd, 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. +  */ +  rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize); +  if( rc!=SQLITE_OK ){ +    goto end_stmt_playback; +  } +  pPager->journalOff = pPager->stmtJSize; +  pPager->cksumInit = pPager->stmtCksum; +  assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); +  while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ +    rc = pager_playback_one_page(pPager, &pPager->jfd, 1); +    assert( rc!=SQLITE_DONE ); +    if( rc!=SQLITE_OK ) goto end_stmt_playback; +  } + +  while( pPager->journalOff < szJ ){ +    u32 nRec; +    u32 dummy; +    rc = readJournalHdr(pPager, szJ, &nRec, &dummy); +    if( rc!=SQLITE_OK ){ +      assert( rc!=SQLITE_DONE ); +      goto end_stmt_playback; +    } +    if( nRec==0 ){ +      nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); +    } +    for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){ +      rc = pager_playback_one_page(pPager, &pPager->jfd, 1); +      assert( rc!=SQLITE_DONE ); +      if( rc!=SQLITE_OK ) goto end_stmt_playback; +    } +  } + +  pPager->journalOff = szJ; +   +end_stmt_playback: +  if( rc!=SQLITE_OK ){ +    pPager->errMask |= PAGER_ERR_CORRUPT; +    rc = SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +  }else{ +    pPager->journalOff = szJ; +    /* pager_reload_cache(pPager); */ +  } +  return rc; +} + +/* +** Change the maximum number of in-memory pages that are allowed. +** +** The maximum number is the absolute value of the mxPage parameter. +** If mxPage is negative, the noSync flag is also set.  noSync bypasses +** calls to sqlite3OsSync().  The pager runs much faster with noSync on, +** but if the operating system crashes or there is an abrupt power  +** failure, the database file might be left in an inconsistent and +** unrepairable state.   +*/ +void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ +  if( mxPage>=0 ){ +    pPager->noSync = pPager->tempFile; +    if( pPager->noSync ) pPager->needSync = 0;  +  }else{ +    pPager->noSync = 1; +    mxPage = -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. +*/ +void sqlite3pager_set_safety_level(Pager *pPager, int level){ +  pPager->noSync =  level==1 || pPager->tempFile; +  pPager->fullSync = level==3 && !pPager->tempFile; +  if( pPager->noSync ) pPager->needSync = 0; +} + +/* +** Open a temporary file.  Write the name of the file into zName +** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.)  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 sqlite3pager_opentemp(char *zFile, OsFile *fd){ +  int cnt = 8; +  int rc; +  do{ +    cnt--; +    sqlite3OsTempFileName(zFile); +    rc = sqlite3OsOpenExclusive(zFile, fd, 1); +  }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); +  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 sqlite3pager_get() and is only held open until the +** last page is released using sqlite3pager_unref(). +** +** 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 sqlite3pager_open( +  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 useJournal           /* TRUE to use a rollback journal on this file */ +){ +  Pager *pPager; +  char *zFullPathname = 0; +  int nameLen; +  OsFile fd; +  int rc = SQLITE_OK; +  int i; +  int tempFile = 0; +  int memDb = 0; +  int readOnly = 0; +  char zTemp[SQLITE_TEMPNAME_SIZE]; + +  *ppPager = 0; +  memset(&fd, 0, sizeof(fd)); +  if( sqlite3_malloc_failed ){ +    return SQLITE_NOMEM; +  } +  if( zFilename && zFilename[0] ){ +    if( strcmp(zFilename,":memory:")==0 ){ +      memDb = 1; +      zFullPathname = sqliteStrDup(""); +      rc = SQLITE_OK; +    }else{ +      zFullPathname = sqlite3OsFullPathname(zFilename); +      if( zFullPathname ){ +        rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); +      } +    } +  }else{ +    rc = sqlite3pager_opentemp(zTemp, &fd); +    zFilename = zTemp; +    zFullPathname = sqlite3OsFullPathname(zFilename); +    if( rc==SQLITE_OK ){ +      tempFile = 1; +    } +  } +  if( !zFullPathname ){ +    sqlite3OsClose(&fd); +    return SQLITE_NOMEM; +  } +  if( rc!=SQLITE_OK ){ +    sqlite3OsClose(&fd); +    sqliteFree(zFullPathname); +    return rc; +  } +  nameLen = strlen(zFullPathname); +  pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); +  if( pPager==0 ){ +    sqlite3OsClose(&fd); +    sqliteFree(zFullPathname); +    return SQLITE_NOMEM; +  } +  TRACE3("OPEN %d %s\n", fd.h, zFullPathname); +  pPager->zFilename = (char*)&pPager[1]; +  pPager->zDirectory = &pPager->zFilename[nameLen+1]; +  pPager->zJournal = &pPager->zDirectory[nameLen+1]; +  strcpy(pPager->zFilename, zFullPathname); +  strcpy(pPager->zDirectory, zFullPathname); +  for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} +  if( i>0 ) pPager->zDirectory[i-1] = 0; +  strcpy(pPager->zJournal, zFullPathname); +  sqliteFree(zFullPathname); +  strcpy(&pPager->zJournal[nameLen], "-journal"); +  pPager->fd = fd; +#if OS_UNIX +  pPager->fd.pPager = pPager; +#endif +  pPager->journalOpen = 0; +  pPager->useJournal = useJournal && !memDb; +  pPager->stmtOpen = 0; +  pPager->stmtInUse = 0; +  pPager->nRef = 0; +  pPager->dbSize = memDb-1; +  pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; +  pPager->stmtSize = 0; +  pPager->stmtJSize = 0; +  pPager->nPage = 0; +  pPager->mxPage = 100; +  pPager->state = PAGER_UNLOCK; +  pPager->errMask = 0; +  pPager->tempFile = tempFile; +  pPager->memDb = memDb; +  pPager->readOnly = readOnly; +  pPager->needSync = 0; +  pPager->noSync = pPager->tempFile || !useJournal; +  pPager->fullSync = (pPager->noSync?0:1); +  pPager->pFirst = 0; +  pPager->pFirstSynced = 0; +  pPager->pLast = 0; +  pPager->nExtra = nExtra; +  pPager->sectorSize = PAGER_SECTOR_SIZE; +  pPager->pBusyHandler = 0; +  memset(pPager->aHash, 0, sizeof(pPager->aHash)); +  *ppPager = pPager; +  return SQLITE_OK; +} + +/* +** Set the busy handler function. +*/ +void sqlite3pager_set_busyhandler(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 sqlite3pager_close().   +** Destructors are only called by sqlite3pager_unref(). +*/ +void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*,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 sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ +  pPager->xReiniter = xReinit; +} + +/* +** Set the page size. +** +** The page size must only be changed when the cache is empty. +*/ +void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ +  assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); +  pPager->pageSize = pageSize; +} + +/* +** Read the first N bytes from the beginning of the file into memory +** that pDest points to.  No error checking is done. +*/ +void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ +  memset(pDest, 0, N); +  if( pPager->memDb==0 ){ +    sqlite3OsSeek(&pPager->fd, 0); +    sqlite3OsRead(&pPager->fd, pDest, N); +  } +} + +/* +** Return the total number of pages in the disk file associated with +** pPager. +*/ +int sqlite3pager_pagecount(Pager *pPager){ +  i64 n; +  assert( pPager!=0 ); +  if( pPager->dbSize>=0 ){ +    return pPager->dbSize; +  } +  if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ +    pPager->errMask |= PAGER_ERR_DISK; +    return 0; +  } +  n /= pPager->pageSize; +  if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){ +    n++; +  } +  if( pPager->state!=PAGER_UNLOCK ){ +    pPager->dbSize = n; +  } +  return n; +} + +/* +** Forward declaration +*/ +static int syncJournal(Pager*); + + +/* +** 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; + +  /* Keep the pFirstSynced pointer pointing at the first synchronized page */ +  if( pPg==pPager->pFirstSynced ){ +    PgHdr *p = pPg->pNextFree; +    while( p && p->needSync ){ p = p->pNextFree; } +    pPager->pFirstSynced = p; +  } + +  /* Unlink from the freelist */ +  if( pPg->pPrevFree ){ +    pPg->pPrevFree->pNextFree = pPg->pNextFree; +  }else{ +    assert( pPager->pFirst==pPg ); +    pPager->pFirst = pPg->pNextFree; +  } +  if( pPg->pNextFree ){ +    pPg->pNextFree->pPrevFree = pPg->pPrevFree; +  }else{ +    assert( pPager->pLast==pPg ); +    pPager->pLast = pPg->pPrevFree; +  } +  pPg->pNextFree = pPg->pPrevFree = 0; + +  /* Unlink from the pgno hash table */ +  if( pPg->pNextHash ){ +    pPg->pNextHash->pPrevHash = pPg->pPrevHash; +  } +  if( pPg->pPrevHash ){ +    pPg->pPrevHash->pNextHash = pPg->pNextHash; +  }else{ +    int h = pager_hash(pPg->pgno); +    assert( pPager->aHash[h]==pPg ); +    pPager->aHash[h] = pPg->pNextHash; +  } +  pPg->pNextHash = pPg->pPrevHash = 0; +} + +/* +** This routine is used to truncate an in-memory database.  Delete +** all pages whose pgno is larger than pPager->dbSize and is unreferenced. +** Referenced pages larger than pPager->dbSize are zeroed. +*/ +static void memoryTruncate(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; +      unlinkPage(pPg); +      sqliteFree(pPg); +      pPager->nPage--; +    } +  } +} + +/* +** Truncate the file to the number of pages specified. +*/ +int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ +  int rc; +  sqlite3pager_pagecount(pPager); +  if( pPager->errMask!=0 ){ +    rc = pager_errcode(pPager); +    return rc; +  } +  if( nPage>=(unsigned)pPager->dbSize ){ +    return SQLITE_OK; +  } +  if( pPager->memDb ){ +    pPager->dbSize = nPage; +    memoryTruncate(pPager); +    return SQLITE_OK; +  } +  rc = syncJournal(pPager); +  if( rc!=SQLITE_OK ){ +    return rc; +  } +  rc = pager_truncate(pPager, nPage); +  if( rc==SQLITE_OK ){ +    pPager->dbSize = 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. +*/ +int sqlite3pager_close(Pager *pPager){ +  PgHdr *pPg, *pNext; +  switch( pPager->state ){ +    case PAGER_RESERVED: +    case PAGER_SYNCED:  +    case PAGER_EXCLUSIVE: { +      sqlite3pager_rollback(pPager); +      if( !pPager->memDb ){ +        sqlite3OsUnlock(&pPager->fd, NO_LOCK); +      } +      assert( pPager->journalOpen==0 ); +      break; +    } +    case PAGER_SHARED: { +      if( !pPager->memDb ){ +        sqlite3OsUnlock(&pPager->fd, NO_LOCK); +      } +      break; +    } +    default: { +      /* Do nothing */ +      break; +    } +  } +  for(pPg=pPager->pAll; pPg; pPg=pNext){ +#ifndef NDEBUG +    if( pPager->memDb ){ +      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); +      assert( !pPg->alwaysRollback ); +      assert( !pHist->pOrig ); +      assert( !pHist->pStmt ); +    } +#endif +    pNext = pPg->pNextAll; +    sqliteFree(pPg); +  } +  TRACE2("CLOSE %d\n", pPager->fd.h); +  sqlite3OsClose(&pPager->fd); +  assert( pPager->journalOpen==0 ); +  /* Temp files are automatically deleted by the OS +  ** if( pPager->tempFile ){ +  **   sqlite3OsDelete(pPager->zFilename); +  ** } +  */ +  if( pPager->zFilename!=(char*)&pPager[1] ){ +    assert( 0 );  /* Cannot happen */ +    sqliteFree(pPager->zFilename); +    sqliteFree(pPager->zJournal); +    sqliteFree(pPager->zDirectory); +  } +  sqliteFree(pPager); +  return SQLITE_OK; +} + +/* +** Return the page number for the given page data. +*/ +Pgno sqlite3pager_pagenumber(void *pData){ +  PgHdr *p = DATA_TO_PGHDR(pData); +  return p->pgno; +} + +/* +** 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. */ +    if( pPg==pPg->pPager->pFirstSynced ){ +      PgHdr *p = pPg->pNextFree; +      while( p && p->needSync ){ p = p->pNextFree; } +      pPg->pPager->pFirstSynced = p; +    } +    if( pPg->pPrevFree ){ +      pPg->pPrevFree->pNextFree = pPg->pNextFree; +    }else{ +      pPg->pPager->pFirst = pPg->pNextFree; +    } +    if( pPg->pNextFree ){ +      pPg->pNextFree->pPrevFree = pPg->pPrevFree; +    }else{ +      pPg->pPager->pLast = pPg->pPrevFree; +    } +    pPg->pPager->nRef++; +  } +  pPg->nRef++; +  REFINFO(pPg); +} +#ifdef SQLITE_TEST +  static void page_ref(PgHdr *pPg){ +    if( pPg->nRef==0 ){ +      _page_ref(pPg); +    }else{ +      pPg->nRef++; +      REFINFO(pPg); +    } +  } +#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 sqlite3pager_ref(void *pData){ +  PgHdr *pPg = DATA_TO_PGHDR(pData); +  page_ref(pPg); +  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 sync occurs. +** +** 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 ){ +      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 +      { +        /* 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.  +        */ +        if( pPager->fullSync ){ +          TRACE2("SYNC journal of %d\n", pPager->fd.h); +          rc = sqlite3OsSync(&pPager->jfd); +          if( rc!=0 ) return rc; +        } +        sqlite3OsSeek(&pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); +        rc = write32bits(&pPager->jfd, pPager->nRec); +        if( rc ) return rc; + +        sqlite3OsSeek(&pPager->jfd, pPager->journalOff); +      } +      TRACE2("SYNC journal of %d\n", pPager->fd.h); +      rc = sqlite3OsSync(&pPager->jfd); +      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; +    } +    pPager->pFirstSynced = pPager->pFirst; +  } + +#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->pFirstSynced==pPager->pFirst ); +  } +#endif + +  return rc; +} + +/* +** Try to obtain a lock on a file.  Invoke the busy callback if the lock +** is currently not available.  Repeate 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; +  assert( PAGER_SHARED==SHARED_LOCK ); +  assert( PAGER_RESERVED==RESERVED_LOCK ); +  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); +  if( pPager->state>=locktype ){ +    rc = SQLITE_OK; +  }else{ +    int busy = 1; +    do { +      rc = sqlite3OsLock(&pPager->fd, locktype); +    }while( rc==SQLITE_BUSY &&  +        pPager->pBusyHandler &&  +        pPager->pBusyHandler->xFunc &&  +        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++) +    ); +    if( rc==SQLITE_OK ){ +      pPager->state = locktype; +    } +  } +  return rc; +} + +/* +** Given a list of pages (connected by the PgHdr.pDirty pointer) write +** every one of those pages out to the database file and mark them all +** as clean. +*/ +static int pager_write_pagelist(PgHdr *pList){ +  Pager *pPager; +  int rc; + +  if( pList==0 ) return SQLITE_OK; +  pPager = pList->pPager; + +  /* 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; +  } + +  while( pList ){ +    assert( pList->dirty ); +    sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); +    CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); +    TRACE3("STORE %d page %d\n", pPager->fd.h, pList->pgno); +    rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); +    CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); +    if( rc ) return rc; +    pList->dirty = 0; +    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){ +  PgHdr *p, *pList; +  pList = 0; +  for(p=pPager->pAll; p; p=p->pNextAll){ +    if( p->dirty ){ +      p->pDirty = pList; +      pList = p; +    } +  } +  return pList; +} + +/* +** 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. +** +** A _get 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 sqlite3pager_lookup().  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. +*/ +int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ +  PgHdr *pPg; +  int rc; + +  /* Make sure we have not hit any critical errors. +  */  +  assert( pPager!=0 ); +  assert( pgno!=0 ); +  *ppPage = 0; +  if( pPager->errMask & ~(PAGER_ERR_FULL) ){ +    return pager_errcode(pPager); +  } + +  /* If this is the first page accessed, then get a SHARED lock +  ** on the database file. +  */ +  if( pPager->nRef==0 && !pPager->memDb ){ +    rc = pager_wait_on_lock(pPager, SHARED_LOCK); +    if( rc!=SQLITE_OK ){ +      return rc; +    } + +    /* 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( pPager->useJournal &&  +        sqlite3OsFileExists(pPager->zJournal) && +        !sqlite3OsCheckReservedLock(&pPager->fd)  +    ){ +       int rc; + +       /* 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 it's own EXCLUSIVE lock on the database file. +       */ +       rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); +       if( rc!=SQLITE_OK ){ +         sqlite3OsUnlock(&pPager->fd, NO_LOCK); +         pPager->state = PAGER_UNLOCK; +         return 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. +       */ +       rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd); +       if( rc!=SQLITE_OK ){ +         sqlite3OsUnlock(&pPager->fd, NO_LOCK); +         pPager->state = PAGER_UNLOCK; +         return 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); +       if( rc!=SQLITE_OK ){ +         return rc; +       } +    } +    pPg = 0; +  }else{ +    /* Search for page in cache */ +    pPg = pager_lookup(pPager, pgno); +    if( pPager->memDb && pPager->state==PAGER_UNLOCK ){ +      pPager->state = PAGER_SHARED; +    } +  } +  if( pPg==0 ){ +    /* The requested page is not in the page cache. */ +    int h; +    pPager->nMiss++; +    if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){ +      /* Create a new page */ +      pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize  +                              + sizeof(u32) + pPager->nExtra +                              + pPager->memDb*sizeof(PgHistory) ); +      if( pPg==0 ){ +        if( !pPager->memDb ){ +          pager_unwritelock(pPager); +        } +        pPager->errMask |= PAGER_ERR_MEM; +        return SQLITE_NOMEM; +      } +      memset(pPg, 0, sizeof(*pPg)); +      if( pPager->memDb ){ +        memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); +      } +      pPg->pPager = pPager; +      pPg->pNextAll = pPager->pAll; +      pPager->pAll = pPg; +      pPager->nPage++; +    }else{ +      /* Find a page to recycle.  Try to locate a page that does not +      ** require us to do an fsync() on the journal. +      */ +      pPg = pPager->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 ){ +        int rc = syncJournal(pPager); +        if( rc!=0 ){ +          sqlite3pager_rollback(pPager); +          return SQLITE_IOERR; +        } +        if( pPager->fullSync ){ +          /* 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 ); +          rc = writeJournalHdr(pPager); +          if( rc!=0 ){ +            sqlite3pager_rollback(pPager); +            return SQLITE_IOERR; +          } +        } +        pPg = pPager->pFirst; +      } +      assert( pPg->nRef==0 ); + +      /* Write the page to the database file if it is dirty. +      */ +      if( pPg->dirty ){ +        assert( pPg->needSync==0 ); +        pPg->pDirty = 0; +        rc = pager_write_pagelist( pPg ); +        if( rc!=SQLITE_OK ){ +          sqlite3pager_rollback(pPager); +          return SQLITE_IOERR; +        } +      } +      assert( pPg->dirty==0 ); + +      /* If the page we are recycling is marked as alwaysRollback, then +      ** set the global alwaysRollback flag, thus disabling the +      ** sqlite_dont_rollback() 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 ){ +        pPager->alwaysRollback = 1; +      } + +      /* Unlink the old page from the free list and the hash table +      */ +      unlinkPage(pPg); +      pPager->nOvfl++; +    } +    pPg->pgno = pgno; +    if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ +      sqlite3CheckMemory(pPager->aInJournal, pgno/8); +      assert( pPager->journalOpen ); +      pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; +      pPg->needSync = 0; +    }else{ +      pPg->inJournal = 0; +      pPg->needSync = 0; +    } +    if( pPager->aInStmt && (int)pgno<=pPager->stmtSize +             && (pPager->aInStmt[pgno/8] & (1<<(pgno&7)))!=0 ){ +      page_add_to_stmt_list(pPg); +    }else{ +      page_remove_from_stmt_list(pPg); +    } +    pPg->dirty = 0; +    pPg->nRef = 1; +    REFINFO(pPg); +    pPager->nRef++; +    h = pager_hash(pgno); +    pPg->pNextHash = pPager->aHash[h]; +    pPager->aHash[h] = pPg; +    if( pPg->pNextHash ){ +      assert( pPg->pNextHash->pPrevHash==0 ); +      pPg->pNextHash->pPrevHash = pPg; +    } +    if( pPager->nExtra>0 ){ +      memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); +    } +    sqlite3pager_pagecount(pPager); +    if( pPager->errMask!=0 ){ +      sqlite3pager_unref(PGHDR_TO_DATA(pPg)); +      rc = pager_errcode(pPager); +      return rc; +    } +    if( pPager->dbSize<(int)pgno ){ +      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); +    }else{ +      int rc; +      assert( pPager->memDb==0 ); +      sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); +      rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); +      TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno); +      CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); +      if( rc!=SQLITE_OK ){ +        i64 fileSize; +        if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK +               || fileSize>=pgno*pPager->pageSize ){ +          sqlite3pager_unref(PGHDR_TO_DATA(pPg)); +          return rc; +        }else{ +          memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); +        } +      } +    } +  }else{ +    /* The requested page is in the page cache. */ +    pPager->nHit++; +    page_ref(pPg); +  } +  *ppPage = PGHDR_TO_DATA(pPg); +  return SQLITE_OK; +} + +/* +** 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 sqlite3pager_get().  The difference between this routine +** and sqlite3pager_get() 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. +*/ +void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ +  PgHdr *pPg; + +  assert( pPager!=0 ); +  assert( pgno!=0 ); +  if( pPager->errMask & ~(PAGER_ERR_FULL) ){ +    return 0; +  } +  pPg = pager_lookup(pPager, pgno); +  if( pPg==0 ) return 0; +  page_ref(pPg); +  return PGHDR_TO_DATA(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 sqlite3pager_unref(void *pData){ +  PgHdr *pPg; + +  /* Decrement the reference count for this page +  */ +  pPg = DATA_TO_PGHDR(pData); +  assert( pPg->nRef>0 ); +  pPg->nRef--; +  REFINFO(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 ){ +    Pager *pPager; +    pPager = pPg->pPager; +    pPg->pNextFree = 0; +    pPg->pPrevFree = pPager->pLast; +    pPager->pLast = pPg; +    if( pPg->pPrevFree ){ +      pPg->pPrevFree->pNextFree = pPg; +    }else{ +      pPager->pFirst = pPg; +    } +    if( pPg->needSync==0 && pPager->pFirstSynced==0 ){ +      pPager->pFirstSynced = pPg; +    } +    if( pPager->xDestructor ){ +      pPager->xDestructor(pData, 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->memDb ){ +      pager_reset(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){ +  int rc; +  assert( !pPager->memDb ); +  assert( pPager->state>=PAGER_RESERVED ); +  assert( pPager->journalOpen==0 ); +  assert( pPager->useJournal ); +  sqlite3pager_pagecount(pPager); +  pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); +  if( pPager->aInJournal==0 ){ +    rc = SQLITE_NOMEM; +    goto failed_to_open_journal; +  } +  rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); +  pPager->journalOff = 0; +  pPager->setMaster = 0; +  pPager->journalHdr = 0; +  if( rc!=SQLITE_OK ){ +    goto failed_to_open_journal; +  } +  sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); +  pPager->journalOpen = 1; +  pPager->journalStarted = 0; +  pPager->needSync = 0; +  pPager->alwaysRollback = 0; +  pPager->nRec = 0; +  if( pPager->errMask!=0 ){ +    rc = pager_errcode(pPager); +    return rc; +  } +  pPager->origDbSize = pPager->dbSize; + +  rc = writeJournalHdr(pPager); + +  if( pPager->stmtAutoopen && rc==SQLITE_OK ){ +    rc = sqlite3pager_stmt_begin(pPager); +  } +  if( rc!=SQLITE_OK ){ +    rc = pager_unwritelock(pPager); +    if( rc==SQLITE_OK ){ +      rc = SQLITE_FULL; +    } +  } +  return rc; + +failed_to_open_journal: +  sqliteFree(pPager->aInJournal); +  pPager->aInJournal = 0; +  sqlite3OsUnlock(&pPager->fd, NO_LOCK); +  pPager->state = PAGER_UNLOCK; +  return rc; +} + +/* +** Acquire a write-lock on the database.  The lock is removed when +** the any of the following happen: +** +**   *  sqlite3pager_commit() is called. +**   *  sqlite3pager_rollback() is called. +**   *  sqlite3pager_close() is called. +**   *  sqlite3pager_unref() 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 sqlite3pager_begin(void *pData, int exFlag){ +  PgHdr *pPg = DATA_TO_PGHDR(pData); +  Pager *pPager = pPg->pPager; +  int rc = SQLITE_OK; +  assert( pPg->nRef>0 ); +  assert( pPager->state!=PAGER_UNLOCK ); +  if( pPager->state==PAGER_SHARED ){ +    assert( pPager->aInJournal==0 ); +    if( pPager->memDb ){ +      pPager->state = PAGER_EXCLUSIVE; +      pPager->origDbSize = pPager->dbSize; +    }else{ +      if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){ +        rc = pager_wait_on_lock(pPager, RESERVED_LOCK); +      }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 ){ +        return rc; +      } +      pPager->dirtyCache = 0; +      TRACE2("TRANSACTION %d\n", pPager->fd.h); +      if( pPager->useJournal && !pPager->tempFile ){ +        rc = pager_open_journal(pPager); +      } +    } +  } +  return rc; +} + +/* +** 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 sqlite3pager_commit() or sqlite3pager_rollback() to +** reset. +*/ +int sqlite3pager_write(void *pData){ +  PgHdr *pPg = DATA_TO_PGHDR(pData); +  Pager *pPager = pPg->pPager; +  int rc = SQLITE_OK; + +  /* Check for errors +  */ +  if( pPager->errMask ){  +    return pager_errcode(pPager); +  } +  if( pPager->readOnly ){ +    return SQLITE_PERM; +  } + +  assert( !pPager->setMaster ); + +  /* Mark the page as dirty.  If the page has already been written +  ** to the journal then we can return right away. +  */ +  pPg->dirty = 1; +  if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){ +    pPager->dirtyCache = 1; +    return SQLITE_OK; +  } + +  /* 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 = sqlite3pager_begin(pData, 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 || pPager->memDb) ){ +    if( (int)pPg->pgno <= pPager->origDbSize ){ +      int szPg; +      u32 saved; +      if( pPager->memDb ){ +        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); +        TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno); +        assert( pHist->pOrig==0 ); +        pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); +        if( pHist->pOrig ){ +          memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); +        } +      }else{ +        u32 cksum; +        CODEC(pPager, pData, pPg->pgno, 7); +        cksum = pager_cksum(pPager, pPg->pgno, pData); +        saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager); +        store32bits(cksum, pPg, pPager->pageSize); +        szPg = pPager->pageSize+8; +        store32bits(pPg->pgno, pPg, -4); +        rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); +        pPager->journalOff += szPg; +        TRACE4("JOURNAL %d page %d needSync=%d\n", +                pPager->fd.h, pPg->pgno, pPg->needSync); +        CODEC(pPager, pData, pPg->pgno, 0); +        *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; +        if( rc!=SQLITE_OK ){ +          sqlite3pager_rollback(pPager); +          pPager->errMask |= PAGER_ERR_FULL; +          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); +          page_add_to_stmt_list(pPg); +        } +      } +    }else{ +      pPg->needSync = !pPager->journalStarted && !pPager->noSync; +      TRACE4("APPEND %d page %d needSync=%d\n", +              pPager->fd.h, 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 && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ +    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); +    if( pPager->memDb ){ +      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); +      assert( pHist->pStmt==0 ); +      pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); +      if( pHist->pStmt ){ +        memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); +      } +      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno); +    }else{ +      store32bits(pPg->pgno, pPg, -4); +      CODEC(pPager, pData, pPg->pgno, 7); +      rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, pPager->pageSize+4); +      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno); +      CODEC(pPager, pData, pPg->pgno, 0); +      if( rc!=SQLITE_OK ){ +        sqlite3pager_rollback(pPager); +        pPager->errMask |= PAGER_ERR_FULL; +        return rc; +      } +      pPager->stmtNRec++; +      assert( pPager->aInStmt!=0 ); +      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); +    } +    page_add_to_stmt_list(pPg); +  } + +  /* Update the database size and return. +  */ +  if( pPager->dbSize<(int)pPg->pgno ){ +    pPager->dbSize = pPg->pgno; +    if( !pPager->memDb && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ +      pPager->dbSize++; +    } +  } +  return rc; +} + +/* +** Return TRUE if the page given in the argument was previously passed +** to sqlite3pager_write().  In other words, return TRUE if it is ok +** to change the content of the page. +*/ +int sqlite3pager_iswriteable(void *pData){ +  PgHdr *pPg = DATA_TO_PGHDR(pData); +  return pPg->dirty; +} + +/* +** Replace the content of a single page with the information in the third +** argument. +*/ +int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){ +  void *pPage; +  int rc; + +  rc = sqlite3pager_get(pPager, pgno, &pPage); +  if( rc==SQLITE_OK ){ +    rc = sqlite3pager_write(pPage); +    if( rc==SQLITE_OK ){ +      memcpy(pPage, pData, pPager->pageSize); +    } +    sqlite3pager_unref(pPage); +  } +  return rc; +} + +/* +** A call to this routine tells the pager that it is not necessary to +** write the information on page "pgno" 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 +** sqlite3pager_dont_rollback() 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 sqlite3pager_dont_rollback() 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 dont_rollback() routine is called.  But because the page contains +** critical data, we still need to be sure it gets rolled back in spite +** of the dont_rollback() call. +*/ +void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ +  PgHdr *pPg; + +  if( pPager->memDb ) return; + +  pPg = pager_lookup(pPager, pgno); +  pPg->alwaysRollback = 1; +  if( pPg && pPg->dirty ){ +    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){ +      /* 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{ +      TRACE3("DONT_WRITE page %d of %d\n", pgno, pPager->fd.h); +      pPg->dirty = 0; +    } +  } +} + +/* +** 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. +*/ +void sqlite3pager_dont_rollback(void *pData){ +  PgHdr *pPg = DATA_TO_PGHDR(pData); +  Pager *pPager = pPg->pPager; + +  if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return; +  if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return; +  if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ +    assert( pPager->aInJournal!=0 ); +    pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); +    pPg->inJournal = 1; +    if( pPager->stmtInUse ){ +      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); +      page_add_to_stmt_list(pPg); +    } +    TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, pPager->fd.h); +  } +  if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ +    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); +    assert( pPager->aInStmt!=0 ); +    pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); +    page_add_to_stmt_list(pPg); +  } +} + + +/* +** Clear a PgHistory block +*/ +static void clearHistory(PgHistory *pHist){ +  sqliteFree(pHist->pOrig); +  sqliteFree(pHist->pStmt); +  pHist->pOrig = 0; +  pHist->pStmt = 0; +} + +/* +** 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 sqlite3pager_commit(Pager *pPager){ +  int rc; +  PgHdr *pPg; + +  if( pPager->errMask==PAGER_ERR_FULL ){ +    rc = sqlite3pager_rollback(pPager); +    if( rc==SQLITE_OK ){ +      rc = SQLITE_FULL; +    } +    return rc; +  } +  if( pPager->errMask!=0 ){ +    rc = pager_errcode(pPager); +    return rc; +  } +  if( pPager->state<PAGER_RESERVED ){ +    return SQLITE_ERROR; +  } +  TRACE2("COMMIT %d\n", pPager->fd.h); +  if( pPager->memDb ){ +    pPg = pager_get_all_dirty_pages(pPager); +    while( pPg ){ +      clearHistory(PGHDR_TO_HIST(pPg, pPager)); +      pPg->dirty = 0; +      pPg->inJournal = 0; +      pPg->inStmt = 0; +      pPg->pPrevStmt = pPg->pNextStmt = 0; +      pPg = pPg->pDirty; +    } +#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; +    return SQLITE_OK; +  } +  if( pPager->dirtyCache==0 ){ +    /* Exit early (without doing the time-consuming sqlite3OsSync() calls) +    ** if there have been no changes to the database file. */ +    assert( pPager->needSync==0 ); +    rc = pager_unwritelock(pPager); +    pPager->dbSize = -1; +    return rc; +  } +  assert( pPager->journalOpen ); +  rc = sqlite3pager_sync(pPager, 0); +  if( rc!=SQLITE_OK ){ +    goto commit_abort; +  } +  rc = pager_unwritelock(pPager); +  pPager->dbSize = -1; +  return rc; + +  /* Jump here if anything goes wrong during the commit process. +  */ +commit_abort: +  sqlite3pager_rollback(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 (SQLITE_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 sqlite3pager_rollback(Pager *pPager){ +  int rc; +  TRACE2("ROLLBACK %d\n", pPager->fd.h); +  if( pPager->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); +        TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, pPager->fd.h); +      }else{ +        TRACE3("PAGE %d is clean on %d\n", p->pgno, pPager->fd.h); +      } +      clearHistory(pHist); +      p->dirty = 0; +      p->inJournal = 0; +      p->inStmt = 0; +      p->pPrevStmt = p->pNextStmt = 0; + +      if( pPager->xReiniter ){ +        pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize); +      } +       +    } +    pPager->pStmt = 0; +    pPager->dbSize = pPager->origDbSize; +    memoryTruncate(pPager); +    pPager->stmtInUse = 0; +    pPager->state = PAGER_SHARED; +    return SQLITE_OK; +  } + +  if( !pPager->dirtyCache || !pPager->journalOpen ){ +    rc = pager_unwritelock(pPager); +    pPager->dbSize = -1; +    return rc; +  } + +  if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ +    if( pPager->state>=PAGER_EXCLUSIVE ){ +      pager_playback(pPager); +    } +    return pager_errcode(pPager); +  } +  if( pPager->state==PAGER_RESERVED ){ +    int rc2, rc3; +    rc = pager_reload_cache(pPager); +    rc2 = pager_truncate(pPager, pPager->origDbSize); +    rc3 = pager_unwritelock(pPager); +    if( rc==SQLITE_OK ){ +      rc = rc2; +      if( rc3 ) rc = rc3; +    } +  }else{ +    rc = pager_playback(pPager); +  } +  if( rc!=SQLITE_OK ){ +    rc = SQLITE_CORRUPT;  /* bkpt-CORRUPT */ +    pPager->errMask |= PAGER_ERR_CORRUPT; +  } +  pPager->dbSize = -1; +  return rc; +} + +/* +** Return TRUE if the database file is opened read-only.  Return FALSE +** if the database is (in theory) writable. +*/ +int sqlite3pager_isreadonly(Pager *pPager){ +  return pPager->readOnly; +} + +/* +** This routine is used for testing and analysis only. +*/ +int *sqlite3pager_stats(Pager *pPager){ +  static int a[9]; +  a[0] = pPager->nRef; +  a[1] = pPager->nPage; +  a[2] = pPager->mxPage; +  a[3] = pPager->dbSize; +  a[4] = pPager->state; +  a[5] = pPager->errMask; +  a[6] = pPager->nHit; +  a[7] = pPager->nMiss; +  a[8] = pPager->nOvfl; +  return a; +} + +/* +** 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. +*/ +int sqlite3pager_stmt_begin(Pager *pPager){ +  int rc; +  char zTemp[SQLITE_TEMPNAME_SIZE]; +  assert( !pPager->stmtInUse ); +  assert( pPager->dbSize>=0 ); +  TRACE2("STMT-BEGIN %d\n", pPager->fd.h); +  if( pPager->memDb ){ +    pPager->stmtInUse = 1; +    pPager->stmtSize = pPager->dbSize; +    return SQLITE_OK; +  } +  if( !pPager->journalOpen ){ +    pPager->stmtAutoopen = 1; +    return SQLITE_OK; +  } +  assert( pPager->journalOpen ); +  pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); +  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 = sqlite3pager_opentemp(zTemp, &pPager->stfd); +    if( rc ) goto stmt_begin_failed; +    pPager->stmtOpen = 1; +    pPager->stmtNRec = 0; +  } +  pPager->stmtInUse = 1; +  return SQLITE_OK; +  +stmt_begin_failed: +  if( pPager->aInStmt ){ +    sqliteFree(pPager->aInStmt); +    pPager->aInStmt = 0; +  } +  return rc; +} + +/* +** Commit a statement. +*/ +int sqlite3pager_stmt_commit(Pager *pPager){ +  if( pPager->stmtInUse ){ +    PgHdr *pPg, *pNext; +    TRACE2("STMT-COMMIT %d\n", pPager->fd.h); +    if( !pPager->memDb ){ +      sqlite3OsSeek(&pPager->stfd, 0); +      /* sqlite3OsTruncate(&pPager->stfd, 0); */ +      sqliteFree( pPager->aInStmt ); +      pPager->aInStmt = 0; +    } +    for(pPg=pPager->pStmt; pPg; pPg=pNext){ +      pNext = pPg->pNextStmt; +      assert( pPg->inStmt ); +      pPg->inStmt = 0; +      pPg->pPrevStmt = pPg->pNextStmt = 0; +      if( pPager->memDb ){ +        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); +        sqliteFree(pHist->pStmt); +        pHist->pStmt = 0; +      } +    } +    pPager->stmtNRec = 0; +    pPager->stmtInUse = 0; +    pPager->pStmt = 0; +  } +  pPager->stmtAutoopen = 0; +  return SQLITE_OK; +} + +/* +** Rollback a statement. +*/ +int sqlite3pager_stmt_rollback(Pager *pPager){ +  int rc; +  if( pPager->stmtInUse ){ +    TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h); +    if( pPager->memDb ){ +      PgHdr *pPg; +      for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){ +        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); +        if( pHist->pStmt ){ +          memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize); +          sqliteFree(pHist->pStmt); +          pHist->pStmt = 0; +        } +      } +      pPager->dbSize = pPager->stmtSize; +      memoryTruncate(pPager); +      rc = SQLITE_OK; +    }else{ +      rc = pager_stmt_playback(pPager); +    } +    sqlite3pager_stmt_commit(pPager); +  }else{ +    rc = SQLITE_OK; +  } +  pPager->stmtAutoopen = 0; +  return rc; +} + +/* +** Return the full pathname of the database file. +*/ +const char *sqlite3pager_filename(Pager *pPager){ +  return pPager->zFilename; +} + +/* +** Return the directory of the database file. +*/ +const char *sqlite3pager_dirname(Pager *pPager){ +  return pPager->zDirectory; +} + +/* +** Return the full pathname of the journal file. +*/ +const char *sqlite3pager_journalname(Pager *pPager){ +  return pPager->zJournal; +} + +/* +** Set the codec for this pager +*/ +void sqlite3pager_set_codec( +  Pager *pPager, +  void (*xCodec)(void*,void*,Pgno,int), +  void *pCodecArg +){ +  pPager->xCodec = xCodec; +  pPager->pCodecArg = pCodecArg; +} + +/* +** 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){ +  void *pPage; +  PgHdr *pPgHdr; +  u32 change_counter; +  int rc; + +  /* Open page 1 of the file for writing. */ +  rc = sqlite3pager_get(pPager, 1, &pPage); +  if( rc!=SQLITE_OK ) return rc; +  rc = sqlite3pager_write(pPage); +  if( rc!=SQLITE_OK ) return rc; + +  /* Read the current value at byte 24. */ +  pPgHdr = DATA_TO_PGHDR(pPage); +  change_counter = retrieve32bits(pPgHdr, 24); + +  /* Increment the value just read and write it back to byte 24. */ +  change_counter++; +  store32bits(change_counter, pPgHdr, 24); + +  /* Release the page reference. */ +  sqlite3pager_unref(pPage); +  return SQLITE_OK; +} + +/* +** 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 sqlite3pager_sync() call. +*/ +int sqlite3pager_sync(Pager *pPager, const char *zMaster){ +  int rc = SQLITE_OK; + +  /* 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 && !pPager->memDb && pPager->dirtyCache ){ +    PgHdr *pPg; +    assert( pPager->journalOpen ); + +    /* 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 ){ +      rc = pager_incr_changecounter(pPager); +      if( rc!=SQLITE_OK ) goto sync_exit; +      rc = writeMasterJournal(pPager, zMaster); +      if( rc!=SQLITE_OK ) goto sync_exit; +      rc = syncJournal(pPager); +      if( rc!=SQLITE_OK ) goto sync_exit; +    } + +    /* Write all dirty pages to the database file */ +    pPg = pager_get_all_dirty_pages(pPager); +    rc = pager_write_pagelist(pPg); +    if( rc!=SQLITE_OK ) goto sync_exit; + +    /* Sync the database file. */ +    if( !pPager->noSync ){ +      rc = sqlite3OsSync(&pPager->fd); +    } + +    pPager->state = PAGER_SYNCED; +  } + +sync_exit: +  return rc; +} + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +/* +** Return the current state of the file lock for the given pager. +** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK, +** PENDING_LOCK, or EXCLUSIVE_LOCK. +*/ +int sqlite3pager_lockstate(Pager *pPager){ +#ifdef OS_TEST +  return pPager->fd->fd.locktype; +#else +  return pPager->fd.locktype; +#endif +} +#endif + +#ifdef SQLITE_TEST +/* +** Print a listing of all referenced pages and their ref count. +*/ +void sqlite3pager_refdump(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 diff --git a/ext/pdo_sqlite/sqlite/src/pager.h b/ext/pdo_sqlite/sqlite/src/pager.h new file mode 100644 index 0000000000..0231e27a93 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/pager.h @@ -0,0 +1,102 @@ +/* +** 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$ +*/ + +/* +** 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 65536 (a limit +** imposed by the 2-byte size of cell array pointers.)  The +** maximum page size determines the amount of stack space allocated +** by many of the routines in pager.c and btree.c  On embedded architectures +** or any machine where memory and especially stack memory is limited, +** one may wish to chose a smaller value for the maximum page size. +*/ +#ifndef SQLITE_MAX_PAGE_SIZE +# define SQLITE_MAX_PAGE_SIZE 8192 +#endif + +/* +** Maximum number of pages in one database. +*/ +#define SQLITE_MAX_PAGE 1073741823 + +/* +** 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; + + +/* +** See source code comments for a detailed description of the following +** routines: +*/ +int sqlite3pager_open(Pager **ppPager, const char *zFilename, +                     int nExtra, int useJournal); +void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler); +void sqlite3pager_set_destructor(Pager*, void(*)(void*,int)); +void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int)); +void sqlite3pager_set_pagesize(Pager*, int); +void sqlite3pager_read_fileheader(Pager*, int, unsigned char*); +void sqlite3pager_set_cachesize(Pager*, int); +int sqlite3pager_close(Pager *pPager); +int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage); +void *sqlite3pager_lookup(Pager *pPager, Pgno pgno); +int sqlite3pager_ref(void*); +int sqlite3pager_unref(void*); +Pgno sqlite3pager_pagenumber(void*); +int sqlite3pager_write(void*); +int sqlite3pager_iswriteable(void*); +int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*); +int sqlite3pager_pagecount(Pager*); +int sqlite3pager_truncate(Pager*,Pgno); +int sqlite3pager_begin(void*, int exFlag); +int sqlite3pager_commit(Pager*); +int sqlite3pager_sync(Pager*,const char *zMaster); +int sqlite3pager_rollback(Pager*); +int sqlite3pager_isreadonly(Pager*); +int sqlite3pager_stmt_begin(Pager*); +int sqlite3pager_stmt_commit(Pager*); +int sqlite3pager_stmt_rollback(Pager*); +void sqlite3pager_dont_rollback(void*); +void sqlite3pager_dont_write(Pager*, Pgno); +int *sqlite3pager_stats(Pager*); +void sqlite3pager_set_safety_level(Pager*,int); +const char *sqlite3pager_filename(Pager*); +const char *sqlite3pager_dirname(Pager*); +const char *sqlite3pager_journalname(Pager*); +int sqlite3pager_rename(Pager*, const char *zNewName); +void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +int sqlite3pager_lockstate(Pager*); +#endif + +#ifdef SQLITE_TEST +void sqlite3pager_refdump(Pager*); +int pager3_refinfo_enable; +#endif diff --git a/ext/pdo_sqlite/sqlite/src/parse.c b/ext/pdo_sqlite/sqlite/src/parse.c new file mode 100644 index 0000000000..35cb266f64 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/parse.c @@ -0,0 +1,3143 @@ +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. +*/ +/* First off, code is include which follows the "include" declaration +** in the input file. */ +#include <stdio.h> +#line 33 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" + +#include "sqliteInt.h" +#include "parse.h" + +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { +  int limit;    /* The LIMIT value.  -1 if there is no limit */ +  int offset;   /* The OFFSET.  0 if there is none */ +}; + +/* +** An instance of this structure is used to store the LIKE, +** GLOB, NOT LIKE, and NOT GLOB operators. +*/ +struct LikeOp { +  int opcode;   /* Either TK_GLOB or TK_LIKE */ +  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; }; + +#line 48 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/*  +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands.  +** +** Each symbol here is a terminal symbol in the grammar. +*/ +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control +** various aspects of the generated parser. +**    YYCODETYPE         is the data type used for storing terminal +**                       and nonterminal numbers.  "unsigned char" is +**                       used if there are fewer than 250 terminals +**                       and nonterminals.  "int" is used otherwise. +**    YYNOCODE           is a number of type YYCODETYPE which corresponds +**                       to no legal terminal or nonterminal number.  This +**                       number is used to fill in empty slots of the hash  +**                       table. +**    YYFALLBACK         If defined, this indicates that one or more tokens +**                       have fall-back values which should be used if the +**                       original value of the token will not parse. +**    YYACTIONTYPE       is the data type used for storing terminal +**                       and nonterminal numbers.  "unsigned char" is +**                       used if there are fewer than 250 rules and +**                       states combined.  "int" is used otherwise. +**    sqlite3ParserTOKENTYPE     is the data type used for minor tokens given  +**                       directly to the parser from the tokenizer. +**    YYMINORTYPE        is the data type used for all minor tokens. +**                       This is typically a union of many types, one of +**                       which is sqlite3ParserTOKENTYPE.  The entry in the union +**                       for base tokens is called "yy0". +**    YYSTACKDEPTH       is the maximum depth of the parser's stack. +**    sqlite3ParserARG_SDECL     A static variable declaration for the %extra_argument +**    sqlite3ParserARG_PDECL     A parameter declaration for the %extra_argument +**    sqlite3ParserARG_STORE     Code to store %extra_argument into yypParser +**    sqlite3ParserARG_FETCH     Code to extract %extra_argument from yypParser +**    YYNSTATE           the combined number of states. +**    YYNRULE            the number of rules in the grammar +**    YYERRORSYMBOL      is the code number of the error symbol.  If not +**                       defined, then do no error processing. +*/ +#define YYCODETYPE unsigned char +#define YYNOCODE 225 +#define YYACTIONTYPE unsigned short int +#define sqlite3ParserTOKENTYPE Token +typedef union { +  sqlite3ParserTOKENTYPE yy0; +  struct {int value; int mask;} yy47; +  TriggerStep* yy91; +  Token yy98; +  Select* yy107; +  struct TrigEvent yy146; +  ExprList* yy210; +  Expr* yy258; +  SrcList* yy259; +  IdList* yy272; +  int yy284; +  struct AttachKey yy292; +  struct LikeOp yy342; +  struct LimitVal yy404; +  int yy449; +} YYMINORTYPE; +#define YYSTACKDEPTH 100 +#define sqlite3ParserARG_SDECL Parse *pParse; +#define sqlite3ParserARG_PDECL ,Parse *pParse +#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse +#define sqlite3ParserARG_STORE yypParser->pParse = pParse +#define YYNSTATE 537 +#define YYNRULE 292 +#define YYERRORSYMBOL 130 +#define YYERRSYMDT yy449 +#define YYFALLBACK 1 +#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE) + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token.  These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer.   +** +** Suppose the action integer is N.  Then the action is determined as +** follows +** +**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead +**                                      token onto the stack and goto state N. +** +**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE. +** +**   N == YYNSTATE+YYNRULE              A syntax error has occurred. +** +**   N == YYNSTATE+YYNRULE+1            The parser accepts its input. +** +**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused +**                                      slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as +** +**      yy_action[ yy_shift_ofst[S] + X ] +** +** If the index value yy_shift_ofst[S]+X is out of range or if the value +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table +** and that yy_default[S] should be used instead.   +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol.  If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +**  yy_action[]        A single table containing all actions. +**  yy_lookahead[]     A table containing the lookahead for each entry in +**                     yy_action.  Used to detect hash collisions. +**  yy_shift_ofst[]    For each state, the offset into yy_action for +**                     shifting terminals. +**  yy_reduce_ofst[]   For each state, the offset into yy_action for +**                     shifting non-terminals after a reduce. +**  yy_default[]       Default action for each state. +*/ +static const YYACTIONTYPE yy_action[] = { + /*     0 */   257,  325,  255,  138,  140,  142,  144,  146,  148,  150, + /*    10 */   152,  154,  156,   89,   87,   88,  159,   12,    4,    6, + /*    20 */   158,  537,   38,   24,  830,    1,  536,    3,  329,  488, + /*    30 */   534,  535,  319,   50,  124,  112,  160,  169,  174,  179, + /*    40 */   168,  173,  134,  136,  128,  130,  126,  132,  138,  140, + /*    50 */   142,  144,  146,  148,  150,  152,  154,  156,   26,   73, + /*    60 */   384,  256,   39,   58,   64,   66,  299,  330,  612,  611, + /*    70 */   351,   30,   92,  332,  326,  159,   13,   14,  353,  158, + /*    80 */     5,  355,  361,  366,  499,  146,  148,  150,  152,  154, + /*    90 */   156,   12,  369,  124,  112,  160,  169,  174,  179,  168, + /*   100 */   173,  134,  136,  128,  130,  126,  132,  138,  140,  142, + /*   110 */   144,  146,  148,  150,  152,  154,  156,  128,  130,  126, + /*   120 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154, + /*   130 */   156,  659,  353,  244,   62,  355,  361,  366,   79,   12, + /*   140 */    63,   98,   96,  289,  159,  280,  369,  349,  158,  181, + /*   150 */    13,   14,   27,   12,  546,  383,   32,   10,  368,  273, + /*   160 */   515,  765,  124,  112,  160,  169,  174,  179,  168,  173, + /*   170 */   134,  136,  128,  130,  126,  132,  138,  140,  142,  144, + /*   180 */   146,  148,  150,  152,  154,  156,  810,  349,   47,   73, + /*   190 */   222,  763,  223,  114,  246,   31,   32,   48,   13,   14, + /*   200 */    74,  274,  252,  166,  175,  180,  275,  304,   49,    8, + /*   210 */   255,   45,   13,   14,  159,  290,  350,  382,  158,  245, + /*   220 */   441,   46,  378,  183,  247,  185,  186,   15,   16,   17, + /*   230 */    73,  205,  124,  112,  160,  169,  174,  179,  168,  173, + /*   240 */   134,  136,  128,  130,  126,  132,  138,  140,  142,  144, + /*   250 */   146,  148,  150,  152,  154,  156,  542,  306,  438,  159, + /*   260 */    98,   96,  332,  158,  272,  475,  447,  437,   12,  256, + /*   270 */   288,   12,  304,  339,  287,   50,   77,  124,  112,  160, + /*   280 */   169,  174,  179,  168,  173,  134,  136,  128,  130,  126, + /*   290 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154, + /*   300 */   156,  547,   36,  335,   39,   58,   64,   66,  299,  330, + /*   310 */    35,  334,  291,  545,  114,  332,  114,  329,   12,  625, + /*   320 */   353,  187,  306,  355,  361,  366,  422,   13,   14,  159, + /*   330 */    13,   14,  184,  158,  369,  636,  188,  259,  188,  764, + /*   340 */    91,   87,   88,  100,   87,   88,  219,  124,  112,  160, + /*   350 */   169,  174,  179,  168,  173,  134,  136,  128,  130,  126, + /*   360 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154, + /*   370 */   156,  297,  282,  114,  292,   51,  237,   13,   14,  150, + /*   380 */   152,  154,  156,  114,   12,  225,   53,  225,  159,  166, + /*   390 */   175,  180,  158,  380,  303,  111,  433,  658,   69,   92, + /*   400 */   379,  183,   92,  185,  186,  111,  124,  112,  160,  169, + /*   410 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132, + /*   420 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156, + /*   430 */   103,  230,  561,  159,  773,   12,  286,  158,  631,  534, + /*   440 */   535,  105,  815,   13,   14,  166,  175,  180,  203,  808, + /*   450 */   215,  124,  112,  160,  169,  174,  179,  168,  173,  134, + /*   460 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146, + /*   470 */   148,  150,  152,  154,  156,    2,    3,  183,  159,  185, + /*   480 */   186,  813,  158,   43,   44,  569,   33,  633,   41,  348, + /*   490 */   340,  413,  415,  414,   13,   14,  124,  112,  160,  169, + /*   500 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132, + /*   510 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156, + /*   520 */   249,  336,  697,  159,  337,  338,  183,  158,  185,  186, + /*   530 */    56,   57,  183,   11,  185,  186,  183,  416,  185,  186, + /*   540 */   402,  124,  112,  160,  169,  174,  179,  168,  173,  134, + /*   550 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146, + /*   560 */   148,  150,  152,  154,  156,  342,   87,   88,  159,  345, + /*   570 */    87,   88,  158,   98,   96,  183,  404,  185,  186,  240, + /*   580 */     9,  183,   92,  185,  186,  802,  124,  177,  160,  169, + /*   590 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132, + /*   600 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156, + /*   610 */   787,  341,  257,  159,  255,  255,  183,  158,  185,  186, + /*   620 */    94,   95,  480,  518,   92,  307,  314,  316,   92,  548, + /*   630 */   325,  171,  112,  160,  169,  174,  179,  168,  173,  134, + /*   640 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146, + /*   650 */   148,  150,  152,  154,  156,  255,   25,  486,  159,  482, + /*   660 */   170,  358,  158,   19,  241,  242,  252,  266,  513,  267, + /*   670 */   259,  553,   72,  256,  256,  402,   68,  244,  160,  169, + /*   680 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132, + /*   690 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156, + /*   700 */   207,  255,   72,  326,  780,  260,   68,  267,  514,   47, + /*   710 */   189,  428,  388,  385,  256,  325,  259,   21,   48,  162, + /*   720 */   395,   12,  114,  161,  516,  517,  195,  193,  294,   49, + /*   730 */   207,  484,  209,  312,  191,   70,   71,  387,  246,  113, + /*   740 */   189,  164,  165,   73,  198,  114,  363,  396,  114,  391, + /*   750 */    73,  277,  529,  313,  436,  182,  195,  193,   72,  467, + /*   760 */   256,  623,   68,  245,  191,   70,   71,  188,  163,  113, + /*   770 */   188,  119,  120,  121,  122,  197,  114,  803,  691,   72, + /*   780 */    13,   14,   92,   68,   73,   73,  207,   77,  326,   73, + /*   790 */   199,  807,   99,  436,  452,  293,  189,  223,  474,  325, + /*   800 */   309,  119,  120,  121,  122,  197,  423,  207,  221,  460, + /*   810 */   434,  419,  195,  193,  418,   90,  224,  189,   77,  225, + /*   820 */   191,   70,   71,   73,  442,  113,  420,  114,  325,  444, + /*   830 */   372,  468,  114,  195,  193,  283,  325,  311,  310,  402, + /*   840 */   470,  191,   70,   71,  114,    7,  113,   41,  460,  474, + /*   850 */    18,   20,   22,  386,  296,  114,  457,  119,  120,  121, + /*   860 */   122,  197,  766,  446,  521,  554,  123,  430,  444,   23, + /*   870 */   531,  114,  326,  114,  114,  481,  114,  125,  119,  120, + /*   880 */   121,  122,  197,  510,   72,  441,  114,  238,   68,  114, + /*   890 */   508,  506,  114,  127,  114,  129,  131,  114,  133,  411, + /*   900 */   412,  322,  114,  114,  114,  114,  407,  114,  135,  326, + /*   910 */   660,  137,  207,  114,  139,  114,  141,  451,  114,  143, + /*   920 */   114,  114,  189,  114,  145,  147,  149,  151,  114,  153, + /*   930 */   489,  493,  437,  114,  114,  155,  479,  157,  195,  193, + /*   940 */   167,   77,  176,  178,  114,  190,  191,   70,   71,  114, + /*   950 */   192,  113,  114,  114,  114,  194,  196,  114,  691,  114, + /*   960 */   269,  320,  343,  321,  344,  269,  204,  114,  359,  284, + /*   970 */   321,  206,  114,  555,  216,  218,  220,  114,  364,  234, + /*   980 */   321,  239,  660,  119,  120,  121,  122,  197,  373,  271, + /*   990 */   321,  281,  114,  114,  367,  227,  227,  269,  431,  408, + /*  1000 */   321,  503,  439,   44,  465,  473,  267,  471,  114,   77, + /*  1010 */   402,  402,  402,  402,  455,  459,  265,  457,  402,  402, + /*  1020 */   823,  417,  504,  507,  556,  471,   28,   29,  560,   37, + /*  1030 */   472,   73,   34,   55,   40,   41,   42,   54,   59,   67, + /*  1040 */   570,  571,   52,   75,   60,   78,  483,  485,  487,  491, + /*  1050 */    61,   65,   76,  464,  495,  501,  101,  527,   77,  238, + /*  1060 */   233,  235,   85,   93,   86,   80,   97,  238,  102,   81, + /*  1070 */   104,   82,  108,  107,  109,  110,   83,  115,  497,   84, + /*  1080 */   117,  116,  156,  172,  637,  217,  638,  118,  202,  226, + /*  1090 */   639,  208,  106,  211,  227,  210,  213,  214,  212,  229, + /*  1100 */   228,  231,  236,  223,  200,  243,  201,  251,  248,  250, + /*  1110 */   254,  253,  232,  258,  261,  270,  264,  263,  262,  268, + /*  1120 */   276,  278,  285,  295,  318,  279,  300,  303,  301,  305, + /*  1130 */   333,  346,  298,  323,  327,  356,  357,  362,  370,  302, + /*  1140 */   371,   53,  374,  394,  399,  354,  331,  375,  401,  409, + /*  1150 */   308,  347,  315,  324,  406,  317,  405,  328,  795,  390, + /*  1160 */   389,  392,  397,  410,  421,  800,  360,  381,  365,  393, + /*  1170 */   398,  352,  376,  403,  801,  377,  400,  425,  426,  424, + /*  1180 */   427,  429,  771,  432,  772,  435,  440,  698,  443,  794, + /*  1190 */   445,  438,  809,  449,  699,  450,  453,  448,  454,  456, + /*  1200 */   811,  458,  461,  462,  463,  469,  812,  814,  476,  630, + /*  1210 */   478,  632,  779,  821,  490,  477,  690,  492,  494,  496, + /*  1220 */   498,  693,  500,  505,  696,  509,  781,  511,  782,  783, + /*  1230 */   466,  784,  785,  502,  512,  786,  520,  822,  519,  530, + /*  1240 */   524,  824,  523,  825,  525,  528,  533,  828,  518,  518, + /*  1250 */   518,  518,  518,  518,  522,  518,  526,  518,  518,  532, +}; +static const YYCODETYPE yy_lookahead[] = { + /*     0 */    24,  139,   26,   72,   73,   74,   75,   76,   77,   78, + /*    10 */    79,   80,   81,  154,  155,  156,   40,   26,  135,  136, + /*    20 */    44,    0,  158,  140,  131,  132,  133,  134,  164,  146, + /*    30 */     9,   10,  170,   60,   58,   59,   60,   61,   62,   63, + /*    40 */    64,   65,   66,   67,   68,   69,   70,   71,   72,   73, + /*    50 */    74,   75,   76,   77,   78,   79,   80,   81,   22,  176, + /*    60 */    24,   85,   89,   90,   91,   92,   93,   94,   23,   23, + /*    70 */    25,   25,  213,  100,  212,   40,   85,   86,   87,   44, + /*    80 */     9,   90,   91,   92,  201,   76,   77,   78,   79,   80, + /*    90 */    81,   26,  101,   58,   59,   60,   61,   62,   63,   64, + /*   100 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74, + /*   110 */    75,   76,   77,   78,   79,   80,   81,   68,   69,   70, + /*   120 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80, + /*   130 */    81,   23,   87,   25,   29,   90,   91,   92,  179,   26, + /*   140 */    35,   76,   77,   23,   40,  186,  101,  139,   44,   22, + /*   150 */    85,   86,  144,   26,    9,  147,  148,   12,  159,  146, + /*   160 */    95,  126,   58,   59,   60,   61,   62,   63,   64,   65, + /*   170 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75, + /*   180 */    76,   77,   78,   79,   80,   81,   17,  139,   18,  176, + /*   190 */    23,   17,   25,  139,   86,  147,  148,   27,   85,   86, + /*   200 */   146,  188,  189,  204,  205,  206,  193,   45,   38,  137, + /*   210 */    26,   41,   85,   86,   40,  161,  168,  169,   44,  111, + /*   220 */    51,   51,   60,  103,  111,  105,  106,   13,   14,   15, + /*   230 */   176,  127,   58,   59,   60,   61,   62,   63,   64,   65, + /*   240 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75, + /*   250 */    76,   77,   78,   79,   80,   81,    9,   95,   58,   40, + /*   260 */    76,   77,  100,   44,   22,   96,   97,   98,   26,   85, + /*   270 */   104,   26,   45,   89,  108,   60,  107,   58,   59,   60, + /*   280 */    61,   62,   63,   64,   65,   66,   67,   68,   69,   70, + /*   290 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80, + /*   300 */    81,    9,   87,   88,   89,   90,   91,   92,   93,   94, + /*   310 */   157,  158,   23,    9,  139,  100,  139,  164,   26,  119, + /*   320 */    87,   23,   95,   90,   91,   92,   21,   85,   86,   40, + /*   330 */    85,   86,  104,   44,  101,  107,  161,  152,  161,   17, + /*   340 */   154,  155,  156,  154,  155,  156,  127,   58,   59,   60, + /*   350 */    61,   62,   63,   64,   65,   66,   67,   68,   69,   70, + /*   360 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80, + /*   370 */    81,   23,  187,  139,  199,   89,  199,   85,   86,   78, + /*   380 */    79,   80,   81,  139,   26,  210,  100,  210,   40,  204, + /*   390 */   205,  206,   44,  164,  165,  161,   91,   23,   22,  213, + /*   400 */   171,  103,  213,  105,  106,  161,   58,   59,   60,   61, + /*   410 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71, + /*   420 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81, + /*   430 */   196,  197,    9,   40,  129,   26,   78,   44,    9,    9, + /*   440 */    10,  197,    9,   85,   86,  204,  205,  206,  126,   11, + /*   450 */   128,   58,   59,   60,   61,   62,   63,   64,   65,   66, + /*   460 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76, + /*   470 */    77,   78,   79,   80,   81,  133,  134,  103,   40,  105, + /*   480 */   106,    9,   44,  173,  174,  109,  149,    9,   95,  152, + /*   490 */   153,   96,   97,   98,   85,   86,   58,   59,   60,   61, + /*   500 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71, + /*   510 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81, + /*   520 */   111,  152,    9,   40,  155,  156,  103,   44,  105,  106, + /*   530 */    13,   14,  103,  139,  105,  106,  103,   47,  105,  106, + /*   540 */   139,   58,   59,   60,   61,   62,   63,   64,   65,   66, + /*   550 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76, + /*   560 */    77,   78,   79,   80,   81,  154,  155,  156,   40,  154, + /*   570 */   155,  156,   44,   76,   77,  103,  175,  105,  106,   25, + /*   580 */   138,  103,  213,  105,  106,   95,   58,   59,   60,   61, + /*   590 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71, + /*   600 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81, + /*   610 */     9,   22,   24,   40,   26,   26,  103,   44,  105,  106, + /*   620 */   121,  122,   20,   22,  213,   96,   97,   98,  213,    9, + /*   630 */   139,   60,   59,   60,   61,   62,   63,   64,   65,   66, + /*   640 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76, + /*   650 */    77,   78,   79,   80,   81,   26,  141,   55,   40,   57, + /*   660 */    89,  170,   44,  138,  110,  188,  189,   23,   67,   25, + /*   670 */   152,    9,   22,   85,   85,  139,   26,   25,   60,   61, + /*   680 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71, + /*   690 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81, + /*   700 */    50,   26,   22,  212,    9,  187,   26,   25,  139,   18, + /*   710 */    60,  175,   20,  146,   85,  139,  152,  138,   27,   40, + /*   720 */   146,   26,  139,   44,  155,  156,   76,   77,   78,   38, + /*   730 */    50,  129,   41,   32,   84,   85,   86,  142,   86,   89, + /*   740 */    60,   62,   63,  176,  161,  139,  170,   55,  139,   57, + /*   750 */   176,  187,  123,   52,  146,  146,   76,   77,   22,  146, + /*   760 */    85,    9,   26,  111,   84,   85,   86,  161,   89,   89, + /*   770 */   161,  121,  122,  123,  124,  125,  139,   95,    9,   22, + /*   780 */    85,   86,  213,   26,  176,  176,   50,  107,  212,  176, + /*   790 */   207,   11,   25,  146,   25,   23,   60,   25,  161,  139, + /*   800 */    99,  121,  122,  123,  124,  125,  211,   50,  199,  201, + /*   810 */   215,   28,   76,   77,   31,   48,  210,   60,  107,  210, + /*   820 */    84,   85,   86,  176,  216,   89,   43,  139,  139,  221, + /*   830 */   170,  120,  139,   76,   77,   78,  139,   88,   89,  139, + /*   840 */   203,   84,   85,   86,  139,   11,   89,   95,  201,  161, + /*   850 */    16,   17,   18,   19,  161,  139,  139,  121,  122,  123, + /*   860 */   124,  125,  126,  216,   30,    9,  161,  170,  221,  138, + /*   870 */    36,  139,  212,  139,  139,  175,  139,  161,  121,  122, + /*   880 */   123,  124,  125,   49,   22,   51,  139,  118,   26,  139, + /*   890 */    56,  203,  139,  161,  139,  161,  161,  139,  161,   53, + /*   900 */    54,  212,  139,  139,  139,  139,  126,  139,  161,  212, + /*   910 */    24,  161,   50,  139,  161,  139,  161,  200,  139,  161, + /*   920 */   139,  139,   60,  139,  161,  161,  161,  161,  139,  161, + /*   930 */    96,   97,   98,  139,  139,  161,  102,  161,   76,   77, + /*   940 */   161,  107,  161,  161,  139,  161,   84,   85,   86,  139, + /*   950 */   161,   89,  139,  139,  139,  161,  161,  139,    9,  139, + /*   960 */   139,   23,   23,   25,   25,  139,  161,  139,   23,  139, + /*   970 */    25,  161,  139,    9,  161,  161,  161,  139,   23,  161, + /*   980 */    25,  161,   95,  121,  122,  123,  124,  125,   23,  161, + /*   990 */    25,  161,  139,  139,  161,  109,  109,  139,   23,  161, + /*  1000 */    25,  146,  173,  174,   23,   23,   25,   25,  139,  107, + /*  1010 */   139,  139,  139,  139,  161,  161,  195,  139,  139,  139, + /*  1020 */     9,  195,  120,   23,    9,   25,  145,   23,    9,  139, + /*  1030 */   161,  176,  150,   42,  159,   95,   33,  167,   46,   22, + /*  1040 */   109,  109,  159,  177,  160,  178,  175,  175,  175,  175, + /*  1050 */   159,  159,  176,  195,  175,  175,  113,   46,  107,  118, + /*  1060 */   116,  115,  185,  214,  117,  180,  214,  118,  114,  181, + /*  1070 */    25,  182,   94,  160,   26,  151,  183,  109,  200,  184, + /*  1080 */   109,  139,   81,   89,  107,  126,  107,  139,   17,  139, + /*  1090 */   107,   22,  198,  174,  109,   23,  139,   23,   25,  143, + /*  1100 */   139,  198,  114,   25,  208,  190,  209,  111,  139,  139, + /*  1110 */   143,  139,  160,  139,  191,   95,   22,  112,  192,  139, + /*  1120 */    23,  191,  109,   23,   22,  192,  139,  165,  162,  139, + /*  1130 */   167,   23,  159,  198,  198,   46,   22,   22,   46,  163, + /*  1140 */    22,  100,   93,   24,  217,  139,  151,  139,   95,   39, + /*  1150 */   166,  152,  166,  160,  220,  166,  219,  160,   11,  143, + /*  1160 */   139,  139,  139,   37,   47,   95,  159,  169,  159,  143, + /*  1170 */   143,  169,  162,  143,   95,  163,  218,  139,  143,  129, + /*  1180 */    95,   22,    9,  159,  129,   11,  172,  119,   17,    9, + /*  1190 */     9,   58,   17,  139,  119,   99,  139,  172,   67,  181, + /*  1200 */     9,   67,  119,  139,   22,   22,    9,    9,  110,    9, + /*  1210 */   181,    9,    9,    9,  110,  139,    9,  181,  172,   99, + /*  1220 */   181,    9,  119,   22,    9,  139,    9,  139,    9,    9, + /*  1230 */   202,    9,    9,  202,  143,    9,   23,    9,  139,   34, + /*  1240 */    24,    9,  152,    9,  139,  152,  139,    9,  224,  224, + /*  1250 */   224,  224,  224,  224,  222,  224,  223,  224,  224,  222, +}; +#define YY_SHIFT_USE_DFLT (-70) +static const short yy_shift_ofst[] = { + /*     0 */   430,   21,  -70,  834,   71,  -70,  247,  214,  145,  304, + /*    10 */   292,  620,  -70,  -70,  -70,  -70,  -70,  -70,  145,  662, + /*    20 */   145,  856,  145,  964,   36, 1015,  245,   46, 1004, 1019, + /*    30 */    -9,  -70,  675,  -70,  215,  -70,  245,  -27,  -70,  940, + /*    40 */   -70, 1003,  170,  -70,  -70,  -70,  -70,  -70,  -70,  -70, + /*    50 */   286,  940,  -70,  991,  -70,  517,  -70,  -70,  992,  105, + /*    60 */   940,  -70,  -70,  -70,  940,  -70, 1017,  862,  376,  650, + /*    70 */   931,  932,  680,  -70,  120,  951,  -70,  166,  -70,  554, + /*    80 */   941,  946,  944,  943,  947,  -70,  497,  -70,  -70,  767, + /*    90 */   497,  -70,  499,  -70,  -70,  -70,  499,  -70,  -70,  497, + /*   100 */   -70,  954,  862, 1045,  862,  978,  105,  -70, 1048,  -70, + /*   110 */   -70,  483,  862,  -70,  968,  245,  971,  245,  -70,  -70, + /*   120 */   -70,  -70,  -70,  618,  862,  573,  862,  -69,  862,  -69, + /*   130 */   862,  -69,  862,  -69,  862,   49,  862,   49,  862,    9, + /*   140 */   862,    9,  862,    9,  862,    9,  862,  301,  862,  301, + /*   150 */   862, 1001,  862, 1001,  862, 1001,  862,  -70,  -70,  -70, + /*   160 */   679,  -70,  -70,  -70,  -70,  -70,  862,   49,  -70,  571, + /*   170 */   -70,  994,  -70,  -70,  -70,  862,  528,  862,   49,  -70, + /*   180 */   127,  680,  298,  228,  977,  979,  983,  -70,  483,  862, + /*   190 */   618,  862,  -70,  862,  -70,  862,  -70,  736,   35,  959, + /*   200 */   322, 1071,  -70,  862,  104,  862,  483, 1069,  691, 1072, + /*   210 */   -70, 1073,  245, 1074,  -70,  862,  174,  862,  219,  862, + /*   220 */   483,  167,  -70,  862,  -70,  -70,  985,  245,  -70,  -70, + /*   230 */   978,  105,  -70,  862,  483,  988,  862, 1078,  862,  483, + /*   240 */   -70,  -70,  652,  -70,  -70,  -70,  113,  -70,  409,  -70, + /*   250 */   996,  -70,  242,  985,  588,  -70,  -70,  245,  -70,  -70, + /*   260 */  1020, 1005,  -70, 1094,  245,  644,  -70,  245,  -70,  -70, + /*   270 */   862,  483,  951,  374,  108, 1097,  588, 1020, 1005,  -70, + /*   280 */   757,  -24,  -70,  -70, 1013,  358,  -70,  -70,  -70,  -70, + /*   290 */   289,  -70,  772,  -70, 1100,  -70,  348,  940,  -70,  245, + /*   300 */  1102,  -70,  227,  -70,  245,  -70,  529,  701,  -70,  749, + /*   310 */   -70,  -70,  -70,  -70,  701,  -70,  701,  -70,  245,  938, + /*   320 */   -70,  245,  978,  105,  -70,  -70,  978,  105,  -70,  -70, + /*   330 */  1048,  -70,  991,  -70,  -70,  184,  -70,  -70,  -70,  -70, + /*   340 */   589,  497,  939,  -70,  497, 1108,  -70,  -70,  -70,  -70, + /*   350 */    45,  233,  -70,  245,  -70, 1089, 1114,  245,  945,  940, + /*   360 */   -70, 1115,  245,  955,  940,  -70,  862,  393,  -70, 1092, + /*   370 */  1118,  245,  965, 1049,  245, 1102,  -70,  162, 1041,  -70, + /*   380 */   -70,  -70,  -70,  -70,  951,  423,  305,  692,  245,  985, + /*   390 */   -70,  245,  886, 1119,  951,  429,  245,  985,  783,  395, + /*   400 */  1053,  245,  985,  -70, 1110,  780, 1147,  862,  438, 1126, + /*   410 */   846,  -70,  -70, 1070, 1079,  490,  245,  682,  -70,  -70, + /*   420 */  1117,  -70,  -70, 1050,  245,  887, 1085,  245, 1159,  245, + /*   430 */   975,  752, 1173, 1055, 1174,  169,  433,  200,  170,  -70, + /*   440 */  1068, 1075, 1171, 1180, 1181,  169, 1175, 1133,  245, 1096, + /*   450 */   245,  769,  245, 1131,  862,  483, 1191, 1134,  862,  483, + /*   460 */  1083,  245, 1182,  245,  981,  -70,  711,  472, 1183,  862, + /*   470 */   982,  862,  483, 1197,  483, 1098,  245,  949, 1198,  602, + /*   480 */   245, 1200,  245, 1202,  245, 1203,  245, 1204,  478, 1104, + /*   490 */   245,  949, 1207, 1133,  245, 1120,  245,  769, 1212, 1103, + /*   500 */   245, 1182,  902,  513, 1201,  862, 1000, 1215,  695, 1217, + /*   510 */   245,  985,  601,   65, 1219, 1220, 1222, 1223,  245, 1213, + /*   520 */  1226, 1205,  675, 1216,  245, 1011, 1228,  629, 1232, 1234, + /*   530 */   -70, 1205,  245, 1238,  -70,  -70,  -70, +}; +#define YY_REDUCE_USE_DFLT (-142) +static const short yy_reduce_ofst[] = { + /*     0 */  -107,  342, -142, -117, -142, -142, -142,   72,  442, -142, + /*    10 */   394, -142, -142, -142, -142, -142, -142, -142,  525, -142, + /*    20 */   579, -142,  731, -142,  515, -142,    8,  881, -142, -142, + /*    30 */    48, -142,  337,  882,  153, -142,  890, -136, -142,  875, + /*    40 */  -142, -142,  310, -142, -142, -142, -142, -142, -142, -142, + /*    50 */  -142,  883, -142,  870, -142, -142, -142, -142, -142,  884, + /*    60 */   891, -142, -142, -142,  892, -142, -142,  693, -142,  175, + /*    70 */  -142, -142,   54, -142,  866,  876, -142,  867,  -41,  885, + /*    80 */   888,  889,  893,  895,  877, -142, -141, -142, -142, -142, + /*    90 */   186, -142,  849, -142, -142, -142,  852, -142, -142,  189, + /*   100 */  -142, -142,  234, -142,  244,  894,  913, -142,  924, -142, + /*   110 */  -142,  241,  705, -142, -142,  942, -142,  948, -142, -142, + /*   120 */  -142, -142, -142,  241,  716,  241,  732,  241,  734,  241, + /*   130 */   735,  241,  737,  241,  747,  241,  750,  241,  753,  241, + /*   140 */   755,  241,  758,  241,  763,  241,  764,  241,  765,  241, + /*   150 */   766,  241,  768,  241,  774,  241,  776,  241, -142, -142, + /*   160 */  -142, -142, -142, -142, -142, -142,  779,  241, -142, -142, + /*   170 */  -142, -142, -142, -142, -142,  781,  241,  782,  241, -142, + /*   180 */   950,  609,  866, -142, -142, -142, -142, -142,  241,  784, + /*   190 */   241,  789,  241,  794,  241,  795,  241,  583,  241,  896, + /*   200 */   897, -142, -142,  805,  241,  810,  241, -142,  919, -142, + /*   210 */  -142, -142,  957, -142, -142,  813,  241,  814,  241,  815, + /*   220 */   241, -142, -142,  606, -142, -142,  956,  961, -142, -142, + /*   230 */   903,  952, -142,  818,  241, -142,  177, -142,  820,  241, + /*   240 */  -142,  477,  915, -142, -142, -142,  969, -142,  970, -142, + /*   250 */  -142, -142,  972,  967,  518, -142, -142,  974, -142, -142, + /*   260 */   923,  926, -142, -142,  821, -142, -142,  980, -142, -142, + /*   270 */   828,  241,   13,  866,  915, -142,  564,  930,  933, -142, + /*   280 */   830,  185, -142, -142, -142,  942, -142, -142, -142, -142, + /*   290 */   241, -142, -142, -142, -142, -142,  241,  973, -142,  987, + /*   300 */   966,  976,  962, -142,  990, -142, -142,  984, -142, -142, + /*   310 */  -142, -142, -142, -142,  986, -142,  989, -142, -138, -142, + /*   320 */  -142,  689,  935,  993, -142, -142,  936,  997, -142, -142, + /*   330 */   995, -142,  963, -142, -142,  369, -142, -142, -142, -142, + /*   340 */   999,  411, -142, -142,  415, -142, -142, -142, -142, -142, + /*   350 */   998, 1002, -142, 1006, -142, -142, -142,  491, -142, 1007, + /*   360 */  -142, -142,  576, -142, 1009, -142,  833,   -1, -142, -142, + /*   370 */  -142,  660, -142, -142, 1008, 1010, 1012,  229, -142, -142, + /*   380 */  -142, -142, -142, -142,  567,  866,  595, -142, 1021, 1016, + /*   390 */  -142, 1022, 1026, -142,  574,  866, 1023, 1027,  927,  958, + /*   400 */  -142,  401, 1030, -142,  937,  934, -142,  838,  241, -142, + /*   410 */  -142, -142, -142, -142, -142, -142,  826, -142, -142, -142, + /*   420 */  -142, -142, -142, -142, 1038, 1035, -142,  536, -142,  697, + /*   430 */  -142, 1024, -142, -142, -142,  608,  866, 1014,  829, -142, + /*   440 */  -142, -142, -142, -142, -142,  647, -142, 1025, 1054, -142, + /*   450 */   717, 1018, 1057, -142,  853,  241, -142, -142,  854,  241, + /*   460 */  -142, 1064, 1028,  858, -142, -142,  613,  866, -142,  637, + /*   470 */  -142,  869,  241, -142,  241, -142, 1076, 1029, -142, -142, + /*   480 */   700, -142,  871, -142,  872, -142,  873, -142,  866, -142, + /*   490 */   874, 1036, -142, 1046,  879, -142,  878, 1039, -142, -142, + /*   500 */   880, 1031,  855,  866, -142,  688, -142, -142, 1086, -142, + /*   510 */  1088, 1091, -142,  569, -142, -142, -142, -142, 1099, -142, + /*   520 */  -142, 1032, 1090, -142, 1105, 1033, -142, 1093, -142, -142, + /*   530 */  -142, 1037, 1107, -142, -142, -142, -142, +}; +static const YYACTIONTYPE yy_default[] = { + /*     0 */   544,  544,  538,  829,  829,  540,  829,  549,  829,  829, + /*    10 */   829,  829,  569,  570,  571,  550,  551,  552,  829,  829, + /*    20 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  829, + /*    30 */   829,  562,  572,  581,  564,  580,  829,  829,  582,  623, + /*    40 */   588,  829,  829,  624,  627,  628,  629,  818,  819,  820, + /*    50 */   829,  623,  589,  608,  606,  829,  609,  610,  829,  679, + /*    60 */   623,  590,  677,  678,  623,  591,  829,  829,  708,  770, + /*    70 */   714,  709,  829,  634,  829,  829,  635,  643,  645,  652, + /*    80 */   691,  682,  684,  672,  686,  640,  793,  578,  579,  687, + /*    90 */   793,  688,  829,  788,  790,  791,  829,  789,  792,  793, + /*   100 */   689,  829,  829,  673,  829,  680,  679,  674,  829,  566, + /*   110 */   681,  676,  829,  707,  829,  829,  710,  829,  711,  712, + /*   120 */   713,  715,  716,  719,  829,  720,  829,  721,  829,  722, + /*   130 */   829,  723,  829,  724,  829,  725,  829,  726,  829,  727, + /*   140 */   829,  728,  829,  729,  829,  730,  829,  731,  829,  732, + /*   150 */   829,  733,  829,  734,  829,  735,  829,  736,  737,  738, + /*   160 */   829,  739,  740,  745,  753,  756,  829,  741,  742,  829, + /*   170 */   743,  829,  746,  744,  752,  829,  829,  829,  754,  755, + /*   180 */   829,  770,  829,  829,  829,  829,  829,  758,  769,  829, + /*   190 */   747,  829,  748,  829,  749,  829,  750,  829,  829,  829, + /*   200 */   829,  829,  760,  829,  829,  829,  761,  829,  829,  829, + /*   210 */   816,  829,  829,  829,  817,  829,  829,  829,  829,  829, + /*   220 */   762,  829,  757,  770,  767,  768,  660,  829,  661,  759, + /*   230 */   680,  679,  675,  829,  685,  829,  770,  683,  829,  692, + /*   240 */   644,  655,  653,  654,  663,  664,  829,  665,  829,  666, + /*   250 */   829,  667,  829,  660,  651,  567,  568,  829,  649,  650, + /*   260 */   669,  671,  656,  829,  829,  829,  670,  829,  704,  705, + /*   270 */   829,  668,  655,  829,  829,  829,  651,  669,  671,  657, + /*   280 */   829,  651,  646,  647,  829,  829,  648,  641,  642,  751, + /*   290 */   829,  706,  829,  717,  829,  718,  829,  623,  592,  829, + /*   300 */   774,  596,  593,  597,  829,  598,  829,  829,  599,  829, + /*   310 */   602,  603,  604,  605,  829,  600,  829,  601,  829,  829, + /*   320 */   775,  829,  680,  679,  776,  778,  680,  679,  777,  594, + /*   330 */   829,  595,  608,  607,  583,  793,  584,  585,  586,  587, + /*   340 */   573,  793,  829,  574,  793,  829,  575,  577,  576,  565, + /*   350 */   829,  829,  613,  829,  616,  829,  829,  829,  829,  623, + /*   360 */   617,  829,  829,  829,  623,  618,  829,  623,  619,  829, + /*   370 */   829,  829,  829,  829,  829,  774,  596,  621,  829,  620, + /*   380 */   622,  614,  615,  563,  829,  829,  559,  829,  829,  660, + /*   390 */   557,  829,  829,  829,  829,  829,  829,  660,  799,  829, + /*   400 */   829,  829,  660,  662,  804,  829,  829,  829,  829,  829, + /*   410 */   829,  805,  806,  829,  829,  829,  829,  829,  796,  797, + /*   420 */   829,  798,  558,  829,  829,  829,  829,  829,  829,  829, + /*   430 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  626, + /*   440 */   829,  829,  829,  829,  829,  829,  829,  625,  829,  829, + /*   450 */   829,  829,  829,  829,  829,  694,  829,  829,  829,  695, + /*   460 */   829,  829,  702,  829,  829,  703,  829,  829,  829,  829, + /*   470 */   829,  829,  700,  829,  701,  829,  829,  829,  829,  829, + /*   480 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  829, + /*   490 */   829,  829,  829,  625,  829,  829,  829,  829,  829,  829, + /*   500 */   829,  702,  829,  829,  829,  829,  829,  829,  829,  829, + /*   510 */   829,  660,  829,  793,  829,  829,  829,  829,  829,  829, + /*   520 */   829,  827,  829,  829,  829,  829,  829,  829,  829,  829, + /*   530 */   826,  827,  829,  829,  541,  543,  539, +}; +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) + +/* The next table maps tokens into fallback tokens.  If a construct +** like the following: +**  +**      %fallback ID X Y Z. +** +** appears in the grammer, then ID becomes a fallback token for X, Y, +** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +*/ +#ifdef YYFALLBACK +static const YYCODETYPE yyFallback[] = { +    0,  /*          $ => nothing */ +    0,  /* END_OF_FILE => nothing */ +    0,  /*    ILLEGAL => nothing */ +    0,  /*      SPACE => nothing */ +    0,  /* UNCLOSED_STRING => nothing */ +    0,  /*    COMMENT => nothing */ +    0,  /*   FUNCTION => nothing */ +    0,  /*     COLUMN => nothing */ +    0,  /* AGG_FUNCTION => nothing */ +    0,  /*       SEMI => nothing */ +   26,  /*    EXPLAIN => ID */ +   26,  /*      BEGIN => ID */ +    0,  /* TRANSACTION => nothing */ +   26,  /*   DEFERRED => ID */ +   26,  /*  IMMEDIATE => ID */ +   26,  /*  EXCLUSIVE => ID */ +    0,  /*     COMMIT => nothing */ +   26,  /*        END => ID */ +    0,  /*   ROLLBACK => nothing */ +    0,  /*     CREATE => nothing */ +    0,  /*      TABLE => nothing */ +   26,  /*       TEMP => ID */ +    0,  /*         LP => nothing */ +    0,  /*         RP => nothing */ +    0,  /*         AS => nothing */ +    0,  /*      COMMA => nothing */ +    0,  /*         ID => nothing */ +   26,  /*      ABORT => ID */ +   26,  /*      AFTER => ID */ +   26,  /*        ASC => ID */ +   26,  /*     ATTACH => ID */ +   26,  /*     BEFORE => ID */ +   26,  /*    CASCADE => ID */ +   26,  /*   CONFLICT => ID */ +   26,  /*   DATABASE => ID */ +   26,  /*       DESC => ID */ +   26,  /*     DETACH => ID */ +   26,  /*       EACH => ID */ +   26,  /*       FAIL => ID */ +   26,  /*        FOR => ID */ +   26,  /*       GLOB => ID */ +   26,  /*     IGNORE => ID */ +   26,  /*  INITIALLY => ID */ +   26,  /*    INSTEAD => ID */ +   26,  /*       LIKE => ID */ +   26,  /*      MATCH => ID */ +   26,  /*        KEY => ID */ +   26,  /*         OF => ID */ +   26,  /*     OFFSET => ID */ +   26,  /*     PRAGMA => ID */ +   26,  /*      RAISE => ID */ +   26,  /*    REPLACE => ID */ +   26,  /*   RESTRICT => ID */ +   26,  /*        ROW => ID */ +   26,  /*  STATEMENT => ID */ +   26,  /*    TRIGGER => ID */ +   26,  /*     VACUUM => ID */ +   26,  /*       VIEW => ID */ +    0,  /*         OR => nothing */ +    0,  /*        AND => nothing */ +    0,  /*        NOT => nothing */ +    0,  /*         IS => nothing */ +    0,  /*    BETWEEN => nothing */ +    0,  /*         IN => nothing */ +    0,  /*     ISNULL => nothing */ +    0,  /*    NOTNULL => nothing */ +    0,  /*         NE => nothing */ +    0,  /*         EQ => nothing */ +    0,  /*         GT => nothing */ +    0,  /*         LE => nothing */ +    0,  /*         LT => nothing */ +    0,  /*         GE => nothing */ +    0,  /*     BITAND => nothing */ +    0,  /*      BITOR => nothing */ +    0,  /*     LSHIFT => nothing */ +    0,  /*     RSHIFT => nothing */ +    0,  /*       PLUS => nothing */ +    0,  /*      MINUS => nothing */ +    0,  /*       STAR => nothing */ +    0,  /*      SLASH => nothing */ +    0,  /*        REM => nothing */ +    0,  /*     CONCAT => nothing */ +    0,  /*     UMINUS => nothing */ +    0,  /*      UPLUS => nothing */ +    0,  /*     BITNOT => nothing */ +    0,  /*     STRING => nothing */ +    0,  /*    JOIN_KW => nothing */ +    0,  /* CONSTRAINT => nothing */ +    0,  /*    DEFAULT => nothing */ +    0,  /*       NULL => nothing */ +    0,  /*    PRIMARY => nothing */ +    0,  /*     UNIQUE => nothing */ +    0,  /*      CHECK => nothing */ +    0,  /* REFERENCES => nothing */ +    0,  /*    COLLATE => nothing */ +    0,  /*         ON => nothing */ +    0,  /*     DELETE => nothing */ +    0,  /*     UPDATE => nothing */ +    0,  /*     INSERT => nothing */ +    0,  /*        SET => nothing */ +    0,  /* DEFERRABLE => nothing */ +    0,  /*    FOREIGN => nothing */ +    0,  /*       DROP => nothing */ +    0,  /*      UNION => nothing */ +    0,  /*        ALL => nothing */ +    0,  /*  INTERSECT => nothing */ +    0,  /*     EXCEPT => nothing */ +    0,  /*     SELECT => nothing */ +    0,  /*   DISTINCT => nothing */ +    0,  /*        DOT => nothing */ +    0,  /*       FROM => nothing */ +    0,  /*       JOIN => nothing */ +    0,  /*      USING => nothing */ +    0,  /*      ORDER => nothing */ +    0,  /*         BY => nothing */ +    0,  /*      GROUP => nothing */ +    0,  /*     HAVING => nothing */ +    0,  /*      LIMIT => nothing */ +    0,  /*      WHERE => nothing */ +    0,  /*       INTO => nothing */ +    0,  /*     VALUES => nothing */ +    0,  /*    INTEGER => nothing */ +    0,  /*      FLOAT => nothing */ +    0,  /*       BLOB => nothing */ +    0,  /*   VARIABLE => nothing */ +    0,  /*       CASE => nothing */ +    0,  /*       WHEN => nothing */ +    0,  /*       THEN => nothing */ +    0,  /*       ELSE => nothing */ +    0,  /*      INDEX => nothing */ +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack.  Information stored includes: +** +**   +  The state number for the parser at this level of the stack. +** +**   +  The value of the token stored at this level of the stack. +**      (In other words, the "major" token.) +** +**   +  The semantic value stored at this level of the stack.  This is +**      the information used by the action routines in the grammar. +**      It is sometimes called the "minor" token. +*/ +struct yyStackEntry { +  int stateno;       /* The state-number */ +  int major;         /* The major token value.  This is the code +                     ** number for the token at this stack level */ +  YYMINORTYPE minor; /* The user-supplied minor token value.  This +                     ** is the value of the token  */ +}; +typedef struct yyStackEntry yyStackEntry; + +/* The state of the parser is completely contained in an instance of +** the following structure */ +struct yyParser { +  int yyidx;                    /* Index of top element in stack */ +  int yyerrcnt;                 /* Shifts left before out of the error */ +  sqlite3ParserARG_SDECL                /* A place to hold %extra_argument */ +  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */ +}; +typedef struct yyParser yyParser; + +#ifndef NDEBUG +#include <stdio.h> +static FILE *yyTraceFILE = 0; +static char *yyTracePrompt = 0; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/*  +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message.  Tracing is turned off +** by making either argument NULL  +** +** Inputs: +** <ul> +** <li> A FILE* to which trace output should be written. +**      If NULL, then tracing is turned off. +** <li> A prefix string written at the beginning of every +**      line of trace output.  If NULL, then tracing is +**      turned off. +** </ul> +** +** Outputs: +** None. +*/ +void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ +  yyTraceFILE = TraceFILE; +  yyTracePrompt = zTracePrompt; +  if( yyTraceFILE==0 ) yyTracePrompt = 0; +  else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required.  The following table supplies these names */ +static const char *const yyTokenName[] = {  +  "$",             "END_OF_FILE",   "ILLEGAL",       "SPACE",        +  "UNCLOSED_STRING",  "COMMENT",       "FUNCTION",      "COLUMN",       +  "AGG_FUNCTION",  "SEMI",          "EXPLAIN",       "BEGIN",        +  "TRANSACTION",   "DEFERRED",      "IMMEDIATE",     "EXCLUSIVE",    +  "COMMIT",        "END",           "ROLLBACK",      "CREATE",       +  "TABLE",         "TEMP",          "LP",            "RP",           +  "AS",            "COMMA",         "ID",            "ABORT",        +  "AFTER",         "ASC",           "ATTACH",        "BEFORE",       +  "CASCADE",       "CONFLICT",      "DATABASE",      "DESC",         +  "DETACH",        "EACH",          "FAIL",          "FOR",          +  "GLOB",          "IGNORE",        "INITIALLY",     "INSTEAD",      +  "LIKE",          "MATCH",         "KEY",           "OF",           +  "OFFSET",        "PRAGMA",        "RAISE",         "REPLACE",      +  "RESTRICT",      "ROW",           "STATEMENT",     "TRIGGER",      +  "VACUUM",        "VIEW",          "OR",            "AND",          +  "NOT",           "IS",            "BETWEEN",       "IN",           +  "ISNULL",        "NOTNULL",       "NE",            "EQ",           +  "GT",            "LE",            "LT",            "GE",           +  "BITAND",        "BITOR",         "LSHIFT",        "RSHIFT",       +  "PLUS",          "MINUS",         "STAR",          "SLASH",        +  "REM",           "CONCAT",        "UMINUS",        "UPLUS",        +  "BITNOT",        "STRING",        "JOIN_KW",       "CONSTRAINT",   +  "DEFAULT",       "NULL",          "PRIMARY",       "UNIQUE",       +  "CHECK",         "REFERENCES",    "COLLATE",       "ON",           +  "DELETE",        "UPDATE",        "INSERT",        "SET",          +  "DEFERRABLE",    "FOREIGN",       "DROP",          "UNION",        +  "ALL",           "INTERSECT",     "EXCEPT",        "SELECT",       +  "DISTINCT",      "DOT",           "FROM",          "JOIN",         +  "USING",         "ORDER",         "BY",            "GROUP",        +  "HAVING",        "LIMIT",         "WHERE",         "INTO",         +  "VALUES",        "INTEGER",       "FLOAT",         "BLOB",         +  "VARIABLE",      "CASE",          "WHEN",          "THEN",         +  "ELSE",          "INDEX",         "error",         "input",        +  "cmdlist",       "ecmd",          "explain",       "cmdx",         +  "cmd",           "transtype",     "trans_opt",     "nm",           +  "create_table",  "create_table_args",  "temp",          "dbnm",         +  "columnlist",    "conslist_opt",  "select",        "column",       +  "columnid",      "type",          "carglist",      "id",           +  "ids",           "typename",      "signed",        "plus_num",     +  "minus_num",     "carg",          "ccons",         "onconf",       +  "sortorder",     "expr",          "idxlist_opt",   "refargs",      +  "defer_subclause",  "refarg",        "refact",        "init_deferred_pred_opt", +  "conslist",      "tcons",         "idxlist",       "defer_subclause_opt", +  "orconf",        "resolvetype",   "raisetype",     "fullname",     +  "oneselect",     "multiselect_op",  "distinct",      "selcollist",   +  "from",          "where_opt",     "groupby_opt",   "having_opt",   +  "orderby_opt",   "limit_opt",     "sclp",          "as",           +  "seltablist",    "stl_prefix",    "joinop",        "on_opt",       +  "using_opt",     "seltablist_paren",  "joinop2",       "inscollist",   +  "sortlist",      "sortitem",      "collate",       "exprlist",     +  "setlist",       "insert_cmd",    "inscollist_opt",  "itemlist",     +  "likeop",        "between_op",    "in_op",         "case_operand", +  "case_exprlist",  "case_else",     "expritem",      "uniqueflag",   +  "idxitem",       "plus_opt",      "number",        "trigger_decl", +  "trigger_cmd_list",  "trigger_time",  "trigger_event",  "foreach_clause", +  "when_clause",   "trigger_cmd",   "database_kw_opt",  "key_opt",      +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +static const char *const yyRuleName[] = { + /*   0 */ "input ::= cmdlist", + /*   1 */ "cmdlist ::= cmdlist ecmd", + /*   2 */ "cmdlist ::= ecmd", + /*   3 */ "ecmd ::= explain cmdx SEMI", + /*   4 */ "ecmd ::= SEMI", + /*   5 */ "cmdx ::= cmd", + /*   6 */ "explain ::= EXPLAIN", + /*   7 */ "explain ::=", + /*   8 */ "cmd ::= BEGIN transtype trans_opt", + /*   9 */ "trans_opt ::=", + /*  10 */ "trans_opt ::= TRANSACTION", + /*  11 */ "trans_opt ::= TRANSACTION nm", + /*  12 */ "transtype ::=", + /*  13 */ "transtype ::= DEFERRED", + /*  14 */ "transtype ::= IMMEDIATE", + /*  15 */ "transtype ::= EXCLUSIVE", + /*  16 */ "cmd ::= COMMIT trans_opt", + /*  17 */ "cmd ::= END trans_opt", + /*  18 */ "cmd ::= ROLLBACK trans_opt", + /*  19 */ "cmd ::= create_table create_table_args", + /*  20 */ "create_table ::= CREATE temp TABLE nm dbnm", + /*  21 */ "temp ::= TEMP", + /*  22 */ "temp ::=", + /*  23 */ "create_table_args ::= LP columnlist conslist_opt RP", + /*  24 */ "create_table_args ::= AS select", + /*  25 */ "columnlist ::= columnlist COMMA column", + /*  26 */ "columnlist ::= column", + /*  27 */ "column ::= columnid type carglist", + /*  28 */ "columnid ::= nm", + /*  29 */ "id ::= ID", + /*  30 */ "ids ::= ID", + /*  31 */ "ids ::= STRING", + /*  32 */ "nm ::= ID", + /*  33 */ "nm ::= STRING", + /*  34 */ "nm ::= JOIN_KW", + /*  35 */ "type ::=", + /*  36 */ "type ::= typename", + /*  37 */ "type ::= typename LP signed RP", + /*  38 */ "type ::= typename LP signed COMMA signed RP", + /*  39 */ "typename ::= ids", + /*  40 */ "typename ::= typename ids", + /*  41 */ "signed ::= plus_num", + /*  42 */ "signed ::= minus_num", + /*  43 */ "carglist ::= carglist carg", + /*  44 */ "carglist ::=", + /*  45 */ "carg ::= CONSTRAINT nm ccons", + /*  46 */ "carg ::= ccons", + /*  47 */ "carg ::= DEFAULT ids", + /*  48 */ "carg ::= DEFAULT plus_num", + /*  49 */ "carg ::= DEFAULT minus_num", + /*  50 */ "carg ::= DEFAULT NULL", + /*  51 */ "ccons ::= NULL onconf", + /*  52 */ "ccons ::= NOT NULL onconf", + /*  53 */ "ccons ::= PRIMARY KEY sortorder onconf", + /*  54 */ "ccons ::= UNIQUE onconf", + /*  55 */ "ccons ::= CHECK LP expr RP onconf", + /*  56 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /*  57 */ "ccons ::= defer_subclause", + /*  58 */ "ccons ::= COLLATE id", + /*  59 */ "refargs ::=", + /*  60 */ "refargs ::= refargs refarg", + /*  61 */ "refarg ::= MATCH nm", + /*  62 */ "refarg ::= ON DELETE refact", + /*  63 */ "refarg ::= ON UPDATE refact", + /*  64 */ "refarg ::= ON INSERT refact", + /*  65 */ "refact ::= SET NULL", + /*  66 */ "refact ::= SET DEFAULT", + /*  67 */ "refact ::= CASCADE", + /*  68 */ "refact ::= RESTRICT", + /*  69 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /*  70 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /*  71 */ "init_deferred_pred_opt ::=", + /*  72 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /*  73 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /*  74 */ "conslist_opt ::=", + /*  75 */ "conslist_opt ::= COMMA conslist", + /*  76 */ "conslist ::= conslist COMMA tcons", + /*  77 */ "conslist ::= conslist tcons", + /*  78 */ "conslist ::= tcons", + /*  79 */ "tcons ::= CONSTRAINT nm", + /*  80 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf", + /*  81 */ "tcons ::= UNIQUE LP idxlist RP onconf", + /*  82 */ "tcons ::= CHECK expr onconf", + /*  83 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", + /*  84 */ "defer_subclause_opt ::=", + /*  85 */ "defer_subclause_opt ::= defer_subclause", + /*  86 */ "onconf ::=", + /*  87 */ "onconf ::= ON CONFLICT resolvetype", + /*  88 */ "orconf ::=", + /*  89 */ "orconf ::= OR resolvetype", + /*  90 */ "resolvetype ::= raisetype", + /*  91 */ "resolvetype ::= IGNORE", + /*  92 */ "resolvetype ::= REPLACE", + /*  93 */ "cmd ::= DROP TABLE fullname", + /*  94 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", + /*  95 */ "cmd ::= DROP VIEW fullname", + /*  96 */ "cmd ::= select", + /*  97 */ "select ::= oneselect", + /*  98 */ "select ::= select multiselect_op oneselect", + /*  99 */ "multiselect_op ::= UNION", + /* 100 */ "multiselect_op ::= UNION ALL", + /* 101 */ "multiselect_op ::= INTERSECT", + /* 102 */ "multiselect_op ::= EXCEPT", + /* 103 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 104 */ "distinct ::= DISTINCT", + /* 105 */ "distinct ::= ALL", + /* 106 */ "distinct ::=", + /* 107 */ "sclp ::= selcollist COMMA", + /* 108 */ "sclp ::=", + /* 109 */ "selcollist ::= sclp expr as", + /* 110 */ "selcollist ::= sclp STAR", + /* 111 */ "selcollist ::= sclp nm DOT STAR", + /* 112 */ "as ::= AS nm", + /* 113 */ "as ::= ids", + /* 114 */ "as ::=", + /* 115 */ "from ::=", + /* 116 */ "from ::= FROM seltablist", + /* 117 */ "stl_prefix ::= seltablist joinop", + /* 118 */ "stl_prefix ::=", + /* 119 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", + /* 120 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", + /* 121 */ "seltablist_paren ::= select", + /* 122 */ "seltablist_paren ::= seltablist", + /* 123 */ "dbnm ::=", + /* 124 */ "dbnm ::= DOT nm", + /* 125 */ "fullname ::= nm dbnm", + /* 126 */ "joinop ::= COMMA", + /* 127 */ "joinop ::= JOIN", + /* 128 */ "joinop ::= JOIN_KW JOIN", + /* 129 */ "joinop ::= JOIN_KW nm JOIN", + /* 130 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 131 */ "on_opt ::= ON expr", + /* 132 */ "on_opt ::=", + /* 133 */ "using_opt ::= USING LP inscollist RP", + /* 134 */ "using_opt ::=", + /* 135 */ "orderby_opt ::=", + /* 136 */ "orderby_opt ::= ORDER BY sortlist", + /* 137 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", + /* 138 */ "sortlist ::= sortitem collate sortorder", + /* 139 */ "sortitem ::= expr", + /* 140 */ "sortorder ::= ASC", + /* 141 */ "sortorder ::= DESC", + /* 142 */ "sortorder ::=", + /* 143 */ "collate ::=", + /* 144 */ "collate ::= COLLATE id", + /* 145 */ "groupby_opt ::=", + /* 146 */ "groupby_opt ::= GROUP BY exprlist", + /* 147 */ "having_opt ::=", + /* 148 */ "having_opt ::= HAVING expr", + /* 149 */ "limit_opt ::=", + /* 150 */ "limit_opt ::= LIMIT signed", + /* 151 */ "limit_opt ::= LIMIT signed OFFSET signed", + /* 152 */ "limit_opt ::= LIMIT signed COMMA signed", + /* 153 */ "cmd ::= DELETE FROM fullname where_opt", + /* 154 */ "where_opt ::=", + /* 155 */ "where_opt ::= WHERE expr", + /* 156 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", + /* 157 */ "setlist ::= setlist COMMA nm EQ expr", + /* 158 */ "setlist ::= nm EQ expr", + /* 159 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", + /* 160 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", + /* 161 */ "insert_cmd ::= INSERT orconf", + /* 162 */ "insert_cmd ::= REPLACE", + /* 163 */ "itemlist ::= itemlist COMMA expr", + /* 164 */ "itemlist ::= expr", + /* 165 */ "inscollist_opt ::=", + /* 166 */ "inscollist_opt ::= LP inscollist RP", + /* 167 */ "inscollist ::= inscollist COMMA nm", + /* 168 */ "inscollist ::= nm", + /* 169 */ "expr ::= LP expr RP", + /* 170 */ "expr ::= NULL", + /* 171 */ "expr ::= ID", + /* 172 */ "expr ::= JOIN_KW", + /* 173 */ "expr ::= nm DOT nm", + /* 174 */ "expr ::= nm DOT nm DOT nm", + /* 175 */ "expr ::= INTEGER", + /* 176 */ "expr ::= FLOAT", + /* 177 */ "expr ::= STRING", + /* 178 */ "expr ::= BLOB", + /* 179 */ "expr ::= VARIABLE", + /* 180 */ "expr ::= ID LP exprlist RP", + /* 181 */ "expr ::= ID LP STAR RP", + /* 182 */ "expr ::= expr AND expr", + /* 183 */ "expr ::= expr OR expr", + /* 184 */ "expr ::= expr LT expr", + /* 185 */ "expr ::= expr GT expr", + /* 186 */ "expr ::= expr LE expr", + /* 187 */ "expr ::= expr GE expr", + /* 188 */ "expr ::= expr NE expr", + /* 189 */ "expr ::= expr EQ expr", + /* 190 */ "expr ::= expr BITAND expr", + /* 191 */ "expr ::= expr BITOR expr", + /* 192 */ "expr ::= expr LSHIFT expr", + /* 193 */ "expr ::= expr RSHIFT expr", + /* 194 */ "expr ::= expr PLUS expr", + /* 195 */ "expr ::= expr MINUS expr", + /* 196 */ "expr ::= expr STAR expr", + /* 197 */ "expr ::= expr SLASH expr", + /* 198 */ "expr ::= expr REM expr", + /* 199 */ "expr ::= expr CONCAT expr", + /* 200 */ "likeop ::= LIKE", + /* 201 */ "likeop ::= GLOB", + /* 202 */ "likeop ::= NOT LIKE", + /* 203 */ "likeop ::= NOT GLOB", + /* 204 */ "expr ::= expr likeop expr", + /* 205 */ "expr ::= expr ISNULL", + /* 206 */ "expr ::= expr IS NULL", + /* 207 */ "expr ::= expr NOTNULL", + /* 208 */ "expr ::= expr NOT NULL", + /* 209 */ "expr ::= expr IS NOT NULL", + /* 210 */ "expr ::= NOT expr", + /* 211 */ "expr ::= BITNOT expr", + /* 212 */ "expr ::= MINUS expr", + /* 213 */ "expr ::= PLUS expr", + /* 214 */ "expr ::= LP select RP", + /* 215 */ "between_op ::= BETWEEN", + /* 216 */ "between_op ::= NOT BETWEEN", + /* 217 */ "expr ::= expr between_op expr AND expr", + /* 218 */ "in_op ::= IN", + /* 219 */ "in_op ::= NOT IN", + /* 220 */ "expr ::= expr in_op LP exprlist RP", + /* 221 */ "expr ::= expr in_op LP select RP", + /* 222 */ "expr ::= expr in_op nm dbnm", + /* 223 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 224 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 225 */ "case_exprlist ::= WHEN expr THEN expr", + /* 226 */ "case_else ::= ELSE expr", + /* 227 */ "case_else ::=", + /* 228 */ "case_operand ::= expr", + /* 229 */ "case_operand ::=", + /* 230 */ "exprlist ::= exprlist COMMA expritem", + /* 231 */ "exprlist ::= expritem", + /* 232 */ "expritem ::= expr", + /* 233 */ "expritem ::=", + /* 234 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON fullname LP idxlist RP onconf", + /* 235 */ "uniqueflag ::= UNIQUE", + /* 236 */ "uniqueflag ::=", + /* 237 */ "idxlist_opt ::=", + /* 238 */ "idxlist_opt ::= LP idxlist RP", + /* 239 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", + /* 240 */ "idxlist ::= idxitem collate sortorder", + /* 241 */ "idxitem ::= nm", + /* 242 */ "cmd ::= DROP INDEX fullname", + /* 243 */ "cmd ::= VACUUM", + /* 244 */ "cmd ::= VACUUM nm", + /* 245 */ "cmd ::= PRAGMA nm dbnm EQ nm", + /* 246 */ "cmd ::= PRAGMA nm dbnm EQ ON", + /* 247 */ "cmd ::= PRAGMA nm dbnm EQ plus_num", + /* 248 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 249 */ "cmd ::= PRAGMA nm dbnm LP nm RP", + /* 250 */ "cmd ::= PRAGMA nm dbnm", + /* 251 */ "plus_num ::= plus_opt number", + /* 252 */ "minus_num ::= MINUS number", + /* 253 */ "number ::= INTEGER", + /* 254 */ "number ::= FLOAT", + /* 255 */ "plus_opt ::= PLUS", + /* 256 */ "plus_opt ::=", + /* 257 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", + /* 258 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 259 */ "trigger_time ::= BEFORE", + /* 260 */ "trigger_time ::= AFTER", + /* 261 */ "trigger_time ::= INSTEAD OF", + /* 262 */ "trigger_time ::=", + /* 263 */ "trigger_event ::= DELETE", + /* 264 */ "trigger_event ::= INSERT", + /* 265 */ "trigger_event ::= UPDATE", + /* 266 */ "trigger_event ::= UPDATE OF inscollist", + /* 267 */ "foreach_clause ::=", + /* 268 */ "foreach_clause ::= FOR EACH ROW", + /* 269 */ "foreach_clause ::= FOR EACH STATEMENT", + /* 270 */ "when_clause ::=", + /* 271 */ "when_clause ::= WHEN expr", + /* 272 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", + /* 273 */ "trigger_cmd_list ::=", + /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 278 */ "trigger_cmd ::= select", + /* 279 */ "expr ::= RAISE LP IGNORE RP", + /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 281 */ "raisetype ::= ROLLBACK", + /* 282 */ "raisetype ::= ABORT", + /* 283 */ "raisetype ::= FAIL", + /* 284 */ "cmd ::= DROP TRIGGER fullname", + /* 285 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt", + /* 286 */ "key_opt ::=", + /* 287 */ "key_opt ::= KEY ids", + /* 288 */ "key_opt ::= KEY BLOB", + /* 289 */ "database_kw_opt ::= DATABASE", + /* 290 */ "database_kw_opt ::=", + /* 291 */ "cmd ::= DETACH database_kw_opt nm", +}; +#endif /* NDEBUG */ + +/* +** This function returns the symbolic name associated with a token +** value. +*/ +const char *sqlite3ParserTokenName(int tokenType){ +#ifndef NDEBUG +  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ +    return yyTokenName[tokenType]; +  }else{ +    return "Unknown"; +  } +#else +  return ""; +#endif +} + +/*  +** This function allocates a new parser. +** The only argument is a pointer to a function which works like +** malloc. +** +** Inputs: +** A pointer to the function used to allocate memory. +** +** Outputs: +** A pointer to a parser.  This pointer is used in subsequent calls +** to sqlite3Parser and sqlite3ParserFree. +*/ +void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){ +  yyParser *pParser; +  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); +  if( pParser ){ +    pParser->yyidx = -1; +  } +  return pParser; +} + +/* The following function deletes the value associated with a +** symbol.  The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. +*/ +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ +  switch( yymajor ){ +    /* Here is inserted the actions which take place when a +    ** terminal or non-terminal is destroyed.  This can happen +    ** when the symbol is popped from the stack during a +    ** reduce or during error processing or when a parser is  +    ** being destroyed before it is finished parsing. +    ** +    ** Note: during a reduce, the only symbols destroyed are those +    ** which appear on the RHS of the rule, but which are not used +    ** inside the C code. +    */ +    case 146: +    case 176: +    case 193: +#line 303 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3SelectDelete((yypminor->yy107));} +#line 1236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 161: +    case 181: +    case 183: +    case 191: +    case 197: +    case 210: +#line 552 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3ExprDelete((yypminor->yy258));} +#line 1246 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 162: +    case 170: +    case 179: +    case 182: +    case 184: +    case 186: +    case 196: +    case 199: +    case 200: +    case 203: +    case 208: +#line 744 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3ExprListDelete((yypminor->yy210));} +#line 1261 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 175: +    case 180: +    case 188: +    case 189: +#line 428 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3SrcListDelete((yypminor->yy259));} +#line 1269 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 192: +    case 195: +    case 202: +#line 446 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3IdListDelete((yypminor->yy272));} +#line 1276 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 216: +    case 221: +#line 833 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeleteTriggerStep((yypminor->yy91));} +#line 1282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    case 218: +#line 817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3IdListDelete((yypminor->yy146).b);} +#line 1287 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +      break; +    default:  break;   /* If no destructor action specified: do nothing */ +  } +} + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. +*/ +static int yy_pop_parser_stack(yyParser *pParser){ +  YYCODETYPE yymajor; +  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + +  if( pParser->yyidx<0 ) return 0; +#ifndef NDEBUG +  if( yyTraceFILE && pParser->yyidx>=0 ){ +    fprintf(yyTraceFILE,"%sPopping %s\n", +      yyTracePrompt, +      yyTokenName[yytos->major]); +  } +#endif +  yymajor = yytos->major; +  yy_destructor( yymajor, &yytos->minor); +  pParser->yyidx--; +  return yymajor; +} + +/*  +** Deallocate and destroy a parser.  Destructors are all called for +** all stack elements before shutting the parser down. +** +** Inputs: +** <ul> +** <li>  A pointer to the parser.  This should be a pointer +**       obtained from sqlite3ParserAlloc. +** <li>  A pointer to a function used to reclaim memory obtained +**       from malloc. +** </ul> +*/ +void sqlite3ParserFree( +  void *p,                    /* The parser to be deleted */ +  void (*freeProc)(void*)     /* Function used to reclaim memory */ +){ +  yyParser *pParser = (yyParser*)p; +  if( pParser==0 ) return; +  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +  (*freeProc)((void*)pParser); +} + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead.  If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_shift_action( +  yyParser *pParser,        /* The parser */ +  int iLookAhead            /* The look-ahead token */ +){ +  int i; +  int stateno = pParser->yystack[pParser->yyidx].stateno; +  +  /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */ +  i = yy_shift_ofst[stateno]; +  if( i==YY_SHIFT_USE_DFLT ){ +    return yy_default[stateno]; +  } +  if( iLookAhead==YYNOCODE ){ +    return YY_NO_ACTION; +  } +  i += iLookAhead; +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ +#ifdef YYFALLBACK +    int iFallback;            /* Fallback token */ +    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) +           && (iFallback = yyFallback[iLookAhead])!=0 ){ +#ifndef NDEBUG +      if( yyTraceFILE ){ +        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", +           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); +      } +#endif +      return yy_find_shift_action(pParser, iFallback); +    } +#endif +    return yy_default[stateno]; +  }else{ +    return yy_action[i]; +  } +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead.  If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_reduce_action( +  yyParser *pParser,        /* The parser */ +  int iLookAhead            /* The look-ahead token */ +){ +  int i; +  int stateno = pParser->yystack[pParser->yyidx].stateno; +  +  i = yy_reduce_ofst[stateno]; +  if( i==YY_REDUCE_USE_DFLT ){ +    return yy_default[stateno]; +  } +  if( iLookAhead==YYNOCODE ){ +    return YY_NO_ACTION; +  } +  i += iLookAhead; +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ +    return yy_default[stateno]; +  }else{ +    return yy_action[i]; +  } +} + +/* +** Perform a shift action. +*/ +static void yy_shift( +  yyParser *yypParser,          /* The parser to be shifted */ +  int yyNewState,               /* The new state to shift in */ +  int yyMajor,                  /* The major token to shift in */ +  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */ +){ +  yyStackEntry *yytos; +  yypParser->yyidx++; +  if( yypParser->yyidx>=YYSTACKDEPTH ){ +     sqlite3ParserARG_FETCH; +     yypParser->yyidx--; +#ifndef NDEBUG +     if( yyTraceFILE ){ +       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); +     } +#endif +     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +     /* Here code is inserted which will execute if the parser +     ** stack every overflows */ +     sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ +     return; +  } +  yytos = &yypParser->yystack[yypParser->yyidx]; +  yytos->stateno = yyNewState; +  yytos->major = yyMajor; +  yytos->minor = *yypMinor; +#ifndef NDEBUG +  if( yyTraceFILE && yypParser->yyidx>0 ){ +    int i; +    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); +    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); +    for(i=1; i<=yypParser->yyidx; i++) +      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); +    fprintf(yyTraceFILE,"\n"); +  } +#endif +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { +  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */ +  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */ +} yyRuleInfo[] = { +  { 131, 1 }, +  { 132, 2 }, +  { 132, 1 }, +  { 133, 3 }, +  { 133, 1 }, +  { 135, 1 }, +  { 134, 1 }, +  { 134, 0 }, +  { 136, 3 }, +  { 138, 0 }, +  { 138, 1 }, +  { 138, 2 }, +  { 137, 0 }, +  { 137, 1 }, +  { 137, 1 }, +  { 137, 1 }, +  { 136, 2 }, +  { 136, 2 }, +  { 136, 2 }, +  { 136, 2 }, +  { 140, 5 }, +  { 142, 1 }, +  { 142, 0 }, +  { 141, 4 }, +  { 141, 2 }, +  { 144, 3 }, +  { 144, 1 }, +  { 147, 3 }, +  { 148, 1 }, +  { 151, 1 }, +  { 152, 1 }, +  { 152, 1 }, +  { 139, 1 }, +  { 139, 1 }, +  { 139, 1 }, +  { 149, 0 }, +  { 149, 1 }, +  { 149, 4 }, +  { 149, 6 }, +  { 153, 1 }, +  { 153, 2 }, +  { 154, 1 }, +  { 154, 1 }, +  { 150, 2 }, +  { 150, 0 }, +  { 157, 3 }, +  { 157, 1 }, +  { 157, 2 }, +  { 157, 2 }, +  { 157, 2 }, +  { 157, 2 }, +  { 158, 2 }, +  { 158, 3 }, +  { 158, 4 }, +  { 158, 2 }, +  { 158, 5 }, +  { 158, 4 }, +  { 158, 1 }, +  { 158, 2 }, +  { 163, 0 }, +  { 163, 2 }, +  { 165, 2 }, +  { 165, 3 }, +  { 165, 3 }, +  { 165, 3 }, +  { 166, 2 }, +  { 166, 2 }, +  { 166, 1 }, +  { 166, 1 }, +  { 164, 3 }, +  { 164, 2 }, +  { 167, 0 }, +  { 167, 2 }, +  { 167, 2 }, +  { 145, 0 }, +  { 145, 2 }, +  { 168, 3 }, +  { 168, 2 }, +  { 168, 1 }, +  { 169, 2 }, +  { 169, 6 }, +  { 169, 5 }, +  { 169, 3 }, +  { 169, 10 }, +  { 171, 0 }, +  { 171, 1 }, +  { 159, 0 }, +  { 159, 3 }, +  { 172, 0 }, +  { 172, 2 }, +  { 173, 1 }, +  { 173, 1 }, +  { 173, 1 }, +  { 136, 3 }, +  { 136, 7 }, +  { 136, 3 }, +  { 136, 1 }, +  { 146, 1 }, +  { 146, 3 }, +  { 177, 1 }, +  { 177, 2 }, +  { 177, 1 }, +  { 177, 1 }, +  { 176, 9 }, +  { 178, 1 }, +  { 178, 1 }, +  { 178, 0 }, +  { 186, 2 }, +  { 186, 0 }, +  { 179, 3 }, +  { 179, 2 }, +  { 179, 4 }, +  { 187, 2 }, +  { 187, 1 }, +  { 187, 0 }, +  { 180, 0 }, +  { 180, 2 }, +  { 189, 2 }, +  { 189, 0 }, +  { 188, 6 }, +  { 188, 7 }, +  { 193, 1 }, +  { 193, 1 }, +  { 143, 0 }, +  { 143, 2 }, +  { 175, 2 }, +  { 190, 1 }, +  { 190, 1 }, +  { 190, 2 }, +  { 190, 3 }, +  { 190, 4 }, +  { 191, 2 }, +  { 191, 0 }, +  { 192, 4 }, +  { 192, 0 }, +  { 184, 0 }, +  { 184, 3 }, +  { 196, 5 }, +  { 196, 3 }, +  { 197, 1 }, +  { 160, 1 }, +  { 160, 1 }, +  { 160, 0 }, +  { 198, 0 }, +  { 198, 2 }, +  { 182, 0 }, +  { 182, 3 }, +  { 183, 0 }, +  { 183, 2 }, +  { 185, 0 }, +  { 185, 2 }, +  { 185, 4 }, +  { 185, 4 }, +  { 136, 4 }, +  { 181, 0 }, +  { 181, 2 }, +  { 136, 6 }, +  { 200, 5 }, +  { 200, 3 }, +  { 136, 8 }, +  { 136, 5 }, +  { 201, 2 }, +  { 201, 1 }, +  { 203, 3 }, +  { 203, 1 }, +  { 202, 0 }, +  { 202, 3 }, +  { 195, 3 }, +  { 195, 1 }, +  { 161, 3 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 3 }, +  { 161, 5 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 1 }, +  { 161, 4 }, +  { 161, 4 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 161, 3 }, +  { 204, 1 }, +  { 204, 1 }, +  { 204, 2 }, +  { 204, 2 }, +  { 161, 3 }, +  { 161, 2 }, +  { 161, 3 }, +  { 161, 2 }, +  { 161, 3 }, +  { 161, 4 }, +  { 161, 2 }, +  { 161, 2 }, +  { 161, 2 }, +  { 161, 2 }, +  { 161, 3 }, +  { 205, 1 }, +  { 205, 2 }, +  { 161, 5 }, +  { 206, 1 }, +  { 206, 2 }, +  { 161, 5 }, +  { 161, 5 }, +  { 161, 4 }, +  { 161, 5 }, +  { 208, 5 }, +  { 208, 4 }, +  { 209, 2 }, +  { 209, 0 }, +  { 207, 1 }, +  { 207, 0 }, +  { 199, 3 }, +  { 199, 1 }, +  { 210, 1 }, +  { 210, 0 }, +  { 136, 11 }, +  { 211, 1 }, +  { 211, 0 }, +  { 162, 0 }, +  { 162, 3 }, +  { 170, 5 }, +  { 170, 3 }, +  { 212, 1 }, +  { 136, 3 }, +  { 136, 1 }, +  { 136, 2 }, +  { 136, 5 }, +  { 136, 5 }, +  { 136, 5 }, +  { 136, 5 }, +  { 136, 6 }, +  { 136, 3 }, +  { 155, 2 }, +  { 156, 2 }, +  { 214, 1 }, +  { 214, 1 }, +  { 213, 1 }, +  { 213, 0 }, +  { 136, 5 }, +  { 215, 10 }, +  { 217, 1 }, +  { 217, 1 }, +  { 217, 2 }, +  { 217, 0 }, +  { 218, 1 }, +  { 218, 1 }, +  { 218, 1 }, +  { 218, 3 }, +  { 219, 0 }, +  { 219, 3 }, +  { 219, 3 }, +  { 220, 0 }, +  { 220, 2 }, +  { 216, 3 }, +  { 216, 0 }, +  { 221, 6 }, +  { 221, 8 }, +  { 221, 5 }, +  { 221, 4 }, +  { 221, 1 }, +  { 161, 4 }, +  { 161, 6 }, +  { 174, 1 }, +  { 174, 1 }, +  { 174, 1 }, +  { 136, 3 }, +  { 136, 6 }, +  { 223, 0 }, +  { 223, 2 }, +  { 223, 2 }, +  { 222, 1 }, +  { 222, 0 }, +  { 136, 3 }, +}; + +static void yy_accept(yyParser*);  /* Forward Declaration */ + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +static void yy_reduce( +  yyParser *yypParser,         /* The parser */ +  int yyruleno                 /* Number of the rule by which to reduce */ +){ +  int yygoto;                     /* The next state */ +  int yyact;                      /* The next action */ +  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */ +  yyStackEntry *yymsp;            /* The top of the parser's stack */ +  int yysize;                     /* Amount to pop the stack */ +  sqlite3ParserARG_FETCH; +  yymsp = &yypParser->yystack[yypParser->yyidx]; +#ifndef NDEBUG +  if( yyTraceFILE && yyruleno>=0  +        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ +    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, +      yyRuleName[yyruleno]); +  } +#endif /* NDEBUG */ + +  switch( yyruleno ){ +  /* Beginning here are the reduction cases.  A typical example +  ** follows: +  **   case 0: +  **  #line <lineno> <grammarfile> +  **     { ... }           // User supplied code +  **  #line <lineno> <thisfile> +  **     break; +  */ +      case 5: +#line 86 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ sqlite3FinishCoding(pParse); } +#line 1794 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 6: +#line 87 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ sqlite3BeginParse(pParse, 1); } +#line 1799 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 7: +#line 88 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ sqlite3BeginParse(pParse, 0); } +#line 1804 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 8: +#line 93 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy284);} +#line 1809 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 12: +#line 98 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = TK_DEFERRED;} +#line 1814 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 13: +      case 14: +      case 15: +      case 99: +      case 101: +      case 102: +#line 99 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = yymsp[0].major;} +#line 1824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 16: +      case 17: +#line 102 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CommitTransaction(pParse);} +#line 1830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 18: +#line 104 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3RollbackTransaction(pParse);} +#line 1835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 20: +#line 109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +   sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,yymsp[-3].minor.yy284,0); +} +#line 1842 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 21: +      case 72: +      case 104: +      case 216: +      case 219: +#line 113 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = 1;} +#line 1851 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 22: +      case 71: +      case 73: +      case 84: +      case 105: +      case 106: +      case 215: +      case 218: +#line 114 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = 0;} +#line 1863 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 23: +#line 115 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3EndTable(pParse,&yymsp[0].minor.yy0,0); +} +#line 1870 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 24: +#line 118 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3EndTable(pParse,0,yymsp[0].minor.yy107); +  sqlite3SelectDelete(yymsp[0].minor.yy107); +} +#line 1878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 28: +#line 130 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddColumn(pParse,&yymsp[0].minor.yy98);} +#line 1883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 29: +      case 30: +      case 31: +      case 32: +      case 33: +      case 34: +      case 253: +      case 254: +#line 136 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98 = yymsp[0].minor.yy0;} +#line 1895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 36: +#line 185 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy98,&yymsp[0].minor.yy98);} +#line 1900 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 37: +#line 186 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy98,&yymsp[0].minor.yy0);} +#line 1905 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 38: +#line 188 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy98,&yymsp[0].minor.yy0);} +#line 1910 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 39: +      case 112: +      case 113: +      case 124: +      case 144: +      case 241: +      case 251: +      case 252: +#line 190 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98 = yymsp[0].minor.yy98;} +#line 1922 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 40: +#line 191 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98.z=yymsp[-1].minor.yy98.z; yygotominor.yy98.n=yymsp[0].minor.yy98.n+(yymsp[0].minor.yy98.z-yymsp[-1].minor.yy98.z);} +#line 1927 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 41: +#line 193 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = atoi(yymsp[0].minor.yy98.z); } +#line 1932 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 42: +#line 194 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = -atoi(yymsp[0].minor.yy98.z); } +#line 1937 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 47: +      case 48: +#line 199 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,0);} +#line 1943 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 49: +#line 201 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,1);} +#line 1948 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 52: +#line 208 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy284);} +#line 1953 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 53: +#line 209 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddPrimaryKey(pParse,0,yymsp[0].minor.yy284);} +#line 1958 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 54: +#line 210 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy284,0,0);} +#line 1963 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 56: +#line 213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy98,yymsp[-1].minor.yy210,yymsp[0].minor.yy284);} +#line 1968 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 57: +#line 214 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy284);} +#line 1973 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 58: +#line 215 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddCollateType(pParse, yymsp[0].minor.yy98.z, yymsp[0].minor.yy98.n);} +#line 1978 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 59: +#line 223 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = OE_Restrict * 0x010101; } +#line 1983 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 60: +#line 224 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = (yymsp[-1].minor.yy284 & yymsp[0].minor.yy47.mask) | yymsp[0].minor.yy47.value; } +#line 1988 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 61: +#line 226 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy47.value = 0;     yygotominor.yy47.mask = 0x000000; } +#line 1993 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 62: +#line 227 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy47.value = yymsp[0].minor.yy284;     yygotominor.yy47.mask = 0x0000ff; } +#line 1998 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 63: +#line 228 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy47.value = yymsp[0].minor.yy284<<8;  yygotominor.yy47.mask = 0x00ff00; } +#line 2003 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 64: +#line 229 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy47.value = yymsp[0].minor.yy284<<16; yygotominor.yy47.mask = 0xff0000; } +#line 2008 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 65: +#line 231 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = OE_SetNull; } +#line 2013 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 66: +#line 232 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = OE_SetDflt; } +#line 2018 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 67: +#line 233 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = OE_Cascade; } +#line 2023 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 68: +#line 234 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = OE_Restrict; } +#line 2028 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 69: +      case 70: +      case 85: +      case 87: +      case 89: +      case 90: +      case 161: +#line 236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = yymsp[0].minor.yy284;} +#line 2039 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 80: +#line 253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddPrimaryKey(pParse,yymsp[-2].minor.yy210,yymsp[0].minor.yy284);} +#line 2044 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 81: +#line 255 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy210,yymsp[0].minor.yy284,0,0);} +#line 2049 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 83: +#line 258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy210, &yymsp[-3].minor.yy98, yymsp[-2].minor.yy210, yymsp[-1].minor.yy284); +    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy284); +} +#line 2057 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 86: +      case 88: +#line 272 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Default;} +#line 2063 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 91: +#line 277 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Ignore;} +#line 2068 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 92: +      case 162: +#line 278 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Replace;} +#line 2074 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 93: +#line 282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0); +} +#line 2081 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 94: +#line 288 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy98, &yymsp[-2].minor.yy98, yymsp[0].minor.yy107, yymsp[-5].minor.yy284); +} +#line 2088 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 95: +#line 291 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1); +} +#line 2095 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 96: +#line 297 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3Select(pParse, yymsp[0].minor.yy107, SRT_Callback, 0, 0, 0, 0, 0); +  sqlite3SelectDelete(yymsp[0].minor.yy107); +} +#line 2103 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 97: +      case 121: +#line 307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy107 = yymsp[0].minor.yy107;} +#line 2109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 98: +#line 308 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  if( yymsp[0].minor.yy107 ){ +    yymsp[0].minor.yy107->op = yymsp[-1].minor.yy284; +    yymsp[0].minor.yy107->pPrior = yymsp[-2].minor.yy107; +  } +  yygotominor.yy107 = yymsp[0].minor.yy107; +} +#line 2120 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 100: +#line 317 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = TK_ALL;} +#line 2125 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 103: +#line 321 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy107 = sqlite3SelectNew(yymsp[-6].minor.yy210,yymsp[-5].minor.yy259,yymsp[-4].minor.yy258,yymsp[-3].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy210,yymsp[-7].minor.yy284,yymsp[0].minor.yy404.limit,yymsp[0].minor.yy404.offset); +} +#line 2132 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 107: +      case 238: +#line 342 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = yymsp[-1].minor.yy210;} +#line 2138 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 108: +      case 135: +      case 145: +      case 237: +#line 343 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = 0;} +#line 2146 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 109: +#line 344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +   yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[-1].minor.yy258,yymsp[0].minor.yy98.n?&yymsp[0].minor.yy98:0); +} +#line 2153 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 110: +#line 347 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-1].minor.yy210, sqlite3Expr(TK_ALL, 0, 0, 0), 0); +} +#line 2160 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 111: +#line 350 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); +  Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98); +  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-3].minor.yy210, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); +} +#line 2169 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 114: +#line 362 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98.n = 0;} +#line 2174 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 115: +#line 374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy259 = sqliteMalloc(sizeof(*yygotominor.yy259));} +#line 2179 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 116: +#line 375 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy259 = yymsp[0].minor.yy259;} +#line 2184 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 117: +#line 380 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +   yygotominor.yy259 = yymsp[-1].minor.yy259; +   if( yygotominor.yy259 && yygotominor.yy259->nSrc>0 ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = yymsp[0].minor.yy284; +} +#line 2192 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 118: +#line 384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy259 = 0;} +#line 2197 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 119: +#line 385 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-5].minor.yy259,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98); +  if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98); +  if( yymsp[-1].minor.yy258 ){ +    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; } +    else { sqlite3ExprDelete(yymsp[-1].minor.yy258); } +  } +  if( yymsp[0].minor.yy272 ){ +    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; } +    else { sqlite3IdListDelete(yymsp[0].minor.yy272); } +  } +} +#line 2213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 120: +#line 398 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-6].minor.yy259,0,0); +  yygotominor.yy259->a[yygotominor.yy259->nSrc-1].pSelect = yymsp[-4].minor.yy107; +  if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98); +  if( yymsp[-1].minor.yy258 ){ +    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; } +    else { sqlite3ExprDelete(yymsp[-1].minor.yy258); } +  } +  if( yymsp[0].minor.yy272 ){ +    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; } +    else { sqlite3IdListDelete(yymsp[0].minor.yy272); } +  } +} +#line 2230 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 122: +#line 419 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +   yygotominor.yy107 = sqlite3SelectNew(0,yymsp[0].minor.yy259,0,0,0,0,0,-1,0); +} +#line 2237 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 123: +#line 424 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98.z=0; yygotominor.yy98.n=0;} +#line 2242 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 125: +#line 429 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy259 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98);} +#line 2247 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 126: +      case 127: +#line 433 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = JT_INNER; } +#line 2253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 128: +#line 435 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +#line 2258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 129: +#line 436 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy98,0); } +#line 2263 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 130: +#line 438 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy98,&yymsp[-1].minor.yy98); } +#line 2268 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 131: +      case 139: +      case 148: +      case 155: +      case 226: +      case 228: +      case 232: +#line 442 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = yymsp[0].minor.yy258;} +#line 2279 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 132: +      case 147: +      case 154: +      case 227: +      case 229: +      case 233: +#line 443 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = 0;} +#line 2289 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 133: +      case 166: +#line 447 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy272 = yymsp[-1].minor.yy272;} +#line 2295 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 134: +      case 165: +#line 448 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy272 = 0;} +#line 2301 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 136: +      case 146: +#line 459 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = yymsp[0].minor.yy210;} +#line 2307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 137: +#line 460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0); +  if( yygotominor.yy210 ) yygotominor.yy210->a[yygotominor.yy210->nExpr-1].sortOrder = yymsp[0].minor.yy284; +} +#line 2315 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 138: +#line 464 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0); +  if( yygotominor.yy210 && yygotominor.yy210->a ) yygotominor.yy210->a[0].sortOrder = yymsp[0].minor.yy284; +} +#line 2323 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 140: +      case 142: +#line 473 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = SQLITE_SO_ASC;} +#line 2329 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 141: +#line 474 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = SQLITE_SO_DESC;} +#line 2334 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 143: +#line 476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy98.z = 0; yygotominor.yy98.n = 0;} +#line 2339 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 149: +#line 490 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy404.limit = -1; yygotominor.yy404.offset = 0;} +#line 2344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 150: +#line 491 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = 0;} +#line 2349 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 151: +#line 493 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy404.limit = yymsp[-2].minor.yy284; yygotominor.yy404.offset = yymsp[0].minor.yy284;} +#line 2354 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 152: +#line 495 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = yymsp[-2].minor.yy284;} +#line 2359 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 153: +#line 499 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy259,yymsp[0].minor.yy258);} +#line 2364 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 156: +#line 513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Update(pParse,yymsp[-3].minor.yy259,yymsp[-1].minor.yy210,yymsp[0].minor.yy258,yymsp[-4].minor.yy284);} +#line 2369 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 157: +#line 516 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);} +#line 2374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 158: +#line 517 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);} +#line 2379 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 159: +#line 523 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Insert(pParse, yymsp[-5].minor.yy259, yymsp[-1].minor.yy210, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy284);} +#line 2384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 160: +#line 525 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy107, yymsp[-1].minor.yy272, yymsp[-4].minor.yy284);} +#line 2389 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 163: +      case 230: +#line 535 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[0].minor.yy258,0);} +#line 2395 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 164: +      case 231: +#line 536 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,0);} +#line 2401 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 167: +#line 545 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy98);} +#line 2406 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 168: +#line 546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy98);} +#line 2411 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 169: +#line 554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = yymsp[-1].minor.yy258; sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +#line 2416 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 170: +      case 175: +      case 176: +      case 177: +      case 178: +#line 555 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} +#line 2425 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 171: +      case 172: +#line 556 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} +#line 2431 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 173: +#line 558 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98); +  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98); +  yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp2, 0); +} +#line 2440 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 174: +#line 563 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy98); +  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98); +  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98); +  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); +  yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp4, 0); +} +#line 2451 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 179: +#line 574 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Token *pToken = &yymsp[0].minor.yy0; +  Expr *pExpr = yygotominor.yy258 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); +  sqlite3ExprAssignVarNumber(pParse, pExpr); +} +#line 2460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 180: +#line 579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3ExprFunction(yymsp[-1].minor.yy210, &yymsp[-3].minor.yy0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2468 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 181: +#line 583 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 182: +      case 183: +      case 184: +      case 185: +      case 186: +      case 187: +      case 188: +      case 189: +      case 190: +      case 191: +      case 192: +      case 193: +      case 194: +      case 195: +      case 196: +      case 197: +      case 198: +      case 199: +#line 587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy258, yymsp[0].minor.yy258, 0);} +#line 2498 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 200: +#line 606 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 0;} +#line 2503 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 201: +#line 607 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 0;} +#line 2508 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 202: +#line 608 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 1;} +#line 2513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 203: +#line 609 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 1;} +#line 2518 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 204: +#line 610 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  ExprList *pList = sqlite3ExprListAppend(0, yymsp[0].minor.yy258, 0); +  pList = sqlite3ExprListAppend(pList, yymsp[-2].minor.yy258, 0); +  yygotominor.yy258 = sqlite3ExprFunction(pList, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->op = yymsp[-1].minor.yy342.opcode; +  if( yymsp[-1].minor.yy342.not ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-2].minor.yy258->span, &yymsp[0].minor.yy258->span); +} +#line 2530 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 205: +#line 618 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2538 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 206: +#line 622 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 207: +#line 626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 208: +#line 630 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2562 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 209: +#line 634 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2570 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 210: +      case 211: +#line 638 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span); +} +#line 2579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 212: +#line 646 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span); +} +#line 2587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 213: +#line 650 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span); +} +#line 2595 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 214: +#line 654 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_SELECT, 0, 0, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107; +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2604 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 217: +#line 662 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0); +  pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy258, 0); +  yygotominor.yy258 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy258, 0, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pList = pList; +  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy258->span); +} +#line 2616 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 220: +#line 673 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-1].minor.yy210; +  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 221: +#line 679 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107; +  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0); +} +#line 2636 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 222: +#line 685 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98); +  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy258, 0, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0); +  if( yymsp[-2].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0); +  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,yymsp[0].minor.yy98.z?&yymsp[0].minor.yy98:&yymsp[-1].minor.yy98); +} +#line 2647 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 223: +#line 695 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy258, yymsp[-1].minor.yy258, 0); +  if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-2].minor.yy210; +  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2656 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 224: +#line 702 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, yymsp[-2].minor.yy258, 0); +  yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0); +} +#line 2664 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 225: +#line 706 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy210 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0); +  yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0); +} +#line 2672 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 234: +#line 731 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  if( yymsp[-9].minor.yy284!=OE_None ) yymsp[-9].minor.yy284 = yymsp[0].minor.yy284; +  if( yymsp[-9].minor.yy284==OE_Default) yymsp[-9].minor.yy284 = OE_Abort; +  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-4].minor.yy259, yymsp[-2].minor.yy210, yymsp[-9].minor.yy284, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); +} +#line 2681 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 235: +      case 282: +#line 738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Abort;} +#line 2687 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 236: +#line 739 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_None;} +#line 2692 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 239: +#line 749 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Expr *p = 0; +  if( yymsp[-1].minor.yy98.n>0 ){ +    p = sqlite3Expr(TK_COLUMN, 0, 0, 0); +    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n); +  } +  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, p, &yymsp[-2].minor.yy98); +} +#line 2704 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 240: +#line 757 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Expr *p = 0; +  if( yymsp[-1].minor.yy98.n>0 ){ +    p = sqlite3Expr(TK_COLUMN, 0, 0, 0); +    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n); +  } +  yygotominor.yy210 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy98); +} +#line 2716 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 242: +#line 770 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DropIndex(pParse, yymsp[0].minor.yy259);} +#line 2721 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 243: +      case 244: +#line 774 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Vacuum(pParse,0);} +#line 2727 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 245: +      case 247: +#line 779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,0);} +#line 2733 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 246: +#line 780 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy0,0);} +#line 2738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 248: +#line 782 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,1); +} +#line 2745 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 249: +#line 785 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98,&yymsp[-1].minor.yy98,0);} +#line 2750 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 250: +#line 786 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,0,0);} +#line 2755 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 257: +#line 796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  Token all; +  all.z = yymsp[-3].minor.yy98.z; +  all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy98.z) + yymsp[0].minor.yy0.n; +  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy91, &all); +} +#line 2765 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 258: +#line 805 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-5].minor.yy284, yymsp[-4].minor.yy146.a, yymsp[-4].minor.yy146.b, yymsp[-2].minor.yy259, yymsp[-1].minor.yy284, yymsp[0].minor.yy258, yymsp[-9].minor.yy284); +  yygotominor.yy98 = (yymsp[-6].minor.yy98.n==0?yymsp[-7].minor.yy98:yymsp[-6].minor.yy98); +} +#line 2773 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 259: +      case 262: +#line 811 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = TK_BEFORE; } +#line 2779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 260: +#line 812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = TK_AFTER;  } +#line 2784 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 261: +#line 813 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = TK_INSTEAD;} +#line 2789 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 263: +      case 264: +      case 265: +#line 818 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy146.a = yymsp[0].major; yygotominor.yy146.b = 0;} +#line 2796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 266: +#line 821 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy146.a = TK_UPDATE; yygotominor.yy146.b = yymsp[0].minor.yy272;} +#line 2801 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 267: +      case 268: +#line 824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = TK_ROW; } +#line 2807 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 269: +#line 826 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy284 = TK_STATEMENT; } +#line 2812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 270: +#line 829 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy258 = 0; } +#line 2817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 271: +#line 830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy258 = yymsp[0].minor.yy258; } +#line 2822 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 272: +#line 834 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yymsp[-2].minor.yy91->pNext = yymsp[0].minor.yy91; +  yygotominor.yy91 = yymsp[-2].minor.yy91; +} +#line 2830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 273: +#line 838 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy91 = 0; } +#line 2835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 274: +#line 844 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy91 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy98, yymsp[-1].minor.yy210, yymsp[0].minor.yy258, yymsp[-4].minor.yy284); } +#line 2840 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 275: +#line 849 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy98, yymsp[-4].minor.yy272, yymsp[-1].minor.yy210, 0, yymsp[-7].minor.yy284);} +#line 2845 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 276: +#line 852 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy98, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy107, yymsp[-4].minor.yy284);} +#line 2850 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 277: +#line 856 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy91 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy98, yymsp[0].minor.yy258);} +#line 2855 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 278: +#line 859 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy91 = sqlite3TriggerSelectStep(yymsp[0].minor.yy107); } +#line 2860 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 279: +#line 862 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, 0);  +  yygotominor.yy258->iColumn = OE_Ignore; +  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2869 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 280: +#line 867 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy98);  +  yygotominor.yy258->iColumn = yymsp[-3].minor.yy284; +  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 281: +#line 873 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Rollback;} +#line 2883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 283: +#line 875 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy284 = OE_Fail;} +#line 2888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 284: +#line 879 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3DropTrigger(pParse,yymsp[0].minor.yy259); +} +#line 2895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 285: +#line 884 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3Attach(pParse, &yymsp[-3].minor.yy98, &yymsp[-1].minor.yy98, yymsp[0].minor.yy292.type, &yymsp[0].minor.yy292.key); +} +#line 2902 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 286: +#line 888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy292.type = 0; } +#line 2907 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 287: +#line 889 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy292.type=1; yygotominor.yy292.key = yymsp[0].minor.yy98; } +#line 2912 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 288: +#line 890 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy292.type=2; yygotominor.yy292.key = yymsp[0].minor.yy0; } +#line 2917 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +      case 291: +#line 896 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" +{ +  sqlite3Detach(pParse, &yymsp[0].minor.yy98); +} +#line 2924 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +        break; +  }; +  yygoto = yyRuleInfo[yyruleno].lhs; +  yysize = yyRuleInfo[yyruleno].nrhs; +  yypParser->yyidx -= yysize; +  yyact = yy_find_reduce_action(yypParser,yygoto); +  if( yyact < YYNSTATE ){ +    yy_shift(yypParser,yyact,yygoto,&yygotominor); +  }else if( yyact == YYNSTATE + YYNRULE + 1 ){ +    yy_accept(yypParser); +  } +} + +/* +** The following code executes when the parse fails +*/ +static void yy_parse_failed( +  yyParser *yypParser           /* The parser */ +){ +  sqlite3ParserARG_FETCH; +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); +  } +#endif +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +  /* Here code is inserted which will be executed whenever the +  ** parser fails */ +  sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following code executes when a syntax error first occurs. +*/ +static void yy_syntax_error( +  yyParser *yypParser,           /* The parser */ +  int yymajor,                   /* The major type of the error token */ +  YYMINORTYPE yyminor            /* The minor type of the error token */ +){ +  sqlite3ParserARG_FETCH; +#define TOKEN (yyminor.yy0) +#line 23 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y" + +  if( pParse->zErrMsg==0 ){ +    if( TOKEN.z[0] ){ +      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); +    }else{ +      sqlite3ErrorMsg(pParse, "incomplete SQL statement"); +    } +  } +#line 2976 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c" +  sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following is executed when the parser accepts +*/ +static void yy_accept( +  yyParser *yypParser           /* The parser */ +){ +  sqlite3ParserARG_FETCH; +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); +  } +#endif +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +  /* Here code is inserted which will be executed whenever the +  ** parser accepts */ +  sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "sqlite3ParserAlloc" which describes the current state of the parser. +** The second argument is the major token number.  The third is +** the minor token.  The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +** <ul> +** <li> A pointer to the parser (an opaque structure.) +** <li> The major token number. +** <li> The minor token number. +** <li> An option argument of a grammar-specified type. +** </ul> +** +** Outputs: +** None. +*/ +void sqlite3Parser( +  void *yyp,                   /* The parser */ +  int yymajor,                 /* The major token code number */ +  sqlite3ParserTOKENTYPE yyminor       /* The value for the token */ +  sqlite3ParserARG_PDECL               /* Optional %extra_argument parameter */ +){ +  YYMINORTYPE yyminorunion; +  int yyact;            /* The parser action. */ +  int yyendofinput;     /* True if we are at the end of input */ +  int yyerrorhit = 0;   /* True if yymajor has invoked an error */ +  yyParser *yypParser;  /* The parser */ + +  /* (re)initialize the parser, if necessary */ +  yypParser = (yyParser*)yyp; +  if( yypParser->yyidx<0 ){ +    if( yymajor==0 ) return; +    yypParser->yyidx = 0; +    yypParser->yyerrcnt = -1; +    yypParser->yystack[0].stateno = 0; +    yypParser->yystack[0].major = 0; +  } +  yyminorunion.yy0 = yyminor; +  yyendofinput = (yymajor==0); +  sqlite3ParserARG_STORE; + +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); +  } +#endif + +  do{ +    yyact = yy_find_shift_action(yypParser,yymajor); +    if( yyact<YYNSTATE ){ +      yy_shift(yypParser,yyact,yymajor,&yyminorunion); +      yypParser->yyerrcnt--; +      if( yyendofinput && yypParser->yyidx>=0 ){ +        yymajor = 0; +      }else{ +        yymajor = YYNOCODE; +      } +    }else if( yyact < YYNSTATE + YYNRULE ){ +      yy_reduce(yypParser,yyact-YYNSTATE); +    }else if( yyact == YY_ERROR_ACTION ){ +      int yymx; +#ifndef NDEBUG +      if( yyTraceFILE ){ +        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); +      } +#endif +#ifdef YYERRORSYMBOL +      /* A syntax error has occurred. +      ** The response to an error depends upon whether or not the +      ** grammar defines an error token "ERROR".   +      ** +      ** This is what we do if the grammar does define ERROR: +      ** +      **  * Call the %syntax_error function. +      ** +      **  * Begin popping the stack until we enter a state where +      **    it is legal to shift the error symbol, then shift +      **    the error symbol. +      ** +      **  * Set the error count to three. +      ** +      **  * Begin accepting and shifting new tokens.  No new error +      **    processing will occur until three tokens have been +      **    shifted successfully. +      ** +      */ +      if( yypParser->yyerrcnt<0 ){ +        yy_syntax_error(yypParser,yymajor,yyminorunion); +      } +      yymx = yypParser->yystack[yypParser->yyidx].major; +      if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG +        if( yyTraceFILE ){ +          fprintf(yyTraceFILE,"%sDiscard input token %s\n", +             yyTracePrompt,yyTokenName[yymajor]); +        } +#endif +        yy_destructor(yymajor,&yyminorunion); +        yymajor = YYNOCODE; +      }else{ +         while( +          yypParser->yyidx >= 0 && +          yymx != YYERRORSYMBOL && +          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE +        ){ +          yy_pop_parser_stack(yypParser); +        } +        if( yypParser->yyidx < 0 || yymajor==0 ){ +          yy_destructor(yymajor,&yyminorunion); +          yy_parse_failed(yypParser); +          yymajor = YYNOCODE; +        }else if( yymx!=YYERRORSYMBOL ){ +          YYMINORTYPE u2; +          u2.YYERRSYMDT = 0; +          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); +        } +      } +      yypParser->yyerrcnt = 3; +      yyerrorhit = 1; +#else  /* YYERRORSYMBOL is not defined */ +      /* This is what we do if the grammar does not define ERROR: +      ** +      **  * Report an error message, and throw away the input token. +      ** +      **  * If the input token is $, then fail the parse. +      ** +      ** As before, subsequent error messages are suppressed until +      ** three input tokens have been successfully shifted. +      */ +      if( yypParser->yyerrcnt<=0 ){ +        yy_syntax_error(yypParser,yymajor,yyminorunion); +      } +      yypParser->yyerrcnt = 3; +      yy_destructor(yymajor,&yyminorunion); +      if( yyendofinput ){ +        yy_parse_failed(yypParser); +      } +      yymajor = YYNOCODE; +#endif +    }else{ +      yy_accept(yypParser); +      yymajor = YYNOCODE; +    } +  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); +  return; +} diff --git a/ext/pdo_sqlite/sqlite/src/parse.h b/ext/pdo_sqlite/sqlite/src/parse.h new file mode 100644 index 0000000000..547319ed70 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/parse.h @@ -0,0 +1,129 @@ +#define TK_END_OF_FILE                     1 +#define TK_ILLEGAL                         2 +#define TK_SPACE                           3 +#define TK_UNCLOSED_STRING                 4 +#define TK_COMMENT                         5 +#define TK_FUNCTION                        6 +#define TK_COLUMN                          7 +#define TK_AGG_FUNCTION                    8 +#define TK_SEMI                            9 +#define TK_EXPLAIN                        10 +#define TK_BEGIN                          11 +#define TK_TRANSACTION                    12 +#define TK_DEFERRED                       13 +#define TK_IMMEDIATE                      14 +#define TK_EXCLUSIVE                      15 +#define TK_COMMIT                         16 +#define TK_END                            17 +#define TK_ROLLBACK                       18 +#define TK_CREATE                         19 +#define TK_TABLE                          20 +#define TK_TEMP                           21 +#define TK_LP                             22 +#define TK_RP                             23 +#define TK_AS                             24 +#define TK_COMMA                          25 +#define TK_ID                             26 +#define TK_ABORT                          27 +#define TK_AFTER                          28 +#define TK_ASC                            29 +#define TK_ATTACH                         30 +#define TK_BEFORE                         31 +#define TK_CASCADE                        32 +#define TK_CONFLICT                       33 +#define TK_DATABASE                       34 +#define TK_DESC                           35 +#define TK_DETACH                         36 +#define TK_EACH                           37 +#define TK_FAIL                           38 +#define TK_FOR                            39 +#define TK_GLOB                           40 +#define TK_IGNORE                         41 +#define TK_INITIALLY                      42 +#define TK_INSTEAD                        43 +#define TK_LIKE                           44 +#define TK_MATCH                          45 +#define TK_KEY                            46 +#define TK_OF                             47 +#define TK_OFFSET                         48 +#define TK_PRAGMA                         49 +#define TK_RAISE                          50 +#define TK_REPLACE                        51 +#define TK_RESTRICT                       52 +#define TK_ROW                            53 +#define TK_STATEMENT                      54 +#define TK_TRIGGER                        55 +#define TK_VACUUM                         56 +#define TK_VIEW                           57 +#define TK_OR                             58 +#define TK_AND                            59 +#define TK_NOT                            60 +#define TK_IS                             61 +#define TK_BETWEEN                        62 +#define TK_IN                             63 +#define TK_ISNULL                         64 +#define TK_NOTNULL                        65 +#define TK_NE                             66 +#define TK_EQ                             67 +#define TK_GT                             68 +#define TK_LE                             69 +#define TK_LT                             70 +#define TK_GE                             71 +#define TK_BITAND                         72 +#define TK_BITOR                          73 +#define TK_LSHIFT                         74 +#define TK_RSHIFT                         75 +#define TK_PLUS                           76 +#define TK_MINUS                          77 +#define TK_STAR                           78 +#define TK_SLASH                          79 +#define TK_REM                            80 +#define TK_CONCAT                         81 +#define TK_UMINUS                         82 +#define TK_UPLUS                          83 +#define TK_BITNOT                         84 +#define TK_STRING                         85 +#define TK_JOIN_KW                        86 +#define TK_CONSTRAINT                     87 +#define TK_DEFAULT                        88 +#define TK_NULL                           89 +#define TK_PRIMARY                        90 +#define TK_UNIQUE                         91 +#define TK_CHECK                          92 +#define TK_REFERENCES                     93 +#define TK_COLLATE                        94 +#define TK_ON                             95 +#define TK_DELETE                         96 +#define TK_UPDATE                         97 +#define TK_INSERT                         98 +#define TK_SET                            99 +#define TK_DEFERRABLE                     100 +#define TK_FOREIGN                        101 +#define TK_DROP                           102 +#define TK_UNION                          103 +#define TK_ALL                            104 +#define TK_INTERSECT                      105 +#define TK_EXCEPT                         106 +#define TK_SELECT                         107 +#define TK_DISTINCT                       108 +#define TK_DOT                            109 +#define TK_FROM                           110 +#define TK_JOIN                           111 +#define TK_USING                          112 +#define TK_ORDER                          113 +#define TK_BY                             114 +#define TK_GROUP                          115 +#define TK_HAVING                         116 +#define TK_LIMIT                          117 +#define TK_WHERE                          118 +#define TK_INTO                           119 +#define TK_VALUES                         120 +#define TK_INTEGER                        121 +#define TK_FLOAT                          122 +#define TK_BLOB                           123 +#define TK_VARIABLE                       124 +#define TK_CASE                           125 +#define TK_WHEN                           126 +#define TK_THEN                           127 +#define TK_ELSE                           128 +#define TK_INDEX                          129 diff --git a/ext/pdo_sqlite/sqlite/src/parse.y b/ext/pdo_sqlite/sqlite/src/parse.y new file mode 100644 index 0000000000..59dd563a6c --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/parse.y @@ -0,0 +1,898 @@ +/* +** 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$ +*/ +%token_prefix TK_ +%token_type {Token} +%default_type {Token} +%extra_argument {Parse *pParse} +%syntax_error { +  if( pParse->zErrMsg==0 ){ +    if( TOKEN.z[0] ){ +      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); +    }else{ +      sqlite3ErrorMsg(pParse, "incomplete SQL statement"); +    } +  } +} +%name sqlite3Parser +%include { +#include "sqliteInt.h" +#include "parse.h" + +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { +  int limit;    /* The LIMIT value.  -1 if there is no limit */ +  int offset;   /* The OFFSET.  0 if there is none */ +}; + +/* +** An instance of this structure is used to store the LIKE, +** GLOB, NOT LIKE, and NOT GLOB operators. +*/ +struct LikeOp { +  int opcode;   /* Either TK_GLOB or TK_LIKE */ +  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 + +// These are extra tokens used by the lexer but never seen by the +// parser.  We put them in a rule so that the parser generator will +// add them to the parse.h output file. +// +%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION +          COLUMN AGG_FUNCTION. + +// Input is a single SQL command +input ::= cmdlist. +cmdlist ::= cmdlist ecmd. +cmdlist ::= ecmd. +ecmd ::= explain cmdx SEMI. +ecmd ::= SEMI. +cmdx ::= cmd.           { sqlite3FinishCoding(pParse); } +explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); } +explain ::= .           { sqlite3BeginParse(pParse, 0); } + +///////////////////// 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(X) temp(T) TABLE nm(Y) dbnm(Z). { +   sqlite3StartTable(pParse,&X,&Y,&Z,T,0); +} +%type temp {int} +temp(A) ::= TEMP.  {A = 1;} +temp(A) ::= .      {A = 0;} +create_table_args ::= LP columnlist conslist_opt RP(X). { +  sqlite3EndTable(pParse,&X,0); +} +create_table_args ::= AS select(S). { +  sqlite3EndTable(pParse,0,S); +  sqlite3SelectDelete(S); +} +columnlist ::= columnlist COMMA column. +columnlist ::= column. + +// About the only information used for a column is the name of the +// column.  The type is always just "text".  But the code will accept +// an elaborate typename.  Perhaps someday we'll do something with it. +// +column ::= columnid type carglist.  +columnid ::= nm(X).                {sqlite3AddColumn(pParse,&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 ASC ATTACH BEFORE BEGIN CASCADE CONFLICT +  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR +  GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY +  OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT +  TEMP TRIGGER VACUUM VIEW. + +// 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 LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ. +%left GT LE LT GE. +%left BITAND BITOR LSHIFT RSHIFT. +%left PLUS MINUS. +%left STAR SLASH REM. +%left CONCAT. +%right UMINUS UPLUS BITNOT. + +// And "ids" is an identifer-or-string. +// +%type ids {Token} +ids(A) ::= ID(X).        {A = X;} +ids(A) ::= 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;} + +type ::= . +type ::= typename(X).                    {sqlite3AddColumnType(pParse,&X,&X);} +type ::= typename(X) LP signed RP(Y).    {sqlite3AddColumnType(pParse,&X,&Y);} +type ::= typename(X) LP signed COMMA signed RP(Y). +                                         {sqlite3AddColumnType(pParse,&X,&Y);} +%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);} +%type signed {int} +signed(A) ::= plus_num(X).    { A = atoi(X.z); } +signed(A) ::= minus_num(X).   { A = -atoi(X.z); } +carglist ::= carglist carg. +carglist ::= . +carg ::= CONSTRAINT nm ccons. +carg ::= ccons. +carg ::= DEFAULT ids(X).             {sqlite3AddDefaultValue(pParse,&X,0);} +carg ::= DEFAULT plus_num(X).        {sqlite3AddDefaultValue(pParse,&X,0);} +carg ::= DEFAULT minus_num(X).       {sqlite3AddDefaultValue(pParse,&X,1);} +carg ::= DEFAULT NULL.  + +// 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 onconf(R).  {sqlite3AddPrimaryKey(pParse,0,R);} +ccons ::= UNIQUE onconf(R).          {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);} +ccons ::= CHECK LP expr RP onconf. +ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). +                                {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} +ccons ::= defer_subclause(D).   {sqlite3DeferForeignKey(pParse,D);} +ccons ::= COLLATE id(C).  {sqlite3AddCollateType(pParse, C.z, C.n);} + +// 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 ::= . +conslist_opt ::= COMMA conslist. +conslist ::= conslist COMMA tcons. +conslist ::= conslist tcons. +conslist ::= tcons. +tcons ::= CONSTRAINT nm. +tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). +                                             {sqlite3AddPrimaryKey(pParse,X,R);} +tcons ::= UNIQUE LP idxlist(X) RP onconf(R). +                                       {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} +tcons ::= CHECK expr onconf. +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 fullname(X). { +  sqlite3DropTable(pParse, X, 0); +} + +///////////////////// The CREATE VIEW statement ///////////////////////////// +// +cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). { +  sqlite3CreateView(pParse, &X, &Y, &Z, S, T); +} +cmd ::= DROP VIEW fullname(X). { +  sqlite3DropTable(pParse, X, 1); +} + +//////////////////////// The SELECT statement ///////////////////////////////// +// +cmd ::= select(X).  { +  sqlite3Select(pParse, X, SRT_Callback, 0, 0, 0, 0, 0); +  sqlite3SelectDelete(X); +} + +%type select {Select*} +%destructor select {sqlite3SelectDelete($$);} +%type oneselect {Select*} +%destructor oneselect {sqlite3SelectDelete($$);} + +select(A) ::= oneselect(X).                      {A = X;} +select(A) ::= select(X) multiselect_op(Y) oneselect(Z).  { +  if( Z ){ +    Z->op = Y; +    Z->pPrior = 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) ::= INTERSECT(OP).  {A = @OP;} +multiselect_op(A) ::= EXCEPT(OP).     {A = @OP;} +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(W,X,Y,P,Q,Z,D,L.limit,L.offset); +} + +// 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(P,X,Y.n?&Y:0); +} +selcollist(A) ::= sclp(P) STAR. { +  A = sqlite3ExprListAppend(P, sqlite3Expr(TK_ALL, 0, 0, 0), 0); +} +selcollist(A) ::= sclp(P) nm(X) DOT STAR. { +  Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); +  Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &X); +  A = sqlite3ExprListAppend(P, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); +} + +// An option "AS <id>" 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 = sqliteMalloc(sizeof(*A));} +from(A) ::= FROM seltablist(X).               {A = X;} + +// "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 = sqlite3SrcListAppend(X,&Y,&D); +  if( Z.n ) sqlite3SrcListAddAlias(A,&Z); +  if( N ){ +    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; } +    else { sqlite3ExprDelete(N); } +  } +  if( U ){ +    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; } +    else { sqlite3IdListDelete(U); } +  } +} +seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP +                  as(Z) on_opt(N) using_opt(U). { +  A = sqlite3SrcListAppend(X,0,0); +  A->a[A->nSrc-1].pSelect = S; +  if( Z.n ) sqlite3SrcListAddAlias(A,&Z); +  if( N ){ +    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; } +    else { sqlite3ExprDelete(N); } +  } +  if( U ){ +    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; } +    else { sqlite3IdListDelete(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).  { +   A = sqlite3SelectNew(0,F,0,0,0,0,0,-1,0); +} + +%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(0,&X,&Y);} + +%type joinop {int} +%type joinop2 {int} +joinop(X) ::= COMMA.                   { X = JT_INNER; } +joinop(X) ::= 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) collate(C) sortorder(Z). { +  A = sqlite3ExprListAppend(X,Y,C.n>0?&C:0); +  if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). { +  A = sqlite3ExprListAppend(0,Y,C.n>0?&C:0); +  if( A && A->a ) A->a[0].sortOrder = Z; +} +sortitem(A) ::= expr(X).   {A = X;} + +%type sortorder {int} +%type collate {Token} + +sortorder(A) ::= ASC.           {A = SQLITE_SO_ASC;} +sortorder(A) ::= DESC.          {A = SQLITE_SO_DESC;} +sortorder(A) ::= .              {A = SQLITE_SO_ASC;} +collate(C) ::= .                {C.z = 0; C.n = 0;} +collate(C) ::= COLLATE id(X).   {C = X;} + +%type groupby_opt {ExprList*} +%destructor groupby_opt {sqlite3ExprListDelete($$);} +groupby_opt(A) ::= .                      {A = 0;} +groupby_opt(A) ::= GROUP BY exprlist(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} +limit_opt(A) ::= .                     {A.limit = -1; A.offset = 0;} +limit_opt(A) ::= LIMIT signed(X).      {A.limit = X; A.offset = 0;} +limit_opt(A) ::= LIMIT signed(X) OFFSET signed(Y).  +                                       {A.limit = X; A.offset = Y;} +limit_opt(A) ::= LIMIT signed(X) COMMA signed(Y).  +                                       {A.limit = Y; A.offset = X;} + +/////////////////////////// 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;} + +%type setlist {ExprList*} +%destructor setlist {sqlite3ExprListDelete($$);} + +////////////////////////// The UPDATE command //////////////////////////////// +// +cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z). +    {sqlite3Update(pParse,X,Y,Z,R);} + +setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). +    {A = sqlite3ExprListAppend(Z,Y,&X);} +setlist(A) ::= nm(X) EQ expr(Y).   {A = sqlite3ExprListAppend(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);} + +%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(X,Y,0);} +itemlist(A) ::= expr(X).                    {A = sqlite3ExprListAppend(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(X,&Y);} +inscollist(A) ::= nm(Y).                      {A = sqlite3IdListAppend(0,&Y);} + +/////////////////////////// Expression Processing ///////////////////////////// +// + +%type expr {Expr*} +%destructor expr {sqlite3ExprDelete($$);} + +expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); } +expr(A) ::= NULL(X).             {A = sqlite3Expr(@X, 0, 0, &X);} +expr(A) ::= ID(X).               {A = sqlite3Expr(TK_ID, 0, 0, &X);} +expr(A) ::= JOIN_KW(X).          {A = sqlite3Expr(TK_ID, 0, 0, &X);} +expr(A) ::= nm(X) DOT nm(Y). { +  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X); +  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y); +  A = sqlite3Expr(TK_DOT, temp1, temp2, 0); +} +expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { +  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X); +  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y); +  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &Z); +  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); +  A = sqlite3Expr(TK_DOT, temp1, temp4, 0); +} +expr(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);} +expr(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);} +expr(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);} +expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);} +expr(A) ::= VARIABLE(X).     { +  Token *pToken = &X; +  Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); +  sqlite3ExprAssignVarNumber(pParse, pExpr); +} +expr(A) ::= ID(X) LP exprlist(Y) RP(E). { +  A = sqlite3ExprFunction(Y, &X); +  sqlite3ExprSpan(A,&X,&E); +} +expr(A) ::= ID(X) LP STAR RP(E). { +  A = sqlite3ExprFunction(0, &X); +  sqlite3ExprSpan(A,&X,&E); +} +expr(A) ::= expr(X) AND(OP) expr(Y).    {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) OR(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) LT(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) GT(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) LE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) GE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) NE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) EQ(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) BITAND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) BITOR(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) LSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) RSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) PLUS(OP) expr(Y).   {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) MINUS(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) STAR(OP) expr(Y).   {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) SLASH(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) REM(OP) expr(Y).    {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +%type likeop {struct LikeOp} +likeop(A) ::= LIKE.     {A.opcode = TK_LIKE; A.not = 0;} +likeop(A) ::= GLOB.     {A.opcode = TK_GLOB; A.not = 0;} +likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;} +likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;} +expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE]  { +  ExprList *pList = sqlite3ExprListAppend(0, Y, 0); +  pList = sqlite3ExprListAppend(pList, X, 0); +  A = sqlite3ExprFunction(pList, 0); +  if( A ) A->op = OP.opcode; +  if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0); +  sqlite3ExprSpan(A, &X->span, &Y->span); +} +expr(A) ::= expr(X) ISNULL(E). { +  A = sqlite3Expr(TK_ISNULL, X, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NULL(E). { +  A = sqlite3Expr(TK_ISNULL, X, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) NOTNULL(E). { +  A = sqlite3Expr(TK_NOTNULL, X, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) NOT NULL(E). { +  A = sqlite3Expr(TK_NOTNULL, X, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NOT NULL(E). { +  A = sqlite3Expr(TK_NOTNULL, X, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= NOT(B) expr(X). { +  A = sqlite3Expr(@B, X, 0, 0); +  sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= BITNOT(B) expr(X). { +  A = sqlite3Expr(@B, X, 0, 0); +  sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= MINUS(B) expr(X). [UMINUS] { +  A = sqlite3Expr(TK_UMINUS, X, 0, 0); +  sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= PLUS(B) expr(X). [UPLUS] { +  A = sqlite3Expr(TK_UPLUS, X, 0, 0); +  sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= LP(B) select(X) RP(E). { +  A = sqlite3Expr(TK_SELECT, 0, 0, 0); +  if( A ) A->pSelect = X; +  sqlite3ExprSpan(A,&B,&E); +} +%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(0, X, 0); +  pList = sqlite3ExprListAppend(pList, Y, 0); +  A = sqlite3Expr(TK_BETWEEN, W, 0, 0); +  if( A ) A->pList = pList; +  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0); +  sqlite3ExprSpan(A,&W->span,&Y->span); +} +%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 = sqlite3Expr(TK_IN, X, 0, 0); +  if( A ) A->pList = Y; +  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0); +  sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E).  [IN] { +  A = sqlite3Expr(TK_IN, X, 0, 0); +  if( A ) A->pSelect = Y; +  if( N ) A = sqlite3Expr(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(0,&Y,&Z); +  A = sqlite3Expr(TK_IN, X, 0, 0); +  if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0); +  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0); +  sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y); +} + + +/* CASE expressions */ +expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { +  A = sqlite3Expr(TK_CASE, X, Z, 0); +  if( A ) A->pList = 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(X, Y, 0); +  A = sqlite3ExprListAppend(A, Z, 0); +} +case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { +  A = sqlite3ExprListAppend(0, Y, 0); +  A = sqlite3ExprListAppend(A, Z, 0); +} +%type case_else {Expr*} +case_else(A) ::=  ELSE expr(X).         {A = X;} +case_else(A) ::=  .                     {A = 0;}  +%type case_operand {Expr*} +case_operand(A) ::= expr(X).            {A = X;}  +case_operand(A) ::= .                   {A = 0;}  + +%type exprlist {ExprList*} +%destructor exprlist {sqlite3ExprListDelete($$);} +%type expritem {Expr*} +%destructor expritem {sqlite3ExprDelete($$);} + +exprlist(A) ::= exprlist(X) COMMA expritem(Y).  +                                        {A = sqlite3ExprListAppend(X,Y,0);} +exprlist(A) ::= expritem(X).            {A = sqlite3ExprListAppend(0,X,0);} +expritem(A) ::= expr(X).                {A = X;} +expritem(A) ::= .                       {A = 0;} + +///////////////////////////// The CREATE INDEX command /////////////////////// +// +cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D) +        ON fullname(Y) LP idxlist(Z) RP(E) onconf(R). { +  if( U!=OE_None ) U = R; +  if( U==OE_Default) U = OE_Abort; +  sqlite3CreateIndex(pParse, &X, &D, Y, Z, U, &S, &E); +} + +%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.  { +  Expr *p = 0; +  if( C.n>0 ){ +    p = sqlite3Expr(TK_COLUMN, 0, 0, 0); +    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, C.z, C.n); +  } +  A = sqlite3ExprListAppend(X, p, &Y); +} +idxlist(A) ::= idxitem(Y) collate(C) sortorder. { +  Expr *p = 0; +  if( C.n>0 ){ +    p = sqlite3Expr(TK_COLUMN, 0, 0, 0); +    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, C.z, C.n); +  } +  A = sqlite3ExprListAppend(0, p, &Y); +} +idxitem(A) ::= nm(X).              {A = X;} + + +///////////////////////////// The DROP INDEX command ///////////////////////// +// +cmd ::= DROP INDEX fullname(X).   {sqlite3DropIndex(pParse, X);} + +///////////////////////////// The VACUUM command ///////////////////////////// +// +cmd ::= VACUUM.                {sqlite3Vacuum(pParse,0);} +cmd ::= VACUUM nm.             {sqlite3Vacuum(pParse,0);} + +///////////////////////////// The PRAGMA command ///////////////////////////// +// +cmd ::= PRAGMA nm(X) dbnm(Z) EQ nm(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 plus_num(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 nm(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z).             {sqlite3Pragma(pParse,&X,&Z,0,0);} +plus_num(A) ::= plus_opt number(X).   {A = X;} +minus_num(A) ::= MINUS number(X).     {A = X;} +number(A) ::= INTEGER(X).             {A = X;} +number(A) ::= FLOAT(X).               {A = X;} +plus_opt ::= PLUS. +plus_opt ::= . + +//////////////////////////// The CREATE TRIGGER command ///////////////////// + +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 nm(B) dbnm(Z) trigger_time(C) +                    trigger_event(D) +                    ON fullname(E) foreach_clause(F) when_clause(G). { +  sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, F, G, T); +  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(OP).              {A.a = @OP; A.b = 0;} +trigger_event(A) ::= 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;} + +%type foreach_clause {int} +foreach_clause(A) ::= .                   { A = TK_ROW; } +foreach_clause(A) ::= FOR EACH ROW.       { A = TK_ROW; } +foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } + +%type when_clause {Expr*} +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(X) SEMI trigger_cmd_list(Y). { +  X->pNext = Y; +  A = X; +} +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(&X, Y, Z, R); } + +// INSERT +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F)  +                   VALUES LP itemlist(Y) RP.   +               {A = sqlite3TriggerInsertStep(&X, F, Y, 0, R);} + +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S). +               {A = sqlite3TriggerInsertStep(&X, F, 0, S, R);} + +// DELETE +trigger_cmd(A) ::= DELETE FROM nm(X) where_opt(Y). +               {A = sqlite3TriggerDeleteStep(&X, Y);} + +// SELECT +trigger_cmd(A) ::= select(X).  {A = sqlite3TriggerSelectStep(X); } + +// The special RAISE expression that may occur in trigger programs +expr(A) ::= RAISE(X) LP IGNORE RP(Y).  { +  A = sqlite3Expr(TK_RAISE, 0, 0, 0);  +  A->iColumn = OE_Ignore; +  sqlite3ExprSpan(A, &X, &Y); +} +expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  { +  A = sqlite3Expr(TK_RAISE, 0, 0, &Z);  +  A->iColumn = T; +  sqlite3ExprSpan(A, &X, &Y); +} +%type raisetype {int} +raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;} +raisetype(A) ::= ABORT.     {A = OE_Abort;} +raisetype(A) ::= FAIL.      {A = OE_Fail;} + + +////////////////////////  DROP TRIGGER statement ////////////////////////////// +cmd ::= DROP TRIGGER fullname(X). { +  sqlite3DropTrigger(pParse,X); +} + +//////////////////////// ATTACH DATABASE file AS name ///////////////////////// +cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). { +  sqlite3Attach(pParse, &F, &D, K.type, &K.key); +} +%type key_opt {struct AttachKey} +key_opt(A) ::= .                     { A.type = 0; } +key_opt(A) ::= KEY ids(X).           { A.type=1; A.key = X; } +key_opt(A) ::= KEY BLOB(X).          { A.type=2; A.key = X; } + +database_kw_opt ::= DATABASE. +database_kw_opt ::= . + +//////////////////////// DETACH DATABASE name ///////////////////////////////// +cmd ::= DETACH database_kw_opt nm(D). { +  sqlite3Detach(pParse, &D); +} diff --git a/ext/pdo_sqlite/sqlite/src/pragma.c b/ext/pdo_sqlite/sqlite/src/pragma.c new file mode 100644 index 0000000000..94a218632a --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/pragma.c @@ -0,0 +1,754 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +# include "pager.h" +# include "btree.h" +#endif + +/* +** Interpret the given string as a boolean value. +*/ +static int getBoolean(const u8 *z){ +  static const u8 *azTrue[] = { "yes", "on", "true" }; +  int i; +  if( z[0]==0 ) return 0; +  if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){ +    return atoi(z); +  } +  for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){ +    if( sqlite3StrICmp(z,azTrue[i])==0 ) return 1; +  } +  return 0; +} + +/* +** 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(u8 *z){ +  static const struct { +    const u8 *zWord; +    int val; +  } aKey[] = { +    { "no",    0 }, +    { "off",   0 }, +    { "false", 0 }, +    { "yes",   1 }, +    { "on",    1 }, +    { "true",  1 }, +    { "full",  2 }, +  }; +  int i; +  if( z[0]==0 ) return 1; +  if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){ +    return atoi(z); +  } +  for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){ +    if( sqlite3StrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val; +  } +  return 1; +} + +/* +** 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; +  } +} + +/* +** 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( db->aDb[1].pBt!=0 ){ +    if( db->flags & SQLITE_InTrans ){ +      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); +  } +  db->temp_store = ts; +  return SQLITE_OK; +} + +/* +** Generate code to return a single integer value. +*/ +static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ +  Vdbe *v = sqlite3GetVdbe(pParse); +  sqlite3VdbeAddOp(v, OP_Integer, value, 0); +  if( pParse->explain==0 ){ +    sqlite3VdbeSetNumCols(v, 1); +    sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC); +  } +  sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +} + +/* +** 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 { +    const char *zName;  /* Name of the pragma */ +    int mask;           /* Mask for the db->flags value */ +  } aPragma[] = { +    { "vdbe_trace",               SQLITE_VdbeTrace     }, +    { "sql_trace",                SQLITE_SqlTrace      }, +    { "vdbe_listing",             SQLITE_VdbeListing   }, +#if 1  /* FIX ME:  Remove the following pragmas */ +    { "full_column_names",        SQLITE_FullColNames  }, +    { "short_column_names",       SQLITE_ShortColNames }, +    { "count_changes",            SQLITE_CountRows     }, +    { "empty_result_callbacks",   SQLITE_NullCallback  }, +#endif +  }; +  int i; +  for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){ +    if( sqlite3StrICmp(zLeft, aPragma[i].zName)==0 ){ +      sqlite3 *db = pParse->db; +      Vdbe *v; +      if( zRight==0 ){ +        v = sqlite3GetVdbe(pParse); +        if( v ){ +          returnSingleInt(pParse, +               aPragma[i].zName, (db->flags&aPragma[i].mask)!=0); +        } +      }else if( getBoolean(zRight) ){ +        db->flags |= aPragma[i].mask; +      }else{ +        db->flags &= ~aPragma[i].mask; +      } +      return 1; +    } +  } +  return 0; +} + +/* +** 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 <value>, or NULL */ +  int minusFlag       /* True if a '-' sign preceded <value> */ +){ +  char *zLeft = 0;       /* Nul-terminated UTF-8 string <id> */ +  char *zRight = 0;      /* Nul-terminated UTF-8 string <value>, or NULL */ +  const char *zDb = 0;   /* The database name */ +  Token *pId;            /* Pointer to <id> token */ +  int iDb;               /* Database index for <database> */ +  sqlite3 *db = pParse->db; +  Db *pDb; +  Vdbe *v = sqlite3GetVdbe(pParse); +  if( v==0 ) return; + +  /* 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]; + +  zLeft = sqlite3NameFromToken(pId); +  if( !zLeft ) return; +  if( minusFlag ){ +    zRight = sqlite3MPrintf("-%T", pValue); +  }else{ +    zRight = sqlite3NameFromToken(pValue); +  } + +  zDb = ((iDb>0)?pDb->zName:0); +  if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ +    goto pragma_out; +  } +  +  /* +  **  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, 2,        0},  /* 0 */ +      { OP_AbsValue,    0, 0,        0}, +      { OP_Dup,         0, 0,        0}, +      { OP_Integer,     0, 0,        0}, +      { OP_Ne,          0, 6,        0}, +      { OP_Integer,     0, 0,        0},  /* 5 */ +      { OP_Callback,    1, 0,        0}, +    }; +    int addr; +    if( sqlite3ReadSchema(pParse) ) goto pragma_out; +    if( !zRight ){ +      sqlite3VdbeSetNumCols(v, 1); +      sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); +      addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); +      sqlite3VdbeChangeP1(v, addr, iDb); +      sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES); +    }else{ +      int size = atoi(zRight); +      if( size<0 ) size = -size; +      sqlite3BeginWriteOperation(pParse, 0, iDb); +      sqlite3VdbeAddOp(v, OP_Integer, size, 0); +      sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2); +      addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +      sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); +      sqlite3VdbeAddOp(v, OP_Negative, 0, 0); +      sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); +      pDb->cache_size = size; +      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->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{ +      sqlite3BtreeSetPageSize(pBt, atoi(zRight), sqlite3BtreeGetReserve(pBt)); +    } +  }else + +  /* +  **  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->cache_size); +    }else{ +      int size = atoi(zRight); +      if( size<0 ) size = -size; +      pDb->cache_size = size; +      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->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 [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; +        sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); +      } +    } +  }else + +#if 0  /* Used once during development.  No longer needed */ +  if( sqlite3StrICmp(zLeft, "trigger_overhead_test")==0 ){ +    if( getBoolean(zRight) ){ +      sqlite3_always_code_trigger_setup = 1; +    }else{ +      sqlite3_always_code_trigger_setup = 0; +    } +  }else +#endif + +  if( flagPragma(pParse, zLeft, zRight) ){ +    /* The flagPragma() subroutine also generates any necessary code +    ** there is nothing more to do here */ +  }else + +  /* +  **   PRAGMA table_info(<table>) +  ** +  ** 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; +      sqlite3VdbeSetNumCols(v, 6); +      sqlite3VdbeSetColName(v, 0, "cid", P3_STATIC); +      sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); +      sqlite3VdbeSetColName(v, 2, "type", P3_STATIC); +      sqlite3VdbeSetColName(v, 3, "notnull", P3_STATIC); +      sqlite3VdbeSetColName(v, 4, "dflt_value", P3_STATIC); +      sqlite3VdbeSetColName(v, 5, "pk", P3_STATIC); +      sqlite3ViewGetColumnNames(pParse, pTab); +      for(i=0; i<pTab->nCol; i++){ +        sqlite3VdbeAddOp(v, OP_Integer, i, 0); +        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zName, 0); +        sqlite3VdbeOp3(v, OP_String8, 0, 0, +           pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0); +        sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0); +        sqlite3VdbeOp3(v, OP_String8, 0, 0, +           pTab->aCol[i].zDflt, P3_STATIC); +        sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0); +        sqlite3VdbeAddOp(v, OP_Callback, 6, 0); +      } +    } +  }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); +      sqlite3VdbeSetColName(v, 0, "seqno", P3_STATIC); +      sqlite3VdbeSetColName(v, 1, "cid", P3_STATIC); +      sqlite3VdbeSetColName(v, 2, "name", P3_STATIC); +      for(i=0; i<pIdx->nColumn; i++){ +        int cnum = pIdx->aiColumn[i]; +        sqlite3VdbeAddOp(v, OP_Integer, i, 0); +        sqlite3VdbeAddOp(v, OP_Integer, cnum, 0); +        assert( pTab->nCol>cnum ); +        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[cnum].zName, 0); +        sqlite3VdbeAddOp(v, OP_Callback, 3, 0); +      } +    } +  }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); +        sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); +        sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); +        sqlite3VdbeSetColName(v, 2, "unique", P3_STATIC); +        while(pIdx){ +          sqlite3VdbeAddOp(v, OP_Integer, i, 0); +          sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0); +          sqlite3VdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0); +          sqlite3VdbeAddOp(v, OP_Callback, 3, 0); +          ++i; +          pIdx = pIdx->pNext; +        } +      } +    } +  }else + +  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); +        sqlite3VdbeSetColName(v, 0, "id", P3_STATIC); +        sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); +        sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); +        sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); +        sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); +        while(pFK){ +          int j; +          for(j=0; j<pFK->nCol; j++){ +            sqlite3VdbeAddOp(v, OP_Integer, i, 0); +            sqlite3VdbeAddOp(v, OP_Integer, j, 0); +            sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0); +            sqlite3VdbeOp3(v, OP_String8, 0, 0, +                             pTab->aCol[pFK->aCol[j].iFrom].zName, 0); +            sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->aCol[j].zCol, 0); +            sqlite3VdbeAddOp(v, OP_Callback, 5, 0); +          } +          ++i; +          pFK = pFK->pNextFrom; +        } +      } +    } +  }else + +  if( sqlite3StrICmp(zLeft, "database_list")==0 ){ +    int i; +    if( sqlite3ReadSchema(pParse) ) goto pragma_out; +    sqlite3VdbeSetNumCols(v, 3); +    sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); +    sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); +    sqlite3VdbeSetColName(v, 2, "file", P3_STATIC); +    for(i=0; i<db->nDb; i++){ +      if( db->aDb[i].pBt==0 ) continue; +      assert( db->aDb[i].zName!=0 ); +      sqlite3VdbeAddOp(v, OP_Integer, i, 0); +      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0); +      sqlite3VdbeOp3(v, OP_String8, 0, 0, +           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); +      sqlite3VdbeAddOp(v, OP_Callback, 3, 0); +    } +  }else + +#ifndef NDEBUG +  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ +    extern void sqlite3ParserTrace(FILE*, char *); +    if( getBoolean(zRight) ){ +      sqlite3ParserTrace(stdout, "parser: "); +    }else{ +      sqlite3ParserTrace(0, 0); +    } +  }else +#endif + +  if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){ +    int i, j, addr; + +    /* Code that initializes the integrity check program.  Set the +    ** error count 0 +    */ +    static const VdbeOpList initCode[] = { +      { OP_Integer,     0, 0,        0}, +      { OP_MemStore,    0, 1,        0}, +    }; + +    /* 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_MemLoad,     0, 0,        0}, +      { OP_Integer,     0, 0,        0}, +      { OP_Ne,          0, 0,        0},    /* 2 */ +      { OP_String8,     0, 0,        "ok"}, +      { OP_Callback,    1, 0,        0}, +    }; + +    /* Initialize the VDBE program */ +    if( sqlite3ReadSchema(pParse) ) goto pragma_out; +    sqlite3VdbeSetNumCols(v, 1); +    sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); +    sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode); + +    /* Do an integrity check on each database file */ +    for(i=0; i<db->nDb; i++){ +      HashElem *x; +      int cnt = 0; + +      sqlite3CodeVerifySchema(pParse, i); + +      /* Do an integrity check of the B-Tree +      */ +      for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ +        Table *pTab = sqliteHashData(x); +        Index *pIdx; +        sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0); +        cnt++; +        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +          if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto pragma_out; +          sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0); +          cnt++; +        } +      } +      assert( cnt>0 ); +      sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 1); +      addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC); +      sqlite3VdbeAddOp(v, OP_Eq, 0, addr+6); +      sqlite3VdbeOp3(v, OP_String8, 0, 0, +         sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), +         P3_DYNAMIC); +      sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +      sqlite3VdbeAddOp(v, OP_Concat, 0, 1); +      sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + +      /* Make sure all the indices are constructed correctly. +      */ +      sqlite3CodeVerifySchema(pParse, i); +      for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ +        Table *pTab = sqliteHashData(x); +        Index *pIdx; +        int loopTop; + +        if( pTab->pIndex==0 ) continue; +        sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); +        sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +        sqlite3VdbeAddOp(v, OP_MemStore, 1, 1); +        loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); +        sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); +        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ +          int jmp2; +          static const VdbeOpList idxErr[] = { +            { OP_MemIncr,     0,  0,  0}, +            { OP_String8,     0,  0,  "rowid "}, +            { OP_Recno,       1,  0,  0}, +            { OP_String8,     0,  0,  " missing from index "}, +            { OP_String8,     0,  0,  0},    /* 4 */ +            { OP_Concat,      2,  0,  0}, +            { OP_Callback,    1,  0,  0}, +          }; +          sqlite3GenerateIndexKey(v, pIdx, 1); +          jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0); +          addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); +          sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); +          sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v)); +        } +        sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1); +        sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v)); +        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ +          static const VdbeOpList cntIdx[] = { +             { OP_Integer,      0,  0,  0}, +             { OP_MemStore,     2,  1,  0}, +             { OP_Rewind,       0,  0,  0},  /* 2 */ +             { OP_MemIncr,      2,  0,  0}, +             { OP_Next,         0,  0,  0},  /* 4 */ +             { OP_MemLoad,      1,  0,  0}, +             { OP_MemLoad,      2,  0,  0}, +             { OP_Eq,           0,  0,  0},  /* 7 */ +             { OP_MemIncr,      0,  0,  0}, +             { OP_String8,      0,  0,  "wrong # of entries in index "}, +             { OP_String8,      0,  0,  0},  /* 10 */ +             { OP_Concat,       0,  0,  0}, +             { OP_Callback,     1,  0,  0}, +          }; +          if( pIdx->tnum==0 ) continue; +          addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); +          sqlite3VdbeChangeP1(v, addr+2, j+2); +          sqlite3VdbeChangeP2(v, addr+2, addr+5); +          sqlite3VdbeChangeP1(v, addr+4, j+2); +          sqlite3VdbeChangeP2(v, addr+4, addr+3); +          sqlite3VdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx)); +          sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC); +        } +      }  +    } +    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); +    sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode)); +  }else +  /* +  **   PRAGMA encoding +  **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" +  ** +  ** In it's 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 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 /* Filled in at run-time */ }, +      { "UTF16",    0 /* Filled in at run-time */ }, +      { 0, 0 } +    }; +    struct EncName *pEnc; +    encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE; +    if( !zRight ){    /* "PRAGMA encoding" */ +      if( sqlite3ReadSchema(pParse) ) goto pragma_out; +      sqlite3VdbeSetNumCols(v, 1); +      sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ +        if( pEnc->enc==pParse->db->enc ){ +          sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC); +          break; +        } +      } +      sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +    }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( !(pParse->db->flags&SQLITE_Initialized) ){ +        for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ +          if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ +            pParse->db->enc = pEnc->enc; +            break; +          } +        } +        if( !pEnc->zName ){ +          sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); +        } +      } +    } +  }else + +#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); +    sqlite3VdbeSetColName(v, 0, "database", P3_STATIC); +    sqlite3VdbeSetColName(v, 1, "status", P3_STATIC); +    for(i=0; i<db->nDb; i++){ +      Btree *pBt; +      Pager *pPager; +      if( db->aDb[i].zName==0 ) continue; +      sqlite3VdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, P3_STATIC); +      pBt = db->aDb[i].pBt; +      if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ +        sqlite3VdbeOp3(v, OP_String, 0, 0, "closed", P3_STATIC); +      }else{ +        int j = sqlite3pager_lockstate(pPager); +        sqlite3VdbeOp3(v, OP_String, 0, 0,  +            (j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC); +      } +      sqlite3VdbeAddOp(v, OP_Callback, 2, 0); +    } +  }else +#endif + +  {} +pragma_out: +  sqliteFree(zLeft); +  sqliteFree(zRight); +} diff --git a/ext/pdo_sqlite/sqlite/src/printf.c b/ext/pdo_sqlite/sqlite/src/printf.c new file mode 100644 index 0000000000..43e1286372 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/printf.c @@ -0,0 +1,825 @@ +/* +** 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 */ +#define etERROR      10 /* Used to indicate no such conversion type */ +/* The rest are extensions, not normally found in printf() */ +#define etCHARLIT    11 /* Literal characters.  %' */ +#define etSQLESCAPE  12 /* Strings with '\'' doubled.  %q */ +#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '', +                          NULL pointers replaced by SQL NULL.  %Q */ +#define etTOKEN      14 /* a pointer to a Token structure */ +#define etSRCLIST    15 /* a pointer to a SrcList */ +#define etPOINTER    16 /* The %p conversion */ + + +/* +** 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 */ + + +/* +** 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, 0, etSTRING,     0,  0 }, +  {  'z',  0, 2, etDYNSTRING,  0,  0 }, +  {  'q',  0, 0, etSQLESCAPE,  0,  0 }, +  {  'Q',  0, 0, etSQLESCAPE2, 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 }, +  {  'f',  0, 1, etFLOAT,      0,  0 }, +  {  'e',  0, 1, etEXP,        30, 0 }, +  {  'E',  0, 1, etEXP,        14, 0 }, +  {  'g',  0, 1, etGENERIC,    30, 0 }, +  {  'G',  0, 1, etGENERIC,    14, 0 }, +  {  '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 }, +}; +#define etNINFO  (sizeof(fmtinfo)/sizeof(fmtinfo[0])) + +/* +** If NOFLOATINGPOINT is defined, then none of the floating point +** conversions will work. +*/ +#ifndef etNOFLOATINGPOINT +/* +** "*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 + +#define etBUFSIZE 1000  /* 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 int vxprintf( +  void (*func)(void*,const char*,int),     /* Consumer of text */ +  void *arg,                         /* First argument to the consumer */ +  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 count;                 /* Total number of characters output */ +  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_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 */ +  UINT64_TYPE 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 */ +  static const char spaces[] = +   "                                                                         "; +#define etSPACESIZE (sizeof(spaces)-1) +#ifndef etNOFLOATINGPOINT +  int  exp;                  /* 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 + +  func(arg,"",0); +  count = length = 0; +  bufpt = 0; +  for(; (c=(*fmt))!=0; ++fmt){ +    if( c!='%' ){ +      int amt; +      bufpt = (char *)fmt; +      amt = 1; +      while( (c=(*++fmt))!='%' && c!=0 ) amt++; +      (*func)(arg,bufpt,amt); +      count += amt; +      if( c==0 ) break; +    } +    if( (c=(*++fmt))==0 ){ +      errorflag = 1; +      (*func)(arg,"%",1); +      count++; +      break; +    } +    /* Find out what flags are present */ +    flag_leftjustify = flag_plussign = flag_blanksign =  +     flag_alternateform = flag_zeropad = 0; +    do{ +      switch( c ){ +        case '-':   flag_leftjustify = 1;     c = 0;   break; +        case '+':   flag_plussign = 1;        c = 0;   break; +        case ' ':   flag_blanksign = 1;       c = 0;   break; +        case '#':   flag_alternateform = 1;   c = 0;   break; +        case '0':   flag_zeropad = 1;         c = 0;   break; +        default:                                       break; +      } +    }while( c==0 && (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; +        } +      } +      /* Limit the precision to prevent overflowing buf[] during conversion */ +      if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40; +    }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; +    xtype = etERROR; +    for(idx=0; idx<etNINFO; idx++){ +      if( c==fmtinfo[idx].fmttype ){ +        infop = &fmtinfo[idx]; +        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){ +          xtype = infop->type; +        } +        break; +      } +    } +    zExtra = 0; + +    /* +    ** At this point, variables are initialized as follows: +    ** +    **   flag_alternateform          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 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<width-(prefix!=0) ){ +          precision = width-(prefix!=0); +        } +        bufpt = &buf[etBUFSIZE-1]; +        { +          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 etNOFLOATINGPOINT +        if( precision<0 ) precision = 6;         /* Set default precision */ +        if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10; +        if( realvalue<0.0 ){ +          realvalue = -realvalue; +          prefix = '-'; +        }else{ +          if( flag_plussign )          prefix = '+'; +          else if( flag_blanksign )    prefix = ' '; +          else                         prefix = 0; +        } +        if( infop->type==etGENERIC && precision>0 ) precision--; +        rounder = 0.0; +#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( infop->type==etFLOAT ) realvalue += rounder; +        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ +        exp = 0; +        if( realvalue>0.0 ){ +          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 ){ +            bufpt = "NaN"; +            length = 3; +            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; +        } +        /* +        ** The "exp+precision" test causes output to be of type etEXP if +        ** the precision is too large to fit in buf[]. +        */ +        nsd = 0; +        if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){ +          flag_dp = (precision>0 || flag_alternateform); +          if( prefix ) *(bufpt++) = prefix;         /* Sign */ +          if( exp<0 )  *(bufpt++) = '0';            /* Digits before "." */ +          else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd); +          if( flag_dp ) *(bufpt++) = '.';           /* The decimal point */ +          for(exp++; exp<0 && precision>0; precision--, exp++){ +            *(bufpt++) = '0'; +          } +          while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); +          *(bufpt--) = 0;                           /* Null terminate */ +          if( flag_rtz && flag_dp ){     /* Remove trailing zeros and "." */ +            while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; +            if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; +          } +          bufpt++;                            /* point to next free slot */ +        }else{    /* etEXP or etGENERIC */ +          flag_dp = (precision>0 || flag_alternateform); +          if( prefix ) *(bufpt++) = prefix;   /* Sign */ +          *(bufpt++) = et_getdigit(&realvalue,&nsd);  /* First digit */ +          if( flag_dp ) *(bufpt++) = '.';     /* Decimal point */ +          while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); +          bufpt--;                            /* point to last digit */ +          if( flag_rtz && flag_dp ){          /* Remove tail zeros */ +            while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; +            if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; +          } +          bufpt++;                            /* point to next free slot */ +          if( exp || flag_exp ){ +            *(bufpt++) = aDigits[infop->charset]; +            if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of 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 */ +          } +        } +        /* 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*)) = count; +        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<precision; idx++) buf[idx] = c; +          length = precision; +        }else{ +          length =1; +        } +        bufpt = buf; +        break; +      case etSTRING: +      case etDYNSTRING: +        bufpt = va_arg(ap,char*); +        if( bufpt==0 ){ +          bufpt = ""; +        }else if( xtype==etDYNSTRING ){ +          zExtra = bufpt; +        } +        length = strlen(bufpt); +        if( precision>=0 && precision<length ) length = precision; +        break; +      case etSQLESCAPE: +      case etSQLESCAPE2: +        { +          int i, j, n, c, isnull; +          char *arg = va_arg(ap,char*); +          isnull = arg==0; +          if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); +          for(i=n=0; (c=arg[i])!=0; i++){ +            if( c=='\'' )  n++; +          } +          n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0); +          if( n>etBUFSIZE ){ +            bufpt = zExtra = sqliteMalloc( n ); +            if( bufpt==0 ) return -1; +          }else{ +            bufpt = buf; +          } +          j = 0; +          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; +          for(i=0; (c=arg[i])!=0; i++){ +            bufpt[j++] = c; +            if( c=='\'' ) bufpt[j++] = c; +          } +          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; +          bufpt[j] = 0; +          length = j; +          if( precision>=0 && precision<length ) length = precision; +        } +        break; +      case etTOKEN: { +        Token *pToken = va_arg(ap, Token*); +        if( pToken && pToken->z ){ +          (*func)(arg, 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 && k<pSrc->nSrc ); +        if( pItem->zDatabase && pItem->zDatabase[0] ){ +          (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase)); +          (*func)(arg, ".", 1); +        } +        (*func)(arg, pItem->zName, strlen(pItem->zName)); +        length = width = 0; +        break; +      } +      case etERROR: +        buf[0] = '%'; +        buf[1] = c; +        errorflag = 0; +        idx = 1+(c!=0); +        (*func)(arg,"%",idx); +        count += idx; +        if( c==0 ) fmt--; +        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 ){ +        count += nspace; +        while( nspace>=etSPACESIZE ){ +          (*func)(arg,spaces,etSPACESIZE); +          nspace -= etSPACESIZE; +        } +        if( nspace>0 ) (*func)(arg,spaces,nspace); +      } +    } +    if( length>0 ){ +      (*func)(arg,bufpt,length); +      count += length; +    } +    if( flag_leftjustify ){ +      register int nspace; +      nspace = width-length; +      if( nspace>0 ){ +        count += nspace; +        while( nspace>=etSPACESIZE ){ +          (*func)(arg,spaces,etSPACESIZE); +          nspace -= etSPACESIZE; +        } +        if( nspace>0 ) (*func)(arg,spaces,nspace); +      } +    } +    if( zExtra ){ +      sqliteFree(zExtra); +    } +  }/* End for loop over the format string */ +  return errorflag ? -1 : count; +} /* End of function */ + + +/* This structure is used to store state information about the +** write to memory that is currently in progress. +*/ +struct sgMprintf { +  char *zBase;     /* A base allocation */ +  char *zText;     /* The string collected so far */ +  int  nChar;      /* Length of the string so far */ +  int  nTotal;     /* Output size if unconstrained */ +  int  nAlloc;     /* Amount of space allocated in zText */ +  void *(*xRealloc)(void*,int);  /* Function used to realloc memory */ +}; + +/*  +** This function implements the callback from vxprintf.  +** +** This routine add nNewChar characters of text in zNewText to +** the sgMprintf structure pointed to by "arg". +*/ +static void mout(void *arg, const char *zNewText, int nNewChar){ +  struct sgMprintf *pM = (struct sgMprintf*)arg; +  pM->nTotal += nNewChar; +  if( pM->nChar + nNewChar + 1 > pM->nAlloc ){ +    if( pM->xRealloc==0 ){ +      nNewChar =  pM->nAlloc - pM->nChar - 1; +    }else{ +      pM->nAlloc = pM->nChar + nNewChar*2 + 1; +      if( pM->zText==pM->zBase ){ +        pM->zText = pM->xRealloc(0, pM->nAlloc); +        if( pM->zText && pM->nChar ){ +          memcpy(pM->zText, pM->zBase, pM->nChar); +        } +      }else{ +        pM->zText = pM->xRealloc(pM->zText, pM->nAlloc); +      } +    } +  } +  if( pM->zText ){ +    if( nNewChar>0 ){ +      memcpy(&pM->zText[pM->nChar], zNewText, nNewChar); +      pM->nChar += nNewChar; +    } +    pM->zText[pM->nChar] = 0; +  } +} + +/* +** This routine is a wrapper around xprintf() that invokes mout() as +** the consumer.   +*/ +static char *base_vprintf( +  void *(*xRealloc)(void*,int),   /* Routine to realloc memory. May be NULL */ +  int useInternal,                /* Use internal %-conversions if true */ +  char *zInitBuf,                 /* Initially write here, before mallocing */ +  int nInitBuf,                   /* Size of zInitBuf[] */ +  const char *zFormat,            /* format string */ +  va_list ap                      /* arguments */ +){ +  struct sgMprintf sM; +  sM.zBase = sM.zText = zInitBuf; +  sM.nChar = sM.nTotal = 0; +  sM.nAlloc = nInitBuf; +  sM.xRealloc = xRealloc; +  vxprintf(mout, &sM, useInternal, zFormat, ap); +  if( xRealloc ){ +    if( sM.zText==sM.zBase ){ +      sM.zText = xRealloc(0, sM.nChar+1); +      if( sM.zText ){ +        memcpy(sM.zText, sM.zBase, sM.nChar+1); +      } +    }else if( sM.nAlloc>sM.nChar+10 ){ +      sM.zText = xRealloc(sM.zText, sM.nChar+1); +    } +  } +  return sM.zText; +} + +/* +** Realloc that is a real function, not a macro. +*/ +static void *printf_realloc(void *old, int size){ +  return sqliteRealloc(old,size); +} + +/* +** Print into memory obtained from sqliteMalloc().  Use the internal +** %-conversion extensions. +*/ +char *sqlite3VMPrintf(const char *zFormat, va_list ap){ +  char zBase[1000]; +  return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); +} + +/* +** Print into memory obtained from sqliteMalloc().  Use the internal +** %-conversion extensions. +*/ +char *sqlite3MPrintf(const char *zFormat, ...){ +  va_list ap; +  char *z; +  char zBase[1000]; +  va_start(ap, zFormat); +  z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); +  va_end(ap); +  return z; +} + +/* +** Print into memory obtained from malloc().  Do not use the internal +** %-conversion extensions.  This routine is for use by external users. +*/ +char *sqlite3_mprintf(const char *zFormat, ...){ +  va_list ap; +  char *z; +  char zBuf[200]; + +  va_start(ap,zFormat); +  z = base_vprintf((void*(*)(void*,int))realloc, 0,  +                   zBuf, sizeof(zBuf), zFormat, ap); +  va_end(ap); +  return z; +} + +/* This is the varargs version of sqlite3_mprintf.   +*/ +char *sqlite3_vmprintf(const char *zFormat, va_list ap){ +  char zBuf[200]; +  return base_vprintf((void*(*)(void*,int))realloc, 0, +                      zBuf, sizeof(zBuf), zFormat, ap); +} + +/* +** 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; + +  va_start(ap,zFormat); +  z = base_vprintf(0, 0, zBuf, n, zFormat, ap); +  va_end(ap); +  return z; +} + +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +/* +** 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, ...){ +  extern int getpid(void); +  va_list ap; +  char zBuf[500]; +  va_start(ap, zFormat); +  base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap); +  va_end(ap); +  fprintf(stdout,"%d: %s", getpid(), zBuf); +  fflush(stdout); +} +#endif diff --git a/ext/pdo_sqlite/sqlite/src/random.c b/ext/pdo_sqlite/sqlite/src/random.c new file mode 100644 index 0000000000..de74e29158 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/random.c @@ -0,0 +1,100 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include "os.h" + + +/* +** 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_NewRecno 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. +*/ +static int randomByte(){ +  unsigned char t; + +  /* All threads share a single random number generator. +  ** This structure is the current state of the generator. +  */ +  static struct { +    unsigned char isInit;          /* True if initialized */ +    unsigned char i, j;            /* State variables */ +    unsigned char s[256];          /* State variables */ +  } prng; + +  /* 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( !prng.isInit ){ +    int i; +    char k[256]; +    prng.j = 0; +    prng.i = 0; +    sqlite3OsRandomSeed(k); +    for(i=0; i<256; i++){ +      prng.s[i] = i; +    } +    for(i=0; i<256; i++){ +      prng.j += prng.s[i] + k[i]; +      t = prng.s[prng.j]; +      prng.s[prng.j] = prng.s[i]; +      prng.s[i] = t; +    } +    prng.isInit = 1; +  } + +  /* Generate and return single random byte +  */ +  prng.i++; +  t = prng.s[prng.i]; +  prng.j += t; +  prng.s[prng.i] = prng.s[prng.j]; +  prng.s[prng.j] = t; +  t += prng.s[prng.i]; +  return prng.s[t]; +} + +/* +** Return N random bytes. +*/ +void sqlite3Randomness(int N, void *pBuf){ +  unsigned char *zBuf = pBuf; +  sqlite3OsEnterMutex(); +  while( N-- ){ +    *(zBuf++) = randomByte(); +  } +  sqlite3OsLeaveMutex(); +} + + + diff --git a/ext/pdo_sqlite/sqlite/src/select.c b/ext/pdo_sqlite/sqlite/src/select.c new file mode 100644 index 0000000000..8bee789773 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/select.c @@ -0,0 +1,2628 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" + + +/* +** Allocate a new Select structure and return a pointer to that +** structure. +*/ +Select *sqlite3SelectNew( +  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 */ +  int nLimit,           /* LIMIT value.  -1 means not used */ +  int nOffset           /* OFFSET value.  0 means no offset */ +){ +  Select *pNew; +  pNew = sqliteMalloc( sizeof(*pNew) ); +  if( pNew==0 ){ +    sqlite3ExprListDelete(pEList); +    sqlite3SrcListDelete(pSrc); +    sqlite3ExprDelete(pWhere); +    sqlite3ExprListDelete(pGroupBy); +    sqlite3ExprDelete(pHaving); +    sqlite3ExprListDelete(pOrderBy); +  }else{ +    if( pEList==0 ){ +      pEList = sqlite3ExprListAppend(0, sqlite3Expr(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; +    pNew->nLimit = nLimit; +    pNew->nOffset = nOffset; +    pNew->iLimit = -1; +    pNew->iOffset = -1; +  } +  return pNew; +} + +/* +** 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_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; +    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 }, +  }; +  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; j<sizeof(keywords)/sizeof(keywords[0]); j++){ +      if( p->n==keywords[j].nChar  +          && sqlite3StrNICmp(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; i<pTab->nCol; 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 = z; +  p->n = strlen(z); +  p->dyn = 0; +} + + +/* +** 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( +  const char *zCol,        /* Name of the column */ +  const Table *pTab1,      /* First table */ +  const Table *pTab2,      /* Second table */ +  Expr **ppExpr            /* Add the equality term to this expression */ +){ +  Token dummy; +  Expr *pE1a, *pE1b, *pE1c; +  Expr *pE2a, *pE2b, *pE2c; +  Expr *pE; + +  setToken(&dummy, zCol); +  pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy); +  pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy); +  setToken(&dummy, pTab1->zName); +  pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy); +  setToken(&dummy, pTab2->zName); +  pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy); +  pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0); +  pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0); +  pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0); +  ExprSetProperty(pE, EP_FromJoin); +  *ppExpr = sqlite3ExprAnd(*ppExpr, pE); +} + +/* +** Set the EP_FromJoin property on all terms of the given 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. +*/ +static void setJoinExpr(Expr *p){ +  while( p ){ +    ExprSetProperty(p, EP_FromJoin); +    setJoinExpr(p->pLeft); +    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; i<pSrc->nSrc-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( pLeft->jointype & JT_NATURAL ){ +      if( pLeft->pOn || pLeft->pUsing ){ +        sqlite3ErrorMsg(pParse, "a NATURAL join may not have " +           "an ON or USING clause", 0); +        return 1; +      } +      for(j=0; j<pLeftTab->nCol; j++){ +        char *zName = pLeftTab->aCol[j].zName; +        if( columnIndex(pRightTab, zName)>=0 ){ +          addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere); +        } +      } +    } + +    /* Disallow both ON and USING clauses in the same join +    */ +    if( pLeft->pOn && pLeft->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( pLeft->pOn ){ +      setJoinExpr(pLeft->pOn); +      p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn); +      pLeft->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( pLeft->pUsing ){ +      IdList *pList = pLeft->pUsing; +      for(j=0; j<pList->nId; 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(zName, pLeftTab, pRightTab, &p->pWhere); +      } +    } +  } +  return 0; +} + +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(Select *p){ +  if( p==0 ) return; +  sqlite3ExprListDelete(p->pEList); +  sqlite3SrcListDelete(p->pSrc); +  sqlite3ExprDelete(p->pWhere); +  sqlite3ExprListDelete(p->pGroupBy); +  sqlite3ExprDelete(p->pHaving); +  sqlite3ExprListDelete(p->pOrderBy); +  sqlite3SelectDelete(p->pPrior); +  sqliteFree(p->zSelect); +  sqliteFree(p); +} + +/* +** Delete the aggregate information from the parse structure. +*/ +static void sqliteAggregateInfoReset(Parse *pParse){ +  sqliteFree(pParse->aAgg); +  pParse->aAgg = 0; +  pParse->nAgg = 0; +  pParse->useAgg = 0; +} + +/* +** Insert code into "v" that will push the record on the top of the +** stack into the sorter. +*/ +static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ +  int i; +  for(i=0; i<pOrderBy->nExpr; i++){ +    sqlite3ExprCode(pParse, pOrderBy->a[i].pExpr); +  } +  sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0); +  sqlite3VdbeAddOp(v, OP_SortPut, 0, 0); +} + +/* +** Add code to implement the OFFSET and LIMIT +*/ +static void codeLimiter( +  Vdbe *v,          /* Generate code into this VM */ +  Select *p,        /* The SELECT statement being coded */ +  int iContinue,    /* Jump here to skip the current record */ +  int iBreak,       /* Jump here to end the loop */ +  int nPop          /* Number of times to pop stack when jumping */ +){ +  if( p->iOffset>=0 ){ +    int addr = sqlite3VdbeCurrentAddr(v) + 2; +    if( nPop>0 ) addr++; +    sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr); +    if( nPop>0 ){ +      sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); +    } +    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); +    VdbeComment((v, "# skip OFFSET records")); +  } +  if( p->iLimit>=0 ){ +    sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); +    VdbeComment((v, "# exit when LIMIT reached")); +  } +} + +/* +** 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 int 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 */ +  int eDest,              /* How to dispose of the results */ +  int iParm,              /* An argument to the disposal method */ +  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 */ + +  if( v==0 ) return 0; +  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 && pEList->nExpr>0; +  if( pOrderBy==0 && !hasDistinct ){ +    codeLimiter(v, p, iContinue, iBreak, 0); +  } + +  /* Pull the requested columns. +  */ +  if( nColumn>0 ){ +    for(i=0; i<nColumn; i++){ +      sqlite3VdbeAddOp(v, OP_Column, srcTab, i); +    } +  }else{ +    nColumn = pEList->nExpr; +    for(i=0; i<pEList->nExpr; i++){ +      sqlite3ExprCode(pParse, pEList->a[i].pExpr); +    } +  } + +  /* 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 ){ +#if NULL_ALWAYS_DISTINCT +    sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7); +#endif +    /* Deliberately leave the affinity string off of the following +    ** OP_MakeRecord */ +    sqlite3VdbeAddOp(v, OP_MakeRecord, pEList->nExpr * -1, 0); +    sqlite3VdbeAddOp(v, OP_Distinct, distinct, sqlite3VdbeCurrentAddr(v)+3); +    sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); +    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); +    VdbeComment((v, "# skip indistinct records")); +    sqlite3VdbeAddOp(v, OP_String8, 0, 0); +    sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0); +    if( pOrderBy==0 ){ +      codeLimiter(v, p, iContinue, iBreak, nColumn); +    } +  } + +  switch( eDest ){ +    /* In this mode, write each query result to the key of the temporary +    ** table iParm. +    */ +    case SRT_Union: { +      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); +      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); +      break; +    } + +    /* Store the result as data using a unique key. +    */ +    case SRT_Table: +    case SRT_TempTable: { +      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); +      if( pOrderBy ){ +        pushOntoSorter(pParse, v, pOrderBy); +      }else{ +        sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0); +        sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +        sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0); +      } +      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 addr; +      addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); +      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); +      sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); +      sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); +      break; +    } + +    /* 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 addr1 = sqlite3VdbeCurrentAddr(v); +      int addr2; + +      assert( nColumn==1 ); +      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3); +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); +      if( pOrderBy ){ +        pushOntoSorter(pParse, v, pOrderBy); +      }else{ +        char aff = (iParm>>16)&0xFF; +        aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); +        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1); +        sqlite3VdbeAddOp(v, OP_String8, 0, 0); +        sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); +      } +      sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v)); +      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, v, pOrderBy); +      }else{ +        sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); +        sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak); +      } +      break; +    } + +    /* Send the data to the callback function. +    */ +    case SRT_Callback: +    case SRT_Sorter: { +      if( pOrderBy ){ +        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); +        pushOntoSorter(pParse, v, pOrderBy); +      }else{ +        assert( eDest==SRT_Callback ); +        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0); +      } +      break; +    } + +    /* Invoke a subroutine to handle the results.  The subroutine itself +    ** is responsible for popping the results off of the stack. +    */ +    case SRT_Subroutine: { +      if( pOrderBy ){ +        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); +        pushOntoSorter(pParse, v, pOrderBy); +      }else{ +        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); +      } +      break; +    } + +    /* 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 ); +      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); +      break; +    } +  } +  return 0; +} + +/* +** 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,   /* The parsing context */ +  Select *p,       /* The SELECT statement */ +  Vdbe *v,         /* Generate code into this VDBE */ +  int nColumn,     /* Number of columns of data */ +  int eDest,       /* Write the sorted results here */ +  int iParm        /* Optional parameter associated with eDest */ +){ +  int end1 = sqlite3VdbeMakeLabel(v); +  int end2 = sqlite3VdbeMakeLabel(v); +  int addr; +  KeyInfo *pInfo; +  ExprList *pOrderBy; +  int nCol, i; +  sqlite3 *db = pParse->db; + +  if( eDest==SRT_Sorter ) return; +  pOrderBy = p->pOrderBy; +  nCol = pOrderBy->nExpr; +  pInfo = sqliteMalloc( sizeof(*pInfo) + nCol*(sizeof(CollSeq*)+1) ); +  if( pInfo==0 ) return; +  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol]; +  pInfo->nField = nCol; +  for(i=0; i<nCol; i++){ +    /* If a collation sequence was specified explicity, then it +    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default +    ** collation type for the expression. +    */ +    pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr); +    if( !pInfo->aColl[i] ){ +      pInfo->aColl[i] = db->pDfltColl; +    } +    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder; +  } +  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF); +  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1); +  codeLimiter(v, p, addr, end2, 1); +  switch( eDest ){ +    case SRT_Table: +    case SRT_TempTable: { +      sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0); +      sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +      sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0); +      break; +    } +    case SRT_Set: { +      assert( nColumn==1 ); +      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); +      sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +      sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); +      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC); +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); +      break; +    } +    case SRT_Mem: { +      assert( nColumn==1 ); +      sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); +      sqlite3VdbeAddOp(v, OP_Goto, 0, end1); +      break; +    } +    case SRT_Callback: +    case SRT_Subroutine: { +      int i; +      sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0); +      sqlite3VdbeAddOp(v, OP_Pull, 1, 0); +      for(i=0; i<nColumn; i++){ +        sqlite3VdbeAddOp(v, OP_Column, -1-i, i); +      } +      if( eDest==SRT_Callback ){ +        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0); +      }else{ +        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); +      } +      sqlite3VdbeAddOp(v, OP_Pop, 2, 0); +      break; +    } +    default: { +      /* Do nothing */ +      break; +    } +  } +  sqlite3VdbeAddOp(v, OP_Goto, 0, addr); +  sqlite3VdbeResolveLabel(v, end2); +  sqlite3VdbeAddOp(v, OP_Pop, 1, 0); +  sqlite3VdbeResolveLabel(v, end1); +  sqlite3VdbeAddOp(v, OP_SortReset, 0, 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. +** +** If 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 an expression is either TEXT, NUMERIC or ANY. +** The declaration type for a ROWID field is INTEGER. +*/ +static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){ +  char const *zType; +  int j; +  if( pExpr==0 || pTabList==0 ) return 0; + +  switch( pExpr->op ){ +    case TK_COLUMN: { +      Table *pTab; +      int iCol = pExpr->iColumn; +      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){} +      assert( j<pTabList->nSrc ); +      pTab = pTabList->a[j].pTab; +      if( iCol<0 ) iCol = pTab->iPKey; +      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); +      if( iCol<0 ){ +        zType = "INTEGER"; +      }else{ +        zType = pTab->aCol[iCol].zType; +      } +      break; +    } +    case TK_AS: +      zType = columnType(pParse, pTabList, pExpr->pLeft);  +      break; +    case TK_SELECT: { +      Select *pS = pExpr->pSelect; +      zType = columnType(pParse, pS->pSrc, pS->pEList->a[0].pExpr);  +      break; +    } +    default: +      zType = 0; +  } +   +  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; +  for(i=0; i<pEList->nExpr; i++){ +    Expr *p = pEList->a[i].pExpr; +    const char *zType = columnType(pParse, pTabList, p); +    if( zType==0 ) continue; +    /* The vdbe must make it's own copy of the column-type, in case the  +    ** schema is reset before this virtual machine is deleted. +    */ +    sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType)); +  } +} + +/* +** 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; + +  /* If this is an EXPLAIN, skip this step */ +  if( pParse->explain ){ +    return; +  } + +  assert( v!=0 ); +  if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; +  pParse->colNamesSet = 1; +  fullNames = (db->flags & SQLITE_FullColNames)!=0; +  shortNames = (db->flags & SQLITE_ShortColNames)!=0; +  sqlite3VdbeSetNumCols(v, pEList->nExpr); +  for(i=0; i<pEList->nExpr; 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, zName, strlen(zName)); +      continue; +    } +    if( p->op==TK_COLUMN && pTabList ){ +      Table *pTab; +      char *zCol; +      int iCol = p->iColumn; +      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){} +      assert( j<pTabList->nSrc ); +      pTab = pTabList->a[j].pTab; +      if( iCol<0 ) iCol = pTab->iPKey; +      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); +      if( iCol<0 ){ +        zCol = "_ROWID_"; +      }else{ +        zCol = pTab->aCol[iCol].zName; +      } +      if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ +        sqlite3VdbeSetColName(v, i, 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, 0); +        sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); +      }else{ +        sqlite3VdbeSetColName(v, i, zCol, 0); +      } +    }else if( p->span.z && p->span.z[0] ){ +      sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); +      /* sqlite3VdbeCompressSpace(v, addr); */ +    }else{ +      char zName[30]; +      assert( p->op!=TK_COLUMN || pTabList==0 ); +      sprintf(zName, "column%d", i+1); +      sqlite3VdbeSetColName(v, i, zName, 0); +    } +  } +  generateColumnTypes(pParse, pTabList, pEList); +} + +/* +** 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; +} + +/* +** Forward declaration +*/ +static int fillInColumnList(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; + +  if( fillInColumnList(pParse, pSelect) ){ +    return 0; +  } +  pTab = sqliteMalloc( sizeof(Table) ); +  if( pTab==0 ){ +    return 0; +  } +  pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; +  pEList = pSelect->pEList; +  pTab->nCol = pEList->nExpr; +  assert( pTab->nCol>0 ); +  pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); +  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ +    Expr *pR; +    char *zType; +    char *zName; +    Expr *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 ){ +      zName = sqliteStrDup(zName); +    }else if( p->op==TK_DOT  +               && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ +      int cnt; +      zName = sqlite3MPrintf("%T", &pR->token); +      for(j=cnt=0; j<i; j++){ +        if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ +          sqliteFree(zName); +          zName = sqlite3MPrintf("%T_%d", &pR->token, ++cnt); +          j = -1; +        } +      } +    }else if( p->span.z && p->span.z[0] ){ +      zName = sqlite3MPrintf("%T", &p->span); +    }else{ +      zName = sqlite3MPrintf("column%d", i+1); +    } +    sqlite3Dequote(zName); +    pCol->zName = zName; + +    zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p)); +    pCol->zType = zType; +    pCol->affinity = SQLITE_AFF_NUMERIC; +    if( zType ){ +      pCol->affinity = sqlite3AffinityType(zType, strlen(zType)); +    } +    pCol->pColl = sqlite3ExprCollSeq(pParse, p); +    if( !pCol->pColl ){ +      pCol->pColl = pParse->db->pDfltColl; +    } +  } +  pTab->iPKey = -1; +  return pTab; +} + +/* +** For the given SELECT statement, do three things. +** +**    (1)  Fill in the pTabList->a[].pTab fields in the SrcList that  +**         defines the set of tables that should be scanned.  For views, +**         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. +** +**    (2)  Add terms to the WHERE clause to accomodate the NATURAL keyword +**         on joins and the ON and USING clause of joins. +** +**    (3)  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 fillInColumnList(Parse *pParse, Select *p){ +  int i, j, k, rc; +  SrcList *pTabList; +  ExprList *pEList; +  Table *pTab; +  struct SrcList_item *pFrom; + +  if( p==0 || p->pSrc==0 ) return 1; +  pTabList = p->pSrc; +  pEList = p->pEList; + +  /* Look up every table in the table list. +  */ +  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ +    if( pFrom->pTab ){ +      /* This routine has run before!  No need to continue */ +      return 0; +    } +    if( pFrom->zName==0 ){ +      /* A sub-query in the FROM clause of a SELECT */ +      assert( pFrom->pSelect!=0 ); +      if( pFrom->zAlias==0 ){ +        pFrom->zAlias = +          sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); +      } +      pFrom->pTab = pTab =  +        sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); +      if( pTab==0 ){ +        return 1; +      } +      /* The isTransient 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->isTransient = 1; +    }else{ +      /* An ordinary table or view name in the FROM clause */ +      pFrom->pTab = pTab =  +        sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); +      if( pTab==0 ){ +        return 1; +      } +      if( pTab->pSelect ){ +        /* 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(pTab->pSelect); +        } +      } +    } +  } + +  /* 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; k<pEList->nExpr; 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( k<pEList->nExpr ){ +    /* +    ** 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; +    for(k=0; k<pEList->nExpr; 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(pNew, a[k].pExpr, 0); +        pNew->a[pNew->nExpr-1].zName = a[k].zName; +        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(&pE->pLeft->token); +        }else{ +          zTName = 0; +        } +        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; 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; j<pTab->nCol; j++){ +            Expr *pExpr, *pLeft, *pRight; +            char *zName = pTab->aCol[j].zName; + +            if( i>0 ){ +              struct SrcList_item *pLeft = &pTabList->a[i-1]; +              if( (pLeft->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->pUsing, zName)>=0 ){ +                /* In a join with a USING clause, omit columns in the +                ** using clause from the table on the right. */ +                continue; +              } +            } +            pRight = sqlite3Expr(TK_ID, 0, 0, 0); +            if( pRight==0 ) break; +            setToken(&pRight->token, zName); +            if( zTabName && pTabList->nSrc>1 ){ +              pLeft = sqlite3Expr(TK_ID, 0, 0, 0); +              pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); +              if( pExpr==0 ) break; +              setToken(&pLeft->token, zTabName); +              setToken(&pExpr->span, sqlite3MPrintf("%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; +            } +            pNew = sqlite3ExprListAppend(pNew, pExpr, 0); +          } +        } +        if( !tableSeen ){ +          if( zTName ){ +            sqlite3ErrorMsg(pParse, "no such table: %s", zTName); +          }else{ +            sqlite3ErrorMsg(pParse, "no tables specified"); +          } +          rc = 1; +        } +        sqliteFree(zTName); +      } +    } +    sqlite3ExprListDelete(pEList); +    p->pEList = pNew; +  } +  return rc; +} + +/* +** This routine recursively unlinks the Select.pSrc.a[].pTab pointers +** in a select structure.  It just sets the pointers to NULL.  This +** routine is recursive in the sense that if the Select.pSrc.a[].pSelect +** pointer is not NULL, this routine is called recursively on that pointer. +** +** This routine is called on the Select structure that defines a +** VIEW in order to undo any bindings to tables.  This is necessary +** because those tables might be DROPed by a subsequent SQL command. +** If the bindings are not removed, then the Select.pSrc->a[].pTab field +** will be left pointing to a deallocated Table structure after the +** DROP and a coredump will occur the next time the VIEW is used. +*/ +void sqlite3SelectUnbind(Select *p){ +  int i; +  SrcList *pSrc = p->pSrc; +  struct SrcList_item *pItem; +  Table *pTab; +  if( p==0 ) return; +  for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ +    if( (pTab = pItem->pTab)!=0 ){ +      if( pTab->isTransient ){ +        sqlite3DeleteTable(0, pTab); +      } +      pItem->pTab = 0; +      if( pItem->pSelect ){ +        sqlite3SelectUnbind(pItem->pSelect); +      } +    } +  } +} + +/* +** This routine associates entries in an ORDER BY expression list with +** columns in a result.  For each ORDER BY expression, the opcode of +** the top-level node is changed to TK_COLUMN and the iColumn value of +** the top-level node is filled in with column number and the iTable +** value of the top-level node is filled with iTable parameter. +** +** If there are prior SELECT clauses, they are processed first.  A match +** in an earlier SELECT takes precedence over a later SELECT. +** +** Any entry that does not match is flagged as an error.  The number +** of errors is returned. +*/ +static int matchOrderbyToColumn( +  Parse *pParse,          /* A place to leave error messages */ +  Select *pSelect,        /* Match to result columns of this SELECT */ +  ExprList *pOrderBy,     /* The ORDER BY values to match against columns */ +  int iTable,             /* Insert this value in iTable */ +  int mustComplete        /* If TRUE all ORDER BYs must match */ +){ +  int nErr = 0; +  int i, j; +  ExprList *pEList; + +  if( pSelect==0 || pOrderBy==0 ) return 1; +  if( mustComplete ){ +    for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } +  } +  if( fillInColumnList(pParse, pSelect) ){ +    return 1; +  } +  if( pSelect->pPrior ){ +    if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ +      return 1; +    } +  } +  pEList = pSelect->pEList; +  for(i=0; i<pOrderBy->nExpr; i++){ +    Expr *pE = pOrderBy->a[i].pExpr; +    int iCol = -1; +    if( pOrderBy->a[i].done ) continue; +    if( sqlite3ExprIsInteger(pE, &iCol) ){ +      if( iCol<=0 || iCol>pEList->nExpr ){ +        sqlite3ErrorMsg(pParse, +          "ORDER BY position %d should be between 1 and %d", +          iCol, pEList->nExpr); +        nErr++; +        break; +      } +      if( !mustComplete ) continue; +      iCol--; +    } +    for(j=0; iCol<0 && j<pEList->nExpr; j++){ +      if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){ +        char *zName, *zLabel; +        zName = pEList->a[j].zName; +        zLabel = sqlite3NameFromToken(&pE->token); +        assert( zLabel!=0 ); +        if( sqlite3StrICmp(zName, zLabel)==0 ){  +          iCol = j; +        } +        sqliteFree(zLabel); +      } +      if( iCol<0 && sqlite3ExprCompare(pE, pEList->a[j].pExpr) ){ +        iCol = j; +      } +    } +    if( iCol>=0 ){ +      pE->op = TK_COLUMN; +      pE->iColumn = iCol; +      pE->iTable = iTable; +      pOrderBy->a[i].done = 1; +    } +    if( iCol<0 && mustComplete ){ +      sqlite3ErrorMsg(pParse, +        "ORDER BY term number %d does not match any result column", i+1); +      nErr++; +      break; +    } +  } +  return nErr;   +} + +/* +** 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); +  } +  return v; +} + +/* +** Compute the iLimit and iOffset fields of the SELECT based on the +** nLimit and nOffset fields.  nLimit and nOffset hold the integers +** that appear in the original SQL statement after the LIMIT and OFFSET +** keywords.  Or that hold -1 and 0 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 if iLimit and iOffset only if +** a limit or offset is defined by nLimit and nOffset.  iLimit and +** iOffset should have been preset to appropriate default values +** (usually but not always -1) prior to calling this routine. +** Only if nLimit>=0 or nOffset>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){ +  /*  +  ** If the comparison is p->nLimit>0 then "LIMIT 0" shows +  ** all rows.  It is the same as no limit. If the comparision is +  ** p->nLimit>=0 then "LIMIT 0" show no rows at all. +  ** "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->nLimit>=0 ){ +    int iMem = pParse->nMem++; +    Vdbe *v = sqlite3GetVdbe(pParse); +    if( v==0 ) return; +    sqlite3VdbeAddOp(v, OP_Integer, -p->nLimit, 0); +    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); +    VdbeComment((v, "# LIMIT counter")); +    p->iLimit = iMem; +  } +  if( p->nOffset>0 ){ +    int iMem = pParse->nMem++; +    Vdbe *v = sqlite3GetVdbe(pParse); +    if( v==0 ) return; +    sqlite3VdbeAddOp(v, OP_Integer, -p->nOffset, 0); +    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); +    VdbeComment((v, "# OFFSET counter")); +    p->iOffset = iMem; +  } +} + +/* +** Generate VDBE instructions that will open a transient table that +** will be used for an index or to store keyed results for a compound +** select.  In other words, open a transient table that needs a +** KeyInfo structure.  The number of columns in the KeyInfo is determined +** by the result set of the SELECT statement in the second argument. +** +** Specifically, this routine is called to open an index table for +** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not  +** UNION ALL). +** +** Make the new table a KeyAsData table if keyAsData is true. +** +** The value returned is the address of the OP_OpenTemp instruction. +*/ +static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){ +  KeyInfo *pKeyInfo; +  int nColumn; +  sqlite3 *db = pParse->db; +  int i; +  Vdbe *v = pParse->pVdbe; +  int addr; + +  if( fillInColumnList(pParse, p) ){ +    return 0; +  } +  nColumn = p->pEList->nExpr; +  pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) ); +  if( pKeyInfo==0 ) return 0; +  pKeyInfo->enc = db->enc; +  pKeyInfo->nField = nColumn; +  for(i=0; i<nColumn; i++){ +    pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); +    if( !pKeyInfo->aColl[i] ){ +      pKeyInfo->aColl[i] = db->pDfltColl; +    } +  } +  addr = sqlite3VdbeOp3(v, OP_OpenTemp, iTab, 0,  +      (char*)pKeyInfo, P3_KEYINFO_HANDOFF); +  if( keyAsData ){ +    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); +  } +  return addr; +} + +/* +** Add the address "addr" to the set of all OpenTemp opcode addresses +** that are being accumulated in p->ppOpenTemp. +*/ +static int multiSelectOpenTempAddr(Select *p, int addr){ +  IdList *pList = *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0); +  if( pList==0 ){ +    return SQLITE_NOMEM; +  } +  pList->a[pList->nId-1].idx = addr; +  return SQLITE_OK; +} + +/* +** 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; +} + +/* +** 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 */ +  int eDest,            /* \___  Store query results as specified */ +  int iParm,            /* /     by these two parameters.         */ +  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 */ +  IdList *pOpenTemp = 0;/* OP_OpenTemp opcodes that need a KeyInfo */ +  int aAddr[5];         /* Addresses of SetNumColumns operators */ +  int nAddr = 0;        /* Number used */ +  int nCol;             /* Number of columns in the result set */ + +  /* 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; +  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->nLimit>=0 || pPrior->nOffset>0 ){ +    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; +  } + +  /* If *p this is the right-most select statement, then initialize +  ** p->ppOpenTemp to point to pOpenTemp.  If *p is not the right most +  ** statement then p->ppOpenTemp will have already been initialized +  ** by a prior call to this same procedure.  Pass along the pOpenTemp +  ** pointer to pPrior, the next statement to our left. +  */ +  if( p->ppOpenTemp==0 ){ +    p->ppOpenTemp = &pOpenTemp; +  } +  pPrior->ppOpenTemp = p->ppOpenTemp; + +  /* Create the destination temporary table if necessary +  */ +  if( eDest==SRT_TempTable ){ +    assert( p->pEList ); +    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); +    assert( nAddr==0 ); +    aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 0); +    eDest = SRT_Table; +  } + +  /* Generate code for the left and right SELECT statements. +  */ +  switch( p->op ){ +    case TK_ALL: { +      if( p->pOrderBy==0 ){ +        pPrior->nLimit = p->nLimit; +        pPrior->nOffset = p->nOffset; +        rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); +        if( rc ){ +          goto multi_select_end; +        } +        p->pPrior = 0; +        p->iLimit = pPrior->iLimit; +        p->iOffset = pPrior->iOffset; +        p->nLimit = -1; +        p->nOffset = 0; +        rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); +        p->pPrior = pPrior; +        if( rc ){ +          goto multi_select_end; +        } +        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 */ +      int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */ +      ExprList *pOrderBy;  /* The ORDER BY clause for the right SELECT */ +      int addr; + +      priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; +      if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){ +        /* We can reuse a temporary table generated by a SELECT to our +        ** right. +        */ +        unionTab = iParm; +      }else{ +        /* We will need to create our own temporary table to hold the +        ** intermediate results. +        */ +        unionTab = pParse->nTab++; +        if( p->pOrderBy  +        && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ +          rc = 1; +          goto multi_select_end; +        } +        addr = sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 0); +        if( p->op!=TK_ALL ){ +          rc = multiSelectOpenTempAddr(p, addr); +          if( rc!=SQLITE_OK ){ +            goto multi_select_end; +          } +          sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1); +        } +	assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); +        aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0); +        assert( p->pEList ); +      } + +      /* Code the SELECT statements to our left +      */ +      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 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; +      pOrderBy = p->pOrderBy; +      p->pOrderBy = 0; +      nLimit = p->nLimit; +      p->nLimit = -1; +      nOffset = p->nOffset; +      p->nOffset = 0; +      rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff); +      p->pPrior = pPrior; +      p->pOrderBy = pOrderBy; +      p->nLimit = nLimit; +      p->nOffset = nOffset; +      if( rc ){ +        goto multi_select_end; +      } + + +      /* Convert the data in the temporary table into whatever form +      ** it is that we currently need. +      */       +      if( eDest!=priorOp || unionTab!=iParm ){ +        int iCont, iBreak, iStart; +        assert( p->pEList ); +        if( eDest==SRT_Callback ){ +          generateColumnNames(pParse, 0, p->pEList); +        } +        iBreak = sqlite3VdbeMakeLabel(v); +        iCont = sqlite3VdbeMakeLabel(v); +        sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); +        computeLimitRegisters(pParse, p); +        iStart = sqlite3VdbeCurrentAddr(v); +        rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, +                             p->pOrderBy, -1, eDest, iParm,  +                             iCont, iBreak, 0); +        if( rc ){ +          rc = 1; +          goto multi_select_end; +        } +        sqlite3VdbeResolveLabel(v, iCont); +        sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart); +        sqlite3VdbeResolveLabel(v, iBreak); +        sqlite3VdbeAddOp(v, OP_Close, unionTab, 0); +      } +      break; +    } +    case TK_INTERSECT: { +      int tab1, tab2; +      int iCont, iBreak, iStart; +      int nLimit, nOffset; +      int addr; + +      /* 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( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ +        rc = 1; +        goto multi_select_end; +      } + +      addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab1, 0); +      rc = multiSelectOpenTempAddr(p, addr); +      if( rc!=SQLITE_OK ){ +        goto multi_select_end; +      } +      sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); +      assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); +      aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0); +      assert( p->pEList ); + +      /* Code the SELECTs to our left into temporary table "tab1". +      */ +      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); +      if( rc ){ +        goto multi_select_end; +      } + +      /* Code the current SELECT into temporary table "tab2" +      */ +      addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab2, 0); +      rc = multiSelectOpenTempAddr(p, addr); +      if( rc!=SQLITE_OK ){ +        goto multi_select_end; +      } +      sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1); +      assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); +      aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0); +      p->pPrior = 0; +      nLimit = p->nLimit; +      p->nLimit = -1; +      nOffset = p->nOffset; +      p->nOffset = 0; +      rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff); +      p->pPrior = pPrior; +      p->nLimit = nLimit; +      p->nOffset = nOffset; +      if( rc ){ +        goto multi_select_end; +      } + +      /* Generate code to take the intersection of the two temporary +      ** tables. +      */ +      assert( p->pEList ); +      if( eDest==SRT_Callback ){ +        generateColumnNames(pParse, 0, p->pEList); +      } +      iBreak = sqlite3VdbeMakeLabel(v); +      iCont = sqlite3VdbeMakeLabel(v); +      sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); +      computeLimitRegisters(pParse, p); +      iStart = sqlite3VdbeAddOp(v, OP_FullKey, tab1, 0); +      sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); +      rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, +                             p->pOrderBy, -1, eDest, iParm,  +                             iCont, iBreak, 0); +      if( rc ){ +        rc = 1; +        goto multi_select_end; +      } +      sqlite3VdbeResolveLabel(v, iCont); +      sqlite3VdbeAddOp(v, OP_Next, tab1, iStart); +      sqlite3VdbeResolveLabel(v, iBreak); +      sqlite3VdbeAddOp(v, OP_Close, tab2, 0); +      sqlite3VdbeAddOp(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( nAddr>0 ){ +    nAddr--; +    sqlite3VdbeChangeP2(v, aAddr[nAddr], 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( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){ +    int i;                        /* Loop counter */ +    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */ + +    assert( p->ppOpenTemp == &pOpenTemp ); +    pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*)); +    if( !pKeyInfo ){ +      rc = SQLITE_NOMEM; +      goto multi_select_end; +    } + +    pKeyInfo->enc = pParse->db->enc; +    pKeyInfo->nField = nCol; + +    for(i=0; i<nCol; i++){ +      pKeyInfo->aColl[i] = multiSelectCollSeq(pParse, p, i); +      if( !pKeyInfo->aColl[i] ){ +        pKeyInfo->aColl[i] = pParse->db->pDfltColl; +      } +    } + +    for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){ +      int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO); +      int addr = pOpenTemp->a[i].idx; +      sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type); +    } + +    if( p->pOrderBy ){ +      struct ExprList_item *pOrderByTerm = p->pOrderBy->a; +      for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ +        Expr *pExpr = pOrderByTerm->pExpr; +        char *zName = pOrderByTerm->zName; +        assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); +        assert( !pExpr->pColl ); +        if( zName ){ +          pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1); +        }else{ +          pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn]; +        } +      } +      generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); +    } + +    if( !pOpenTemp ){ +      /* This happens for UNION ALL ... ORDER BY */ +      sqliteFree(pKeyInfo); +    } +  } + +multi_select_end: +  if( pOpenTemp ){ +    sqlite3IdListDelete(pOpenTemp); +  } +  p->ppOpenTemp = 0; +  return rc; +} + +/* +** 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 substExprList(ExprList*,int,ExprList*);  /* Forward Decl */ +static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ +  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->iColumn<pEList->nExpr ); +      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(pNew->pLeft); +      assert( pExpr->pRight==0 ); +      pExpr->pRight = sqlite3ExprDup(pNew->pRight); +      assert( pExpr->pList==0 ); +      pExpr->pList = sqlite3ExprListDup(pNew->pList); +      pExpr->iTable = pNew->iTable; +      pExpr->iColumn = pNew->iColumn; +      pExpr->iAgg = pNew->iAgg; +      sqlite3TokenCopy(&pExpr->token, &pNew->token); +      sqlite3TokenCopy(&pExpr->span, &pNew->span); +    } +  }else{ +    substExpr(pExpr->pLeft, iTable, pEList); +    substExpr(pExpr->pRight, iTable, pEList); +    substExprList(pExpr->pList, iTable, pEList); +  } +} +static void  +substExprList(ExprList *pList, int iTable, ExprList *pEList){ +  int i; +  if( pList==0 ) return; +  for(i=0; i<pList->nExpr; i++){ +    substExpr(pList->a[i].pExpr, iTable, pEList); +  } +} + +/* +** 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) +** +** 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( +  Parse *pParse,       /* The parsing context */ +  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 && iFrom<pSrc->nSrc ); +  pSubitem = &pSrc->a[iFrom]; +  pSub = pSubitem->pSelect; +  assert( pSub!=0 ); +  if( isAgg && subqueryIsAgg ) return 0; +  if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; +  pSubSrc = pSub->pSrc; +  assert( pSubSrc ); +  if( pSubSrc->nSrc==0 ) return 0; +  if( (pSub->isDistinct || pSub->nLimit>=0) &&  (pSrc->nSrc>1 || isAgg) ){ +     return 0; +  } +  if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0; +  if( p->pOrderBy && pSub->pOrderBy ) return 0; + +  /* 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 && iFrom>0 && (pSrc->a[iFrom-1].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( iFrom>0 && (pSrc->a[iFrom-1].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; +    Table *pTab = pSubitem->pTab; + +    if( pTab && pTab->isTransient ){ +      sqlite3DeleteTable(0, pSubitem->pTab); +    } +    sqliteFree(pSubitem->zDatabase); +    sqliteFree(pSubitem->zName); +    sqliteFree(pSubitem->zAlias); +    if( nSubSrc>1 ){ +      int extra = nSubSrc - 1; +      for(i=1; i<nSubSrc; i++){ +        pSrc = sqlite3SrcListAppend(pSrc, 0, 0); +      } +      p->pSrc = pSrc; +      for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ +        pSrc->a[i] = pSrc->a[i-extra]; +      } +    } +    for(i=0; i<nSubSrc; i++){ +      pSrc->a[i+iFrom] = pSubSrc->a[i]; +      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); +    } +    pSrc->a[iFrom+nSubSrc-1].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". +  */ +  substExprList(p->pEList, iParent, pSub->pEList); +  pList = p->pEList; +  for(i=0; i<pList->nExpr; i++){ +    Expr *pExpr; +    if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ +      pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); +    } +  } +  if( isAgg ){ +    substExprList(p->pGroupBy, iParent, pSub->pEList); +    substExpr(p->pHaving, iParent, pSub->pEList); +  } +  if( pSub->pOrderBy ){ +    assert( p->pOrderBy==0 ); +    p->pOrderBy = pSub->pOrderBy; +    pSub->pOrderBy = 0; +  }else if( p->pOrderBy ){ +    substExprList(p->pOrderBy, iParent, pSub->pEList); +  } +  if( pSub->pWhere ){ +    pWhere = sqlite3ExprDup(pSub->pWhere); +  }else{ +    pWhere = 0; +  } +  if( subqueryIsAgg ){ +    assert( p->pHaving==0 ); +    p->pHaving = p->pWhere; +    p->pWhere = pWhere; +    substExpr(p->pHaving, iParent, pSub->pEList); +    p->pHaving = sqlite3ExprAnd(p->pHaving, sqlite3ExprDup(pSub->pHaving)); +    assert( p->pGroupBy==0 ); +    p->pGroupBy = sqlite3ExprListDup(pSub->pGroupBy); +  }else{ +    substExpr(p->pWhere, iParent, pSub->pEList); +    p->pWhere = sqlite3ExprAnd(p->pWhere, pWhere); +  } + +  /* The flattened query is distinct if either the inner or the +  ** outer query is distinct.  +  */ +  p->isDistinct = p->isDistinct || pSub->isDistinct; + +  /* Transfer the limit expression from the subquery to the outer +  ** query. +  */ +  if( pSub->nLimit>=0 ){ +    if( p->nLimit<0 ){ +      p->nLimit = pSub->nLimit; +    }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){ +      p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset; +    } +  } +  p->nOffset += pSub->nOffset; + +  /* Finially, delete what is left of the subquery and return +  ** success. +  */ +  sqlite3SelectDelete(pSub); +  return 1; +} + +/* +** Analyze the SELECT statement passed in as an argument to see if it +** is a simple min() or max() query.  If it is and this query can be +** satisfied using a single seek to the beginning or end of an index, +** then generate the code for this SELECT and return 1.  If this is not a  +** simple min() or max() query, then return 0; +** +** A simply min() or max() query looks like this: +** +**    SELECT min(a) FROM table; +**    SELECT max(a) FROM table; +** +** The query may have only a single table in its FROM argument.  There +** can be no GROUP BY or HAVING or WHERE clauses.  The result set must +** be the min() or max() of a single column of the table.  The column +** in the min() or max() function must be indexed. +** +** The parameters to this routine are the same as for sqlite3Select(). +** See the header comment on that routine for additional information. +*/ +static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ +  Expr *pExpr; +  int iCol; +  Table *pTab; +  Index *pIdx; +  int base; +  Vdbe *v; +  int seekOp; +  int cont; +  ExprList *pEList, *pList, eList; +  struct ExprList_item eListItem; +  SrcList *pSrc; +   + +  /* Check to see if this query is a simple min() or max() query.  Return +  ** zero if it is  not. +  */ +  if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; +  pSrc = p->pSrc; +  if( pSrc->nSrc!=1 ) return 0; +  pEList = p->pEList; +  if( pEList->nExpr!=1 ) return 0; +  pExpr = pEList->a[0].pExpr; +  if( pExpr->op!=TK_AGG_FUNCTION ) return 0; +  pList = pExpr->pList; +  if( pList==0 || pList->nExpr!=1 ) return 0; +  if( pExpr->token.n!=3 ) return 0; +  if( sqlite3StrNICmp(pExpr->token.z,"min",3)==0 ){ +    seekOp = OP_Rewind; +  }else if( sqlite3StrNICmp(pExpr->token.z,"max",3)==0 ){ +    seekOp = OP_Last; +  }else{ +    return 0; +  } +  pExpr = pList->a[0].pExpr; +  if( pExpr->op!=TK_COLUMN ) return 0; +  iCol = pExpr->iColumn; +  pTab = pSrc->a[0].pTab; + +  /* If we get to here, it means the query is of the correct form. +  ** Check to make sure we have an index and make pIdx point to the +  ** appropriate index.  If the min() or max() is on an INTEGER PRIMARY +  ** key column, no index is necessary so set pIdx to NULL.  If no +  ** usable index is found, return 0. +  */ +  if( iCol<0 ){ +    pIdx = 0; +  }else{ +    CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); +    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +      assert( pIdx->nColumn>=1 ); +      if( pIdx->aiColumn[0]==iCol && pIdx->keyInfo.aColl[0]==pColl ) break; +    } +    if( pIdx==0 ) return 0; +  } + +  /* Identify column types if we will be using the callback.  This +  ** step is skipped if the output is going to a table or a memory cell. +  ** The column names have already been generated in the calling function. +  */ +  v = sqlite3GetVdbe(pParse); +  if( v==0 ) return 0; + +  /* If the output is destined for a temporary table, open that table. +  */ +  if( eDest==SRT_TempTable ){ +    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 1); +  } + +  /* Generating code to find the min or the max.  Basically all we have +  ** to do is find the first or the last entry in the chosen index.  If +  ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first +  ** or last entry in the main table. +  */ +  sqlite3CodeVerifySchema(pParse, pTab->iDb); +  base = pSrc->a[0].iCursor; +  computeLimitRegisters(pParse, p); +  if( pSrc->a[0].pSelect==0 ){ +    sqlite3OpenTableForReading(v, base, pTab); +  } +  cont = sqlite3VdbeMakeLabel(v); +  if( pIdx==0 ){ +    sqlite3VdbeAddOp(v, seekOp, base, 0); +  }else{ +    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); +    sqlite3VdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, +                   (char*)&pIdx->keyInfo, P3_KEYINFO); +    if( seekOp==OP_Rewind ){ +      sqlite3VdbeAddOp(v, OP_String, 0, 0); +      sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0); +      seekOp = OP_MoveGt; +    } +    sqlite3VdbeAddOp(v, seekOp, base+1, 0); +    sqlite3VdbeAddOp(v, OP_IdxRecno, base+1, 0); +    sqlite3VdbeAddOp(v, OP_Close, base+1, 0); +    sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); +  } +  eList.nExpr = 1; +  memset(&eListItem, 0, sizeof(eListItem)); +  eList.a = &eListItem; +  eList.a[0].pExpr = pExpr; +  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); +  sqlite3VdbeResolveLabel(v, cont); +  sqlite3VdbeAddOp(v, OP_Close, base, 0); +   +  return 1; +} + +/* +** Analyze and ORDER BY or GROUP BY clause in a SELECT statement.  Return +** the number of errors seen. +** +** An ORDER BY or GROUP BY is a list of expressions.  If any expression +** is an integer constant, then that expression is replaced by the +** corresponding entry in the result set. +*/ +static int processOrderGroupBy( +  Parse *pParse,        /* Parsing context */ +  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */ +  SrcList *pTabList,    /* The FROM clause */ +  ExprList *pEList,     /* The result set */ +  int isAgg,            /* True if aggregate functions are involved */ +  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */ +){ +  int i; +  if( pOrderBy==0 ) return 0; +  for(i=0; i<pOrderBy->nExpr; i++){ +    int iCol; +    Expr *pE = pOrderBy->a[i].pExpr; +    if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ +      sqlite3ExprDelete(pE); +      pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); +    } +    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){ +      return 1; +    } +    if( sqlite3ExprIsConstant(pE) ){ +      if( sqlite3ExprIsInteger(pE, &iCol)==0 ){ +        sqlite3ErrorMsg(pParse, +          "%s BY terms must not be non-integer constants", zType); +        return 1; +      }else if( iCol<=0 || iCol>pEList->nExpr ){ +        sqlite3ErrorMsg(pParse,  +           "%s BY column number %d out of range - should be " +           "between 1 and %d", zType, iCol, pEList->nExpr); +        return 1; +      } +    } +  } +  return 0; +} + +/* +** Generate code for the given SELECT statement. +** +** The results are distributed in various ways depending on the +** value of eDest and iParm. +** +**     eDest Value       Result +**     ------------    ------------------------------------------- +**     SRT_Callback    Invoke the callback for each row of the result. +** +**     SRT_Mem         Store first result in memory cell iParm +** +**     SRT_Set         Store results as keys of table iParm. +** +**     SRT_Union       Store results as a key in a temporary table iParm +** +**     SRT_Except      Remove results from the temporary table iParm. +** +**     SRT_Table       Store results in temporary table iParm +** +** The table above is incomplete.  Additional eDist value have be added +** since this comment was written.  See the selectInnerLoop() function for +** a complete 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. */ +  int eDest,             /* How to dispose of the results */ +  int iParm,             /* A parameter used by the eDest disposal method */ +  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; +  WhereInfo *pWInfo; +  Vdbe *v; +  int isAgg = 0;         /* 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 */ + +  if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; +  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + +  /* If there is are a sequence of queries, do the earlier ones first. +  */ +  if( p->pPrior ){ +    return multiSelect(pParse, p, eDest, iParm, aff); +  } + +  /* Make local copies of the parameters for this query. +  */ +  pTabList = p->pSrc; +  pWhere = p->pWhere; +  pOrderBy = p->pOrderBy; +  pGroupBy = p->pGroupBy; +  pHaving = p->pHaving; +  isDistinct = p->isDistinct; + +  /* Allocate VDBE cursors for each table in the FROM clause +  */ +  sqlite3SrcListAssignCursors(pParse, pTabList); + +  /*  +  ** 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; + +  /* Expand any "*" terms in the result set.  (For example the "*" in +  ** "SELECT * FROM t1")  The fillInColumnlist() routine also does some +  ** other housekeeping - see the header comment for details. +  */ +  if( fillInColumnList(pParse, p) ){ +    goto select_end; +  } +  pWhere = p->pWhere; +  pEList = p->pEList; +  if( pEList==0 ) goto select_end; + +  /* If writing to memory or generating a set +  ** only a single column may be output. +  */ +  if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ +    sqlite3ErrorMsg(pParse, "only a single result allowed for " +       "a SELECT that is part of an expression"); +    goto select_end; +  } + +  /* ORDER BY is ignored for some destinations. +  */ +  switch( eDest ){ +    case SRT_Union: +    case SRT_Except: +    case SRT_Discard: +      pOrderBy = 0; +      break; +    default: +      break; +  } + +  /* At this point, we should have allocated all the cursors that we +  ** need to handle subquerys and temporary tables.   +  ** +  ** Resolve the column names and do a semantics check on all the expressions. +  */ +  for(i=0; i<pEList->nExpr; i++){ +    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr, +                                    1, &isAgg) ){ +      goto select_end; +    } +  } +  if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){ +    goto select_end; +  } +  if( pHaving ){ +    if( pGroupBy==0 ){ +      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); +      goto select_end; +    } +    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){ +      goto select_end; +    } +  } +  if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER") +   || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP") +  ){ +    goto select_end; +  } + +  /* Begin generating code. +  */ +  v = sqlite3GetVdbe(pParse); +  if( v==0 ) goto 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( eDest==SRT_Callback ){ +    generateColumnNames(pParse, pTabList, pEList); +  } + +  /* Generate code for all sub-queries in the FROM clause +  */ +  for(i=0; i<pTabList->nSrc; i++){ +    const char *zSavedAuthContext = 0; +    int needRestoreContext; + +    if( pTabList->a[i].pSelect==0 ) continue; +    if( pTabList->a[i].zName!=0 ){ +      zSavedAuthContext = pParse->zAuthContext; +      pParse->zAuthContext = pTabList->a[i].zName; +      needRestoreContext = 1; +    }else{ +      needRestoreContext = 0; +    } +    sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable,  +                 pTabList->a[i].iCursor, p, i, &isAgg, 0); +    if( needRestoreContext ){ +      pParse->zAuthContext = zSavedAuthContext; +    } +    pTabList = p->pSrc; +    pWhere = p->pWhere; +    if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ +      pOrderBy = p->pOrderBy; +    } +    pGroupBy = p->pGroupBy; +    pHaving = p->pHaving; +    isDistinct = p->isDistinct; +  } + +  /* Check for the special case of a min() or max() function by itself +  ** in the result set. +  */ +  if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){ +    rc = 0; +    goto select_end; +  } + +  /* 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.   +  */ +  if( pParent && pParentAgg && +      flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ +    if( isAgg ) *pParentAgg = 1; +    return rc; +  } + +  /* If there is an ORDER BY clause, resolve any collation sequences +  ** names that have been explicitly specified. +  */ +  if( pOrderBy ){ +    for(i=0; i<pOrderBy->nExpr; i++){ +      if( pOrderBy->a[i].zName ){ +        pOrderBy->a[i].pExpr->pColl =  +            sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1); +      } +    } +    if( pParse->nErr ){ +      goto select_end; +    } +  } + +  /* Set the limiter. +  */ +  computeLimitRegisters(pParse, p); + +  /* If the output is destined for a temporary table, open that table. +  */ +  if( eDest==SRT_TempTable ){ +    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); +  } + +  /* Do an analysis of aggregate expressions. +  */ +  sqliteAggregateInfoReset(pParse); +  if( isAgg || pGroupBy ){ +    assert( pParse->nAgg==0 ); +    isAgg = 1; +    for(i=0; i<pEList->nExpr; i++){ +      if( sqlite3ExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){ +        goto select_end; +      } +    } +    if( pGroupBy ){ +      for(i=0; i<pGroupBy->nExpr; i++){ +        if( sqlite3ExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){ +          goto select_end; +        } +      } +    } +    if( pHaving && sqlite3ExprAnalyzeAggregates(pParse, pHaving) ){ +      goto select_end; +    } +    if( pOrderBy ){ +      for(i=0; i<pOrderBy->nExpr; i++){ +        if( sqlite3ExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){ +          goto select_end; +        } +      } +    } +  } + +  /* Reset the aggregator +  */ +  if( isAgg ){ +    int addr = sqlite3VdbeAddOp(v, OP_AggReset, (pGroupBy?0:1), pParse->nAgg); +    for(i=0; i<pParse->nAgg; i++){ +      FuncDef *pFunc; +      if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ +        sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_FUNCDEF); +      } +    } +    if( pGroupBy ){ +      int sz = sizeof(KeyInfo) + pGroupBy->nExpr*sizeof(CollSeq*); +      KeyInfo *pKey = (KeyInfo *)sqliteMalloc(sz); +      if( 0==pKey ){ +        goto select_end; +      } +      pKey->enc = pParse->db->enc; +      pKey->nField = pGroupBy->nExpr; +      for(i=0; i<pGroupBy->nExpr; i++){ +        pKey->aColl[i] = sqlite3ExprCollSeq(pParse, pGroupBy->a[i].pExpr); +        if( !pKey->aColl[i] ){ +          pKey->aColl[i] = pParse->db->pDfltColl; +        } +      } +      sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF); +    } +  } + +  /* Initialize the memory cell to NULL +  */ +  if( eDest==SRT_Mem ){ +    sqlite3VdbeAddOp(v, OP_String8, 0, 0); +    sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); +  } + +  /* Open a temporary table to use for the distinct set. +  */ +  if( isDistinct ){ +    distinct = pParse->nTab++; +    openTempIndex(pParse, p, distinct, 0); +  }else{ +    distinct = -1; +  } + +  /* Begin the database scan +  */ +  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,  +                            pGroupBy ? 0 : &pOrderBy); +  if( pWInfo==0 ) goto select_end; + +  /* Use the standard inner loop if we are not dealing with +  ** aggregates +  */ +  if( !isAgg ){ +    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, +                    iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){ +       goto select_end; +    } +  } + +  /* If we are dealing with aggregates, then do the special aggregate +  ** processing.   +  */ +  else{ +    AggExpr *pAgg; +    if( pGroupBy ){ +      int lbl1; +      for(i=0; i<pGroupBy->nExpr; i++){ +        sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr); +      } +      /* No affinity string is attached to the following OP_MakeRecord  +      ** because we do not need to do any coercion of datatypes. */ +      sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0); +      lbl1 = sqlite3VdbeMakeLabel(v); +      sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1); +      for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ +        if( pAgg->isAgg ) continue; +        sqlite3ExprCode(pParse, pAgg->pExpr); +        sqlite3VdbeAddOp(v, OP_AggSet, 0, i); +      } +      sqlite3VdbeResolveLabel(v, lbl1); +    } +    for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ +      Expr *pE; +      int nExpr; +      FuncDef *pDef; +      if( !pAgg->isAgg ) continue; +      assert( pAgg->pFunc!=0 ); +      assert( pAgg->pFunc->xStep!=0 ); +      pDef = pAgg->pFunc; +      pE = pAgg->pExpr; +      assert( pE!=0 ); +      assert( pE->op==TK_AGG_FUNCTION ); +      nExpr = sqlite3ExprCodeExprList(pParse, pE->pList); +      sqlite3VdbeAddOp(v, OP_Integer, i, 0); +      if( pDef->needCollSeq ){ +        CollSeq *pColl = 0; +        int j; +        for(j=0; !pColl && j<nExpr; j++){ +          pColl = sqlite3ExprCollSeq(pParse, pE->pList->a[j].pExpr); +        } +        if( !pColl ) pColl = pParse->db->pDfltColl; +        sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); +      } +      sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER); +    } +  } + +  /* End the database scan loop. +  */ +  sqlite3WhereEnd(pWInfo); + +  /* If we are processing aggregates, we need to set up a second loop +  ** over all of the aggregate values and process them. +  */ +  if( isAgg ){ +    int endagg = sqlite3VdbeMakeLabel(v); +    int startagg; +    startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); +    pParse->useAgg = 1; +    if( pHaving ){ +      sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); +    } +    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, +                    iParm, startagg, endagg, aff) ){ +      goto select_end; +    } +    sqlite3VdbeAddOp(v, OP_Goto, 0, startagg); +    sqlite3VdbeResolveLabel(v, endagg); +    sqlite3VdbeAddOp(v, OP_Noop, 0, 0); +    pParse->useAgg = 0; +  } + +  /* 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, eDest, iParm); +  } + +  /* If this was a subquery, we have now converted the subquery into a +  ** temporary table.  So delete the subquery structure from the parent +  ** to prevent this subquery from being evaluated again and to force the +  ** the use of the temporary table. +  */ +  if( pParent ){ +    assert( pParent->pSrc->nSrc>parentTab ); +    assert( pParent->pSrc->a[parentTab].pSelect==p ); +    sqlite3SelectDelete(p); +    pParent->pSrc->a[parentTab].pSelect = 0; +  } + +  /* 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: +  sqliteAggregateInfoReset(pParse); +  return rc; +} diff --git a/ext/pdo_sqlite/sqlite/src/shell.c b/ext/pdo_sqlite/sqlite/src/shell.c new file mode 100644 index 0000000000..bdd13cc931 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/shell.c @@ -0,0 +1,1786 @@ +/* +** 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$ +*/ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include "sqlite3.h" +#include <ctype.h> + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) +# include <signal.h> +# include <pwd.h> +# include <unistd.h> +# include <sys/types.h> +#endif + +#ifdef __MACOS__ +# include <console.h> +# include <signal.h> +# include <unistd.h> +# include <extras.h> +# include <Files.h> +# include <Folders.h> +#endif + +#if defined(HAVE_READLINE) && HAVE_READLINE==1 +# include <readline/readline.h> +# include <readline/history.h> +#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 + +/* Make sure isatty() has a prototype. +*/ +extern int isatty(); + +/* +** 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 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: "   ...> " */ + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const unsigned 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.  "isatty" is true if text +** is coming from a terminal.  In that case, we issue a prompt and +** attempt to use "readline" for command-line editing.  If "isatty" +** is false, use "local_getline" instead of "readline" and issue no prompt. +** +** 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( zResult ) add_history(zResult); +  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 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 */ +  char *zKey;                 /* Encryption key */ +}; + +/* +** 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) */ + +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); +    }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; +  } +} + +/* +** 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){ +  if( z==0 ){ +    fprintf(p->out,"%s",p->nullvalue); +  }else if( isNumber(z, 0) ){ +    fprintf(p->out,"%s",z); +  }else{ +    output_c_string(p->out, z); +  } +  if( bSep ){ +    fprintf(p->out, p->separator); +  } +} + +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ +  seenInterrupt = 1; +  if( db ) sqlite3_interrupt(db); +} + +/* +** 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; i<nArg; i++){ +        int len = strlen(azCol[i]); +        if( len>w ) w = len; +      } +      if( p->cnt++>0 ) fprintf(p->out,"\n"); +      for(i=0; i<nArg; i++){ +        fprintf(p->out,"%*s = %s\n", w, azCol[i],  +                azArg[i] ? azArg[i] : p->nullvalue); +      } +      break; +    } +    case MODE_Column: { +      if( p->cnt++==0 ){ +        for(i=0; i<nArg; i++){ +          int w, n; +          if( i<ArraySize(p->colWidth) ){ +             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( w<n ) w = n; +          } +          if( i<ArraySize(p->actualWidth) ){ +            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; i<nArg; i++){ +            int w; +            if( i<ArraySize(p->actualWidth) ){ +               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; i<nArg; i++){ +        int w; +        if( i<ArraySize(p->actualWidth) ){ +           w = p->actualWidth[i]; +        }else{ +           w = 10; +        } +        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; i<nArg; i++){ +          fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); +        } +      } +      if( azArg==0 ) break; +      for(i=0; i<nArg; i++){ +        char *z = azArg[i]; +        if( z==0 ) z = p->nullvalue; +        fprintf(p->out, "%s", z); +        if( i<nArg-1 ){ +          fprintf(p->out, "%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,"<TR>"); +        for(i=0; i<nArg; i++){ +          fprintf(p->out,"<TH>%s</TH>",azCol[i]); +        } +        fprintf(p->out,"</TR>\n"); +      } +      if( azArg==0 ) break; +      fprintf(p->out,"<TR>"); +      for(i=0; i<nArg; i++){ +        fprintf(p->out,"<TD>"); +        output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); +        fprintf(p->out,"</TD>\n"); +      } +      fprintf(p->out,"</TR>\n"); +      break; +    } +    case MODE_Tcl: { +      if( p->cnt++==0 && p->showHeader ){ +        for(i=0; i<nArg; i++){ +          output_c_string(p->out,azCol[i]); +          fprintf(p->out, "%s", p->separator); +        } +        fprintf(p->out,"\n"); +      } +      if( azArg==0 ) break; +      for(i=0; i<nArg; i++){ +        output_c_string(p->out, 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; i<nArg; i++){ +          output_csv(p, azCol[i], i<nArg-1); +        } +        fprintf(p->out,"\n"); +      } +      if( azArg==0 ) break; +      for(i=0; i<nArg; i++){ +        output_csv(p, azArg[i], i<nArg-1); +      } +      fprintf(p->out,"\n"); +      break; +    } +    case MODE_Insert: { +      if( azArg==0 ) break; +      fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); +      for(i=0; i<nArg; i++){ +        char *zSep = i>0 ? ",": ""; +        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; i<nAppend; i++){ +      if( zAppend[i]==quote ) len++; +    } +  } + +  zIn = (char *)realloc(zIn, len); +  if( !zIn ){ +    return 0; +  } + +  if( quote ){ +    char *zCsr = &zIn[nIn]; +    *zCsr++ = quote; +    for(i=0; i<nAppend; i++){ +      *zCsr++ = zAppend[i]; +      if( zAppend[i]==quote ) *zCsr++ = quote; +    } +    *zCsr++ = quote; +    *zCsr++ = '\0'; +    assert( (zCsr-zIn)==len ); +  }else{ +    memcpy(&zIn[nIn], zAppend, nAppend); +    zIn[len-1] = '\0'; +  } + +  return zIn; +} + + +/* +** Execute a query statement that has a single result column.  Print +** that result column on a line by itself with a semicolon terminator. +*/ +static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){ +  sqlite3_stmt *pSelect; +  int rc; +  rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0); +  if( rc!=SQLITE_OK || !pSelect ){ +    return rc; +  } +  rc = sqlite3_step(pSelect); +  while( rc==SQLITE_ROW ){ +    fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0)); +    rc = sqlite3_step(pSelect); +  } +  return sqlite3_finalize(pSelect); +} + + +/* +** This is a different callback routine used for dumping the database. +** Each row received by this callback consists of a table name, +** the table type ("index" or "table") and SQL to create the table. +** This routine should print text sufficient to recreate the table. +*/ +static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ +  int rc; +  const char *zTable; +  const char *zType; +  const char *zSql; +  struct callback_data *p = (struct callback_data *)pArg; + +  if( nArg!=3 ) return 1; +  zTable = azArg[0]; +  zType = azArg[1]; +  zSql = azArg[2]; +   +  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 ){ +      zSelect = appendText(zSelect, "quote(", 0); +      zSelect = appendText(zSelect, sqlite3_column_text(pTableInfo, 1), '"'); +      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); +    if( rc!=SQLITE_OK ){ +      return 1; +    } +  } +  return 0; +} + +/* +** Run zQuery.  Update dump_callback() as the callback routine. +** 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; +    sprintf(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[] = +  ".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" +  ".mode MODE ?TABLE?     Set output mode where MODE is on of:\n" +  "                         csv      Comma-separated values\n" +  "                         column   Left-aligned columns.  (See .width)\n" +  "                         html     HTML <table> 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" +#ifdef SQLITE_HAS_CODEC +  ".rekey OLD NEW NEW     Change the encryption key\n" +#endif +  ".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" +  ".width NUM NUM ...     Set column widths for \"column\" mode\n" +; + +/* Forward reference */ +static void 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; +#ifdef SQLITE_HAS_CODEC +    sqlite3_key(p->db, p->zKey, p->zKey ? strlen(p->zKey) : 0); +#endif +    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); +    } +  } +} + +/* +** 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; +} + +/* +** If an input line begins with "." then invoke this routine to +** process that line. +** +** Return 1 to exit and 0 to continue. +*/ +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] && nArg<ArraySize(azArg) ){ +    while( isspace((unsigned char)zLine[i]) ){ i++; } +    if( zLine[i]==0 ) break; +    if( zLine[i]=='\'' || zLine[i]=='"' ){ +      int delim = zLine[i++]; +      azArg[nArg++] = &zLine[i]; +      while( zLine[i] && zLine[i]!=delim ){ i++; } +      if( zLine[i]==delim ){ +        zLine[i++] = 0; +      } +      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); +    }else{ +      azArg[nArg++] = &zLine[i]; +      while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; } +      if( zLine[i] ) zLine[i++] = 0; +      resolve_backslashes(azArg[nArg-1]); +    } +  } + +  /* Process the input line. +  */ +  if( nArg==0 ) return rc; +  n = strlen(azArg[0]); +  c = azArg[0][0]; +  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; +    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"); +    if( nArg==1 ){ +      run_schema_dump_query(p,  +        "SELECT name, type, sql FROM sqlite_master " +        "WHERE sql NOT NULL AND type=='table'", 0 +      ); +      run_schema_dump_query(p,  +        "SELECT name, type, sql FROM sqlite_master " +        "WHERE sql NOT NULL AND type!='table' AND type!='meta'", 0 +      ); +    }else{ +      int i; +      for(i=1; i<nArg; i++){ +        zShellStatic = azArg[i]; +        run_schema_dump_query(p, +          "SELECT name, type, sql FROM sqlite_master " +          "WHERE tbl_name LIKE shellstatic() AND type=='table'" +          "  AND sql NOT NULL", 0); +        run_schema_dump_query(p, +          "SELECT name, type, sql FROM sqlite_master " +          "WHERE tbl_name LIKE shellstatic() AND type!='table'" +          "  AND type!='meta' AND sql NOT NULL", 0); +        zShellStatic = 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 ){ +    int j; +    char *z = azArg[1]; +    int val = atoi(azArg[1]); +    for(j=0; z[j]; j++){ +      z[j] = tolower((unsigned char)z[j]); +    } +    if( strcmp(z,"on")==0 ){ +      val = 1; +    }else if( strcmp(z,"yes")==0 ){ +      val = 1; +    } +    p->echoOn = val; +  }else + +  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ +    rc = 1; +  }else + +  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ +    int j; +    static char zOne[] = "1"; +    char *z = nArg>=2 ? azArg[1] : zOne; +    int val = atoi(z); +    for(j=0; z[j]; j++){ +      z[j] = tolower((unsigned char)z[j]); +    } +    if( strcmp(z,"on")==0 ){ +      val = 1; +    }else if( strcmp(z,"yes")==0 ){ +      val = 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_Column; +      p->showHeader = 1; +      memset(p->colWidth,0,ArraySize(p->colWidth)); +      p->colWidth[0] = 4; +      p->colWidth[1] = 12; +      p->colWidth[2] = 10; +      p->colWidth[3] = 10; +      p->colWidth[4] = 35; +    }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 ){ +    int j; +    char *z = azArg[1]; +    int val = atoi(azArg[1]); +    for(j=0; z[j]; j++){ +      z[j] = tolower((unsigned char)z[j]); +    } +    if( strcmp(z,"on")==0 ){ +      val = 1; +    }else if( strcmp(z,"yes")==0 ){ +      val = 1; +    } +    p->showHeader = val; +  }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 */ + +    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, 0, &pStmt, 0); +    sqlite3_free(zSql); +    if( rc ){ +      fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); +      nCol = 0; +    }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; i<nCol; i++){ +      zSql[j++] = ','; +      zSql[j++] = '?'; +    } +    zSql[j++] = ')'; +    zSql[j] = 0; +    rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0); +    free(zSql); +    if( rc ){ +      fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); +      sqlite3_finalize(pStmt); +      return 0; +    } +    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 ) 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( i<nCol ){ +            azCol[i] = &z[nSep]; +            z += nSep-1; +          } +        } +      } +      if( i+1!=nCol ){ +        fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n", +           zFile, lineno, nCol, i+1); +        zCommit = "ROLLBACK"; +        break; +      } +      for(i=0; i<nCol; i++){ +        sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); +      } +      sqlite3_step(pStmt); +      rc = sqlite3_reset(pStmt); +      free(zLine); +      if( rc!=SQLITE_OK ){ +        fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); +        zCommit = "ROLLBACK"; +        break; +      } +    } +    free(azCol); +    fclose(in); +    sqlite3_finalize(pStmt); +    sqlite3_exec(p->db, 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 + +  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; +      strcpy(p->separator, ","); +    }else if( strncmp(azArg[1],"tabs",n2)==0 ){ +      p->mode = MODE_List; +      strcpy(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 on of: " +         "column csv html insert line list tabs tcl\n"); +    } +  }else + +  if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { +    sprintf(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; +      strcpy(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 { +         strcpy(p->outfile,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 = 1; +  }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 + +#ifdef SQLITE_HAS_CODEC +  if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){ +    char *zOld = p->zKey; +    if( zOld==0 ) zOld = ""; +    if( strcmp(azArg[1],zOld) ){ +      fprintf(stderr,"old key is incorrect\n"); +    }else if( strcmp(azArg[2], azArg[3]) ){ +      fprintf(stderr,"2nd copy of new key does not match the 1st\n"); +    }else{ +      sqlite3_free(p->zKey); +      p->zKey = sqlite3_mprintf("%s", azArg[2]); +      sqlite3_rekey(p->db, p->zKey, strlen(p->zKey)); +    } +  }else +#endif + +  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 " +         "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 ){ +    sprintf(p->separator, "%.*s", (int)ArraySize(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') " +        "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; i<nPrintRow; i++){ +        for(j=i+1; j<=nRow; j+=nPrintRow){ +          char *zSp = j<=nPrintRow ? "" : "  "; +          printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); +        } +        printf("\n"); +      } +    } +    sqlite3_free_table(azResult); +  }else + +  if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ +    open_db(p); +    sqlite3_busy_timeout(p->db, atoi(azArg[1])); +  }else + +  if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ +    int j; +    for(j=1; j<nArg && j<ArraySize(p->colWidth); 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 the last non-whitespace character in z[] is a semicolon. +** z[] is N characters long. +*/ +static int _ends_with_semicolon(const char *z, int N){ +  while( N>0 && isspace((unsigned char)z[N-1]) ){ N--; } +  return N>0 && z[N-1]==';'; +} + +/* +** Test to see if a line consists entirely of whitespace. +*/ +static int _all_whitespace(const char *z){ +  for(; *z; z++){ +    if( isspace(*(unsigned char*)z) ) continue; +    if( *z=='/' && z[1]=='*' ){ +      z += 2; +      while( *z && (*z!='*' || z[1]!='/') ){ z++; } +      if( *z==0 ) return 0; +      z++; +      continue; +    } +    if( *z=='-' && z[1]=='-' ){ +      z += 2; +      while( *z && *z!='\n' ){ z++; } +      if( *z==0 ) return 1; +      continue; +    } +    return 0; +  } +  return 1; +} + +/* +** Return TRUE if the line typed in is an SQL command terminator other +** than a semi-colon.  The SQL Server style "go" command is understood +** as is the Oracle "/". +*/ +static int _is_command_terminator(const char *zLine){ +  while( isspace(*(unsigned char*)zLine) ){ zLine++; }; +  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1;  /* Oracle */ +  if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o' +         && _all_whitespace(&zLine[2]) ){ +    return 1;  /* SQL Server */ +  } +  return 0; +} + +/* +** Read input from *in and process it.  If *in==0 then input +** is interactive - the user is typing it it.  Otherwise, input +** is coming from a file or device.  A prompt is issued and history +** is saved only if input is interactive.  An interrupt signal will +** cause this routine to exit immediately, unless input is interactive. +*/ +static void process_input(struct callback_data *p, FILE *in){ +  char *zLine; +  char *zSql = 0; +  int nSql = 0; +  char *zErrMsg; +  int rc; +  while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){ +    if( seenInterrupt ){ +      if( in!=0 ) break; +      seenInterrupt = 0; +    } +    if( p->echoOn ) printf("%s\n", zLine); +    if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; +    if( zLine && zLine[0]=='.' && nSql==0 ){ +      int rc = do_meta_command(zLine, p); +      free(zLine); +      if( rc ) break; +      continue; +    } +    if( _is_command_terminator(zLine) ){ +      strcpy(zLine,";"); +    } +    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 ); +        strcpy(zSql, zLine); +      } +    }else{ +      int len = strlen(zLine); +      zSql = realloc( zSql, nSql + len + 2 ); +      if( zSql==0 ){ +        fprintf(stderr,"%s: out of memory!\n", Argv0); +        exit(1); +      } +      strcpy(&zSql[nSql++], "\n"); +      strcpy(&zSql[nSql], zLine); +      nSql += len; +    } +    free(zLine); +    if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){ +      p->cnt = 0; +      open_db(p); +      rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg); +      if( rc || zErrMsg ){ +        if( in!=0 && !p->echoOn ) printf("%s\n",zSql); +        if( zErrMsg!=0 ){ +          printf("SQL error: %s\n", zErrMsg); +          sqlite3_free(zErrMsg); +          zErrMsg = 0; +        }else{ +          printf("SQL error: %s\n", sqlite3_errmsg(p->db)); +        } +      } +      free(zSql); +      zSql = 0; +      nSql = 0; +    } +  } +  if( zSql ){ +    if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql); +    free(zSql); +  } +} + +/* +** 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(__MACOS__) +  struct passwd *pwent; +  uid_t uid = getuid(); +  if( (pwent=getpwuid(uid)) != NULL) { +    home_dir = pwent->pw_dir; +  } +#endif + +#ifdef __MACOS__ +  char home_path[_MAX_PATH+1]; +  home_dir = getcwd(home_path, _MAX_PATH); +#endif + +  if (!home_dir) { +    home_dir = getenv("HOME"); +    if (!home_dir) { +      home_dir = getenv("HOMEPATH"); /* Windows? */ +    } +  } + +#if defined(_WIN32) || defined(WIN32) +  if (!home_dir) { +    home_dir = "c:"; +  } +#endif + +  if( home_dir ){ +    char *z = malloc( strlen(home_dir)+1 ); +    if( z ) strcpy(z, home_dir); +    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; +  FILE *in = NULL; + +  if (sqliterc == NULL) { +    home_dir = find_home_dir(); +    if( home_dir==0 ){ +      fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0); +      return; +    } +    zBuf = malloc(strlen(home_dir) + 15); +    if( zBuf==0 ){ +      fprintf(stderr,"%s: out of memory!\n", Argv0); +      exit(1); +    } +    sprintf(zBuf,"%s/.sqliterc",home_dir); +    free(home_dir); +    sqliterc = (const char*)zBuf; +  } +  in = fopen(sqliterc,"rb"); +  if( in ){ +    if( isatty(fileno(stdout)) ){ +      printf("Loading resources from %s\n",sqliterc); +    } +    process_input(p,in); +    fclose(in); +  } +  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" +  "   -column              set output mode to 'column'\n" +  "   -html                set output mode to HTML\n" +#ifdef SQLITE_HAS_CODEC +  "   -key KEY             encryption key\n" +#endif                  +  "   -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" +  "   -help                show this text, also show dot-commands\n" +; +static void usage(int showDetail){ +  fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0); +  if( showDetail ){ +    fprintf(stderr, "Options are:\n%s", zOptions); +  }else{ +    fprintf(stderr, "Use the -help option for additional information\n"); +  } +  exit(1); +} + +/* +** Initialize the state information in data +*/ +void main_init(struct callback_data *data) { +  memset(data, 0, sizeof(*data)); +  data->mode = MODE_List; +  strcpy(data->separator,"|"); +  data->showHeader = 0; +  strcpy(mainPrompt,"sqlite> "); +  strcpy(continuePrompt,"   ...> "); +} + +int main(int argc, char **argv){ +  char *zErrMsg = 0; +  struct callback_data data; +  const char *zInitFile = 0; +  char *zFirstCmd = 0; +  int i; + +#ifdef __MACOS__ +  argc = ccommand(&argv); +#endif + +  Argv0 = argv[0]; +  main_init(&data); + +  /* 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<argc-1; i++){ +    if( argv[i][0]!='-' ) break; +    if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){ +      i++; +    }else if( strcmp(argv[i],"-init")==0 ){ +      i++; +      zInitFile = argv[i]; +    }else if( strcmp(argv[i],"-key")==0 ){ +      i++; +      data.zKey = sqlite3_mprintf("%s",argv[i]); +    } +  } +  if( i<argc ){ +    data.zDbFilename = argv[i++]; +  }else{ +    data.zDbFilename = ":memory:"; +  } +  if( i<argc ){ +    zFirstCmd = argv[i++]; +  } +  data.out = stdout; + +  /* Go ahead and open the database file if it already exists.  If the +  ** file does not exist, delay opening it.  This prevents empty database +  ** files from being created if a user mistypes the database name argument +  ** to the sqlite command-line tool. +  */ +  if( access(data.zDbFilename, 0)==0 ){ +    open_db(&data); +  } + +  /* Process the initialization file if there is one.  If no -init option +  ** is given on the command line, look for a file named ~/.sqliterc and +  ** try to process it. +  */ +  process_sqliterc(&data,zInitFile); + +  /* Make a second pass through the command-line argument and set +  ** options.  This second pass is delayed until after the initialization +  ** file is processed so that the command-line arguments will override +  ** settings in the initialization file. +  */ +  for(i=1; i<argc && argv[i][0]=='-'; i++){ +    char *z = argv[i]; +    if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){ +      i++; +    }else if( strcmp(z,"-html")==0 ){ +      data.mode = MODE_Html; +    }else if( strcmp(z,"-list")==0 ){ +      data.mode = MODE_List; +    }else if( strcmp(z,"-line")==0 ){ +      data.mode = MODE_Line; +    }else if( strcmp(z,"-column")==0 ){ +      data.mode = MODE_Column; +    }else if( strcmp(z,"-separator")==0 ){ +      i++; +      sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]); +    }else if( strcmp(z,"-nullvalue")==0 ){ +      i++; +      sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]); +    }else if( strcmp(z,"-header")==0 ){ +      data.showHeader = 1; +    }else if( strcmp(z,"-noheader")==0 ){ +      data.showHeader = 0; +    }else if( strcmp(z,"-echo")==0 ){ +      data.echoOn = 1; +    }else if( strcmp(z,"-version")==0 ){ +      printf("%s\n", sqlite3_libversion()); +      return 1; +    }else if( strcmp(z,"-help")==0 ){ +      usage(1); +    }else{ +      fprintf(stderr,"%s: unknown option: %s\n", Argv0, z); +      fprintf(stderr,"Use -help for a list of options.\n"); +      return 1; +    } +  } + +  if( zFirstCmd ){ +    /* Run just the command that follows the database name +    */ +    if( zFirstCmd[0]=='.' ){ +      do_meta_command(zFirstCmd, &data); +      exit(0); +    }else{ +      int rc; +      open_db(&data); +      rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg); +      if( rc!=0 && zErrMsg!=0 ){ +        fprintf(stderr,"SQL error: %s\n", zErrMsg); +        exit(1); +      } +    } +  }else{ +    /* Run commands received from standard input +    */ +    if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){ +      char *zHome; +      char *zHistory = 0; +      printf( +        "SQLite version %s\n" +        "Enter \".help\" for instructions\n", +        sqlite3_libversion() +      ); +      zHome = find_home_dir(); +      if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){ +        sprintf(zHistory,"%s/.sqlite_history", zHome); +      } +      if( zHistory ) read_history(zHistory); +      process_input(&data, 0); +      if( zHistory ){ +        stifle_history(100); +        write_history(zHistory); +      } +    }else{ +      process_input(&data, stdin); +    } +  } +  set_table_name(&data, 0); +  if( db ) sqlite3_close(db); +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/src/sqlite.h.in b/ext/pdo_sqlite/sqlite/src/sqlite.h.in new file mode 100644 index 0000000000..2dd97ed8cd --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/sqlite.h.in @@ -0,0 +1,1166 @@ +/* +** 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 library +** presents to client programs. +** +** @(#) $Id$ +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include <stdarg.h>     /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* +** The version of the SQLite library. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#else +# define SQLITE_VERSION         "--VERS--" +#endif + +/* +** The version string is also compiled into the library so that a program +** can check to make sure that the lib*.a file and the *.h file are from +** the same version.  The sqlite3_libversion() function returns a pointer +** to the sqlite3_version variable - useful in DLLs which cannot access +** global variables. +*/ +extern const char sqlite3_version[]; +const char *sqlite3_libversion(void); + +/* +** Each open sqlite database is represented by an instance of the +** following opaque structure. +*/ +typedef struct sqlite3 sqlite3; + + +/* +** Some compilers do not support the "long long" datatype.  So we have +** to do a typedef that for 64-bit integers that depends on what compiler +** is being used. +*/ +#if 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 + + +/* +** A function to close the database. +** +** Call this function with a pointer to a structure that was previously +** returned from sqlite3_open() and the corresponding database will by closed. +** +** All SQL statements prepared using sqlite3_prepare() or +** sqlite3_prepare16() must be deallocated using sqlite3_finalize() before +** this routine is called. Otherwise, SQLITE_BUSY is returned and the +** database connection remains open. +*/ +int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** A function to executes one or more statements of SQL. +** +** If one or more of the SQL statements are queries, then +** the callback function specified by the 3rd parameter is +** invoked once for each row of the query result.  This callback +** should normally return 0.  If the callback returns a non-zero +** value then the query is aborted, all subsequent SQL statements +** are skipped and the sqlite3_exec() function returns the SQLITE_ABORT. +** +** The 4th parameter is an arbitrary pointer that is passed +** to the callback function as its first parameter. +** +** The 2nd parameter to the callback function is the number of +** columns in the query result.  The 3rd parameter to the callback +** is an array of strings holding the values for each column. +** The 4th parameter to the callback is an array of strings holding +** the names of each column. +** +** The callback function may be NULL, even for queries.  A NULL +** callback is not an error.  It just means that no callback +** will be invoked. +** +** If an error occurs while parsing or evaluating the SQL (but +** not while executing the callback) then an appropriate error +** message is written into memory obtained from malloc() and +** *errmsg is made to point to that message.  The calling function +** is responsible for freeing the memory that holds the error +** message.   Use sqlite3_free() for this.  If errmsg==NULL, +** then no error message is ever written. +** +** The return value is is SQLITE_OK if there are no errors and +** some other return code if there is an error.  The particular +** return value depends on the type of error.  +** +** If the query could not be executed because a database file is +** locked or busy, then this function returns SQLITE_BUSY.  (This +** behavior can be modified somewhat using the sqlite3_busy_handler() +** and sqlite3_busy_timeout() functions below.) +*/ +int sqlite3_exec( +  sqlite3*,                     /* An open database */ +  const char *sql,              /* SQL to be executed */ +  sqlite3_callback,             /* Callback function */ +  void *,                       /* 1st argument to callback function */ +  char **errmsg                 /* Error msg written here */ +); + +/* +** Return values for sqlite3_exec() and sqlite3_step() +*/ +#define SQLITE_OK           0   /* Successful result */ +#define SQLITE_ERROR        1   /* SQL error or missing database */ +#define SQLITE_INTERNAL     2   /* An 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   /* (Internal Only) 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   /* Database lock protocol error */ +#define SQLITE_EMPTY       16   /* Database is empty */ +#define SQLITE_SCHEMA      17   /* The database schema changed */ +#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */ +#define SQLITE_CONSTRAINT  19   /* Abort due to contraint 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 */ + +/* +** Each entry in an SQLite table has a unique integer key.  (The key is +** the value of the INTEGER PRIMARY KEY column if there is such a column, +** otherwise the key is generated at random.  The unique key is always +** available as the ROWID, OID, or _ROWID_ column.)  The following routine +** returns the integer key of the most recent insert in the database. +** +** This function is similar to the mysql_insert_id() function from MySQL. +*/ +sqlite_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** This function returns the number of database rows that were changed +** (or inserted or deleted) by the most recent called sqlite3_exec(). +** +** All changes are counted, even if they were later undone by a +** ROLLBACK or ABORT.  Except, changes associated with creating and +** dropping tables are not counted. +** +** If a callback invokes sqlite3_exec() recursively, then the changes +** in the inner, recursive call are counted together with the changes +** in the outer call. +** +** 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. +*/ +int sqlite3_changes(sqlite3*); + +/* +** This function returns the number of database rows that have been +** modified by INSERT, UPDATE or DELETE statements since the database handle +** was opened. This includes UPDATE, INSERT and DELETE statements executed +** as part of trigger programs. All changes are counted as soon as the +** statement that makes them is completed (when the statement handle is +** passed to sqlite3_reset() or sqlite_finalise()). +** +** 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. +*/ +int sqlite3_total_changes(sqlite3*); + +/* 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. +*/ +void sqlite3_interrupt(sqlite3*); + + +/* These functions return true if the given input string comprises +** one or more complete SQL statements. For the sqlite3_complete() call, +** the parameter must be a nul-terminated UTF-8 string. For +** sqlite3_complete16(), a nul-terminated machine byte order UTF-16 string +** is required. +** +** The algorithm is simple.  If the last token other than spaces +** and comments is a semicolon, then return true.  otherwise return +** false. +*/ +int sqlite3_complete(const char *sql); +int sqlite3_complete16(const void *sql); + +/* +** This routine identifies a callback function that is invoked +** whenever an attempt is made to open a database table that is +** currently locked by another process or thread.  If the busy callback +** is NULL, then sqlite3_exec() returns SQLITE_BUSY immediately if +** it finds a locked table.  If the busy callback is not NULL, then +** sqlite3_exec() invokes the callback with three arguments.  The +** second argument is the name of the locked table and the third +** argument is the number of times the table has been busy.  If the +** busy callback returns 0, then sqlite3_exec() immediately returns +** SQLITE_BUSY.  If the callback returns non-zero, then sqlite3_exec() +** tries to open the table again and the cycle repeats. +** +** The default busy callback is NULL. +** +** Sqlite is re-entrant, so the busy handler may start a new query.  +** (It is not clear why anyone would every want to do this, but it +** is allowed, in theory.)  But the busy handler may not close the +** database.  Closing the database from a busy handler will delete  +** data structures out from under the executing query and will  +** probably result in a coredump. +*/ +int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** This routine sets a busy handler that sleeps for a while when a +** table is locked.  The handler will sleep multiple times until  +** at least "ms" milleseconds of sleeping have been done.  After +** "ms" milleseconds of sleeping, the handler returns 0 which +** causes sqlite3_exec() to return SQLITE_BUSY. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +*/ +int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** This next routine is really just a wrapper around sqlite3_exec(). +** Instead of invoking a user-supplied callback for each row of the +** result, this routine remembers each row of the result in memory +** obtained from malloc(), then returns all of the result after the +** query has finished.  +** +** As an example, suppose the query result where this table: +** +**        Name        | Age +**        ----------------------- +**        Alice       | 43 +**        Bob         | 28 +**        Cindy       | 21 +** +** If the 3rd argument were &azResult then after the function returns +** azResult will contain the following data: +** +**        azResult[0] = "Name"; +**        azResult[1] = "Age"; +**        azResult[2] = "Alice"; +**        azResult[3] = "43"; +**        azResult[4] = "Bob"; +**        azResult[5] = "28"; +**        azResult[6] = "Cindy"; +**        azResult[7] = "21"; +** +** Notice that there is an extra row of data containing the column +** headers.  But the *nrow return value is still 3.  *ncolumn is +** set to 2.  In general, the number of values inserted into azResult +** will be ((*nrow) + 1)*(*ncolumn). +** +** After the calling function has finished using the result, it should  +** pass the result data pointer to sqlite3_free_table() in order to  +** release the memory that was malloc-ed.  Because of the way the  +** malloc() happens, the calling function must not try to call  +** malloc() directly.  Only sqlite3_free_table() is able to release  +** the memory properly and safely. +** +** The return value of this routine is the same as from sqlite3_exec(). +*/ +int sqlite3_get_table( +  sqlite3*,               /* An open database */ +  const char *sql,       /* SQL to be executed */ +  char ***resultp,       /* Result written to a char *[]  that this points to */ +  int *nrow,             /* Number of result rows written here */ +  int *ncolumn,          /* Number of result columns written here */ +  char **errmsg          /* Error msg written here */ +); + +/* +** Call this routine to free the memory that sqlite3_get_table() allocated. +*/ +void sqlite3_free_table(char **result); + +/* +** The following routines are variants of the "sprintf()" from the +** standard C library.  The resulting string is written into memory +** obtained from malloc() so that there is never a possiblity of buffer +** overflow.  These routines also implement some additional formatting +** options that are useful for constructing SQL statements. +** +** The strings returned by these routines should be freed by calling +** sqlite3_free(). +** +** All of the usual printf formatting options apply.  In addition, there +** is a "%q" option.  %q 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!"; +** +** We can use this text in an SQL statement as follows: +** +**      sqlite3_exec_printf(db, "INSERT INTO table VALUES('%q')", +**          callback1, 0, 0, zText); +** +** 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. +*/ +char *sqlite3_mprintf(const char*,...); +char *sqlite3_vmprintf(const char*, va_list); +void sqlite3_free(char *z); +char *sqlite3_snprintf(int,char*,const char*, ...); + +#ifndef SQLITE_OMIT_AUTHORIZATION +/* +** This routine registers a callback with the SQLite library.  The +** callback is invoked (at compile-time, not at run-time) for each +** attempt to access a column of a table in the database.  The callback +** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire +** SQL statement should be aborted with an error and SQLITE_IGNORE +** if the column should be treated as a NULL value. +*/ +int sqlite3_set_authorizer( +  sqlite3*, +  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), +  void *pUserData +); +#endif + +/* +** The second parameter to the access authorization function above will +** be one of the values below.  These values signify what kind of operation +** is to be authorized.  The 3rd and 4th parameters to the authorization +** function will be parameters or NULL depending on which of the following +** codes is used as the second parameter.  The 5th parameter is the name +** of the database ("main", "temp", etc.) if applicable.  The 6th parameter +** 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  +** input SQL code. +** +**                                          Arg-3           Arg-4 +*/ +#define SQLITE_COPY                  0   /* Table Name      File Name       */ +#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            */ + + +/* +** The return value of the authorization function should be one of the +** following constants: +*/ +/* #define SQLITE_OK  0   // Allow access (This is actually defined above) */ +#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 */ + +/* +** Register a function that is called at every invocation of sqlite3_exec() +** or sqlite3_prepare().  This function can be used (for example) to generate +** a log file of all SQL executed against a database. +*/ +void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); + +/* +** 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 API is to keep +** a GUI updated during a large query. +** +** The progress callback is invoked once for every N virtual machine opcodes, +** where N is the second argument to this function. The progress callback +** itself is identified by the third argument to this function. The fourth +** argument to this function is a void pointer passed to the progress callback +** function each time it is invoked. +** +** If a call to sqlite3_exec(), sqlite3_step() or sqlite3_get_table() results  +** in less than N opcodes being executed, then the progress callback is not +** invoked. +**  +** To remove the progress callback altogether, pass NULL as the third +** argument to this function. +** +** If the progress callback returns a result other than 0, then the current  +** query is immediately terminated and any database changes rolled back. If the +** query was part of a larger transaction, then the transaction is not rolled +** back and remains active. The sqlite3_exec() call returns SQLITE_ABORT.  +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** Register a callback function to be invoked whenever a new transaction +** is committed.  The pArg argument is passed through to the callback. +** callback.  If the callback function returns non-zero, then the commit +** is converted into a rollback. +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +** +** Registering a NULL function disables the callback. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); + +/* +** Open the sqlite database file "filename".  The "filename" is UTF-8 +** encoded for sqlite3_open() and UTF-16 encoded in the native byte order +** for sqlite3_open16().  An sqlite3* handle is returned in *ppDb, even +** if an error occurs. If the database is opened (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. +** +** If the database file does not exist, then a new database is created. +** The encoding for the database is UTF-8 if sqlite3_open() is called and +** UTF-16 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. +*/ +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 */ +); + +/* +** Return the error code for the most recent sqlite3_* API call associated +** with sqlite3 handle 'db'. SQLITE_OK is returned if the most recent  +** API call was successful. +** +** Calls to many sqlite3_* functions set the error code and string returned +** by sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16() +** (overwriting the previous values). Note that calls to sqlite3_errcode(), +** sqlite3_errmsg() and sqlite3_errmsg16() themselves do not affect the +** results of future invocations. +** +** Assuming no other intervening sqlite3_* API calls are made, the error +** code returned by this function is associated with the same error as +** the strings  returned by sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_errcode(sqlite3 *db); + +/* +** Return a pointer to a UTF-8 encoded string describing in english the +** error condition for the most recent sqlite3_* API call. The returned +** string is always terminated by an 0x00 byte. +** +** The string "not an error" is returned when the most recent API call was +** successful. +*/ +const char *sqlite3_errmsg(sqlite3*); + +/* +** Return a pointer to a UTF-16 native byte order encoded string describing +** in english the error condition for the most recent sqlite3_* API call. +** The returned string is always terminated by a pair of 0x00 bytes. +** +** The string "not an error" is returned when the most recent API call was +** successful. +*/ +const void *sqlite3_errmsg16(sqlite3*); + +/* +** An instance of the following opaque structure is used to represent +** a compiled SQL statment. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of the following routines. The only difference between +** them is that the second argument, specifying the SQL statement to +** compile, is assumed to be encoded in UTF-8 for the sqlite3_prepare() +** function and UTF-16 for sqlite3_prepare16(). +** +** The first parameter "db" is an SQLite database handle. The second +** parameter "zSql" is the statement to be compiled, encoded as either +** UTF-8 or UTF-16 (see above). If the next parameter, "nBytes", is less +** than zero, then zSql is read up to the first nul terminator.  If +** "nBytes" is not less than zero, then it is the length of the string zSql +** in bytes (not characters). +** +** *pzTail is made to point to the first byte past the end of the first +** SQL statement in zSql.  This routine only compiles the first statement +** in zSql, so *pzTail is left pointing to what remains uncompiled. +** +** *ppStmt is left pointing to a compiled SQL statement that can be +** executed using sqlite3_step().  Or if there is an error, *ppStmt may be +** set to NULL.  If the input text contained no SQL (if the input is and +** empty string or a comment) then *ppStmt is set to NULL. +** +** On success, SQLITE_OK is returned.  Otherwise an error code is returned. +*/ +int sqlite3_prepare( +  sqlite3 *db,            /* Database handle */ +  const char *zSql,       /* SQL statement, UTF-8 encoded */ +  int nBytes,             /* 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 nBytes,             /* Length of zSql in bytes. */ +  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */ +  const void **pzTail     /* OUT: Pointer to unused portion of zSql */ +); + +/* +** Pointers to the following two opaque structures are used to communicate +** with the implementations of user-defined functions. +*/ +typedef struct sqlite3_context sqlite3_context; +typedef struct Mem sqlite3_value; + +/* +** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(), +** one or more literals can be replace by a wildcard "?" or ":N:" where +** N is an integer.  These value of these wildcard literals can be set +** using the routines listed below. +** +** In every case, the first parameter is a pointer to the sqlite3_stmt +** structure returned from sqlite3_prepare().  The second parameter is the +** index of the wildcard.  The first "?" has an index of 1.  ":N:" wildcards +** use the index N. +** +** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** text after SQLite has finished with it.  If the fifth argument is the +** special value SQLITE_STATIC, then the library 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. +** +** The sqlite3_bind_* routine must be called before sqlite3_step() after +** an sqlite3_prepare() or sqlite3_reset().  Unbound wildcards are interpreted +** as NULL. +*/ +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, sqlite_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*); + +/* +** Return the number of wildcards in a compiled SQL statement.  This +** routine was added to support DBD::SQLite. +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** Return the name of the i-th parameter.  Ordinary wildcards "?" are +** nameless and a NULL is returned.  For wildcards of the form :N or +** $vvvv the complete text of the wildcard is returned. +** NULL is returned if the index is out of range. +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** Return the index of a parameter with the given name.  The name +** must match exactly.  If no parameter with the given name is found, +** return 0. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** Return the number of columns in the result set returned by the compiled +** SQL statement. This routine returns 0 if pStmt is an SQL statement +** that does not return data (for example an UPDATE). +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** The first parameter is a compiled SQL statement. This function returns +** the column heading for the Nth column of that statement, where N is the +** second function parameter.  The string returned is UTF-8 for +** sqlite3_column_name() and UTF-16 for sqlite3_column_name16(). +*/ +const char *sqlite3_column_name(sqlite3_stmt*,int); +const void *sqlite3_column_name16(sqlite3_stmt*,int); + +/* +** The first parameter is a compiled SQL statement. If this statement +** is a SELECT statement, the Nth column of the returned result set  +** of the SELECT is a table column then the declared type of the table +** column is returned. If the Nth column of the result set is not at table +** column, then a NULL pointer is returned. The returned string is always +** UTF-8 encoded. For example, in the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** And the following statement compiled: +** +** SELECT c1 + 1, 0 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). +*/ +const char *sqlite3_column_decltype(sqlite3_stmt *, int i); + +/* +** The first parameter is a compiled SQL statement. If this statement +** is a SELECT statement, the Nth column of the returned result set  +** of the SELECT is a table column then the declared type of the table +** column is returned. If the Nth column of the result set is not at table +** column, then a NULL pointer is returned. The returned string is always +** UTF-16 encoded. For example, in the database schema: +** +** CREATE TABLE t1(c1 INTEGER); +** +** And the following statement compiled: +** +** SELECT c1 + 1, 0 FROM t1; +** +** Then this routine would return the string "INTEGER" for the second +** result column (i==1), and a NULL pointer for the first result column +** (i==0). +*/ +const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/*  +** After an SQL query has been compiled with a call to either +** sqlite3_prepare() or sqlite3_prepare16(), then this function must be +** called one or more times to execute the statement. +** +** The return value will be either SQLITE_BUSY, SQLITE_DONE,  +** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE. +** +** SQLITE_BUSY means that the database engine attempted to open +** a locked database and there is no busy callback registered. +** Call sqlite3_step() again to retry the open. +** +** SQLITE_DONE means that the statement has finished executing +** successfully.  sqlite3_step() should not be called again on this virtual +** machine. +** +** 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_*() functions described below. 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(). +** +** SQLITE_MISUSE means that the this routine was called inappropriately. +** Perhaps it was called on a virtual machine that had already been +** finalized or on one that had previously returned SQLITE_ERROR or +** SQLITE_DONE.  Or it could be the case the the same database connection +** is being used simulataneously by two or more threads. +*/ +int sqlite3_step(sqlite3_stmt*); + +/* +** Return the number of values in the current row of the result set. +** +** After a call to sqlite3_step() that returns SQLITE_ROW, this routine +** will return the same value as the sqlite3_column_count() function. +** After sqlite3_step() has returned an SQLITE_DONE, SQLITE_BUSY or +** error code, or before sqlite3_step() has been called on a  +** compiled SQL statement, this routine returns zero. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** Values are stored in the database in one of the following fundamental +** types. +*/ +#define SQLITE_INTEGER  1 +#define SQLITE_FLOAT    2 +/* #define SQLITE_TEXT  3  // See below */ +#define SQLITE_BLOB     4 +#define SQLITE_NULL     5 + +/* +** SQLite version 2 defines SQLITE_TEXT differently.  To allow both +** version 2 and version 3 to be included, undefine them both if a +** conflict is seen.  Define SQLITE3_TEXT to be the version 3 value. +*/ +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT     3 +#endif +#define SQLITE3_TEXT     3 + +/* +** The next group of routines returns information about the information +** in a single column of the current result row of a query.  In every +** case the first parameter is a pointer to the SQL statement that is being +** executed (the sqlite_stmt* that was returned from sqlite3_prepare()) and +** the second argument is the index of the column for which information  +** should be returned.  iCol is zero-indexed.  The left-most column as an +** index of 0. +** +** If the SQL statement is not currently point to a valid row, or if the +** the colulmn index is out of range, the result is undefined. +** +** These routines attempt to convert the value where appropriate.  For +** example, if the internal representation is FLOAT and a text result +** is requested, sprintf() 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 an empty string +**       NULL             BLOB            Result is a zero-length BLOB +**       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 \000 terminator if needed +** +** The following access routines are provided: +** +** _type()     Return the datatype of the result.  This is one of +**             SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, +**             or SQLITE_NULL. +** _blob()     Return the value of a BLOB. +** _bytes()    Return the number of bytes in a BLOB value or the number +**             of bytes in a TEXT value represented as UTF-8.  The \000 +**             terminator is included in the byte count for TEXT values. +** _bytes16()  Return the number of bytes in a BLOB value or the number +**             of bytes in a TEXT value represented as UTF-16.  The \u0000 +**             terminator is included in the byte count for TEXT values. +** _double()   Return a FLOAT value. +** _int()      Return an INTEGER value in the host computer's native +**             integer representation.  This might be either a 32- or 64-bit +**             integer depending on the host. +** _int64()    Return an INTEGER value as a 64-bit signed integer. +** _text()     Return the value as UTF-8 text. +** _text16()   Return the value as UTF-16 text. +*/ +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); +sqlite_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); + +/* +** The sqlite3_finalize() function is called to delete a compiled +** SQL statement obtained by a previous call to sqlite3_prepare() +** or sqlite3_prepare16(). 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 is returned.  +** +** This routine can be called at any point during the execution of the +** virtual machine.  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 result code returned will be SQLITE_ABORT. +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** The sqlite3_reset() function is called to reset a compiled SQL +** statement obtained by a previous call to sqlite3_prepare() or +** sqlite3_prepare16() back to it's initial state, ready to be re-executed. +** Any SQL statement variables that had values bound to them using +** the sqlite3_bind_*() API retain their values. +*/ +int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** The following two functions are used to add user functions or aggregates +** implemented in C to the SQL langauge interpreted by SQLite. 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 handle that the new function or +** aggregate is to be added to. If a single program uses more than one +** database handle internally, then user functions or aggregates must  +** be added individually to each database handle with which they will be +** used. +** +** The third parameter is the number of arguments that the function or +** aggregate takes. If this parameter is negative, then the function or +** aggregate may take any number of arguments. +** +** The fourth parameter is one of SQLITE_UTF* values defined below, +** indicating the encoding that the function is most likely to handle +** values in.  This does not change the behaviour of the programming +** interface. However, if two versions of the same function are registered +** with different encoding values, SQLite invokes the version likely to +** minimize conversions between text encodings. +** +** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are +** pointers to user implemented C functions that implement the user +** function or aggregate. A scalar function requires an implementation of +** the xFunc callback only, NULL pointers should be passed as the xStep +** and xFinal parameters. An aggregate function requires an implementation +** of xStep and xFinal, but NULL should be passed for xFunc. To delete an +** existing user function or aggregate, pass NULL for all three function +** callback. Specifying an inconstent set of callback values, such as an +** xFunc and an xFinal, or an xStep but no xFinal, SQLITE_ERROR is +** returned. +*/ +int sqlite3_create_function( +  sqlite3 *, +  const char *zFunctionName, +  int nArg, +  int eTextRep, +  void*, +  void (*xFunc)(sqlite3_context*,int,sqlite3_value**), +  void (*xStep)(sqlite3_context*,int,sqlite3_value**), +  void (*xFinal)(sqlite3_context*) +); +int sqlite3_create_function16( +  sqlite3*, +  const void *zFunctionName, +  int nArg, +  int eTextRep, +  void*, +  void (*xFunc)(sqlite3_context*,int,sqlite3_value**), +  void (*xStep)(sqlite3_context*,int,sqlite3_value**), +  void (*xFinal)(sqlite3_context*) +); + +/* +** The next routine returns the number of calls to xStep for a particular +** aggregate function instance.  The current call to xStep counts so this +** routine always returns at least 1. +*/ +int sqlite3_aggregate_count(sqlite3_context*); + +/* +** The next group of routines returns information about parameters to +** a user-defined function.  Function implementations use these routines +** to access their parameters.  These routines are the same as the +** sqlite3_column_* routines except that these routines take a single +** sqlite3_value* pointer instead of an sqlite3_stmt* and an integer +** column number. +*/ +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*); +sqlite_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*); + +/* +** Aggregate functions use the following routine to allocate +** a structure for storing their state.  The first time this routine +** is called for a particular aggregate, a new structure of size nBytes +** is allocated, zeroed, and returned.  On subsequent calls (for the +** same aggregate instance) the same buffer is returned.  The implementation +** of the aggregate can use the returned buffer to accumulate data. +** +** The buffer allocated is freed automatically by SQLite. +*/ +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** The pUserData parameter to the sqlite3_create_function() and +** sqlite3_create_aggregate() routines used to register user functions +** is available to the implementation of the function using this +** call. +*/ +void *sqlite3_user_data(sqlite3_context*); + +/* +** The following two functions may be used by scalar user functions to +** associate meta-data with argument values. If the same value is passed to +** multiple invocations of the user-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. +** +** Calling sqlite3_get_auxdata() returns a pointer to the meta data +** associated with the Nth argument value to the current user function +** call, where N is the second parameter. If no meta-data has been set for +** that value, then a NULL pointer is returned. +** +** The sqlite3_set_auxdata() is used to associate meta data with a user +** function argument. The third parameter is a pointer to the meta data +** to be associated with the Nth user function argument value. The fourth +** parameter specifies a 'delete function' that will be called on the meta +** data pointer to release it when it is no longer required. If the delete +** function pointer is NULL, it is not invoked. +** +** In practice, meta-data is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and SQL variables. +*/ +void *sqlite3_get_auxdata(sqlite3_context*, int); +void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*)); + + +/* +** 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. +*/ +#define SQLITE_STATIC      ((void(*)(void *))0) +#define SQLITE_TRANSIENT   ((void(*)(void *))-1) + +/* +** User-defined functions invoke the following routines in order to +** set their return value. +*/ +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_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite_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*); + +/* +** These are the allowed values for the eTextRep argument to +** sqlite3_create_collation and sqlite3_create_function. +*/ +#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 */ + +/* +** These two functions are used to add new collation sequences to the +** sqlite3 handle specified as the first argument.  +** +** The name of the new collation sequence is specified as a UTF-8 string +** for sqlite3_create_collation() and a UTF-16 string for +** sqlite3_create_collation16(). In both cases the name is passed as the +** second function argument. +** +** The third argument must 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. +** +** A pointer to the user supplied routine must be passed as the fifth +** argument. If it is NULL, this is the same as deleting the collation +** sequence (so that SQLite cannot call it anymore). Each time the user +** 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. +** +** The remaining arguments to the user-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. The user 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). +*/ +int sqlite3_create_collation( +  sqlite3*,  +  const char *zName,  +  int eTextRep,  +  void*, +  int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_create_collation16( +  sqlite3*,  +  const char *zName,  +  int eTextRep,  +  void*, +  int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** 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. +** +** 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. If sqlite3_collation_needed16() is used, the names +** are passed as UTF-16 in machine native byte order. A call to either +** function replaces any existing callback. +** +** When the user-function is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** handle. The third argument is one of SQLITE_UTF8, SQLITE_UTF16BE or +** SQLITE_UTF16LE, indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence. +** +** The collation sequence is returned to SQLite by a collation-needed +** callback using the sqlite3_create_collation() or +** sqlite3_create_collation16() APIs, described above. +*/ +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 */ +); + +/* +** If the following global variable is made to point to a constant +** string which is the name of a 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. +** +** This variable should only be changed when there are no open databases. +** Once sqlite3_open() has been called, this variable should not be changed +** until all database connections are closed. +*/ +extern const char *sqlite3_temp_directory; + +#ifdef __cplusplus +}  /* End of the 'extern "C"' block */ +#endif +#endif diff --git a/ext/pdo_sqlite/sqlite/src/sqliteInt.h b/ext/pdo_sqlite/sqlite/src/sqliteInt.h new file mode 100644 index 0000000000..b4fa474ba9 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/sqliteInt.h @@ -0,0 +1,1419 @@ +/* +** 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$ +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** 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 + +#include "config.h" +#include "sqlite3.h" +#include "hash.h" +#include "parse.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. +*/ +#define MAX_PAGES   2000 +#define TEMP_PAGES   500 + +/* +** If the following macro is set to 1, then NULL values are considered +** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT +** compound queries.  No other SQL database engine (among those tested)  +** works this way except for OCELOT.  But the SQL92 spec implies that +** this is how things should work. +** +** If the following macro is set to 0, then NULLs are indistinct for +** SELECT DISTINCT and for UNION. +*/ +#define NULL_ALWAYS_DISTINCT 0 + +/* +** 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 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). +*/ +#define MAX_ATTACHED 10 + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#define SQLITE_MAX_VARIABLE_NUMBER 999 + +/* +** When building SQLite for embedded systems where memory is scarce, +** you can define one or more of the following macros to omit extra +** features of the library and thus keep the size of the library to +** a minimum. +*/ +/* #define SQLITE_OMIT_AUTHORIZATION  1 */ +/* #define SQLITE_OMIT_INMEMORYDB     1 */ +/* #define SQLITE_OMIT_VACUUM         1 */ +/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */ +/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */ + +/* +** 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 UINT64_TYPE +# if defined(_MSC_VER) || defined(__BORLANDC__) +#   define UINT64_TYPE unsigned __int64 +# else +#   define UINT64_TYPE unsigned long long int +# endif +#endif +#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 +#ifndef INTPTR_TYPE +# if SQLITE_PTR_SZ==4 +#   define INTPTR_TYPE int +# else +#   define INTPTR_TYPE sqlite_int64 +# endif +#endif +#ifndef UINTPTR_TYPE +# if SQLITE_PTR_SZ==4 +#   define UINTPTR_TYPE unsigned int +# else +#   define UINTPTR_TYPE sqlite_uint64 +# endif +#endif +typedef sqlite_int64 i64;          /* 8-byte signed integer */ +typedef UINT64_TYPE 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 */ +typedef INTPTR_TYPE ptr;           /* Big enough to hold a pointer */ +typedef UINTPTR_TYPE uptr;         /* Big enough to hold a pointer */ + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +extern const int sqlite3one; +#define SQLITE_BIGENDIAN    (*(char *)(&sqlite3one)==0) +#define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) + +/* +** 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 */ +}; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and  +** "BusyHandler typedefs. +*/ +#include "vdbe.h" +#include "btree.h" + +/* +** This macro casts a pointer to an integer.  Useful for doing +** pointer arithmetic. +*/ +#define Addr(X)  ((uptr)X) + +/* +** If memory allocation problems are found, recompile with +** +**      -DSQLITE_DEBUG=1 +** +** to enable some sanity checking on malloc() and free().  To +** check for memory leaks, recompile with +** +**      -DSQLITE_DEBUG=2 +** +** and a line of text will be written to standard error for +** each malloc() and free().  This output can be analyzed +** by an AWK script to determine if there are any leaks. +*/ +#ifdef SQLITE_DEBUG +# define sqliteMalloc(X)    sqlite3Malloc_(X,1,__FILE__,__LINE__) +# define sqliteMallocRaw(X) sqlite3Malloc_(X,0,__FILE__,__LINE__) +# define sqliteFree(X)      sqlite3Free_(X,__FILE__,__LINE__) +# define sqliteRealloc(X,Y) sqlite3Realloc_(X,Y,__FILE__,__LINE__) +# define sqliteStrDup(X)    sqlite3StrDup_(X,__FILE__,__LINE__) +# define sqliteStrNDup(X,Y) sqlite3StrNDup_(X,Y,__FILE__,__LINE__) +#else +# define sqliteFree          sqlite3FreeX +# define sqliteMalloc        sqlite3Malloc +# define sqliteMallocRaw     sqlite3MallocRaw +# define sqliteRealloc       sqlite3Realloc +# define sqliteStrDup        sqlite3StrDup +# define sqliteStrNDup       sqlite3StrNDup +#endif + +/* +** This variable gets set if malloc() ever fails.  After it gets set, +** the SQLite library shuts down permanently. +*/ +extern int sqlite3_malloc_failed; + +/* +** The following global variables are used for testing and debugging +** only.  They only work if SQLITE_DEBUG is defined. +*/ +#ifdef SQLITE_DEBUG +extern int sqlite3_nMalloc;       /* Number of sqliteMalloc() calls */ +extern int sqlite3_nFree;         /* Number of sqliteFree() calls */ +extern int sqlite3_iMallocFail;   /* Fail sqliteMalloc() after this many calls */ +#endif + +/* +** 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)  (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 Column Column; +typedef struct Table Table; +typedef struct Index Index; +typedef struct Instruction Instruction; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct Parse Parse; +typedef struct Token Token; +typedef struct IdList IdList; +typedef struct SrcList SrcList; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; +typedef struct Select Select; +typedef struct AggExpr AggExpr; +typedef struct FuncDef FuncDef; +typedef struct Trigger Trigger; +typedef struct TriggerStep TriggerStep; +typedef struct TriggerStack TriggerStack; +typedef struct FKey FKey; +typedef struct Db Db; +typedef struct AuthContext AuthContext; +typedef struct KeyClass KeyClass; +typedef struct CollSeq CollSeq; +typedef struct KeyInfo KeyInfo; + +/* +** 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 */ +  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 */ +  u16 flags;           /* Flags associated with this database */ +  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */ +  u8 safety_level;     /* How aggressive at synching data to disk */ +  int cache_size;      /* Number of pages to use in the cache */ +  void *pAux;          /* Auxiliary data.  Usually NULL */ +  void (*xFreeAux)(void*);  /* Routine to free pAux */ +}; + +/* +** These macros can be used to test, set, or clear bits in the  +** Db.flags field. +*/ +#define DbHasProperty(D,I,P)     (((D)->aDb[I].flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P)  (((D)->aDb[I].flags&(P))!=0) +#define DbSetProperty(D,I,P)     (D)->aDb[I].flags|=(P) +#define DbClearProperty(D,I,P)   (D)->aDb[I].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 SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) + +/* +** 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 { +  int nDb;                      /* Number of backends currently in use */ +  Db *aDb;                      /* All backends */ +  Db aDbStatic[2];              /* Static space for the 2 default backends */ +  int flags;                    /* Miscellanous flags. See below */ +  u8 file_format;               /* What file format version is this database? */ +  u8 temp_store;                /* 1: file 2: memory 0: default */ +  int nTable;                   /* Number of tables in the database */ +  BusyHandler busyHandler;      /* Busy callback */ +  void *pCommitArg;             /* Argument to xCommitCallback() */    +  int (*xCommitCallback)(void*);/* Invoked at every commit. */ +  Hash aFunc;                   /* All functions that can be in SQL exprs */ +  Hash aCollSeq;                /* All collating sequences */ +  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() */ +  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; +  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 */ +#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 + +  int errCode;                  /* Most recent error code (SQLITE_*) */ +  u8 enc;                       /* Text encoding for this database. */ +  u8 autoCommit;                /* The auto-commit flag. */ +  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); +  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); +  void *pCollNeededArg; +  sqlite3_value *pValue;        /* Value used for transient conversions */ +  sqlite3_value *pErr;          /* Most recent error message */ + +  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */ +  char *zErrMsg16;              /* Most recent error message (UTF-8 encoded) */ +}; + +/* +** 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_Initialized    0x00000002  /* True after initialization */ +#define SQLITE_Interrupt      0x00000004  /* Cancel current operation */ +#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 */ + +/* +** 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_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 { +  char *zName;         /* SQL name of the function */ +  int nArg;            /* Number of arguments.  -1 means unlimited */ +  u8 iPrefEnc;         /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ +  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 */ +  u8 needCollSeq;      /* True if sqlite3GetFuncCollSeq() might be called */ +}; + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { +  char *zName;     /* Name of this column */ +  char *zDflt;     /* Default value of this column */ +  char *zType;     /* Data type for this column */ +  CollSeq *pColl;  /* 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 */ +}; + +/* +** 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 +** transalations, 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() */ +  void *pUser;         /* First argument to xCmp() */ +  int (*xCmp)(void*,int, const void*, int, const void*); +}; + +/* +** 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. +*/ +#define SQLITE_AFF_INTEGER  'i' +#define SQLITE_AFF_NUMERIC  'n' +#define SQLITE_AFF_TEXT     't' +#define SQLITE_AFF_NONE     'o' + + +/* +** 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.isTransient +** 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. */ +  u8 readOnly;     /* True if this table should not be written by the user */ +  u8 iDb;          /* Index into sqlite.aDb[] of the backend for this table */ +  u8 isTransient;  /* True if automatically deleted when VDBE finishes */ +  u8 hasPrimKey;   /* True if there exists a primary key */ +  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */ +  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 */ +}; + +/* +** 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 contraint +** 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 larger. +*/ +struct KeyInfo { +  u8 enc;             /* Text encoding - one of the TEXT_Utf* values */ +  u8 incrKey;         /* Increase 2nd key by epsilon before comparison */ +  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 */ +  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) */ +  u8 iDb;          /* Index in sqlite.aDb[] of where this index is stored */ +  char *zColAff;   /* String defining the affinity of each column */ +  Index *pNext;    /* The next index associated with the same table */ +  KeyInfo keyInfo; /* Info on how to order keys.  MUST BE LAST */ +}; + +/* +** 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 */ +}; + +/* +** 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. +** +** 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. +*/ +struct Expr { +  u8 op;                 /* Operation performed by this node */ +  char affinity;         /* The affinity of the column or 0 if not a column */ +  u8 iDb;                /* Database referenced by this expression */ +  u8 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 "<expr> IN (<expr-list)" */ +  Token token;           /* An operand token */ +  Token span;            /* Complete text of the expression */ +  int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the +                         ** iColumn-th field of the iTable-th table. */ +  int iAgg;              /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull +                         ** result from the iAgg-th element of the aggregator */ +  Select *pSelect;       /* When the expression is a sub-select.  Also the +                         ** right side of "<expr> IN (<select>)" */ +}; + +/* +** The following are the meanings of bits in the Expr.flags field. +*/ +#define EP_FromJoin     0x0001  /* Originated in ON or USING clause of a join */ + +/* +** These macros can be used to test, set, or clear bits in the  +** Expr.flags field. +*/ +#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P)) +#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0) +#define ExprSetProperty(E,P)     (E)->flags|=(P) +#define ExprClearProperty(E,P)   (E)->flags&=~(P) + +/* +** A list of expressions.  Each expression may optionally have a +** name.  An expr/name combination can be used in several ways, such +** as the list of "expr AS ID" fields following a "SELECT" or in the +** list of "ID = expr" items in an UPDATE.  A list of expressions can +** also be used as the argument to a function, in which case the a.zName +** field is not used. +*/ +struct ExprList { +  int nExpr;             /* Number of expressions on the list */ +  int nAlloc;            /* Number of entries allocated below */ +  struct ExprList_item { +    Expr *pExpr;           /* The list of expressions */ +    char *zName;           /* Token associated with this expression */ +    u8 sortOrder;          /* 1 for DESC or 0 for ASC */ +    u8 isAgg;              /* True if this is an aggregate like count(*) */ +    u8 done;               /* A flag to indicate when processing is finished */ +  } *a;                  /* One entry for each expression */ +}; + +/* +** An instance of this structure can hold a simple list of identifiers, +** such as the list "a,b,c" in the following statements: +** +**      INSERT INTO t(a,b,c) VALUES ...; +**      CREATE INDEX idx ON t(a,b,c); +**      CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...; +** +** The IdList.a.idx field is used when the IdList represents the list of +** column names after a table name in an INSERT statement.  In the statement +** +**     INSERT INTO t(a,b,c) ... +** +** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. +*/ +struct IdList { +  int nId;         /* Number of identifiers on the list */ +  int nAlloc;      /* Number of entries allocated for a[] below */ +  struct IdList_item { +    char *zName;      /* Name of the identifier */ +    int idx;          /* Index in some Table.aCol[] of a column named zName */ +  } *a; +}; + +/* +** The following structure describes the FROM clause of a SELECT statement. +** Each table or subquery in the FROM clause is a separate element of +** the SrcList.a[] array. +** +** With the addition of multiple database support, the following structure +** can also be used to describe a particular table such as the table that +** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL, +** such a table must be a simple name: ID.  But in SQLite, the table can +** now be identified by a database name, a dot, then the table name: ID.ID. +*/ +struct SrcList { +  i16 nSrc;        /* Number of tables or subqueries in the FROM clause */ +  i16 nAlloc;      /* Number of entries allocated in a[] below */ +  struct SrcList_item { +    char *zDatabase;  /* Name of database holding this table */ +    char *zName;      /* Name of the table */ +    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */ +    Table *pTab;      /* An SQL table corresponding to zName */ +    Select *pSelect;  /* A SELECT statement used in place of a table name */ +    int jointype;     /* Type of join between this table and the next */ +    int iCursor;      /* The VDBE cursor number used to access this table */ +    Expr *pOn;        /* The ON clause of a join */ +    IdList *pUsing;   /* The USING clause of a join */ +  } a[1];             /* One entry for each identifier on the list */ +}; + +/* +** Permitted values of the SrcList.a.jointype field +*/ +#define JT_INNER     0x0001    /* Any kind of inner or cross join */ +#define JT_NATURAL   0x0002    /* True for a "natural" join */ +#define JT_LEFT      0x0004    /* Left outer join */ +#define JT_RIGHT     0x0008    /* Right outer join */ +#define JT_OUTER     0x0010    /* The "OUTER" keyword is present */ +#define JT_ERROR     0x0020    /* unknown or unsupported join type */ + +/* +** For each nested loop in a WHERE clause implementation, the WhereInfo +** structure contains a single instance of this structure.  This structure +** is intended to be private the the where.c module and should not be +** access or modified by other modules. +*/ +struct WhereLevel { +  int iMem;            /* Memory cell used by this level */ +  Index *pIdx;         /* Index used */ +  int iCur;            /* Cursor number used for this index */ +  int score;           /* How well this indexed scored */ +  int brk;             /* Jump here to break out of the loop */ +  int cont;            /* Jump here to continue with the next loop cycle */ +  int op, p1, p2;      /* Opcode used to terminate the loop */ +  int iLeftJoin;       /* Memory cell used to implement LEFT OUTER JOIN */ +  int top;             /* First instruction of interior of the loop */ +  int inOp, inP1, inP2;/* Opcode used to implement an IN operator */ +  int bRev;            /* Do the scan in the reverse direction */ +}; + +/* +** The WHERE clause processing routine has two halves.  The +** first part does the start of the WHERE loop and the second +** half does the tail of the WHERE loop.  An instance of +** this structure is returned by the first half and passed +** into the second half to give some continuity. +*/ +struct WhereInfo { +  Parse *pParse; +  SrcList *pTabList;   /* List of tables in the join */ +  int iContinue;       /* Jump here to continue with next record */ +  int iBreak;          /* Jump here to break out of the loop */ +  int nLevel;          /* Number of nested loop */ +  WhereLevel a[1];     /* Information about each nest loop in the WHERE */ +}; + +/* +** An instance of the following structure contains all information +** needed to generate code for a single SELECT statement. +** +** The zSelect field is used when the Select structure must be persistent. +** Normally, the expression tree points to tokens in the original input +** string that encodes the select.  But if the Select structure must live +** longer than its input string (for example when it is used to describe +** a VIEW) we have to make a copy of the input string so that the nodes +** of the expression tree will have something to point to.  zSelect is used +** to hold that copy. +** +** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0. +** If there is a LIMIT clause, the parser sets nLimit to the value of the +** limit and nOffset to the value of the offset (or 0 if there is not +** offset).  But later on, nLimit and nOffset become the memory locations +** in the VDBE that record the limit and offset counters. +*/ +struct Select { +  ExprList *pEList;      /* The fields of the result */ +  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ +  u8 isDistinct;         /* True if the DISTINCT keyword is present */ +  SrcList *pSrc;         /* The FROM clause */ +  Expr *pWhere;          /* The WHERE clause */ +  ExprList *pGroupBy;    /* The GROUP BY clause */ +  Expr *pHaving;         /* The HAVING clause */ +  ExprList *pOrderBy;    /* The ORDER BY clause */ +  Select *pPrior;        /* Prior select in a compound select statement */ +  int nLimit, nOffset;   /* LIMIT and OFFSET values.  -1 means not used */ +  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */ +  char *zSelect;         /* Complete text of the SELECT command */ +  IdList **ppOpenTemp;   /* OP_OpenTemp addresses used by multi-selects */ +}; + +/* +** The results of a select can be distributed in several ways. +*/ +#define SRT_Callback     1  /* Invoke a callback with each row of result */ +#define SRT_Mem          2  /* Store result in a memory cell */ +#define SRT_Set          3  /* Store result as unique keys in a table */ +#define SRT_Union        5  /* Store result as keys in a table */ +#define SRT_Except       6  /* Remove result from a UNION table */ +#define SRT_Table        7  /* Store result as data with a unique key */ +#define SRT_TempTable    8  /* Store result in a trasient table */ +#define SRT_Discard      9  /* Do not save the results anywhere */ +#define SRT_Sorter      10  /* Store results in the sorter */ +#define SRT_Subroutine  11  /* Call a subroutine to handle results */ + +/* +** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)") +** we have to do some additional analysis of expressions.  An instance +** of the following structure holds information about a single subexpression +** somewhere in the SELECT statement.  An array of these structures holds +** all the information we need to generate code for aggregate +** expressions. +** +** Note that when analyzing a SELECT containing aggregates, both +** non-aggregate field variables and aggregate functions are stored +** in the AggExpr array of the Parser structure. +** +** The pExpr field points to an expression that is part of either the +** field list, the GROUP BY clause, the HAVING clause or the ORDER BY +** clause.  The expression will be freed when those clauses are cleaned +** up.  Do not try to delete the expression attached to AggExpr.pExpr. +** +** If AggExpr.pExpr==0, that means the expression is "count(*)". +*/ +struct AggExpr { +  int isAgg;        /* if TRUE contains an aggregate function */ +  Expr *pExpr;      /* The expression */ +  FuncDef *pFunc;   /* Information about the aggregate function */ +}; + +/* +** An SQL parser context.  A copy of this structure is passed through +** the parser and down into all the parser action routine in order to +** carry around information that is global to the entire parse. +*/ +struct Parse { +  sqlite3 *db;         /* The main database structure */ +  int rc;              /* Return code from execution */ +  char *zErrMsg;       /* An error message */ +  Token sErrToken;     /* The token at which the error occurred */ +  Token sNameToken;    /* Token with unqualified schema object name */ +  Token sLastToken;    /* The last token parsed */ +  const char *zSql;    /* All SQL text */ +  const char *zTail;   /* All SQL text past the last semicolon parsed */ +  Table *pNewTable;    /* A table being constructed by CREATE TABLE */ +  Vdbe *pVdbe;         /* An engine for executing database bytecode */ +  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */ +  u8 explain;          /* True if the EXPLAIN flag is found on the query */ +  u8 nameClash;        /* A permanent table name clashes with temp table name */ +  u8 useAgg;           /* If true, extract field values from the aggregator +                       ** while generating expressions.  Normally false */ +  u8 checkSchema;      /* Causes schema cookie check after an error */ +  int nErr;            /* Number of errors seen */ +  int nTab;            /* Number of previously allocated VDBE cursors */ +  int nMem;            /* Number of memory cells used so far */ +  int nSet;            /* Number of sets used so far */ +  int nAgg;            /* Number of aggregate expressions */ +  int nVar;            /* Number of '?' variables seen in the SQL so far */ +  int nVarExpr;        /* Number of used slots in apVarExpr[] */ +  int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */ +  Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */ +  AggExpr *aAgg;       /* An array of aggregate expressions */ +  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ +  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */ +  TriggerStack *trigStack;  /* Trigger actions being coded */ +  u32 cookieMask;      /* Bitmask of schema verified databases */ +  int cookieValue[MAX_ATTACHED+2];  /* Values of cookies to verify */ +  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */ +  u32 writeMask;       /* Start a write transaction on these databases */ +}; + +/* +** An instance of the following structure can be declared on a stack and used +** to save the Parse.zAuthContext value so that it can be restored later. +*/ +struct AuthContext { +  const char *zAuthContext;   /* Put saved Parse.zAuthContext here */ +  Parse *pParse;              /* The Parse structure */ +}; + +/* +** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete +*/ +#define OPFLAG_NCHANGE   1    /* Set to update db->nChange */ +#define OPFLAG_LASTROWID 2    /* Set to update db->lastRowid */ + +/* + * Each trigger present in the database schema is stored as an instance of + * struct Trigger.  + * + * Pointers to instances of struct Trigger are stored in two ways. + * 1. In the "trigHash" hash table (part of the sqlite3* that represents the  + *    database). This allows Trigger structures to be retrieved by name. + * 2. All triggers associated with a single table form a linked list, using the + *    pNext member of struct Trigger. A pointer to the first element of the + *    linked list is stored as the "pTrigger" member of the associated + *    struct Table. + * + * The "step_list" member points to the first element of a linked list + * containing the SQL statements specified as the trigger program. + */ +struct Trigger { +  char *name;             /* The name of the trigger                        */ +  char *table;            /* The table or view to which the trigger applies */ +  u8 iDb;                 /* Database containing this trigger               */ +  u8 iTabDb;              /* Database containing Trigger.table              */ +  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */ +  u8 tr_tm;               /* One of TK_BEFORE, TK_AFTER */ +  Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */ +  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger, +                             the <column-list> is stored here */ +  int foreach;            /* One of TK_ROW or TK_STATEMENT */ +  Token nameToken;        /* Token containing zName. Use during parsing only */ + +  TriggerStep *step_list; /* Link list of trigger program steps             */ +  Trigger *pNext;         /* Next trigger associated with the table */ +}; + +/* + * An instance of struct TriggerStep is used to store a single SQL statement + * that is a part of a trigger-program.  + * + * Instances of struct TriggerStep are stored in a singly linked list (linked + * using the "pNext" member) referenced by the "step_list" member of the  + * associated struct Trigger instance. The first element of the linked list is + * the first step of the trigger-program. + *  + * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or + * "SELECT" statement. The meanings of the other members is determined by the  + * value of "op" as follows: + * + * (op == TK_INSERT) + * orconf    -> stores the ON CONFLICT algorithm + * pSelect   -> If this is an INSERT INTO ... SELECT ... statement, then + *              this stores a pointer to the SELECT statement. Otherwise NULL. + * target    -> A token holding the name of the table to insert into. + * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then + *              this stores values to be inserted. Otherwise NULL. + * pIdList   -> If this is an INSERT INTO ... (<column-names>) VALUES ...  + *              statement, then this stores the column-names to be + *              inserted into. + * + * (op == TK_DELETE) + * target    -> A token holding the name of the table to delete from. + * pWhere    -> The WHERE clause of the DELETE statement if one is specified. + *              Otherwise NULL. + *  + * (op == TK_UPDATE) + * target    -> A token holding the name of the table to update rows of. + * pWhere    -> The WHERE clause of the UPDATE statement if one is specified. + *              Otherwise NULL. + * pExprList -> A list of the columns to update and the expressions to update + *              them to. See sqlite3Update() documentation of "pChanges" + *              argument. + *  + */ +struct TriggerStep { +  int op;              /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ +  int orconf;          /* OE_Rollback etc. */ +  Trigger *pTrig;      /* The trigger that this step is a part of */ + +  Select *pSelect;     /* Valid for SELECT and sometimes  +			  INSERT steps (when pExprList == 0) */ +  Token target;        /* Valid for DELETE, UPDATE, INSERT steps */ +  Expr *pWhere;        /* Valid for DELETE, UPDATE steps */ +  ExprList *pExprList; /* Valid for UPDATE statements and sometimes  +			   INSERT steps (when pSelect == 0)         */ +  IdList *pIdList;     /* Valid for INSERT statements only */ + +  TriggerStep * pNext; /* Next in the link-list */ +}; + +/* + * An instance of struct TriggerStack stores information required during code + * generation of a single trigger program. While the trigger program is being + * coded, its associated TriggerStack instance is pointed to by the + * "pTriggerStack" member of the Parse structure. + * + * The pTab member points to the table that triggers are being coded on. The  + * newIdx member contains the index of the vdbe cursor that points at the temp + * table that stores the new.* references. If new.* references are not valid + * for the trigger being coded (for example an ON DELETE trigger), then newIdx + * is set to -1. The oldIdx member is analogous to newIdx, for old.* references. + * + * The ON CONFLICT policy to be used for the trigger program steps is stored  + * as the orconf member. If this is OE_Default, then the ON CONFLICT clause  + * specified for individual triggers steps is used. + * + * struct TriggerStack has a "pNext" member, to allow linked lists to be + * constructed. When coding nested triggers (triggers fired by other triggers) + * each nested trigger stores its parent trigger's TriggerStack as the "pNext"  + * pointer. Once the nested trigger has been coded, the pNext value is restored + * to the pTriggerStack member of the Parse stucture and coding of the parent + * trigger continues. + * + * Before a nested trigger is coded, the linked list pointed to by the  + * pTriggerStack is scanned to ensure that the trigger is not about to be coded + * recursively. If this condition is detected, the nested trigger is not coded. + */ +struct TriggerStack { +  Table *pTab;         /* Table that triggers are currently being coded on */ +  int newIdx;          /* Index of vdbe cursor to "new" temp table */ +  int oldIdx;          /* Index of vdbe cursor to "old" temp table */ +  int orconf;          /* Current orconf policy */ +  int ignoreJump;      /* where to jump to for a RAISE(IGNORE) */ +  Trigger *pTrigger;   /* The trigger currently being coded */ +  TriggerStack *pNext; /* Next trigger down on the trigger stack */ +}; + +/* +** The following structure contains information used by the sqliteFix... +** routines as they walk the parse tree to make database references +** explicit.   +*/ +typedef struct DbFixer DbFixer; +struct DbFixer { +  Parse *pParse;      /* The parsing context.  Error messages written here */ +  const char *zDb;    /* Make sure all objects are contained in this database */ +  const char *zType;  /* Type of the container - used for error messages */ +  const Token *pName; /* Name of the container - used for error messages */ +}; + +/* +** A pointer to this structure is used to communicate information +** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. +*/ +typedef struct { +  sqlite3 *db;        /* The database being initialized */ +  char **pzErrMsg;    /* Error message stored here */ +} InitData; + + +/* + * This global flag is set for performance testing of triggers. When it is set + * SQLite will perform the overhead of building new and old trigger references  + * even when no triggers exist + */ +extern int sqlite3_always_code_trigger_setup; + +/* +** Internal function prototypes +*/ +int sqlite3StrICmp(const char *, const char *); +int sqlite3StrNICmp(const char *, const char *, int); +int sqlite3HashNoCase(const char *, int); +int sqlite3IsNumber(const char*, int*, u8); +int sqlite3Compare(const char *, const char *); +int sqlite3SortCompare(const char *, const char *); +void sqlite3RealToSortable(double r, char *); +#ifdef SQLITE_DEBUG +  void *sqlite3Malloc_(int,int,char*,int); +  void sqlite3Free_(void*,char*,int); +  void *sqlite3Realloc_(void*,int,char*,int); +  char *sqlite3StrDup_(const char*,char*,int); +  char *sqlite3StrNDup_(const char*, int,char*,int); +  void sqlite3CheckMemory(void*,int); +#else +  void *sqlite3Malloc(int); +  void *sqlite3MallocRaw(int); +  void sqlite3Free(void*); +  void *sqlite3Realloc(void*,int); +  char *sqlite3StrDup(const char*); +  char *sqlite3StrNDup(const char*, int); +# define sqlite3CheckMemory(a,b) +#endif +void sqlite3FreeX(void*); +char *sqlite3MPrintf(const char*, ...); +char *sqlite3VMPrintf(const char*, va_list); +void sqlite3DebugPrintf(const char*, ...); +void *sqlite3TextToPtr(const char*); +void sqlite3SetString(char **, const char *, ...); +void sqlite3ErrorMsg(Parse*, const char*, ...); +void sqlite3Dequote(char*); +int sqlite3KeywordCode(const char*, int); +int sqlite3RunParser(Parse*, const char*, char **); +void sqlite3FinishCoding(Parse*); +Expr *sqlite3Expr(int, Expr*, Expr*, Token*); +Expr *sqlite3ExprAnd(Expr*, Expr*); +void sqlite3ExprSpan(Expr*,Token*,Token*); +Expr *sqlite3ExprFunction(ExprList*, Token*); +void sqlite3ExprAssignVarNumber(Parse*, Expr*); +void sqlite3ExprDelete(Expr*); +ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*); +void sqlite3ExprListDelete(ExprList*); +int sqlite3Init(sqlite3*, char**); +int sqlite3InitCallback(void*, int, char**, char**); +void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); +void sqlite3ResetInternalSchema(sqlite3*, int); +void sqlite3BeginParse(Parse*,int); +void sqlite3RollbackInternalChanges(sqlite3*); +void sqlite3CommitInternalChanges(sqlite3*); +Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); +void sqlite3OpenMasterTable(Vdbe *v, int); +void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); +void sqlite3AddColumn(Parse*,Token*); +void sqlite3AddNotNull(Parse*, int); +void sqlite3AddPrimaryKey(Parse*, ExprList*, int); +void sqlite3AddColumnType(Parse*,Token*,Token*); +void sqlite3AddDefaultValue(Parse*,Token*,int); +void sqlite3AddCollateType(Parse*, const char*, int); +void sqlite3EndTable(Parse*,Token*,Select*); +void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int); +int sqlite3ViewGetColumnNames(Parse*,Table*); +void sqlite3DropTable(Parse*, SrcList*, int); +void sqlite3DeleteTable(sqlite3*, Table*); +void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); +IdList *sqlite3IdListAppend(IdList*, Token*); +int sqlite3IdListIndex(IdList*,const char*); +SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); +void sqlite3SrcListAddAlias(SrcList*, Token*); +void sqlite3SrcListAssignCursors(Parse*, SrcList*); +void sqlite3IdListDelete(IdList*); +void sqlite3SrcListDelete(SrcList*); +void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, +                        Token*); +void sqlite3DropIndex(Parse*, SrcList*); +void sqlite3AddKeyType(Vdbe*, ExprList*); +void sqlite3AddIdxKeyType(Vdbe*, Index*); +int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); +Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, +                        int,int,int); +void sqlite3SelectDelete(Select*); +void sqlite3SelectUnbind(Select*); +Table *sqlite3SrcListLookup(Parse*, SrcList*); +int sqlite3IsReadOnly(Parse*, Table*, int); +void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*); +void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); +void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); +WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**); +void sqlite3WhereEnd(WhereInfo*); +void sqlite3ExprCode(Parse*, Expr*); +int sqlite3ExprCodeExprList(Parse*, ExprList*); +void sqlite3ExprIfTrue(Parse*, Expr*, int, int); +void sqlite3ExprIfFalse(Parse*, Expr*, int, int); +Table *sqlite3FindTable(sqlite3*,const char*, const char*); +Table *sqlite3LocateTable(Parse*,const char*, const char*); +Index *sqlite3FindIndex(sqlite3*,const char*, const char*); +void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); +void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); +void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); +void sqlite3Vacuum(Parse*, Token*); +int sqlite3RunVacuum(char**, sqlite3*); +char *sqlite3NameFromToken(Token*); +int sqlite3ExprCheck(Parse*, Expr*, int, int*); +int sqlite3ExprCompare(Expr*, Expr*); +int sqliteFuncId(Token*); +int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*); +int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*); +int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); +Vdbe *sqlite3GetVdbe(Parse*); +void sqlite3Randomness(int, void*); +void sqlite3RollbackAll(sqlite3*); +void sqlite3CodeVerifySchema(Parse*, int); +void sqlite3BeginTransaction(Parse*, int); +void sqlite3CommitTransaction(Parse*); +void sqlite3RollbackTransaction(Parse*); +int sqlite3ExprIsConstant(Expr*); +int sqlite3ExprIsInteger(Expr*, int*); +int sqlite3IsRowid(const char*); +void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int); +void sqlite3GenerateRowIndexDelete(sqlite3*, Vdbe*, Table*, int, char*); +void sqlite3GenerateIndexKey(Vdbe*, Index*, int); +void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); +void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); +void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); +void sqlite3BeginWriteOperation(Parse*, int, int); +Expr *sqlite3ExprDup(Expr*); +void sqlite3TokenCopy(Token*, Token*); +ExprList *sqlite3ExprListDup(ExprList*); +SrcList *sqlite3SrcListDup(SrcList*); +IdList *sqlite3IdListDup(IdList*); +Select *sqlite3SelectDup(Select*); +FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); +void sqlite3RegisterBuiltinFunctions(sqlite3*); +void sqlite3RegisterDateTimeFunctions(sqlite3*); +int sqlite3SafetyOn(sqlite3*); +int sqlite3SafetyOff(sqlite3*); +int sqlite3SafetyCheck(sqlite3*); +void sqlite3ChangeCookie(sqlite3*, Vdbe*, int); +void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, +                         int,Expr*,int); +void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); +void sqlite3DropTrigger(Parse*, SrcList*); +void sqlite3DropTriggerPtr(Parse*, Trigger*, int); +int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*); +int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,  +                         int, int); +void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); +void sqlite3DeleteTriggerStep(TriggerStep*); +TriggerStep *sqlite3TriggerSelectStep(Select*); +TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*, Select*, int); +TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int); +TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*); +void sqlite3DeleteTrigger(Trigger*); +int sqlite3JoinType(Parse*, Token*, Token*, Token*); +void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); +void sqlite3DeferForeignKey(Parse*, int); +#ifndef SQLITE_OMIT_AUTHORIZATION +  void sqlite3AuthRead(Parse*,Expr*,SrcList*); +  int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); +  void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); +  void sqlite3AuthContextPop(AuthContext*); +#else +# define sqlite3AuthRead(a,b,c) +# define sqlite3AuthCheck(a,b,c,d,e)    SQLITE_OK +# define sqlite3AuthContextPush(a,b,c) +# define sqlite3AuthContextPop(a)  ((void)(a)) +#endif +void sqlite3Attach(Parse*, Token*, Token*, int, Token*); +void sqlite3Detach(Parse*, Token*); +int sqlite3BtreeFactory(const sqlite3 *db, const char *zFilename, +                       int omitJournal, int nCache, Btree **ppBtree); +int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); +int sqlite3FixSrcList(DbFixer*, SrcList*); +int sqlite3FixSelect(DbFixer*, Select*); +int sqlite3FixExpr(DbFixer*, Expr*); +int sqlite3FixExprList(DbFixer*, ExprList*); +int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); +double sqlite3AtoF(const char *z, const char **); +char *sqlite3_snprintf(int,char*,const char*,...); +int sqlite3GetInt32(const char *, int*); +int sqlite3FitsIn64Bits(const char *); +int sqlite3utf16ByteLen(const void *pData, int nChar); +int sqlite3utf8CharLen(const char *pData, int nByte); +int sqlite3ReadUtf8(const unsigned char *); +int sqlite3PutVarint(unsigned char *, u64); +int sqlite3GetVarint(const unsigned char *, u64 *); +int sqlite3GetVarint32(const unsigned char *, u32 *); +int sqlite3VarintLen(u64 v); +char sqlite3AffinityType(const char *, int); +void sqlite3IndexAffinityStr(Vdbe *, Index *); +void sqlite3TableAffinityStr(Vdbe *, Table *); +char sqlite3CompareAffinity(Expr *pExpr, char aff2); +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +char sqlite3ExprAffinity(Expr *pExpr); +int sqlite3atoi64(const char*, i64*); +void sqlite3Error(sqlite3*, int, const char*,...); +void *sqlite3HexToBlob(const char *z); +int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); +const char *sqlite3ErrStr(int); +int sqlite3ReadUniChar(const char *zStr, int *pOffset, u8 *pEnc, int fold); +int sqlite3ReadSchema(Parse *pParse); +CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int); +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName); +CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +int sqlite3CheckCollSeq(Parse *, CollSeq *); +int sqlite3CheckIndexCollSeq(Parse *, Index *); +int sqlite3CheckObjectName(Parse *, const char *); +void sqlite3VdbeSetChanges(sqlite3 *, int); +void sqlite3utf16Substr(sqlite3_context *,int,sqlite3_value **); + +const void *sqlite3ValueText(sqlite3_value*, u8); +int sqlite3ValueBytes(sqlite3_value*, u8); +void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); +void sqlite3ValueFree(sqlite3_value*); +sqlite3_value *sqlite3ValueNew(); +sqlite3_value *sqlite3GetTransientValue(sqlite3*db); +extern const unsigned char sqlite3UpperToLower[]; + +#endif diff --git a/ext/pdo_sqlite/sqlite/src/table.c b/ext/pdo_sqlite/sqlite/src/table.c new file mode 100644 index 0000000000..d4ef2c8a78 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/table.c @@ -0,0 +1,195 @@ +/* +** 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 the sqlite3_get_table() and sqlite3_free_table() +** interface routines.  These are just wrappers around the main +** interface routine of sqlite3_exec(). +** +** These routines are in a separate files so that they will not be linked +** if they are not used. +*/ +#include <stdlib.h> +#include <string.h> +#include "sqliteInt.h" + +/* +** This structure is used to pass data from sqlite3_get_table() through +** to the callback function is uses to build the result. +*/ +typedef struct TabResult { +  char **azResult; +  char *zErrMsg; +  int nResult; +  int nAlloc; +  int nRow; +  int nColumn; +  int nData; +  int rc; +} TabResult; + +/* +** This routine is called once for each row in the result table.  Its job +** is to fill in the TabResult structure appropriately, allocating new +** memory as necessary. +*/ +static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ +  TabResult *p = (TabResult*)pArg; +  int need; +  int i; +  char *z; + +  /* Make sure there is enough space in p->azResult to hold everything +  ** we need to remember from this invocation of the callback. +  */ +  if( p->nRow==0 && argv!=0 ){ +    need = nCol*2; +  }else{ +    need = nCol; +  } +  if( p->nData + need >= p->nAlloc ){ +    char **azNew; +    p->nAlloc = p->nAlloc*2 + need + 1; +    azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc ); +    if( azNew==0 ) goto malloc_failed; +    p->azResult = azNew; +  } + +  /* If this is the first row, then generate an extra row containing +  ** the names of all columns. +  */ +  if( p->nRow==0 ){ +    p->nColumn = nCol; +    for(i=0; i<nCol; i++){ +      if( colv[i]==0 ){ +        z = 0; +      }else{ +        z = malloc( strlen(colv[i])+1 ); +        if( z==0 ) goto malloc_failed; +        strcpy(z, colv[i]); +      } +      p->azResult[p->nData++] = z; +    } +  }else if( p->nColumn!=nCol ){ +    sqlite3SetString(&p->zErrMsg, +       "sqlite3_get_table() called with two or more incompatible queries", +       (char*)0); +    p->rc = SQLITE_ERROR; +    return 1; +  } + +  /* Copy over the row data +  */ +  if( argv!=0 ){ +    for(i=0; i<nCol; i++){ +      if( argv[i]==0 ){ +        z = 0; +      }else{ +        z = malloc( strlen(argv[i])+1 ); +        if( z==0 ) goto malloc_failed; +        strcpy(z, argv[i]); +      } +      p->azResult[p->nData++] = z; +    } +    p->nRow++; +  } +  return 0; + +malloc_failed: +  p->rc = SQLITE_NOMEM; +  return 1; +} + +/* +** Query the database.  But instead of invoking a callback for each row, +** malloc() for space to hold the result and return the entire results +** at the conclusion of the call. +** +** The result that is written to ***pazResult is held in memory obtained +** from malloc().  But the caller cannot free this memory directly.   +** Instead, the entire table should be passed to sqlite3_free_table() when +** the calling procedure is finished using it. +*/ +int sqlite3_get_table( +  sqlite3 *db,                /* The database on which the SQL executes */ +  const char *zSql,           /* The SQL to be executed */ +  char ***pazResult,          /* Write the result table here */ +  int *pnRow,                 /* Write the number of rows in the result here */ +  int *pnColumn,              /* Write the number of columns of result here */ +  char **pzErrMsg             /* Write error messages here */ +){ +  int rc; +  TabResult res; +  if( pazResult==0 ){ return SQLITE_ERROR; } +  *pazResult = 0; +  if( pnColumn ) *pnColumn = 0; +  if( pnRow ) *pnRow = 0; +  res.zErrMsg = 0; +  res.nResult = 0; +  res.nRow = 0; +  res.nColumn = 0; +  res.nData = 1; +  res.nAlloc = 20; +  res.rc = SQLITE_OK; +  res.azResult = malloc( sizeof(char*)*res.nAlloc ); +  if( res.azResult==0 ) return SQLITE_NOMEM; +  res.azResult[0] = 0; +  rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); +  if( res.azResult ){ +    res.azResult[0] = (char*)res.nData; +  } +  if( rc==SQLITE_ABORT ){ +    sqlite3_free_table(&res.azResult[1]); +    if( res.zErrMsg ){ +      if( pzErrMsg ){ +        free(*pzErrMsg); +        *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg); +      } +      sqliteFree(res.zErrMsg); +    } +    db->errCode = res.rc; +    return res.rc; +  } +  sqliteFree(res.zErrMsg); +  if( rc!=SQLITE_OK ){ +    sqlite3_free_table(&res.azResult[1]); +    return rc; +  } +  if( res.nAlloc>res.nData ){ +    char **azNew; +    azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) ); +    if( azNew==0 ){ +      sqlite3_free_table(&res.azResult[1]); +      return SQLITE_NOMEM; +    } +    res.nAlloc = res.nData+1; +    res.azResult = azNew; +  } +  *pazResult = &res.azResult[1]; +  if( pnColumn ) *pnColumn = res.nColumn; +  if( pnRow ) *pnRow = res.nRow; +  return rc; +} + +/* +** This routine frees the space the sqlite3_get_table() malloced. +*/ +void sqlite3_free_table( +  char **azResult            /* Result returned from from sqlite3_get_table() */ +){ +  if( azResult ){ +    int i, n; +    azResult--; +    if( azResult==0 ) return; +    n = (int)azResult[0]; +    for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); } +    free(azResult); +  } +} diff --git a/ext/pdo_sqlite/sqlite/src/tclsqlite.c b/ext/pdo_sqlite/sqlite/src/tclsqlite.c new file mode 100644 index 0000000000..5e37945b70 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/tclsqlite.c @@ -0,0 +1,1306 @@ +/* +** 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. +** +************************************************************************* +** A TCL Interface to SQLite +** +** $Id$ +*/ +#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */ + +#include "sqliteInt.h" +#include "hash.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +/* +** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we +** have to do a translation when going between the two.  Set the  +** UTF_TRANSLATION_NEEDED macro to indicate that we need to do +** this translation.   +*/ +#if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8) +# define UTF_TRANSLATION_NEEDED 1 +#endif + +/* +** New SQL functions can be created as TCL scripts.  Each such function +** is described by an instance of the following structure. +*/ +typedef struct SqlFunc SqlFunc; +struct SqlFunc { +  Tcl_Interp *interp;   /* The TCL interpret to execute the function */ +  char *zScript;        /* The script to be run */ +  SqlFunc *pNext;       /* Next function on the list of them all */ +}; + +/* +** New collation sequences function can be created as TCL scripts.  Each such +** function is described by an instance of the following structure. +*/ +typedef struct SqlCollate SqlCollate; +struct SqlCollate { +  Tcl_Interp *interp;   /* The TCL interpret to execute the function */ +  char *zScript;        /* The script to be run */ +  SqlCollate *pNext;       /* Next function on the list of them all */ +}; + +/* +** There is one instance of this structure for each SQLite database +** that has been opened by the SQLite TCL interface. +*/ +typedef struct SqliteDb SqliteDb; +struct SqliteDb { +  sqlite3 *db;          /* The "real" database structure */ +  Tcl_Interp *interp;   /* The interpreter used for this database */ +  char *zBusy;          /* The busy callback routine */ +  char *zCommit;        /* The commit hook callback routine */ +  char *zTrace;         /* The trace callback routine */ +  char *zProgress;      /* The progress callback routine */ +  char *zAuth;          /* The authorization callback routine */ +  SqlFunc *pFunc;       /* List of SQL functions */ +  SqlCollate *pCollate; /* List of SQL collation functions */ +  int rc;               /* Return code of most recent sqlite3_exec() */ +  Tcl_Obj *pCollateNeeded;  /* Collation needed script */ +}; + +/* +** TCL calls this procedure when an sqlite3 database command is +** deleted. +*/ +static void DbDeleteCmd(void *db){ +  SqliteDb *pDb = (SqliteDb*)db; +  sqlite3_close(pDb->db); +  while( pDb->pFunc ){ +    SqlFunc *pFunc = pDb->pFunc; +    pDb->pFunc = pFunc->pNext; +    Tcl_Free((char*)pFunc); +  } +  while( pDb->pCollate ){ +    SqlCollate *pCollate = pDb->pCollate; +    pDb->pCollate = pCollate->pNext; +    Tcl_Free((char*)pCollate); +  } +  if( pDb->zBusy ){ +    Tcl_Free(pDb->zBusy); +  } +  if( pDb->zTrace ){ +    Tcl_Free(pDb->zTrace); +  } +  if( pDb->zAuth ){ +    Tcl_Free(pDb->zAuth); +  } +  Tcl_Free((char*)pDb); +} + +/* +** This routine is called when a database file is locked while trying +** to execute SQL. +*/ +static int DbBusyHandler(void *cd, int nTries){ +  SqliteDb *pDb = (SqliteDb*)cd; +  int rc; +  char zVal[30]; +  char *zCmd; +  Tcl_DString cmd; + +  Tcl_DStringInit(&cmd); +  Tcl_DStringAppend(&cmd, pDb->zBusy, -1); +  sprintf(zVal, "%d", nTries); +  Tcl_DStringAppendElement(&cmd, zVal); +  zCmd = Tcl_DStringValue(&cmd); +  rc = Tcl_Eval(pDb->interp, zCmd); +  Tcl_DStringFree(&cmd); +  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ +    return 0; +  } +  return 1; +} + +/* +** This routine is invoked as the 'progress callback' for the database. +*/ +static int DbProgressHandler(void *cd){ +  SqliteDb *pDb = (SqliteDb*)cd; +  int rc; + +  assert( pDb->zProgress ); +  rc = Tcl_Eval(pDb->interp, pDb->zProgress); +  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ +    return 1; +  } +  return 0; +} + +/* +** This routine is called by the SQLite trace handler whenever a new +** block of SQL is executed.  The TCL script in pDb->zTrace is executed. +*/ +static void DbTraceHandler(void *cd, const char *zSql){ +  SqliteDb *pDb = (SqliteDb*)cd; +  Tcl_DString str; + +  Tcl_DStringInit(&str); +  Tcl_DStringAppend(&str, pDb->zTrace, -1); +  Tcl_DStringAppendElement(&str, zSql); +  Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); +  Tcl_DStringFree(&str); +  Tcl_ResetResult(pDb->interp); +} + +/* +** This routine is called when a transaction is committed.  The +** TCL script in pDb->zCommit is executed.  If it returns non-zero or +** if it throws an exception, the transaction is rolled back instead +** of being committed. +*/ +static int DbCommitHandler(void *cd){ +  SqliteDb *pDb = (SqliteDb*)cd; +  int rc; + +  rc = Tcl_Eval(pDb->interp, pDb->zCommit); +  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ +    return 1; +  } +  return 0; +} + +static void tclCollateNeeded( +  void *pCtx, +  sqlite3 *db, +  int enc, +  const char *zName +){ +  SqliteDb *pDb = (SqliteDb *)pCtx; +  Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded); +  Tcl_IncrRefCount(pScript); +  Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1)); +  Tcl_EvalObjEx(pDb->interp, pScript, 0); +  Tcl_DecrRefCount(pScript); +} + +/* +** This routine is called to evaluate an SQL collation function implemented +** using TCL script. +*/ +static int tclSqlCollate( +  void *pCtx, +  int nA, +  const void *zA, +  int nB, +  const void *zB +){ +  SqlCollate *p = (SqlCollate *)pCtx; +  Tcl_Obj *pCmd; + +  pCmd = Tcl_NewStringObj(p->zScript, -1); +  Tcl_IncrRefCount(pCmd); +  Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); +  Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); +  Tcl_EvalObjEx(p->interp, pCmd, 0); +  Tcl_DecrRefCount(pCmd); +  return (atoi(Tcl_GetStringResult(p->interp))); +} + +/* +** This routine is called to evaluate an SQL function implemented +** using TCL script. +*/ +static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +  SqlFunc *p = sqlite3_user_data(context); +  Tcl_DString cmd; +  int i; +  int rc; + +  Tcl_DStringInit(&cmd); +  Tcl_DStringAppend(&cmd, p->zScript, -1); +  for(i=0; i<argc; i++){ +    if( SQLITE_NULL==sqlite3_value_type(argv[i]) ){ +      Tcl_DStringAppendElement(&cmd, ""); +    }else{ +      Tcl_DStringAppendElement(&cmd, sqlite3_value_text(argv[i])); +    } +  } +  rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd)); +  if( rc ){ +    sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);  +  }else{ +    sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1,  +        SQLITE_TRANSIENT); +  } +} + +#ifndef SQLITE_OMIT_AUTHORIZATION +/* +** This is the authentication function.  It appends the authentication +** type code and the two arguments to zCmd[] then invokes the result +** on the interpreter.  The reply is examined to determine if the +** authentication fails or succeeds. +*/ +static int auth_callback( +  void *pArg, +  int code, +  const char *zArg1, +  const char *zArg2, +  const char *zArg3, +  const char *zArg4 +){ +  char *zCode; +  Tcl_DString str; +  int rc; +  const char *zReply; +  SqliteDb *pDb = (SqliteDb*)pArg; + +  switch( code ){ +    case SQLITE_COPY              : zCode="SQLITE_COPY"; break; +    case SQLITE_CREATE_INDEX      : zCode="SQLITE_CREATE_INDEX"; break; +    case SQLITE_CREATE_TABLE      : zCode="SQLITE_CREATE_TABLE"; break; +    case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; +    case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; +    case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; +    case SQLITE_CREATE_TEMP_VIEW  : zCode="SQLITE_CREATE_TEMP_VIEW"; break; +    case SQLITE_CREATE_TRIGGER    : zCode="SQLITE_CREATE_TRIGGER"; break; +    case SQLITE_CREATE_VIEW       : zCode="SQLITE_CREATE_VIEW"; break; +    case SQLITE_DELETE            : zCode="SQLITE_DELETE"; break; +    case SQLITE_DROP_INDEX        : zCode="SQLITE_DROP_INDEX"; break; +    case SQLITE_DROP_TABLE        : zCode="SQLITE_DROP_TABLE"; break; +    case SQLITE_DROP_TEMP_INDEX   : zCode="SQLITE_DROP_TEMP_INDEX"; break; +    case SQLITE_DROP_TEMP_TABLE   : zCode="SQLITE_DROP_TEMP_TABLE"; break; +    case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; +    case SQLITE_DROP_TEMP_VIEW    : zCode="SQLITE_DROP_TEMP_VIEW"; break; +    case SQLITE_DROP_TRIGGER      : zCode="SQLITE_DROP_TRIGGER"; break; +    case SQLITE_DROP_VIEW         : zCode="SQLITE_DROP_VIEW"; break; +    case SQLITE_INSERT            : zCode="SQLITE_INSERT"; break; +    case SQLITE_PRAGMA            : zCode="SQLITE_PRAGMA"; break; +    case SQLITE_READ              : zCode="SQLITE_READ"; break; +    case SQLITE_SELECT            : zCode="SQLITE_SELECT"; break; +    case SQLITE_TRANSACTION       : zCode="SQLITE_TRANSACTION"; break; +    case SQLITE_UPDATE            : zCode="SQLITE_UPDATE"; break; +    case SQLITE_ATTACH            : zCode="SQLITE_ATTACH"; break; +    case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break; +    default                       : zCode="????"; break; +  } +  Tcl_DStringInit(&str); +  Tcl_DStringAppend(&str, pDb->zAuth, -1); +  Tcl_DStringAppendElement(&str, zCode); +  Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); +  Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); +  Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : ""); +  Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : ""); +  rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str)); +  Tcl_DStringFree(&str); +  zReply = Tcl_GetStringResult(pDb->interp); +  if( strcmp(zReply,"SQLITE_OK")==0 ){ +    rc = SQLITE_OK; +  }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ +    rc = SQLITE_DENY; +  }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ +    rc = SQLITE_IGNORE; +  }else{ +    rc = 999; +  } +  return rc; +} +#endif /* SQLITE_OMIT_AUTHORIZATION */ + +/* +** zText is a pointer to text obtained via an sqlite3_result_text() +** or similar interface. This routine returns a Tcl string object,  +** reference count set to 0, containing the text. If a translation +** between iso8859 and UTF-8 is required, it is preformed. +*/ +static Tcl_Obj *dbTextToObj(char const *zText){ +  Tcl_Obj *pVal; +#ifdef UTF_TRANSLATION_NEEDED +  Tcl_DString dCol; +  Tcl_DStringInit(&dCol); +  Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol); +  pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); +  Tcl_DStringFree(&dCol); +#else +  pVal = Tcl_NewStringObj(zText, -1); +#endif +  return pVal; +} + +/* +** The "sqlite" command below creates a new Tcl command for each +** connection it opens to an SQLite database.  This routine is invoked +** whenever one of those connection-specific commands is executed +** in Tcl.  For example, if you run Tcl code like this: +** +**       sqlite3 db1  "my_database" +**       db1 close +** +** The first command opens a connection to the "my_database" database +** and calls that connection "db1".  The second command causes this +** subroutine to be invoked. +*/ +static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ +  SqliteDb *pDb = (SqliteDb*)cd; +  int choice; +  int rc = TCL_OK; +  static const char *DB_strs[] = { +    "authorizer",         "busy",              "changes", +    "close",              "collate",           "collation_needed", +    "commit_hook",        "complete",          "errorcode", +    "eval",               "function",          "last_insert_rowid", +    "onecolumn",          "progress",          "rekey", +    "timeout",            "total_changes",     "trace", +    0                     +  }; +  enum DB_enum { +    DB_AUTHORIZER,        DB_BUSY,             DB_CHANGES, +    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED, +    DB_COMMIT_HOOK,       DB_COMPLETE,         DB_ERRORCODE, +    DB_EVAL,              DB_FUNCTION,         DB_LAST_INSERT_ROWID, +    DB_ONECOLUMN,         DB_PROGRESS,         DB_REKEY, +    DB_TIMEOUT,           DB_TOTAL_CHANGES,    DB_TRACE, +  }; + +  if( objc<2 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); +    return TCL_ERROR; +  } +  if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ +    return TCL_ERROR; +  } + +  switch( (enum DB_enum)choice ){ + +  /*    $db authorizer ?CALLBACK? +  ** +  ** Invoke the given callback to authorize each SQL operation as it is +  ** compiled.  5 arguments are appended to the callback before it is +  ** invoked: +  ** +  **   (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) +  **   (2) First descriptive name (depends on authorization type) +  **   (3) Second descriptive name +  **   (4) Name of the database (ex: "main", "temp") +  **   (5) Name of trigger that is doing the access +  ** +  ** The callback should return on of the following strings: SQLITE_OK, +  ** SQLITE_IGNORE, or SQLITE_DENY.  Any other return value is an error. +  ** +  ** If this method is invoked with no arguments, the current authorization +  ** callback string is returned. +  */ +  case DB_AUTHORIZER: { +#ifdef SQLITE_OMIT_AUTHORIZATION +    Tcl_AppendResult(interp, "authorization not available in this build", 0); +    return TCL_ERROR; +#else +    if( objc>3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); +      return TCL_ERROR; +    }else if( objc==2 ){ +      if( pDb->zAuth ){ +        Tcl_AppendResult(interp, pDb->zAuth, 0); +      } +    }else{ +      char *zAuth; +      int len; +      if( pDb->zAuth ){ +        Tcl_Free(pDb->zAuth); +      } +      zAuth = Tcl_GetStringFromObj(objv[2], &len); +      if( zAuth && len>0 ){ +        pDb->zAuth = Tcl_Alloc( len + 1 ); +        strcpy(pDb->zAuth, zAuth); +      }else{ +        pDb->zAuth = 0; +      } +      if( pDb->zAuth ){ +        pDb->interp = interp; +        sqlite3_set_authorizer(pDb->db, auth_callback, pDb); +      }else{ +        sqlite3_set_authorizer(pDb->db, 0, 0); +      } +    } +#endif +    break; +  } + +  /*    $db busy ?CALLBACK? +  ** +  ** Invoke the given callback if an SQL statement attempts to open +  ** a locked database file. +  */ +  case DB_BUSY: { +    if( objc>3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); +      return TCL_ERROR; +    }else if( objc==2 ){ +      if( pDb->zBusy ){ +        Tcl_AppendResult(interp, pDb->zBusy, 0); +      } +    }else{ +      char *zBusy; +      int len; +      if( pDb->zBusy ){ +        Tcl_Free(pDb->zBusy); +      } +      zBusy = Tcl_GetStringFromObj(objv[2], &len); +      if( zBusy && len>0 ){ +        pDb->zBusy = Tcl_Alloc( len + 1 ); +        strcpy(pDb->zBusy, zBusy); +      }else{ +        pDb->zBusy = 0; +      } +      if( pDb->zBusy ){ +        pDb->interp = interp; +        sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); +      }else{ +        sqlite3_busy_handler(pDb->db, 0, 0); +      } +    } +    break; +  } + +  /*     $db changes +  ** +  ** Return the number of rows that were modified, inserted, or deleted by +  ** the most recent INSERT, UPDATE or DELETE statement, not including  +  ** any changes made by trigger programs. +  */ +  case DB_CHANGES: { +    Tcl_Obj *pResult; +    if( objc!=2 ){ +      Tcl_WrongNumArgs(interp, 2, objv, ""); +      return TCL_ERROR; +    } +    pResult = Tcl_GetObjResult(interp); +    Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); +    break; +  } + +  /*    $db close +  ** +  ** Shutdown the database +  */ +  case DB_CLOSE: { +    Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); +    break; +  } + +  /*    $db commit_hook ?CALLBACK? +  ** +  ** Invoke the given callback just before committing every SQL transaction. +  ** If the callback throws an exception or returns non-zero, then the +  ** transaction is aborted.  If CALLBACK is an empty string, the callback +  ** is disabled. +  */ +  case DB_COMMIT_HOOK: { +    if( objc>3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); +      return TCL_ERROR; +    }else if( objc==2 ){ +      if( pDb->zCommit ){ +        Tcl_AppendResult(interp, pDb->zCommit, 0); +      } +    }else{ +      char *zCommit; +      int len; +      if( pDb->zCommit ){ +        Tcl_Free(pDb->zCommit); +      } +      zCommit = Tcl_GetStringFromObj(objv[2], &len); +      if( zCommit && len>0 ){ +        pDb->zCommit = Tcl_Alloc( len + 1 ); +        strcpy(pDb->zCommit, zCommit); +      }else{ +        pDb->zCommit = 0; +      } +      if( pDb->zCommit ){ +        pDb->interp = interp; +        sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); +      }else{ +        sqlite3_commit_hook(pDb->db, 0, 0); +      } +    } +    break; +  } + +  /* +  **     $db collate NAME SCRIPT +  ** +  ** Create a new SQL collation function called NAME.  Whenever +  ** that function is called, invoke SCRIPT to evaluate the function. +  */ +  case DB_COLLATE: { +    SqlCollate *pCollate; +    char *zName; +    char *zScript; +    int nScript; +    if( objc!=4 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); +      return TCL_ERROR; +    } +    zName = Tcl_GetStringFromObj(objv[2], 0); +    zScript = Tcl_GetStringFromObj(objv[3], &nScript); +    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 ); +    if( pCollate==0 ) return TCL_ERROR; +    pCollate->interp = interp; +    pCollate->pNext = pDb->pCollate; +    pCollate->zScript = (char*)&pCollate[1]; +    pDb->pCollate = pCollate; +    strcpy(pCollate->zScript, zScript); +    if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,  +        pCollate, tclSqlCollate) ){ +      return TCL_ERROR; +    } +    break; +  } + +  /* +  **     $db collation_needed SCRIPT +  ** +  ** Create a new SQL collation function called NAME.  Whenever +  ** that function is called, invoke SCRIPT to evaluate the function. +  */ +  case DB_COLLATION_NEEDED: { +    if( objc!=3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT"); +      return TCL_ERROR; +    } +    if( pDb->pCollateNeeded ){ +      Tcl_DecrRefCount(pDb->pCollateNeeded); +    } +    pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); +    Tcl_IncrRefCount(pDb->pCollateNeeded); +    sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); +    break; +  } + +  /*    $db complete SQL +  ** +  ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if +  ** additional lines of input are needed.  This is similar to the +  ** built-in "info complete" command of Tcl. +  */ +  case DB_COMPLETE: { +    Tcl_Obj *pResult; +    int isComplete; +    if( objc!=3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "SQL"); +      return TCL_ERROR; +    } +    isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); +    pResult = Tcl_GetObjResult(interp); +    Tcl_SetBooleanObj(pResult, isComplete); +    break; +  } + +  /* +  **    $db errorcode +  ** +  ** Return the numeric error code that was returned by the most recent +  ** call to sqlite3_exec(). +  */ +  case DB_ERRORCODE: { +    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); +    break; +  } +    +  /* +  **    $db eval $sql ?array? ?{  ...code... }? +  **    $db onecolumn $sql +  ** +  ** The SQL statement in $sql is evaluated.  For each row, the values are +  ** placed in elements of the array named "array" and ...code... is executed. +  ** If "array" and "code" are omitted, then no callback is every invoked. +  ** If "array" is an empty string, then the values are placed in variables +  ** that have the same name as the fields extracted by the query. +  ** +  ** The onecolumn method is the equivalent of: +  **     lindex [$db eval $sql] 0 +  */ +  case DB_ONECOLUMN: +  case DB_EVAL: { +    char const *zSql;      /* Next SQL statement to execute */ +    char const *zLeft;     /* What is left after first stmt in zSql */ +    sqlite3_stmt *pStmt;   /* Compiled SQL statment */ +    Tcl_Obj *pArray;       /* Name of array into which results are written */ +    Tcl_Obj *pScript;      /* Script to run for each result set */ +    Tcl_Obj **apParm;      /* Parameters that need a Tcl_DecrRefCount() */ +    int nParm;             /* Number of entries used in apParm[] */ +    Tcl_Obj *aParm[10];    /* Static space for apParm[] in the common case */ +    Tcl_Obj *pRet;         /* Value to be returned */ + +    if( choice==DB_ONECOLUMN ){ +      if( objc!=3 ){ +        Tcl_WrongNumArgs(interp, 2, objv, "SQL"); +        return TCL_ERROR; +      } +      pRet = 0; +    }else{ +      if( objc<3 || objc>5 ){ +        Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); +        return TCL_ERROR; +      } +      pRet = Tcl_NewObj(); +      Tcl_IncrRefCount(pRet); +    } +    if( objc==3 ){ +      pArray = pScript = 0; +    }else if( objc==4 ){ +      pArray = 0; +      pScript = objv[3]; +    }else{ +      pArray = objv[3]; +      if( Tcl_GetString(pArray)[0]==0 ) pArray = 0; +      pScript = objv[4]; +    } + +    Tcl_IncrRefCount(objv[2]); +    zSql = Tcl_GetStringFromObj(objv[2], 0); +    while( rc==TCL_OK && zSql[0] ){ +      int i;      /* Loop counter */ +      int nVar;   /* Number of wildcards in the SQL */ +      int nCol;   /* Number of columns in the result set */ +      Tcl_Obj **apColName = 0;   /* Array of column names */ +   +      /* Compile a single SQL statement */ +      if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){ +        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); +        rc = TCL_ERROR; +        break; +      } +      if( pStmt==0 ){ +        if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ +          Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); +          rc = TCL_ERROR; +          break; +        }else{ +          zSql = zLeft; +          continue; +        } +      } + +      /* Bind values to wildcards that begin with $ or : */   +      nVar = sqlite3_bind_parameter_count(pStmt); +      nParm = 0; +      if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){ +        apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0])); +      }else{ +        apParm = aParm; +      } +      for(i=1; i<=nVar; i++){ +        const char *zVar = sqlite3_bind_parameter_name(pStmt, i); +        if( zVar[0]=='$' || zVar[0]==':' ){ +          Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); +          if( pVar ){ +            int n; +            u8 *data; +            char *zType = pVar->typePtr ? pVar->typePtr->name : ""; +            char c = zType[0]; +            if( c=='b' && strcmp(zType,"bytearray")==0 ){ +              data = Tcl_GetByteArrayFromObj(pVar, &n); +              sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); +              Tcl_IncrRefCount(pVar); +              apParm[nParm++] = pVar; +            }else if( (c=='b' && strcmp(zType,"boolean")==0) || +                  (c=='i' && strcmp(zType,"int")==0) ){ +              Tcl_GetIntFromObj(interp, pVar, &n); +              sqlite3_bind_int(pStmt, i, n); +            }else if( c=='d' && strcmp(zType,"double")==0 ){ +              double r; +              Tcl_GetDoubleFromObj(interp, pVar, &r); +              sqlite3_bind_double(pStmt, i, r); +            }else{ +              data = Tcl_GetStringFromObj(pVar, &n); +              sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC); +              Tcl_IncrRefCount(pVar); +              apParm[nParm++] = pVar; +            } +          } +        } +      } + +      /* Compute column names */ +      nCol = sqlite3_column_count(pStmt); +      if( pScript ){ +        apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); +        if( apColName==0 ) break; +        for(i=0; i<nCol; i++){ +          apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); +          Tcl_IncrRefCount(apColName[i]); +        } +      } + +      /* If results are being stored in an array variable, then create +      ** the array(*) entry for that array +      */ +      if( pArray ){ +        Tcl_Obj *pColList = Tcl_NewObj(); +        Tcl_IncrRefCount(pColList); +        for(i=0; i<nCol; i++){ +          Tcl_ListObjAppendElement(interp, pColList, apColName[i]); +        } +        Tcl_ObjSetVar2(interp, pArray, Tcl_NewStringObj("*",-1), pColList,0); +      } + +      /* Execute the SQL +      */ +      while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){ +        for(i=0; i<nCol; i++){ +          Tcl_Obj *pVal; +           +          /* Set pVal to contain the i'th column of this row. */ +          switch( sqlite3_column_type(pStmt, i) ){ +            case SQLITE_BLOB: { +              int bytes = sqlite3_column_bytes(pStmt, i); +              pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes); +              break; +            } +            case SQLITE_INTEGER: { +              sqlite_int64 v = sqlite3_column_int64(pStmt, i); +              if( v>=-2147483647 && v<=2147483647 ){ +                pVal = Tcl_NewIntObj(v); +              }else{ +                pVal = Tcl_NewWideIntObj(v); +              } +              break; +            } +            case SQLITE_FLOAT: { +              double r = sqlite3_column_double(pStmt, i); +              pVal = Tcl_NewDoubleObj(r); +              break; +            } +            default: { +              pVal = dbTextToObj(sqlite3_column_text(pStmt, i)); +              break; +            } +          } +   +          if( pScript ){ +            if( pArray==0 ){ +              Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); +            }else{ +              Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); +            } +          }else if( choice==DB_ONECOLUMN ){ +            if( pRet==0 ){ +              pRet = pVal; +              Tcl_IncrRefCount(pRet); +            } +            rc = TCL_BREAK; +          }else{ +            Tcl_ListObjAppendElement(interp, pRet, pVal); +          } +        } +   +        if( pScript ){ +          rc = Tcl_EvalObjEx(interp, pScript, 0); +          if( rc==TCL_CONTINUE ){ +            rc = TCL_OK; +          } +        } +      } +      if( rc==TCL_BREAK ){ +        rc = TCL_OK; +      } + +      /* Free the column name objects */ +      if( pScript ){ +        for(i=0; i<nCol; i++){ +          Tcl_DecrRefCount(apColName[i]); +        } +        Tcl_Free((char*)apColName); +      } + +      /* Free the bound string and blob parameters */ +      for(i=0; i<nParm; i++){ +        Tcl_DecrRefCount(apParm[i]); +      } +      if( apParm!=aParm ){ +        Tcl_Free((char*)apParm); +      } + +      /* Finalize the statement.  If the result code is SQLITE_SCHEMA, then +      ** try again to execute the same statement +      */ +      if( SQLITE_SCHEMA==sqlite3_finalize(pStmt) ){ +        continue; +      } +   +      if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ +        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); +        rc = TCL_ERROR; +        break; +      } + +      zSql = zLeft; +    } +    Tcl_DecrRefCount(objv[2]); + +    if( pRet ){ +      if( rc==TCL_OK ){ +        Tcl_SetObjResult(interp, pRet); +      } +      Tcl_DecrRefCount(pRet); +    } +    break; +  } + +  /* +  **     $db function NAME SCRIPT +  ** +  ** Create a new SQL function called NAME.  Whenever that function is +  ** called, invoke SCRIPT to evaluate the function. +  */ +  case DB_FUNCTION: { +    SqlFunc *pFunc; +    char *zName; +    char *zScript; +    int nScript; +    if( objc!=4 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); +      return TCL_ERROR; +    } +    zName = Tcl_GetStringFromObj(objv[2], 0); +    zScript = Tcl_GetStringFromObj(objv[3], &nScript); +    pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 ); +    if( pFunc==0 ) return TCL_ERROR; +    pFunc->interp = interp; +    pFunc->pNext = pDb->pFunc; +    pFunc->zScript = (char*)&pFunc[1]; +    pDb->pFunc = pFunc; +    strcpy(pFunc->zScript, zScript); +    rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, +        pFunc, tclSqlFunc, 0, 0); +    if( rc!=SQLITE_OK ) rc = TCL_ERROR; +    break; +  } + +  /* +  **     $db last_insert_rowid  +  ** +  ** Return an integer which is the ROWID for the most recent insert. +  */ +  case DB_LAST_INSERT_ROWID: { +    Tcl_Obj *pResult; +    int rowid; +    if( objc!=2 ){ +      Tcl_WrongNumArgs(interp, 2, objv, ""); +      return TCL_ERROR; +    } +    rowid = sqlite3_last_insert_rowid(pDb->db); +    pResult = Tcl_GetObjResult(interp); +    Tcl_SetIntObj(pResult, rowid); +    break; +  } + +  /* +  ** The DB_ONECOLUMN method is implemented together with DB_EVAL. +  */ + +  /*    $db progress ?N CALLBACK? +  **  +  ** Invoke the given callback every N virtual machine opcodes while executing +  ** queries. +  */ +  case DB_PROGRESS: { +    if( objc==2 ){ +      if( pDb->zProgress ){ +        Tcl_AppendResult(interp, pDb->zProgress, 0); +      } +    }else if( objc==4 ){ +      char *zProgress; +      int len; +      int N; +      if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ +	return TCL_ERROR; +      }; +      if( pDb->zProgress ){ +        Tcl_Free(pDb->zProgress); +      } +      zProgress = Tcl_GetStringFromObj(objv[3], &len); +      if( zProgress && len>0 ){ +        pDb->zProgress = Tcl_Alloc( len + 1 ); +        strcpy(pDb->zProgress, zProgress); +      }else{ +        pDb->zProgress = 0; +      } +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +      if( pDb->zProgress ){ +        pDb->interp = interp; +        sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); +      }else{ +        sqlite3_progress_handler(pDb->db, 0, 0, 0); +      } +#endif +    }else{ +      Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); +      return TCL_ERROR; +    } +    break; +  } + +  /* +  **     $db rekey KEY +  ** +  ** Change the encryption key on the currently open database. +  */ +  case DB_REKEY: { +    int nKey; +    void *pKey; +    if( objc!=3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "KEY"); +      return TCL_ERROR; +    } +    pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); +#ifdef SQLITE_HAS_CODEC +    rc = sqlite3_rekey(pDb->db, pKey, nKey); +    if( rc ){ +      Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); +      rc = TCL_ERROR; +    } +#endif +    break; +  } + +  /* +  **     $db timeout MILLESECONDS +  ** +  ** Delay for the number of milliseconds specified when a file is locked. +  */ +  case DB_TIMEOUT: { +    int ms; +    if( objc!=3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); +      return TCL_ERROR; +    } +    if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; +    sqlite3_busy_timeout(pDb->db, ms); +    break; +  } + +  /* +  **     $db total_changes +  ** +  ** Return the number of rows that were modified, inserted, or deleted  +  ** since the database handle was created. +  */ +  case DB_TOTAL_CHANGES: { +    Tcl_Obj *pResult; +    if( objc!=2 ){ +      Tcl_WrongNumArgs(interp, 2, objv, ""); +      return TCL_ERROR; +    } +    pResult = Tcl_GetObjResult(interp); +    Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); +    break; +  } + +  /*    $db trace ?CALLBACK? +  ** +  ** Make arrangements to invoke the CALLBACK routine for each SQL statement +  ** that is executed.  The text of the SQL is appended to CALLBACK before +  ** it is executed. +  */ +  case DB_TRACE: { +    if( objc>3 ){ +      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); +      return TCL_ERROR; +    }else if( objc==2 ){ +      if( pDb->zTrace ){ +        Tcl_AppendResult(interp, pDb->zTrace, 0); +      } +    }else{ +      char *zTrace; +      int len; +      if( pDb->zTrace ){ +        Tcl_Free(pDb->zTrace); +      } +      zTrace = Tcl_GetStringFromObj(objv[2], &len); +      if( zTrace && len>0 ){ +        pDb->zTrace = Tcl_Alloc( len + 1 ); +        strcpy(pDb->zTrace, zTrace); +      }else{ +        pDb->zTrace = 0; +      } +      if( pDb->zTrace ){ +        pDb->interp = interp; +        sqlite3_trace(pDb->db, DbTraceHandler, pDb); +      }else{ +        sqlite3_trace(pDb->db, 0, 0); +      } +    } +    break; +  } + +  } /* End of the SWITCH statement */ +  return rc; +} + +/* +**   sqlite3 DBNAME FILENAME ?MODE? ?-key KEY? +** +** This is the main Tcl command.  When the "sqlite" Tcl command is +** invoked, this routine runs to process that command. +** +** The first argument, DBNAME, is an arbitrary name for a new +** database connection.  This command creates a new command named +** DBNAME that is used to control that connection.  The database +** connection is deleted when the DBNAME command is deleted. +** +** The second argument is the name of the directory that contains +** the sqlite database that is to be accessed. +** +** For testing purposes, we also support the following: +** +**  sqlite3 -encoding +** +**       Return the encoding used by LIKE and GLOB operators.  Choices +**       are UTF-8 and iso8859. +** +**  sqlite3 -version +** +**       Return the version number of the SQLite library. +** +**  sqlite3 -tcl-uses-utf +** +**       Return "1" if compiled with a Tcl uses UTF-8.  Return "0" if +**       not.  Used by tests to make sure the library was compiled  +**       correctly. +*/ +static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ +  SqliteDb *p; +  void *pKey = 0; +  int nKey = 0; +  const char *zArg; +  char *zErrMsg; +  const char *zFile; +  char zBuf[80]; +  if( objc==2 ){ +    zArg = Tcl_GetStringFromObj(objv[1], 0); +    if( strcmp(zArg,"-version")==0 ){ +      Tcl_AppendResult(interp,sqlite3_version,0); +      return TCL_OK; +    } +    if( strcmp(zArg,"-has-codec")==0 ){ +#ifdef SQLITE_HAS_CODEC +      Tcl_AppendResult(interp,"1",0); +#else +      Tcl_AppendResult(interp,"0",0); +#endif +      return TCL_OK; +    } +    if( strcmp(zArg,"-tcl-uses-utf")==0 ){ +#ifdef TCL_UTF_MAX +      Tcl_AppendResult(interp,"1",0); +#else +      Tcl_AppendResult(interp,"0",0); +#endif +      return TCL_OK; +    } +  } +  if( objc==5 || objc==6 ){ +    zArg = Tcl_GetStringFromObj(objv[objc-2], 0); +    if( strcmp(zArg,"-key")==0 ){ +      pKey = Tcl_GetByteArrayFromObj(objv[objc-1], &nKey); +      objc -= 2; +    } +  } +  if( objc!=3 && objc!=4 ){ +    Tcl_WrongNumArgs(interp, 1, objv,  +#ifdef SQLITE_HAS_CODEC +      "HANDLE FILENAME ?-key CODEC-KEY?" +#else +      "HANDLE FILENAME ?MODE?" +#endif +    ); +    return TCL_ERROR; +  } +  zErrMsg = 0; +  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); +  if( p==0 ){ +    Tcl_SetResult(interp, "malloc failed", TCL_STATIC); +    return TCL_ERROR; +  } +  memset(p, 0, sizeof(*p)); +  zFile = Tcl_GetStringFromObj(objv[2], 0); +  sqlite3_open(zFile, &p->db); +  if( SQLITE_OK!=sqlite3_errcode(p->db) ){ +    zErrMsg = strdup(sqlite3_errmsg(p->db)); +    sqlite3_close(p->db); +    p->db = 0; +  } +#ifdef SQLITE_HAS_CODEC +  sqlite3_key(p->db, pKey, nKey); +#endif +  if( p->db==0 ){ +    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); +    Tcl_Free((char*)p); +    free(zErrMsg); +    return TCL_ERROR; +  } +  zArg = Tcl_GetStringFromObj(objv[1], 0); +  Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); + +  /* The return value is the value of the sqlite* pointer +  */ +  sprintf(zBuf, "%p", p->db); +  if( strncmp(zBuf,"0x",2) ){ +    sprintf(zBuf, "0x%p", p->db); +  } +  Tcl_AppendResult(interp, zBuf, 0); + +  /* If compiled with SQLITE_TEST turned on, then register the "md5sum" +  ** SQL function. +  */ +#ifdef SQLITE_TEST +  { +    extern void Md5_Register(sqlite3*); +#ifdef SQLITE_DEBUG +    int mallocfail = sqlite3_iMallocFail; +    sqlite3_iMallocFail = 0; +#endif +    Md5_Register(p->db); +#ifdef SQLITE_DEBUG +    sqlite3_iMallocFail = mallocfail; +#endif +   } +#endif   +  p->interp = interp; +  return TCL_OK; +} + +/* +** Provide a dummy Tcl_InitStubs if we are using this as a static +** library. +*/ +#ifndef USE_TCL_STUBS +# undef  Tcl_InitStubs +# define Tcl_InitStubs(a,b,c) +#endif + +/* +** Initialize this module. +** +** This Tcl module contains only a single new Tcl command named "sqlite". +** (Hence there is no namespace.  There is no point in using a namespace +** if the extension only supplies one new name!)  The "sqlite" command is +** used to open a new SQLite database.  See the DbMain() routine above +** for additional information. +*/ +int Sqlite3_Init(Tcl_Interp *interp){ +  Tcl_InitStubs(interp, "8.4", 0); +  Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); +  Tcl_PkgProvide(interp, "sqlite3", "3.0"); +  return TCL_OK; +} +int Tclsqlite3_Init(Tcl_Interp *interp){ +  Tcl_InitStubs(interp, "8.4", 0); +  Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); +  Tcl_PkgProvide(interp, "sqlite3", "3.0"); +  return TCL_OK; +} +int Sqlite3_SafeInit(Tcl_Interp *interp){ +  return TCL_OK; +} +int Tclsqlite3_SafeInit(Tcl_Interp *interp){ +  return TCL_OK; +} + +#ifdef TCLSH +/***************************************************************************** +** The code that follows is used to build standalone TCL interpreters +*/ + +/* +** If the macro TCLSH is one, then put in code this for the +** "main" routine that will initialize Tcl and take input from +** standard input. +*/ +#if TCLSH==1 +static char zMainloop[] = +  "set line {}\n" +  "while {![eof stdin]} {\n" +    "if {$line!=\"\"} {\n" +      "puts -nonewline \"> \"\n" +    "} else {\n" +      "puts -nonewline \"% \"\n" +    "}\n" +    "flush stdout\n" +    "append line [gets stdin]\n" +    "if {[info complete $line]} {\n" +      "if {[catch {uplevel #0 $line} result]} {\n" +        "puts stderr \"Error: $result\"\n" +      "} elseif {$result!=\"\"} {\n" +        "puts $result\n" +      "}\n" +      "set line {}\n" +    "} else {\n" +      "append line \\n\n" +    "}\n" +  "}\n" +; +#endif + +/* +** If the macro TCLSH is two, then get the main loop code out of +** the separate file "spaceanal_tcl.h". +*/ +#if TCLSH==2 +static char zMainloop[] =  +#include "spaceanal_tcl.h" +; +#endif + +#define TCLSH_MAIN main   /* Needed to fake out mktclapp */ +int TCLSH_MAIN(int argc, char **argv){ +  Tcl_Interp *interp; +  Tcl_FindExecutable(argv[0]); +  interp = Tcl_CreateInterp(); +  Sqlite3_Init(interp); +#ifdef SQLITE_TEST +  { +    extern int Sqlitetest1_Init(Tcl_Interp*); +    extern int Sqlitetest2_Init(Tcl_Interp*); +    extern int Sqlitetest3_Init(Tcl_Interp*); +    extern int Sqlitetest4_Init(Tcl_Interp*); +    extern int Sqlitetest5_Init(Tcl_Interp*); +    extern int Md5_Init(Tcl_Interp*); +    Sqlitetest1_Init(interp); +    Sqlitetest2_Init(interp); +    Sqlitetest3_Init(interp); +    Sqlitetest4_Init(interp); +    Sqlitetest5_Init(interp); +    Md5_Init(interp); +  } +#endif +  if( argc>=2 || TCLSH==2 ){ +    int i; +    Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); +    Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); +    for(i=2; i<argc; i++){ +      Tcl_SetVar(interp, "argv", argv[i], +          TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); +    } +    if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ +      const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); +      if( zInfo==0 ) zInfo = interp->result; +      fprintf(stderr,"%s: %s\n", *argv, zInfo); +      return 1; +    } +  } +  if( argc<=1 || TCLSH==2 ){ +    Tcl_GlobalEval(interp, zMainloop); +  } +  return 0; +} +#endif /* TCLSH */ + +#endif /* !defined(NO_TCL) */ diff --git a/ext/pdo_sqlite/sqlite/src/test1.c b/ext/pdo_sqlite/sqlite/src/test1.c new file mode 100644 index 0000000000..ba4e440eba --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/test1.c @@ -0,0 +1,2593 @@ +/* +** 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. +** +************************************************************************* +** Code for testing the printf() interface to SQLite.  This code +** is not included in the SQLite library.  It is used for automated +** testing of the SQLite library. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include "os.h" +#include <stdlib.h> +#include <string.h> + +static const char * errorName(int rc){ +  const char *zName = 0; +  switch( rc ){ +    case SQLITE_OK:         zName = "SQLITE_OK";          break; +    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break; +    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break; +    case SQLITE_PERM:       zName = "SQLITE_PERM";        break; +    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break; +    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break; +    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break; +    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break; +    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break; +    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break; +    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break; +    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break; +    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break; +    case SQLITE_FULL:       zName = "SQLITE_FULL";        break; +    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break; +    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break; +    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break; +    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break; +    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break; +    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break; +    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break; +    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break; +    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break; +    case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break; +    case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break; +    case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break; +    case SQLITE_ROW:        zName = "SQLITE_ROW";         break; +    case SQLITE_DONE:       zName = "SQLITE_DONE";        break; +    case SQLITE_NOTADB:     zName = "SQLITE_NOTADB";      break; +    default:                zName = "SQLITE_Unknown";     break; +  } +  return zName; +} + +/* +** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the +** fact that the sqlite3* is the first field in the Vdbe structure. +*/ +#define StmtToDb(X)   (*(sqlite3**)(X)) + +/* +** Check a return value to make sure it agrees with the results +** from sqlite3_errcode. +*/ +int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ +  if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){ +    char zBuf[200]; +    int r2 = sqlite3_errcode(db); +    sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", +       errorName(rc), rc, errorName(r2), r2); +    Tcl_ResetResult(interp); +    Tcl_AppendResult(interp, zBuf, 0); +    return 1; +  } +  return 0; +} + +/* +** Decode a pointer to an sqlite3 object. +*/ +static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ +  *ppDb = (sqlite3*)sqlite3TextToPtr(zA); +  return TCL_OK; +} + +/* +** Decode a pointer to an sqlite3_stmt object. +*/ +static int getStmtPointer( +  Tcl_Interp *interp,  +  const char *zArg,   +  sqlite3_stmt **ppStmt +){ +  *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg); +  return TCL_OK; +} + +/* +** Decode a pointer to an sqlite3_stmt object. +*/ +static int getFilePointer( +  Tcl_Interp *interp,  +  const char *zArg,   +  OsFile **ppFile +){ +  *ppFile = (OsFile*)sqlite3TextToPtr(zArg); +  return TCL_OK; +} + +/* +** Generate a text representation of a pointer that can be understood +** by the getDbPointer and getVmPointer routines above. +** +** The problem is, on some machines (Solaris) if you do a printf with +** "%p" you cannot turn around and do a scanf with the same "%p" and +** get your pointer back.  You have to prepend a "0x" before it will +** work.  Or at least that is what is reported to me (drh).  But this +** behavior varies from machine to machine.  The solution used her is +** to test the string right after it is generated to see if it can be +** understood by scanf, and if not, try prepending an "0x" to see if +** that helps.  If nothing works, a fatal error is generated. +*/ +static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ +  sqlite3_snprintf(100, zPtr, "%p", p); +  return TCL_OK; +} + +/* +** The callback routine for sqlite3_exec_printf(). +*/ +static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ +  Tcl_DString *str = (Tcl_DString*)pArg; +  int i; + +  if( Tcl_DStringLength(str)==0 ){ +    for(i=0; i<argc; i++){ +      Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); +    } +  } +  for(i=0; i<argc; i++){ +    Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); +  } +  return 0; +} + +/* +** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING +** +** Invoke the sqlite3_exec_printf() interface using the open database +** DB.  The SQL is the string FORMAT.  The format string should contain +** one %s or %q.  STRING is the value inserted into %s or %q. +*/ +static int test_exec_printf( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  Tcl_DString str; +  int rc; +  char *zErr = 0; +  char *zSql; +  char zBuf[30]; +  if( argc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  +       " DB FORMAT STRING", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  Tcl_DStringInit(&str); +  zSql = sqlite3_mprintf(argv[2], argv[3]); +  rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); +  sqlite3_free(zSql); +  sprintf(zBuf, "%d", rc); +  Tcl_AppendElement(interp, zBuf); +  Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); +  Tcl_DStringFree(&str); +  if( zErr ) free(zErr); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + +/* +** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ... +** +** Test the %z format of mprintf().  Use multiple mprintf() calls to  +** concatenate arg0 through argn using separator as the separator. +** Return the result. +*/ +static int test_mprintf_z( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  char *zResult = 0; +  int i; + +  for(i=2; i<argc; i++){ +    zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]); +  } +  Tcl_AppendResult(interp, zResult, 0); +  sqliteFree(zResult); +  return TCL_OK; +} + +/* +** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING +** +** Invoke the sqlite3_get_table_printf() interface using the open database +** DB.  The SQL is the string FORMAT.  The format string should contain +** one %s or %q.  STRING is the value inserted into %s or %q. +*/ +static int test_get_table_printf( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  Tcl_DString str; +  int rc; +  char *zErr = 0; +  int nRow, nCol; +  char **aResult; +  int i; +  char zBuf[30]; +  char *zSql; +  if( argc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  +       " DB FORMAT STRING", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  Tcl_DStringInit(&str); +  zSql = sqlite3_mprintf(argv[2],argv[3]); +  rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); +  sqlite3_free(zSql); +  sprintf(zBuf, "%d", rc); +  Tcl_AppendElement(interp, zBuf); +  if( rc==SQLITE_OK ){ +    sprintf(zBuf, "%d", nRow); +    Tcl_AppendElement(interp, zBuf); +    sprintf(zBuf, "%d", nCol); +    Tcl_AppendElement(interp, zBuf); +    for(i=0; i<(nRow+1)*nCol; i++){ +      Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); +    } +  }else{ +    Tcl_AppendElement(interp, zErr); +  } +  sqlite3_free_table(aResult); +  if( zErr ) free(zErr); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + + +/* +** Usage:  sqlite3_last_insert_rowid DB +** +** Returns the integer ROWID of the most recent insert. +*/ +static int test_last_rowid( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  char zBuf[30]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:  sqlite3_key DB KEY +** +** Set the codec key. +*/ +static int test_key( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  const char *zKey; +  int nKey; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  zKey = argv[2]; +  nKey = strlen(zKey); +#ifdef SQLITE_HAS_CODEC +  sqlite3_key(db, zKey, nKey); +#endif +  return TCL_OK; +} + +/* +** Usage:  sqlite3_rekey DB KEY +** +** Change the codec key. +*/ +static int test_rekey( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  const char *zKey; +  int nKey; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  zKey = argv[2]; +  nKey = strlen(zKey); +#ifdef SQLITE_HAS_CODEC +  sqlite3_rekey(db, zKey, nKey); +#endif +  return TCL_OK; +} + +/* +** Usage:  sqlite3_close DB +** +** Closes the database opened by sqlite3_open. +*/ +static int sqlite_test_close( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  rc = sqlite3_close(db); +  Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +  return TCL_OK; +} + +/* +** Implementation of the x_coalesce() function. +** Return the first argument non-NULL argument. +*/ +static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +  int i; +  for(i=0; i<argc; i++){ +    if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ +      sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, +          SQLITE_TRANSIENT); +      break; +    } +  } +} + +/* +** A structure into which to accumulate text. +*/ +struct dstr { +  int nAlloc;  /* Space allocated */ +  int nUsed;   /* Space used */ +  char *z;     /* The space */ +}; + +/* +** Append text to a dstr +*/ +static void dstrAppend(struct dstr *p, const char *z, int divider){ +  int n = strlen(z); +  if( p->nUsed + n + 2 > p->nAlloc ){ +    char *zNew; +    p->nAlloc = p->nAlloc*2 + n + 200; +    zNew = sqliteRealloc(p->z, p->nAlloc); +    if( zNew==0 ){ +      sqliteFree(p->z); +      memset(p, 0, sizeof(*p)); +      return; +    } +    p->z = zNew; +  } +  if( divider && p->nUsed>0 ){ +    p->z[p->nUsed++] = divider; +  } +  memcpy(&p->z[p->nUsed], z, n+1); +  p->nUsed += n; +} + +/* +** Invoked for each callback from sqlite3ExecFunc +*/ +static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ +  struct dstr *p = (struct dstr*)pData; +  int i; +  for(i=0; i<argc; i++){ +    if( argv[i]==0 ){ +      dstrAppend(p, "NULL", ' '); +    }else{ +      dstrAppend(p, argv[i], ' '); +    } +  } +  return 0; +} + +/* +** Implementation of the x_sqlite_exec() function.  This function takes +** a single argument and attempts to execute that argument as SQL code. +** This is illegal and should set the SQLITE_MISUSE flag on the database. +** +** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec() +** from within a function call.   +**  +** This routine simulates the effect of having two threads attempt to +** use the same database at the same time. +*/ +static void sqlite3ExecFunc( +  sqlite3_context *context,  +  int argc,   +  sqlite3_value **argv +){ +  struct dstr x; +  memset(&x, 0, sizeof(x)); +  sqlite3_exec((sqlite3*)sqlite3_user_data(context), +      sqlite3_value_text(argv[0]), +      execFuncCallback, &x, 0); +  sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); +  sqliteFree(x.z); +} + +/* +** Usage:  sqlite_test_create_function DB +** +** Call the sqlite3_create_function API on the given database in order +** to create a function named "x_coalesce".  This function does the same thing +** as the "coalesce" function.  This function also registers an SQL function +** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec() +** in this way is illegal recursion and should raise an SQLITE_MISUSE error. +** The effect is similar to trying to use the same database connection from +** two threads at the same time. +** +** The original motivation for this routine was to be able to call the +** sqlite3_create_function function while a query is in progress in order +** to test the SQLITE_MISUSE detection logic. +*/ +static int test_create_function( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int rc; +  sqlite3 *db; +  sqlite3_value *pVal; +  extern void Md5_Register(sqlite3*); + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,  +        ifnullFunc, 0, 0); + +  /* Use the sqlite3_create_function16() API here. Mainly for fun, but also  +  ** because it is not tested anywhere else. */ +  if( rc==SQLITE_OK ){ +    pVal = sqlite3ValueNew(); +    sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); +    rc = sqlite3_create_function16(db,  +              sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), +              1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); +    sqlite3ValueFree(pVal); +  } +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + +/* +** Routines to implement the x_count() aggregate function. +*/ +typedef struct CountCtx CountCtx; +struct CountCtx { +  int n; +}; +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, sizeof(*p)); +  sqlite3_result_int(context, p ? p->n : 0); +} + +/* +** Usage:  sqlite_test_create_aggregate DB +** +** Call the sqlite3_create_function API on the given database in order +** to create a function named "x_count".  This function does the same thing +** as the "md5sum" function. +** +** The original motivation for this routine was to be able to call the +** sqlite3_create_aggregate function while a query is in progress in order +** to test the SQLITE_MISUSE detection logic. +*/ +static int test_create_aggregate( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME\"", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, +      countStep,countFinalize); +  if( rc==SQLITE_OK ){ +    sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, +        countStep,countFinalize); +  } +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + + + +/* +** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER +** +** Call mprintf with three integer arguments +*/ +static int sqlite3_mprintf_int( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int a[3], i; +  char *z; +  if( argc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT INT INT INT\"", 0); +    return TCL_ERROR; +  } +  for(i=2; i<5; i++){ +    if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; +  } +  z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** If zNum represents an integer that will fit in 64-bits, then set +** *pValue to that integer and return true.  Otherwise return false. +*/ +static int sqlite3GetInt64(const char *zNum, i64 *pValue){ +  if( sqlite3FitsIn64Bits(zNum) ){ +    sqlite3atoi64(zNum, pValue); +    return 1; +  } +  return 0; +} + +/* +** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER +** +** Call mprintf with three 64-bit integer arguments +*/ +static int sqlite3_mprintf_int64( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int i; +  sqlite_int64 a[3]; +  char *z; +  if( argc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT INT INT INT\"", 0); +    return TCL_ERROR; +  } +  for(i=2; i<5; i++){ +    if( !sqlite3GetInt64(argv[i], &a[i-2]) ){ +      Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); +      return TCL_ERROR; +    } +  } +  z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING +** +** Call mprintf with two integer arguments and one string argument +*/ +static int sqlite3_mprintf_str( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int a[3], i; +  char *z; +  if( argc<4 || argc>5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT INT INT ?STRING?\"", 0); +    return TCL_ERROR; +  } +  for(i=2; i<4; i++){ +    if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; +  } +  z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE +** +** Call mprintf with two integer arguments and one double argument +*/ +static int sqlite3_mprintf_double( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int a[3], i; +  double r; +  char *z; +  if( argc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT INT INT STRING\"", 0); +    return TCL_ERROR; +  } +  for(i=2; i<4; i++){ +    if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; +  } +  if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; +  z = sqlite3_mprintf(argv[1], a[0], a[1], r); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** Usage:  sqlite3_mprintf_str FORMAT DOUBLE DOUBLE +** +** Call mprintf with a single double argument which is the product of the +** two arguments given above.  This is used to generate overflow and underflow +** doubles to test that they are converted properly. +*/ +static int sqlite3_mprintf_scaled( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int i; +  double r[2]; +  char *z; +  if( argc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT DOUBLE DOUBLE\"", 0); +    return TCL_ERROR; +  } +  for(i=2; i<4; i++){ +    if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; +  } +  z = sqlite3_mprintf(argv[1], r[0]*r[1]); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** Usage:  sqlite3_mprintf_stronly FORMAT STRING +** +** Call mprintf with a single double argument which is the product of the +** two arguments given above.  This is used to generate overflow and underflow +** doubles to test that they are converted properly. +*/ +static int sqlite3_mprintf_stronly( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  char *z; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FORMAT STRING\"", 0); +    return TCL_ERROR; +  } +  z = sqlite3_mprintf(argv[1], argv[2]); +  Tcl_AppendResult(interp, z, 0); +  sqlite3_free(z); +  return TCL_OK; +} + +/* +** Usage: sqlite_malloc_fail N +** +** Rig sqliteMalloc() to fail on the N-th call.  Turn off this mechanism +** and reset the sqlite3_malloc_failed variable is N==0. +*/ +#ifdef SQLITE_DEBUG +static int sqlite_malloc_fail( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  int n; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; +  sqlite3_iMallocFail = n; +  sqlite3_malloc_failed = 0; +  return TCL_OK; +} +#endif + +/* +** Usage: sqlite_malloc_stat +** +** Return the number of prior calls to sqliteMalloc() and sqliteFree(). +*/ +#ifdef SQLITE_DEBUG +static int sqlite_malloc_stat( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  char zBuf[200]; +  sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} +#endif + +/* +** Usage:  sqlite_abort +** +** Shutdown the process immediately.  This is not a clean shutdown. +** This command is used to test the recoverability of a database in +** the event of a program crash. +*/ +static int sqlite_abort( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  assert( interp==0 );   /* This will always fail */ +  return TCL_OK; +} + +/* +** The following routine is a user-defined SQL function whose purpose +** is to test the sqlite_set_result() API. +*/ +static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +  while( argc>=2 ){ +    const char *zArg0 = sqlite3_value_text(argv[0]); +    if( zArg0 ){ +      if( 0==sqlite3StrICmp(zArg0, "int") ){ +        sqlite3_result_int(context, sqlite3_value_int(argv[1])); +      }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ +        sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); +      }else if( sqlite3StrICmp(zArg0,"string")==0 ){ +        sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, +            SQLITE_TRANSIENT); +      }else if( sqlite3StrICmp(zArg0,"double")==0 ){ +        sqlite3_result_double(context, sqlite3_value_double(argv[1])); +      }else if( sqlite3StrICmp(zArg0,"null")==0 ){ +        sqlite3_result_null(context); +      }else if( sqlite3StrICmp(zArg0,"value")==0 ){ +        sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); +      }else{ +        goto error_out; +      } +    }else{ +      goto error_out; +    } +    argc -= 2; +    argv += 2; +  } +  return; + +error_out: +  sqlite3_result_error(context,"first argument should be one of: " +      "int int64 string double null value", -1); +} + +/* +** Usage:   sqlite_register_test_function  DB  NAME +** +** Register the test SQL function on the database DB under the name NAME. +*/ +static int test_register_func( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3 *db; +  int rc; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  +       " DB FUNCTION-NAME", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +  rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,  +      testFunc, 0, 0); +  if( rc!=0 ){ +    Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); +    return TCL_ERROR; +  } +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + +/* +** Usage:  sqlite3_finalize  STMT  +** +** Finalize a statement handle. +*/ +static int test_finalize( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int rc; +  sqlite3 *db; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + +  db = StmtToDb(pStmt); +  rc = sqlite3_finalize(pStmt); +  Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; +} + +/* +** Usage:  sqlite3_reset  STMT  +** +** Finalize a statement handle. +*/ +static int test_reset( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int rc; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + +  rc = sqlite3_reset(pStmt); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc ){ +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:  sqlite3_changes DB +** +** Return the number of changes made to the database by the last SQL +** execution. +*/ +static int test_changes( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +       Tcl_GetString(objv[0]), " DB", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); +  return TCL_OK; +} + +/* +** This is the "static_bind_value" that variables are bound to when +** the FLAG option of sqlite3_bind is "static" +*/ +static char *sqlite_static_bind_value = 0; + +/* +** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS +** +** Sets the value of the IDX-th occurance of "?" in the original SQL +** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is +** ignored and the value is set to NULL.  If FLAGS=="static" then +** the value is set to the value of a static variable named +** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy +** of the VALUE is made. +*/ +static int test_bind( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  sqlite3_stmt *pStmt; +  int rc; +  int idx; +  if( argc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  +       " VM IDX VALUE (null|static|normal)\"", 0); +    return TCL_ERROR; +  } +  if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; +  if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; +  if( strcmp(argv[4],"null")==0 ){ +    rc = sqlite3_bind_null(pStmt, idx); +  }else if( strcmp(argv[4],"static")==0 ){ +    rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); +  }else if( strcmp(argv[4],"normal")==0 ){ +    rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); +  }else{ +    Tcl_AppendResult(interp, "4th argument should be " +        "\"null\" or \"static\" or \"normal\"", 0); +    return TCL_ERROR; +  } +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc ){ +    char zBuf[50]; +    sprintf(zBuf, "(%d) ", rc); +    Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + + +/* +** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> +** +** This function is used to test that SQLite selects the correct collation +** sequence callback when multiple versions (for different text encodings) +** are available. +** +** Calling this routine registers the collation sequence "test_collate" +** with database handle <db>. The second argument must be a list of three +** boolean values. If the first is true, then a version of test_collate is +** registered for UTF-8, if the second is true, a version is registered for +** UTF-16le, if the third is true, a UTF-16be version is available. +** Previous versions of test_collate are deleted. +** +** The collation sequence test_collate is implemented by calling the +** following TCL script: +** +**   "test_collate <enc> <lhs> <rhs>" +** +** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. +** The <enc> parameter is the encoding of the collation function that +** SQLite selected to call. The TCL test script implements the +** "test_collate" proc. +** +** Note that this will only work with one intepreter at a time, as the +** interp pointer to use when evaluating the TCL script is stored in +** pTestCollateInterp. +*/ +static Tcl_Interp* pTestCollateInterp; +static int test_collate_func( +  void *pCtx,  +  int nA, const void *zA, +  int nB, const void *zB +){ +  Tcl_Interp *i = pTestCollateInterp; +  int encin = (int)pCtx; +  int res; + +  sqlite3_value *pVal; +  Tcl_Obj *pX; + +  pX = Tcl_NewStringObj("test_collate", -1); +  Tcl_IncrRefCount(pX); + +  switch( encin ){ +    case SQLITE_UTF8: +      Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); +      break; +    case SQLITE_UTF16LE: +      Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); +      break; +    case SQLITE_UTF16BE: +      Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); +      break; +    default: +      assert(0); +  } + +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); +  Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); +  sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); +  Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); +  sqlite3ValueFree(pVal); + +  Tcl_EvalObjEx(i, pX, 0); +  Tcl_DecrRefCount(pX); +  Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); +  return res; +} +static int test_collate( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  int val; +  sqlite3_value *pVal; +  int rc; + +  if( objc!=5 ) goto bad_args; +  pTestCollateInterp = interp; +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + +  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; +  rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,  +          (void *)SQLITE_UTF8, val?test_collate_func:0); +  if( rc==SQLITE_OK ){ +    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; +    rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,  +            (void *)SQLITE_UTF16LE, val?test_collate_func:0); +    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; + +    pVal = sqlite3ValueNew(); +    sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); +    sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),  +          SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0); +    sqlite3ValueFree(pVal); +  } +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; + +bad_args: +  Tcl_AppendResult(interp, "wrong # args: should be \"", +      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); +  return TCL_ERROR; +} + +static void test_collate_needed_cb( +  void *pCtx,  +  sqlite3 *db, +  int eTextRep, +  const void *notUsed +){ +  int enc = db->enc; +  sqlite3_create_collation( +      db, "test_collate", db->enc, (void *)enc, test_collate_func); +} + +/* +** Usage: add_test_collate_needed DB +*/ +static int test_collate_needed( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  int rc; + +  if( objc!=2 ) goto bad_args; +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +  rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  return TCL_OK; + +bad_args: +  Tcl_WrongNumArgs(interp, 1, objv, "DB"); +  return TCL_ERROR; +} + +/* +** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> +** +** This function is used to test that SQLite selects the correct user +** function callback when multiple versions (for different text encodings) +** are available. +** +** Calling this routine registers up to three versions of the user function +** "test_function" with database handle <db>.  If the second argument is +** true, then a version of test_function is registered for UTF-8, if the +** third is true, a version is registered for UTF-16le, if the fourth is +** true, a UTF-16be version is available.  Previous versions of +** test_function are deleted. +** +** The user function is implemented by calling the following TCL script: +** +**   "test_function <enc> <arg>" +** +** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the +** single argument passed to the SQL function. The value returned by +** the TCL script is used as the return value of the SQL function. It +** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 +** for a UTF-16LE test_function(), and UTF-16LE for an implementation that +** prefers UTF-16BE. +*/ +static void test_function_utf8( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  Tcl_Interp *interp; +  Tcl_Obj *pX; +  sqlite3_value *pVal; +  interp = (Tcl_Interp *)sqlite3_user_data(pCtx); +  pX = Tcl_NewStringObj("test_function", -1); +  Tcl_IncrRefCount(pX); +  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); +  Tcl_ListObjAppendElement(interp, pX,  +      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); +  Tcl_EvalObjEx(interp, pX, 0); +  Tcl_DecrRefCount(pX); +  sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  +      SQLITE_UTF8, SQLITE_STATIC); +  sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), +      -1, SQLITE_TRANSIENT); +  sqlite3ValueFree(pVal); +} +static void test_function_utf16le( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  Tcl_Interp *interp; +  Tcl_Obj *pX; +  sqlite3_value *pVal; +  interp = (Tcl_Interp *)sqlite3_user_data(pCtx); +  pX = Tcl_NewStringObj("test_function", -1); +  Tcl_IncrRefCount(pX); +  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); +  Tcl_ListObjAppendElement(interp, pX,  +      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); +  Tcl_EvalObjEx(interp, pX, 0); +  Tcl_DecrRefCount(pX); +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  +      SQLITE_UTF8, SQLITE_STATIC); +  sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); +  sqlite3ValueFree(pVal); +} +static void test_function_utf16be( +  sqlite3_context *pCtx,  +  int nArg, +  sqlite3_value **argv +){ +  Tcl_Interp *interp; +  Tcl_Obj *pX; +  sqlite3_value *pVal; +  interp = (Tcl_Interp *)sqlite3_user_data(pCtx); +  pX = Tcl_NewStringObj("test_function", -1); +  Tcl_IncrRefCount(pX); +  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); +  Tcl_ListObjAppendElement(interp, pX,  +      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); +  Tcl_EvalObjEx(interp, pX, 0); +  Tcl_DecrRefCount(pX); +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  +      SQLITE_UTF8, SQLITE_STATIC); +  sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), +      -1, SQLITE_TRANSIENT); +  sqlite3ValueFree(pVal); +} +static int test_function( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  int val; + +  if( objc!=5 ) goto bad_args; +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + +  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; +  if( val ){ +    sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,  +        interp, test_function_utf8, 0, 0); +  } +  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; +  if( val ){ +    sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,  +        interp, test_function_utf16le, 0, 0); +  } +  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; +  if( val ){ +    sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,  +        interp, test_function_utf16be, 0, 0); +  } + +  return TCL_OK; +bad_args: +  Tcl_AppendResult(interp, "wrong # args: should be \"", +      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); +  return TCL_ERROR; +} + +/* +** Usage:         test_errstr <err code> +** +** Test that the english language string equivalents for sqlite error codes +** are sane. The parameter is an integer representing an sqlite error code. +** The result is a list of two elements, the string representation of the +** error code and the english language explanation. +*/ +static int test_errstr( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  char *zCode; +  int i; +  if( objc!=1 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); +  } + +  zCode = Tcl_GetString(objv[1]); +  for(i=0; i<200; i++){ +    if( 0==strcmp(errorName(i), zCode) ) break; +  } +  Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); +  return TCL_OK; +} + +static int sqlite3_crashparams( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +#ifdef OS_TEST +  int delay; +  if( objc!=3 ) goto bad_args; +  if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR; +  sqlite3SetCrashParams(delay, Tcl_GetString(objv[2])); +#endif +  return TCL_OK; + +#ifdef OS_TEST +bad_args: +  Tcl_AppendResult(interp, "wrong # args: should be \"", +      Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0); +  return TCL_ERROR; +#endif +} + + +/* +** Usage:    breakpoint +** +** This routine exists for one purpose - to provide a place to put a +** breakpoint with GDB that can be triggered using TCL code.  The use +** for this is when a particular test fails on (say) the 1485th iteration. +** In the TCL test script, we can add code like this: +** +**     if {$i==1485} breakpoint +** +** Then run testfixture in the debugger and wait for the breakpoint to +** fire.  Then additional breakpoints can be set to trace down the bug. +*/ +static int test_breakpoint( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  char **argv            /* Text of each argument */ +){ +  return TCL_OK;         /* Do nothing */ +} + +/* +** Usage:   sqlite3_bind_int  STMT N VALUE +** +** Test the sqlite3_bind_int interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a 32-bit integer VALUE to that wildcard. +*/ +static int test_bind_int( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  int value; +  int rc; + +  if( objc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + +  rc = sqlite3_bind_int(pStmt, idx, value); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + + +/* +** Usage:   sqlite3_bind_int64  STMT N VALUE +** +** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a 64-bit integer VALUE to that wildcard. +*/ +static int test_bind_int64( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  i64 value; +  int rc; + +  if( objc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + +  rc = sqlite3_bind_int64(pStmt, idx, value); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + + +/* +** Usage:   sqlite3_bind_double  STMT N VALUE +** +** Test the sqlite3_bind_double interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a 64-bit integer VALUE to that wildcard. +*/ +static int test_bind_double( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  double value; +  int rc; + +  if( objc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; + +  rc = sqlite3_bind_double(pStmt, idx, value); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_null  STMT N +** +** Test the sqlite3_bind_null interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a NULL to the wildcard. +*/ +static int test_bind_null( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  int rc; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + +  rc = sqlite3_bind_null(pStmt, idx); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_text  STMT N STRING BYTES +** +** Test the sqlite3_bind_text interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes +** long. +*/ +static int test_bind_text( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  int bytes; +  char *value; +  int rc; + +  if( objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  value = Tcl_GetString(objv[3]); +  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + +  rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_text16  STMT N STRING BYTES +** +** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes +** long. +*/ +static int test_bind_text16( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  int bytes; +  char *value; +  int rc; + +  if( objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  value = Tcl_GetByteArrayFromObj(objv[3], 0); +  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + +  rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_blob  STMT N DATA BYTES +** +** Test the sqlite3_bind_blob interface.  STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement.  This command +** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size. +*/ +static int test_bind_blob( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int idx; +  int bytes; +  char *value; +  int rc; + +  if( objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; +  value = Tcl_GetString(objv[3]); +  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + +  rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT); +  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; +  if( rc!=SQLITE_OK ){ +    return TCL_ERROR; +  } + +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_parameter_count  STMT +** +** Return the number of wildcards in the given statement. +*/ +static int test_bind_parameter_count( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; + +  if( objc!=2 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "STMT"); +    return TCL_ERROR; +  } +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_parameter_name  STMT  N +** +** Return the name of the Nth wildcard.  The first wildcard is 1. +** An empty string is returned if N is out of range or if the wildcard +** is nameless. +*/ +static int test_bind_parameter_name( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int i; + +  if( objc!=3 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); +    return TCL_ERROR; +  } +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; +  Tcl_SetObjResult(interp,  +     Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) +  ); +  return TCL_OK; +} + +/* +** Usage:   sqlite3_bind_parameter_index  STMT  NAME +** +** Return the index of the wildcard called NAME.  Return 0 if there is +** no such wildcard. +*/ +static int test_bind_parameter_index( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; + +  if( objc!=3 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); +    return TCL_ERROR; +  } +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  Tcl_SetObjResult(interp,  +     Tcl_NewIntObj( +       sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) +     ) +  ); +  return TCL_OK; +} + +/* +** Usage: sqlite3_errcode DB +** +** Return the string representation of the most recent sqlite3_* API +** error code. e.g. "SQLITE_ERROR". +*/ +static int test_errcode( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " DB", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +  Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); +  return TCL_OK; +} + +/* +** Usage:   test_errmsg DB +** +** Returns the UTF-8 representation of the error message string for the +** most recent sqlite3_* API call. +*/ +static int test_errmsg( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  const char *zErr; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " DB", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + +  zErr = sqlite3_errmsg(db); +  Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); +  return TCL_OK; +} + +/* +** Usage:   test_errmsg16 DB +** +** Returns the UTF-16 representation of the error message string for the +** most recent sqlite3_* API call. This is a byte array object at the TCL  +** level, and it includes the 0x00 0x00 terminator bytes at the end of the +** UTF-16 string. +*/ +static int test_errmsg16( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  const void *zErr; +  int bytes; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " DB", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + +  zErr = sqlite3_errmsg16(db); +  bytes = sqlite3utf16ByteLen(zErr, -1); +  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); +  return TCL_OK; +} + +/* +** Usage: sqlite3_prepare DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  const char *zSql; +  int bytes; +  const char *zTail = 0; +  sqlite3_stmt *pStmt = 0; +  char zBuf[50]; +  int rc; + +  if( objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +  zSql = Tcl_GetString(objv[2]); +  if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + +  rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  if( zTail ){ +    if( bytes>=0 ){ +      bytes = bytes - (zTail-zSql); +    } +    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); +  } +  if( rc!=SQLITE_OK ){ +    assert( pStmt==0 ); +    sprintf(zBuf, "(%d) ", rc); +    Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); +    return TCL_ERROR; +  } + +  if( pStmt ){ +    if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; +    Tcl_AppendResult(interp, zBuf, 0); +  } +  return TCL_OK; +} + +/* +** Usage: sqlite3_prepare DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare16( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3 *db; +  const void *zSql; +  const void *zTail = 0; +  Tcl_Obj *pTail = 0; +  sqlite3_stmt *pStmt = 0; +  char zBuf[50];  +  int rc; +  int bytes;                /* The integer specified as arg 3 */ +  int objlen;               /* The byte-array length of arg 2 */ + +  if( objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); +    return TCL_ERROR; +  } +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +  zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); +  if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + +  rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail); +  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; +  if( rc ){ +    return TCL_ERROR; +  } + +  if( zTail ){ +    objlen = objlen - ((u8 *)zTail-(u8 *)zSql); +  }else{ +    objlen = 0; +  } +  pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); +  Tcl_IncrRefCount(pTail); +  Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); +  Tcl_DecrRefCount(pTail); + +  if( pStmt ){ +    if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; +  } +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage: sqlite3_open filename ?options-list? +*/ +static int test_open( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  const char *zFilename; +  sqlite3 *db; +  int rc; +  char zBuf[100]; + +  if( objc!=3 && objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " filename options-list", 0); +    return TCL_ERROR; +  } + +  zFilename = Tcl_GetString(objv[1]); +  rc = sqlite3_open(zFilename, &db); +   +  if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage: sqlite3_open16 filename options +*/ +static int test_open16( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  const void *zFilename; +  sqlite3 *db; +  int rc; +  char zBuf[100]; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " filename options-list", 0); +    return TCL_ERROR; +  } + +  zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); +  rc = sqlite3_open16(zFilename, &db); +   +  if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage: sqlite3_complete16 <UTF-16 string> +** +** Return 1 if the supplied argument is a complete SQL statement, or zero +** otherwise. +*/ +static int test_complete16( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  char *zBuf; + +  if( objc!=2 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); +    return TCL_ERROR; +  } + +  zBuf = Tcl_GetByteArrayFromObj(objv[1], 0); +  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); +  return TCL_OK; +} + +/* +** Usage: sqlite3_step STMT +** +** Advance the statement to the next row. +*/ +static int test_step( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int rc; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  rc = sqlite3_step(pStmt); + +  /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ +  Tcl_SetResult(interp, (char *)errorName(rc), 0); +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_count STMT  +** +** Return the number of columns returned by the sql statement STMT. +*/ +static int test_column_count( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + +  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_type STMT column +** +** Return the type of the data in column 'column' of the current row. +*/ +static int test_column_type( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  int tp; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  tp = sqlite3_column_type(pStmt, col); +  switch( tp ){ +    case SQLITE_INTEGER:  +      Tcl_SetResult(interp, "INTEGER", TCL_STATIC);  +      break; +    case SQLITE_NULL: +      Tcl_SetResult(interp, "NULL", TCL_STATIC);  +      break; +    case SQLITE_FLOAT: +      Tcl_SetResult(interp, "FLOAT", TCL_STATIC);  +      break; +    case SQLITE_TEXT: +      Tcl_SetResult(interp, "TEXT", TCL_STATIC);  +      break; +    case SQLITE_BLOB: +      Tcl_SetResult(interp, "BLOB", TCL_STATIC);  +      break; +    default: +      assert(0); +  } + +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_int64 STMT column +** +** Return the data in column 'column' of the current row cast as an +** wide (64-bit) integer. +*/ +static int test_column_int64( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  i64 iVal; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  iVal = sqlite3_column_int64(pStmt, col); +  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_blob STMT column +*/ +static int test_column_blob( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; + +  int len; +  const void *pBlob; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  pBlob = sqlite3_column_blob(pStmt, col); +  len = sqlite3_column_bytes(pStmt, col); +  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_double STMT column +** +** Return the data in column 'column' of the current row cast as a double. +*/ +static int test_column_double( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  double rVal; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  rVal = sqlite3_column_double(pStmt, col); +  Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); +  return TCL_OK; +} + +/* +** Usage: sqlite3_data_count STMT  +** +** Return the number of columns returned by the sql statement STMT. +*/ +static int test_data_count( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + +  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_text STMT column +** +** Usage: sqlite3_column_decltype STMT column +** +** Usage: sqlite3_column_name STMT column +*/ +static int test_stmt_utf8( +  void * clientData,        /* Pointer to SQLite API function to be invoke */ +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  const char *(*xFunc)(sqlite3_stmt*, int) = clientData; +  const char *zRet; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; +  zRet = xFunc(pStmt, col); +  if( zRet ){ +    Tcl_SetResult(interp, (char *)zRet, 0); +  } +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_text STMT column +** +** Usage: sqlite3_column_decltype STMT column +** +** Usage: sqlite3_column_name STMT column +*/ +static int test_stmt_utf16( +  void * clientData,     /* Pointer to SQLite API function to be invoked */ +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  Tcl_Obj *pRet; +  const void *zName16; +  const void *(*xFunc)(sqlite3_stmt*, int) = clientData; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  zName16 = xFunc(pStmt, col); +  if( zName16 ){ +    pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); +    Tcl_SetObjResult(interp, pRet); +  } + +  return TCL_OK; +} + +/* +** Usage: sqlite3_column_int STMT column +** +** Usage: sqlite3_column_bytes STMT column +** +** Usage: sqlite3_column_bytes16 STMT column +** +*/ +static int test_stmt_int( +  void * clientData,    /* Pointer to SQLite API function to be invoked */ +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3_stmt *pStmt; +  int col; +  int (*xFunc)(sqlite3_stmt*, int) = clientData; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " STMT column", 0); +    return TCL_ERROR; +  } + +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + +  Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); +  return TCL_OK; +} + +/* +** Usage:  sqlite3OsOpenReadWrite <filename> +*/ +static int test_sqlite3OsOpenReadWrite( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  OsFile * pFile; +  int rc; +  int dummy; +  char zBuf[100]; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " filename", 0); +    return TCL_ERROR; +  } + +  pFile = sqliteMalloc(sizeof(OsFile)); +  rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); +  if( rc!=SQLITE_OK ){ +    sqliteFree(pFile); +    Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +    return TCL_ERROR; +  } +  makePointerStr(interp, zBuf, pFile); +  Tcl_SetResult(interp, zBuf, 0); +  return TCL_ERROR; +} + +/* +** Usage:  sqlite3OsClose <file handle> +*/ +static int test_sqlite3OsClose( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  OsFile * pFile; +  int rc; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " filehandle", 0); +    return TCL_ERROR; +  } + +  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ +    return TCL_ERROR; +  } +  rc = sqlite3OsClose(pFile); +  if( rc!=SQLITE_OK ){ +    Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +    return TCL_ERROR; +  } +  sqliteFree(pFile); +  return TCL_OK; +} + +/* +** Usage:  sqlite3OsLock <file handle> <locktype> +*/ +static int test_sqlite3OsLock( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  OsFile * pFile; +  int rc; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +        Tcl_GetString(objv[0]),  +        " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); +    return TCL_ERROR; +  } + +  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ +    return TCL_ERROR; +  } + +  if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ +    rc = sqlite3OsLock(pFile, SHARED_LOCK); +  } +  else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ +    rc = sqlite3OsLock(pFile, RESERVED_LOCK); +  } +  else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ +    rc = sqlite3OsLock(pFile, PENDING_LOCK); +  } +  else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ +    rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); +  }else{ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +        Tcl_GetString(objv[0]),  +        " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); +    return TCL_ERROR; +  } + +  if( rc!=SQLITE_OK ){ +    Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:  sqlite3OsUnlock <file handle> +*/ +static int test_sqlite3OsUnlock( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  OsFile * pFile; +  int rc; + +  if( objc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"",  +       Tcl_GetString(objv[0]), " filehandle", 0); +    return TCL_ERROR; +  } + +  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ +    return TCL_ERROR; +  } +  rc = sqlite3OsUnlock(pFile, NO_LOCK); +  if( rc!=SQLITE_OK ){ +    Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:  sqlite3OsTempFileName +*/ +static int test_sqlite3OsTempFileName( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  char zFile[SQLITE_TEMPNAME_SIZE]; +  int rc; + +  rc = sqlite3OsTempFileName(zFile); +  if( rc!=SQLITE_OK ){ +    Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +    return TCL_ERROR; +  } +  Tcl_AppendResult(interp, zFile, 0); +  return TCL_OK; +} + +/* +** Usage:  tcl_variable_type VARIABLENAME +** +** Return the name of the internal representation for the +** value of the given variable. +*/ +static int tcl_variable_type( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  Tcl_Obj *pVar; +  if( objc!=2 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); +    return TCL_ERROR; +  } +  pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); +  if( pVar==0 ) return TCL_ERROR; +  if( pVar->typePtr ){ +    Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); +  } +  return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest1_Init(Tcl_Interp *interp){ +  extern int sqlite3_search_count; +  extern int sqlite3_interrupt_count; +  extern int sqlite3_open_file_count; +  extern int sqlite3_current_time; +  static struct { +     char *zName; +     Tcl_CmdProc *xProc; +  } aCmd[] = { +     { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    }, +     { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  }, +     { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    }, +     { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly}, +     { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double }, +     { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled }, +     { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        }, +     { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       }, +     { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      }, +     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf }, +     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     }, +     { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  }, +     { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate }, +     { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    }, +     { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          }, +#ifdef SQLITE_DEBUG +     { "sqlite_malloc_fail",            (Tcl_CmdProc*)sqlite_malloc_fail    }, +     { "sqlite_malloc_stat",            (Tcl_CmdProc*)sqlite_malloc_stat    }, +#endif +     { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             }, +     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       }, +     { "sqlite3_key",                   (Tcl_CmdProc*)test_key              }, +     { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            }, +  }; +  static struct { +     char *zName; +     Tcl_ObjCmdProc *xProc; +     void *clientData; +  } aObjCmd[] = { +     { "sqlite3_bind_int",              test_bind_int,      0 }, +     { "sqlite3_bind_int64",            test_bind_int64,    0 }, +     { "sqlite3_bind_double",           test_bind_double,   0 }, +     { "sqlite3_bind_null",             test_bind_null     ,0 }, +     { "sqlite3_bind_text",             test_bind_text     ,0 }, +     { "sqlite3_bind_text16",           test_bind_text16   ,0 }, +     { "sqlite3_bind_blob",             test_bind_blob     ,0 }, +     { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0}, +     { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0}, +     { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0}, +     { "sqlite3_errcode",               test_errcode       ,0 }, +     { "sqlite3_errmsg",                test_errmsg        ,0 }, +     { "sqlite3_errmsg16",              test_errmsg16      ,0 }, +     { "sqlite3_open",                  test_open          ,0 }, +     { "sqlite3_open16",                test_open16        ,0 }, +     { "sqlite3_complete16",            test_complete16    ,0 }, + +     { "sqlite3_prepare",               test_prepare       ,0 }, +     { "sqlite3_prepare16",             test_prepare16     ,0 }, +     { "sqlite3_finalize",              test_finalize      ,0 }, +     { "sqlite3_reset",                 test_reset         ,0 }, +     { "sqlite3_changes",               test_changes       ,0 }, +     { "sqlite3_step",                  test_step          ,0 }, + +     /* sqlite3_column_*() API */ +     { "sqlite3_column_count",          test_column_count  ,0 }, +     { "sqlite3_data_count",            test_data_count    ,0 }, +     { "sqlite3_column_type",           test_column_type   ,0 }, +     { "sqlite3_column_blob",           test_column_blob   ,0 }, +     { "sqlite3_column_double",         test_column_double ,0 }, +     { "sqlite3_column_int64",          test_column_int64  ,0 }, +     { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       }, +     { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     }, +     { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   }, +     { "sqlite3_column_text",       test_stmt_utf8,  sqlite3_column_text      }, +     { "sqlite3_column_decltype",   test_stmt_utf8,  sqlite3_column_decltype  }, +     { "sqlite3_column_name",       test_stmt_utf8,  sqlite3_column_name      }, +     { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    }, +     { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16}, +     { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    }, + +     /* Functions from os.h */ +     { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, +     { "sqlite3OsClose",        test_sqlite3OsClose, 0 }, +     { "sqlite3OsLock",         test_sqlite3OsLock, 0 }, +     { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 }, +    +     /* Custom test interfaces */ +     { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    }, +     { "add_test_collate",        test_collate, 0            }, +     { "add_test_collate_needed", test_collate_needed, 0     }, +     { "add_test_function",       test_function, 0           }, +     { "sqlite3_crashparams",     sqlite3_crashparams, 0     }, +     { "sqlite3_test_errstr",     test_errstr, 0             }, +     { "tcl_variable_type",       tcl_variable_type, 0       }, + +  }; +  int i; +  extern int sqlite3_os_trace; + +  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ +    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); +  } +  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ +    Tcl_CreateObjCommand(interp, aObjCmd[i].zName,  +        aObjCmd[i].xProc, aObjCmd[i].clientData, 0); +  } +  Tcl_LinkVar(interp, "sqlite_search_count",  +      (char*)&sqlite3_search_count, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_interrupt_count",  +      (char*)&sqlite3_interrupt_count, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_open_file_count",  +      (char*)&sqlite3_open_file_count, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_current_time",  +      (char*)&sqlite3_current_time, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_os_trace", +      (char*)&sqlite3_os_trace, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_static_bind_value", +      (char*)&sqlite_static_bind_value, TCL_LINK_STRING); +  Tcl_LinkVar(interp, "sqlite_temp_directory", +      (char*)&sqlite3_temp_directory, TCL_LINK_STRING); +  return TCL_OK; +} diff --git a/ext/pdo_sqlite/sqlite/src/test2.c b/ext/pdo_sqlite/sqlite/src/test2.c new file mode 100644 index 0000000000..a3706c1a78 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/test2.c @@ -0,0 +1,569 @@ +/* +** 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. +** +************************************************************************* +** Code for testing the pager.c module in SQLite.  This code +** is not included in the SQLite library.  It is used for automated +** testing of the SQLite library. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include "pager.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** Interpret an SQLite error number +*/ +static char *errorName(int rc){ +  char *zName; +  switch( rc ){ +    case SQLITE_OK:         zName = "SQLITE_OK";          break; +    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break; +    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break; +    case SQLITE_PERM:       zName = "SQLITE_PERM";        break; +    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break; +    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break; +    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break; +    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break; +    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break; +    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break; +    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break; +    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break; +    case SQLITE_FULL:       zName = "SQLITE_FULL";        break; +    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break; +    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break; +    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break; +    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break; +    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break; +    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break; +    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break; +    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break; +    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break; +    default:                zName = "SQLITE_Unknown";     break; +  } +  return zName; +} + +/* +** Page size and reserved size used for testing. +*/ +static int test_pagesize = 1024; + +/* +** Usage:   pager_open FILENAME N-PAGE +** +** Open a new pager +*/ +static int pager_open( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int nPage; +  int rc; +  char zBuf[100]; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME N-PAGE\"", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; +  rc = sqlite3pager_open(&pPager, argv[1], 0, 1); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3pager_set_cachesize(pPager, nPage); +  sqlite3pager_set_pagesize(pPager, test_pagesize); +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   pager_close ID +** +** Close the given pager. +*/ +static int pager_close( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_close(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_rollback ID +** +** Rollback changes +*/ +static int pager_rollback( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_rollback(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_commit ID +** +** Commit all changes +*/ +static int pager_commit( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_commit(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_stmt_begin ID +** +** Start a new checkpoint. +*/ +static int pager_stmt_begin( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_stmt_begin(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_stmt_rollback ID +** +** Rollback changes to a checkpoint +*/ +static int pager_stmt_rollback( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_stmt_rollback(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_stmt_commit ID +** +** Commit changes to a checkpoint +*/ +static int pager_stmt_commit( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_stmt_commit(pPager); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   pager_stats ID +** +** Return pager statistics. +*/ +static int pager_stats( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  int i, *a; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  a = sqlite3pager_stats(pPager); +  for(i=0; i<9; i++){ +    static char *zName[] = { +      "ref", "page", "max", "size", "state", "err", +      "hit", "miss", "ovfl", +    }; +    char zBuf[100]; +    Tcl_AppendElement(interp, zName[i]); +    sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); +    Tcl_AppendElement(interp, zBuf); +  } +  return TCL_OK; +} + +/* +** Usage:   pager_pagecount ID +** +** Return the size of the database file. +*/ +static int pager_pagecount( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  char zBuf[100]; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3pager_pagecount(pPager)); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   page_get ID PGNO +** +** Return a pointer to a page from the database. +*/ +static int page_get( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  char zBuf[100]; +  void *pPage; +  int pgno; +  int rc; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID PGNO\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; +  rc = sqlite3pager_get(pPager, pgno, &pPage); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   page_lookup ID PGNO +** +** Return a pointer to a page if the page is already in cache. +** If not in cache, return an empty string. +*/ +static int page_lookup( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Pager *pPager; +  char zBuf[100]; +  void *pPage; +  int pgno; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID PGNO\"", 0); +    return TCL_ERROR; +  } +  pPager = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; +  pPage = sqlite3pager_lookup(pPager, pgno); +  if( pPage ){ +    sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); +    Tcl_AppendResult(interp, zBuf, 0); +  } +  return TCL_OK; +} + +/* +** Usage:   page_unref PAGE +** +** Drop a pointer to a page. +*/ +static int page_unref( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  void *pPage; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " PAGE\"", 0); +    return TCL_ERROR; +  } +  pPage = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_unref(pPage); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   page_read PAGE +** +** Return the content of a page +*/ +static int page_read( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  char zBuf[100]; +  void *pPage; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " PAGE\"", 0); +    return TCL_ERROR; +  } +  pPage = sqlite3TextToPtr(argv[1]); +  memcpy(zBuf, pPage, sizeof(zBuf)); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   page_number PAGE +** +** Return the page number for a page. +*/ +static int page_number( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  char zBuf[100]; +  void *pPage; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " PAGE\"", 0); +    return TCL_ERROR; +  } +  pPage = sqlite3TextToPtr(argv[1]); +  sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3pager_pagenumber(pPage)); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   page_write PAGE DATA +** +** Write something into a page. +*/ +static int page_write( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  void *pPage; +  int rc; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " PAGE DATA\"", 0); +    return TCL_ERROR; +  } +  pPage = sqlite3TextToPtr(argv[1]); +  rc = sqlite3pager_write(pPage); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  strncpy((char*)pPage, argv[2], test_pagesize-1); +  ((char*)pPage)[test_pagesize-1] = 0; +  return TCL_OK; +} + +/* +** Usage:   fake_big_file  N  FILENAME +** +** Write a few bytes at the N megabyte point of FILENAME.  This will +** create a large file.  If the file was a valid SQLite database, then +** the next time the database is opened, SQLite will begin allocating +** new pages after N.  If N is 2096 or bigger, this will test the +** ability of SQLite to write to large files. +*/ +static int fake_big_file( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int rc; +  int n; +  i64 offset; +  OsFile fd; +  int readOnly = 0; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " N-MEGABYTES FILE\"", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; +  memset(&fd, 0, sizeof(fd)); +  rc = sqlite3OsOpenReadWrite(argv[2], &fd, &readOnly); +  if( rc ){ +    Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); +    return TCL_ERROR; +  } +  offset = n; +  offset *= 1024*1024; +  rc = sqlite3OsSeek(&fd, offset); +  if( rc ){ +    Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0); +    return TCL_ERROR; +  } +  rc = sqlite3OsWrite(&fd, "Hello, World!", 14); +  sqlite3OsClose(&fd); +  if( rc ){ +    Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest2_Init(Tcl_Interp *interp){ +  extern int sqlite3_io_error_pending; +  extern int sqlite3_diskfull_pending; +  static struct { +    char *zName; +    Tcl_CmdProc *xProc; +  } aCmd[] = { +    { "pager_open",              (Tcl_CmdProc*)pager_open          }, +    { "pager_close",             (Tcl_CmdProc*)pager_close         }, +    { "pager_commit",            (Tcl_CmdProc*)pager_commit        }, +    { "pager_rollback",          (Tcl_CmdProc*)pager_rollback      }, +    { "pager_stmt_begin",        (Tcl_CmdProc*)pager_stmt_begin    }, +    { "pager_stmt_commit",       (Tcl_CmdProc*)pager_stmt_commit   }, +    { "pager_stmt_rollback",     (Tcl_CmdProc*)pager_stmt_rollback }, +    { "pager_stats",             (Tcl_CmdProc*)pager_stats         }, +    { "pager_pagecount",         (Tcl_CmdProc*)pager_pagecount     }, +    { "page_get",                (Tcl_CmdProc*)page_get            }, +    { "page_lookup",             (Tcl_CmdProc*)page_lookup         }, +    { "page_unref",              (Tcl_CmdProc*)page_unref          }, +    { "page_read",               (Tcl_CmdProc*)page_read           }, +    { "page_write",              (Tcl_CmdProc*)page_write          }, +    { "page_number",             (Tcl_CmdProc*)page_number         }, +    { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       }, +  }; +  int i; +  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ +    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); +  } +  Tcl_LinkVar(interp, "sqlite_io_error_pending", +     (char*)&sqlite3_io_error_pending, TCL_LINK_INT); +  Tcl_LinkVar(interp, "sqlite_diskfull_pending", +     (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); +  Tcl_LinkVar(interp, "pager_pagesize", +     (char*)&test_pagesize, TCL_LINK_INT); +  return TCL_OK; +} diff --git a/ext/pdo_sqlite/sqlite/src/test3.c b/ext/pdo_sqlite/sqlite/src/test3.c new file mode 100644 index 0000000000..8824029f89 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/test3.c @@ -0,0 +1,1380 @@ +/* +** 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. +** +************************************************************************* +** Code for testing the btree.c module in SQLite.  This code +** is not included in the SQLite library.  It is used for automated +** testing of the SQLite library. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "pager.h" +#include "btree.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** Interpret an SQLite error number +*/ +static char *errorName(int rc){ +  char *zName; +  switch( rc ){ +    case SQLITE_OK:         zName = "SQLITE_OK";          break; +    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break; +    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break; +    case SQLITE_PERM:       zName = "SQLITE_PERM";        break; +    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break; +    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break; +    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break; +    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break; +    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break; +    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break; +    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break; +    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break; +    case SQLITE_FULL:       zName = "SQLITE_FULL";        break; +    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break; +    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break; +    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break; +    default:                zName = "SQLITE_Unknown";     break; +  } +  return zName; +} + +/* +** Usage:   btree_open FILENAME NCACHE FLAGS +** +** Open a new database +*/ +static int btree_open( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc, nCache, flags; +  char zBuf[100]; +  if( argc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " FILENAME NCACHE FLAGS\"", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; +  if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; +  rc = sqlite3BtreeOpen(argv[1], &pBt, flags); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3BtreeSetCacheSize(pBt, nCache); +  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   btree_close ID +** +** Close the given database. +*/ +static int btree_close( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeClose(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_begin_transaction ID +** +** Start a new transaction +*/ +static int btree_begin_transaction( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeBeginTrans(pBt, 1); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_rollback ID +** +** Rollback changes +*/ +static int btree_rollback( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeRollback(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_commit ID +** +** Commit all changes +*/ +static int btree_commit( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeCommit(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_begin_statement ID +** +** Start a new statement transaction +*/ +static int btree_begin_statement( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeBeginStmt(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_rollback_statement ID +** +** Rollback changes +*/ +static int btree_rollback_statement( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeRollbackStmt(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_commit_statement ID +** +** Commit all changes +*/ +static int btree_commit_statement( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeCommitStmt(pBt); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_create_table ID FLAGS +** +** Create a new table in the database +*/ +static int btree_create_table( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc, iTable, flags; +  char zBuf[30]; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID FLAGS\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR; +  rc = sqlite3BtreeCreateTable(pBt, &iTable, flags); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iTable); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage:   btree_drop_table ID TABLENUM +** +** Delete an entire table from the database +*/ +static int btree_drop_table( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int iTable; +  int rc; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID TABLENUM\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; +  rc = sqlite3BtreeDropTable(pBt, iTable); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_clear_table ID TABLENUM +** +** Remove all entries from the given table but keep the table around. +*/ +static int btree_clear_table( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int iTable; +  int rc; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID TABLENUM\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; +  rc = sqlite3BtreeClearTable(pBt, iTable); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_get_meta ID +** +** Return meta data +*/ +static int btree_get_meta( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  int i; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  for(i=0; i<SQLITE_N_BTREE_META; i++){ +    char zBuf[30]; +    unsigned int v; +    rc = sqlite3BtreeGetMeta(pBt, i, &v); +    if( rc!=SQLITE_OK ){ +      Tcl_AppendResult(interp, errorName(rc), 0); +      return TCL_ERROR; +    } +    sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",v); +    Tcl_AppendElement(interp, zBuf); +  } +  return TCL_OK; +} + +/* +** Usage:   btree_update_meta ID METADATA... +** +** Return meta data +*/ +static int btree_update_meta( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int rc; +  int i; +  int aMeta[SQLITE_N_BTREE_META]; + +  if( argc!=2+SQLITE_N_BTREE_META ){ +    char zBuf[30]; +    sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",SQLITE_N_BTREE_META); +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  for(i=1; i<SQLITE_N_BTREE_META; i++){ +    if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR; +  } +  for(i=1; i<SQLITE_N_BTREE_META; i++){ +    rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]); +    if( rc!=SQLITE_OK ){ +      Tcl_AppendResult(interp, errorName(rc), 0); +      return TCL_ERROR; +    } +  } +  return TCL_OK; +} + +/* +** Usage:   btree_page_dump ID PAGENUM +** +** Print a disassembly of a page on standard output +*/ +static int btree_page_dump( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int iPage; +  int rc; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR; +  rc = sqlite3BtreePageDump(pBt, iPage, 0); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_tree_dump ID PAGENUM +** +** Print a disassembly of a page and all its child pages on standard output +*/ +static int btree_tree_dump( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int iPage; +  int rc; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR; +  rc = sqlite3BtreePageDump(pBt, iPage, 1); +  if( rc!=SQLITE_OK ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return TCL_OK; +} + +/* +** Usage:   btree_pager_stats ID +** +** Returns pager statistics +*/ +static int btree_pager_stats( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int i; +  int *a; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  a = sqlite3pager_stats(sqlite3BtreePager(pBt)); +  for(i=0; i<9; i++){ +    static char *zName[] = { +      "ref", "page", "max", "size", "state", "err", +      "hit", "miss", "ovfl", +    }; +    char zBuf[100]; +    Tcl_AppendElement(interp, zName[i]); +    sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); +    Tcl_AppendElement(interp, zBuf); +  } +  return TCL_OK; +} + +/* +** Usage:   btree_pager_ref_dump ID +** +** Print out all outstanding pages. +*/ +static int btree_pager_ref_dump( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  sqlite3pager_refdump(sqlite3BtreePager(pBt)); +  return TCL_OK; +} + +/* +** Usage:   btree_integrity_check ID ROOT ... +** +** Look through every page of the given BTree file to verify correct +** formatting and linkage.  Return a line of text for each problem found. +** Return an empty string if everything worked. +*/ +static int btree_integrity_check( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  char *zResult; +  int nRoot; +  int *aRoot; +  int i; + +  if( argc<3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID ROOT ...\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  nRoot = argc-2; +  aRoot = malloc( sizeof(int)*(argc-2) ); +  for(i=0; i<argc-2; i++){ +    if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR; +  } +  zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot); +  if( zResult ){ +    Tcl_AppendResult(interp, zResult, 0); +    sqliteFree(zResult);  +  } +  return TCL_OK; +} + +/* +** Usage:   btree_cursor_list ID +** +** Print information about all cursors to standard output for debugging. +*/ +static int btree_cursor_list( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  sqlite3BtreeCursorList(pBt); +  return SQLITE_OK; +} + +/* +** Usage:   btree_cursor ID TABLENUM WRITEABLE +** +** Create a new cursor.  Return the ID for the cursor. +*/ +static int btree_cursor( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  Btree *pBt; +  int iTable; +  BtCursor *pCur; +  int rc; +  int wrFlag; +  char zBuf[30]; + +  if( argc!=4 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID TABLENUM WRITEABLE\"", 0); +    return TCL_ERROR; +  } +  pBt = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; +  if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR; +  rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_close_cursor ID +** +** Close a cursor opened using btree_cursor. +*/ +static int btree_close_cursor( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeCloseCursor(pCur); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return SQLITE_OK; +} + +/* +** Usage:   btree_move_to ID KEY +** +** Move the cursor to the entry with the given key. +*/ +static int btree_move_to( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int res; +  char zBuf[20]; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID KEY\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ +    int iKey; +    if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR; +    rc = sqlite3BtreeMoveto(pCur, 0, iKey, &res); +  }else{ +    rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);   +  } +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  if( res<0 ) res = -1; +  if( res>0 ) res = 1; +  sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",res); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_delete ID +** +** Delete the entry that the cursor is pointing to +*/ +static int btree_delete( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeDelete(pCur); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return SQLITE_OK; +} + +/* +** Usage:   btree_insert ID KEY DATA +** +** Create a new entry with the given key and data.  If an entry already +** exists with the same key the old entry is overwritten. +*/ +static int btree_insert( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  BtCursor *pCur; +  int rc; + +  if( objc!=4 ){ +    Tcl_WrongNumArgs(interp, 1, objv, "ID KEY DATA"); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(Tcl_GetString(objv[1])); +  if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ +    i64 iKey; +    int len; +    unsigned char *pBuf; +    if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ) return TCL_ERROR; +    pBuf = Tcl_GetByteArrayFromObj(objv[3], &len); +    rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len); +  }else{ +    int keylen; +    int dlen; +    unsigned char *pKBuf; +    unsigned char *pDBuf; +    pKBuf = Tcl_GetByteArrayFromObj(objv[2], &keylen); +    pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen); +    rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen); +  } +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  return SQLITE_OK; +} + +/* +** Usage:   btree_next ID +** +** Move the cursor to the next entry in the table.  Return 0 on success +** or 1 if the cursor was already on the last entry in the table or if +** the table is empty. +*/ +static int btree_next( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int res = 0; +  char zBuf[100]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeNext(pCur, &res); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_prev ID +** +** Move the cursor to the previous entry in the table.  Return 0 on +** success and 1 if the cursor was already on the first entry in +** the table or if the table was empty. +*/ +static int btree_prev( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int res = 0; +  char zBuf[100]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreePrevious(pCur, &res); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_first ID +** +** Move the cursor to the first entry in the table.  Return 0 if the +** cursor was left point to something and 1 if the table is empty. +*/ +static int btree_first( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int res = 0; +  char zBuf[100]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeFirst(pCur, &res); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_last ID +** +** Move the cursor to the last entry in the table.  Return 0 if the +** cursor was left point to something and 1 if the table is empty. +*/ +static int btree_last( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int res = 0; +  char zBuf[100]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  rc = sqlite3BtreeLast(pCur, &res); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_eof ID +** +** Return TRUE if the given cursor is not pointing at a valid entry. +** Return FALSE if the cursor does point to a valid entry. +*/ +static int btree_eof( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  char zBuf[50]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", sqlite3BtreeEof(pCur)); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_keysize ID +** +** Return the number of bytes of key.  For an INTKEY table, this +** returns the key itself. +*/ +static int btree_keysize( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  u64 n; +  char zBuf[50]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  sqlite3BtreeKeySize(pCur, &n); +  sqlite3_snprintf(sizeof(zBuf),zBuf, "%llu", n); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_key ID +** +** Return the key for the entry at which the cursor is pointing. +*/ +static int btree_key( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  u64 n; +  char *zBuf; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  sqlite3BtreeKeySize(pCur, &n); +  if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ +    char zBuf2[60]; +    sqlite3_snprintf(sizeof(zBuf2),zBuf2, "%llu", n); +    Tcl_AppendResult(interp, zBuf2, 0); +  }else{ +    zBuf = malloc( n+1 ); +    rc = sqlite3BtreeKey(pCur, 0, n, zBuf); +    if( rc ){ +      Tcl_AppendResult(interp, errorName(rc), 0); +      return TCL_ERROR; +    } +    zBuf[n] = 0; +    Tcl_AppendResult(interp, zBuf, 0); +    free(zBuf); +  } +  return SQLITE_OK; +} + +/* +** Usage:   btree_data ID +** +** Return the data for the entry at which the cursor is pointing. +*/ +static int btree_data( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  u32 n; +  char *zBuf; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  sqlite3BtreeDataSize(pCur, &n); +  zBuf = malloc( n+1 ); +  rc = sqlite3BtreeData(pCur, 0, n, zBuf); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  zBuf[n] = 0; +  Tcl_AppendResult(interp, zBuf, 0); +  free(zBuf); +  return SQLITE_OK; +} + +/* +** Usage:   btree_fetch_key ID AMT +** +** Use the sqlite3BtreeKeyFetch() routine to get AMT bytes of the key. +** If sqlite3BtreeKeyFetch() fails, return an empty string. +*/ +static int btree_fetch_key( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int n; +  int amt; +  u64 nKey; +  const char *zBuf; +  char zStatic[1000]; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID AMT\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; +  sqlite3BtreeKeySize(pCur, &nKey); +  zBuf = sqlite3BtreeKeyFetch(pCur, &amt); +  if( zBuf && amt>=n ){ +    assert( nKey<sizeof(zStatic) ); +    if( n>0 ) nKey = n; +    memcpy(zStatic, zBuf, (int)nKey);  +    zStatic[nKey] = 0; +    Tcl_AppendResult(interp, zStatic, 0); +  } +  return TCL_OK; +} + +/* +** Usage:   btree_fetch_data ID AMT +** +** Use the sqlite3BtreeDataFetch() routine to get AMT bytes of the key. +** If sqlite3BtreeDataFetch() fails, return an empty string. +*/ +static int btree_fetch_data( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int n; +  int amt; +  u32 nData; +  const char *zBuf; +  char zStatic[1000]; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID AMT\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; +  sqlite3BtreeDataSize(pCur, &nData); +  zBuf = sqlite3BtreeDataFetch(pCur, &amt); +  if( zBuf && amt>=n ){ +    assert( nData<sizeof(zStatic) ); +    if( n>0 ) nData = n; +    memcpy(zStatic, zBuf, (int)nData);  +    zStatic[nData] = 0; +    Tcl_AppendResult(interp, zStatic, 0); +  } +  return TCL_OK; +} + +/* +** Usage:   btree_payload_size ID +** +** Return the number of bytes of payload +*/ +static int btree_payload_size( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int n2; +  u64 n1; +  char zBuf[50]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ +    n1 = 0; +  }else{ +    sqlite3BtreeKeySize(pCur, &n1); +  } +  sqlite3BtreeDataSize(pCur, &n2); +  sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2)); +  Tcl_AppendResult(interp, zBuf, 0); +  return SQLITE_OK; +} + +/* +** Usage:   btree_cursor_info ID ?UP-CNT? +** +** Return integers containing information about the entry the +** cursor is pointing to: +** +**   aResult[0] =  The page number +**   aResult[1] =  The entry number +**   aResult[2] =  Total number of entries on this page +**   aResult[3] =  Cell size (local payload + header) +**   aResult[4] =  Number of free bytes on this page +**   aResult[5] =  Number of free blocks on the page +**   aResult[6] =  Total payload size (local + overflow) +**   aResult[7] =  Header size in bytes +**   aResult[8] =  Local payload size +**   aResult[9] =  Parent page number +*/ +static int btree_cursor_info( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  BtCursor *pCur; +  int rc; +  int i, j; +  int up; +  int aResult[10]; +  char zBuf[400]; + +  if( argc!=2 && argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID ?UP-CNT?\"", 0); +    return TCL_ERROR; +  } +  pCur = sqlite3TextToPtr(argv[1]); +  if( argc==3 ){ +    if( Tcl_GetInt(interp, argv[2], &up) ) return TCL_ERROR; +  }else{ +    up = 0; +  } +  rc = sqlite3BtreeCursorInfo(pCur, aResult, up); +  if( rc ){ +    Tcl_AppendResult(interp, errorName(rc), 0); +    return TCL_ERROR; +  } +  j = 0; +  for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){ +    sqlite3_snprintf(40,&zBuf[j]," %d", aResult[i]); +    j += strlen(&zBuf[j]); +  } +  Tcl_AppendResult(interp, &zBuf[1], 0); +  return SQLITE_OK; +} + +/* +** The command is provided for the purpose of setting breakpoints. +** in regression test scripts. +** +** By setting a GDB breakpoint on this procedure and executing the +** btree_breakpoint command in a test script, we can stop GDB at +** the point in the script where the btree_breakpoint command is +** inserted.  This is useful for debugging. +*/ +static int btree_breakpoint( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  return TCL_OK; +} + +/* +** usage:   varint_test  START  MULTIPLIER  COUNT  INCREMENT +** +** This command tests the sqlite3PutVarint() and sqlite3GetVarint() +** routines, both for accuracy and for speed. +** +** An integer is written using PutVarint() and read back with +** GetVarint() and varified to be unchanged.  This repeats COUNT +** times.  The first integer is START*MULTIPLIER.  Each iteration +** increases the integer by INCREMENT. +** +** This command returns nothing if it works.  It returns an error message +** if something goes wrong. +*/ +static int btree_varint_test( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  u32 start, mult, count, incr; +  u64 in, out; +  int n1, n2, i, j; +  unsigned char zBuf[100]; +  if( argc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " START MULTIPLIER COUNT INCREMENT\"", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR; +  if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR; +  if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR; +  if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR; +  in = start; +  in *= mult; +  for(i=0; i<count; i++){ +    char zErr[200]; +    n1 = sqlite3PutVarint(zBuf, in); +    if( n1>9 || n1<1 ){ +      sprintf(zErr, "PutVarint returned %d - should be between 1 and 9", n1); +      Tcl_AppendResult(interp, zErr, 0); +      return TCL_ERROR; +    } +    n2 = sqlite3GetVarint(zBuf, &out); +    if( n1!=n2 ){ +      sprintf(zErr, "PutVarint returned %d and GetVarint returned %d", n1, n2); +      Tcl_AppendResult(interp, zErr, 0); +      return TCL_ERROR; +    } +    if( in!=out ){ +      sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out); +      Tcl_AppendResult(interp, zErr, 0); +      return TCL_ERROR; +    } +    if( (in & 0xffffffff)==in ){ +      u32 out32; +      n2 = sqlite3GetVarint32(zBuf, &out32); +      out = out32; +      if( n1!=n2 ){ +        sprintf(zErr, "PutVarint returned %d and GetVarint32 returned %d",  +                  n1, n2); +        Tcl_AppendResult(interp, zErr, 0); +        return TCL_ERROR; +      } +      if( in!=out ){ +        sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32", +            in, out); +        Tcl_AppendResult(interp, zErr, 0); +        return TCL_ERROR; +      } +    } + +    /* In order to get realistic timings, run getVarint 19 more times. +    ** This is because getVarint is called about 20 times more often +    ** than putVarint. +    */ +    for(j=0; j<19; j++){ +      sqlite3GetVarint(zBuf, &out); +    } +    in += incr; +  } +  return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest3_Init(Tcl_Interp *interp){ +  extern int sqlite3_btree_trace; +  static struct { +     char *zName; +     Tcl_CmdProc *xProc; +  } aCmd[] = { +     { "btree_open",               (Tcl_CmdProc*)btree_open               }, +     { "btree_close",              (Tcl_CmdProc*)btree_close              }, +     { "btree_begin_transaction",  (Tcl_CmdProc*)btree_begin_transaction  }, +     { "btree_commit",             (Tcl_CmdProc*)btree_commit             }, +     { "btree_rollback",           (Tcl_CmdProc*)btree_rollback           }, +     { "btree_create_table",       (Tcl_CmdProc*)btree_create_table       }, +     { "btree_drop_table",         (Tcl_CmdProc*)btree_drop_table         }, +     { "btree_clear_table",        (Tcl_CmdProc*)btree_clear_table        }, +     { "btree_get_meta",           (Tcl_CmdProc*)btree_get_meta           }, +     { "btree_update_meta",        (Tcl_CmdProc*)btree_update_meta        }, +     { "btree_page_dump",          (Tcl_CmdProc*)btree_page_dump          }, +     { "btree_tree_dump",          (Tcl_CmdProc*)btree_tree_dump          }, +     { "btree_pager_stats",        (Tcl_CmdProc*)btree_pager_stats        }, +     { "btree_pager_ref_dump",     (Tcl_CmdProc*)btree_pager_ref_dump     }, +     { "btree_cursor",             (Tcl_CmdProc*)btree_cursor             }, +     { "btree_close_cursor",       (Tcl_CmdProc*)btree_close_cursor       }, +     { "btree_move_to",            (Tcl_CmdProc*)btree_move_to            }, +     { "btree_delete",             (Tcl_CmdProc*)btree_delete             }, +     { "btree_next",               (Tcl_CmdProc*)btree_next               }, +     { "btree_prev",               (Tcl_CmdProc*)btree_prev               }, +     { "btree_eof",                (Tcl_CmdProc*)btree_eof                }, +     { "btree_keysize",            (Tcl_CmdProc*)btree_keysize            }, +     { "btree_key",                (Tcl_CmdProc*)btree_key                }, +     { "btree_data",               (Tcl_CmdProc*)btree_data               }, +     { "btree_fetch_key",          (Tcl_CmdProc*)btree_fetch_key          }, +     { "btree_fetch_data",         (Tcl_CmdProc*)btree_fetch_data         }, +     { "btree_payload_size",       (Tcl_CmdProc*)btree_payload_size       }, +     { "btree_first",              (Tcl_CmdProc*)btree_first              }, +     { "btree_last",               (Tcl_CmdProc*)btree_last               }, +     { "btree_cursor_info",        (Tcl_CmdProc*)btree_cursor_info        }, +     { "btree_cursor_list",        (Tcl_CmdProc*)btree_cursor_list        }, +     { "btree_integrity_check",    (Tcl_CmdProc*)btree_integrity_check    }, +     { "btree_breakpoint",         (Tcl_CmdProc*)btree_breakpoint         }, +     { "btree_varint_test",        (Tcl_CmdProc*)btree_varint_test        }, +     { "btree_begin_statement",    (Tcl_CmdProc*)btree_begin_statement    }, +     { "btree_commit_statement",   (Tcl_CmdProc*)btree_commit_statement   }, +     { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement }, +  }; +  int i; + +  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ +    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); +  } +  Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager3_refinfo_enable, +     TCL_LINK_INT); +  Tcl_LinkVar(interp, "btree_trace", (char*)&sqlite3_btree_trace, +     TCL_LINK_INT); + +  /* The btree_insert command is implemented using the tcl 'object' +  ** interface, not the string interface like the other commands in this +  ** file. This is so binary data can be inserted into btree tables. +  */ +  Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0); +  return TCL_OK; +} diff --git a/ext/pdo_sqlite/sqlite/src/test4.c b/ext/pdo_sqlite/sqlite/src/test4.c new file mode 100644 index 0000000000..47a407a4b5 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/test4.c @@ -0,0 +1,650 @@ +/* +** 2003 December 18 +** +** The author disclaims copyright to this source code.  In place of +** a legal notice, here is a blessing: +** +**    May you do good and not evil. +**    May you find forgiveness for yourself and forgive others. +**    May you share freely, never taking more than you give. +** +************************************************************************* +** Code for testing the the SQLite library in a multithreaded environment. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include "os.h" +#if defined(OS_UNIX) && OS_UNIX==1 && defined(THREADSAFE) && THREADSAFE==1 +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <sched.h> +#include <ctype.h> + +/* +** Each thread is controlled by an instance of the following +** structure. +*/ +typedef struct Thread Thread; +struct Thread { +  /* The first group of fields are writable by the master and read-only +  ** to the thread. */ +  char *zFilename;       /* Name of database file */ +  void (*xOp)(Thread*);  /* next operation to do */ +  char *zArg;            /* argument usable by xOp */ +  int opnum;             /* Operation number */ +  int busy;              /* True if this thread is in use */ + +  /* The next group of fields are writable by the thread but read-only to the +  ** master. */ +  int completed;        /* Number of operations completed */ +  sqlite3 *db;           /* Open database */ +  sqlite3_stmt *pStmt;     /* Pending operation */ +  char *zErr;           /* operation error */ +  char *zStaticErr;     /* Static error message */ +  int rc;               /* operation return code */ +  int argc;             /* number of columns in result */ +  const char *argv[100];    /* result columns */ +  const char *colv[100];    /* result column names */ +}; + +/* +** There can be as many as 26 threads running at once.  Each is named +** by a capital letter: A, B, C, ..., Y, Z. +*/ +#define N_THREAD 26 +static Thread threadset[N_THREAD]; + + +/* +** The main loop for a thread.  Threads use busy waiting.  +*/ +static void *thread_main(void *pArg){ +  Thread *p = (Thread*)pArg; +  if( p->db ){ +    sqlite3_close(p->db); +  } +  sqlite3_open(p->zFilename, &p->db); +  if( SQLITE_OK!=sqlite3_errcode(p->db) ){ +    p->zErr = strdup(sqlite3_errmsg(p->db)); +    sqlite3_close(p->db); +    p->db = 0; +  } +  p->pStmt = 0; +  p->completed = 1; +  while( p->opnum<=p->completed ) sched_yield(); +  while( p->xOp ){ +    if( p->zErr && p->zErr!=p->zStaticErr ){ +      sqlite3_free(p->zErr); +      p->zErr = 0; +    } +    (*p->xOp)(p); +    p->completed++; +    while( p->opnum<=p->completed ) sched_yield(); +  } +  if( p->pStmt ){ +    sqlite3_finalize(p->pStmt); +    p->pStmt = 0; +  } +  if( p->db ){ +    sqlite3_close(p->db); +    p->db = 0; +  } +  if( p->zErr && p->zErr!=p->zStaticErr ){ +    sqlite3_free(p->zErr); +    p->zErr = 0; +  } +  p->completed++; +  return 0; +} + +/* +** Get a thread ID which is an upper case letter.  Return the index. +** If the argument is not a valid thread ID put an error message in +** the interpreter and return -1. +*/ +static int parse_thread_id(Tcl_Interp *interp, const char *zArg){ +  if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ +    Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); +    return -1; +  } +  return zArg[0] - 'A'; +} + +/* +** Usage:    thread_create NAME  FILENAME +** +** NAME should be an upper case letter.  Start the thread running with +** an open connection to the given database. +*/ +static int tcl_thread_create( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  pthread_t x; +  int rc; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID FILENAME", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( threadset[i].busy ){ +    Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); +    return TCL_ERROR; +  } +  threadset[i].busy = 1; +  sqliteFree(threadset[i].zFilename); +  threadset[i].zFilename = sqliteStrDup(argv[2]); +  threadset[i].opnum = 1; +  threadset[i].completed = 0; +  rc = pthread_create(&x, 0, thread_main, &threadset[i]); +  if( rc ){ +    Tcl_AppendResult(interp, "failed to create the thread", 0); +    sqliteFree(threadset[i].zFilename); +    threadset[i].busy = 0; +    return TCL_ERROR; +  } +  pthread_detach(x); +  return TCL_OK; +} + +/* +** Wait for a thread to reach its idle state. +*/ +static void thread_wait(Thread *p){ +  while( p->opnum>p->completed ) sched_yield(); +} + +/* +** Usage:  thread_wait ID +** +** Wait on thread ID to reach its idle state. +*/ +static int tcl_thread_wait( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  return TCL_OK; +} + +/* +** Stop a thread. +*/ +static void stop_thread(Thread *p){ +  thread_wait(p); +  p->xOp = 0; +  p->opnum++; +  thread_wait(p); +  sqliteFree(p->zArg); +  p->zArg = 0; +  sqliteFree(p->zFilename); +  p->zFilename = 0; +  p->busy = 0; +} + +/* +** Usage:  thread_halt ID +** +** Cause a thread to shut itself down.  Wait for the shutdown to be +** completed.  If ID is "*" then stop all threads. +*/ +static int tcl_thread_halt( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID", 0); +    return TCL_ERROR; +  } +  if( argv[1][0]=='*' && argv[1][1]==0 ){ +    for(i=0; i<N_THREAD; i++){ +      if( threadset[i].busy ) stop_thread(&threadset[i]); +    } +  }else{ +    i = parse_thread_id(interp, argv[1]); +    if( i<0 ) return TCL_ERROR; +    if( !threadset[i].busy ){ +      Tcl_AppendResult(interp, "no such thread", 0); +      return TCL_ERROR; +    } +    stop_thread(&threadset[i]); +  } +  return TCL_OK; +} + +/* +** Usage: thread_argc  ID +** +** Wait on the most recent thread_step to complete, then return the +** number of columns in the result set. +*/ +static int tcl_thread_argc( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  char zBuf[100]; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  sprintf(zBuf, "%d", threadset[i].argc); +  Tcl_AppendResult(interp, zBuf, 0); +  return TCL_OK; +} + +/* +** Usage: thread_argv  ID   N +** +** Wait on the most recent thread_step to complete, then return the +** value of the N-th columns in the result set. +*/ +static int tcl_thread_argv( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  int n; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID N", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; +  thread_wait(&threadset[i]); +  if( n<0 || n>=threadset[i].argc ){ +    Tcl_AppendResult(interp, "column number out of range", 0); +    return TCL_ERROR; +  } +  Tcl_AppendResult(interp, threadset[i].argv[n], 0); +  return TCL_OK; +} + +/* +** Usage: thread_colname  ID   N +** +** Wait on the most recent thread_step to complete, then return the +** name of the N-th columns in the result set. +*/ +static int tcl_thread_colname( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  int n; + +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID N", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; +  thread_wait(&threadset[i]); +  if( n<0 || n>=threadset[i].argc ){ +    Tcl_AppendResult(interp, "column number out of range", 0); +    return TCL_ERROR; +  } +  Tcl_AppendResult(interp, threadset[i].colv[n], 0); +  return TCL_OK; +} + +/* +** Usage: thread_result  ID +** +** Wait on the most recent operation to complete, then return the +** result code from that operation. +*/ +static int tcl_thread_result( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  const char *zName; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  switch( threadset[i].rc ){ +    case SQLITE_OK:         zName = "SQLITE_OK";          break; +    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break; +    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break; +    case SQLITE_PERM:       zName = "SQLITE_PERM";        break; +    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break; +    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break; +    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break; +    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break; +    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break; +    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break; +    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break; +    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break; +    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break; +    case SQLITE_FULL:       zName = "SQLITE_FULL";        break; +    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break; +    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break; +    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break; +    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break; +    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break; +    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break; +    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break; +    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break; +    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break; +    case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break; +    case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break; +    case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break; +    case SQLITE_ROW:        zName = "SQLITE_ROW";         break; +    case SQLITE_DONE:       zName = "SQLITE_DONE";        break; +    default:                zName = "SQLITE_Unknown";     break; +  } +  Tcl_AppendResult(interp, zName, 0); +  return TCL_OK; +} + +/* +** Usage: thread_error  ID +** +** Wait on the most recent operation to complete, then return the +** error string. +*/ +static int tcl_thread_error( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; + +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  Tcl_AppendResult(interp, threadset[i].zErr, 0); +  return TCL_OK; +} + +/* +** This procedure runs in the thread to compile an SQL statement. +*/ +static void do_compile(Thread *p){ +  if( p->db==0 ){ +    p->zErr = p->zStaticErr = "no database is open"; +    p->rc = SQLITE_ERROR; +    return; +  } +  if( p->pStmt ){ +    sqlite3_finalize(p->pStmt); +    p->pStmt = 0; +  } +  p->rc = sqlite3_prepare(p->db, p->zArg, -1, &p->pStmt, 0); +} + +/* +** Usage: thread_compile ID SQL +** +** Compile a new virtual machine. +*/ +static int tcl_thread_compile( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID SQL", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  threadset[i].xOp = do_compile; +  sqliteFree(threadset[i].zArg); +  threadset[i].zArg = sqliteStrDup(argv[2]); +  threadset[i].opnum++; +  return TCL_OK; +} + +/* +** This procedure runs in the thread to step the virtual machine. +*/ +static void do_step(Thread *p){ +  int i; +  if( p->pStmt==0 ){ +    p->zErr = p->zStaticErr = "no virtual machine available"; +    p->rc = SQLITE_ERROR; +    return; +  } +  p->rc = sqlite3_step(p->pStmt); +  if( p->rc==SQLITE_ROW ){ +    p->argc = sqlite3_column_count(p->pStmt); +    for(i=0; i<sqlite3_data_count(p->pStmt); i++){ +      p->argv[i] = sqlite3_column_text(p->pStmt, i); +    } +    for(i=0; i<p->argc; i++){ +      p->colv[i] = sqlite3_column_name(p->pStmt, i); +    } +  } +} + +/* +** Usage: thread_step ID +** +** Advance the virtual machine by one step +*/ +static int tcl_thread_step( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " IDL", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  threadset[i].xOp = do_step; +  threadset[i].opnum++; +  return TCL_OK; +} + +/* +** This procedure runs in the thread to finalize a virtual machine. +*/ +static void do_finalize(Thread *p){ +  if( p->pStmt==0 ){ +    p->zErr = p->zStaticErr = "no virtual machine available"; +    p->rc = SQLITE_ERROR; +    return; +  } +  p->rc = sqlite3_finalize(p->pStmt); +  p->pStmt = 0; +} + +/* +** Usage: thread_finalize ID +** +** Finalize the virtual machine. +*/ +static int tcl_thread_finalize( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i; +  if( argc!=2 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " IDL", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  threadset[i].xOp = do_finalize; +  sqliteFree(threadset[i].zArg); +  threadset[i].zArg = 0; +  threadset[i].opnum++; +  return TCL_OK; +} + +/* +** Usage: thread_swap ID ID +** +** Interchange the sqlite* pointer between two threads. +*/ +static int tcl_thread_swap( +  void *NotUsed, +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ +  int argc,              /* Number of arguments */ +  const char **argv      /* Text of each argument */ +){ +  int i, j; +  sqlite3 *temp; +  if( argc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], +       " ID1 ID2", 0); +    return TCL_ERROR; +  } +  i = parse_thread_id(interp, argv[1]); +  if( i<0 ) return TCL_ERROR; +  if( !threadset[i].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[i]); +  j = parse_thread_id(interp, argv[2]); +  if( j<0 ) return TCL_ERROR; +  if( !threadset[j].busy ){ +    Tcl_AppendResult(interp, "no such thread", 0); +    return TCL_ERROR; +  } +  thread_wait(&threadset[j]); +  temp = threadset[i].db; +  threadset[i].db = threadset[j].db; +  threadset[j].db = temp; +  return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest4_Init(Tcl_Interp *interp){ +  static struct { +     char *zName; +     Tcl_CmdProc *xProc; +  } aCmd[] = { +     { "thread_create",     (Tcl_CmdProc*)tcl_thread_create     }, +     { "thread_wait",       (Tcl_CmdProc*)tcl_thread_wait       }, +     { "thread_halt",       (Tcl_CmdProc*)tcl_thread_halt       }, +     { "thread_argc",       (Tcl_CmdProc*)tcl_thread_argc       }, +     { "thread_argv",       (Tcl_CmdProc*)tcl_thread_argv       }, +     { "thread_colname",    (Tcl_CmdProc*)tcl_thread_colname    }, +     { "thread_result",     (Tcl_CmdProc*)tcl_thread_result     }, +     { "thread_error",      (Tcl_CmdProc*)tcl_thread_error      }, +     { "thread_compile",    (Tcl_CmdProc*)tcl_thread_compile    }, +     { "thread_step",       (Tcl_CmdProc*)tcl_thread_step       }, +     { "thread_finalize",   (Tcl_CmdProc*)tcl_thread_finalize   }, +     { "thread_swap",       (Tcl_CmdProc*)tcl_thread_swap       }, +  }; +  int i; + +  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ +    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); +  } +  return TCL_OK; +} +#else +int Sqlitetest4_Init(Tcl_Interp *interp){ return TCL_OK; } +#endif /* OS_UNIX */ diff --git a/ext/pdo_sqlite/sqlite/src/test5.c b/ext/pdo_sqlite/sqlite/src/test5.c new file mode 100644 index 0000000000..4de7269642 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/test5.c @@ -0,0 +1,217 @@ +/* +** 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. +** +************************************************************************* +** Code for testing the utf.c module in SQLite.  This code +** is not included in the SQLite library.  It is used for automated +** testing of the SQLite library. Specifically, the code in this file +** is used for testing the SQLite routines for converting between +** the various supported unicode encodings. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" +#include "os.h"         /* to get SQLITE_BIGENDIAN */ +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** The first argument is a TCL UTF-8 string. Return the byte array +** object with the encoded representation of the string, including +** the NULL terminator. +*/ +static int binarize( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  int len; +  char *bytes; +  Tcl_Obj *pRet; +  assert(objc==2); + +  bytes = Tcl_GetStringFromObj(objv[1], &len); +  pRet = Tcl_NewByteArrayObj(bytes, len+1); +  Tcl_SetObjResult(interp, pRet); +  return TCL_OK; +} + +/* +** Usage: test_value_overhead <repeat-count> <do-calls>. +** +** This routine is used to test the overhead of calls to +** sqlite3_value_text(), on a value that contains a UTF-8 string. The idea +** is to figure out whether or not it is a problem to use sqlite3_value +** structures with collation sequence functions. +** +** If <do-calls> is 0, then the calls to sqlite3_value_text() are not +** actually made. +*/ +static int test_value_overhead( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  int do_calls; +  int repeat_count; +  int i; +  Mem val; +  const char *zVal; + +  if( objc!=3 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0), " <repeat-count> <do-calls>", 0); +    return TCL_ERROR; +  } + +  if( Tcl_GetIntFromObj(interp, objv[1], &repeat_count) ) return TCL_ERROR; +  if( Tcl_GetIntFromObj(interp, objv[2], &do_calls) ) return TCL_ERROR; + +  val.flags = MEM_Str|MEM_Term|MEM_Static; +  val.z = "hello world"; +  val.type = SQLITE_TEXT; +  val.enc = SQLITE_UTF8; + +  for(i=0; i<repeat_count; i++){ +    if( do_calls ){ +      zVal = sqlite3_value_text(&val); +    } +  } + +  return TCL_OK; +} + +static u8 name_to_enc(Tcl_Interp *interp, Tcl_Obj *pObj){ +  struct EncName { +    char *zName; +    u8 enc; +  } encnames[] = { +    { "UTF8", SQLITE_UTF8 }, +    { "UTF16LE", SQLITE_UTF16LE }, +    { "UTF16BE", SQLITE_UTF16BE }, +    { "UTF16", SQLITE_UTF16NATIVE }, +    { 0, 0 } +  }; +  struct EncName *pEnc; +  char *z = Tcl_GetString(pObj); +  for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ +    if( 0==sqlite3StrICmp(z, pEnc->zName) ){ +      break; +    } +  } +  if( !pEnc->enc ){ +    Tcl_AppendResult(interp, "No such encoding: ", z, 0); +  } +  return pEnc->enc; +} + +/* +** Usage:   test_translate <string/blob> <from enc> <to enc> ?<transient>? +** +*/ +static int test_translate( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  u8 enc_from; +  u8 enc_to; +  sqlite3_value *pVal; + +  char *z; +  int len; +  void (*xDel)(void *p) = SQLITE_STATIC; + +  if( objc!=4 && objc!=5 ){ +    Tcl_AppendResult(interp, "wrong # args: should be \"", +        Tcl_GetStringFromObj(objv[0], 0),  +        " <string/blob> <from enc> <to enc>", 0 +    ); +    return TCL_ERROR; +  } +  if( objc==5 ){ +    xDel = sqlite3FreeX; +  } + +  enc_from = name_to_enc(interp, objv[2]); +  if( !enc_from ) return TCL_ERROR; +  enc_to = name_to_enc(interp, objv[3]); +  if( !enc_to ) return TCL_ERROR; + +  pVal = sqlite3ValueNew(); + +  if( enc_from==SQLITE_UTF8 ){ +    z = Tcl_GetString(objv[1]); +    if( objc==5 ){ +      z = sqliteStrDup(z); +    } +    sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); +  }else{ +    z = Tcl_GetByteArrayFromObj(objv[1], &len); +    if( objc==5 ){ +      char *zTmp = z; +      z = sqliteMalloc(len); +      memcpy(z, zTmp, len); +    } +    sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); +  } + +  z = (char *)sqlite3ValueText(pVal, enc_to); +  len = sqlite3ValueBytes(pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2); +  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(z, len)); + +  sqlite3ValueFree(pVal); + +  return TCL_OK; +} + +/* +** Usage: translate_selftest +** +** Call sqlite3utfSelfTest() to run the internal tests for unicode +** translation. If there is a problem an assert() will fail. +**/ +void sqlite3utfSelfTest(); +static int test_translate_selftest( +  void * clientData, +  Tcl_Interp *interp, +  int objc, +  Tcl_Obj *CONST objv[] +){ +  sqlite3utfSelfTest(); +  return SQLITE_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest5_Init(Tcl_Interp *interp){ +  static struct { +    char *zName; +    Tcl_ObjCmdProc *xProc; +  } aCmd[] = { +    { "binarize",                (Tcl_ObjCmdProc*)binarize }, +    { "test_value_overhead",     (Tcl_ObjCmdProc*)test_value_overhead }, +    { "test_translate",          (Tcl_ObjCmdProc*)test_translate     }, +    { "translate_selftest",      (Tcl_ObjCmdProc*)test_translate_selftest}, +  }; +  int i; +  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ +    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); +  } +  return SQLITE_OK; +} + diff --git a/ext/pdo_sqlite/sqlite/src/tokenize.c b/ext/pdo_sqlite/sqlite/src/tokenize.c new file mode 100644 index 0000000000..061e5b9a45 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/tokenize.c @@ -0,0 +1,707 @@ +/* +** 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 splits an SQL input string up into +** individual tokens and sends those tokens one-by-one over to the +** parser for analysis. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> +#include <stdlib.h> + +/* +** This function looks up an identifier to determine if it is a +** keyword.  If it is a keyword, the token code of that keyword is  +** returned.  If the input is not a keyword, TK_ID is returned. +** +** The implementation of this routine was generated by a program, +** mkkeywordhash.c, located in the tool subdirectory of the distribution. +** The output of the mkkeywordhash.c program was manually cut and pasted +** into this file.  When the set of keywords for SQLite changes, you +** must modify the mkkeywordhash.c program (to add or remove keywords from +** the data tables) then rerun that program to regenerate this function. +*/ +int sqlite3KeywordCode(const char *z, int n){ +  static const char zText[519] = +    "ABORTAFTERALLANDASCATTACHBEFOREBEGINBETWEENBYCASCADECASECHECK" +    "COLLATECOMMITCONFLICTCONSTRAINTCREATECROSSDATABASEDEFAULTDEFERRABLE" +    "DEFERREDDELETEDESCDETACHDISTINCTDROPEACHELSEENDEXCEPTEXCLUSIVE" +    "EXPLAINFAILFOREIGNFROMFULLGLOBGROUPHAVINGIGNOREIMMEDIATEINDEX" +    "INITIALLYINNERINSERTINSTEADINTERSECTINTOISNULLJOINKEYLEFTLIKE" +    "LIMITMATCHNATURALNOTNULLNULLOFFSETONORDEROUTERPRAGMAPRIMARYRAISE" +    "REFERENCESREPLACERESTRICTRIGHTROLLBACKROWSELECTSETSTATEMENTTABLE" +    "TEMPORARYTHENTRANSACTIONTRIGGERUNIONUNIQUEUPDATEUSINGVACUUMVALUES" +    "VIEWWHENWHERE"; +  static const unsigned char aHash[154] = { +       0,  75,  82,   0,   0,  97,  80,   0,  83,   0,   0,   0,   0, +       0,   0,   6,   0,  95,   4,   0,   0,   0,   0,   0,   0,   0, +       0,  96,  86,   8,   0,  26,  13,   7,  19,  15,   0,   0,  32, +      25,   0,  21,  31,  41,   0,   0,   0,  34,  27,   0,   0,  30, +       0,   0,   0,   9,   0,  10,   0,   0,   0,   0,  51,   0,  44, +      43,   0,  45,  40,   0,  29,  39,  35,   0,   0,  20,   0,  59, +       0,  16,   0,  17,   0,  18,   0,  55,  42,  72,   0,  33,   0, +       0,  61,  66,  56,   0,   0,   0,   0,   0,   0,   0,  54,   0, +       0,   0,   0,   0,  74,  50,  76,  64,  52,   0,   0,   0,   0, +      68,  84,   0,  47,   0,  58,  60,  92,   0,   0,  48,   0,  93, +       0,  63,  71,  98,   0,   0,   0,   0,   0,  67,   0,   0,   0, +       0,  87,   0,   0,   0,   0,   0,  90,  88,   0,  94, +  }; +  static const unsigned char aNext[98] = { +       0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0, +       0,  12,   0,   0,   0,   0,   0,   0,  11,   0,   0,   0,   0, +       0,   0,   0,  14,   3,  24,   0,   0,   0,   1,  22,   0,   0, +      36,  23,  28,   0,   0,   0,   0,   0,   0,   0,   0,   5,   0, +       0,  49,  37,   0,   0,   0,  38,   0,  53,   0,  57,  62,   0, +       0,   0,   0,   0,   0,  70,  46,   0,  65,   0,   0,   0,   0, +      69,  73,   0,  77,   0,   0,   0,   0,   0,   0,  81,  85,   0, +      91,  79,  78,   0,   0,  89,   0, +  }; +  static const unsigned char aLen[98] = { +       5,   5,   3,   3,   2,   3,   6,   6,   5,   7,   2,   7,   4, +       5,   7,   6,   8,  10,   6,   5,   8,   7,  10,   8,   6,   4, +       6,   8,   4,   4,   4,   3,   6,   9,   7,   4,   3,   7,   4, +       4,   4,   5,   6,   6,   9,   2,   5,   9,   5,   6,   7,   9, +       4,   2,   6,   4,   3,   4,   4,   5,   5,   7,   3,   7,   4, +       2,   6,   2,   2,   5,   5,   6,   7,   5,  10,   7,   8,   5, +       8,   3,   6,   3,   9,   5,   4,   9,   4,  11,   7,   5,   6, +       6,   5,   6,   6,   4,   4,   5, +  }; +  static const unsigned short int aOffset[98] = { +       0,   5,  10,  13,  16,  16,  19,  25,  31,  36,  43,  45,  52, +      56,  61,  68,  74,  82,  92,  98, 103, 111, 118, 128, 136, 142, +     146, 152, 160, 164, 168, 172, 175, 181, 190, 197, 201, 201, 208, +     212, 216, 220, 225, 231, 237, 246, 246, 251, 260, 265, 271, 278, +     287, 291, 291, 297, 301, 304, 308, 312, 317, 322, 329, 329, 336, +     340, 340, 346, 348, 348, 353, 358, 364, 371, 376, 386, 393, 401, +     406, 414, 417, 423, 426, 435, 440, 440, 449, 453, 464, 471, 476, +     482, 488, 493, 499, 505, 509, 513, +  }; +  static const unsigned char aCode[98] = { +    TK_ABORT,      TK_AFTER,      TK_ALL,        TK_AND,        TK_AS,          +    TK_ASC,        TK_ATTACH,     TK_BEFORE,     TK_BEGIN,      TK_BETWEEN,     +    TK_BY,         TK_CASCADE,    TK_CASE,       TK_CHECK,      TK_COLLATE,     +    TK_COMMIT,     TK_CONFLICT,   TK_CONSTRAINT, TK_CREATE,     TK_JOIN_KW,     +    TK_DATABASE,   TK_DEFAULT,    TK_DEFERRABLE, TK_DEFERRED,   TK_DELETE,      +    TK_DESC,       TK_DETACH,     TK_DISTINCT,   TK_DROP,       TK_EACH,        +    TK_ELSE,       TK_END,        TK_EXCEPT,     TK_EXCLUSIVE,  TK_EXPLAIN,     +    TK_FAIL,       TK_FOR,        TK_FOREIGN,    TK_FROM,       TK_JOIN_KW,     +    TK_GLOB,       TK_GROUP,      TK_HAVING,     TK_IGNORE,     TK_IMMEDIATE,   +    TK_IN,         TK_INDEX,      TK_INITIALLY,  TK_JOIN_KW,    TK_INSERT,      +    TK_INSTEAD,    TK_INTERSECT,  TK_INTO,       TK_IS,         TK_ISNULL,      +    TK_JOIN,       TK_KEY,        TK_JOIN_KW,    TK_LIKE,       TK_LIMIT,       +    TK_MATCH,      TK_JOIN_KW,    TK_NOT,        TK_NOTNULL,    TK_NULL,        +    TK_OF,         TK_OFFSET,     TK_ON,         TK_OR,         TK_ORDER,       +    TK_JOIN_KW,    TK_PRAGMA,     TK_PRIMARY,    TK_RAISE,      TK_REFERENCES,  +    TK_REPLACE,    TK_RESTRICT,   TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,         +    TK_SELECT,     TK_SET,        TK_STATEMENT,  TK_TABLE,      TK_TEMP,        +    TK_TEMP,       TK_THEN,       TK_TRANSACTION,TK_TRIGGER,    TK_UNION,       +    TK_UNIQUE,     TK_UPDATE,     TK_USING,      TK_VACUUM,     TK_VALUES,      +    TK_VIEW,       TK_WHEN,       TK_WHERE,       +  }; +  int h, i; +  if( n<2 ) return TK_ID; +  h = (sqlite3UpperToLower[((unsigned char*)z)[0]]*5 +  +      sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3 + +      n) % 154; +  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ +    if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ +      return aCode[i]; +    } +  } +  return TK_ID; +} + +/* +** If X is a character that can be used in an identifier and +** X&0x80==0 then isIdChar[X] will be 1.  If X&0x80==0x80 then +** X is always an identifier character.  (Hence all UTF-8 +** characters can be part of an identifier).  isIdChar[X] will +** be 0 for every character in the lower 128 ASCII characters +** that cannot be used as part of an identifier. +** +** In this implementation, an identifier can be a string of +** alphabetic characters, digits, and "_" plus any character +** with the high-order bit set.  The latter rule means that +** any sequence of UTF-8 characters or characters taken from +** an extended ISO8859 character set can form an identifier. +*/ +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)  (((c=C)&0x80)!=0 || (c>0x2f && isIdChar[c-0x30])) + +/* +** Return the length of the token that begins at z[0].  +** Store the token type in *tokenType before returning. +*/ +static int sqliteGetToken(const unsigned char *z, int *tokenType){ +  int i, c; +  switch( *z ){ +    case ' ': case '\t': case '\n': case '\f': case '\r': { +      for(i=1; isspace(z[i]); i++){} +      *tokenType = TK_SPACE; +      return i; +    } +    case '-': { +      if( z[1]=='-' ){ +        for(i=2; (c=z[i])!=0 && c!='\n'; i++){} +        *tokenType = TK_COMMENT; +        return i; +      } +      *tokenType = TK_MINUS; +      return 1; +    } +    case '(': { +      *tokenType = TK_LP; +      return 1; +    } +    case ')': { +      *tokenType = TK_RP; +      return 1; +    } +    case ';': { +      *tokenType = TK_SEMI; +      return 1; +    } +    case '+': { +      *tokenType = TK_PLUS; +      return 1; +    } +    case '*': { +      *tokenType = TK_STAR; +      return 1; +    } +    case '/': { +      if( z[1]!='*' || z[2]==0 ){ +        *tokenType = TK_SLASH; +        return 1; +      } +      for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} +      if( c ) i++; +      *tokenType = TK_COMMENT; +      return i; +    } +    case '%': { +      *tokenType = TK_REM; +      return 1; +    } +    case '=': { +      *tokenType = TK_EQ; +      return 1 + (z[1]=='='); +    } +    case '<': { +      if( (c=z[1])=='=' ){ +        *tokenType = TK_LE; +        return 2; +      }else if( c=='>' ){ +        *tokenType = TK_NE; +        return 2; +      }else if( c=='<' ){ +        *tokenType = TK_LSHIFT; +        return 2; +      }else{ +        *tokenType = TK_LT; +        return 1; +      } +    } +    case '>': { +      if( (c=z[1])=='=' ){ +        *tokenType = TK_GE; +        return 2; +      }else if( c=='>' ){ +        *tokenType = TK_RSHIFT; +        return 2; +      }else{ +        *tokenType = TK_GT; +        return 1; +      } +    } +    case '!': { +      if( z[1]!='=' ){ +        *tokenType = TK_ILLEGAL; +        return 2; +      }else{ +        *tokenType = TK_NE; +        return 2; +      } +    } +    case '|': { +      if( z[1]!='|' ){ +        *tokenType = TK_BITOR; +        return 1; +      }else{ +        *tokenType = TK_CONCAT; +        return 2; +      } +    } +    case ',': { +      *tokenType = TK_COMMA; +      return 1; +    } +    case '&': { +      *tokenType = TK_BITAND; +      return 1; +    } +    case '~': { +      *tokenType = TK_BITNOT; +      return 1; +    } +    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; +          } +        } +      } +      if( c ) i++; +      *tokenType = TK_STRING; +      return i; +    } +    case '.': { +      *tokenType = TK_DOT; +      return 1; +    } +    case '0': case '1': case '2': case '3': case '4': +    case '5': case '6': case '7': case '8': case '9': { +      *tokenType = TK_INTEGER; +      for(i=1; isdigit(z[i]); i++){} +      if( z[i]=='.' && isdigit(z[i+1]) ){ +        i += 2; +        while( isdigit(z[i]) ){ i++; } +        *tokenType = TK_FLOAT; +      } +      if( (z[i]=='e' || z[i]=='E') && +           ( isdigit(z[i+1])  +            || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) +           ) +      ){ +        i += 2; +        while( isdigit(z[i]) ){ i++; } +        *tokenType = TK_FLOAT; +      } +      return i; +    } +    case '[': { +      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} +      *tokenType = TK_ID; +      return i; +    } +    case '?': { +      *tokenType = TK_VARIABLE; +      for(i=1; isdigit(z[i]); i++){} +      return i; +    } +    case ':': { +      for(i=1; IdChar(z[i]); i++){} +      *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL; +      return i; +    } +    case '$': { +      *tokenType = TK_VARIABLE; +      if( z[1]=='{' ){ +        int nBrace = 1; +        for(i=2; (c=z[i])!=0 && nBrace; i++){ +          if( c=='{' ){ +            nBrace++; +          }else if( c=='}' ){ +            nBrace--; +          } +        } +        if( c==0 ) *tokenType = TK_ILLEGAL; +      }else{ +        int n = 0; +        for(i=1; (c=z[i])!=0; i++){ +          if( isalnum(c) || c=='_' ){ +            n++; +          }else if( c=='(' && n>0 ){ +            do{ +              i++; +            }while( (c=z[i])!=0 && !isspace(c) && c!=')' ); +            if( c==')' ){ +              i++; +            }else{ +              *tokenType = TK_ILLEGAL; +            } +            break; +          }else if( c==':' && z[i+1]==':' ){ +            i++; +          }else{ +            break; +          } +        } +        if( n==0 ) *tokenType = TK_ILLEGAL; +      } +      return i; +    }  +    case 'x': case 'X': { +      if( (c=z[1])=='\'' || c=='"' ){ +        int delim = c; +        *tokenType = TK_BLOB; +        for(i=2; (c=z[i])!=0; i++){ +          if( c==delim ){ +            if( i%2 ) *tokenType = TK_ILLEGAL; +            break; +          } +          if( !isxdigit(c) ){ +            *tokenType = TK_ILLEGAL; +            return i; +          } +        } +        if( c ) i++; +        return i; +      } +      /* Otherwise fall through to the next case */ +    } +    default: { +      if( !IdChar(*z) ){ +        break; +      } +      for(i=1; IdChar(z[i]); i++){} +      *tokenType = sqlite3KeywordCode((char*)z, i); +      return i; +    } +  } +  *tokenType = TK_ILLEGAL; +  return 1; +} + +/* +** Run the parser on the given SQL string.  The parser structure is +** passed in.  An SQLITE_ status code is returned.  If an error occurs +** and pzErrMsg!=NULL then an error message might be written into  +** memory obtained from malloc() and *pzErrMsg made to point to that +** error message.  Or maybe not. +*/ +int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ +  int nErr = 0; +  int i; +  void *pEngine; +  int tokenType; +  int lastTokenParsed = -1; +  sqlite3 *db = pParse->db; +  extern void *sqlite3ParserAlloc(void*(*)(int)); +  extern void sqlite3ParserFree(void*, void(*)(void*)); +  extern int sqlite3Parser(void*, int, Token, Parse*); + +  db->flags &= ~SQLITE_Interrupt; +  pParse->rc = SQLITE_OK; +  i = 0; +  pEngine = sqlite3ParserAlloc((void*(*)(int))malloc); +  if( pEngine==0 ){ +    sqlite3SetString(pzErrMsg, "out of memory", (char*)0); +    return 1; +  } +  assert( pParse->sLastToken.dyn==0 ); +  assert( pParse->pNewTable==0 ); +  assert( pParse->pNewTrigger==0 ); +  assert( pParse->nVar==0 ); +  assert( pParse->nVarExpr==0 ); +  assert( pParse->nVarExprAlloc==0 ); +  assert( pParse->apVarExpr==0 ); +  pParse->zTail = pParse->zSql = zSql; +  while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){ +    assert( i>=0 ); +    pParse->sLastToken.z = &zSql[i]; +    assert( pParse->sLastToken.dyn==0 ); +    pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); +    i += pParse->sLastToken.n; +    switch( tokenType ){ +      case TK_SPACE: +      case TK_COMMENT: { +        if( (db->flags & SQLITE_Interrupt)!=0 ){ +          pParse->rc = SQLITE_INTERRUPT; +          sqlite3SetString(pzErrMsg, "interrupt", (char*)0); +          goto abort_parse; +        } +        break; +      } +      case TK_ILLEGAL: { +        if( pzErrMsg ){ +          sqliteFree(*pzErrMsg); +          *pzErrMsg = sqlite3MPrintf("unrecognized token: \"%T\"", +                          &pParse->sLastToken); +        } +        nErr++; +        goto abort_parse; +      } +      case TK_SEMI: { +        pParse->zTail = &zSql[i]; +        /* Fall thru into the default case */ +      } +      default: { +        sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); +        lastTokenParsed = tokenType; +        if( pParse->rc!=SQLITE_OK ){ +          goto abort_parse; +        } +        break; +      } +    } +  } +abort_parse: +  if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ +    if( lastTokenParsed!=TK_SEMI ){ +      sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); +      pParse->zTail = &zSql[i]; +    } +    sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); +  } +  sqlite3ParserFree(pEngine, free); +  if( sqlite3_malloc_failed ){ +    pParse->rc = SQLITE_NOMEM; +  } +  if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ +    sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), +                    (char*)0); +  } +  if( pParse->zErrMsg ){ +    if( pzErrMsg && *pzErrMsg==0 ){ +      *pzErrMsg = pParse->zErrMsg; +    }else{ +      sqliteFree(pParse->zErrMsg); +    } +    pParse->zErrMsg = 0; +    if( !nErr ) nErr++; +  } +  if( pParse->pVdbe && pParse->nErr>0 ){ +    sqlite3VdbeDelete(pParse->pVdbe); +    pParse->pVdbe = 0; +  } +  sqlite3DeleteTable(pParse->db, pParse->pNewTable); +  sqlite3DeleteTrigger(pParse->pNewTrigger); +  sqliteFree(pParse->apVarExpr); +  if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ +    pParse->rc = SQLITE_ERROR; +  } +  return nErr; +} + +/* +** Token types used by the sqlite3_complete() routine.  See the header +** comments on that procedure for additional information. +*/ +#define tkEXPLAIN 0 +#define tkCREATE  1 +#define tkTEMP    2 +#define tkTRIGGER 3 +#define tkEND     4 +#define tkSEMI    5 +#define tkWS      6 +#define tkOTHER   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) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of  +**                 a statement. +** +**   (2) CREATE    The keyword CREATE has been seen at the beginning of a +**                 statement, possibly preceeded by EXPLAIN and/or followed by +**                 TEMP or TEMPORARY +** +**   (3) NORMAL    We are in the middle of statement which ends with a single +**                 semicolon. +** +**   (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) tkEXPLAIN   The "explain" keyword. +**   (1) tkCREATE    The "create" keyword. +**   (2) tkTEMP      The "temp" or "temporary" keyword. +**   (3) tkTRIGGER   The "trigger" keyword. +**   (4) tkEND       The "end" keyword. +**   (5) tkSEMI      A semicolon. +**   (6) tkWS        Whitespace +**   (7) tkOTHER     Any other SQL token. +** +** Whitespace never causes a state transition and is always ignored. +*/ +int sqlite3_complete(const char *zSql){ +  u8 state = 0;   /* Current state, using numbers defined in header comment */ +  u8 token;       /* Value of the next token */ + +  /* The following matrix defines the transition from one state to another +  ** according to what token is seen.  trans[state][token] returns the +  ** next state. +  */ +  static const u8 trans[7][8] = { +                     /* Token:                                                */ +     /* State:       **  EXPLAIN  CREATE  TEMP  TRIGGER  END  SEMI  WS  OTHER */ +     /* 0   START: */ {       1,      2,    3,       3,   3,    0,  0,     3, }, +     /* 1 EXPLAIN: */ {       3,      2,    3,       3,   3,    0,  1,     3, }, +     /* 2  CREATE: */ {       3,      3,    2,       4,   3,    0,  2,     3, }, +     /* 3  NORMAL: */ {       3,      3,    3,       3,   3,    0,  3,     3, }, +     /* 4 TRIGGER: */ {       4,      4,    4,       4,   4,    5,  4,     4, }, +     /* 5    SEMI: */ {       4,      4,    4,       4,   6,    5,  5,     4, }, +     /* 6     END: */ {       4,      4,    4,       4,   4,    0,  6,     4, }, +  }; + +  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 '"':     /* 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++){} +          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 if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ +                token = tkEXPLAIN; +              }else{ +                token = tkOTHER; +              } +              break; +            } +            default: { +              token = tkOTHER; +              break; +            } +          } +          zSql += nId-1; +        }else{ +          /* Operators and special symbols */ +          token = tkOTHER; +        } +        break; +      } +    } +    state = trans[state][token]; +    zSql++; +  } +  return state==0; +} + +/* +** 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 = 0; + +  pVal = sqlite3ValueNew(); +  sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); +  zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); +  if( zSql8 ){ +    rc = sqlite3_complete(zSql8); +  } +  sqlite3ValueFree(pVal); +  return rc; +} diff --git a/ext/pdo_sqlite/sqlite/src/trigger.c b/ext/pdo_sqlite/sqlite/src/trigger.c new file mode 100644 index 0000000000..bbb526f802 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/trigger.c @@ -0,0 +1,804 @@ +/* +** +** The author disclaims copyright to this source code.  In place of +** a legal notice, here is a blessing: +** +**    May you do good and not evil. +**    May you find forgiveness for yourself and forgive others. +**    May you share freely, never taking more than you give. +** +************************************************************************* +* +*/ +#include "sqliteInt.h" + +/* +** Delete a linked list of TriggerStep structures. +*/ +void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){ +  while( pTriggerStep ){ +    TriggerStep * pTmp = pTriggerStep; +    pTriggerStep = pTriggerStep->pNext; + +    if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z); +    sqlite3ExprDelete(pTmp->pWhere); +    sqlite3ExprListDelete(pTmp->pExprList); +    sqlite3SelectDelete(pTmp->pSelect); +    sqlite3IdListDelete(pTmp->pIdList); + +    sqliteFree(pTmp); +  } +} + +/* +** This is called by the parser when it sees a CREATE TRIGGER statement +** up to the point of the BEGIN before the trigger actions.  A Trigger +** structure is generated based on the information available and stored +** in pParse->pNewTrigger.  After the trigger actions have been parsed, the +** sqlite3FinishTrigger() function is called to complete the trigger +** construction process. +*/ +void sqlite3BeginTrigger( +  Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */ +  Token *pName1,      /* The name of the trigger */ +  Token *pName2,      /* The name of the trigger */ +  int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ +  int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ +  IdList *pColumns,   /* column list if this is an UPDATE OF trigger */ +  SrcList *pTableName,/* The name of the table/view the trigger applies to */ +  int foreach,        /* One of TK_ROW or TK_STATEMENT */ +  Expr *pWhen,        /* WHEN clause */ +  int isTemp          /* True if the TEMPORARY keyword is present */ +){ +  Trigger *pTrigger; +  Table *pTab; +  char *zName = 0;        /* Name of the trigger */ +  sqlite3 *db = pParse->db; +  int iDb;                /* The database to store the trigger in */ +  Token *pName;           /* The unqualified db name */ +  DbFixer sFix; + +  if( isTemp ){ +    /* If TEMP was specified, then the trigger name may not be qualified. */ +    if( pName2 && pName2->n>0 ){ +      sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); +      goto trigger_cleanup; +    } +    iDb = 1; +    pName = pName1; +  }else{ +    /* Figure out the db that the the trigger will be created in */ +    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); +    if( iDb<0 ){ +      goto trigger_cleanup; +    } +  } + +  /* If the trigger name was unqualified, and the table is a temp table, +  ** then set iDb to 1 to create the trigger in the temporary database. +  ** If sqlite3SrcListLookup() returns 0, indicating the table does not +  ** exist, the error is caught by the block below. +  */ +  if( !pTableName || sqlite3_malloc_failed ) goto trigger_cleanup; +  pTab = sqlite3SrcListLookup(pParse, pTableName); +  if( pName2->n==0 && pTab && pTab->iDb==1 ){ +    iDb = 1; +  } + +  /* Ensure the table name matches database name and that the table exists */ +  if( sqlite3_malloc_failed ) goto trigger_cleanup; +  assert( pTableName->nSrc==1 ); +  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&  +      sqlite3FixSrcList(&sFix, pTableName) ){ +    goto trigger_cleanup; +  } +  pTab = sqlite3SrcListLookup(pParse, pTableName); +  if( !pTab ){ +    /* The table does not exist. */ +    goto trigger_cleanup; +  } + +  /* Check that the trigger name is not reserved and that no trigger of the +  ** specified name exists */ +  zName = sqlite3NameFromToken(pName); +  if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ +    goto trigger_cleanup; +  } +  if( sqlite3HashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){ +    sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); +    goto trigger_cleanup; +  } + +  /* Do not create a trigger on a system table */ +  if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) ||  +      (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0)  +  ){ +    sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); +    pParse->nErr++; +    goto trigger_cleanup; +  } + +  /* INSTEAD of triggers are only for views and views only support INSTEAD +  ** of triggers. +  */ +  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ +    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",  +        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); +    goto trigger_cleanup; +  } +  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ +    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" +        " trigger on table: %S", pTableName, 0); +    goto trigger_cleanup; +  } + +#ifndef SQLITE_OMIT_AUTHORIZATION +  { +    int code = SQLITE_CREATE_TRIGGER; +    const char *zDb = db->aDb[pTab->iDb].zName; +    const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; +    if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; +    if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ +      goto trigger_cleanup; +    } +    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){ +      goto trigger_cleanup; +    } +  } +#endif + +  /* INSTEAD OF triggers can only appear on views and BEFORE triggers +  ** cannot appear on views.  So we might as well translate every +  ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code +  ** elsewhere. +  */ +  if (tr_tm == TK_INSTEAD){ +    tr_tm = TK_BEFORE; +  } + +  /* Build the Trigger object */ +  pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); +  if( pTrigger==0 ) goto trigger_cleanup; +  pTrigger->name = zName; +  zName = 0; +  pTrigger->table = sqliteStrDup(pTableName->a[0].zName); +  if( sqlite3_malloc_failed ) goto trigger_cleanup; +  pTrigger->iDb = iDb; +  pTrigger->iTabDb = pTab->iDb; +  pTrigger->op = op; +  pTrigger->tr_tm = tr_tm; +  pTrigger->pWhen = sqlite3ExprDup(pWhen); +  pTrigger->pColumns = sqlite3IdListDup(pColumns); +  pTrigger->foreach = foreach; +  sqlite3TokenCopy(&pTrigger->nameToken,pName); +  assert( pParse->pNewTrigger==0 ); +  pParse->pNewTrigger = pTrigger; + +trigger_cleanup: +  sqliteFree(zName); +  sqlite3SrcListDelete(pTableName); +  sqlite3IdListDelete(pColumns); +  sqlite3ExprDelete(pWhen); +} + +/* +** This routine is called after all of the trigger actions have been parsed +** in order to complete the process of building the trigger. +*/ +void sqlite3FinishTrigger( +  Parse *pParse,          /* Parser context */ +  TriggerStep *pStepList, /* The triggered program */ +  Token *pAll             /* Token that describes the complete CREATE TRIGGER */ +){ +  Trigger *nt = 0;          /* The trigger whose construction is finishing up */ +  sqlite3 *db = pParse->db;  /* The database */ +  DbFixer sFix; + +  if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup; +  nt = pParse->pNewTrigger; +  pParse->pNewTrigger = 0; +  nt->step_list = pStepList; +  while( pStepList ){ +    pStepList->pTrig = nt; +    pStepList = pStepList->pNext; +  } +  if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)  +          && sqlite3FixTriggerStep(&sFix, nt->step_list) ){ +    goto triggerfinish_cleanup; +  } + +  /* if we are not initializing, and this trigger is not on a TEMP table,  +  ** build the sqlite_master entry +  */ +  if( !db->init.busy ){ +    static const VdbeOpList insertTrig[] = { +      { OP_NewRecno,   0, 0,  0          }, +      { OP_String8,    0, 0,  "trigger"  }, +      { OP_String8,    0, 0,  0          },  /* 2: trigger name */ +      { OP_String8,    0, 0,  0          },  /* 3: table name */ +      { OP_Integer,    0, 0,  0          }, +      { OP_String8,    0, 0,  "CREATE TRIGGER "}, +      { OP_String8,    0, 0,  0          },  /* 6: SQL */ +      { OP_Concat,     0, 0,  0          },  +      { OP_MakeRecord, 5, 0,  "tttit"    }, +      { OP_PutIntKey,  0, 0,  0          }, +    }; +    int addr; +    Vdbe *v; + +    /* Make an entry in the sqlite_master table */ +    v = sqlite3GetVdbe(pParse); +    if( v==0 ) goto triggerfinish_cleanup; +    sqlite3BeginWriteOperation(pParse, 0, nt->iDb); +    sqlite3OpenMasterTable(v, nt->iDb); +    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); +    sqlite3VdbeChangeP3(v, addr+2, nt->name, 0);  +    sqlite3VdbeChangeP3(v, addr+3, nt->table, 0);  +    sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); +    if( nt->iDb!=0 ){ +      sqlite3ChangeCookie(db, v, nt->iDb); +    } +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); +    sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0,  +       sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC); +  } + +  if( db->init.busy ){ +    Table *pTab; +    sqlite3HashInsert(&db->aDb[nt->iDb].trigHash,  +                     nt->name, strlen(nt->name)+1, nt); +    pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName); +    assert( pTab!=0 ); +    nt->pNext = pTab->pTrigger; +    pTab->pTrigger = nt; +    nt = 0; +  } + +triggerfinish_cleanup: +  sqlite3DeleteTrigger(nt); +  sqlite3DeleteTrigger(pParse->pNewTrigger); +  pParse->pNewTrigger = 0; +  sqlite3DeleteTriggerStep(pStepList); +} + +/* +** Make a copy of all components of the given trigger step.  This has +** the effect of copying all Expr.token.z values into memory obtained +** from sqliteMalloc().  As initially created, the Expr.token.z values +** all point to the input string that was fed to the parser.  But that +** string is ephemeral - it will go away as soon as the sqlite3_exec() +** call that started the parser exits.  This routine makes a persistent +** copy of all the Expr.token.z strings so that the TriggerStep structure +** will be valid even after the sqlite3_exec() call returns. +*/ +static void sqlitePersistTriggerStep(TriggerStep *p){ +  if( p->target.z ){ +    p->target.z = sqliteStrNDup(p->target.z, p->target.n); +    p->target.dyn = 1; +  } +  if( p->pSelect ){ +    Select *pNew = sqlite3SelectDup(p->pSelect); +    sqlite3SelectDelete(p->pSelect); +    p->pSelect = pNew; +  } +  if( p->pWhere ){ +    Expr *pNew = sqlite3ExprDup(p->pWhere); +    sqlite3ExprDelete(p->pWhere); +    p->pWhere = pNew; +  } +  if( p->pExprList ){ +    ExprList *pNew = sqlite3ExprListDup(p->pExprList); +    sqlite3ExprListDelete(p->pExprList); +    p->pExprList = pNew; +  } +  if( p->pIdList ){ +    IdList *pNew = sqlite3IdListDup(p->pIdList); +    sqlite3IdListDelete(p->pIdList); +    p->pIdList = pNew; +  } +} + +/* +** Turn a SELECT statement (that the pSelect parameter points to) into +** a trigger step.  Return a pointer to a TriggerStep structure. +** +** The parser calls this routine when it finds a SELECT statement in +** body of a TRIGGER.   +*/ +TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ +  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); +  if( pTriggerStep==0 ) return 0; + +  pTriggerStep->op = TK_SELECT; +  pTriggerStep->pSelect = pSelect; +  pTriggerStep->orconf = OE_Default; +  sqlitePersistTriggerStep(pTriggerStep); + +  return pTriggerStep; +} + +/* +** Build a trigger step out of an INSERT statement.  Return a pointer +** to the new trigger step. +** +** The parser calls this routine when it sees an INSERT inside the +** body of a trigger. +*/ +TriggerStep *sqlite3TriggerInsertStep( +  Token *pTableName,  /* Name of the table into which we insert */ +  IdList *pColumn,    /* List of columns in pTableName to insert into */ +  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */ +  Select *pSelect,    /* A SELECT statement that supplies values */ +  int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ +){ +  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); +  if( pTriggerStep==0 ) return 0; + +  assert(pEList == 0 || pSelect == 0); +  assert(pEList != 0 || pSelect != 0); + +  pTriggerStep->op = TK_INSERT; +  pTriggerStep->pSelect = pSelect; +  pTriggerStep->target  = *pTableName; +  pTriggerStep->pIdList = pColumn; +  pTriggerStep->pExprList = pEList; +  pTriggerStep->orconf = orconf; +  sqlitePersistTriggerStep(pTriggerStep); + +  return pTriggerStep; +} + +/* +** Construct a trigger step that implements an UPDATE statement and return +** a pointer to that trigger step.  The parser calls this routine when it +** sees an UPDATE statement inside the body of a CREATE TRIGGER. +*/ +TriggerStep *sqlite3TriggerUpdateStep( +  Token *pTableName,   /* Name of the table to be updated */ +  ExprList *pEList,    /* The SET clause: list of column and new values */ +  Expr *pWhere,        /* The WHERE clause */ +  int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ +){ +  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); +  if( pTriggerStep==0 ) return 0; + +  pTriggerStep->op = TK_UPDATE; +  pTriggerStep->target  = *pTableName; +  pTriggerStep->pExprList = pEList; +  pTriggerStep->pWhere = pWhere; +  pTriggerStep->orconf = orconf; +  sqlitePersistTriggerStep(pTriggerStep); + +  return pTriggerStep; +} + +/* +** Construct a trigger step that implements a DELETE statement and return +** a pointer to that trigger step.  The parser calls this routine when it +** sees a DELETE statement inside the body of a CREATE TRIGGER. +*/ +TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){ +  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); +  if( pTriggerStep==0 ) return 0; + +  pTriggerStep->op = TK_DELETE; +  pTriggerStep->target  = *pTableName; +  pTriggerStep->pWhere = pWhere; +  pTriggerStep->orconf = OE_Default; +  sqlitePersistTriggerStep(pTriggerStep); + +  return pTriggerStep; +} + +/*  +** Recursively delete a Trigger structure +*/ +void sqlite3DeleteTrigger(Trigger *pTrigger){ +  if( pTrigger==0 ) return; +  sqlite3DeleteTriggerStep(pTrigger->step_list); +  sqliteFree(pTrigger->name); +  sqliteFree(pTrigger->table); +  sqlite3ExprDelete(pTrigger->pWhen); +  sqlite3IdListDelete(pTrigger->pColumns); +  if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z); +  sqliteFree(pTrigger); +} + +/* +** This function is called to drop a trigger from the database schema.  +** +** This may be called directly from the parser and therefore identifies +** the trigger by name.  The sqlite3DropTriggerPtr() routine does the +** same job as this routine except it takes a pointer to the trigger +** instead of the trigger name. +**/ +void sqlite3DropTrigger(Parse *pParse, SrcList *pName){ +  Trigger *pTrigger = 0; +  int i; +  const char *zDb; +  const char *zName; +  int nName; +  sqlite3 *db = pParse->db; + +  if( sqlite3_malloc_failed ) goto drop_trigger_cleanup; +  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ +    goto drop_trigger_cleanup; +  } + +  assert( pName->nSrc==1 ); +  zDb = pName->a[0].zDatabase; +  zName = pName->a[0].zName; +  nName = strlen(zName); +  for(i=0; i<db->nDb; i++){ +    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */ +    if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; +    pTrigger = sqlite3HashFind(&(db->aDb[j].trigHash), zName, nName+1); +    if( pTrigger ) break; +  } +  if( !pTrigger ){ +    sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); +    goto drop_trigger_cleanup; +  } +  sqlite3DropTriggerPtr(pParse, pTrigger, 0); + +drop_trigger_cleanup: +  sqlite3SrcListDelete(pName); +} + +/* +** Return a pointer to the Table structure for the table that a trigger +** is set on. +*/ +static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){ +  return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName); +} + + +/* +** Drop a trigger given a pointer to that trigger.  If nested is false, +** then also generate code to remove the trigger from the SQLITE_MASTER +** table. +*/ +void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ +  Table   *pTable; +  Vdbe *v; +  sqlite3 *db = pParse->db; +  int iDb; + +  iDb = pTrigger->iDb; +  assert( iDb>=0 && iDb<db->nDb ); +  pTable = tableOfTrigger(db, pTrigger); +  assert(pTable); +  assert( pTable->iDb==iDb || iDb==1 ); +#ifndef SQLITE_OMIT_AUTHORIZATION +  { +    int code = SQLITE_DROP_TRIGGER; +    const char *zDb = db->aDb[iDb].zName; +    const char *zTab = SCHEMA_TABLE(iDb); +    if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; +    if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || +      sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ +      return; +    } +  } +#endif + +  /* Generate code to destroy the database record of the trigger. +  */ +  if( pTable!=0 && (v = sqlite3GetVdbe(pParse))!=0 ){ +    int base; +    static const VdbeOpList dropTrigger[] = { +      { OP_Rewind,     0, ADDR(9),  0}, +      { OP_String8,    0, 0,        0}, /* 1 */ +      { OP_Column,     0, 1,        0}, +      { OP_Ne,         0, ADDR(8),  0}, +      { OP_String8,    0, 0,        "trigger"}, +      { OP_Column,     0, 0,        0}, +      { OP_Ne,         0, ADDR(8),  0}, +      { OP_Delete,     0, 0,        0}, +      { OP_Next,       0, ADDR(1),  0}, /* 8 */ +    }; + +    sqlite3BeginWriteOperation(pParse, 0, iDb); +    sqlite3OpenMasterTable(v, iDb); +    base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger); +    sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); +    sqlite3ChangeCookie(db, v, iDb); +    sqlite3VdbeAddOp(v, OP_Close, 0, 0); +    sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); +  } +} + +/* +** Remove a trigger from the hash tables of the sqlite* pointer. +*/ +void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ +  Trigger *pTrigger; +  int nName = strlen(zName); +  pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0); +  if( pTrigger ){ +    Table *pTable = tableOfTrigger(db, pTrigger); +    assert( pTable!=0 ); +    if( pTable->pTrigger == pTrigger ){ +      pTable->pTrigger = pTrigger->pNext; +    }else{ +      Trigger *cc = pTable->pTrigger; +      while( cc ){  +        if( cc->pNext == pTrigger ){ +          cc->pNext = cc->pNext->pNext; +          break; +        } +        cc = cc->pNext; +      } +      assert(cc); +    } +    sqlite3DeleteTrigger(pTrigger); +    db->flags |= SQLITE_InternChanges; +  } +} + +/* +** pEList is the SET clause of an UPDATE statement.  Each entry +** in pEList is of the format <id>=<expr>.  If any of the entries +** in pEList have an <id> which matches an identifier in pIdList, +** then return TRUE.  If pIdList==NULL, then it is considered a +** wildcard that matches anything.  Likewise if pEList==NULL then +** it matches anything so always return true.  Return false only +** if there is no match. +*/ +static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ +  int e; +  if( !pIdList || !pEList ) return 1; +  for(e=0; e<pEList->nExpr; e++){ +    if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; +  } +  return 0;  +} + +/* A global variable that is TRUE if we should always set up temp tables for + * for triggers, even if there are no triggers to code. This is used to test  + * how much overhead the triggers algorithm is causing. + * + * This flag can be set or cleared using the "trigger_overhead_test" pragma. + * The pragma is not documented since it is not really part of the interface + * to SQLite, just the test procedure. +*/ +int sqlite3_always_code_trigger_setup = 0; + +/* + * Returns true if a trigger matching op, tr_tm and foreach that is NOT already + * on the Parse objects trigger-stack (to prevent recursive trigger firing) is + * found in the list specified as pTrigger. + */ +int sqlite3TriggersExist( +  Parse *pParse,          /* Used to check for recursive triggers */ +  Trigger *pTrigger,      /* A list of triggers associated with a table */ +  int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ +  int tr_tm,              /* one of TK_BEFORE, TK_AFTER */ +  int foreach,            /* one of TK_ROW or TK_STATEMENT */ +  ExprList *pChanges      /* Columns that change in an UPDATE statement */ +){ +  Trigger * pTriggerCursor; + +  if( sqlite3_always_code_trigger_setup ){ +    return 1; +  } + +  pTriggerCursor = pTrigger; +  while( pTriggerCursor ){ +    if( pTriggerCursor->op == op &&  +	pTriggerCursor->tr_tm == tr_tm &&  +	pTriggerCursor->foreach == foreach && +	checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){ +      TriggerStack * ss; +      ss = pParse->trigStack; +      while( ss && ss->pTrigger != pTrigger ){ +	ss = ss->pNext; +      } +      if( !ss )return 1; +    } +    pTriggerCursor = pTriggerCursor->pNext; +  } + +  return 0; +} + +/* +** Convert the pStep->target token into a SrcList and return a pointer +** to that SrcList. +** +** This routine adds a specific database name, if needed, to the target when +** forming the SrcList.  This prevents a trigger in one database from +** referring to a target in another database.  An exception is when the +** trigger is in TEMP in which case it can refer to any other database it +** wants. +*/ +static SrcList *targetSrcList( +  Parse *pParse,       /* The parsing context */ +  TriggerStep *pStep   /* The trigger containing the target token */ +){ +  Token sDb;           /* Dummy database name token */ +  int iDb;             /* Index of the database to use */ +  SrcList *pSrc;       /* SrcList to be returned */ + +  iDb = pStep->pTrig->iDb; +  if( iDb==0 || iDb>=2 ){ +    assert( iDb<pParse->db->nDb ); +    sDb.z = pParse->db->aDb[iDb].zName; +    sDb.n = strlen(sDb.z); +    pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target); +  } else { +    pSrc = sqlite3SrcListAppend(0, &pStep->target, 0); +  } +  return pSrc; +} + +/* +** Generate VDBE code for zero or more statements inside the body of a +** trigger.   +*/ +static int codeTriggerProgram( +  Parse *pParse,            /* The parser context */ +  TriggerStep *pStepList,   /* List of statements inside the trigger body */ +  int orconfin              /* Conflict algorithm. (OE_Abort, etc) */   +){ +  TriggerStep * pTriggerStep = pStepList; +  int orconf; +  Vdbe *v = pParse->pVdbe; + +  assert( pTriggerStep!=0 ); +  assert( v!=0 ); +  sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); +  VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); +  while( pTriggerStep ){ +    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; +    pParse->trigStack->orconf = orconf; +    switch( pTriggerStep->op ){ +      case TK_SELECT: { +	Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);		   +	assert(ss); +	assert(ss->pSrc); +	sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); +	sqlite3SelectDelete(ss); +	break; +      } +      case TK_UPDATE: { +        SrcList *pSrc; +        pSrc = targetSrcList(pParse, pTriggerStep); +        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); +        sqlite3Update(pParse, pSrc, +		sqlite3ExprListDup(pTriggerStep->pExprList),  +		sqlite3ExprDup(pTriggerStep->pWhere), orconf); +        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); +        break; +      } +      case TK_INSERT: { +        SrcList *pSrc; +        pSrc = targetSrcList(pParse, pTriggerStep); +        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); +        sqlite3Insert(pParse, pSrc, +          sqlite3ExprListDup(pTriggerStep->pExprList),  +          sqlite3SelectDup(pTriggerStep->pSelect),  +          sqlite3IdListDup(pTriggerStep->pIdList), orconf); +        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); +        break; +      } +      case TK_DELETE: { +        SrcList *pSrc; +        sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); +        pSrc = targetSrcList(pParse, pTriggerStep); +        sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); +        sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); +        break; +      } +      default: +        assert(0); +    }  +    pTriggerStep = pTriggerStep->pNext; +  } +  sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); +  VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); + +  return 0; +} + +/* +** This is called to code FOR EACH ROW triggers. +** +** When the code that this function generates is executed, the following  +** must be true: +** +** 1. No cursors may be open in the main database.  (But newIdx and oldIdx +**    can be indices of cursors in temporary tables.  See below.) +** +** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then +**    a temporary vdbe cursor (index newIdx) must be open and pointing at +**    a row containing values to be substituted for new.* expressions in the +**    trigger program(s). +** +** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then +**    a temporary vdbe cursor (index oldIdx) must be open and pointing at +**    a row containing values to be substituted for old.* expressions in the +**    trigger program(s). +** +*/ +int sqlite3CodeRowTrigger( +  Parse *pParse,       /* Parse context */ +  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ +  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */ +  int tr_tm,           /* One of TK_BEFORE, TK_AFTER */ +  Table *pTab,         /* The table to code triggers from */ +  int newIdx,          /* The indice of the "new" row to access */ +  int oldIdx,          /* The indice of the "old" row to access */ +  int orconf,          /* ON CONFLICT policy */ +  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */ +){ +  Trigger *pTrigger; +  TriggerStack *pStack; +  TriggerStack trigStackEntry; + +  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); +  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER ); + +  assert(newIdx != -1 || oldIdx != -1); + +  pTrigger = pTab->pTrigger; +  while( pTrigger ){ +    int fire_this = 0; + +    /* determine whether we should code this trigger */ +    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&  +        pTrigger->foreach == TK_ROW ){ +      fire_this = 1; +      for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){ +        if( pStack->pTrigger==pTrigger ){ +	  fire_this = 0; +	} +      } +      if( op == TK_UPDATE && pTrigger->pColumns && +          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){ +        fire_this = 0; +      } +    } +  +    if( fire_this ){ +      int endTrigger; +      SrcList dummyTablist; +      Expr * whenExpr; +      AuthContext sContext; + +      dummyTablist.nSrc = 0; + +      /* Push an entry on to the trigger stack */ +      trigStackEntry.pTrigger = pTrigger; +      trigStackEntry.newIdx = newIdx; +      trigStackEntry.oldIdx = oldIdx; +      trigStackEntry.pTab = pTab; +      trigStackEntry.pNext = pParse->trigStack; +      trigStackEntry.ignoreJump = ignoreJump; +      pParse->trigStack = &trigStackEntry; +      sqlite3AuthContextPush(pParse, &sContext, pTrigger->name); + +      /* code the WHEN clause */ +      endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); +      whenExpr = sqlite3ExprDup(pTrigger->pWhen); +      if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){ +        pParse->trigStack = trigStackEntry.pNext; +        sqlite3ExprDelete(whenExpr); +        return 1; +      } +      sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); +      sqlite3ExprDelete(whenExpr); + +      codeTriggerProgram(pParse, pTrigger->step_list, orconf);  + +      /* Pop the entry off the trigger stack */ +      pParse->trigStack = trigStackEntry.pNext; +      sqlite3AuthContextPop(&sContext); + +      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); +    } +    pTrigger = pTrigger->pNext; +  } +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/src/update.c b/ext/pdo_sqlite/sqlite/src/update.c new file mode 100644 index 0000000000..08c7987c6f --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/update.c @@ -0,0 +1,450 @@ +/* +** 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 UPDATE statements. +** +** $Id$ +*/ +#include "sqliteInt.h" + +/* +** Process an UPDATE statement. +** +**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; +**          \_______/ \________/     \______/       \________________/ +*            onError   pTabList      pChanges             pWhere +*/ +void sqlite3Update( +  Parse *pParse,         /* The parser context */ +  SrcList *pTabList,     /* The table in which we should change things */ +  ExprList *pChanges,    /* Things to be changed */ +  Expr *pWhere,          /* The WHERE clause.  May be null */ +  int onError            /* How to handle constraint errors */ +){ +  int i, j;              /* Loop counters */ +  Table *pTab;           /* The table to be updated */ +  int addr = 0;          /* VDBE instruction address of the start of the loop */ +  WhereInfo *pWInfo;     /* Information about the WHERE clause */ +  Vdbe *v;               /* The virtual database engine */ +  Index *pIdx;           /* For looping over indices */ +  int nIdx;              /* Number of indices that need updating */ +  int nIdxTotal;         /* Total number of indices */ +  int iCur;              /* VDBE Cursor number of pTab */ +  sqlite3 *db;           /* The database structure */ +  Index **apIdx = 0;     /* An array of indices that need updating too */ +  char *aIdxUsed = 0;    /* aIdxUsed[i]==1 if the i-th index is used */ +  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the +                         ** an expression for the i-th column of the table. +                         ** aXRef[i]==-1 if the i-th column is not changed. */ +  int chngRecno;         /* True if the record number is being changed */ +  Expr *pRecnoExpr = 0;  /* Expression defining the new record number */ +  int openAll = 0;       /* True if all indices need to be opened */ +  int isView;            /* Trying to update a view */ +  AuthContext sContext;  /* The authorization context */ + +  int before_triggers;         /* True if there are any BEFORE triggers */ +  int after_triggers;          /* True if there are any AFTER triggers */ +  int row_triggers_exist = 0;  /* True if any row triggers exist */ + +  int newIdx      = -1;  /* index of trigger "new" temp table       */ +  int oldIdx      = -1;  /* index of trigger "old" temp table       */ + +  sContext.pParse = 0; +  if( pParse->nErr || sqlite3_malloc_failed ) goto update_cleanup; +  db = pParse->db; +  assert( pTabList->nSrc==1 ); + +  /* Locate the table which we want to update.  +  */ +  pTab = sqlite3SrcListLookup(pParse, pTabList); +  if( pTab==0 ) goto update_cleanup; +  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,  +            TK_UPDATE, TK_BEFORE, TK_ROW, pChanges); +  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,  +            TK_UPDATE, TK_AFTER, TK_ROW, pChanges); +  row_triggers_exist = before_triggers || after_triggers; +  isView = pTab->pSelect!=0; +  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ +    goto update_cleanup; +  } +  if( isView ){ +    if( sqlite3ViewGetColumnNames(pParse, pTab) ){ +      goto update_cleanup; +    } +  } +  aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol ); +  if( aXRef==0 ) goto update_cleanup; +  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; + +  /* If there are FOR EACH ROW triggers, allocate cursors for the +  ** special OLD and NEW tables +  */ +  if( row_triggers_exist ){ +    newIdx = pParse->nTab++; +    oldIdx = pParse->nTab++; +  } + +  /* Allocate a cursors for the main database table and for all indices. +  ** The index cursors might not be used, but if they are used they +  ** need to occur right after the database cursor.  So go ahead and +  ** allocate enough space, just in case. +  */ +  pTabList->a[0].iCursor = iCur = pParse->nTab++; +  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +    pParse->nTab++; +  } + +  /* Resolve the column names in all the expressions of the +  ** of the UPDATE statement.  Also find the column index +  ** for each column to be updated in the pChanges array.  For each +  ** column to be updated, make sure we have authorization to change +  ** that column. +  */ +  chngRecno = 0; +  for(i=0; i<pChanges->nExpr; i++){ +    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, +             pChanges->a[i].pExpr, 0, 0) ){ +      goto update_cleanup; +    } +    for(j=0; j<pTab->nCol; j++){ +      if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ +        if( j==pTab->iPKey ){ +          chngRecno = 1; +          pRecnoExpr = pChanges->a[i].pExpr; +        } +        aXRef[j] = i; +        break; +      } +    } +    if( j>=pTab->nCol ){ +      if( sqlite3IsRowid(pChanges->a[i].zName) ){ +        chngRecno = 1; +        pRecnoExpr = pChanges->a[i].pExpr; +      }else{ +        sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); +        goto update_cleanup; +      } +    } +#ifndef SQLITE_OMIT_AUTHORIZATION +    { +      int rc; +      rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, +                           pTab->aCol[j].zName, db->aDb[pTab->iDb].zName); +      if( rc==SQLITE_DENY ){ +        goto update_cleanup; +      }else if( rc==SQLITE_IGNORE ){ +        aXRef[j] = -1; +      } +    } +#endif +  } + +  /* Allocate memory for the array apIdx[] and fill it with pointers to every +  ** index that needs to be updated.  Indices only need updating if their +  ** key includes one of the columns named in pChanges or if the record +  ** number of the original table entry is changing. +  */ +  for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){ +    if( chngRecno ){ +      i = 0; +    }else { +      for(i=0; i<pIdx->nColumn; i++){ +        if( aXRef[pIdx->aiColumn[i]]>=0 ) break; +      } +    } +    if( i<pIdx->nColumn ) nIdx++; +  } +  if( nIdxTotal>0 ){ +    apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal ); +    if( apIdx==0 ) goto update_cleanup; +    aIdxUsed = (char*)&apIdx[nIdx]; +  } +  for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ +    if( chngRecno ){ +      i = 0; +    }else{ +      for(i=0; i<pIdx->nColumn; i++){ +        if( aXRef[pIdx->aiColumn[i]]>=0 ) break; +      } +    } +    if( i<pIdx->nColumn ){ +      if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto update_cleanup; +      apIdx[nIdx++] = pIdx; +      aIdxUsed[j] = 1; +    }else{ +      aIdxUsed[j] = 0; +    } +  } + +  /* Resolve the column names in all the expressions in the +  ** WHERE clause. +  */ +  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ +    goto update_cleanup; +  } + +  /* Start the view context +  */ +  if( isView ){ +    sqlite3AuthContextPush(pParse, &sContext, pTab->zName); +  } + +  /* Begin generating code. +  */ +  v = sqlite3GetVdbe(pParse); +  if( v==0 ) goto update_cleanup; +  sqlite3VdbeCountChanges(v); +  sqlite3BeginWriteOperation(pParse, 1, pTab->iDb); + +  /* If we are trying to update a view, construct that view into +  ** a temporary table. +  */ +  if( isView ){ +    Select *pView; +    pView = sqlite3SelectDup(pTab->pSelect); +    sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); +    sqlite3SelectDelete(pView); +  } + +  /* Begin the database scan +  */ +  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0); +  if( pWInfo==0 ) goto update_cleanup; + +  /* Remember the index of every item to be updated. +  */ +  sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); + +  /* End the database scan loop. +  */ +  sqlite3WhereEnd(pWInfo); + +  /* Initialize the count of updated rows +  */ +  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ +    sqlite3VdbeAddOp(v, OP_Integer, 0, 0); +  } + +  if( row_triggers_exist ){ +    /* Create pseudo-tables for NEW and OLD +    */ +    sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); +    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); + +    /* The top of the update loop for when there are triggers. +    */ +    sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); +    addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); +    sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + +    /* Open a cursor and make it point to the record that is +    ** being updated. +    */ +    sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +    if( !isView ){ +      sqlite3OpenTableForReading(v, iCur, pTab); +    } +    sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); + +    /* Generate the OLD table +    */ +    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); +    sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); +    sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0); + +    /* Generate the NEW table +    */ +    if( chngRecno ){ +      sqlite3ExprCode(pParse, pRecnoExpr); +    }else{ +      sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); +    } +    for(i=0; i<pTab->nCol; i++){ /* TODO: Factor out this loop as common code */ +      if( i==pTab->iPKey ){ +        sqlite3VdbeAddOp(v, OP_String8, 0, 0); +        continue; +      } +      j = aXRef[i]; +      if( j<0 ){ +        sqlite3VdbeAddOp(v, OP_Column, iCur, i); +      }else{ +        sqlite3ExprCode(pParse, pChanges->a[j].pExpr); +      } +    } +    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); +    if( !isView ){ +      sqlite3TableAffinityStr(v, pTab); +    } +    if( pParse->nErr ) goto update_cleanup; +    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); +    if( !isView ){ +      sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +    } + +    /* Fire the BEFORE and INSTEAD OF triggers +    */ +    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,  +          newIdx, oldIdx, onError, addr) ){ +      goto update_cleanup; +    } +  } + +  if( !isView ){ +    /*  +    ** Open every index that needs updating.  Note that if any +    ** index could potentially invoke a REPLACE conflict resolution  +    ** action, then we need to open all indices because we might need +    ** to be deleting some records. +    */ +    sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); +    sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum); +    sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); +    if( onError==OE_Replace ){ +      openAll = 1; +    }else{ +      openAll = 0; +      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +        if( pIdx->onError==OE_Replace ){ +          openAll = 1; +          break; +        } +      } +    } +    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ +      if( openAll || aIdxUsed[i] ){ +        sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); +        sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, +                       (char*)&pIdx->keyInfo, P3_KEYINFO); +        assert( pParse->nTab>iCur+i+1 ); +      } +    } + +    /* Loop over every record that needs updating.  We have to load +    ** the old data for each record to be updated because some columns +    ** might not change and we will need to copy the old value. +    ** Also, the old data is needed to delete the old index entires. +    ** So make the cursor point at the old record. +    */ +    if( !row_triggers_exist ){ +      sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); +      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); +      sqlite3VdbeAddOp(v, OP_Dup, 0, 0); +    } +    sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr); + +    /* If the record number will change, push the record number as it +    ** will be after the update. (The old record number is currently +    ** on top of the stack.) +    */ +    if( chngRecno ){ +      sqlite3ExprCode(pParse, pRecnoExpr); +      sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); +    } + +    /* Compute new data for this record.   +    */ +    for(i=0; i<pTab->nCol; i++){ +      if( i==pTab->iPKey ){ +        sqlite3VdbeAddOp(v, OP_String8, 0, 0); +        continue; +      } +      j = aXRef[i]; +      if( j<0 ){ +        sqlite3VdbeAddOp(v, OP_Column, iCur, i); +      }else{ +        sqlite3ExprCode(pParse, pChanges->a[j].pExpr); +      } +    } + +    /* Do constraint checks +    */ +    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, +                                   onError, addr); + +    /* Delete the old indices for the current record. +    */ +    sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed); + +    /* If changing the record number, delete the old record. +    */ +    if( chngRecno ){ +      sqlite3VdbeAddOp(v, OP_Delete, iCur, 0); +    } + +    /* Create the new index entries and the new record. +    */ +    sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1); +  } + +  /* Increment the row counter  +  */ +  if( db->flags & SQLITE_CountRows && !pParse->trigStack){ +    sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); +  } + +  /* If there are triggers, close all the cursors after each iteration +  ** through the loop.  The fire the after triggers. +  */ +  if( row_triggers_exist ){ +    if( !isView ){ +      for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ +        if( openAll || aIdxUsed[i] ) +          sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); +      } +      sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +    } +    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,  +          newIdx, oldIdx, onError, addr) ){ +      goto update_cleanup; +    } +  } + +  /* Repeat the above with the next record to be updated, until +  ** all record selected by the WHERE clause have been updated. +  */ +  sqlite3VdbeAddOp(v, OP_Goto, 0, addr); +  sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); +  sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); + +  /* Close all tables if there were no FOR EACH ROW triggers */ +  if( !row_triggers_exist ){ +    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ +      if( openAll || aIdxUsed[i] ){ +        sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); +      } +    } +    sqlite3VdbeAddOp(v, OP_Close, iCur, 0); +  }else{ +    sqlite3VdbeAddOp(v, OP_Close, newIdx, 0); +    sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0); +  } + +  /* +  ** Return the number of rows that were changed. +  */ +  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ +    sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +    sqlite3VdbeSetNumCols(v, 1); +    sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC); +  } + +update_cleanup: +  sqlite3AuthContextPop(&sContext); +  sqliteFree(apIdx); +  sqliteFree(aXRef); +  sqlite3SrcListDelete(pTabList); +  sqlite3ExprListDelete(pChanges); +  sqlite3ExprDelete(pWhere); +  return; +} diff --git a/ext/pdo_sqlite/sqlite/src/utf.c b/ext/pdo_sqlite/sqlite/src/utf.c new file mode 100644 index 0000000000..58b1a972d7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/utf.c @@ -0,0 +1,566 @@ +/* +** 2004 April 13 +** +** The author disclaims copyright to this source code.  In place of +** a legal notice, here is a blessing: +** +**    May you do good and not evil. +**    May you find forgiveness for yourself and forgive others. +**    May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains routines used to translate between UTF-8,  +** UTF-16, UTF-16BE, and UTF-16LE. +** +** $Id$ +** +** Notes on UTF-8: +** +**   Byte-0    Byte-1    Byte-2    Byte-3    Value +**  0xxxxxxx                                 00000000 00000000 0xxxxxxx +**  110yyyyy  10xxxxxx                       00000000 00000yyy yyxxxxxx +**  1110zzzz  10yyyyyy  10xxxxxx             00000000 zzzzyyyy yyxxxxxx +**  11110uuu  10uuzzzz  10yyyyyy  10xxxxxx   000uuuuu zzzzyyyy yyxxxxxx +** +** +** Notes on UTF-16:  (with wwww+1==uuuuu) +** +**      Word-0               Word-1          Value +**  110110ww wwzzzzyy   110111yy yyxxxxxx    000uuuuu zzzzyyyy yyxxxxxx +**  zzzzyyyy yyxxxxxx                        00000000 zzzzyyyy yyxxxxxx +** +** +** BOM or Byte Order Mark: +**     0xff 0xfe   little-endian utf-16 follows +**     0xfe 0xff   big-endian utf-16 follows +** +** +** Handling of malformed strings: +** +** SQLite accepts and processes malformed strings without an error wherever +** possible. However this is not possible when converting between UTF-8 and +** UTF-16. +** +** When converting malformed UTF-8 strings to UTF-16, one instance of the +** replacement character U+FFFD for each byte that cannot be interpeted as +** part of a valid unicode character. +** +** When converting malformed UTF-16 strings to UTF-8, one instance of the +** replacement character U+FFFD for each pair of bytes that cannot be +** interpeted as part of a valid unicode character. +** +** This file contains the following public routines: +** +** sqlite3VdbeMemTranslate() - Translate the encoding used by a Mem* string. +** sqlite3VdbeMemHandleBom() - Handle byte-order-marks in UTF16 Mem* strings. +** sqlite3utf16ByteLen()     - Calculate byte-length of a void* UTF16 string. +** sqlite3utf8CharLen()      - Calculate char-length of a char* UTF8 string. +** sqlite3utf8LikeCompare()  - Do a LIKE match given two UTF8 char* strings. +** +*/ +#include <assert.h> +#include "sqliteInt.h" +#include "vdbeInt.h" + +/* +** This table maps from the first byte of a UTF-8 character to the number +** of trailing bytes expected. A value '255' indicates that the table key +** is not a legal first byte for a UTF-8 character. +*/ +static const u8 xtra_utf8_bytes[256]  = { +/* 0xxxxxxx */ +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0, + +/* 10wwwwww */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + +/* 110yyyyy */ +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, + +/* 1110zzzz */ +2, 2, 2, 2, 2, 2, 2, 2,     2, 2, 2, 2, 2, 2, 2, 2, + +/* 11110yyy */ +3, 3, 3, 3, 3, 3, 3, 3,     255, 255, 255, 255, 255, 255, 255, 255, +}; + +/* +** This table maps from the number of trailing bytes in a UTF-8 character +** to an integer constant that is effectively calculated for each character +** read by a naive implementation of a UTF-8 character reader. The code +** in the READ_UTF8 macro explains things best. +*/ +static const int xtra_utf8_bits[4] =  { +0, +12416,          /* (0xC0 << 6) + (0x80) */ +925824,         /* (0xE0 << 12) + (0x80 << 6) + (0x80) */ +63447168        /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */ +}; + +#define READ_UTF8(zIn, c) { \ +  int xtra;                                            \ +  c = *(zIn)++;                                        \ +  xtra = xtra_utf8_bytes[c];                           \ +  switch( xtra ){                                      \ +    case 255: c = (int)0xFFFD; break;                  \ +    case 3: c = (c<<6) + *(zIn)++;                     \ +    case 2: c = (c<<6) + *(zIn)++;                     \ +    case 1: c = (c<<6) + *(zIn)++;                     \ +    c -= xtra_utf8_bits[xtra];                         \ +  }                                                    \ +} +int sqlite3ReadUtf8(const unsigned char *z){ +  int c; +  READ_UTF8(z, c); +  return c; +} + +#define SKIP_UTF8(zIn) {                               \ +  zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1);            \ +} + +#define WRITE_UTF8(zOut, c) {                          \ +  if( c<0x00080 ){                                     \ +    *zOut++ = (c&0xFF);                                \ +  }                                                    \ +  else if( c<0x00800 ){                                \ +    *zOut++ = 0xC0 + ((c>>6)&0x1F);                    \ +    *zOut++ = 0x80 + (c & 0x3F);                       \ +  }                                                    \ +  else if( c<0x10000 ){                                \ +    *zOut++ = 0xE0 + ((c>>12)&0x0F);                   \ +    *zOut++ = 0x80 + ((c>>6) & 0x3F);                  \ +    *zOut++ = 0x80 + (c & 0x3F);                       \ +  }else{                                               \ +    *zOut++ = 0xF0 + ((c>>18) & 0x07);                 \ +    *zOut++ = 0x80 + ((c>>12) & 0x3F);                 \ +    *zOut++ = 0x80 + ((c>>6) & 0x3F);                  \ +    *zOut++ = 0x80 + (c & 0x3F);                       \ +  }                                                    \ +} + +#define WRITE_UTF16LE(zOut, c) {                                \ +  if( c<=0xFFFF ){                                              \ +    *zOut++ = (c&0x00FF);                                       \ +    *zOut++ = ((c>>8)&0x00FF);                                  \ +  }else{                                                        \ +    *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \ +    *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03));              \ +    *zOut++ = (c&0x00FF);                                       \ +    *zOut++ = (0x00DC + ((c>>8)&0x03));                         \ +  }                                                             \ +} + +#define WRITE_UTF16BE(zOut, c) {                                \ +  if( c<=0xFFFF ){                                              \ +    *zOut++ = ((c>>8)&0x00FF);                                  \ +    *zOut++ = (c&0x00FF);                                       \ +  }else{                                                        \ +    *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03));              \ +    *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \ +    *zOut++ = (0x00DC + ((c>>8)&0x03));                         \ +    *zOut++ = (c&0x00FF);                                       \ +  }                                                             \ +} + +#define READ_UTF16LE(zIn, c){                                         \ +  c = (*zIn++);                                                       \ +  c += ((*zIn++)<<8);                                                 \ +  if( c>=0xD800 && c<=0xE000 ){                                       \ +    int c2 = (*zIn++);                                                \ +    c2 += ((*zIn++)<<8);                                              \ +    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \ +  }                                                                   \ +} + +#define READ_UTF16BE(zIn, c){                                         \ +  c = ((*zIn++)<<8);                                                  \ +  c += (*zIn++);                                                      \ +  if( c>=0xD800 && c<=0xE000 ){                                       \ +    int c2 = ((*zIn++)<<8);                                           \ +    c2 += (*zIn++);                                                   \ +    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \ +  }                                                                   \ +} + +#define SKIP_UTF16BE(zIn){                                            \ +  if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){  \ +    zIn += 4;                                                         \ +  }else{                                                              \ +    zIn += 2;                                                         \ +  }                                                                   \ +} +#define SKIP_UTF16LE(zIn){                                            \ +  zIn++;                                                              \ +  if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){  \ +    zIn += 3;                                                         \ +  }else{                                                              \ +    zIn += 1;                                                         \ +  }                                                                   \ +} + +#define RSKIP_UTF16LE(zIn){                                            \ +  if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){  \ +    zIn -= 4;                                                         \ +  }else{                                                              \ +    zIn -= 2;                                                         \ +  }                                                                   \ +} +#define RSKIP_UTF16BE(zIn){                                            \ +  zIn--;                                                              \ +  if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){  \ +    zIn -= 3;                                                         \ +  }else{                                                              \ +    zIn -= 1;                                                         \ +  }                                                                   \ +} + +/* +** If the TRANSLATE_TRACE macro is defined, the value of each Mem is +** printed on stderr on the way into and out of sqlite3VdbeMemTranslate(). +*/  +/* #define TRANSLATE_TRACE 1 */ + +/* +** This routine transforms the internal text encoding used by pMem to +** desiredEnc. It is an error if the string is already of the desired +** encoding, or if *pMem does not contain a string value. +*/ +int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ +  unsigned char zShort[NBFS]; /* Temporary short output buffer */ +  int len;                    /* Maximum length of output string in bytes */ +  unsigned char *zOut;                  /* Output buffer */ +  unsigned char *zIn;                   /* Input iterator */ +  unsigned char *zTerm;                 /* End of input */ +  unsigned char *z;                     /* Output iterator */ +  int c; + +  assert( pMem->flags&MEM_Str ); +  assert( pMem->enc!=desiredEnc ); +  assert( pMem->enc!=0 ); +  assert( pMem->n>=0 ); + +#ifdef TRANSLATE_TRACE +  { +    char zBuf[100]; +    sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100); +    fprintf(stderr, "INPUT:  %s\n", zBuf); +  } +#endif + +  /* If the translation is between UTF-16 little and big endian, then  +  ** all that is required is to swap the byte order. This case is handled +  ** differently from the others. +  */ +  if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ +    u8 temp; +    int rc; +    rc = sqlite3VdbeMemMakeWriteable(pMem); +    if( rc!=SQLITE_OK ){ +      assert( rc==SQLITE_NOMEM ); +      return SQLITE_NOMEM; +    } +    zIn = pMem->z; +    zTerm = &zIn[pMem->n]; +    while( zIn<zTerm ){ +      temp = *zIn; +      *zIn = *(zIn+1); +      zIn++; +      *zIn++ = temp; +    } +    pMem->enc = desiredEnc; +    goto translate_out; +  } + +  /* Set len to the maximum number of bytes required in the output buffer. */ +  if( desiredEnc==SQLITE_UTF8 ){ +    /* When converting from UTF-16, the maximum growth results from +    ** translating a 2-byte character to a 3-byte UTF-8 character (i.e. +    ** code-point 0xFFFC). A single byte is required for the output string +    ** nul-terminator. +    */ +    len = (pMem->n/2) * 3 + 1; +  }else{ +    /* When converting from UTF-8 to UTF-16 the maximum growth is caused +    ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 +    ** character. Two bytes are required in the output buffer for the +    ** nul-terminator. +    */ +    len = pMem->n * 2 + 2; +  } + +  /* Set zIn to point at the start of the input buffer and zTerm to point 1 +  ** byte past the end. +  ** +  ** Variable zOut is set to point at the output buffer. This may be space +  ** obtained from malloc(), or Mem.zShort, if it large enough and not in +  ** use, or the zShort array on the stack (see above). +  */ +  zIn = pMem->z; +  zTerm = &zIn[pMem->n]; +  if( len>NBFS ){ +    zOut = sqliteMallocRaw(len); +    if( !zOut ) return SQLITE_NOMEM; +  }else{ +    zOut = zShort; +  } +  z = zOut; + +  if( pMem->enc==SQLITE_UTF8 ){ +    if( desiredEnc==SQLITE_UTF16LE ){ +      /* UTF-8 -> UTF-16 Little-endian */ +      while( zIn<zTerm ){ +        READ_UTF8(zIn, c);  +        WRITE_UTF16LE(z, c); +      } +    }else{ +      assert( desiredEnc==SQLITE_UTF16BE ); +      /* UTF-8 -> UTF-16 Big-endian */ +      while( zIn<zTerm ){ +        READ_UTF8(zIn, c);  +        WRITE_UTF16BE(z, c); +      } +    } +    pMem->n = z - zOut; +    *z++ = 0; +  }else{ +    assert( desiredEnc==SQLITE_UTF8 ); +    if( pMem->enc==SQLITE_UTF16LE ){ +      /* UTF-16 Little-endian -> UTF-8 */ +      while( zIn<zTerm ){ +        READ_UTF16LE(zIn, c);  +        WRITE_UTF8(z, c); +      } +    }else{ +      /* UTF-16 Little-endian -> UTF-8 */ +      while( zIn<zTerm ){ +        READ_UTF16BE(zIn, c);  +        WRITE_UTF8(z, c); +      } +    } +    pMem->n = z - zOut; +  } +  *z = 0; +  assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); + +  sqlite3VdbeMemRelease(pMem); +  pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); +  pMem->enc = desiredEnc; +  if( zOut==zShort ){ +    memcpy(pMem->zShort, zOut, len); +    zOut = pMem->zShort; +    pMem->flags |= (MEM_Term|MEM_Short); +  }else{ +    pMem->flags |= (MEM_Term|MEM_Dyn); +  } +  pMem->z = zOut; + +translate_out: +#ifdef TRANSLATE_TRACE +  { +    char zBuf[100]; +    sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100); +    fprintf(stderr, "OUTPUT: %s\n", zBuf); +  } +#endif +  return SQLITE_OK; +} + +/* +** This routine checks for a byte-order mark at the beginning of the  +** UTF-16 string stored in *pMem. If one is present, it is removed and +** the encoding of the Mem adjusted. This routine does not do any +** byte-swapping, it just sets Mem.enc appropriately. +** +** The allocation (static, dynamic etc.) and encoding of the Mem may be +** changed by this function. +*/ +int sqlite3VdbeMemHandleBom(Mem *pMem){ +  int rc = SQLITE_OK; +  u8 bom = 0; + +  if( pMem->n<0 || pMem->n>1 ){ +    u8 b1 = *(u8 *)pMem->z; +    u8 b2 = *(((u8 *)pMem->z) + 1); +    if( b1==0xFE && b2==0xFF ){ +      bom = SQLITE_UTF16BE; +    } +    if( b1==0xFF && b2==0xFE ){ +      bom = SQLITE_UTF16LE; +    } +  } +   +  if( bom ){ +    /* This function is called as soon as a string is stored in a Mem*, +    ** from within sqlite3VdbeMemSetStr(). At that point it is not possible +    ** for the string to be stored in Mem.zShort, or for it to be stored +    ** in dynamic memory with no destructor. +    */ +    assert( !(pMem->flags&MEM_Short) ); +    assert( !(pMem->flags&MEM_Dyn) || pMem->xDel ); +    if( pMem->flags & MEM_Dyn ){ +      void (*xDel)(void*) = pMem->xDel; +      char *z = pMem->z; +      pMem->z = 0; +      pMem->xDel = 0; +      rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom, SQLITE_TRANSIENT); +      xDel(z); +    }else{ +      rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom,  +          SQLITE_TRANSIENT); +    } +  } +  return rc; +} + +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to  +** the first 0x00, whichever comes first). +*/ +int sqlite3utf8CharLen(const char *z, int nByte){ +  int r = 0; +  const char *zTerm; +  if( nByte>=0 ){ +    zTerm = &z[nByte]; +  }else{ +    zTerm = (const char *)(-1); +  } +  assert( z<=zTerm ); +  while( *z!=0 && z<zTerm ){ +    SKIP_UTF8(z); +    r++; +  } +  return r; +} + +/* +** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, +** return the number of bytes up to (but not including), the first pair +** of consecutive 0x00 bytes in pZ. If nChar is not less than zero, +** then return the number of bytes in the first nChar unicode characters +** in pZ (or up until the first pair of 0x00 bytes, whichever comes first). +*/ +int sqlite3utf16ByteLen(const void *zIn, int nChar){ +  int c = 1; +  char const *z = zIn; +  int n = 0; +  if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){ +    while( c && ((nChar<0) || n<nChar) ){ +      READ_UTF16BE(z, c); +      n++; +    } +  }else{ +    while( c && ((nChar<0) || n<nChar) ){ +      READ_UTF16LE(z, c); +      n++; +    } +  } +  return (z-(char const *)zIn)-((c==0)?2:0); +} + +/* +** UTF-16 implementation of the substr() +*/ +void sqlite3utf16Substr( +  sqlite3_context *context, +  int argc, +  sqlite3_value **argv +){ +  int y, z; +  unsigned char const *zStr; +  unsigned char const *zStrEnd; +  unsigned char const *zStart; +  unsigned char const *zEnd; +  int i; + +  zStr = (unsigned char const *)sqlite3_value_text16(argv[0]); +  zStrEnd = &zStr[sqlite3_value_bytes16(argv[0])]; +  y = sqlite3_value_int(argv[1]); +  z = sqlite3_value_int(argv[2]); + +  if( y>0 ){ +    y = y-1; +    zStart = zStr; +    if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ +      for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16BE(zStart); +    }else{ +      for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16LE(zStart); +    } +  }else{ +    zStart = zStrEnd; +    if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ +      for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16BE(zStart); +    }else{ +      for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16LE(zStart); +    } +    for(; i<0; i++) z -= 1; +  } + +  zEnd = zStart; +  if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ +    for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16BE(zEnd); +  }else{ +    for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16LE(zEnd); +  } + +  sqlite3_result_text16(context, zStart, zEnd-zStart, SQLITE_TRANSIENT); +} + +#if defined(SQLITE_TEST) +/* +** This routine is called from the TCL test function "translate_selftest". +** It checks that the primitives for serializing and deserializing +** characters in each encoding are inverses of each other. +*/ +void sqlite3utfSelfTest(){ +  int i; +  unsigned char zBuf[20]; +  unsigned char *z; +  int n; +  int c; + +  for(i=0; i<0x00110000; i++){ +    z = zBuf; +    WRITE_UTF8(z, i); +    n = z-zBuf; +    z = zBuf; +    READ_UTF8(z, c); +    assert( c==i ); +    assert( (z-zBuf)==n ); +  } +  for(i=0; i<0x00110000; i++){ +    if( i>=0xD800 && i<=0xE000 ) continue; +    z = zBuf; +    WRITE_UTF16LE(z, i); +    n = z-zBuf; +    z = zBuf; +    READ_UTF16LE(z, c); +    assert( c==i ); +    assert( (z-zBuf)==n ); +  } +  for(i=0; i<0x00110000; i++){ +    if( i>=0xD800 && i<=0xE000 ) continue; +    z = zBuf; +    WRITE_UTF16BE(z, i); +    n = z-zBuf; +    z = zBuf; +    READ_UTF16BE(z, c); +    assert( c==i ); +    assert( (z-zBuf)==n ); +  } +} +#endif diff --git a/ext/pdo_sqlite/sqlite/src/util.c b/ext/pdo_sqlite/sqlite/src/util.c new file mode 100644 index 0000000000..74ec89795f --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/util.c @@ -0,0 +1,962 @@ +/* +** 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. +** +************************************************************************* +** Utility functions used throughout sqlite. +** +** This file contains functions for allocating memory, comparing +** strings, and stuff like that. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include <stdarg.h> +#include <ctype.h> + +#if SQLITE_DEBUG>2 && defined(__GLIBC__) +#include <execinfo.h> +void print_stack_trace(){ +  void *bt[30]; +  int i; +  int n = backtrace(bt, 30); + +  sqlite3DebugPrintf("STACK: "); +  for(i=0; i<n;i++){ +    sqlite3DebugPrintf("%p ", bt[i]); +  } +  sqlite3DebugPrintf("\n"); +} +#else +#define print_stack_trace() +#endif + +/* +** If malloc() ever fails, this global variable gets set to 1. +** This causes the library to abort and never again function. +*/ +int sqlite3_malloc_failed = 0; + +/* +** If SQLITE_DEBUG is defined, then use versions of malloc() and +** free() that track memory usage and check for buffer overruns. +*/ +#ifdef SQLITE_DEBUG + +/* +** For keeping track of the number of mallocs and frees.   This +** is used to check for memory leaks. +*/ +int sqlite3_nMalloc;         /* Number of sqliteMalloc() calls */ +int sqlite3_nFree;           /* Number of sqliteFree() calls */ +int sqlite3_iMallocFail;     /* Fail sqliteMalloc() after this many calls */ +#if SQLITE_DEBUG>1 +static int memcnt = 0; +#endif + +/* +** Number of 32-bit guard words +*/ +#define N_GUARD 1 + +/* +** Allocate new memory and set it to zero.  Return NULL if +** no memory is available. +*/ +void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){ +  void *p; +  int *pi; +  int i, k; +  if( sqlite3_iMallocFail>=0 ){ +    sqlite3_iMallocFail--; +    if( sqlite3_iMallocFail==0 ){ +      sqlite3_malloc_failed++; +#if SQLITE_DEBUG>1 +      fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n", +              n, zFile,line); +#endif +      sqlite3_iMallocFail--; +      return 0; +    } +  } +  if( n==0 ) return 0; +  k = (n+sizeof(int)-1)/sizeof(int); +  pi = malloc( (N_GUARD*2+1+k)*sizeof(int)); +  if( pi==0 ){ +    sqlite3_malloc_failed++; +    return 0; +  } +  sqlite3_nMalloc++; +  for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; +  pi[N_GUARD] = n; +  for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344; +  p = &pi[N_GUARD+1]; +  memset(p, bZero==0, n); +#if SQLITE_DEBUG>1 +  print_stack_trace(); +  fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", +      ++memcnt, n, (int)p, zFile,line); +#endif +  return p; +} + +/* +** Check to see if the given pointer was obtained from sqliteMalloc() +** and is able to hold at least N bytes.  Raise an exception if this +** is not the case. +** +** This routine is used for testing purposes only. +*/ +void sqlite3CheckMemory(void *p, int N){ +  int *pi = p; +  int n, i, k; +  pi -= N_GUARD+1; +  for(i=0; i<N_GUARD; i++){ +    assert( pi[i]==0xdead1122 ); +  } +  n = pi[N_GUARD]; +  assert( N>=0 && N<n ); +  k = (n+sizeof(int)-1)/sizeof(int); +  for(i=0; i<N_GUARD; i++){ +    assert( pi[k+N_GUARD+1+i]==0xdead3344 ); +  } +} + +/* +** Free memory previously obtained from sqliteMalloc() +*/ +void sqlite3Free_(void *p, char *zFile, int line){ +  if( p ){ +    int *pi, i, k, n; +    pi = p; +    pi -= N_GUARD+1; +    sqlite3_nFree++; +    for(i=0; i<N_GUARD; i++){ +      if( pi[i]!=0xdead1122 ){ +        fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p); +        return; +      } +    } +    n = pi[N_GUARD]; +    k = (n+sizeof(int)-1)/sizeof(int); +    for(i=0; i<N_GUARD; i++){ +      if( pi[k+N_GUARD+1+i]!=0xdead3344 ){ +        fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p); +        return; +      } +    } +    memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int)); +#if SQLITE_DEBUG>1 +    fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n", +         ++memcnt, n, (int)p, zFile,line); +#endif +    free(pi); +  } +} + +/* +** Resize a prior allocation.  If p==0, then this routine +** works just like sqliteMalloc().  If n==0, then this routine +** works just like sqliteFree(). +*/ +void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){ +  int *oldPi, *pi, i, k, oldN, oldK; +  void *p; +  if( oldP==0 ){ +    return sqlite3Malloc_(n,1,zFile,line); +  } +  if( n==0 ){ +    sqlite3Free_(oldP,zFile,line); +    return 0; +  } +  oldPi = oldP; +  oldPi -= N_GUARD+1; +  if( oldPi[0]!=0xdead1122 ){ +    fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP); +    return 0; +  } +  oldN = oldPi[N_GUARD]; +  oldK = (oldN+sizeof(int)-1)/sizeof(int); +  for(i=0; i<N_GUARD; i++){ +    if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){ +      fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", +              (int)oldP); +      return 0; +    } +  } +  k = (n + sizeof(int) - 1)/sizeof(int); +  pi = malloc( (k+N_GUARD*2+1)*sizeof(int) ); +  if( pi==0 ){ +    sqlite3_malloc_failed++; +    return 0; +  } +  for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; +  pi[N_GUARD] = n; +  for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344; +  p = &pi[N_GUARD+1]; +  memcpy(p, oldP, n>oldN ? oldN : n); +  if( n>oldN ){ +    memset(&((char*)p)[oldN], 0x55, n-oldN); +  } +  memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int)); +  free(oldPi); +#if SQLITE_DEBUG>1 +  print_stack_trace(); +  fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", +    ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line); +#endif +  return p; +} + +/* +** Make a copy of a string in memory obtained from sqliteMalloc() +*/ +char *sqlite3StrDup_(const char *z, char *zFile, int line){ +  char *zNew; +  if( z==0 ) return 0; +  zNew = sqlite3Malloc_(strlen(z)+1, 0, zFile, line); +  if( zNew ) strcpy(zNew, z); +  return zNew; +} +char *sqlite3StrNDup_(const char *z, int n, char *zFile, int line){ +  char *zNew; +  if( z==0 ) return 0; +  zNew = sqlite3Malloc_(n+1, 0, zFile, line); +  if( zNew ){ +    memcpy(zNew, z, n); +    zNew[n] = 0; +  } +  return zNew; +} + +/* +** A version of sqliteFree that is always a function, not a macro. +*/ +void sqlite3FreeX(void *p){ +  sqliteFree(p); +} +#endif /* SQLITE_DEBUG */ + +/* +** The following versions of malloc() and free() are for use in a +** normal build. +*/ +#if !defined(SQLITE_DEBUG) + +/* +** Allocate new memory and set it to zero.  Return NULL if +** no memory is available.  See also sqliteMallocRaw(). +*/ +void *sqlite3Malloc(int n){ +  void *p; +  if( (p = malloc(n))==0 ){ +    if( n>0 ) sqlite3_malloc_failed++; +  }else{ +    memset(p, 0, n); +  } +  return p; +} + +/* +** Allocate new memory but do not set it to zero.  Return NULL if +** no memory is available.  See also sqliteMalloc(). +*/ +void *sqlite3MallocRaw(int n){ +  void *p; +  if( (p = malloc(n))==0 ){ +    if( n>0 ) sqlite3_malloc_failed++; +  } +  return p; +} + +/* +** Free memory previously obtained from sqliteMalloc() +*/ +void sqlite3FreeX(void *p){ +  if( p ){ +    free(p); +  } +} + +/* +** Resize a prior allocation.  If p==0, then this routine +** works just like sqliteMalloc().  If n==0, then this routine +** works just like sqliteFree(). +*/ +void *sqlite3Realloc(void *p, int n){ +  void *p2; +  if( p==0 ){ +    return sqliteMalloc(n); +  } +  if( n==0 ){ +    sqliteFree(p); +    return 0; +  } +  p2 = realloc(p, n); +  if( p2==0 ){ +    sqlite3_malloc_failed++; +  } +  return p2; +} + +/* +** Make a copy of a string in memory obtained from sqliteMalloc() +*/ +char *sqlite3StrDup(const char *z){ +  char *zNew; +  if( z==0 ) return 0; +  zNew = sqliteMallocRaw(strlen(z)+1); +  if( zNew ) strcpy(zNew, z); +  return zNew; +} +char *sqlite3StrNDup(const char *z, int n){ +  char *zNew; +  if( z==0 ) return 0; +  zNew = sqliteMallocRaw(n+1); +  if( zNew ){ +    memcpy(zNew, z, n); +    zNew[n] = 0; +  } +  return zNew; +} +#endif /* !defined(SQLITE_DEBUG) */ + +/* +** 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, const char *zFirst, ...){ +  va_list ap; +  int nByte; +  const char *z; +  char *zResult; + +  if( pz==0 ) return; +  nByte = strlen(zFirst) + 1; +  va_start(ap, zFirst); +  while( (z = va_arg(ap, const char*))!=0 ){ +    nByte += strlen(z); +  } +  va_end(ap); +  sqliteFree(*pz); +  *pz = zResult = sqliteMallocRaw( nByte ); +  if( zResult==0 ){ +    return; +  } +  strcpy(zResult, zFirst); +  zResult += strlen(zResult); +  va_start(ap, zFirst); +  while( (z = va_arg(ap, const char*))!=0 ){ +    strcpy(zResult, z); +    zResult += strlen(zResult); +  } +  va_end(ap); +#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG>1 +  fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz); +#endif +#endif +} + +/* +** Set the most recent error code and error string for the sqlite +** handle "db". The error code is set to "err_code". +** +** If it is not NULL, string zFormat specifies the format of the +** error string in the style of the printf functions: The following +** format characters are allowed: +** +**      %s      Insert a string +**      %z      A string that should be freed after use +**      %d      Insert an integer +**      %T      Insert a token +**      %S      Insert the first element of a SrcList +** +** zFormat and any string tokens that follow it are assumed to be +** encoded in UTF-8. +** +** To clear the most recent error for slqite handle "db", sqlite3Error +** should be called with err_code set to SQLITE_OK and zFormat set +** to NULL. +*/ +void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ +  if( db && (db->pErr || (db->pErr = sqlite3ValueNew())) ){ +    db->errCode = err_code; +    if( zFormat ){ +      char *z; +      va_list ap; +      va_start(ap, zFormat); +      z = sqlite3VMPrintf(zFormat, ap); +      va_end(ap); +      sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3FreeX); +    }else{ +      sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); +    } +  } +} + +/* +** Add an error message to pParse->zErrMsg and increment pParse->nErr. +** The following formatting characters are allowed: +** +**      %s      Insert a string +**      %z      A string that should be freed after use +**      %d      Insert an integer +**      %T      Insert a token +**      %S      Insert the first element of a SrcList +** +** This function should be used to report any error that occurs whilst +** compiling an SQL statement (i.e. within sqlite3_prepare()). The +** last thing the sqlite3_prepare() function does is copy the error +** stored by this function into the database handle using sqlite3Error(). +** Function sqlite3Error() should be used during statement execution +** (sqlite3_step() etc.). +*/ +void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ +  va_list ap; +  pParse->nErr++; +  sqliteFree(pParse->zErrMsg); +  va_start(ap, zFormat); +  pParse->zErrMsg = sqlite3VMPrintf(zFormat, ap); +  va_end(ap); +} + +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters.  The conversion is done in-place.  If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** 2002-Feb-14: This routine is extended to remove MS-Access style +** brackets from around identifers.  For example:  "[a-b-c]" becomes +** "a-b-c". +*/ +void sqlite3Dequote(char *z){ +  int quote; +  int i, j; +  if( z==0 ) return; +  quote = z[0]; +  switch( quote ){ +    case '\'':  break; +    case '"':   break; +    case '[':   quote = ']';  break; +    default:    return; +  } +  for(i=1, j=0; z[i]; i++){ +    if( z[i]==quote ){ +      if( z[i+1]==quote ){ +        z[j++] = quote; +        i++; +      }else{ +        z[j++] = 0; +        break; +      } +    }else{ +      z[j++] = z[i]; +    } +  } +} + +/* An array to map all upper-case characters into their corresponding +** lower-case character.  +*/ +const unsigned char sqlite3UpperToLower[] = { +      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, +     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, +    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, +    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, +    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, +    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, +    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, +    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, +    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, +    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, +    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, +    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, +    252,253,254,255 +}; +#define UpperToLower sqlite3UpperToLower + +/* +** This function computes a hash on the name of a keyword. +** Case is not significant. +*/ +int sqlite3HashNoCase(const char *z, int n){ +  int h = 0; +  if( n<=0 ) n = strlen(z); +  while( n > 0  ){ +    h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++]; +    n--; +  } +  return h & 0x7fffffff; +} + +/* +** Some systems have stricmp().  Others have strcasecmp().  Because +** there is no consistency, we will define our own. +*/ +int sqlite3StrICmp(const char *zLeft, const char *zRight){ +  register unsigned char *a, *b; +  a = (unsigned char *)zLeft; +  b = (unsigned char *)zRight; +  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } +  return UpperToLower[*a] - UpperToLower[*b]; +} +int sqlite3StrNICmp(const char *zLeft, const char *zRight, int N){ +  register unsigned char *a, *b; +  a = (unsigned char *)zLeft; +  b = (unsigned char *)zRight; +  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } +  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; +} + +/* +** Return TRUE if z is a pure numeric string.  Return FALSE if the +** string contains any character which is not part of a number. If +** the string is numeric and contains the '.' character, set *realnum +** to TRUE (otherwise FALSE). +** +** An empty string is considered non-numeric. +*/ +int sqlite3IsNumber(const char *z, int *realnum, u8 enc){ +  int incr = (enc==SQLITE_UTF8?1:2); +  if( enc==SQLITE_UTF16BE ) z++; +  if( *z=='-' || *z=='+' ) z += incr; +  if( !isdigit(*(u8*)z) ){ +    return 0; +  } +  z += incr; +  if( realnum ) *realnum = 0; +  while( isdigit(*(u8*)z) ){ z += incr; } +  if( *z=='.' ){ +    z += incr; +    if( !isdigit(*(u8*)z) ) return 0; +    while( isdigit(*(u8*)z) ){ z += incr; } +    if( realnum ) *realnum = 1; +  } +  if( *z=='e' || *z=='E' ){ +    z += incr; +    if( *z=='+' || *z=='-' ) z += incr; +    if( !isdigit(*(u8*)z) ) return 0; +    while( isdigit(*(u8*)z) ){ z += incr; } +    if( realnum ) *realnum = 1; +  } +  return *z==0; +} + +/* +** The string z[] is an ascii representation of a real number. +** Convert this string to a double. +** +** This routine assumes that z[] really is a valid number.  If it +** is not, the result is undefined. +** +** This routine is used instead of the library atof() function because +** the library atof() might want to use "," as the decimal point instead +** of "." depending on how locale is set.  But that would cause problems +** for SQL.  So this routine always uses "." regardless of locale. +*/ +double sqlite3AtoF(const char *z, const char **pzEnd){ +  int sign = 1; +  LONGDOUBLE_TYPE v1 = 0.0; +  if( *z=='-' ){ +    sign = -1; +    z++; +  }else if( *z=='+' ){ +    z++; +  } +  while( isdigit(*(u8*)z) ){ +    v1 = v1*10.0 + (*z - '0'); +    z++; +  } +  if( *z=='.' ){ +    LONGDOUBLE_TYPE divisor = 1.0; +    z++; +    while( isdigit(*(u8*)z) ){ +      v1 = v1*10.0 + (*z - '0'); +      divisor *= 10.0; +      z++; +    } +    v1 /= divisor; +  } +  if( *z=='e' || *z=='E' ){ +    int esign = 1; +    int eval = 0; +    LONGDOUBLE_TYPE scale = 1.0; +    z++; +    if( *z=='-' ){ +      esign = -1; +      z++; +    }else if( *z=='+' ){ +      z++; +    } +    while( isdigit(*(u8*)z) ){ +      eval = eval*10 + *z - '0'; +      z++; +    } +    while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; } +    while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; } +    while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; } +    while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } +    if( esign<0 ){ +      v1 /= scale; +    }else{ +      v1 *= scale; +    } +  } +  if( pzEnd ) *pzEnd = z; +  return sign<0 ? -v1 : v1; +} + +/* +** Return TRUE if zNum is a 64-bit signed integer and write +** the value of the integer into *pNum.  If zNum is not an integer +** or is an integer that is too large to be expressed with 64 bits, +** then return false.  If n>0 and the integer is string is not +** exactly n bytes long, return false. +** +** When this routine was originally written it dealt with only +** 32-bit numbers.  At that time, it was much faster than the +** atoi() library routine in RedHat 7.2. +*/ +int sqlite3atoi64(const char *zNum, i64 *pNum){ +  i64 v = 0; +  int neg; +  int i, c; +  if( *zNum=='-' ){ +    neg = 1; +    zNum++; +  }else if( *zNum=='+' ){ +    neg = 0; +    zNum++; +  }else{ +    neg = 0; +  } +  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ +    v = v*10 + c - '0'; +  } +  *pNum = neg ? -v : v; +  return c==0 && i>0 &&  +      (i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0)); +} + +/* +** The string zNum represents an integer.  There might be some other +** information following the integer too, but that part is ignored. +** If the integer that the prefix of zNum represents will fit in a +** 32-bit signed integer, return TRUE.  Otherwise return FALSE. +** +** This routine returns FALSE for the string -2147483648 even that +** that number will in fact fit in a 32-bit integer.  But positive +** 2147483648 will not fit in 32 bits.  So it seems safer to return +** false. +*/ +static int sqlite3FitsIn32Bits(const char *zNum){ +  int i, c; +  if( *zNum=='-' || *zNum=='+' ) zNum++; +  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} +  return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0); +} + +/* +** If zNum represents an integer that will fit in 32-bits, then set +** *pValue to that integer and return true.  Otherwise return false. +*/ +int sqlite3GetInt32(const char *zNum, int *pValue){ +  if( sqlite3FitsIn32Bits(zNum) ){ +    *pValue = atoi(zNum); +    return 1; +  } +  return 0; +} + +/* +** The string zNum represents an integer.  There might be some other +** information following the integer too, but that part is ignored. +** If the integer that the prefix of zNum represents will fit in a +** 64-bit signed integer, return TRUE.  Otherwise return FALSE. +** +** This routine returns FALSE for the string -9223372036854775808 even that +** that number will, in theory fit in a 64-bit integer.  Positive +** 9223373036854775808 will not fit in 64 bits.  So it seems safer to return +** false. +*/ +int sqlite3FitsIn64Bits(const char *zNum){ +  int i, c; +  if( *zNum=='-' || *zNum=='+' ) zNum++; +  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} +  return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0); +} + + +/* +** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. +** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN +** when this routine is called. +** +** This routine is a attempt to detect if two threads use the +** same sqlite* pointer at the same time.  There is a race  +** condition so it is possible that the error is not detected. +** But usually the problem will be seen.  The result will be an +** error which can be used to debug the application that is +** using SQLite incorrectly. +** +** Ticket #202:  If db->magic is not a valid open value, take care not +** to modify the db structure at all.  It could be that db is a stale +** pointer.  In other words, it could be that there has been a prior +** call to sqlite3_close(db) and db has been deallocated.  And we do +** not want to write into deallocated memory. +*/ +int sqlite3SafetyOn(sqlite3 *db){ +  if( db->magic==SQLITE_MAGIC_OPEN ){ +    db->magic = SQLITE_MAGIC_BUSY; +    return 0; +  }else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR ){ +    db->magic = SQLITE_MAGIC_ERROR; +    db->flags |= SQLITE_Interrupt; +  } +  return 1; +} + +/* +** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. +** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY +** when this routine is called. +*/ +int sqlite3SafetyOff(sqlite3 *db){ +  if( db->magic==SQLITE_MAGIC_BUSY ){ +    db->magic = SQLITE_MAGIC_OPEN; +    return 0; +  }else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR ){ +    db->magic = SQLITE_MAGIC_ERROR; +    db->flags |= SQLITE_Interrupt; +  } +  return 1; +} + +/* +** Check to make sure we have a valid db pointer.  This test is not +** foolproof but it does provide some measure of protection against +** misuse of the interface such as passing in db pointers that are +** NULL or which have been previously closed.  If this routine returns +** TRUE it means that the db pointer is invalid and should not be +** dereferenced for any reason.  The calling function should invoke +** SQLITE_MISUSE immediately. +*/ +int sqlite3SafetyCheck(sqlite3 *db){ +  int magic; +  if( db==0 ) return 1; +  magic = db->magic; +  if( magic!=SQLITE_MAGIC_CLOSED && +         magic!=SQLITE_MAGIC_OPEN && +         magic!=SQLITE_MAGIC_BUSY ) return 1; +  return 0; +} + +/* +** The variable-length integer encoding is as follows: +** +** KEY: +**         A = 0xxxxxxx    7 bits of data and one flag bit +**         B = 1xxxxxxx    7 bits of data and one flag bit +**         C = xxxxxxxx    8 bits of data +** +**  7 bits - A +** 14 bits - BA +** 21 bits - BBA +** 28 bits - BBBA +** 35 bits - BBBBA +** 42 bits - BBBBBA +** 49 bits - BBBBBBA +** 56 bits - BBBBBBBA +** 64 bits - BBBBBBBBC +*/ + +/* +** Write a 64-bit variable-length integer to memory starting at p[0]. +** The length of data write will be between 1 and 9 bytes.  The number +** of bytes written is returned. +** +** A variable-length integer consists of the lower 7 bits of each byte +** for all bytes that have the 8th bit set and one byte with the 8th +** bit clear.  Except, if we get to the 9th byte, it stores the full +** 8 bits and is the last byte. +*/ +int sqlite3PutVarint(unsigned char *p, u64 v){ +  int i, j, n; +  u8 buf[10]; +  if( v & 0xff00000000000000 ){ +    p[8] = v; +    v >>= 8; +    for(i=7; i>=0; i--){ +      p[i] = (v & 0x7f) | 0x80; +      v >>= 7; +    } +    return 9; +  }     +  n = 0; +  do{ +    buf[n++] = (v & 0x7f) | 0x80; +    v >>= 7; +  }while( v!=0 ); +  buf[0] &= 0x7f; +  assert( n<=9 ); +  for(i=0, j=n-1; j>=0; j--, i++){ +    p[i] = buf[j]; +  } +  return n; +} + +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read.  The value is stored in *v. +*/ +int sqlite3GetVarint(const unsigned char *p, u64 *v){ +  u32 x; +  u64 x64; +  int n; +  unsigned char c; +  if( ((c = p[0]) & 0x80)==0 ){ +    *v = c; +    return 1; +  } +  x = c & 0x7f; +  if( ((c = p[1]) & 0x80)==0 ){ +    *v = (x<<7) | c; +    return 2; +  } +  x = (x<<7) | (c&0x7f); +  if( ((c = p[2]) & 0x80)==0 ){ +    *v = (x<<7) | c; +    return 3; +  } +  x = (x<<7) | (c&0x7f); +  if( ((c = p[3]) & 0x80)==0 ){ +    *v = (x<<7) | c; +    return 4; +  } +  x64 = (x<<7) | (c&0x7f); +  n = 4; +  do{ +    c = p[n++]; +    if( n==9 ){ +      x64 = (x64<<8) | c; +      break; +    } +    x64 = (x64<<7) | (c&0x7f); +  }while( (c & 0x80)!=0 ); +  *v = x64; +  return n; +} + +/* +** Read a 32-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read.  The value is stored in *v. +*/ +int sqlite3GetVarint32(const unsigned char *p, u32 *v){ +  u32 x; +  int n; +  unsigned char c; +  if( ((c = p[0]) & 0x80)==0 ){ +    *v = c; +    return 1; +  } +  x = c & 0x7f; +  if( ((c = p[1]) & 0x80)==0 ){ +    *v = (x<<7) | c; +    return 2; +  } +  x = (x<<7) | (c & 0x7f); +  n = 2; +  do{ +    x = (x<<7) | ((c = p[n++])&0x7f); +  }while( (c & 0x80)!=0 && n<9 ); +  *v = x; +  return n; +} + +/* +** Return the number of bytes that will be needed to store the given +** 64-bit integer. +*/ +int sqlite3VarintLen(u64 v){ +  int i = 0; +  do{ +    i++; +    v >>= 7; +  }while( v!=0 && i<9 ); +  return i; +} + +/* +** Translate a single byte of Hex into an integer. +*/ +static int hexToInt(int h){ +  if( h>='0' && h<='9' ){ +    return h - '0'; +  }else if( h>='a' && h<='f' ){ +    return h - 'a' + 10; +  }else if( h>='A' && h<='F' ){ +    return h - 'A' + 10; +  }else{ +    return 0; +  } +} + +/* +** Convert a BLOB literal of the form "x'hhhhhh'" into its binary +** value.  Return a pointer to its binary value.  Space to hold the +** binary value has been obtained from malloc and must be freed by +** the calling routine. +*/ +void *sqlite3HexToBlob(const char *z){ +  char *zBlob; +  int i; +  int n = strlen(z); +  if( n%2 ) return 0; + +  zBlob = (char *)sqliteMalloc(n/2); +  for(i=0; i<n; i+=2){ +    zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]); +  } +  return zBlob; +} + +#if defined(SQLITE_TEST) +/* +** Convert text generated by the "%p" conversion format back into +** a pointer. +*/ +void *sqlite3TextToPtr(const char *z){ +  void *p; +  u64 v; +  u32 v2; +  if( z[0]=='0' && z[1]=='x' ){ +    z += 2; +  } +  v = 0; +  while( *z ){ +    v = (v<<4) + hexToInt(*z); +    z++; +  } +  if( sizeof(p)==sizeof(v) ){ +    p = *(void**)&v; +  }else{ +    assert( sizeof(p)==sizeof(v2) ); +    v2 = (u32)v; +    p = *(void**)&v2; +  } +  return p; +} +#endif diff --git a/ext/pdo_sqlite/sqlite/src/vacuum.c b/ext/pdo_sqlite/sqlite/src/vacuum.c new file mode 100644 index 0000000000..371a855770 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vacuum.c @@ -0,0 +1,262 @@ +/* +** 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 VACUUM command. +** +** Most of the code in this file may be omitted by defining the +** SQLITE_OMIT_VACUUM macro. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" + +#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM +/* +** Generate a random name of 20 character in length. +*/ +static void randomName(unsigned char *zBuf){ +  static const unsigned char zChars[] = +    "abcdefghijklmnopqrstuvwxyz" +    "0123456789"; +  int i; +  sqlite3Randomness(20, zBuf); +  for(i=0; i<20; i++){ +    zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ]; +  } +} + +/* +** Execute zSql on database db. Return an error code. +*/ +static int execSql(sqlite3 *db, const char *zSql){ +  sqlite3_stmt *pStmt; +  if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ +    return sqlite3_errcode(db); +  } +  while( SQLITE_ROW==sqlite3_step(pStmt) ); +  return sqlite3_finalize(pStmt); +} + +/* +** Execute zSql on database db. The statement returns exactly +** one column. Execute this as SQL on the same database. +*/ +static int execExecSql(sqlite3 *db, const char *zSql){ +  sqlite3_stmt *pStmt; +  int rc; + +  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); +  if( rc!=SQLITE_OK ) return rc; + +  while( SQLITE_ROW==sqlite3_step(pStmt) ){ +    rc = execSql(db, sqlite3_column_text(pStmt, 0)); +    if( rc!=SQLITE_OK ){ +      sqlite3_finalize(pStmt); +      return rc; +    } +  } + +  return sqlite3_finalize(pStmt); +} + +#endif + +/* +** The non-standard VACUUM command is used to clean up the database, +** collapse free space, etc.  It is modelled after the VACUUM command +** in PostgreSQL. +** +** In version 1.0.x of SQLite, the VACUUM command would call +** gdbm_reorganize() on all the database tables.  But beginning +** with 2.0.0, SQLite no longer uses GDBM so this command has +** become a no-op. +*/ +void sqlite3Vacuum(Parse *pParse, Token *pTableName){ +  Vdbe *v = sqlite3GetVdbe(pParse); +  if( v ){ +    sqlite3VdbeAddOp(v, OP_Vacuum, 0, 0); +  } +  return; +} + +/* +** This routine implements the OP_Vacuum opcode of the VDBE. +*/ +int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ +  int rc = SQLITE_OK;     /* Return code from service routines */ +#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM +  const char *zFilename;  /* full pathname of the database file */ +  int nFilename;          /* number of characters  in zFilename[] */ +  char *zTemp = 0;        /* a temporary file in same directory as zFilename */ +  int i;                  /* Loop counter */ +  Btree *pMain;           /* The database being vacuumed */ +  Btree *pTemp; +  char *zSql = 0; + +  if( !db->autoCommit ){ +    sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",  +       (char*)0); +    rc = SQLITE_ERROR; +    goto end_of_vacuum; +  } + +  /* Get the full pathname of the database file and create a +  ** temporary filename in the same directory as the original file. +  */ +  pMain = db->aDb[0].pBt; +  zFilename = sqlite3BtreeGetFilename(pMain); +  assert( zFilename ); +  if( zFilename[0]=='\0' ){ +    /* The in-memory database. Do nothing. Return directly to avoid causing +    ** an error trying to DETACH the vacuum_db (which never got attached) +    ** in the exit-handler. +    */ +    return SQLITE_OK; +  } +  nFilename = strlen(zFilename); +  zTemp = sqliteMalloc( nFilename+100 ); +  if( zTemp==0 ){ +    rc = SQLITE_NOMEM; +    goto end_of_vacuum; +  } +  strcpy(zTemp, zFilename); +  i = 0; +  do { +    zTemp[nFilename] = '-'; +    randomName((unsigned char*)&zTemp[nFilename+1]); +  } while( i<10 && sqlite3OsFileExists(zTemp) ); + +  /* Attach the temporary database as 'vacuum_db'. The synchronous pragma +  ** can be set to 'off' for this file, as it is not recovered if a crash +  ** occurs anyway. The integrity of the database is maintained by a +  ** (possibly synchronous) transaction opened on the main database before +  ** sqlite3BtreeCopyFile() is called. +  ** +  ** An optimisation would be to use a non-journaled pager. +  */ +  zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp); +  if( !zSql ){ +    rc = SQLITE_NOMEM; +    goto end_of_vacuum; +  } +  rc = execSql(db, zSql); +  sqliteFree(zSql); +  zSql = 0; +  if( rc!=SQLITE_OK ) goto end_of_vacuum; +  assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); +  pTemp = db->aDb[db->nDb-1].pBt; +  sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), +     sqlite3BtreeGetReserve(pMain)); +  assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); +  execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); + +  /* Begin a transaction */ +  rc = execSql(db, "BEGIN;"); +  if( rc!=SQLITE_OK ) goto end_of_vacuum; + +  /* Query the schema of the main database. Create a mirror schema +  ** in the temporary database. +  */ +  rc = execExecSql(db,  +      "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) " +      "  FROM sqlite_master WHERE type='table' " +      "UNION ALL " +      "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000) " +      "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' " +      "UNION ALL " +      "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) " +      "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'" +      "UNION ALL " +      "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) " +      "  FROM sqlite_master WHERE type='view'" +  ); +  if( rc!=SQLITE_OK ) goto end_of_vacuum; + +  /* Loop through the tables in the main database. For each, do +  ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy +  ** the contents to the temporary database. +  */ +  rc = execExecSql(db,  +      "SELECT 'INSERT INTO vacuum_db.' || quote(name) " +      "|| ' SELECT * FROM ' || quote(name) || ';'" +      "FROM sqlite_master " +      "WHERE type = 'table';" +  ); +  if( rc!=SQLITE_OK ) goto end_of_vacuum; + +  /* Copy the triggers from the main database to the temporary database. +  ** This was deferred before in case the triggers interfered with copying +  ** the data. It's possible the indices should be deferred until this +  ** point also. +  */ +  rc = execExecSql(db,  +      "SELECT 'CREATE TRIGGER  vacuum_db.' || substr(sql, 16, 1000000) " +      "FROM sqlite_master WHERE type='trigger'" +  ); +  if( rc!=SQLITE_OK ) goto end_of_vacuum; + + +  /* At this point, unless the main db was completely empty, there is now a +  ** transaction open on the vacuum database, but not on the main database. +  ** Open a btree level transaction on the main database. This allows a +  ** call to sqlite3BtreeCopyFile(). The main database btree level +  ** transaction is then committed, so the SQL level never knows it was +  ** opened for writing. This way, the SQL transaction used to create the +  ** temporary database never needs to be committed. +  */ +  if( sqlite3BtreeIsInTrans(pTemp) ){ +    u32 meta; + +    assert( 0==sqlite3BtreeIsInTrans(pMain) ); +    rc = sqlite3BtreeBeginTrans(pMain, 1); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; + +    /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta  +    ** values 2 and 3, the default values of a couple of pragmas. +    */ +    rc = sqlite3BtreeGetMeta(pMain, 3, &meta); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; +    rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; +    rc = sqlite3BtreeGetMeta(pMain, 4, &meta); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; +    rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; + +    rc = sqlite3BtreeCopyFile(pMain, pTemp); +    if( rc!=SQLITE_OK ) goto end_of_vacuum; +    rc = sqlite3BtreeCommit(pMain); +  } + +end_of_vacuum: +  /* Currently there is an SQL level transaction open on the vacuum +  ** database. No locks are held on any other files (since the main file +  ** was committed at the btree level). So it safe to end the transaction +  ** by manually setting the autoCommit flag to true and detaching the +  ** vacuum database. The vacuum_db journal file is deleted when the pager +  ** is closed by the DETACH. +  */ +  db->autoCommit = 1; +  if( rc==SQLITE_OK ){ +    rc = execSql(db, "DETACH vacuum_db;"); +  }else{ +    execSql(db, "DETACH vacuum_db;"); +  } +  if( zTemp ){ +    sqlite3OsDelete(zTemp); +    sqliteFree(zTemp); +  } +  if( zSql ) sqliteFree( zSql ); +  sqlite3ResetInternalSchema(db, 0); +#endif +  return rc; +} diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.c b/ext/pdo_sqlite/sqlite/src/vdbe.c new file mode 100644 index 0000000000..58f8c73109 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbe.c @@ -0,0 +1,4450 @@ +/* +** 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. +** +************************************************************************* +** The code in this file implements execution method of the  +** Virtual Database Engine (VDBE).  A separate file ("vdbeaux.c") +** handles housekeeping details such as creating and deleting +** VDBE instances.  This file is solely interested in executing +** the VDBE program. +** +** In the external interface, an "sqlite3_stmt*" is an opaque pointer +** to a VDBE. +** +** The SQL parser generates a program which is then executed by +** the VDBE to do the work of the SQL statement.  VDBE programs are  +** similar in form to assembly language.  The program consists of +** a linear sequence of operations.  Each operation has an opcode  +** and 3 operands.  Operands P1 and P2 are integers.  Operand P3  +** is a null-terminated string.   The P2 operand must be non-negative. +** Opcodes will typically ignore one or more operands.  Many opcodes +** ignore all three operands. +** +** Computation results are stored on a stack.  Each entry on the +** stack is either an integer, a null-terminated string, a floating point +** number, or the SQL "NULL" value.  An inplicit conversion from one +** type to the other occurs as necessary. +**  +** Most of the code in this file is taken up by the sqlite3VdbeExec() +** function which does the work of interpreting a VDBE program. +** But other routines are also provided to help in building up +** a program instruction by instruction. +** +** Various scripts scan this source file in order to generate HTML +** documentation, headers files, or other derived files.  The formatting +** of the code in this file is, therefore, important.  See other comments +** in this file for details.  If in doubt, do not deviate from existing +** commenting and indentation practices when changing or adding code. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> +#include "vdbeInt.h" + +/* +** The following global variable is incremented every time a cursor +** moves, either by the OP_MoveXX, OP_Next, or OP_Prev opcodes.  The test +** procedures use this information to make sure that indices are +** working correctly.  This variable has no function other than to +** help verify the correct operation of the library. +*/ +int sqlite3_search_count = 0; + +/* +** When this global variable is positive, it gets decremented once before +** each instruction in the VDBE.  When reaches zero, the SQLITE_Interrupt +** of the db.flags field is set in order to simulate and interrupt. +** +** This facility is used for testing purposes only.  It does not function +** in an ordinary build. +*/ +int sqlite3_interrupt_count = 0; + +/* +** Release the memory associated with the given stack level.  This +** leaves the Mem.flags field in an inconsistent state. +*/ +#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); } + +/* +** Convert the given stack entity into a string if it isn't one +** already. Return non-zero if a malloc() fails. +*/ +#define Stringify(P, enc) \ +   if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ +     { goto no_mem; } + +/* +** Convert the given stack entity into a string that has been obtained +** from sqliteMalloc().  This is different from Stringify() above in that +** Stringify() will use the NBFS bytes of static string space if the string +** will fit but this routine always mallocs for space. +** Return non-zero if we run out of memory. +*/ +#define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P) + + +/* +** An ephemeral string value (signified by the MEM_Ephem flag) contains +** a pointer to a dynamically allocated string where some other entity +** is responsible for deallocating that string.  Because the stack entry +** does not control the string, it might be deleted without the stack +** entry knowing it. +** +** This routine converts an ephemeral string into a dynamically allocated +** string that the stack entry itself controls.  In other words, it +** converts an MEM_Ephem string into an MEM_Dyn string. +*/ +#define Deephemeralize(P) \ +   if( ((P)->flags&MEM_Ephem)!=0 \ +       && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} + +/* +** Convert the given stack entity into a integer if it isn't one +** already. +** +** Any prior string or real representation is invalidated.   +** NULLs are converted into 0. +*/ +#define Integerify(P) sqlite3VdbeMemIntegerify(P) + +/* +** Convert P so that it has type MEM_Real. +** +** Any prior string or integer representation is invalidated. +** NULLs are converted into 0.0. +*/ +#define Realify(P) sqlite3VdbeMemRealify(P) + +/* +** Argument pMem points at a memory cell that will be passed to a +** user-defined function or returned to the user as the result of a query. +** The second argument, 'db_enc' is the text encoding used by the vdbe for +** stack variables.  This routine sets the pMem->enc and pMem->type +** variables used by the sqlite3_value_*() routines. +*/ +#define storeTypeInfo(A,B) _storeTypeInfo(A) +static void _storeTypeInfo(Mem *pMem){ +  int flags = pMem->flags; +  if( flags & MEM_Null ){ +    pMem->type = SQLITE_NULL; +  } +  else if( flags & MEM_Int ){ +    pMem->type = SQLITE_INTEGER; +  } +  else if( flags & MEM_Real ){ +    pMem->type = SQLITE_FLOAT; +  } +  else if( flags & MEM_Str ){ +    pMem->type = SQLITE_TEXT; +  }else{ +    pMem->type = SQLITE_BLOB; +  } +} + +/* +** Insert a new aggregate element and make it the element that +** has focus. +** +** Return 0 on success and 1 if memory is exhausted. +*/ +static int AggInsert(Agg *p, char *zKey, int nKey){ +  AggElem *pElem; +  int i; +  int rc; +  pElem = sqliteMalloc( sizeof(AggElem) + nKey + +                        (p->nMem-1)*sizeof(pElem->aMem[0]) ); +  if( pElem==0 ) return SQLITE_NOMEM; +  pElem->zKey = (char*)&pElem->aMem[p->nMem]; +  memcpy(pElem->zKey, zKey, nKey); +  pElem->nKey = nKey; + +  if( p->pCsr ){ +    rc = sqlite3BtreeInsert(p->pCsr, zKey, nKey, &pElem, sizeof(AggElem*)); +    if( rc!=SQLITE_OK ){ +      sqliteFree(pElem); +      return rc; +    } +  } + +  for(i=0; i<p->nMem; i++){ +    pElem->aMem[i].flags = MEM_Null; +  } +  p->pCurrent = pElem; +  return 0; +} + +/* +** Pop the stack N times. +*/ +static void popStack(Mem **ppTos, int N){ +  Mem *pTos = *ppTos; +  while( N>0 ){ +    N--; +    Release(pTos); +    pTos--; +  } +  *ppTos = pTos; +} + +/* +** The parameters are pointers to the head of two sorted lists +** of Sorter structures.  Merge these two lists together and return +** a single sorted list.  This routine forms the core of the merge-sort +** algorithm. +** +** In the case of a tie, left sorts in front of right. +*/ +static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){ +  Sorter sHead; +  Sorter *pTail; +  pTail = &sHead; +  pTail->pNext = 0; +  while( pLeft && pRight ){ +    int c = sqlite3VdbeRecordCompare(pKeyInfo, pLeft->nKey, pLeft->zKey, +                                     pRight->nKey, pRight->zKey); +    if( c<=0 ){ +      pTail->pNext = pLeft; +      pLeft = pLeft->pNext; +    }else{ +      pTail->pNext = pRight; +      pRight = pRight->pNext; +    } +    pTail = pTail->pNext; +  } +  if( pLeft ){ +    pTail->pNext = pLeft; +  }else if( pRight ){ +    pTail->pNext = pRight; +  } +  return sHead.pNext; +} + +/* +** Allocate cursor number iCur.  Return a pointer to it.  Return NULL +** if we run out of memory. +*/ +static Cursor *allocateCursor(Vdbe *p, int iCur){ +  Cursor *pCx; +  assert( iCur<p->nCursor ); +  if( p->apCsr[iCur] ){ +    sqlite3VdbeFreeCursor(p->apCsr[iCur]); +  } +  p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); +  return pCx; +} + +/* +** Apply any conversion required by the supplied column affinity to +** memory cell pRec. affinity may be one of: +** +** SQLITE_AFF_NUMERIC +** SQLITE_AFF_TEXT +** SQLITE_AFF_NONE +** SQLITE_AFF_INTEGER +** +*/ +static void applyAffinity(Mem *pRec, char affinity, u8 enc){ +  if( affinity==SQLITE_AFF_NONE ){ +    /* do nothing */ +  }else if( affinity==SQLITE_AFF_TEXT ){ +    /* Only attempt the conversion to TEXT if there is an integer or real +    ** representation (blob and NULL do not get converted) but no string +    ** representation. +    */ +    if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ +      sqlite3VdbeMemStringify(pRec, enc); +    } +    pRec->flags &= ~(MEM_Real|MEM_Int); +  }else{ +    if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){ +      /* pRec does not have a valid integer or real representation.  +      ** Attempt a conversion if pRec has a string representation and +      ** it looks like a number. +      */ +      int realnum; +      sqlite3VdbeMemNulTerminate(pRec); +      if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum, enc) ){ +        if( realnum ){ +          Realify(pRec); +        }else{ +          Integerify(pRec); +        } +      } +    } + +    if( affinity==SQLITE_AFF_INTEGER ){ +      /* For INTEGER affinity, try to convert a real value to an int */ +      if( (pRec->flags&MEM_Real) && !(pRec->flags&MEM_Int) ){ +        pRec->i = pRec->r; +        if( ((double)pRec->i)==pRec->r ){ +          pRec->flags |= MEM_Int; +        } +      } +    } +  } +} + +#ifndef NDEBUG +/* +** Write a nice string representation of the contents of cell pMem +** into buffer zBuf, length nBuf. +*/ +void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf){ +  char *zCsr = zBuf; +  int f = pMem->flags; + +  static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; + +  if( f&MEM_Blob ){ +    int i; +    char c; +    if( f & MEM_Dyn ){ +      c = 'z'; +      assert( (f & (MEM_Static|MEM_Ephem))==0 ); +    }else if( f & MEM_Static ){ +      c = 't'; +      assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); +    }else if( f & MEM_Ephem ){ +      c = 'e'; +      assert( (f & (MEM_Static|MEM_Dyn))==0 ); +    }else{ +      c = 's'; +    } + +    zCsr += sprintf(zCsr, "%c", c); +    zCsr += sprintf(zCsr, "%d[", pMem->n); +    for(i=0; i<16 && i<pMem->n; i++){ +      zCsr += sprintf(zCsr, "%02X ", ((int)pMem->z[i] & 0xFF)); +    } +    for(i=0; i<16 && i<pMem->n; i++){ +      char z = pMem->z[i]; +      if( z<32 || z>126 ) *zCsr++ = '.'; +      else *zCsr++ = z; +    } + +    zCsr += sprintf(zCsr, "]"); +    *zCsr = '\0'; +  }else if( f & MEM_Str ){ +    int j, k; +    zBuf[0] = ' '; +    if( f & MEM_Dyn ){ +      zBuf[1] = 'z'; +      assert( (f & (MEM_Static|MEM_Ephem))==0 ); +    }else if( f & MEM_Static ){ +      zBuf[1] = 't'; +      assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); +    }else if( f & MEM_Ephem ){ +      zBuf[1] = 'e'; +      assert( (f & (MEM_Static|MEM_Dyn))==0 ); +    }else{ +      zBuf[1] = 's'; +    } +    k = 2; +    k += sprintf(&zBuf[k], "%d", pMem->n); +    zBuf[k++] = '['; +    for(j=0; j<15 && j<pMem->n; j++){ +      u8 c = pMem->z[j]; +      if( c>=0x20 && c<0x7f ){ +        zBuf[k++] = c; +      }else{ +        zBuf[k++] = '.'; +      } +    } +    zBuf[k++] = ']'; +    k += sprintf(&zBuf[k], encnames[pMem->enc]); +    zBuf[k++] = 0; +  } +} +#endif + + +#ifdef VDBE_PROFILE +/* +** The following routine only works on pentium-class processors. +** It uses the RDTSC opcode to read cycle count value out of the +** processor and returns that value.  This can be used for high-res +** profiling. +*/ +__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; +} +#endif + +/* +** The CHECK_FOR_INTERRUPT macro defined here looks to see if the +** sqlite3_interrupt() routine has been called.  If it has been, then +** processing of the VDBE program is interrupted. +** +** This macro added to every instruction that does a jump in order to +** implement a loop.  This test used to be on every single instruction, +** but that meant we more testing that we needed.  By only testing the +** flag on jump instructions, we get a (small) speed improvement. +*/ +#define CHECK_FOR_INTERRUPT \ +   if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt; + + +/* +** Execute as much of a VDBE program as we can then return. +** +** sqlite3VdbeMakeReady() must be called before this routine in order to +** close the program with a final OP_Halt and to set up the callbacks +** and the error message pointer. +** +** Whenever a row or result data is available, this routine will either +** invoke the result callback (if there is one) or return with +** SQLITE_ROW. +** +** If an attempt is made to open a locked database, then this routine +** will either invoke the busy callback (if there is one) or it will +** return SQLITE_BUSY. +** +** If an error occurs, an error message is written to memory obtained +** from sqliteMalloc() and p->zErrMsg is made to point to that memory. +** The error code is stored in p->rc and this routine returns SQLITE_ERROR. +** +** If the callback ever returns non-zero, then the program exits +** immediately.  There will be no error message but the p->rc field is +** set to SQLITE_ABORT and this routine will return SQLITE_ERROR. +** +** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this +** routine to return SQLITE_ERROR. +** +** Other fatal errors return SQLITE_ERROR. +** +** After this routine has finished, sqlite3VdbeFinalize() should be +** used to clean up the mess that was left behind. +*/ +int sqlite3VdbeExec( +  Vdbe *p                    /* The VDBE */ +){ +  int pc;                    /* The program counter */ +  Op *pOp;                   /* Current operation */ +  int rc = SQLITE_OK;        /* Value to return */ +  sqlite3 *db = p->db;       /* The database */ +  Mem *pTos;                 /* Top entry in the operand stack */ +  char zBuf[100];            /* Space to sprintf() an integer */ +#ifdef VDBE_PROFILE +  unsigned long long start;  /* CPU clock count at start of opcode */ +  int origPc;                /* Program counter at start of opcode */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +  int nProgressOps = 0;      /* Opcodes executed since progress callback. */ +#endif + +  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; +  assert( db->magic==SQLITE_MAGIC_BUSY ); +  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); +  p->rc = SQLITE_OK; +  assert( p->explain==0 ); +  pTos = p->pTos; +  if( sqlite3_malloc_failed ) goto no_mem; +  if( p->popStack ){ +    popStack(&pTos, p->popStack); +    p->popStack = 0; +  } +  p->resOnStack = 0; +  CHECK_FOR_INTERRUPT; +  for(pc=p->pc; rc==SQLITE_OK; pc++){ +    assert( pc>=0 && pc<p->nOp ); +    assert( pTos<=&p->aStack[pc] ); +#ifdef VDBE_PROFILE +    origPc = pc; +    start = hwtime(); +#endif +    pOp = &p->aOp[pc]; + +    /* Only allow tracing if NDEBUG is not defined. +    */ +#ifndef NDEBUG +    if( p->trace ){ +      if( pc==0 ){ +        printf("VDBE Execution Trace:\n"); +        sqlite3VdbePrintSql(p); +      } +      sqlite3VdbePrintOp(p->trace, pc, pOp); +    } +#endif +#ifdef SQLITE_TEST +    if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){ +      sqlite3VdbePrintSql(p); +    } +#endif +       + +    /* Check to see if we need to simulate an interrupt.  This only happens +    ** if we have a special test build. +    */ +#ifdef SQLITE_TEST +    if( sqlite3_interrupt_count>0 ){ +      sqlite3_interrupt_count--; +      if( sqlite3_interrupt_count==0 ){ +        sqlite3_interrupt(db); +      } +    } +#endif + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +    /* Call the progress callback if it is configured and the required number +    ** of VDBE ops have been executed (either since this invocation of +    ** sqlite3VdbeExec() or since last time the progress callback was called). +    ** If the progress callback returns non-zero, exit the virtual machine with +    ** a return code SQLITE_ABORT. +    */ +    if( db->xProgress ){ +      if( db->nProgressOps==nProgressOps ){ +        if( db->xProgress(db->pProgressArg)!=0 ){ +          rc = SQLITE_ABORT; +          continue; /* skip to the next iteration of the for loop */ +        } +        nProgressOps = 0; +      } +      nProgressOps++; +    } +#endif + +    switch( pOp->opcode ){ + +/***************************************************************************** +** What follows is a massive switch statement where each case implements a +** separate instruction in the virtual machine.  If we follow the usual +** indentation conventions, each case should be indented by 6 spaces.  But +** that is a lot of wasted space on the left margin.  So the code within +** the switch statement will break with convention and be flush-left. Another +** big comment (similar to this one) will mark the point in the code where +** we transition back to normal indentation. +** +** The formatting of each case is important.  The makefile for SQLite +** generates two C files "opcodes.h" and "opcodes.c" by scanning this +** file looking for lines that begin with "case OP_".  The opcodes.h files +** will be filled with #defines that give unique integer values to each +** opcode and the opcodes.c file is filled with an array of strings where +** each string is the symbolic name for the corresponding opcode.  If the +** case statement is followed by a comment of the form "/# same as ... #/" +** that comment is used to determine the particular value of the opcode. +** +** Documentation about VDBE opcodes is generated by scanning this file +** for lines of that contain "Opcode:".  That line and all subsequent +** comment lines are used in the generation of the opcode.html documentation +** file. +** +** SUMMARY: +** +**     Formatting is important to scripts that scan this file. +**     Do not deviate from the formatting style currently in use. +** +*****************************************************************************/ + +/* Opcode:  Goto * P2 * +** +** An unconditional jump to address P2. +** The next instruction executed will be  +** the one at index P2 from the beginning of +** the program. +*/ +case OP_Goto: { +  CHECK_FOR_INTERRUPT; +  pc = pOp->p2 - 1; +  break; +} + +/* Opcode:  Gosub * P2 * +** +** Push the current address plus 1 onto the return address stack +** and then jump to address P2. +** +** The return address stack is of limited depth.  If too many +** OP_Gosub operations occur without intervening OP_Returns, then +** the return address stack will fill up and processing will abort +** with a fatal error. +*/ +case OP_Gosub: { +  assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) ); +  p->returnStack[p->returnDepth++] = pc+1; +  pc = pOp->p2 - 1; +  break; +} + +/* Opcode:  Return * * * +** +** Jump immediately to the next instruction after the last unreturned +** OP_Gosub.  If an OP_Return has occurred for all OP_Gosubs, then +** processing aborts with a fatal error. +*/ +case OP_Return: { +  assert( p->returnDepth>0 ); +  p->returnDepth--; +  pc = p->returnStack[p->returnDepth] - 1; +  break; +} + +/* Opcode:  Halt P1 P2 * +** +** Exit immediately.  All open cursors, Lists, Sorts, etc are closed +** automatically. +** +** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), +** or sqlite3_finalize().  For a normal halt, this should be SQLITE_OK (0). +** For errors, it can be some other value.  If P1!=0 then P2 will determine +** whether or not to rollback the current transaction.  Do not rollback +** if P2==OE_Fail. Do the rollback if P2==OE_Rollback.  If P2==OE_Abort, +** then back out all changes that have occurred during this execution of the +** VDBE, but do not rollback the transaction.  +** +** There is an implied "Halt 0 0 0" instruction inserted at the very end of +** every program.  So a jump past the last instruction of the program +** is the same as executing Halt. +*/ +case OP_Halt: { +  p->pTos = pTos; +  p->rc = pOp->p1; +  p->pc = pc; +  p->errorAction = pOp->p2; +  if( pOp->p3 ){ +    sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); +  } +  rc = sqlite3VdbeHalt(p); +  if( rc==SQLITE_BUSY ){ +    p->rc = SQLITE_BUSY; +    return SQLITE_BUSY; +  }else if( rc!=SQLITE_OK ){ +    p->rc = rc; +  } +  return p->rc ? SQLITE_ERROR : SQLITE_DONE; +} + +/* Opcode: Integer P1 * P3 +** +** The integer value P1 is pushed onto the stack.  If P3 is not zero +** then it is assumed to be a string representation of the same integer. +** If P1 is zero and P3 is not zero, then the value is derived from P3. +*/ +case OP_Integer: { +  pTos++; +  if( pOp->p3==0 ){ +    pTos->flags = MEM_Int; +    pTos->i = pOp->p1; +  }else{ +    pTos->flags = MEM_Str|MEM_Static|MEM_Term; +    pTos->z = pOp->p3; +    pTos->n = strlen(pTos->z); +    pTos->enc = SQLITE_UTF8; +    pTos->i = sqlite3VdbeIntValue(pTos); +    pTos->flags |= MEM_Int; +  } +  break; +} + +/* Opcode: Real * * P3 +** +** The string value P3 is converted to a real and pushed on to the stack. +*/ +case OP_Real: {            /* same as TK_FLOAT */ +  pTos++; +  pTos->flags = MEM_Str|MEM_Static|MEM_Term; +  pTos->z = pOp->p3; +  pTos->n = strlen(pTos->z); +  pTos->enc = SQLITE_UTF8; +  pTos->r = sqlite3VdbeRealValue(pTos); +  pTos->flags |= MEM_Real; +  sqlite3VdbeChangeEncoding(pTos, db->enc); +  break; +} + +/* Opcode: String8 * * P3 +** +** P3 points to a nul terminated UTF-8 string. This opcode is transformed +** into an OP_String before it is executed for the first time. +*/ +case OP_String8: {         /* same as TK_STRING */ +  pOp->opcode = OP_String; + +  if( db->enc!=SQLITE_UTF8 && pOp->p3 ){ +    pTos++; +    sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); +    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem; +    if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem; +    pTos->flags &= ~(MEM_Dyn); +    pTos->flags |= MEM_Static; +    if( pOp->p3type==P3_DYNAMIC ){ +      sqliteFree(pOp->p3); +    } +    pOp->p3type = P3_DYNAMIC; +    pOp->p3 = pTos->z; +    break; +  } +  /* Otherwise fall through to the next case, OP_String */ +} +   +/* Opcode: String * * P3 +** +** The string value P3 is pushed onto the stack.  If P3==0 then a +** NULL is pushed onto the stack. P3 is assumed to be a nul terminated +** string encoded with the database native encoding. +*/ +case OP_String: { +  pTos++; +  if( pOp->p3 ){ +    pTos->flags = MEM_Str|MEM_Static|MEM_Term; +    pTos->z = pOp->p3; +    if( db->enc==SQLITE_UTF8 ){ +      pTos->n = strlen(pTos->z); +    }else{ +      pTos->n  = sqlite3utf16ByteLen(pTos->z, -1); +    } +    pTos->enc = db->enc; +  }else{ +    pTos->flags = MEM_Null; +  } +  break; +} + +/* Opcode: HexBlob * * P3 +** +** P3 is an UTF-8 SQL hex encoding of a blob. The blob is pushed onto the +** vdbe stack. +** +** The first time this instruction executes, in transforms itself into a +** 'Blob' opcode with a binary blob as P3. +*/ +case OP_HexBlob: {            /* same as TK_BLOB */ +  pOp->opcode = OP_Blob; +  pOp->p1 = strlen(pOp->p3)/2; +  if( pOp->p1 ){ +    char *zBlob = sqlite3HexToBlob(pOp->p3); +    if( !zBlob ) goto no_mem; +    if( pOp->p3type==P3_DYNAMIC ){ +      sqliteFree(pOp->p3); +    } +    pOp->p3 = zBlob; +    pOp->p3type = P3_DYNAMIC; +  }else{ +    if( pOp->p3type==P3_DYNAMIC ){ +      sqliteFree(pOp->p3); +    } +    pOp->p3type = P3_STATIC; +    pOp->p3 = ""; +  } + +  /* Fall through to the next case, OP_Blob. */ +} + +/* Opcode: Blob P1 * P3 +** +** P3 points to a blob of data P1 bytes long. Push this +** value onto the stack. This instruction is not coded directly +** by the compiler. Instead, the compiler layer specifies +** an OP_HexBlob opcode, with the hex string representation of +** the blob as P3. This opcode is transformed to an OP_Blob +** before execution (within the sqlite3_prepare() function). +*/ +case OP_Blob: { +  pTos++; +  sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); +  break; +} + +/* Opcode: Variable P1 * * +** +** Push the value of variable P1 onto the stack.  A variable is +** an unknown in the original SQL string as handed to sqlite3_compile(). +** Any occurance of the '?' character in the original SQL is considered +** a variable.  Variables in the SQL string are number from left to +** right beginning with 1.  The values of variables are set using the +** sqlite3_bind() API. +*/ +case OP_Variable: { +  int j = pOp->p1 - 1; +  assert( j>=0 && j<p->nVar ); + +  pTos++; +  sqlite3VdbeMemShallowCopy(pTos, &p->aVar[j], MEM_Static); +  break; +} + +/* Opcode: Pop P1 * * +** +** P1 elements are popped off of the top of stack and discarded. +*/ +case OP_Pop: { +  assert( pOp->p1>=0 ); +  popStack(&pTos, pOp->p1); +  assert( pTos>=&p->aStack[-1] ); +  break; +} + +/* Opcode: Dup P1 P2 * +** +** A copy of the P1-th element of the stack  +** is made and pushed onto the top of the stack. +** The top of the stack is element 0.  So the +** instruction "Dup 0 0 0" will make a copy of the +** top of the stack. +** +** If the content of the P1-th element is a dynamically +** allocated string, then a new copy of that string +** is made if P2==0.  If P2!=0, then just a pointer +** to the string is copied. +** +** Also see the Pull instruction. +*/ +case OP_Dup: { +  Mem *pFrom = &pTos[-pOp->p1]; +  assert( pFrom<=pTos && pFrom>=p->aStack ); +  pTos++; +  sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem); +  if( pOp->p2 ){ +    Deephemeralize(pTos); +  } +  break; +} + +/* Opcode: Pull P1 * * +** +** The P1-th element is removed from its current location on  +** the stack and pushed back on top of the stack.  The +** top of the stack is element 0, so "Pull 0 0 0" is +** a no-op.  "Pull 1 0 0" swaps the top two elements of +** the stack. +** +** See also the Dup instruction. +*/ +case OP_Pull: { +  Mem *pFrom = &pTos[-pOp->p1]; +  int i; +  Mem ts; + +  ts = *pFrom; +  Deephemeralize(pTos); +  for(i=0; i<pOp->p1; i++, pFrom++){ +    Deephemeralize(&pFrom[1]); +    assert( (pFrom->flags & MEM_Ephem)==0 ); +    *pFrom = pFrom[1]; +    if( pFrom->flags & MEM_Short ){ +      assert( pFrom->flags & (MEM_Str|MEM_Blob) ); +      assert( pFrom->z==pFrom[1].zShort ); +      pFrom->z = pFrom->zShort; +    } +  } +  *pTos = ts; +  if( pTos->flags & MEM_Short ){ +    assert( pTos->flags & (MEM_Str|MEM_Blob) ); +    assert( pTos->z==pTos[-pOp->p1].zShort ); +    pTos->z = pTos->zShort; +  } +  break; +} + +/* Opcode: Push P1 * * +** +** Overwrite the value of the P1-th element down on the +** stack (P1==0 is the top of the stack) with the value +** of the top of the stack.  Then pop the top of the stack. +*/ +case OP_Push: { +  Mem *pTo = &pTos[-pOp->p1]; + +  assert( pTo>=p->aStack ); +  sqlite3VdbeMemMove(pTo, pTos); +  pTos--; +  break; +} + +/* Opcode: Callback P1 * * +** +** Pop P1 values off the stack and form them into an array.  Then +** invoke the callback function using the newly formed array as the +** 3rd parameter. +*/ +case OP_Callback: { +  int i; +  assert( p->nResColumn==pOp->p1 ); + +  for(i=0; i<pOp->p1; i++){ +    Mem *pVal = &pTos[0-i]; +    sqlite3VdbeMemNulTerminate(pVal); +    storeTypeInfo(pVal, db->enc); +  } + +  p->resOnStack = 1; +  p->nCallback++; +  p->popStack = pOp->p1; +  p->pc = pc + 1; +  p->pTos = pTos; +  return SQLITE_ROW; +} + +/* Opcode: Concat P1 P2 * +** +** Look at the first P1+2 elements of the stack.  Append them all  +** together with the lowest element first.  The original P1+2 elements +** are popped from the stack if P2==0 and retained if P2==1.  If +** any element of the stack is NULL, then the result is NULL. +** +** When P1==1, this routine makes a copy of the top stack element +** into memory obtained from sqliteMalloc(). +*/ +case OP_Concat: {           /* same as TK_CONCAT */ +  char *zNew; +  int nByte; +  int nField; +  int i, j; +  Mem *pTerm; + +  /* Loop through the stack elements to see how long the result will be. */ +  nField = pOp->p1 + 2; +  pTerm = &pTos[1-nField]; +  nByte = 0; +  for(i=0; i<nField; i++, pTerm++){ +    assert( pOp->p2==0 || (pTerm->flags&MEM_Str) ); +    if( pTerm->flags&MEM_Null ){ +      nByte = -1; +      break; +    } +    Stringify(pTerm, db->enc); +    nByte += pTerm->n; +  } + +  if( nByte<0 ){ +    /* If nByte is less than zero, then there is a NULL value on the stack. +    ** In this case just pop the values off the stack (if required) and +    ** push on a NULL. +    */ +    if( pOp->p2==0 ){ +      popStack(&pTos, nField); +    } +    pTos++; +    pTos->flags = MEM_Null; +  }else{ +    /* Otherwise malloc() space for the result and concatenate all the +    ** stack values. +    */ +    zNew = sqliteMallocRaw( nByte+2 ); +    if( zNew==0 ) goto no_mem; +    j = 0; +    pTerm = &pTos[1-nField]; +    for(i=j=0; i<nField; i++, pTerm++){ +      int n = pTerm->n; +      assert( pTerm->flags & MEM_Str ); +      memcpy(&zNew[j], pTerm->z, n); +      j += n; +    } +    zNew[j] = 0; +    zNew[j+1] = 0; +    assert( j==nByte ); + +    if( pOp->p2==0 ){ +      popStack(&pTos, nField); +    } +    pTos++; +    pTos->n = j; +    pTos->flags = MEM_Str|MEM_Dyn|MEM_Term; +    pTos->xDel = 0; +    pTos->enc = db->enc; +    pTos->z = zNew; +  } +  break; +} + +/* Opcode: Add * * * +** +** Pop the top two elements from the stack, add them together, +** and push the result back onto the stack.  If either element +** is a string then it is converted to a double using the atof() +** function before the addition. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: Multiply * * * +** +** Pop the top two elements from the stack, multiply them together, +** and push the result back onto the stack.  If either element +** is a string then it is converted to a double using the atof() +** function before the multiplication. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: Subtract * * * +** +** Pop the top two elements from the stack, subtract the +** first (what was on top of the stack) from the second (the +** next on stack) +** and push the result back onto the stack.  If either element +** is a string then it is converted to a double using the atof() +** function before the subtraction. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: Divide * * * +** +** Pop the top two elements from the stack, divide the +** first (what was on top of the stack) from the second (the +** next on stack) +** and push the result back onto the stack.  If either element +** is a string then it is converted to a double using the atof() +** function before the division.  Division by zero returns NULL. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: Remainder * * * +** +** Pop the top two elements from the stack, divide the +** first (what was on top of the stack) from the second (the +** next on stack) +** and push the remainder after division onto the stack.  If either element +** is a string then it is converted to a double using the atof() +** function before the division.  Division by zero returns NULL. +** If either operand is NULL, the result is NULL. +*/ +case OP_Add:                   /* same as TK_PLUS */ +case OP_Subtract:              /* same as TK_MINUS */ +case OP_Multiply:              /* same as TK_STAR */ +case OP_Divide:                /* same as TK_SLASH */ +case OP_Remainder: {           /* same as TK_REM */ +  Mem *pNos = &pTos[-1]; +  assert( pNos>=p->aStack ); +  if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){ +    Release(pTos); +    pTos--; +    Release(pTos); +    pTos->flags = MEM_Null; +  }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ +    i64 a, b; +    a = pTos->i; +    b = pNos->i; +    switch( pOp->opcode ){ +      case OP_Add:         b += a;       break; +      case OP_Subtract:    b -= a;       break; +      case OP_Multiply:    b *= a;       break; +      case OP_Divide: { +        if( a==0 ) goto divide_by_zero; +        b /= a; +        break; +      } +      default: { +        if( a==0 ) goto divide_by_zero; +        b %= a; +        break; +      } +    } +    Release(pTos); +    pTos--; +    Release(pTos); +    pTos->i = b; +    pTos->flags = MEM_Int; +  }else{ +    double a, b; +    a = sqlite3VdbeRealValue(pTos); +    b = sqlite3VdbeRealValue(pNos); +    switch( pOp->opcode ){ +      case OP_Add:         b += a;       break; +      case OP_Subtract:    b -= a;       break; +      case OP_Multiply:    b *= a;       break; +      case OP_Divide: { +        if( a==0.0 ) goto divide_by_zero; +        b /= a; +        break; +      } +      default: { +        int ia = (int)a; +        int ib = (int)b; +        if( ia==0.0 ) goto divide_by_zero; +        b = ib % ia; +        break; +      } +    } +    Release(pTos); +    pTos--; +    Release(pTos); +    pTos->r = b; +    pTos->flags = MEM_Real; +  } +  break; + +divide_by_zero: +  Release(pTos); +  pTos--; +  Release(pTos); +  pTos->flags = MEM_Null; +  break; +} + +/* Opcode: CollSeq * * P3 +** +** P3 is a pointer to a CollSeq struct. If the next call to a user function +** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will +** be returned. This is used by the built-in min(), max() and nullif() +** built-in functions. +** +** The interface used by the implementation of the aforementioned functions +** to retrieve the collation sequence set by this opcode is not available +** publicly, only to user functions defined in func.c. +*/ +case OP_CollSeq: { +  assert( pOp->p3type==P3_COLLSEQ ); +  break; +} + +/* Opcode: Function P1 P2 P3 +** +** Invoke a user function (P3 is a pointer to a Function structure that +** defines the function) with P1 arguments taken from the stack.  Pop all +** arguments from the stack and push back the result. +** +** P2 is a 32-bit bitmask indicating whether or not each argument to the  +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P2 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** See also: AggFunc +*/ +case OP_Function: { +  int i; +  Mem *pArg; +  sqlite3_context ctx; +  sqlite3_value **apVal; +  int n = pOp->p1; + +  n = pOp->p1; +  apVal = p->apArg; +  assert( apVal || n==0 ); + +  pArg = &pTos[1-n]; +  for(i=0; i<n; i++, pArg++){ +    apVal[i] = pArg; +    storeTypeInfo(pArg, db->enc); +  } + +  assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC ); +  if( pOp->p3type==P3_FUNCDEF ){ +    ctx.pFunc = (FuncDef*)pOp->p3; +    ctx.pVdbeFunc = 0; +  }else{ +    ctx.pVdbeFunc = (VdbeFunc*)pOp->p3; +    ctx.pFunc = ctx.pVdbeFunc->pFunc; +  } + +  ctx.s.flags = MEM_Null; +  ctx.s.z = 0; +  ctx.s.xDel = 0; +  ctx.isError = 0; +  ctx.isStep = 0; +  if( ctx.pFunc->needCollSeq ){ +    assert( pOp>p->aOp ); +    assert( pOp[-1].p3type==P3_COLLSEQ ); +    assert( pOp[-1].opcode==OP_CollSeq ); +    ctx.pColl = (CollSeq *)pOp[-1].p3; +  } +  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; +  (*ctx.pFunc->xFunc)(&ctx, n, apVal); +  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; +  if( sqlite3_malloc_failed ) goto no_mem; +  popStack(&pTos, n); + +  /* If any auxilary data functions have been called by this user function, +  ** immediately call the destructor for any non-static values. +  */ +  if( ctx.pVdbeFunc ){ +    sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p2); +    pOp->p3 = (char *)ctx.pVdbeFunc; +    pOp->p3type = P3_VDBEFUNC; +  } + +  /* Copy the result of the function to the top of the stack */ +  sqlite3VdbeChangeEncoding(&ctx.s, db->enc); +  pTos++; +  pTos->flags = 0; +  sqlite3VdbeMemMove(pTos, &ctx.s); + +  /* If the function returned an error, throw an exception */ +  if( ctx.isError ){ +    if( !(pTos->flags&MEM_Str) ){ +      sqlite3SetString(&p->zErrMsg, "user function error", (char*)0); +    }else{ +      sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0); +      sqlite3VdbeChangeEncoding(pTos, db->enc); +    } +    rc = SQLITE_ERROR; +  } +  break; +} + +/* Opcode: BitAnd * * * +** +** Pop the top two elements from the stack.  Convert both elements +** to integers.  Push back onto the stack the bit-wise AND of the +** two elements. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: BitOr * * * +** +** Pop the top two elements from the stack.  Convert both elements +** to integers.  Push back onto the stack the bit-wise OR of the +** two elements. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: ShiftLeft * * * +** +** Pop the top two elements from the stack.  Convert both elements +** to integers.  Push back onto the stack the second element shifted +** left by N bits where N is the top element on the stack. +** If either operand is NULL, the result is NULL. +*/ +/* Opcode: ShiftRight * * * +** +** Pop the top two elements from the stack.  Convert both elements +** to integers.  Push back onto the stack the second element shifted +** right by N bits where N is the top element on the stack. +** If either operand is NULL, the result is NULL. +*/ +case OP_BitAnd:                 /* same as TK_BITAND */ +case OP_BitOr:                  /* same as TK_BITOR */ +case OP_ShiftLeft:              /* same as TK_LSHIFT */ +case OP_ShiftRight: {           /* same as TK_RSHIFT */ +  Mem *pNos = &pTos[-1]; +  int a, b; + +  assert( pNos>=p->aStack ); +  if( (pTos->flags | pNos->flags) & MEM_Null ){ +    popStack(&pTos, 2); +    pTos++; +    pTos->flags = MEM_Null; +    break; +  } +  a = sqlite3VdbeIntValue(pNos); +  b = sqlite3VdbeIntValue(pTos); +  switch( pOp->opcode ){ +    case OP_BitAnd:      a &= b;     break; +    case OP_BitOr:       a |= b;     break; +    case OP_ShiftLeft:   a <<= b;    break; +    case OP_ShiftRight:  a >>= b;    break; +    default:   /* CANT HAPPEN */     break; +  } +  Release(pTos); +  pTos--; +  Release(pTos); +  pTos->i = a; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: AddImm  P1 * * +**  +** Add the value P1 to whatever is on top of the stack.  The result +** is always an integer. +** +** To force the top of the stack to be an integer, just add 0. +*/ +case OP_AddImm: { +  assert( pTos>=p->aStack ); +  Integerify(pTos); +  pTos->i += pOp->p1; +  break; +} + +/* Opcode: ForceInt P1 P2 * +** +** Convert the top of the stack into an integer.  If the current top of +** the stack is not numeric (meaning that is is a NULL or a string that +** does not look like an integer or floating point number) then pop the +** stack and jump to P2.  If the top of the stack is numeric then +** convert it into the least integer that is greater than or equal to its +** current value if P1==0, or to the least integer that is strictly +** greater than its current value if P1==1. +*/ +case OP_ForceInt: { +  int v; +  assert( pTos>=p->aStack ); +  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); +  if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ +    Release(pTos); +    pTos--; +    pc = pOp->p2 - 1; +    break; +  } +  if( pTos->flags & MEM_Int ){ +    v = pTos->i + (pOp->p1!=0); +  }else{ +    Realify(pTos); +    v = (int)pTos->r; +    if( pTos->r>(double)v ) v++; +    if( pOp->p1 && pTos->r==(double)v ) v++; +  } +  Release(pTos); +  pTos->i = v; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: MustBeInt P1 P2 * +**  +** Force the top of the stack to be an integer.  If the top of the +** stack is not an integer and cannot be converted into an integer +** with out data loss, then jump immediately to P2, or if P2==0 +** raise an SQLITE_MISMATCH exception. +** +** If the top of the stack is not an integer and P2 is not zero and +** P1 is 1, then the stack is popped.  In all other cases, the depth +** of the stack is unchanged. +*/ +case OP_MustBeInt: { +  assert( pTos>=p->aStack ); +  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); +  if( (pTos->flags & MEM_Int)==0 ){ +    if( pOp->p2==0 ){ +      rc = SQLITE_MISMATCH; +      goto abort_due_to_error; +    }else{ +      if( pOp->p1 ) popStack(&pTos, 1); +      pc = pOp->p2 - 1; +    } +  }else{ +    Release(pTos); +    pTos->flags = MEM_Int; +  } +  break; +} + +/* Opcode: Eq P1 P2 P3 +** +** Pop the top two elements from the stack.  If they are equal, then +** jump to instruction P2.  Otherwise, continue to the next instruction. +** +** The least significant byte of P1 may be either 0x00 or 0x01. If either +** operand is NULL (and thus if the result is unknown) then take the jump +** only if the least significant byte of P1 is 0x01. +** +** The second least significant byte of P1 must be an affinity character - +** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values +** according to the affinity before the comparison is made. If the byte is +** 0x00, then numeric affinity is used. +** +** Once any conversions have taken place, and neither value is NULL,  +** the values are compared. If both values are blobs, or both are text, +** then memcmp() is used to determine the results of the comparison. If +** both values are numeric, then a numeric comparison is used. If the +** two values are of different types, then they are inequal. +** +** If P2 is zero, do not jump.  Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not.  Push a +** NULL if either operand was NULL. +** +** If P3 is not NULL it is a pointer to a collating sequence (a CollSeq +** structure) that defines how to compare text. +*/ +/* Opcode: Ne P1 P2 P3 +** +** This works just like the Eq opcode except that the jump is taken if +** the operands from the stack are not equal.  See the Eq opcode for +** additional information. +*/ +/* Opcode: Lt P1 P2 P3 +** +** This works just like the Eq opcode except that the jump is taken if +** the 2nd element down on the stack is less than the top of the stack. +** See the Eq opcode for additional information. +*/ +/* Opcode: Le P1 P2 P3 +** +** This works just like the Eq opcode except that the jump is taken if +** the 2nd element down on the stack is less than or equal to the +** top of the stack.  See the Eq opcode for additional information. +*/ +/* Opcode: Gt P1 P2 P3 +** +** This works just like the Eq opcode except that the jump is taken if +** the 2nd element down on the stack is greater than the top of the stack. +** See the Eq opcode for additional information. +*/ +/* Opcode: Ge P1 P2 P3 +** +** This works just like the Eq opcode except that the jump is taken if +** the 2nd element down on the stack is greater than or equal to the +** top of the stack.  See the Eq opcode for additional information. +*/ +case OP_Eq:               /* same as TK_EQ */ +case OP_Ne:               /* same as TK_NE */ +case OP_Lt:               /* same as TK_LT */ +case OP_Le:               /* same as TK_LE */ +case OP_Gt:               /* same as TK_GT */ +case OP_Ge: {             /* same as TK_GE */ +  Mem *pNos; +  int flags; +  int res; +  char affinity; + +  pNos = &pTos[-1]; +  flags = pTos->flags|pNos->flags; + +  /* If either value is a NULL P2 is not zero, take the jump if the least +  ** significant byte of P1 is true. If P2 is zero, then push a NULL onto +  ** the stack. +  */ +  if( flags&MEM_Null ){ +    popStack(&pTos, 2); +    if( pOp->p2 ){ +      if( (pOp->p1&0xFF) ) pc = pOp->p2-1; +    }else{ +      pTos++; +      pTos->flags = MEM_Null; +    } +    break; +  } + +  affinity = (pOp->p1>>8)&0xFF; +  if( affinity ){ +    applyAffinity(pNos, affinity, db->enc); +    applyAffinity(pTos, affinity, db->enc); +  } + +  assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); +  res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); +  switch( pOp->opcode ){ +    case OP_Eq:    res = res==0;     break; +    case OP_Ne:    res = res!=0;     break; +    case OP_Lt:    res = res<0;      break; +    case OP_Le:    res = res<=0;     break; +    case OP_Gt:    res = res>0;      break; +    default:       res = res>=0;     break; +  } + +  popStack(&pTos, 2); +  if( pOp->p2 ){ +    if( res ){ +      pc = pOp->p2-1; +    } +  }else{ +    pTos++; +    pTos->flags = MEM_Int; +    pTos->i = res; +  } +  break; +} + +/* Opcode: And * * * +** +** Pop two values off the stack.  Take the logical AND of the +** two values and push the resulting boolean value back onto the +** stack.  +*/ +/* Opcode: Or * * * +** +** Pop two values off the stack.  Take the logical OR of the +** two values and push the resulting boolean value back onto the +** stack.  +*/ +case OP_And:              /* same as TK_AND */ +case OP_Or: {             /* same as TK_OR */ +  Mem *pNos = &pTos[-1]; +  int v1, v2;    /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ + +  assert( pNos>=p->aStack ); +  if( pTos->flags & MEM_Null ){ +    v1 = 2; +  }else{ +    Integerify(pTos); +    v1 = pTos->i==0; +  } +  if( pNos->flags & MEM_Null ){ +    v2 = 2; +  }else{ +    Integerify(pNos); +    v2 = pNos->i==0; +  } +  if( pOp->opcode==OP_And ){ +    static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; +    v1 = and_logic[v1*3+v2]; +  }else{ +    static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; +    v1 = or_logic[v1*3+v2]; +  } +  popStack(&pTos, 2); +  pTos++; +  if( v1==2 ){ +    pTos->flags = MEM_Null; +  }else{ +    pTos->i = v1==0; +    pTos->flags = MEM_Int; +  } +  break; +} + +/* Opcode: Negative * * * +** +** Treat the top of the stack as a numeric quantity.  Replace it +** with its additive inverse.  If the top of the stack is NULL +** its value is unchanged. +*/ +/* Opcode: AbsValue * * * +** +** Treat the top of the stack as a numeric quantity.  Replace it +** with its absolute value. If the top of the stack is NULL +** its value is unchanged. +*/ +case OP_Negative:              /* same as TK_UMINUS */ +case OP_AbsValue: { +  assert( pTos>=p->aStack ); +  if( pTos->flags & MEM_Real ){ +    Release(pTos); +    if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ +      pTos->r = -pTos->r; +    } +    pTos->flags = MEM_Real; +  }else if( pTos->flags & MEM_Int ){ +    Release(pTos); +    if( pOp->opcode==OP_Negative || pTos->i<0 ){ +      pTos->i = -pTos->i; +    } +    pTos->flags = MEM_Int; +  }else if( pTos->flags & MEM_Null ){ +    /* Do nothing */ +  }else{ +    Realify(pTos); +    if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ +      pTos->r = -pTos->r; +    } +    pTos->flags = MEM_Real; +  } +  break; +} + +/* Opcode: Not * * * +** +** Interpret the top of the stack as a boolean value.  Replace it +** with its complement.  If the top of the stack is NULL its value +** is unchanged. +*/ +case OP_Not: {                /* same as TK_NOT */ +  assert( pTos>=p->aStack ); +  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */ +  Integerify(pTos); +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos->i = !pTos->i; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: BitNot * * * +** +** Interpret the top of the stack as an value.  Replace it +** with its ones-complement.  If the top of the stack is NULL its +** value is unchanged. +*/ +case OP_BitNot: {             /* same as TK_BITNOT */ +  assert( pTos>=p->aStack ); +  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */ +  Integerify(pTos); +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos->i = ~pTos->i; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: Noop * * * +** +** Do nothing.  This instruction is often useful as a jump +** destination. +*/ +case OP_Noop: { +  break; +} + +/* Opcode: If P1 P2 * +** +** Pop a single boolean from the stack.  If the boolean popped is +** true, then jump to p2.  Otherwise continue to the next instruction. +** An integer is false if zero and true otherwise.  A string is +** false if it has zero length and true otherwise. +** +** If the value popped of the stack is NULL, then take the jump if P1 +** is true and fall through if P1 is false. +*/ +/* Opcode: IfNot P1 P2 * +** +** Pop a single boolean from the stack.  If the boolean popped is +** false, then jump to p2.  Otherwise continue to the next instruction. +** An integer is false if zero and true otherwise.  A string is +** false if it has zero length and true otherwise. +** +** If the value popped of the stack is NULL, then take the jump if P1 +** is true and fall through if P1 is false. +*/ +case OP_If: +case OP_IfNot: { +  int c; +  assert( pTos>=p->aStack ); +  if( pTos->flags & MEM_Null ){ +    c = pOp->p1; +  }else{ +    c = sqlite3VdbeIntValue(pTos); +    if( pOp->opcode==OP_IfNot ) c = !c; +  } +  Release(pTos); +  pTos--; +  if( c ) pc = pOp->p2-1; +  break; +} + +/* Opcode: IsNull P1 P2 * +** +** If any of the top abs(P1) values on the stack are NULL, then jump +** to P2.  Pop the stack P1 times if P1>0.   If P1<0 leave the stack +** unchanged. +*/ +case OP_IsNull: {            /* same as TK_ISNULL */ +  int i, cnt; +  Mem *pTerm; +  cnt = pOp->p1; +  if( cnt<0 ) cnt = -cnt; +  pTerm = &pTos[1-cnt]; +  assert( pTerm>=p->aStack ); +  for(i=0; i<cnt; i++, pTerm++){ +    if( pTerm->flags & MEM_Null ){ +      pc = pOp->p2-1; +      break; +    } +  } +  if( pOp->p1>0 ) popStack(&pTos, cnt); +  break; +} + +/* Opcode: NotNull P1 P2 * +** +** Jump to P2 if the top P1 values on the stack are all not NULL.  Pop the +** stack if P1 times if P1 is greater than zero.  If P1 is less than +** zero then leave the stack unchanged. +*/ +case OP_NotNull: {            /* same as TK_NOTNULL */ +  int i, cnt; +  cnt = pOp->p1; +  if( cnt<0 ) cnt = -cnt; +  assert( &pTos[1-cnt] >= p->aStack ); +  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){} +  if( i>=cnt ) pc = pOp->p2-1; +  if( pOp->p1>0 ) popStack(&pTos, cnt); +  break; +} + +/* Opcode: SetNumColumns P1 P2 * +** +** Before the OP_Column opcode can be executed on a cursor, this +** opcode must be called to set the number of fields in the table. +** +** This opcode sets the number of columns for cursor P1 to P2. +*/ +case OP_SetNumColumns: { +  assert( (pOp->p1)<p->nCursor ); +  assert( p->apCsr[pOp->p1]!=0 ); +  p->apCsr[pOp->p1]->nField = pOp->p2; +  break; +} + +/* Opcode: IdxColumn P1 * * +** +** P1 is a cursor opened on an index. Push the first field from the +** current index key onto the stack. +*/ +/* Opcode: Column P1 P2 * +** +** Interpret the data that cursor P1 points to as a structure built using +** the MakeRecord instruction.  (See the MakeRecord opcode for additional +** information about the format of the data.) Push onto the stack the value +** of the P2-th column contained in the data. +** +** If the KeyAsData opcode has previously executed on this cursor, then the +** field might be extracted from the key rather than the data. +** +** If P1 is negative, then the record is stored on the stack rather than in +** a table.  For P1==-1, the top of the stack is used.  For P1==-2, the +** next on the stack is used.  And so forth.  The value pushed is always +** just a pointer into the record which is stored further down on the +** stack.  The column value is not copied. The number of columns in the +** record is stored on the stack just above the record itself. +*/ +case OP_IdxColumn: +case OP_Column: { +  u32 payloadSize;   /* Number of bytes in the record */ +  int p1 = pOp->p1;  /* P1 value of the opcode */ +  int p2 = pOp->p2;  /* column number to retrieve */ +  Cursor *pC = 0;    /* The VDBE cursor */ +  char *zRec;        /* Pointer to complete record-data */ +  BtCursor *pCrsr;   /* The BTree cursor */ +  u32 *aType;        /* aType[i] holds the numeric type of the i-th column */ +  u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */ +  u32 nField;        /* number of fields in the record */ +  u32 szHdr;         /* Number of bytes in the record header */ +  int len;           /* The length of the serialized data for the column */ +  int offset = 0;    /* Offset into the data */ +  int idx;           /* Index into the header */ +  int i;             /* Loop counter */ +  char *zData;       /* Part of the record being decoded */ +  Mem sMem;          /* For storing the record being decoded */ + +  sMem.flags = 0; +  assert( p1<p->nCursor ); +  pTos++; +  pTos->flags = MEM_Null; + +  /* This block sets the variable payloadSize to be the total number of +  ** bytes in the record. +  ** +  ** zRec is set to be the complete text of the record if it is available. +  ** The complete record text is always available for pseudo-tables and +  ** when we are decoded a record from the stack.  If the record is stored +  ** in a cursor, the complete record text might be available in the  +  ** pC->aRow cache.  Or it might not be.  If the data is unavailable, +  ** zRec is set to NULL. +  ** +  ** We also compute the number of columns in the record.  For cursors, +  ** the number of columns is stored in the Cursor.nField element.  For +  ** records on the stack, the next entry down on the stack is an integer +  ** which is the number of records. +  */ +  assert( p1<0 || p->apCsr[p1]!=0 ); +  if( p1<0 ){ +    /* Take the record off of the stack */ +    Mem *pRec = &pTos[p1]; +    Mem *pCnt = &pRec[-1]; +    assert( pRec>=p->aStack ); +    assert( pRec->flags & MEM_Blob ); +    payloadSize = pRec->n; +    zRec = pRec->z; +    assert( pCnt>=p->aStack ); +    assert( pCnt->flags & MEM_Int ); +    nField = pCnt->i; +    pCrsr = 0; +  }else if( (pC = p->apCsr[p1])->pCursor!=0 ){ +    /* The record is stored in a B-Tree */ +    sqlite3VdbeCursorMoveto(pC); +    zRec = 0; +    pCrsr = pC->pCursor; +    if( pC->nullRow ){ +      payloadSize = 0; +    }else if( pC->cacheValid ){ +      payloadSize = pC->payloadSize; +      zRec = pC->aRow; +    }else if( pC->keyAsData ){ +      i64 payloadSize64; +      sqlite3BtreeKeySize(pCrsr, &payloadSize64); +      payloadSize = payloadSize64; +    }else{ +      sqlite3BtreeDataSize(pCrsr, &payloadSize); +    } +    nField = pC->nField; +  }else if( pC->pseudoTable ){ +    /* The record is the sole entry of a pseudo-table */ +    payloadSize = pC->nData; +    zRec = pC->pData; +    pC->cacheValid = 0; +    assert( payloadSize==0 || zRec!=0 ); +    nField = pC->nField; +    pCrsr = 0; +  }else{ +    zRec = 0; +    payloadSize = 0; +    pCrsr = 0; +    nField = 0; +  } + +  /* If payloadSize is 0, then just push a NULL onto the stack. */ +  if( payloadSize==0 ){ +    pTos->flags = MEM_Null; +    break; +  } + +  assert( p2<nField ); + +  /* Read and parse the table header.  Store the results of the parse +  ** into the record header cache fields of the cursor. +  */ +  if( pC && pC->cacheValid ){ +    aType = pC->aType; +    aOffset = pC->aOffset; +  }else{ +    int avail;    /* Number of bytes of available data */ +    if( pC && pC->aType ){ +      aType = pC->aType; +    }else{ +      aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); +    } +    aOffset = &aType[nField]; +    if( aType==0 ){ +      goto no_mem; +    } + +    /* Figure out how many bytes are in the header */ +    if( zRec ){ +      zData = zRec; +    }else{ +      if( pC->keyAsData ){ +        zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); +      }else{ +        zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); +      } +      /* If KeyFetch()/DataFetch() managed to get the entire payload, +      ** save the payload in the pC->aRow cache.  That will save us from +      ** having to make additional calls to fetch the content portion of +      ** the record. +      */ +      if( avail>=payloadSize ){ +        zRec = pC->aRow = zData; +      }else{ +        pC->aRow = 0; +      } +    } +    idx = sqlite3GetVarint32(zData, &szHdr); + + +    /* The KeyFetch() or DataFetch() above are fast and will get the entire +    ** record header in most cases.  But they will fail to get the complete +    ** record header if the record header does not fit on a single page +    ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to +    ** acquire the complete header text. +    */ +    if( !zRec && avail<szHdr ){ +      rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem); +      if( rc!=SQLITE_OK ){ +        goto abort_due_to_error; +      } +      zData = sMem.z; +    } + +    /* Scan the header and use it to fill in the aType[] and aOffset[] +    ** arrays.  aType[i] will contain the type integer for the i-th +    ** column and aOffset[i] will contain the offset from the beginning +    ** of the record to the start of the data for the i-th column +    */ +    offset = szHdr; +    i = 0; +    while( idx<szHdr && i<nField && offset<=payloadSize ){ +      aOffset[i] = offset; +      idx += sqlite3GetVarint32(&zData[idx], &aType[i]); +      offset += sqlite3VdbeSerialTypeLen(aType[i]); +      i++; +    } +    Release(&sMem); +    sMem.flags = MEM_Null; + +    /* The header should end at the start of data and the data should +    ** end at last byte of the record. If this is not the case then +    ** we are dealing with a malformed record. +    */ +    if( idx!=szHdr || offset!=payloadSize ){ +      sqliteFree(aType); +      if( pC ) pC->aType = 0; +      rc = SQLITE_CORRUPT; +      break; +    } + +    /* Remember all aType and aColumn information if we have a cursor +    ** to remember it in. */ +    if( pC ){ +      pC->payloadSize = payloadSize; +      pC->aType = aType; +      pC->aOffset = aOffset; +      pC->cacheValid = 1; +    } +  } + +  /* Get the column information. +  */ +  if( rc!=SQLITE_OK ){ +    goto abort_due_to_error; +  } +  if( zRec ){ +    zData = &zRec[aOffset[p2]]; +  }else{ +    len = sqlite3VdbeSerialTypeLen(aType[p2]); +    sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem); +    zData = sMem.z; +  } +  sqlite3VdbeSerialGet(zData, aType[p2], pTos); +  pTos->enc = db->enc; + +  /* If we dynamically allocated space to hold the data (in the +  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that +  ** dynamically allocated space over to the pTos structure rather. +  ** This prevents a memory copy. +  */ +  if( (sMem.flags & MEM_Dyn)!=0 ){ +    assert( pTos->flags & MEM_Ephem ); +    assert( pTos->flags & (MEM_Str|MEM_Blob) ); +    assert( pTos->z==sMem.z ); +    assert( sMem.flags & MEM_Term ); +    pTos->flags &= ~MEM_Ephem; +    pTos->flags |= MEM_Dyn|MEM_Term; +  } + +  /* pTos->z might be pointing to sMem.zShort[].  Fix that so that we +  ** can abandon sMem */ +  rc = sqlite3VdbeMemMakeWriteable(pTos); + +  /* Release the aType[] memory if we are not dealing with cursor */ +  if( !pC ){ +    sqliteFree(aType); +  } +  break; +} + +/* Opcode MakeRecord P1 P2 P3 +** +** Convert the top abs(P1) entries of the stack into a single entry +** suitable for use as a data record in a database table or as a key +** in an index.  The details of the format are irrelavant as long as +** the OP_Column opcode can decode the record later and as long as the +** sqlite3VdbeRecordCompare function will correctly compare two encoded +** records.  Refer to source code comments for the details of the record +** format. +** +** The original stack entries are popped from the stack if P1>0 but +** remain on the stack if P1<0. +** +** The P2 argument is divided into two 16-bit words before it is processed. +** If the hi-word is non-zero, then an extra integer is read from the stack +** and appended to the record as a varint.  If the low-word of P2 is not +** zero and one or more of the entries are NULL, then jump to the value of +** the low-word of P2.  This feature can be used to skip a uniqueness test +** on indices. +** +** P3 may be a string that is P1 characters long.  The nth character of the +** string indicates the column affinity that should be used for the nth +** field of the index key (i.e. the first character of P3 corresponds to the +** lowest element on the stack). +** +**  Character      Column affinity +**  ------------------------------ +**  'n'            NUMERIC +**  'i'            INTEGER +**  't'            TEXT +**  'o'            NONE +** +** If P3 is NULL then all index fields have the affinity NONE. +*/ +case OP_MakeRecord: { +  /* Assuming the record contains N fields, the record format looks +  ** like this: +  ** +  ** ------------------------------------------------------------------------ +  ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |  +  ** ------------------------------------------------------------------------ +  ** +  ** Data(0) is taken from the lowest element of the stack and data(N-1) is +  ** the top of the stack. +  ** +  ** Each type field is a varint representing the serial type of the  +  ** corresponding data element (see sqlite3VdbeSerialType()). The +  ** hdr-size field is also a varint which is the offset from the beginning +  ** of the record to data0. +  */ +  unsigned char *zNewRecord; +  unsigned char *zCsr; +  Mem *pRec; +  Mem *pRowid = 0; +  int nData = 0;         /* Number of bytes of data space */ +  int nHdr = 0;          /* Number of bytes of header space */ +  int nByte = 0;         /* Space required for this record */ +  u32 serial_type;       /* Type field */ +  int containsNull = 0;  /* True if any of the data fields are NULL */ +  char zTemp[NBFS];      /* Space to hold small records */ +  Mem *pData0; + +  int leaveOnStack;      /* If true, leave the entries on the stack */ +  int nField;            /* Number of fields in the record */ +  int jumpIfNull;        /* Jump here if non-zero and any entries are NULL. */ +  int addRowid;          /* True to append a rowid column at the end */ +  char *zAffinity;       /* The affinity string for the record */ + +  leaveOnStack = ((pOp->p1<0)?1:0); +  nField = pOp->p1 * (leaveOnStack?-1:1); +  jumpIfNull = (pOp->p2 & 0x00FFFFFF); +  addRowid = ((pOp->p2>>24) & 0x0000FFFF)?1:0; +  zAffinity = pOp->p3; + +  pData0 = &pTos[1-nField]; +  assert( pData0>=p->aStack ); +  containsNull = 0; + +  /* Loop through the elements that will make up the record to figure +  ** out how much space is required for the new record. +  */ +  for(pRec=pData0; pRec<=pTos; pRec++){ +    if( zAffinity ){ +      applyAffinity(pRec, zAffinity[pRec-pData0], db->enc); +    } +    if( pRec->flags&MEM_Null ){ +      containsNull = 1; +    } +    serial_type = sqlite3VdbeSerialType(pRec); +    nData += sqlite3VdbeSerialTypeLen(serial_type); +    nHdr += sqlite3VarintLen(serial_type); +  } + +  /* If we have to append a varint rowid to this record, set 'rowid' +  ** to the value of the rowid and increase nByte by the amount of space +  ** required to store it and the 0x00 seperator byte. +  */ +  if( addRowid ){ +    pRowid = &pTos[0-nField]; +    assert( pRowid>=p->aStack ); +    Integerify(pRowid); +    serial_type = sqlite3VdbeSerialType(pRowid); +    nData += sqlite3VdbeSerialTypeLen(serial_type); +    nHdr += sqlite3VarintLen(serial_type); +  } + +  /* Add the initial header varint and total the size */ +  nHdr += sqlite3VarintLen(nHdr); +  nByte = nHdr+nData; + +  /* Allocate space for the new record. */ +  if( nByte>sizeof(zTemp) ){ +    zNewRecord = sqliteMallocRaw(nByte); +    if( !zNewRecord ){ +      goto no_mem; +    } +  }else{ +    zNewRecord = zTemp; +  } + +  /* Write the record */ +  zCsr = zNewRecord; +  zCsr += sqlite3PutVarint(zCsr, nHdr); +  for(pRec=pData0; pRec<=pTos; pRec++){ +    serial_type = sqlite3VdbeSerialType(pRec); +    zCsr += sqlite3PutVarint(zCsr, serial_type);      /* serial type */ +  } +  if( addRowid ){ +    zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid)); +  } +  for(pRec=pData0; pRec<=pTos; pRec++){ +    zCsr += sqlite3VdbeSerialPut(zCsr, pRec);  /* serial data */ +  } +  if( addRowid ){ +    zCsr += sqlite3VdbeSerialPut(zCsr, pRowid); +  } + +  /* If zCsr has not been advanced exactly nByte bytes, then one +  ** of the sqlite3PutVarint() or sqlite3VdbeSerialPut() calls above +  ** failed. This indicates a corrupted memory cell or code bug. +  */ +  if( zCsr!=(zNewRecord+nByte) ){ +    rc = SQLITE_INTERNAL; +    goto abort_due_to_error; +  } + +  /* Pop entries off the stack if required. Push the new record on. */ +  if( !leaveOnStack ){ +    popStack(&pTos, nField+addRowid); +  } +  pTos++; +  pTos->n = nByte; +  if( nByte<=sizeof(zTemp) ){ +    assert( zNewRecord==(unsigned char *)zTemp ); +    pTos->z = pTos->zShort; +    memcpy(pTos->zShort, zTemp, nByte); +    pTos->flags = MEM_Blob | MEM_Short; +  }else{ +    assert( zNewRecord!=(unsigned char *)zTemp ); +    pTos->z = zNewRecord; +    pTos->flags = MEM_Blob | MEM_Dyn; +    pTos->xDel = 0; +  } + +  /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */ +  if( jumpIfNull && containsNull ){ +    pc = jumpIfNull - 1; +  } +  break; +} + +/* Opcode: Statement P1 * * +** +** Begin an individual statement transaction which is part of a larger +** BEGIN..COMMIT transaction.  This is needed so that the statement +** can be rolled back after an error without having to roll back the +** entire transaction.  The statement transaction will automatically +** commit when the VDBE halts. +** +** The statement is begun on the database file with index P1.  The main +** database file has an index of 0 and the file used for temporary tables +** has an index of 1. +*/ +case OP_Statement: { +  int i = pOp->p1; +  Btree *pBt; +  if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){ +    assert( sqlite3BtreeIsInTrans(pBt) ); +    if( !sqlite3BtreeIsInStmt(pBt) ){ +      rc = sqlite3BtreeBeginStmt(pBt); +    } +  } +  break; +} + +/* Opcode: AutoCommit P1 P2 * +** +** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll +** back any currently active btree transactions. If there are any active +** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. +** +** This instruction causes the VM to halt. +*/ +case OP_AutoCommit: { +  u8 i = pOp->p1; +  u8 rollback = pOp->p2; + +  assert( i==1 || i==0 ); +  assert( i==1 || rollback==0 ); + +  assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */ + +  if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ +    /* If this instruction implements a COMMIT or ROLLBACK, other VMs are +    ** still running, and a transaction is active, return an error indicating +    ** that the other VMs must complete first.  +    */ +    sqlite3SetString(&p->zErrMsg, "cannot ", rollback?"rollback":"commit",  +        " transaction - SQL statements in progress", 0); +    rc = SQLITE_ERROR; +  }else if( i!=db->autoCommit ){ +    db->autoCommit = i; +    if( pOp->p2 ){ +      assert( i==1 ); +      sqlite3RollbackAll(db); +    }else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ +      p->pTos = pTos; +      p->pc = pc; +      db->autoCommit = 1-i; +      p->rc = SQLITE_BUSY; +      return SQLITE_BUSY; +    } +    return SQLITE_DONE; +  }else{ +    sqlite3SetString(&p->zErrMsg, +        (!i)?"cannot start a transaction within a transaction":( +        (rollback)?"cannot rollback - no transaction is active": +                   "cannot commit - no transaction is active"), 0); +          +    rc = SQLITE_ERROR; +  } +  break; +} + +/* Opcode: Transaction P1 P2 * +** +** Begin a transaction.  The transaction ends when a Commit or Rollback +** opcode is encountered.  Depending on the ON CONFLICT setting, the +** transaction might also be rolled back if an error is encountered. +** +** P1 is the index of the database file on which the transaction is +** started.  Index 0 is the main database file and index 1 is the +** file used for temporary tables. +** +** If P2 is non-zero, then a write-transaction is started.  A RESERVED lock is +** obtained on the database file when a write-transaction is started.  No +** other process can start another write transaction while this transaction is +** underway.  Starting a write transaction also creates a rollback journal. A +** write transaction must be started before any changes can be made to the +** database.  If P2 is 2 or greater then an EXCLUSIVE lock is also obtained +** on the file. +** +** If P2 is zero, then a read-lock is obtained on the database file. +*/ +case OP_Transaction: { +  int i = pOp->p1; +  Btree *pBt; + +  assert( i>=0 && i<db->nDb ); +  pBt = db->aDb[i].pBt; + +  if( pBt ){ +    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); +    if( rc==SQLITE_BUSY ){ +      p->pc = pc; +      p->rc = SQLITE_BUSY; +      p->pTos = pTos; +      return SQLITE_BUSY; +    } +    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ +      goto abort_due_to_error; +    } +  } +  break; +} + +/* Opcode: ReadCookie P1 P2 * +** +** Read cookie number P2 from database P1 and push it onto the stack. +** P2==0 is the schema version.  P2==1 is the database format. +** P2==2 is the recommended pager cache size, and so forth.  P1==0 is +** the main database file and P1==1 is the database file used to store +** temporary tables. +** +** There must be a read-lock on the database (either a transaction +** must be started or there must be an open cursor) before +** executing this instruction. +*/ +case OP_ReadCookie: { +  int iMeta; +  assert( pOp->p2<SQLITE_N_BTREE_META ); +  assert( pOp->p1>=0 && pOp->p1<db->nDb ); +  assert( db->aDb[pOp->p1].pBt!=0 ); +  /* The indexing of meta values at the schema layer is off by one from +  ** the indexing in the btree layer.  The btree considers meta[0] to +  ** be the number of free pages in the database (a read-only value) +  ** and meta[1] to be the schema cookie.  The schema layer considers +  ** meta[1] to be the schema cookie.  So we have to shift the index +  ** by one in the following statement. +  */ +  rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, 1 + pOp->p2, (u32 *)&iMeta); +  pTos++; +  pTos->i = iMeta; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: SetCookie P1 P2 * +** +** Write the top of the stack into cookie number P2 of database P1. +** P2==0 is the schema version.  P2==1 is the database format. +** P2==2 is the recommended pager cache size, and so forth.  P1==0 is +** the main database file and P1==1 is the database file used to store +** temporary tables. +** +** A transaction must be started before executing this opcode. +*/ +case OP_SetCookie: { +  Db *pDb; +  assert( pOp->p2<SQLITE_N_BTREE_META ); +  assert( pOp->p1>=0 && pOp->p1<db->nDb ); +  pDb = &db->aDb[pOp->p1]; +  assert( pDb->pBt!=0 ); +  assert( pTos>=p->aStack ); +  Integerify(pTos); +  /* See note about index shifting on OP_ReadCookie */ +  rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->i); +  if( pOp->p2==0 ){ +    /* When the schema cookie changes, record the new cookie internally */ +    pDb->schema_cookie = pTos->i; +    db->flags |= SQLITE_InternChanges; +  } +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos--; +  break; +} + +/* Opcode: VerifyCookie P1 P2 * +** +** Check the value of global database parameter number 0 (the +** schema version) and make sure it is equal to P2.   +** P1 is the database number which is 0 for the main database file +** and 1 for the file holding temporary tables and some higher number +** for auxiliary databases. +** +** The cookie changes its value whenever the database schema changes. +** This operation is used to detect when that the cookie has changed +** and that the current process needs to reread the schema. +** +** Either a transaction needs to have been started or an OP_Open needs +** to be executed (to establish a read lock) before this opcode is +** invoked. +*/ +case OP_VerifyCookie: { +  int iMeta; +  Btree *pBt; +  assert( pOp->p1>=0 && pOp->p1<db->nDb ); +  pBt = db->aDb[pOp->p1].pBt; +  if( pBt ){ +    rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); +  }else{ +    rc = SQLITE_OK; +    iMeta = 0; +  } +  if( rc==SQLITE_OK && iMeta!=pOp->p2 ){ +    sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0); +    rc = SQLITE_SCHEMA; +  } +  break; +} + +/* Opcode: OpenRead P1 P2 P3 +** +** Open a read-only cursor for the database table whose root page is +** P2 in a database file.  The database file is determined by an  +** integer from the top of the stack.  0 means the main database and +** 1 means the database used for temporary tables.  Give the new  +** cursor an identifier of P1.  The P1 values need not be contiguous +** but all P1 values should be small integers.  It is an error for +** P1 to be negative. +** +** If P2==0 then take the root page number from the next of the stack. +** +** There will be a read lock on the database whenever there is an +** open cursor.  If the database was unlocked prior to this instruction +** then a read lock is acquired as part of this instruction.  A read +** lock allows other processes to read the database but prohibits +** any other process from modifying the database.  The read lock is +** released when all cursors are closed.  If this instruction attempts +** to get a read lock but fails, the script terminates with an +** SQLITE_BUSY error code. +** +** The P3 value is a pointer to a KeyInfo structure that defines the +** content and collating sequence of indices.  P3 is NULL for cursors +** that are not pointing to indices. +** +** See also OpenWrite. +*/ +/* Opcode: OpenWrite P1 P2 P3 +** +** Open a read/write cursor named P1 on the table or index whose root +** page is P2.  If P2==0 then take the root page number from the stack. +** +** The P3 value is a pointer to a KeyInfo structure that defines the +** content and collating sequence of indices.  P3 is NULL for cursors +** that are not pointing to indices. +** +** This instruction works just like OpenRead except that it opens the cursor +** in read/write mode.  For a given table, there can be one or more read-only +** cursors or a single read/write cursor but not both. +** +** See also OpenRead. +*/ +case OP_OpenRead: +case OP_OpenWrite: { +  int i = pOp->p1; +  int p2 = pOp->p2; +  int wrFlag; +  Btree *pX; +  int iDb; +  Cursor *pCur; +   +  assert( pTos>=p->aStack ); +  Integerify(pTos); +  iDb = pTos->i; +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos--; +  assert( iDb>=0 && iDb<db->nDb ); +  pX = db->aDb[iDb].pBt; +  assert( pX!=0 ); +  wrFlag = pOp->opcode==OP_OpenWrite; +  if( p2<=0 ){ +    assert( pTos>=p->aStack ); +    Integerify(pTos); +    p2 = pTos->i; +    assert( (pTos->flags & MEM_Dyn)==0 ); +    pTos--; +    if( p2<2 ){ +      sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); +      rc = SQLITE_INTERNAL; +      break; +    } +  } +  assert( i>=0 ); +  pCur = allocateCursor(p, i); +  if( pCur==0 ) goto no_mem; +  pCur->nullRow = 1; +  if( pX==0 ) break; +  /* We always provide a key comparison function.  If the table being +  ** opened is of type INTKEY, the comparision function will be ignored. */ +  rc = sqlite3BtreeCursor(pX, p2, wrFlag, +           sqlite3VdbeRecordCompare, pOp->p3, +           &pCur->pCursor); +  pCur->pKeyInfo = (KeyInfo*)pOp->p3; +  if( pCur->pKeyInfo ){ +    pCur->pIncrKey = &pCur->pKeyInfo->incrKey; +    pCur->pKeyInfo->enc = p->db->enc; +  }else{ +    pCur->pIncrKey = &pCur->bogusIncrKey; +  } +  switch( rc ){ +    case SQLITE_BUSY: { +      p->pc = pc; +      p->rc = SQLITE_BUSY; +      p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */ +      return SQLITE_BUSY; +    } +    case SQLITE_OK: { +      int flags = sqlite3BtreeFlags(pCur->pCursor); +      pCur->intKey = (flags & BTREE_INTKEY)!=0; +      pCur->zeroData = (flags & BTREE_ZERODATA)!=0; +      break; +    } +    case SQLITE_EMPTY: { +      rc = SQLITE_OK; +      break; +    } +    default: { +      goto abort_due_to_error; +    } +  } +  break; +} + +/* Opcode: OpenTemp P1 * P3 +** +** Open a new cursor to a transient table. +** The transient cursor is always opened read/write even if  +** the main database is read-only.  The transient table is deleted +** automatically when the cursor is closed. +** +** The cursor points to a BTree table if P3==0 and to a BTree index +** if P3 is not 0.  If P3 is not NULL, it points to a KeyInfo structure +** that defines the format of keys in the index. +** +** This opcode is used for tables that exist for the duration of a single +** SQL statement only.  Tables created using CREATE TEMPORARY TABLE +** are opened using OP_OpenRead or OP_OpenWrite.  "Temporary" in the +** context of this opcode means for the duration of a single SQL statement +** whereas "Temporary" in the context of CREATE TABLE means for the duration +** of the connection to the database.  Same word; different meanings. +*/ +case OP_OpenTemp: { +  int i = pOp->p1; +  Cursor *pCx; +  assert( i>=0 ); +  pCx = allocateCursor(p, i); +  if( pCx==0 ) goto no_mem; +  pCx->nullRow = 1; +  rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt); +  if( rc==SQLITE_OK ){ +    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); +  } +  if( rc==SQLITE_OK ){ +    /* If a transient index is required, create it by calling +    ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before +    ** opening it. If a transient table is required, just use the +    ** automatically created table with root-page 1 (an INTKEY table). +    */ +    if( pOp->p3 ){ +      int pgno; +      assert( pOp->p3type==P3_KEYINFO ); +      rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA);  +      if( rc==SQLITE_OK ){ +        assert( pgno==MASTER_ROOT+1 ); +        rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare, +            pOp->p3, &pCx->pCursor); +        pCx->pKeyInfo = (KeyInfo*)pOp->p3; +        pCx->pKeyInfo->enc = p->db->enc; +        pCx->pIncrKey = &pCx->pKeyInfo->incrKey; +      } +    }else{ +      rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); +      pCx->intKey = 1; +      pCx->pIncrKey = &pCx->bogusIncrKey; +    } +  } +  break; +} + +/* Opcode: OpenPseudo P1 * * +** +** Open a new cursor that points to a fake table that contains a single +** row of data.  Any attempt to write a second row of data causes the +** first row to be deleted.  All data is deleted when the cursor is +** closed. +** +** A pseudo-table created by this opcode is useful for holding the +** NEW or OLD tables in a trigger. +*/ +case OP_OpenPseudo: { +  int i = pOp->p1; +  Cursor *pCx; +  assert( i>=0 ); +  pCx = allocateCursor(p, i); +  if( pCx==0 ) goto no_mem; +  pCx->nullRow = 1; +  pCx->pseudoTable = 1; +  pCx->pIncrKey = &pCx->bogusIncrKey; +  break; +} + +/* Opcode: Close P1 * * +** +** Close a cursor previously opened as P1.  If P1 is not +** currently open, this instruction is a no-op. +*/ +case OP_Close: { +  int i = pOp->p1; +  if( i>=0 && i<p->nCursor ){ +    sqlite3VdbeFreeCursor(p->apCsr[i]); +    p->apCsr[i] = 0; +  } +  break; +} + +/* Opcode: MoveGe P1 P2 * +** +** Pop the top of the stack and use its value as a key.  Reposition +** cursor P1 so that it points to the smallest entry that is greater +** than or equal to the key that was popped ffrom the stack. +** If there are no records greater than or equal to the key and P2  +** is not zero, then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe +*/ +/* Opcode: MoveGt P1 P2 * +** +** Pop the top of the stack and use its value as a key.  Reposition +** cursor P1 so that it points to the smallest entry that is greater +** than the key from the stack. +** If there are no records greater than the key and P2 is not zero, +** then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe +*/ +/* Opcode: MoveLt P1 P2 * +** +** Pop the top of the stack and use its value as a key.  Reposition +** cursor P1 so that it points to the largest entry that is less +** than the key from the stack. +** If there are no records less than the key and P2 is not zero, +** then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe +*/ +/* Opcode: MoveLe P1 P2 * +** +** Pop the top of the stack and use its value as a key.  Reposition +** cursor P1 so that it points to the largest entry that is less than +** or equal to the key that was popped from the stack. +** If there are no records less than or eqal to the key and P2 is not zero, +** then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt +*/ +case OP_MoveLt: +case OP_MoveLe: +case OP_MoveGe: +case OP_MoveGt: { +  int i = pOp->p1; +  Cursor *pC; + +  assert( pTos>=p->aStack ); +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  if( pC->pCursor!=0 ){ +    int res, oc; +    oc = pOp->opcode; +    pC->nullRow = 0; +    *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe; +    if( pC->intKey ){ +      i64 iKey; +      assert( !pOp->p3 ); +      Integerify(pTos); +      iKey = intToKey(pTos->i); +      if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){ +        pC->movetoTarget = iKey; +        pC->deferredMoveto = 1; +        assert( (pTos->flags & MEM_Dyn)==0 ); +        pTos--; +        break; +      } +      sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); +      pC->lastRecno = pTos->i; +      pC->recnoIsValid = res==0; +    }else{ +      Stringify(pTos, db->enc); +      sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); +      pC->recnoIsValid = 0; +    } +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +    *pC->pIncrKey = 0; +    sqlite3_search_count++; +    if( oc==OP_MoveGe || oc==OP_MoveGt ){ +      if( res<0 ){ +        sqlite3BtreeNext(pC->pCursor, &res); +        pC->recnoIsValid = 0; +      }else{ +        res = 0; +      } +    }else{ +      assert( oc==OP_MoveLt || oc==OP_MoveLe ); +      if( res>=0 ){ +        sqlite3BtreePrevious(pC->pCursor, &res); +        pC->recnoIsValid = 0; +      }else{ +        /* res might be negative because the table is empty.  Check to +        ** see if this is the case. +        */ +        res = sqlite3BtreeEof(pC->pCursor); +      } +    } +    if( res ){ +      if( pOp->p2>0 ){ +        pc = pOp->p2 - 1; +      }else{ +        pC->nullRow = 1; +      } +    } +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: Distinct P1 P2 * +** +** Use the top of the stack as a string key.  If a record with that key does +** not exist in the table of cursor P1, then jump to P2.  If the record +** does already exist, then fall thru.  The cursor is left pointing +** at the record if it exists. The key is not popped from the stack. +** +** This operation is similar to NotFound except that this operation +** does not pop the key from the stack. +** +** See also: Found, NotFound, MoveTo, IsUnique, NotExists +*/ +/* Opcode: Found P1 P2 * +** +** Use the top of the stack as a string key.  If a record with that key +** does exist in table of P1, then jump to P2.  If the record +** does not exist, then fall thru.  The cursor is left pointing +** to the record if it exists.  The key is popped from the stack. +** +** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists +*/ +/* Opcode: NotFound P1 P2 * +** +** Use the top of the stack as a string key.  If a record with that key +** does not exist in table of P1, then jump to P2.  If the record +** does exist, then fall thru.  The cursor is left pointing to the +** record if it exists.  The key is popped from the stack. +** +** The difference between this operation and Distinct is that +** Distinct does not pop the key from the stack. +** +** See also: Distinct, Found, MoveTo, NotExists, IsUnique +*/ +case OP_Distinct: +case OP_NotFound: +case OP_Found: { +  int i = pOp->p1; +  int alreadyExists = 0; +  Cursor *pC; +  assert( pTos>=p->aStack ); +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  if( (pC = p->apCsr[i])->pCursor!=0 ){ +    int res, rx; +    assert( pC->intKey==0 ); +    Stringify(pTos, db->enc); +    rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); +    alreadyExists = rx==SQLITE_OK && res==0; +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +  } +  if( pOp->opcode==OP_Found ){ +    if( alreadyExists ) pc = pOp->p2 - 1; +  }else{ +    if( !alreadyExists ) pc = pOp->p2 - 1; +  } +  if( pOp->opcode!=OP_Distinct ){ +    Release(pTos); +    pTos--; +  } +  break; +} + +/* Opcode: IsUnique P1 P2 * +** +** The top of the stack is an integer record number.  Call this +** record number R.  The next on the stack is an index key created +** using MakeIdxKey.  Call it K.  This instruction pops R from the +** stack but it leaves K unchanged. +** +** P1 is an index.  So it has no data and its key consists of a +** record generated by OP_MakeIdxKey.  This key contains one or more +** fields followed by a ROWID field. +**  +** This instruction asks if there is an entry in P1 where the +** fields matches K but the rowid is different from R. +** If there is no such entry, then there is an immediate +** jump to P2.  If any entry does exist where the index string +** matches K but the record number is not R, then the record +** number for that entry is pushed onto the stack and control +** falls through to the next instruction. +** +** See also: Distinct, NotFound, NotExists, Found +*/ +case OP_IsUnique: { +  int i = pOp->p1; +  Mem *pNos = &pTos[-1]; +  Cursor *pCx; +  BtCursor *pCrsr; +  i64 R; + +  /* Pop the value R off the top of the stack +  */ +  assert( pNos>=p->aStack ); +  Integerify(pTos); +  R = pTos->i; +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos--; +  assert( i>=0 && i<=p->nCursor ); +  pCx = p->apCsr[i]; +  assert( pCx!=0 ); +  pCrsr = pCx->pCursor; +  if( pCrsr!=0 ){ +    int res, rc; +    i64 v;         /* The record number on the P1 entry that matches K */ +    char *zKey;    /* The value of K */ +    int nKey;      /* Number of bytes in K */ +    int len;       /* Number of bytes in K without the rowid at the end */ +    int szRowid;   /* Size of the rowid column at the end of zKey */ + +    /* Make sure K is a string and make zKey point to K +    */ +    Stringify(pNos, db->enc); +    zKey = pNos->z; +    nKey = pNos->n; + +    szRowid = sqlite3VdbeIdxRowidLen(nKey, zKey); +    len = nKey-szRowid; + +    /* Search for an entry in P1 where all but the last four bytes match K. +    ** If there is no such entry, jump immediately to P2. +    */ +    assert( pCx->deferredMoveto==0 ); +    pCx->cacheValid = 0; +    rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); +    if( rc!=SQLITE_OK ) goto abort_due_to_error; +    if( res<0 ){ +      rc = sqlite3BtreeNext(pCrsr, &res); +      if( res ){ +        pc = pOp->p2 - 1; +        break; +      } +    } +    rc = sqlite3VdbeIdxKeyCompare(pCx, len, zKey, &res);  +    if( rc!=SQLITE_OK ) goto abort_due_to_error; +    if( res>0 ){ +      pc = pOp->p2 - 1; +      break; +    } + +    /* At this point, pCrsr is pointing to an entry in P1 where all but +    ** the final entry (the rowid) matches K.  Check to see if the +    ** final rowid column is different from R.  If it equals R then jump +    ** immediately to P2. +    */ +    rc = sqlite3VdbeIdxRowid(pCrsr, &v); +    if( rc!=SQLITE_OK ){ +      goto abort_due_to_error; +    } +    if( v==R ){ +      pc = pOp->p2 - 1; +      break; +    } + +    /* The final varint of the key is different from R.  Push it onto +    ** the stack.  (The record number of an entry that violates a UNIQUE +    ** constraint.) +    */ +    pTos++; +    pTos->i = v; +    pTos->flags = MEM_Int; +  } +  break; +} + +/* Opcode: NotExists P1 P2 * +** +** Use the top of the stack as a integer key.  If a record with that key +** does not exist in table of P1, then jump to P2.  If the record +** does exist, then fall thru.  The cursor is left pointing to the +** record if it exists.  The integer key is popped from the stack. +** +** The difference between this operation and NotFound is that this +** operation assumes the key is an integer and NotFound assumes it +** is a string. +** +** See also: Distinct, Found, MoveTo, NotFound, IsUnique +*/ +case OP_NotExists: { +  int i = pOp->p1; +  Cursor *pC; +  BtCursor *pCrsr; +  assert( pTos>=p->aStack ); +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    int res, rx; +    u64 iKey; +    assert( pTos->flags & MEM_Int ); +    assert( p->apCsr[i]->intKey ); +    iKey = intToKey(pTos->i); +    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); +    pC->lastRecno = pTos->i; +    pC->recnoIsValid = res==0; +    pC->nullRow = 0; +    pC->cacheValid = 0; +    if( rx!=SQLITE_OK || res!=0 ){ +      pc = pOp->p2 - 1; +      pC->recnoIsValid = 0; +    } +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: NewRecno P1 * * +** +** Get a new integer record number used as the key to a table. +** The record number is not previously used as a key in the database +** table that cursor P1 points to.  The new record number is pushed  +** onto the stack. +*/ +case OP_NewRecno: { +  int i = pOp->p1; +  i64 v = 0; +  Cursor *pC; +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  if( (pC = p->apCsr[i])->pCursor==0 ){ +    /* The zero initialization above is all that is needed */ +  }else{ +    /* The next rowid or record number (different terms for the same +    ** thing) is obtained in a two-step algorithm. +    ** +    ** First we attempt to find the largest existing rowid and add one +    ** to that.  But if the largest existing rowid is already the maximum +    ** positive integer, we have to fall through to the second +    ** probabilistic algorithm +    ** +    ** The second algorithm is to select a rowid at random and see if +    ** it already exists in the table.  If it does not exist, we have +    ** succeeded.  If the random rowid does exist, we select a new one +    ** and try again, up to 1000 times. +    ** +    ** For a table with less than 2 billion entries, the probability +    ** of not finding a unused rowid is about 1.0e-300.  This is a  +    ** non-zero probability, but it is still vanishingly small and should +    ** never cause a problem.  You are much, much more likely to have a +    ** hardware failure than for this algorithm to fail. +    ** +    ** The analysis in the previous paragraph assumes that you have a good +    ** source of random numbers.  Is a library function like lrand48() +    ** good enough?  Maybe. Maybe not. It's hard to know whether there +    ** might be subtle bugs is some implementations of lrand48() that +    ** could cause problems. To avoid uncertainty, SQLite uses its own  +    ** random number generator based on the RC4 algorithm. +    ** +    ** To promote locality of reference for repetitive inserts, the +    ** first few attempts at chosing a random rowid pick values just a little +    ** larger than the previous rowid.  This has been shown experimentally +    ** to double the speed of the COPY operation. +    */ +    int res, rx=SQLITE_OK, cnt; +    i64 x; +    cnt = 0; +    assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 ); +    assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 ); +    if( !pC->useRandomRowid ){ +      if( pC->nextRowidValid ){ +        v = pC->nextRowid; +      }else{ +        rx = sqlite3BtreeLast(pC->pCursor, &res); +        if( res ){ +          v = 1; +        }else{ +          sqlite3BtreeKeySize(pC->pCursor, &v); +          v = keyToInt(v); +          if( v==0x7fffffffffffffff ){ +            pC->useRandomRowid = 1; +          }else{ +            v++; +          } +        } +      } +      if( v<0x7fffffffffffffff ){ +        pC->nextRowidValid = 1; +        pC->nextRowid = v+1; +      }else{ +        pC->nextRowidValid = 0; +      } +    } +    if( pC->useRandomRowid ){ +      v = db->priorNewRowid; +      cnt = 0; +      do{ +        if( v==0 || cnt>2 ){ +          sqlite3Randomness(sizeof(v), &v); +          if( cnt<5 ) v &= 0xffffff; +        }else{ +          unsigned char r; +          sqlite3Randomness(1, &r); +          v += r + 1; +        } +        if( v==0 ) continue; +        x = intToKey(v); +        rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res); +        cnt++; +      }while( cnt<1000 && rx==SQLITE_OK && res==0 ); +      db->priorNewRowid = v; +      if( rx==SQLITE_OK && res==0 ){ +        rc = SQLITE_FULL; +        goto abort_due_to_error; +      } +    } +    pC->recnoIsValid = 0; +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +  } +  pTos++; +  pTos->i = v; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: PutIntKey P1 P2 * +** +** Write an entry into the table of cursor P1.  A new entry is +** created if it doesn't already exist or the data for an existing +** entry is overwritten.  The data is the value on the top of the +** stack.  The key is the next value down on the stack.  The key must +** be an integer.  The stack is popped twice by this instruction. +** +** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is +** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P2 is set, +** then rowid is stored for subsequent return by the +** sqlite3_last_insert_rowid() function (otherwise it's unmodified). +*/ +/* Opcode: PutStrKey P1 * * +** +** Write an entry into the table of cursor P1.  A new entry is +** created if it doesn't already exist or the data for an existing +** entry is overwritten.  The data is the value on the top of the +** stack.  The key is the next value down on the stack.  The key must +** be a string.  The stack is popped twice by this instruction. +** +** P1 may not be a pseudo-table opened using the OpenPseudo opcode. +*/ +case OP_PutIntKey: +case OP_PutStrKey: { +  Mem *pNos = &pTos[-1]; +  int i = pOp->p1; +  Cursor *pC; +  assert( pNos>=p->aStack ); +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ +    char *zKey; +    i64 nKey;  +    i64 iKey; +    if( pOp->opcode==OP_PutStrKey ){ +      Stringify(pNos, db->enc); +      nKey = pNos->n; +      zKey = pNos->z; +    }else{ +      assert( pNos->flags & MEM_Int ); + +      /* If the table is an INTKEY table, set nKey to the value of +      ** the integer key, and zKey to NULL. Otherwise, set nKey to +      ** sizeof(i64) and point zKey at iKey. iKey contains the integer +      ** key in the on-disk byte order. +      */ +      iKey = intToKey(pNos->i); +      if( pC->intKey ){ +        nKey = intToKey(pNos->i); +        zKey = 0; +      }else{ +        nKey = sizeof(i64); +        zKey = (char*)&iKey; +      } + +      if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; +      if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i; +      if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ +        pC->nextRowidValid = 0; +      } +    } +    if( pTos->flags & MEM_Null ){ +      pTos->z = 0; +      pTos->n = 0; +    }else{ +      assert( pTos->flags & (MEM_Blob|MEM_Str) ); +    } +    if( pC->pseudoTable ){ +      /* PutStrKey does not work for pseudo-tables. +      ** The following assert makes sure we are not trying to use +      ** PutStrKey on a pseudo-table +      */ +      assert( pOp->opcode==OP_PutIntKey ); +      sqliteFree(pC->pData); +      pC->iKey = iKey; +      pC->nData = pTos->n; +      if( pTos->flags & MEM_Dyn ){ +        pC->pData = pTos->z; +        pTos->flags = MEM_Null; +      }else{ +        pC->pData = sqliteMallocRaw( pC->nData+2 ); +        if( !pC->pData ) goto no_mem; +        memcpy(pC->pData, pTos->z, pC->nData); +        pC->pData[pC->nData] = 0; +        pC->pData[pC->nData+1] = 0; +      } +      pC->nullRow = 0; +    }else{ +      rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n); +    } +    pC->recnoIsValid = 0; +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +  } +  popStack(&pTos, 2); +  break; +} + +/* Opcode: Delete P1 P2 * +** +** Delete the record at which the P1 cursor is currently pointing. +** +** The cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op.  Hence it is OK to delete +** a record from within an Next loop. +** +** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is +** incremented (otherwise not). +** +** If P1 is a pseudo-table, then this instruction is a no-op. +*/ +case OP_Delete: { +  int i = pOp->p1; +  Cursor *pC; +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  if( pC->pCursor!=0 ){ +    sqlite3VdbeCursorMoveto(pC); +    rc = sqlite3BtreeDelete(pC->pCursor); +    pC->nextRowidValid = 0; +    pC->cacheValid = 0; +  } +  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; +  break; +} + +/* Opcode: ResetCount P1 * * +** +** This opcode resets the VMs internal change counter to 0. If P1 is true, +** then the value of the change counter is copied to the database handle +** change counter (returned by subsequent calls to sqlite3_changes()) +** before it is reset. This is used by trigger programs. +*/ +case OP_ResetCount: { +  if( pOp->p1 ){ +    sqlite3VdbeSetChanges(db, p->nChange); +  } +  p->nChange = 0; +  break; +} + +/* Opcode: KeyAsData P1 P2 * +** +** Turn the key-as-data mode for cursor P1 either on (if P2==1) or +** off (if P2==0).  In key-as-data mode, the OP_Column opcode pulls +** data off of the key rather than the data.  This is used for +** processing compound selects. +*/ +case OP_KeyAsData: { +  int i = pOp->p1; +  Cursor *pC; +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  pC->keyAsData = pOp->p2; +  break; +} + +/* Opcode: RowData P1 * * +** +** Push onto the stack the complete row data for cursor P1. +** There is no interpretation of the data.  It is just copied +** onto the stack exactly as it is found in the database file. +** +** If the cursor is not pointing to a valid row, a NULL is pushed +** onto the stack. +*/ +/* Opcode: RowKey P1 * * +** +** Push onto the stack the complete row key for cursor P1. +** There is no interpretation of the key.  It is just copied +** onto the stack exactly as it is found in the database file. +** +** If the cursor is not pointing to a valid row, a NULL is pushed +** onto the stack. +*/ +case OP_RowKey: +case OP_RowData: { +  int i = pOp->p1; +  Cursor *pC; +  u32 n; + +  pTos++; +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  if( pC->nullRow ){ +    pTos->flags = MEM_Null; +  }else if( pC->pCursor!=0 ){ +    BtCursor *pCrsr = pC->pCursor; +    sqlite3VdbeCursorMoveto(pC); +    if( pC->nullRow ){ +      pTos->flags = MEM_Null; +      break; +    }else if( pC->keyAsData || pOp->opcode==OP_RowKey ){ +      i64 n64; +      assert( !pC->intKey ); +      sqlite3BtreeKeySize(pCrsr, &n64); +      n = n64; +    }else{ +      sqlite3BtreeDataSize(pCrsr, &n); +    } +    pTos->n = n; +    if( n<=NBFS ){ +      pTos->flags = MEM_Blob | MEM_Short; +      pTos->z = pTos->zShort; +    }else{ +      char *z = sqliteMallocRaw( n ); +      if( z==0 ) goto no_mem; +      pTos->flags = MEM_Blob | MEM_Dyn; +      pTos->xDel = 0; +      pTos->z = z; +    } +    if( pC->keyAsData || pOp->opcode==OP_RowKey ){ +      sqlite3BtreeKey(pCrsr, 0, n, pTos->z); +    }else{ +      sqlite3BtreeData(pCrsr, 0, n, pTos->z); +    } +  }else if( pC->pseudoTable ){ +    pTos->n = pC->nData; +    pTos->z = pC->pData; +    pTos->flags = MEM_Blob|MEM_Ephem; +  }else{ +    pTos->flags = MEM_Null; +  } +  break; +} + +/* Opcode: Recno P1 * * +** +** Push onto the stack an integer which is the first 4 bytes of the +** the key to the current entry in a sequential scan of the database +** file P1.  The sequential scan should have been started using the  +** Next opcode. +*/ +case OP_Recno: { +  int i = pOp->p1; +  Cursor *pC; +  i64 v; + +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  sqlite3VdbeCursorMoveto(pC); +  pTos++; +  if( pC->recnoIsValid ){ +    v = pC->lastRecno; +  }else if( pC->pseudoTable ){ +    v = keyToInt(pC->iKey); +  }else if( pC->nullRow || pC->pCursor==0 ){ +    pTos->flags = MEM_Null; +    break; +  }else{ +    assert( pC->pCursor!=0 ); +    sqlite3BtreeKeySize(pC->pCursor, &v); +    v = keyToInt(v); +  } +  pTos->i = v; +  pTos->flags = MEM_Int; +  break; +} + +/* Opcode: FullKey P1 * * +** +** Extract the complete key from the record that cursor P1 is currently +** pointing to and push the key onto the stack as a string. +** +** Compare this opcode to Recno.  The Recno opcode extracts the first +** 4 bytes of the key and pushes those bytes onto the stack as an +** integer.  This instruction pushes the entire key as a string. +** +** This opcode may not be used on a pseudo-table. +*/ +case OP_FullKey: { +  int i = pOp->p1; +  BtCursor *pCrsr; +  Cursor *pC; + +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  assert( p->apCsr[i]->keyAsData ); +  assert( !p->apCsr[i]->pseudoTable ); +  pTos++; +  pTos->flags = MEM_Null; +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    i64 amt; +    char *z; + +    sqlite3VdbeCursorMoveto(pC); +    assert( pC->intKey==0 ); +    sqlite3BtreeKeySize(pCrsr, &amt); +    if( amt<=0 ){ +      rc = SQLITE_CORRUPT; +      goto abort_due_to_error; +    } +    if( amt>NBFS ){ +      z = sqliteMallocRaw( amt ); +      if( z==0 ) goto no_mem; +      pTos->flags = MEM_Blob | MEM_Dyn; +      pTos->xDel = 0; +    }else{ +      z = pTos->zShort; +      pTos->flags = MEM_Blob | MEM_Short; +    } +    sqlite3BtreeKey(pCrsr, 0, amt, z); +    pTos->z = z; +    pTos->n = amt; +  } +  break; +} + +/* Opcode: NullRow P1 * * +** +** Move the cursor P1 to a null row.  Any OP_Column operations +** that occur while the cursor is on the null row will always push  +** a NULL onto the stack. +*/ +case OP_NullRow: { +  int i = pOp->p1; +  Cursor *pC; + +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  pC->nullRow = 1; +  pC->recnoIsValid = 0; +  break; +} + +/* Opcode: Last P1 P2 * +** +** The next use of the Recno or Column or Next instruction for P1  +** will refer to the last entry in the database table or index. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. +*/ +case OP_Last: { +  int i = pOp->p1; +  Cursor *pC; +  BtCursor *pCrsr; + +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  if( (pCrsr = pC->pCursor)!=0 ){ +    int res; +    rc = sqlite3BtreeLast(pCrsr, &res); +    pC->nullRow = res; +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +    if( res && pOp->p2>0 ){ +      pc = pOp->p2 - 1; +    } +  }else{ +    pC->nullRow = 0; +  } +  break; +} + +/* Opcode: Rewind P1 P2 * +** +** The next use of the Recno or Column or Next instruction for P1  +** will refer to the first entry in the database table or index. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. +*/ +case OP_Rewind: { +  int i = pOp->p1; +  Cursor *pC; +  BtCursor *pCrsr; +  int res; + +  assert( i>=0 && i<p->nCursor ); +  pC = p->apCsr[i]; +  assert( pC!=0 ); +  if( (pCrsr = pC->pCursor)!=0 ){ +    rc = sqlite3BtreeFirst(pCrsr, &res); +    pC->atFirst = res==0; +    pC->deferredMoveto = 0; +    pC->cacheValid = 0; +  }else{ +    res = 1; +  } +  pC->nullRow = res; +  if( res && pOp->p2>0 ){ +    pc = pOp->p2 - 1; +  } +  break; +} + +/* Opcode: Next P1 P2 * +** +** Advance cursor P1 so that it points to the next key/data pair in its +** table or index.  If there are no more key/value pairs then fall through +** to the following instruction.  But if the cursor advance was successful, +** jump immediately to P2. +** +** See also: Prev +*/ +/* Opcode: Prev P1 P2 * +** +** Back up cursor P1 so that it points to the previous key/data pair in its +** table or index.  If there is no previous key/value pairs then fall through +** to the following instruction.  But if the cursor backup was successful, +** jump immediately to P2. +*/ +case OP_Prev: +case OP_Next: { +  Cursor *pC; +  BtCursor *pCrsr; + +  CHECK_FOR_INTERRUPT; +  assert( pOp->p1>=0 && pOp->p1<p->nCursor ); +  pC = p->apCsr[pOp->p1]; +  assert( pC!=0 ); +  if( (pCrsr = pC->pCursor)!=0 ){ +    int res; +    if( pC->nullRow ){ +      res = 1; +    }else{ +      assert( pC->deferredMoveto==0 ); +      rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : +                                  sqlite3BtreePrevious(pCrsr, &res); +      pC->nullRow = res; +      pC->cacheValid = 0; +    } +    if( res==0 ){ +      pc = pOp->p2 - 1; +      sqlite3_search_count++; +    } +  }else{ +    pC->nullRow = 1; +  } +  pC->recnoIsValid = 0; +  break; +} + +/* Opcode: IdxPut P1 P2 P3 +** +** The top of the stack holds a SQL index key made using the +** MakeIdxKey instruction.  This opcode writes that key into the +** index P1.  Data for the entry is nil. +** +** If P2==1, then the key must be unique.  If the key is not unique, +** the program aborts with a SQLITE_CONSTRAINT error and the database +** is rolled back.  If P3 is not null, then it becomes part of the +** error message returned with the SQLITE_CONSTRAINT. +*/ +case OP_IdxPut: { +  int i = pOp->p1; +  Cursor *pC; +  BtCursor *pCrsr; +  assert( pTos>=p->aStack ); +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  assert( pTos->flags & MEM_Blob ); +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    int nKey = pTos->n; +    const char *zKey = pTos->z; +    if( pOp->p2 ){ +      int res; +      int len; +    +      /* 'len' is the length of the key minus the rowid at the end */ +      len = nKey - sqlite3VdbeIdxRowidLen(nKey, zKey); + +      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); +      if( rc!=SQLITE_OK ) goto abort_due_to_error; +      while( res!=0 && !sqlite3BtreeEof(pCrsr) ){ +        int c; +        if( sqlite3VdbeIdxKeyCompare(pC, len, zKey, &c)==SQLITE_OK && c==0 ){ +          rc = SQLITE_CONSTRAINT; +          if( pOp->p3 && pOp->p3[0] ){ +            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); +          } +          goto abort_due_to_error; +        } +        if( res<0 ){ +          sqlite3BtreeNext(pCrsr, &res); +          res = +1; +        }else{ +          break; +        } +      } +    } +    assert( pC->intKey==0 ); +    rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); +    assert( pC->deferredMoveto==0 ); +    pC->cacheValid = 0; +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: IdxDelete P1 * * +** +** The top of the stack is an index key built using the MakeIdxKey opcode. +** This opcode removes that entry from the index. +*/ +case OP_IdxDelete: { +  int i = pOp->p1; +  Cursor *pC; +  BtCursor *pCrsr; +  assert( pTos>=p->aStack ); +  assert( pTos->flags & MEM_Blob ); +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    int rx, res; +    rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); +    if( rx==SQLITE_OK && res==0 ){ +      rc = sqlite3BtreeDelete(pCrsr); +    } +    assert( pC->deferredMoveto==0 ); +    pC->cacheValid = 0; +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: IdxRecno P1 * * +** +** Push onto the stack an integer which is the varint located at the +** end of the index key pointed to by cursor P1.  These integer should be +** the record number of the table entry to which this index entry points. +** +** See also: Recno, MakeIdxKey. +*/ +case OP_IdxRecno: { +  int i = pOp->p1; +  BtCursor *pCrsr; +  Cursor *pC; + +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  pTos++; +  pTos->flags = MEM_Null; +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    i64 rowid; + +    assert( pC->deferredMoveto==0 ); +    assert( pC->intKey==0 ); +    if( pC->nullRow ){ +      pTos->flags = MEM_Null; +    }else{ +      rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); +      if( rc!=SQLITE_OK ){ +        goto abort_due_to_error; +      } +      pTos->flags = MEM_Int; +      pTos->i = rowid; +    } +  } +  break; +} + +/* Opcode: IdxGT P1 P2 * +** +** The top of the stack is an index entry that omits the ROWID.  Compare +** the top of stack against the index that P1 is currently pointing to. +** Ignore the ROWID on the P1 index. +** +** The top of the stack might have fewer columns that P1. +** +** If the P1 index entry is greater than the top of the stack +** then jump to P2.  Otherwise fall through to the next instruction. +** In either case, the stack is popped once. +*/ +/* Opcode: IdxGE P1 P2 P3 +** +** The top of the stack is an index entry that omits the ROWID.  Compare +** the top of stack against the index that P1 is currently pointing to. +** Ignore the ROWID on the P1 index. +** +** If the P1 index entry is greater than or equal to the top of the stack +** then jump to P2.  Otherwise fall through to the next instruction. +** In either case, the stack is popped once. +** +** If P3 is the "+" string (or any other non-NULL string) then the +** index taken from the top of the stack is temporarily increased by +** an epsilon prior to the comparison.  This make the opcode work +** like IdxGT except that if the key from the stack is a prefix of +** the key in the cursor, the result is false whereas it would be +** true with IdxGT. +*/ +/* Opcode: IdxLT P1 P2 P3 +** +** The top of the stack is an index entry that omits the ROWID.  Compare +** the top of stack against the index that P1 is currently pointing to. +** Ignore the ROWID on the P1 index. +** +** If the P1 index entry is less than  the top of the stack +** then jump to P2.  Otherwise fall through to the next instruction. +** In either case, the stack is popped once. +** +** If P3 is the "+" string (or any other non-NULL string) then the +** index taken from the top of the stack is temporarily increased by +** an epsilon prior to the comparison.  This makes the opcode work +** like IdxLE. +*/ +case OP_IdxLT: +case OP_IdxGT: +case OP_IdxGE: { +  int i= pOp->p1; +  BtCursor *pCrsr; +  Cursor *pC; + +  assert( i>=0 && i<p->nCursor ); +  assert( p->apCsr[i]!=0 ); +  assert( pTos>=p->aStack ); +  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ +    int res, rc; +  +    assert( pTos->flags & MEM_Blob );  /* Created using OP_Make*Key */ +    Stringify(pTos, db->enc); +    assert( pC->deferredMoveto==0 ); +    *pC->pIncrKey = pOp->p3!=0; +    assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); +    rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, &res); +    *pC->pIncrKey = 0; +    if( rc!=SQLITE_OK ){ +      break; +    } +    if( pOp->opcode==OP_IdxLT ){ +      res = -res; +    }else if( pOp->opcode==OP_IdxGE ){ +      res++; +    } +    if( res>0 ){ +      pc = pOp->p2 - 1 ; +    } +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: IdxIsNull P1 P2 * +** +** The top of the stack contains an index entry such as might be generated +** by the MakeIdxKey opcode.  This routine looks at the first P1 fields of +** that key.  If any of the first P1 fields are NULL, then a jump is made +** to address P2.  Otherwise we fall straight through. +** +** The index entry is always popped from the stack. +*/ +case OP_IdxIsNull: { +  int i = pOp->p1; +  int k, n; +  const char *z; +  u32 serial_type; + +  assert( pTos>=p->aStack ); +  assert( pTos->flags & MEM_Blob ); +  z = pTos->z; +  n = pTos->n; +  k = sqlite3GetVarint32(z, &serial_type); +  for(; k<n && i>0; i--){ +    k += sqlite3GetVarint32(&z[k], &serial_type); +    if( serial_type==0 ){   /* Serial type 0 is a NULL */ +      pc = pOp->p2-1; +      break; +    } +  } +  Release(pTos); +  pTos--; +  break; +} + +/* Opcode: Destroy P1 P2 * +** +** Delete an entire database table or index whose root page in the database +** file is given by P1. +** +** The table being destroyed is in the main database file if P2==0.  If +** P2==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** See also: Clear +*/ +case OP_Destroy: { +  rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1); +  break; +} + +/* Opcode: Clear P1 P2 * +** +** Delete all contents of the database table or index whose root page +** in the database file is given by P1.  But, unlike Destroy, do not +** remove the table or index from the database file. +** +** The table being clear is in the main database file if P2==0.  If +** P2==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** See also: Destroy +*/ +case OP_Clear: { +  rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); +  break; +} + +/* Opcode: CreateTable P1 * * +** +** Allocate a new table in the main database file if P2==0 or in the +** auxiliary database file if P2==1.  Push the page number +** for the root page of the new table onto the stack. +** +** The difference between a table and an index is this:  A table must +** have a 4-byte integer key and can have arbitrary data.  An index +** has an arbitrary key but no data. +** +** See also: CreateIndex +*/ +/* Opcode: CreateIndex P1 * * +** +** Allocate a new index in the main database file if P2==0 or in the +** auxiliary database file if P2==1.  Push the page number of the +** root page of the new index onto the stack. +** +** See documentation on OP_CreateTable for additional information. +*/ +case OP_CreateIndex: +case OP_CreateTable: { +  int pgno; +  int flags; +  Db *pDb; +  assert( pOp->p1>=0 && pOp->p1<db->nDb ); +  pDb = &db->aDb[pOp->p1]; +  assert( pDb->pBt!=0 ); +  if( pOp->opcode==OP_CreateTable ){ +    /* flags = BTREE_INTKEY; */ +    flags = BTREE_LEAFDATA|BTREE_INTKEY; +  }else{ +    flags = BTREE_ZERODATA; +  } +  rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); +  pTos++; +  if( rc==SQLITE_OK ){ +    pTos->i = pgno; +    pTos->flags = MEM_Int; +  }else{ +    pTos->flags = MEM_Null; +  } +  break; +} + +/* Opcode: ParseSchema P1 * P3 +** +** Read and parse all entries from the SQLITE_MASTER table of database P1 +** that match the WHERE clause P3. +** +** This opcode invokes the parser to create a new virtual machine, +** then runs the new virtual machine.  It is thus a reentrant opcode. +*/ +case OP_ParseSchema: { +  char *zSql; +  int iDb = pOp->p1; +  const char *zMaster; +  InitData initData; + +  assert( iDb>=0 && iDb<db->nDb ); +  if( !DbHasProperty(db, iDb, DB_SchemaLoaded) ) break; +  zMaster = iDb==1 ? TEMP_MASTER_NAME : MASTER_NAME; +  initData.db = db; +  initData.pzErrMsg = &p->zErrMsg; +  zSql = sqlite3MPrintf( +     "SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s", +     pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3); +  if( zSql==0 ) goto no_mem; +  sqlite3SafetyOff(db); +  assert( db->init.busy==0 ); +  db->init.busy = 1; +  rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); +  db->init.busy = 0; +  sqlite3SafetyOn(db); +  sqliteFree(zSql); +  break;   +} + +/* Opcode: DropTable P1 * P3 +** +** Remove the internal (in-memory) data structures that describe +** the table named P3 in database P1.  This is called after a table +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTable: { +  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3); +  break; +} + +/* Opcode: DropIndex P1 * P3 +** +** Remove the internal (in-memory) data structures that describe +** the index named P3 in database P1.  This is called after an index +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropIndex: { +  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3); +  break; +} + +/* Opcode: DropTrigger P1 * P3 +** +** Remove the internal (in-memory) data structures that describe +** the trigger named P3 in database P1.  This is called after a trigger +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTrigger: { +  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3); +  break; +} + + +/* Opcode: IntegrityCk * P2 * +** +** Do an analysis of the currently open database.  Push onto the +** stack the text of an error message describing any problems. +** If there are no errors, push a "ok" onto the stack. +** +** The root page numbers of all tables in the database are integer +** values on the stack.  This opcode pulls as many integers as it +** can off of the stack and uses those numbers as the root pages. +** +** If P2 is not zero, the check is done on the auxiliary database +** file, not the main database file. +** +** This opcode is used for testing purposes only. +*/ +case OP_IntegrityCk: { +  int nRoot; +  int *aRoot; +  int j; +  char *z; + +  for(nRoot=0; &pTos[-nRoot]>=p->aStack; nRoot++){ +    if( (pTos[-nRoot].flags & MEM_Int)==0 ) break; +  } +  assert( nRoot>0 ); +  aRoot = sqliteMallocRaw( sizeof(int*)*(nRoot+1) ); +  if( aRoot==0 ) goto no_mem; +  for(j=0; j<nRoot; j++){ +    Mem *pMem = &pTos[-j]; +    aRoot[j] = pMem->i; +  } +  aRoot[j] = 0; +  popStack(&pTos, nRoot); +  pTos++; +  z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot); +  if( z==0 || z[0]==0 ){ +    if( z ) sqliteFree(z); +    pTos->z = "ok"; +    pTos->n = 2; +    pTos->flags = MEM_Str | MEM_Static | MEM_Term; +  }else{ +    pTos->z = z; +    pTos->n = strlen(z); +    pTos->flags = MEM_Str | MEM_Dyn | MEM_Term; +    pTos->xDel = 0; +  } +  pTos->enc = SQLITE_UTF8; +  sqlite3VdbeChangeEncoding(pTos, db->enc); +  sqliteFree(aRoot); +  break; +} + +/* Opcode: ListWrite * * * +** +** Write the integer on the top of the stack +** into the temporary storage list. +*/ +case OP_ListWrite: { +  Keylist *pKeylist; +  assert( pTos>=p->aStack ); +  pKeylist = p->pList; +  if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ +    pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); +    if( pKeylist==0 ) goto no_mem; +    pKeylist->nKey = 1000; +    pKeylist->nRead = 0; +    pKeylist->nUsed = 0; +    pKeylist->pNext = p->pList; +    p->pList = pKeylist; +  } +  Integerify(pTos); +  pKeylist->aKey[pKeylist->nUsed++] = pTos->i; +  assert( (pTos->flags & MEM_Dyn)==0 ); +  pTos--; +  break; +} + +/* Opcode: ListRewind * * * +** +** Rewind the temporary buffer back to the beginning. +*/ +case OP_ListRewind: { +  /* What this opcode codes, really, is reverse the order of the +  ** linked list of Keylist structures so that they are read out +  ** in the same order that they were read in. */ +  Keylist *pRev, *pTop; +  pRev = 0; +  while( p->pList ){ +    pTop = p->pList; +    p->pList = pTop->pNext; +    pTop->pNext = pRev; +    pRev = pTop; +  } +  p->pList = pRev; +  break; +} + +/* Opcode: ListRead * P2 * +** +** Attempt to read an integer from the temporary storage buffer +** and push it onto the stack.  If the storage buffer is empty,  +** push nothing but instead jump to P2. +*/ +case OP_ListRead: { +  Keylist *pKeylist; +  CHECK_FOR_INTERRUPT; +  pKeylist = p->pList; +  if( pKeylist!=0 ){ +    assert( pKeylist->nRead>=0 ); +    assert( pKeylist->nRead<pKeylist->nUsed ); +    assert( pKeylist->nRead<pKeylist->nKey ); +    pTos++; +    pTos->i = pKeylist->aKey[pKeylist->nRead++]; +    pTos->flags = MEM_Int; +    if( pKeylist->nRead>=pKeylist->nUsed ){ +      p->pList = pKeylist->pNext; +      sqliteFree(pKeylist); +    } +  }else{ +    pc = pOp->p2 - 1; +  } +  break; +} + +/* Opcode: ListReset * * * +** +** Reset the temporary storage buffer so that it holds nothing. +*/ +case OP_ListReset: { +  if( p->pList ){ +    sqlite3VdbeKeylistFree(p->pList); +    p->pList = 0; +  } +  break; +} + +/* Opcode: ContextPush * * *  +** +** Save the current Vdbe context such that it can be restored by a ContextPop +** opcode. The context stores the last insert row id, the last statement change +** count, and the current statement change count. +*/ +case OP_ContextPush: { +  int i = p->contextStackTop++; +  Context *pContext; + +  assert( i>=0 ); +  /* FIX ME: This should be allocated as part of the vdbe at compile-time */ +  if( i>=p->contextStackDepth ){ +    p->contextStackDepth = i+1; +    p->contextStack = sqliteRealloc(p->contextStack, sizeof(Context)*(i+1)); +    if( p->contextStack==0 ) goto no_mem; +  } +  pContext = &p->contextStack[i]; +  pContext->lastRowid = db->lastRowid; +  pContext->nChange = p->nChange; +  pContext->pList = p->pList; +  p->pList = 0; +  break; +} + +/* Opcode: ContextPop * * *  +** +** Restore the Vdbe context to the state it was in when contextPush was last +** executed. The context stores the last insert row id, the last statement +** change count, and the current statement change count. +*/ +case OP_ContextPop: { +  Context *pContext = &p->contextStack[--p->contextStackTop]; +  assert( p->contextStackTop>=0 ); +  db->lastRowid = pContext->lastRowid; +  p->nChange = pContext->nChange; +  sqlite3VdbeKeylistFree(p->pList); +  p->pList = pContext->pList; +  break; +} + +/* Opcode: SortPut * * * +** +** The TOS is the key and the NOS is the data.  Pop both from the stack +** and put them on the sorter.  The key and data should have been +** made using SortMakeKey and SortMakeRec, respectively. +*/ +case OP_SortPut: { +  Mem *pNos = &pTos[-1]; +  Sorter *pSorter; +  assert( pNos>=p->aStack ); +  if( Dynamicify(pTos, db->enc) ) goto no_mem; +  pSorter = sqliteMallocRaw( sizeof(Sorter) ); +  if( pSorter==0 ) goto no_mem; +  pSorter->pNext = p->pSort; +  p->pSort = pSorter; +  assert( pTos->flags & MEM_Dyn ); +  pSorter->nKey = pTos->n; +  pSorter->zKey = pTos->z; +  pSorter->data.flags = MEM_Null; +  rc = sqlite3VdbeMemMove(&pSorter->data, pNos); +  pTos -= 2; +  break; +} + +/* Opcode: Sort * * P3 +** +** Sort all elements on the sorter.  The algorithm is a +** mergesort.  The P3 argument is a pointer to a KeyInfo structure +** that describes the keys to be sorted. +*/ +case OP_Sort: { +  int i; +  KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3; +  Sorter *pElem; +  Sorter *apSorter[NSORT]; +  pKeyInfo->enc = p->db->enc; +  for(i=0; i<NSORT; i++){ +    apSorter[i] = 0; +  } +  while( p->pSort ){ +    pElem = p->pSort; +    p->pSort = pElem->pNext; +    pElem->pNext = 0; +    for(i=0; i<NSORT-1; i++){ +      if( apSorter[i]==0 ){ +        apSorter[i] = pElem; +        break; +      }else{ +        pElem = Merge(apSorter[i], pElem, pKeyInfo); +        apSorter[i] = 0; +      } +    } +    if( i>=NSORT-1 ){ +      apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem, pKeyInfo); +    } +  } +  pElem = 0; +  for(i=0; i<NSORT; i++){ +    pElem = Merge(apSorter[i], pElem, pKeyInfo); +  } +  p->pSort = pElem; +  break; +} + +/* Opcode: SortNext * P2 * +** +** Push the data for the topmost element in the sorter onto the +** stack, then remove the element from the sorter.  If the sorter +** is empty, push nothing on the stack and instead jump immediately  +** to instruction P2. +*/ +case OP_SortNext: { +  Sorter *pSorter = p->pSort; +  CHECK_FOR_INTERRUPT; +  if( pSorter!=0 ){ +    p->pSort = pSorter->pNext; +    pTos++; +    pTos->flags = MEM_Null; +    rc = sqlite3VdbeMemMove(pTos, &pSorter->data); +    sqliteFree(pSorter->zKey); +    sqliteFree(pSorter); +  }else{ +    pc = pOp->p2 - 1; +  } +  break; +} + +/* Opcode: SortReset * * * +** +** Remove any elements that remain on the sorter. +*/ +case OP_SortReset: { +  sqlite3VdbeSorterReset(p); +  break; +} + +/* Opcode: MemStore P1 P2 * +** +** Write the top of the stack into memory location P1. +** P1 should be a small integer since space is allocated +** for all memory locations between 0 and P1 inclusive. +** +** After the data is stored in the memory location, the +** stack is popped once if P2 is 1.  If P2 is zero, then +** the original data remains on the stack. +*/ +case OP_MemStore: { +  assert( pTos>=p->aStack ); +  assert( pOp->p1>=0 && pOp->p1<p->nMem ); +  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos); +  pTos--; + +  /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will +  ** restore the top of the stack to its original value. +  */ +  if( pOp->p2 ){ +    break; +  } +} +/* Opcode: MemLoad P1 * * +** +** Push a copy of the value in memory location P1 onto the stack. +** +** If the value is a string, then the value pushed is a pointer to +** the string that is stored in the memory location.  If the memory +** location is subsequently changed (using OP_MemStore) then the +** value pushed onto the stack will change too. +*/ +case OP_MemLoad: { +  int i = pOp->p1; +  assert( i>=0 && i<p->nMem ); +  pTos++; +  sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem); +  break; +} + +/* Opcode: MemIncr P1 P2 * +** +** Increment the integer valued memory cell P1 by 1.  If P2 is not zero +** and the result after the increment is greater than zero, then jump +** to P2. +** +** This instruction throws an error if the memory cell is not initially +** an integer. +*/ +case OP_MemIncr: { +  int i = pOp->p1; +  Mem *pMem; +  assert( i>=0 && i<p->nMem ); +  pMem = &p->aMem[i]; +  assert( pMem->flags==MEM_Int ); +  pMem->i++; +  if( pOp->p2>0 && pMem->i>0 ){ +     pc = pOp->p2 - 1; +  } +  break; +} + +/* Opcode: AggReset P1 P2 P3 +** +** Reset the aggregator so that it no longer contains any data. +** Future aggregator elements will contain P2 values each and be sorted +** using the KeyInfo structure pointed to by P3. +** +** If P1 is non-zero, then only a single aggregator row is available (i.e. +** there is no GROUP BY expression). In this case it is illegal to invoke +** OP_AggFocus. +*/ +case OP_AggReset: { +  assert( !pOp->p3 || pOp->p3type==P3_KEYINFO ); +  if( pOp->p1 ){ +    rc = sqlite3VdbeAggReset(0, &p->agg, (KeyInfo *)pOp->p3); +    p->agg.nMem = pOp->p2;    /* Agg.nMem is used by AggInsert() */ +    rc = AggInsert(&p->agg, 0, 0); +  }else{ +    rc = sqlite3VdbeAggReset(db, &p->agg, (KeyInfo *)pOp->p3); +    p->agg.nMem = pOp->p2; +  } +  if( rc!=SQLITE_OK ){ +    goto abort_due_to_error; +  } +  p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) ); +  if( p->agg.apFunc==0 ) goto no_mem; +  break; +} + +/* Opcode: AggInit * P2 P3 +** +** Initialize the function parameters for an aggregate function. +** The aggregate will operate out of aggregate column P2. +** P3 is a pointer to the FuncDef structure for the function. +*/ +case OP_AggInit: { +  int i = pOp->p2; +  assert( i>=0 && i<p->agg.nMem ); +  p->agg.apFunc[i] = (FuncDef*)pOp->p3; +  break; +} + +/* Opcode: AggFunc * P2 P3 +** +** Execute the step function for an aggregate.  The +** function has P2 arguments.  P3 is a pointer to the FuncDef +** structure that specifies the function. +** +** The top of the stack must be an integer which is the index of +** the aggregate column that corresponds to this aggregate function. +** Ideally, this index would be another parameter, but there are +** no free parameters left.  The integer is popped from the stack. +*/ +case OP_AggFunc: { +  int n = pOp->p2; +  int i; +  Mem *pMem, *pRec; +  sqlite3_context ctx; +  sqlite3_value **apVal; + +  assert( n>=0 ); +  assert( pTos->flags==MEM_Int ); +  pRec = &pTos[-n]; +  assert( pRec>=p->aStack ); + +  apVal = p->apArg; +  assert( apVal || n==0 ); + +  for(i=0; i<n; i++, pRec++){ +    apVal[i] = pRec; +    storeTypeInfo(pRec, db->enc); +  } +  i = pTos->i; +  assert( i>=0 && i<p->agg.nMem ); +  ctx.pFunc = (FuncDef*)pOp->p3; +  pMem = &p->agg.pCurrent->aMem[i]; +  ctx.s.z = pMem->zShort;  /* Space used for small aggregate contexts */ +  ctx.pAgg = pMem->z; +  ctx.cnt = ++pMem->i; +  ctx.isError = 0; +  ctx.isStep = 1; +  ctx.pColl = 0; +  if( ctx.pFunc->needCollSeq ){ +    assert( pOp>p->aOp ); +    assert( pOp[-1].p3type==P3_COLLSEQ ); +    assert( pOp[-1].opcode==OP_CollSeq ); +    ctx.pColl = (CollSeq *)pOp[-1].p3; +  } +  (ctx.pFunc->xStep)(&ctx, n, apVal); +  pMem->z = ctx.pAgg; +  pMem->flags = MEM_AggCtx; +  popStack(&pTos, n+1); +  if( ctx.isError ){ +    rc = SQLITE_ERROR; +  } +  break; +} + +/* Opcode: AggFocus * P2 * +** +** Pop the top of the stack and use that as an aggregator key.  If +** an aggregator with that same key already exists, then make the +** aggregator the current aggregator and jump to P2.  If no aggregator +** with the given key exists, create one and make it current but +** do not jump. +** +** The order of aggregator opcodes is important.  The order is: +** AggReset AggFocus AggNext.  In other words, you must execute +** AggReset first, then zero or more AggFocus operations, then +** zero or more AggNext operations.  You must not execute an AggFocus +** in between an AggNext and an AggReset. +*/ +case OP_AggFocus: { +  char *zKey; +  int nKey; +  int res; +  assert( pTos>=p->aStack ); +  Stringify(pTos, db->enc); +  zKey = pTos->z; +  nKey = pTos->n; +  assert( p->agg.pBtree ); +  assert( p->agg.pCsr ); +  rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res); +  if( rc!=SQLITE_OK ){ +    goto abort_due_to_error; +  } +  if( res==0 ){ +    rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), +        (char *)&p->agg.pCurrent); +    pc = pOp->p2 - 1; +  }else{ +    rc = AggInsert(&p->agg, zKey, nKey); +  } +  if( rc!=SQLITE_OK ){ +    goto abort_due_to_error; +  } +  Release(pTos); +  pTos--; +  break;  +} + +/* Opcode: AggSet * P2 * +** +** Move the top of the stack into the P2-th field of the current +** aggregate.  String values are duplicated into new memory. +*/ +case OP_AggSet: { +  AggElem *pFocus; +  int i = pOp->p2; +  pFocus = p->agg.pCurrent; +  assert( pTos>=p->aStack ); +  if( pFocus==0 ) goto no_mem; +  assert( i>=0 && i<p->agg.nMem ); +  rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos); +  pTos--; +  break; +} + +/* Opcode: AggGet * P2 * +** +** Push a new entry onto the stack which is a copy of the P2-th field +** of the current aggregate.  Strings are not duplicated so +** string values will be ephemeral. +*/ +case OP_AggGet: { +  AggElem *pFocus; +  int i = pOp->p2; +  pFocus = p->agg.pCurrent; +  if( pFocus==0 ) goto no_mem; +  assert( i>=0 && i<p->agg.nMem ); +  pTos++; +  sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem); +  if( pTos->flags&MEM_Str ){ +    sqlite3VdbeChangeEncoding(pTos, db->enc); +  } +  break; +} + +/* Opcode: AggNext * P2 * +** +** Make the next aggregate value the current aggregate.  The prior +** aggregate is deleted.  If all aggregate values have been consumed, +** jump to P2. +** +** The order of aggregator opcodes is important.  The order is: +** AggReset AggFocus AggNext.  In other words, you must execute +** AggReset first, then zero or more AggFocus operations, then +** zero or more AggNext operations.  You must not execute an AggFocus +** in between an AggNext and an AggReset. +*/ +case OP_AggNext: { +  int res; +  assert( rc==SQLITE_OK ); +  CHECK_FOR_INTERRUPT; +  if( p->agg.searching==0 ){ +    p->agg.searching = 1; +    if( p->agg.pCsr ){ +      rc = sqlite3BtreeFirst(p->agg.pCsr, &res); +    }else{ +      res = 0; +    } +  }else{ +    if( p->agg.pCsr ){ +      rc = sqlite3BtreeNext(p->agg.pCsr, &res); +    }else{ +      res = 1; +    } +  } +  if( rc!=SQLITE_OK ) goto abort_due_to_error; +  if( res!=0 ){ +    pc = pOp->p2 - 1; +  }else{ +    int i; +    sqlite3_context ctx; +    Mem *aMem; + +    if( p->agg.pCsr ){ +      rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), +          (char *)&p->agg.pCurrent); +      if( rc!=SQLITE_OK ) goto abort_due_to_error; +    } +    aMem = p->agg.pCurrent->aMem; +    for(i=0; i<p->agg.nMem; i++){ +      FuncDef *pFunc = p->agg.apFunc[i]; +      Mem *pMem = &aMem[i]; +      if( pFunc==0 || pFunc->xFinalize==0 ) continue; +      ctx.s.flags = MEM_Null; +      ctx.s.z = pMem->zShort; +      ctx.pAgg = (void*)pMem->z; +      ctx.cnt = pMem->i; +      ctx.isStep = 0; +      ctx.pFunc = pFunc; +      pFunc->xFinalize(&ctx); +      pMem->z = ctx.pAgg; +      if( pMem->z && pMem->z!=pMem->zShort ){ +        sqliteFree( pMem->z ); +      } +      *pMem = ctx.s; +      if( pMem->flags & MEM_Short ){ +        pMem->z = pMem->zShort; +      } +    } +  } +  break; +} + +/* Opcode: Vacuum * * * +** +** Vacuum the entire database.  This opcode will cause other virtual +** machines to be created and run.  It may not be called from within +** a transaction. +*/ +case OP_Vacuum: { +  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;  +  rc = sqlite3RunVacuum(&p->zErrMsg, db); +  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; +  break; +} + +/* An other opcode is illegal... +*/ +default: { +  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode); +  sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0); +  rc = SQLITE_INTERNAL; +  break; +} + +/***************************************************************************** +** The cases of the switch statement above this line should all be indented +** by 6 spaces.  But the left-most 6 spaces have been removed to improve the +** readability.  From this point on down, the normal indentation rules are +** restored. +*****************************************************************************/ +    } + +#ifdef VDBE_PROFILE +    { +      long long elapse = hwtime() - start; +      pOp->cycles += elapse; +      pOp->cnt++; +#if 0 +        fprintf(stdout, "%10lld ", elapse); +        sqlite3VdbePrintOp(stdout, origPc, &p->aOp[origPc]); +#endif +    } +#endif + +    /* The following code adds nothing to the actual functionality +    ** of the program.  It is only here for testing and debugging. +    ** On the other hand, it does burn CPU cycles every time through +    ** the evaluator loop.  So we can leave it out when NDEBUG is defined. +    */ +#ifndef NDEBUG +    /* Sanity checking on the top element of the stack */ +    if( pTos>=p->aStack ){ +      sqlite3VdbeMemSanity(pTos, db->enc); +    } +    if( pc<-1 || pc>=p->nOp ){ +      sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0); +      rc = SQLITE_INTERNAL; +    } +    if( p->trace && pTos>=p->aStack ){ +      int i; +      fprintf(p->trace, "Stack:"); +      for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ +        if( pTos[i].flags & MEM_Null ){ +          fprintf(p->trace, " NULL"); +        }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ +          fprintf(p->trace, " si:%lld", pTos[i].i); +        }else if( pTos[i].flags & MEM_Int ){ +          fprintf(p->trace, " i:%lld", pTos[i].i); +        }else if( pTos[i].flags & MEM_Real ){ +          fprintf(p->trace, " r:%g", pTos[i].r); +        }else{ +          char zBuf[100]; +          sqlite3VdbeMemPrettyPrint(&pTos[i], zBuf, 100); +          fprintf(p->trace, " "); +          fprintf(p->trace, "%s", zBuf); +        } +      } +      if( rc!=0 ) fprintf(p->trace," rc=%d",rc); +      fprintf(p->trace,"\n"); +    } +#endif +  }  /* The end of the for(;;) loop the loops through opcodes */ + +  /* If we reach this point, it means that execution is finished. +  */ +vdbe_halt: +  if( rc ){ +    p->rc = rc; +    rc = SQLITE_ERROR; +  }else{ +    rc = SQLITE_DONE; +  } +  sqlite3VdbeHalt(p); +  p->pTos = pTos; +  return rc; + +  /* Jump to here if a malloc() fails.  It's hard to get a malloc() +  ** to fail on a modern VM computer, so this code is untested. +  */ +no_mem: +  sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0); +  rc = SQLITE_NOMEM; +  goto vdbe_halt; + +  /* Jump to here for an SQLITE_MISUSE error. +  */ +abort_due_to_misuse: +  rc = SQLITE_MISUSE; +  /* Fall thru into abort_due_to_error */ + +  /* Jump to here for any other kind of fatal error.  The "rc" variable +  ** should hold the error number. +  */ +abort_due_to_error: +  if( p->zErrMsg==0 ){ +    if( sqlite3_malloc_failed ) rc = SQLITE_NOMEM; +    sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0); +  } +  goto vdbe_halt; + +  /* Jump to here if the sqlite3_interrupt() API sets the interrupt +  ** flag. +  */ +abort_due_to_interrupt: +  assert( db->flags & SQLITE_Interrupt ); +  db->flags &= ~SQLITE_Interrupt; +  if( db->magic!=SQLITE_MAGIC_BUSY ){ +    rc = SQLITE_MISUSE; +  }else{ +    rc = SQLITE_INTERRUPT; +  } +  p->rc = rc; +  sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0); +  goto vdbe_halt; +} diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.h b/ext/pdo_sqlite/sqlite/src/vdbe.h new file mode 100644 index 0000000000..490417a422 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbe.h @@ -0,0 +1,131 @@ +/* +** 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. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE.  The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +** +** $Id$ +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ +#include <stdio.h> + +/* +** A single VDBE is an opaque structure named "Vdbe".  Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands.  The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { +  u8 opcode;          /* What operation to perform */ +  int p1;             /* First operand */ +  int p2;             /* Second parameter (often the jump destination) */ +  char *p3;           /* Third parameter */ +  int p3type;         /* P3_STATIC, P3_DYNAMIC or P3_POINTER */ +#ifdef VDBE_PROFILE +  int cnt;            /* Number of times this instruction was executed */ +  long long cycles;   /* Total time spend executing this instruction */ +#endif +}; +typedef struct VdbeOp VdbeOp; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { +  u8 opcode;          /* What operation to perform */ +  signed char p1;     /* First operand */ +  short int p2;       /* Second parameter (often the jump destination) */ +  char *p3;           /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p3type +*/ +#define P3_NOTUSED    0   /* The P3 parameter is not used */ +#define P3_DYNAMIC  (-1)  /* Pointer to a string obtained from sqliteMalloc() */ +#define P3_STATIC   (-2)  /* Pointer to a static string */ +#define P3_POINTER  (-3)  /* P3 is a pointer to some structure or object */ +#define P3_COLLSEQ  (-4)  /* P3 is a pointer to a CollSeq structure */ +#define P3_FUNCDEF  (-5)  /* P3 is a pointer to a FuncDef structure */ +#define P3_KEYINFO  (-6)  /* P3 is a pointer to a KeyInfo structure */ +#define P3_VDBEFUNC (-7)  /* P3 is a pointer to a VdbeFunc structure */ + +/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure +** is made.  That copy is freed when the Vdbe is finalized.  But if the +** argument is P3_KEYINFO_HANDOFF, the passed in pointer is used.  It still +** gets freed when the Vdbe is finalized so it still should be obtained +** from a single sqliteMalloc().  But no copy is made and the calling +** function should *not* try to free the KeyInfo. +*/ +#define P3_KEYINFO_HANDOFF (-7) + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that  +** sqlite3VdbeAddOpList() knows that the address is relative.  Calling +** the macro again restores the address. +*/ +#define ADDR(X)  (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +#include "opcodes.h" + +/* +** Prototypes for the VDBE interface.  See comments on the implementation +** for a description of what each of these routines does. +*/ +Vdbe *sqlite3VdbeCreate(sqlite3*); +void sqlite3VdbeCreateCallback(Vdbe*, int*); +int sqlite3VdbeAddOp(Vdbe*,int,int,int); +int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); +int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); +void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); +void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); +void sqlite3VdbeDequoteP3(Vdbe*, int addr); +int sqlite3VdbeFindOp(Vdbe*, int, int, int); +VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +int sqlite3VdbeMakeLabel(Vdbe*); +void sqlite3VdbeDelete(Vdbe*); +void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); +int sqlite3VdbeFinalize(Vdbe*); +void sqlite3VdbeResolveLabel(Vdbe*, int); +int sqlite3VdbeCurrentAddr(Vdbe*); +void sqlite3VdbeTrace(Vdbe*,FILE*); +int sqlite3VdbeReset(Vdbe*); +int sqliteVdbeSetVariables(Vdbe*,int,const char**); +void sqlite3VdbeSetNumCols(Vdbe*,int); +int sqlite3VdbeSetColName(Vdbe*, int, const char *, int); +void sqlite3VdbeCountChanges(Vdbe*); + +#ifndef NDEBUG +  void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X)  sqlite3VdbeComment X +#else +# define VdbeComment(X) +#endif + +#endif diff --git a/ext/pdo_sqlite/sqlite/src/vdbeInt.h b/ext/pdo_sqlite/sqlite/src/vdbeInt.h new file mode 100644 index 0000000000..a929cb95e1 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbeInt.h @@ -0,0 +1,408 @@ +/* +** 2003 September 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 is the header file for information that is private to the +** VDBE.  This information used to all be at the top of the single +** source code file "vdbe.c".  When that file became too big (over +** 6000 lines long) it was split up into several smaller files and +** this header information was factored out. +*/ + +/* +** intToKey() and keyToInt() used to transform the rowid.  But with +** the latest versions of the design they are no-ops. +*/ +#define keyToInt(X)   (X) +#define intToKey(X)   (X) + +/* +** The makefile scans the vdbe.c source file and creates the following +** array of string constants which are the names of all VDBE opcodes.  This +** array is defined in a separate source code file named opcode.c which is +** automatically generated by the makefile. +*/ +extern char *sqlite3OpcodeNames[]; + +/* +** SQL is translated into a sequence of instructions to be +** executed by a virtual machine.  Each instruction is an instance +** of the following structure. +*/ +typedef struct VdbeOp Op; + +/* +** Boolean values +*/ +typedef unsigned char Bool; + +/* +** A cursor is a pointer into a single BTree within a database file. +** The cursor can seek to a BTree entry with a particular key, or +** loop over all entries of the Btree.  You can also insert new BTree +** entries or retrieve the key or data from the entry that the cursor +** is currently pointing to. +**  +** Every cursor that the virtual machine has open is represented by an +** instance of the following structure. +** +** If the Cursor.isTriggerRow flag is set it means that this cursor is +** really a single row that represents the NEW or OLD pseudo-table of +** a row trigger.  The data for the row is stored in Cursor.pData and +** the rowid is in Cursor.iKey. +*/ +struct Cursor { +  BtCursor *pCursor;    /* The cursor structure of the backend */ +  i64 lastRecno;        /* Last recno from a Next or NextIdx operation */ +  i64 nextRowid;        /* Next rowid returned by OP_NewRowid */ +  Bool zeroed;          /* True if zeroed out and ready for reuse */ +  Bool recnoIsValid;    /* True if lastRecno is valid */ +  Bool keyAsData;       /* The OP_Column command works on key instead of data */ +  Bool atFirst;         /* True if pointing to first entry */ +  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */ +  Bool nullRow;         /* True if pointing to a row with no data */ +  Bool nextRowidValid;  /* True if the nextRowid field is valid */ +  Bool pseudoTable;     /* This is a NEW or OLD pseudo-tables of a trigger */ +  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */ +  Bool intKey;          /* True if the table requires integer keys */ +  Bool zeroData;        /* True if table contains keys only - no data */ +  u8 bogusIncrKey;      /* Something for pIncrKey to point to if pKeyInfo==0 */ +  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */ +  Btree *pBt;           /* Separate file holding temporary table */ +  int nData;            /* Number of bytes in pData */ +  char *pData;          /* Data for a NEW or OLD pseudo-table */ +  i64 iKey;             /* Key for the NEW or OLD pseudo-table row */ +  u8 *pIncrKey;         /* Pointer to pKeyInfo->incrKey */ +  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */ +  int nField;           /* Number of fields in the header */ + +  /* Cached information about the header for the data record that the +  ** cursor is currently pointing to.  Only valid if cacheValid is true. +  ** zRow might point to (ephemeral) data for the current row, or it might +  ** be NULL. */ +  Bool cacheValid;      /* True if the cache is valid */ +  int payloadSize;      /* Total number of bytes in the record */ +  u32 *aType;           /* Type values for all entries in the record */ +  u32 *aOffset;         /* Cached offsets to the start of each columns data */ +  u8 *aRow;             /* Data for the current row, if all on one page */ +}; +typedef struct Cursor Cursor; + +/* +** Number of bytes of string storage space available to each stack +** layer without having to malloc.  NBFS is short for Number of Bytes +** For Strings. +*/ +#define NBFS 32 + +/* +** Internally, the vdbe manipulates nearly all SQL values as Mem +** structures. Each Mem struct may cache multiple representations (string, +** integer etc.) of the same value.  A value (and therefore Mem structure) +** has the following properties: +** +** Each value has a manifest type. The manifest type of the value stored +** in a Mem struct is returned by the MemType(Mem*) macro. The type is +** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or +** SQLITE_BLOB. +*/ +struct Mem { +  i64 i;              /* Integer value */ +  int n;              /* Number of characters in string value, including '\0' */ +  u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ +  u8  type;           /* One of MEM_Null, MEM_Str, etc. */ +  u8  enc;            /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */ +  double r;           /* Real value */ +  char *z;            /* String or BLOB value */ +  void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */ +  char zShort[NBFS];  /* Space for short strings */ +}; +typedef struct Mem Mem; + +/* +** A sorter builds a list of elements to be sorted.  Each element of +** the list is an instance of the following structure. +*/ +typedef struct Sorter Sorter; +struct Sorter { +  int nKey;           /* Number of bytes in the key */ +  char *zKey;         /* The key by which we will sort */ +  Mem data; +  Sorter *pNext;      /* Next in the list */ +}; + +/*  +** Number of buckets used for merge-sort.   +*/ +#define NSORT 30 + +/* One or more of the following flags are set to indicate the validOK +** representations of the value stored in the Mem struct. +** +** If the MEM_Null flag is set, then the value is an SQL NULL value. +** No other flags may be set in this case. +** +** If the MEM_Str flag is set then Mem.z points at a string representation. +** Usually this is encoded in the same unicode encoding as the main +** database (see below for exceptions). If the MEM_Term flag is also +** set, then the string is nul terminated. The MEM_Int and MEM_Real  +** flags may coexist with the MEM_Str flag. +** +** Multiple of these values can appear in Mem.flags.  But only one +** at a time can appear in Mem.type. +*/ +#define MEM_Null      0x0001   /* Value is NULL */ +#define MEM_Str       0x0002   /* Value is a string */ +#define MEM_Int       0x0004   /* Value is an integer */ +#define MEM_Real      0x0008   /* Value is a real number */ +#define MEM_Blob      0x0010   /* Value is a BLOB */ + +/* Whenever Mem contains a valid string or blob representation, one of +** the following flags must be set to determine the memory management +** policy for Mem.z.  The MEM_Term flag tells us whether or not the +** string is \000 or \u0000 terminated +*/ +#define MEM_Term      0x0020   /* String rep is nul terminated */ +#define MEM_Dyn       0x0040   /* Need to call sqliteFree() on Mem.z */ +#define MEM_Static    0x0080   /* Mem.z points to a static string */ +#define MEM_Ephem     0x0100   /* Mem.z points to an ephemeral string */ +#define MEM_Short     0x0200   /* Mem.z points to Mem.zShort */ + +/* The following MEM_ value appears only in AggElem.aMem.s.flag fields. +** It indicates that the corresponding AggElem.aMem.z points to a +** aggregate function context that needs to be finalized. +*/ +#define MEM_AggCtx    0x0400  /* Mem.z points to an agg function context */ + + +/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains +** additional information about auxiliary information bound to arguments +** of the function.  This is used to implement the sqlite3_get_auxdata() +** and sqlite3_set_auxdata() APIs.  The "auxdata" is some auxiliary data +** that can be associated with a constant argument to a function.  This +** allows functions such as "regexp" to compile their constant regular +** expression argument once and reused the compiled code for multiple +** invocations. +*/ +struct VdbeFunc { +  FuncDef *pFunc;               /* The definition of the function */ +  int nAux;                     /* Number of entries allocated for apAux[] */ +  struct AuxData { +    void *pAux;                   /* Aux data for the i-th argument */ +    void (*xDelete)(void *);      /* Destructor for the aux data */ +  } apAux[1];                   /* One slot for each function argument */ +}; +typedef struct VdbeFunc VdbeFunc; + +/* +** The "context" argument for a installable function.  A pointer to an +** instance of this structure is the first argument to the routines used +** implement the SQL functions. +** +** There is a typedef for this structure in sqlite.h.  So all routines, +** even the public interface to SQLite, can use a pointer to this structure. +** But this file is the only place where the internal details of this +** structure are known. +** +** This structure is defined inside of vdbe.c because it uses substructures +** (Mem) which are only defined there. +*/ +struct sqlite3_context { +  FuncDef *pFunc;   /* Pointer to function information.  MUST BE FIRST */ +  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */ +  Mem s;            /* The return value is stored here */ +  void *pAgg;       /* Aggregate context */ +  u8 isError;       /* Set to true for an error */ +  u8 isStep;        /* Current in the step function */ +  int cnt;          /* Number of times that the step function has been called */ +  CollSeq *pColl; +}; + +/* +** An Agg structure describes an Aggregator.  Each Agg consists of +** zero or more Aggregator elements (AggElem).  Each AggElem contains +** a key and one or more values.  The values are used in processing +** aggregate functions in a SELECT.  The key is used to implement +** the GROUP BY clause of a select. +*/ +typedef struct Agg Agg; +typedef struct AggElem AggElem; +struct Agg { +  int nMem;            /* Number of values stored in each AggElem */ +  AggElem *pCurrent;   /* The AggElem currently in focus */ +  FuncDef **apFunc;    /* Information about aggregate functions */ +  Btree *pBtree;       /* The tmp. btree used to group elements, if required. */ +  BtCursor *pCsr;      /* Read/write cursor to the table in pBtree */ +  int nTab;            /* Root page of the table in pBtree */ +  u8 searching;        /* True between the first AggNext and AggReset */ +}; +struct AggElem { +  char *zKey;          /* The key to this AggElem */ +  int nKey;            /* Number of bytes in the key, including '\0' at end */ +  Mem aMem[1];         /* The values for this AggElem */ +}; + +/* +** A Set structure is used for quick testing to see if a value +** is part of a small set.  Sets are used to implement code like +** this: +**            x.y IN ('hi','hoo','hum') +*/ +typedef struct Set Set; +struct Set { +  Hash hash;             /* A set is just a hash table */ +  HashElem *prev;        /* Previously accessed hash elemen */ +}; + +/* +** A Keylist is a bunch of keys into a table.  The keylist can +** grow without bound.  The keylist stores the ROWIDs of database +** records that need to be deleted or updated. +*/ +typedef struct Keylist Keylist; +struct Keylist { +  int nKey;         /* Number of slots in aKey[] */ +  int nUsed;        /* Next unwritten slot in aKey[] */ +  int nRead;        /* Next unread slot in aKey[] */ +  Keylist *pNext;   /* Next block of keys */ +  i64 aKey[1];      /* One or more keys.  Extra space allocated as needed */ +}; + +/* +** A Context stores the last insert rowid, the last statement change count, +** and the current statement change count (i.e. changes since last statement). +** The current keylist is also stored in the context. +** Elements of Context structure type make up the ContextStack, which is +** updated by the ContextPush and ContextPop opcodes (used by triggers). +** The context is pushed before executing a trigger a popped when the +** trigger finishes. +*/ +typedef struct Context Context; +struct Context { +  int lastRowid;    /* Last insert rowid (sqlite3.lastRowid) */ +  int nChange;      /* Statement changes (Vdbe.nChanges)     */ +  Keylist *pList;   /* Records that will participate in a DELETE or UPDATE */ +}; + +/* +** An instance of the virtual machine.  This structure contains the complete +** state of the virtual machine. +** +** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile() +** is really a pointer to an instance of this structure. +*/ +struct Vdbe { +  sqlite3 *db;        /* The whole database */ +  Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ +  FILE *trace;        /* Write an execution trace here, if not NULL */ +  int nOp;            /* Number of instructions in the program */ +  int nOpAlloc;       /* Number of slots allocated for aOp[] */ +  Op *aOp;            /* Space to hold the virtual machine's program */ +  int nLabel;         /* Number of labels used */ +  int nLabelAlloc;    /* Number of slots allocated in aLabel[] */ +  int *aLabel;        /* Space to hold the labels */ +  Mem *aStack;        /* The operand stack, except string values */ +  Mem *pTos;          /* Top entry in the operand stack */ +  Mem **apArg;        /* Arguments to currently executing user function */ +  Mem *aColName;      /* Column names to return */ +  int nCursor;        /* Number of slots in apCsr[] */ +  Cursor **apCsr;     /* One element of this array for each open cursor */ +  Sorter *pSort;      /* A linked list of objects to be sorted */ +  int nVar;           /* Number of entries in aVar[] */ +  Mem *aVar;          /* Values for the OP_Variable opcode. */ +  char **azVar;       /* Name of variables */ +  int okVar;          /* True if azVar[] has been initialized */ +  int magic;              /* Magic number for sanity checking */ +  int nMem;               /* Number of memory locations currently allocated */ +  Mem *aMem;              /* The memory locations */ +  Agg agg;                /* Aggregate information */ +  int nCallback;          /* Number of callbacks invoked so far */ +  Keylist *pList;         /* A list of ROWIDs */ +  int contextStackTop;    /* Index of top element in the context stack */ +  int contextStackDepth;  /* The size of the "context" stack */ +  Context *contextStack;  /* Stack used by opcodes ContextPush & ContextPop*/ +  int pc;                 /* The program counter */ +  int rc;                 /* Value to return */ +  unsigned uniqueCnt;     /* Used by OP_MakeRecord when P2!=0 */ +  int errorAction;        /* Recovery action to do in case of an error */ +  int inTempTrans;        /* True if temp database is transactioned */ +  int returnStack[100];   /* Return address stack for OP_Gosub & OP_Return */ +  int returnDepth;        /* Next unused element in returnStack[] */ +  int nResColumn;         /* Number of columns in one row of the result set */ +  char **azResColumn;     /* Values for one row of result */  +  int popStack;           /* Pop the stack this much on entry to VdbeExec() */ +  char *zErrMsg;          /* Error message written here */ +  u8 resOnStack;          /* True if there are result values on the stack */ +  u8 explain;             /* True if EXPLAIN present on SQL command */ +  u8 changeCntOn;         /* True to update the change-counter */ +  u8 aborted;             /* True if ROLLBACK in another VM causes an abort */ +  int nChange;            /* Number of db changes made since last reset */ +}; + +/* +** The following are allowed values for Vdbe.magic +*/ +#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */ +#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */ +#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */ + +/* +** Function prototypes +*/ +void sqlite3VdbeFreeCursor(Cursor*); +void sqlite3VdbeSorterReset(Vdbe*); +int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *); +void sqlite3VdbeKeylistFree(Keylist*); +void sqliteVdbePopStack(Vdbe*,int); +int sqlite3VdbeCursorMoveto(Cursor*); +#if !defined(NDEBUG) || defined(VDBE_PROFILE) +void sqlite3VdbePrintOp(FILE*, int, Op*); +#endif +void sqlite3VdbePrintSql(Vdbe*); +int sqlite3VdbeSerialTypeLen(u32); +u32 sqlite3VdbeSerialType(Mem*); +int sqlite3VdbeSerialPut(unsigned char*, Mem*); +int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); + +int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); +int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*); +int sqlite3VdbeIdxRowid(BtCursor *, i64 *); +int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); +int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); +int sqlite3VdbeIdxRowidLen(int,const u8*); +int sqlite3VdbeExec(Vdbe*); +int sqlite3VdbeList(Vdbe*); +int sqlite3VdbeHalt(Vdbe*); +int sqlite3VdbeChangeEncoding(Mem *, int); +int sqlite3VdbeMemCopy(Mem*, const Mem*); +void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); +int sqlite3VdbeMemMove(Mem*, Mem*); +int sqlite3VdbeMemNulTerminate(Mem*); +int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); +void sqlite3VdbeMemSetInt64(Mem*, i64); +void sqlite3VdbeMemSetDouble(Mem*, double); +void sqlite3VdbeMemSetNull(Mem*); +int sqlite3VdbeMemMakeWriteable(Mem*); +int sqlite3VdbeMemDynamicify(Mem*); +int sqlite3VdbeMemStringify(Mem*, int); +i64 sqlite3VdbeIntValue(Mem*); +int sqlite3VdbeMemIntegerify(Mem*); +double sqlite3VdbeRealValue(Mem*); +int sqlite3VdbeMemRealify(Mem*); +int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); +void sqlite3VdbeMemRelease(Mem *p); +#ifndef NDEBUG +void sqlite3VdbeMemSanity(Mem*, u8); +#endif +int sqlite3VdbeMemTranslate(Mem*, u8); +void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf); +int sqlite3VdbeMemHandleBom(Mem *pMem); diff --git a/ext/pdo_sqlite/sqlite/src/vdbeapi.c b/ext/pdo_sqlite/sqlite/src/vdbeapi.c new file mode 100644 index 0000000000..f6047f6fbe --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbeapi.c @@ -0,0 +1,588 @@ +/* +** 2004 May 26 +** +** 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 use to implement APIs that are part of the +** VDBE. +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" + +/**************************** sqlite3_value_  ******************************* +** The following routines extract information from a Mem or sqlite3_value +** structure. +*/ +const void *sqlite3_value_blob(sqlite3_value *pVal){ +  Mem *p = (Mem*)pVal; +  if( p->flags & (MEM_Blob|MEM_Str) ){ +    return p->z; +  }else{ +    return sqlite3_value_text(pVal); +  } +} +int sqlite3_value_bytes(sqlite3_value *pVal){ +  return sqlite3ValueBytes(pVal, SQLITE_UTF8); +} +int sqlite3_value_bytes16(sqlite3_value *pVal){ +  return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); +} +double sqlite3_value_double(sqlite3_value *pVal){ +  return sqlite3VdbeRealValue((Mem*)pVal); +} +int sqlite3_value_int(sqlite3_value *pVal){ +  return sqlite3VdbeIntValue((Mem*)pVal); +} +sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ +  return sqlite3VdbeIntValue((Mem*)pVal); +} +const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ +  return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8); +} +const void *sqlite3_value_text16(sqlite3_value* pVal){ +  return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); +} +const void *sqlite3_value_text16be(sqlite3_value *pVal){ +  return sqlite3ValueText(pVal, SQLITE_UTF16BE); +} +const void *sqlite3_value_text16le(sqlite3_value *pVal){ +  return sqlite3ValueText(pVal, SQLITE_UTF16LE); +} +int sqlite3_value_type(sqlite3_value* pVal){ +  return pVal->type; +} + +/**************************** sqlite3_result_  ******************************* +** The following routines are used by user-defined functions to specify +** the function result. +*/ +void sqlite3_result_blob( +  sqlite3_context *pCtx,  +  const void *z,  +  int n,  +  void (*xDel)(void *) +){ +  assert( n>0 ); +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); +} +void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ +  sqlite3VdbeMemSetDouble(&pCtx->s, rVal); +} +void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ +  pCtx->isError = 1; +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); +} +void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ +  pCtx->isError = 1; +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); +} +void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ +  sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); +} +void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ +  sqlite3VdbeMemSetInt64(&pCtx->s, iVal); +} +void sqlite3_result_null(sqlite3_context *pCtx){ +  sqlite3VdbeMemSetNull(&pCtx->s); +} +void sqlite3_result_text( +  sqlite3_context *pCtx,  +  const char *z,  +  int n, +  void (*xDel)(void *) +){ +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel); +} +void sqlite3_result_text16( +  sqlite3_context *pCtx,  +  const void *z,  +  int n,  +  void (*xDel)(void *) +){ +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); +} +void sqlite3_result_text16be( +  sqlite3_context *pCtx,  +  const void *z,  +  int n,  +  void (*xDel)(void *) +){ +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel); +} +void sqlite3_result_text16le( +  sqlite3_context *pCtx,  +  const void *z,  +  int n,  +  void (*xDel)(void *) +){ +  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel); +} +void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ +  sqlite3VdbeMemCopy(&pCtx->s, pValue); +} + + +/* +** Execute the statement pStmt, either until a row of data is ready, the +** statement is completely executed or an error occurs. +*/ +int sqlite3_step(sqlite3_stmt *pStmt){ +  Vdbe *p = (Vdbe*)pStmt; +  sqlite3 *db; +  int rc; + +  if( p==0 || p->magic!=VDBE_MAGIC_RUN ){ +    return SQLITE_MISUSE; +  } +  if( p->aborted ){ +    return SQLITE_ABORT; +  } +  db = p->db; +  if( sqlite3SafetyOn(db) ){ +    p->rc = SQLITE_MISUSE; +    return SQLITE_MISUSE; +  } +  if( p->pc<0 ){ +    /* Invoke the trace callback if there is one +    */ +    if( (db = p->db)->xTrace && !db->init.busy ){ +      assert( p->nOp>0 ); +      assert( p->aOp[p->nOp-1].opcode==OP_Noop ); +      assert( p->aOp[p->nOp-1].p3!=0 ); +      assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); +      sqlite3SafetyOff(db); +      db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3); +      if( sqlite3SafetyOn(db) ){ +        p->rc = SQLITE_MISUSE; +        return SQLITE_MISUSE; +      } +    } + +    /* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned +    ** on in debugging mode. +    */ +#ifdef SQLITE_DEBUG +    if( (db->flags & SQLITE_SqlTrace)!=0 ){ +      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3); +    } +#endif /* SQLITE_DEBUG */ + +    db->activeVdbeCnt++; +    p->pc = 0; +  } +  if( p->explain ){ +    rc = sqlite3VdbeList(p); +  }else{ +    rc = sqlite3VdbeExec(p); +  } + +  if( sqlite3SafetyOff(db) ){ +    rc = SQLITE_MISUSE; +  } + +  sqlite3Error(p->db, rc, p->zErrMsg); +  return rc; +} + +/* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +*/ +void *sqlite3_user_data(sqlite3_context *p){ +  assert( p && p->pFunc ); +  return p->pFunc->pUserData; +} + +/* +** Allocate or return the aggregate context for a user function.  A new +** context is allocated on the first call.  Subsequent calls return the +** same context that was returned on prior calls. +** +** This routine is defined here in vdbe.c because it depends on knowing +** the internals of the sqlite3_context structure which is only defined in +** this source file. +*/ +void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ +  assert( p && p->pFunc && p->pFunc->xStep ); +  if( p->pAgg==0 ){ +    if( nByte<=NBFS ){ +      p->pAgg = (void*)p->s.z; +      memset(p->pAgg, 0, nByte); +    }else{ +      p->pAgg = sqliteMalloc( nByte ); +    } +  } +  return p->pAgg; +} + +/* +** Return the auxilary data pointer, if any, for the iArg'th argument to +** the user-function defined by pCtx. +*/ +void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ +  VdbeFunc *pVdbeFunc = pCtx->pVdbeFunc; +  if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){ +    return 0; +  } +  return pVdbeFunc->apAux[iArg].pAux; +} + +/* +** Set the auxilary data pointer and delete function, for the iArg'th +** argument to the user-function defined by pCtx. Any previous value is +** deleted by calling the delete function specified when it was set. +*/ +void sqlite3_set_auxdata( +  sqlite3_context *pCtx,  +  int iArg,  +  void *pAux,  +  void (*xDelete)(void*) +){ +  struct AuxData *pAuxData; +  VdbeFunc *pVdbeFunc; +  if( iArg<0 ) return; + +  pVdbeFunc = pCtx->pVdbeFunc; +  if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ +    int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; +    pCtx->pVdbeFunc = pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc); +    if( !pVdbeFunc ) return; +    memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0,  +             sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux)); +    pVdbeFunc->nAux = iArg+1; +    pVdbeFunc->pFunc = pCtx->pFunc; +  } + +  pAuxData = &pVdbeFunc->apAux[iArg]; +  if( pAuxData->pAux && pAuxData->xDelete ){ +    pAuxData->xDelete(pAuxData->pAux); +  } +  pAuxData->pAux = pAux; +  pAuxData->xDelete = xDelete; +} + +/* +** Return the number of times the Step function of a aggregate has been  +** called. +** +** This routine is defined here in vdbe.c because it depends on knowing +** the internals of the sqlite3_context structure which is only defined in +** this source file. +*/ +int sqlite3_aggregate_count(sqlite3_context *p){ +  assert( p && p->pFunc && p->pFunc->xStep ); +  return p->cnt; +} + +/* +** Return the number of columns in the result set for the statement pStmt. +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt){ +  Vdbe *pVm = (Vdbe *)pStmt; +  return pVm ? pVm->nResColumn : 0; +} + +/* +** Return the number of values available from the current row of the +** currently executing statement pStmt. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt){ +  Vdbe *pVm = (Vdbe *)pStmt; +  if( pVm==0 || !pVm->resOnStack ) return 0; +  return pVm->nResColumn; +} + + +/* +** Check to see if column iCol of the given statement is valid.  If +** it is, return a pointer to the Mem for the value of that column. +** If iCol is not valid, return a pointer to a Mem which has a value +** of NULL. +*/ +static Mem *columnMem(sqlite3_stmt *pStmt, int i){ +  Vdbe *pVm = (Vdbe *)pStmt; +  int vals = sqlite3_data_count(pStmt); +  if( i>=vals || i<0 ){ +    static Mem nullMem; +    if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } +    sqlite3Error(pVm->db, SQLITE_RANGE, 0); +    return &nullMem; +  } +  return &pVm->pTos[(1-vals)+i]; +} + +/**************************** sqlite3_column_  ******************************* +** The following routines are used to access elements of the current row +** in the result set. +*/ +const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_blob( columnMem(pStmt,i) ); +} +int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_bytes( columnMem(pStmt,i) ); +} +int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_bytes16( columnMem(pStmt,i) ); +} +double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_double( columnMem(pStmt,i) ); +} +int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_int( columnMem(pStmt,i) ); +} +sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_int64( columnMem(pStmt,i) ); +} +const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_text( columnMem(pStmt,i) ); +} +const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_text16( columnMem(pStmt,i) ); +} +int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ +  return sqlite3_value_type( columnMem(pStmt,i) ); +} + +/* +** Convert the N-th element of pStmt->pColName[] into a string using +** xFunc() then return that string.  If N is out of range, return 0. +** If useType is 1, then use the second set of N elements (the datatype +** names) instead of the first set. +*/ +static const void *columnName( +  sqlite3_stmt *pStmt, +  int N, +  const void *(*xFunc)(Mem*), +  int useType +){ +  Vdbe *p = (Vdbe *)pStmt; +  int n = sqlite3_column_count(pStmt); + +  if( p==0 || N>=n || N<0 ){ +    return 0; +  } +  if( useType ){ +    N += n; +  } +  return xFunc(&p->aColName[N]); +} + + +/* +** Return the name of the Nth column of the result set returned by SQL +** statement pStmt. +*/ +const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ +  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0); +} + +/* +** Return the name of the 'i'th column of the result set of SQL statement +** pStmt, encoded as UTF-16. +*/ +const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ +  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0); +} + +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt, encoded as UTF-8. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ +  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1); +} + +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt, encoded as UTF-16. +*/ +const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ +  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1); +} + +/******************************* sqlite3_bind_  *************************** +**  +** Routines used to attach values to wildcards in a compiled SQL statement. +*/ +/* +** Unbind the value bound to variable i in virtual machine p. This is the  +** the same as binding a NULL value to the column. If the "i" parameter is +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** +** The error code stored in database p->db is overwritten with the return +** value in any case. +*/ +static int vdbeUnbind(Vdbe *p, int i){ +  Mem *pVar; +  if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ +    sqlite3Error(p->db, SQLITE_MISUSE, 0); +    return SQLITE_MISUSE; +  } +  if( i<1 || i>p->nVar ){ +    sqlite3Error(p->db, SQLITE_RANGE, 0); +    return SQLITE_RANGE; +  } +  i--; +  pVar = &p->aVar[i]; +  sqlite3VdbeMemRelease(pVar); +  pVar->flags = MEM_Null; +  sqlite3Error(p->db, SQLITE_OK, 0); +  return SQLITE_OK; +} + +/* +** Bind a text or BLOB value. +*/ +static int bindText( +  sqlite3_stmt *pStmt,  +  int i,  +  const void *zData,  +  int nData,  +  void (*xDel)(void*), +  int encoding +){ +  Vdbe *p = (Vdbe *)pStmt; +  Mem *pVar; +  int rc; + +  rc = vdbeUnbind(p, i); +  if( rc || zData==0 ){ +    return rc; +  } +  pVar = &p->aVar[i-1]; +  rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); +  if( rc ){ +    return rc; +  } +  if( rc==SQLITE_OK && encoding!=0 ){ +    rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc); +  } +  return rc; +} + + +/* +** Bind a blob value to an SQL statement variable. +*/ +int sqlite3_bind_blob( +  sqlite3_stmt *pStmt,  +  int i,  +  const void *zData,  +  int nData,  +  void (*xDel)(void*) +){ +  return bindText(pStmt, i, zData, nData, xDel, 0); +} +int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ +  int rc; +  Vdbe *p = (Vdbe *)pStmt; +  rc = vdbeUnbind(p, i); +  if( rc==SQLITE_OK ){ +    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); +  } +  return rc; +} +int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ +  return sqlite3_bind_int64(p, i, (i64)iValue); +} +int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ +  int rc; +  Vdbe *p = (Vdbe *)pStmt; +  rc = vdbeUnbind(p, i); +  if( rc==SQLITE_OK ){ +    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); +  } +  return rc; +} +int sqlite3_bind_null(sqlite3_stmt* p, int i){ +  return vdbeUnbind((Vdbe *)p, i); +} +int sqlite3_bind_text(  +  sqlite3_stmt *pStmt,  +  int i,  +  const char *zData,  +  int nData,  +  void (*xDel)(void*) +){ +  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); +} +int sqlite3_bind_text16( +  sqlite3_stmt *pStmt,  +  int i,  +  const void *zData,  +  int nData,  +  void (*xDel)(void*) +){ +  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); +} + +/* +** Return the number of wildcards that can be potentially bound to. +** This routine is added to support DBD::SQLite.   +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ +  Vdbe *p = (Vdbe*)pStmt; +  return p ? p->nVar : 0; +} + +/* +** Create a mapping from variable numbers to variable names +** in the Vdbe.azVar[] array, if such a mapping does not already +** exist. +*/ +static void createVarMap(Vdbe *p){ +  if( !p->okVar ){ +    int j; +    Op *pOp; +    for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){ +      if( pOp->opcode==OP_Variable ){ +        assert( pOp->p1>0 && pOp->p1<=p->nVar ); +        p->azVar[pOp->p1-1] = pOp->p3; +      } +    } +    p->okVar = 1; +  } +} + +/* +** Return the name of a wildcard parameter.  Return NULL if the index +** is out of range or if the wildcard is unnamed. +** +** The result is always UTF-8. +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ +  Vdbe *p = (Vdbe*)pStmt; +  if( p==0 || i<1 || i>p->nVar ){ +    return 0; +  } +  createVarMap(p); +  return p->azVar[i-1]; +} + +/* +** Given a wildcard parameter name, return the index of the variable +** with that name.  If there is no variable with the given name, +** return 0. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ +  Vdbe *p = (Vdbe*)pStmt; +  int i; +  if( p==0 ){ +    return 0; +  } +  createVarMap(p);  +  for(i=0; i<p->nVar; i++){ +    const char *z = p->azVar[i]; +    if( z && strcmp(z,zName)==0 ){ +      return i+1; +    } +  } +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/src/vdbeaux.c b/ext/pdo_sqlite/sqlite/src/vdbeaux.c new file mode 100644 index 0000000000..fa9751daab --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbeaux.c @@ -0,0 +1,1806 @@ +/* +** 2003 September 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 for creating, destroying, and populating +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior +** to version 2.8.7, all this code was combined into the vdbe.c source file. +** But that file was getting too big so this subroutines were split out. +*/ +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> +#include "vdbeInt.h" + + +/* +** When debugging the code generator in a symbolic debugger, one can +** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed +** as they are added to the instruction stream. +*/ +#ifndef NDEBUG +int sqlite3_vdbe_addop_trace = 0; +#endif + + +/* +** Create a new virtual database engine. +*/ +Vdbe *sqlite3VdbeCreate(sqlite3 *db){ +  Vdbe *p; +  p = sqliteMalloc( sizeof(Vdbe) ); +  if( p==0 ) return 0; +  p->db = db; +  if( db->pVdbe ){ +    db->pVdbe->pPrev = p; +  } +  p->pNext = db->pVdbe; +  p->pPrev = 0; +  db->pVdbe = p; +  p->magic = VDBE_MAGIC_INIT; +  return p; +} + +/* +** Turn tracing on or off +*/ +void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ +  p->trace = trace; +} + +/* +** Resize the Vdbe.aOp array so that it contains at least N +** elements. +*/ +static void resizeOpArray(Vdbe *p, int N){ +  if( p->nOpAlloc<N ){ +    int oldSize = p->nOpAlloc; +    p->nOpAlloc = N+100; +    p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); +    if( p->aOp ){ +      memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); +    } +  } +} + +/* +** Add a new instruction to the list of instructions current in the +** VDBE.  Return the address of the new instruction. +** +** Parameters: +** +**    p               Pointer to the VDBE +** +**    op              The opcode for this instruction +** +**    p1, p2          First two of the three possible operands. +** +** Use the sqlite3VdbeResolveLabel() function to fix an address and +** the sqlite3VdbeChangeP3() function to change the value of the P3 +** operand. +*/ +int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){ +  int i; +  VdbeOp *pOp; + +  i = p->nOp; +  p->nOp++; +  assert( p->magic==VDBE_MAGIC_INIT ); +  resizeOpArray(p, i+1); +  if( p->aOp==0 ){ +    return 0; +  } +  pOp = &p->aOp[i]; +  pOp->opcode = op; +  pOp->p1 = p1; +  pOp->p2 = p2; +  pOp->p3 = 0; +  pOp->p3type = P3_NOTUSED; +#ifndef NDEBUG +  if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); +#endif +  return i; +} + +/* +** Add an opcode that includes the p3 value. +*/ +int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){ +  int addr = sqlite3VdbeAddOp(p, op, p1, p2); +  sqlite3VdbeChangeP3(p, addr, zP3, p3type); +  return addr; +} + +/* +** Create a new symbolic label for an instruction that has yet to be +** coded.  The symbolic label is really just a negative number.  The +** label can be used as the P2 value of an operation.  Later, when +** the label is resolved to a specific address, the VDBE will scan +** through its operation list and change all values of P2 which match +** the label into the resolved address. +** +** The VDBE knows that a P2 value is a label because labels are +** always negative and P2 values are suppose to be non-negative. +** Hence, a negative P2 value is a label that has yet to be resolved. +** +** Zero is returned if a malloc() fails. +*/ +int sqlite3VdbeMakeLabel(Vdbe *p){ +  int i; +  i = p->nLabel++; +  assert( p->magic==VDBE_MAGIC_INIT ); +  if( i>=p->nLabelAlloc ){ +    p->nLabelAlloc = p->nLabelAlloc*2 + 10; +    p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); +  } +  if( p->aLabel ){ +    p->aLabel[i] = -1; +  } +  return -1-i; +} + +/* +** Resolve label "x" to be the address of the next instruction to +** be inserted.  The parameter "x" must have been obtained from +** a prior call to sqlite3VdbeMakeLabel(). +*/ +void sqlite3VdbeResolveLabel(Vdbe *p, int x){ +  int j = -1-x; +  assert( p->magic==VDBE_MAGIC_INIT ); +  assert( j>=0 && j<p->nLabel ); +  if( p->aLabel ){ +    p->aLabel[j] = p->nOp; +  } +} + +/* +** Loop through the program looking for P2 values that are negative. +** Each such value is a label.  Resolve the label by setting the P2 +** value to its correct non-zero value. +** +** This routine is called once after all opcodes have been inserted. +*/ +static void resolveP2Values(Vdbe *p){ +  int i; +  Op *pOp; +  int *aLabel = p->aLabel; +  if( aLabel==0 ) return; +  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ +    if( pOp->p2>=0 ) continue; +    assert( -1-pOp->p2<p->nLabel ); +    pOp->p2 = aLabel[-1-pOp->p2]; +  } +  sqliteFree(p->aLabel); +  p->aLabel = 0; +} + +/* +** Return the address of the next instruction to be inserted. +*/ +int sqlite3VdbeCurrentAddr(Vdbe *p){ +  assert( p->magic==VDBE_MAGIC_INIT ); +  return p->nOp; +} + +/* +** Add a whole list of operations to the operation stack.  Return the +** address of the first operation added. +*/ +int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ +  int addr; +  assert( p->magic==VDBE_MAGIC_INIT ); +  resizeOpArray(p, p->nOp + nOp); +  if( p->aOp==0 ){ +    return 0; +  } +  addr = p->nOp; +  if( nOp>0 ){ +    int i; +    VdbeOpList const *pIn = aOp; +    for(i=0; i<nOp; i++, pIn++){ +      int p2 = pIn->p2; +      VdbeOp *pOut = &p->aOp[i+addr]; +      pOut->opcode = pIn->opcode; +      pOut->p1 = pIn->p1; +      pOut->p2 = p2<0 ? addr + ADDR(p2) : p2; +      pOut->p3 = pIn->p3; +      pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED; +#ifndef NDEBUG +      if( sqlite3_vdbe_addop_trace ){ +        sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); +      } +#endif +    } +    p->nOp += nOp; +  } +  return addr; +} + +/* +** Change the value of the P1 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +*/ +void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ +  assert( p->magic==VDBE_MAGIC_INIT ); +  if( p && addr>=0 && p->nOp>addr && p->aOp ){ +    p->aOp[addr].p1 = val; +  } +} + +/* +** Change the value of the P2 operand for a specific instruction. +** This routine is useful for setting a jump destination. +*/ +void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ +  assert( val>=0 ); +  assert( p->magic==VDBE_MAGIC_INIT ); +  if( p && addr>=0 && p->nOp>addr && p->aOp ){ +    p->aOp[addr].p2 = val; +  } +} + +/* +** Change the value of the P3 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +** +** If n>=0 then the P3 operand is dynamic, meaning that a copy of +** the string is made into memory obtained from sqliteMalloc(). +** A value of n==0 means copy bytes of zP3 up to and including the +** first null byte.  If n>0 then copy n+1 bytes of zP3. +** +** If n==P3_STATIC  it means that zP3 is a pointer to a constant static +** string and we can just copy the pointer.  n==P3_POINTER means zP3 is +** a pointer to some object other than a string.  n==P3_COLLSEQ and +** n==P3_KEYINFO mean that zP3 is a pointer to a CollSeq or KeyInfo +** structure.  A copy is made of KeyInfo structures into memory obtained +** from sqliteMalloc. +** +** If addr<0 then change P3 on the most recently inserted instruction. +*/ +void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ +  Op *pOp; +  assert( p->magic==VDBE_MAGIC_INIT ); +  if( p==0 || p->aOp==0 ) return; +  if( addr<0 || addr>=p->nOp ){ +    addr = p->nOp - 1; +    if( addr<0 ) return; +  } +  pOp = &p->aOp[addr]; +  if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){ +    sqliteFree(pOp->p3); +    pOp->p3 = 0; +  } +  if( zP3==0 ){ +    pOp->p3 = 0; +    pOp->p3type = P3_NOTUSED; +  }else if( n==P3_KEYINFO ){ +    KeyInfo *pKeyInfo; +    int nField, nByte; +    nField = ((KeyInfo*)zP3)->nField; +    nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]); +    pKeyInfo = sqliteMallocRaw( nByte ); +    pOp->p3 = (char*)pKeyInfo; +    if( pKeyInfo ){ +      memcpy(pKeyInfo, zP3, nByte); +      pOp->p3type = P3_KEYINFO; +    }else{ +      pOp->p3type = P3_NOTUSED; +    } +  }else if( n==P3_KEYINFO_HANDOFF ){ +    pOp->p3 = (char*)zP3; +    pOp->p3type = P3_KEYINFO; +  }else if( n<0 ){ +    pOp->p3 = (char*)zP3; +    pOp->p3type = n; +  }else{ +    if( n==0 ) n = strlen(zP3); +    pOp->p3 = sqliteStrNDup(zP3, n); +    pOp->p3type = P3_DYNAMIC; +  } +} + +#ifndef NDEBUG +/* +** Replace the P3 field of the most recently coded instruction with +** comment text. +*/ +void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ +  va_list ap; +  assert( p->nOp>0 ); +  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 ); +  va_start(ap, zFormat); +  sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC); +  va_end(ap); +} +#endif + +/* +** If the P3 operand to the specified instruction appears +** to be a quoted string token, then this procedure removes  +** the quotes. +** +** The quoting operator can be either a grave ascent (ASCII 0x27) +** or a double quote character (ASCII 0x22).  Two quotes in a row +** resolve to be a single actual quote character within the string. +*/ +void sqlite3VdbeDequoteP3(Vdbe *p, int addr){ +  Op *pOp; +  assert( p->magic==VDBE_MAGIC_INIT ); +  if( p->aOp==0 ) return; +  if( addr<0 || addr>=p->nOp ){ +    addr = p->nOp - 1; +    if( addr<0 ) return; +  } +  pOp = &p->aOp[addr]; +  if( pOp->p3==0 || pOp->p3[0]==0 ) return; +  if( pOp->p3type==P3_STATIC ){ +    pOp->p3 = sqliteStrDup(pOp->p3); +    pOp->p3type = P3_DYNAMIC; +  } +  assert( pOp->p3type==P3_DYNAMIC ); +  sqlite3Dequote(pOp->p3); +} + +/* +** Search the current program starting at instruction addr for the given +** opcode and P2 value.  Return the address plus 1 if found and 0 if not +** found. +*/ +int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){ +  int i; +  assert( p->magic==VDBE_MAGIC_INIT ); +  for(i=addr; i<p->nOp; i++){ +    if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1; +  } +  return 0; +} + +/* +** Return the opcode for a given address. +*/ +VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ +  assert( p->magic==VDBE_MAGIC_INIT ); +  assert( addr>=0 && addr<p->nOp ); +  return &p->aOp[addr]; +} + +/* +** Compute a string that describes the P3 parameter for an opcode. +** Use zTemp for any required temporary buffer space. +*/ +static char *displayP3(Op *pOp, char *zTemp, int nTemp){ +  char *zP3; +  assert( nTemp>=20 ); +  switch( pOp->p3type ){ +    case P3_POINTER: { +      sprintf(zTemp, "ptr(%#x)", (int)pOp->p3); +      zP3 = zTemp; +      break; +    } +    case P3_KEYINFO: { +      int i, j; +      KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3; +      sprintf(zTemp, "keyinfo(%d", pKeyInfo->nField); +      i = strlen(zTemp); +      for(j=0; j<pKeyInfo->nField; j++){ +        CollSeq *pColl = pKeyInfo->aColl[j]; +        if( pColl ){ +          int n = strlen(pColl->zName); +          if( i+n>nTemp-6 ){ +            strcpy(&zTemp[i],",..."); +            break; +          } +          zTemp[i++] = ','; +          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){ +            zTemp[i++] = '-'; +          } +          strcpy(&zTemp[i], pColl->zName); +          i += n; +        }else if( i+4<nTemp-6 ){ +          strcpy(&zTemp[i],",nil"); +          i += 4; +        } +      } +      zTemp[i++] = ')'; +      zTemp[i] = 0; +      assert( i<nTemp ); +      zP3 = zTemp; +      break; +    } +    case P3_COLLSEQ: { +      CollSeq *pColl = (CollSeq*)pOp->p3; +      sprintf(zTemp, "collseq(%.20s)", pColl->zName); +      zP3 = zTemp; +      break; +    } +    case P3_FUNCDEF: { +      FuncDef *pDef = (FuncDef*)pOp->p3; +      char zNum[30]; +      sprintf(zTemp, "%.*s", nTemp, pDef->zName); +      sprintf(zNum,"(%d)", pDef->nArg); +      if( strlen(zTemp)+strlen(zNum)+1<=nTemp ){ +        strcat(zTemp, zNum); +      } +      zP3 = zTemp; +      break; +    } +    default: { +      zP3 = pOp->p3; +      if( zP3==0 || pOp->opcode==OP_Noop ){ +        zP3 = ""; +      } +    } +  } +  return zP3; +} + + +#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +/* +** Print a single opcode.  This routine is used for debugging only. +*/ +void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ +  char *zP3; +  char zPtr[50]; +  static const char *zFormat1 = "%4d %-13s %4d %4d %s\n"; +  if( pOut==0 ) pOut = stdout; +  zP3 = displayP3(pOp, zPtr, sizeof(zPtr)); +  fprintf(pOut, zFormat1, +      pc, sqlite3OpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3); +  fflush(pOut); +} +#endif + +/* +** Release an array of N Mem elements +*/ +static void releaseMemArray(Mem *p, int N){ +  if( p ){ +    while( N-->0 ){ +      sqlite3VdbeMemRelease(p++); +    } +  } +} + +/* +** Give a listing of the program in the virtual machine. +** +** The interface is the same as sqlite3VdbeExec().  But instead of +** running the code, it invokes the callback once for each instruction. +** This feature is used to implement "EXPLAIN". +*/ +int sqlite3VdbeList( +  Vdbe *p                   /* The VDBE */ +){ +  sqlite3 *db = p->db; +  int i; +  int rc = SQLITE_OK; + +  assert( p->explain ); + +  /* Even though this opcode does not put dynamic strings onto the +  ** the stack, they may become dynamic if the user calls +  ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. +  */ +  if( p->pTos==&p->aStack[4] ){ +    releaseMemArray(p->aStack, 5); +  } +  p->resOnStack = 0; + +  i = p->pc++; +  if( i>=p->nOp ){ +    p->rc = SQLITE_OK; +    rc = SQLITE_DONE; +  }else if( db->flags & SQLITE_Interrupt ){ +    db->flags &= ~SQLITE_Interrupt; +    if( db->magic!=SQLITE_MAGIC_BUSY ){ +      p->rc = SQLITE_MISUSE; +    }else{ +      p->rc = SQLITE_INTERRUPT; +    } +    rc = SQLITE_ERROR; +    sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0); +  }else{ +    Op *pOp = &p->aOp[i]; +    Mem *pMem = p->aStack; +    pMem->flags = MEM_Int; +    pMem->type = SQLITE_INTEGER; +    pMem->i = i;                                /* Program counter */ +    pMem++; + +    pMem->flags = MEM_Static|MEM_Str|MEM_Term; +    pMem->z = sqlite3OpcodeNames[pOp->opcode];  /* Opcode */ +    pMem->n = strlen(pMem->z); +    pMem->type = SQLITE_TEXT; +    pMem->enc = SQLITE_UTF8; +    pMem++; + +    pMem->flags = MEM_Int; +    pMem->i = pOp->p1;                          /* P1 */ +    pMem->type = SQLITE_INTEGER; +    pMem++; + +    pMem->flags = MEM_Int; +    pMem->i = pOp->p2;                          /* P2 */ +    pMem->type = SQLITE_INTEGER; +    pMem++; + +    pMem->flags = MEM_Short|MEM_Str|MEM_Term;   /* P3 */ +    pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort)); +    pMem->type = SQLITE_TEXT; +    pMem->enc = SQLITE_UTF8; + +    p->nResColumn = 5; +    p->pTos = pMem; +    p->rc = SQLITE_OK; +    p->resOnStack = 1; +    rc = SQLITE_ROW; +  } +  return rc; +} + +/* +** Print the SQL that was used to generate a VDBE program. +*/ +void sqlite3VdbePrintSql(Vdbe *p){ +#ifdef SQLITE_DEBUG +  int nOp = p->nOp; +  VdbeOp *pOp; +  if( nOp<1 ) return; +  pOp = &p->aOp[nOp-1]; +  if( pOp->opcode==OP_Noop && pOp->p3!=0 ){ +    const char *z = pOp->p3; +    while( isspace(*(u8*)z) ) z++; +    printf("SQL: [%s]\n", z); +  } +#endif +} + +/* +** Prepare a virtual machine for execution.  This involves things such +** as allocating stack space and initializing the program counter. +** After the VDBE has be prepped, it can be executed by one or more +** calls to sqlite3VdbeExec().   +** +** This is the only way to move a VDBE from VDBE_MAGIC_INIT to +** VDBE_MAGIC_RUN. +*/ +void sqlite3VdbeMakeReady( +  Vdbe *p,                       /* The VDBE */ +  int nVar,                      /* Number of '?' see in the SQL statement */ +  int nMem,                      /* Number of memory cells to allocate */ +  int nCursor,                   /* Number of cursors to allocate */ +  int isExplain                  /* True if the EXPLAIN keywords is present */ +){ +  int n; + +  assert( p!=0 ); +  assert( p->magic==VDBE_MAGIC_INIT ); + +  /* There should be at least one opcode. +  */ +  assert( p->nOp>0 ); + +  /* No instruction ever pushes more than a single element onto the +  ** stack.  And the stack never grows on successive executions of the +  ** same loop.  So the total number of instructions is an upper bound +  ** on the maximum stack depth required. +  ** +  ** Allocation all the stack space we will ever need. +  */ +  if( p->aStack==0 ){ +    resolveP2Values(p); +    assert( nVar>=0 ); +    n = isExplain ? 10 : p->nOp; +    p->aStack = sqliteMalloc( +        n*sizeof(p->aStack[0])         /* aStack */ +      + n*sizeof(Mem*)                 /* apArg */ +      + nVar*sizeof(Mem)               /* aVar */ +      + nVar*sizeof(char*)             /* azVar */ +      + nMem*sizeof(Mem)               /* aMem */ +      + nCursor*sizeof(Cursor*)        /* apCsr */ +    ); +    if( !sqlite3_malloc_failed ){ +      p->aMem = &p->aStack[n]; +      p->nMem = nMem; +      p->aVar = &p->aMem[nMem]; +      p->nVar = nVar; +      p->okVar = 0; +      p->apArg = (Mem**)&p->aVar[nVar]; +      p->azVar = (char**)&p->apArg[n]; +      p->apCsr = (Cursor**)&p->azVar[nVar]; +      p->nCursor = nCursor; +      for(n=0; n<nVar; n++){ +        p->aVar[n].flags = MEM_Null; +      } +      for(n=0; n<nMem; n++){ +        p->aMem[n].flags = MEM_Null; +      } +    } +  } + +#ifdef SQLITE_DEBUG +  if( (p->db->flags & SQLITE_VdbeListing)!=0 +    || sqlite3OsFileExists("vdbe_explain") +  ){ +    int i; +    printf("VDBE Program Listing:\n"); +    sqlite3VdbePrintSql(p); +    for(i=0; i<p->nOp; i++){ +      sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); +    } +  } +  if( sqlite3OsFileExists("vdbe_trace") ){ +    p->trace = stdout; +  } +#endif +  p->pTos = &p->aStack[-1]; +  p->pc = -1; +  p->rc = SQLITE_OK; +  p->uniqueCnt = 0; +  p->returnDepth = 0; +  p->errorAction = OE_Abort; +  p->popStack =  0; +  p->explain |= isExplain; +  p->magic = VDBE_MAGIC_RUN; +  p->nChange = 0; +#ifdef VDBE_PROFILE +  { +    int i; +    for(i=0; i<p->nOp; i++){ +      p->aOp[i].cnt = 0; +      p->aOp[i].cycles = 0; +    } +  } +#endif +} + + +/* +** Remove any elements that remain on the sorter for the VDBE given. +*/ +void sqlite3VdbeSorterReset(Vdbe *p){ +  while( p->pSort ){ +    Sorter *pSorter = p->pSort; +    p->pSort = pSorter->pNext; +    sqliteFree(pSorter->zKey); +    sqlite3VdbeMemRelease(&pSorter->data); +    sqliteFree(pSorter); +  } +} + +/* +** Free all resources allociated with AggElem pElem, an element of +** aggregate pAgg. +*/ +void freeAggElem(AggElem *pElem, Agg *pAgg){ +  int i; +  for(i=0; i<pAgg->nMem; i++){ +    Mem *pMem = &pElem->aMem[i]; +    if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){ +      sqlite3_context ctx; +      ctx.pFunc = pAgg->apFunc[i]; +      ctx.s.flags = MEM_Null; +      ctx.pAgg = pMem->z; +      ctx.cnt = pMem->i; +      ctx.isStep = 0; +      ctx.isError = 0; +      (*pAgg->apFunc[i]->xFinalize)(&ctx); +      pMem->z = ctx.pAgg; +      if( pMem->z!=0 && pMem->z!=pMem->zShort ){ +        sqliteFree(pMem->z); +      } +      sqlite3VdbeMemRelease(&ctx.s); +    }else{ +      sqlite3VdbeMemRelease(pMem); +    } +  } +  sqliteFree(pElem); +} + +/* +** Reset an Agg structure.  Delete all its contents. +** +** For installable aggregate functions, if the step function has been +** called, make sure the finalizer function has also been called.  The +** finalizer might need to free memory that was allocated as part of its +** private context.  If the finalizer has not been called yet, call it +** now. +** +** If db is NULL, then this is being called from sqliteVdbeReset(). In +** this case clean up all references to the temp-table used for +** aggregates (if it was ever opened). +** +** If db is not NULL, then this is being called from with an OP_AggReset +** opcode. Open the temp-table, if it has not already been opened and +** delete the contents of the table used for aggregate information, ready +** for the next round of aggregate processing. +*/ +int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){ +  int rc = 0; +  BtCursor *pCsr = pAgg->pCsr; + +  assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0) +         || sqlite3_malloc_failed ); + +  /* If pCsr is not NULL, then the table used for aggregate information +  ** is open. Loop through it and free the AggElem* structure pointed at +  ** by each entry. If the finalizer has not been called for an AggElem, +  ** do that too. Finally, clear the btree table itself. +  */ +  if( pCsr ){ +    int res; +    assert( pAgg->pBtree ); +    assert( pAgg->nTab>0 ); + +    rc=sqlite3BtreeFirst(pCsr, &res); +    while( res==0 && rc==SQLITE_OK ){ +      AggElem *pElem; +      rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem); +      if( res!=SQLITE_OK ){ +        return rc; +      } +      assert( pAgg->apFunc!=0 ); +      freeAggElem(pElem, pAgg); +      rc=sqlite3BtreeNext(pCsr, &res); +    } +    if( rc!=SQLITE_OK ){ +      return rc; +    } + +    sqlite3BtreeCloseCursor(pCsr); +    sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab); +  }else{  +    /* The cursor may not be open because the aggregator was never used, +    ** or it could be that it was used but there was no GROUP BY clause. +    */ +    if( pAgg->pCurrent ){ +      freeAggElem(pAgg->pCurrent, pAgg); +    } +  } + +  /* If db is not NULL and we have not yet and we have not yet opened +  ** the temporary btree then do so and create the table to store aggregate +  ** information. +  ** +  ** If db is NULL, then close the temporary btree if it is open. +  */ +  if( db ){ +    if( !pAgg->pBtree ){ +      assert( pAgg->nTab==0 ); +      rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree); +      if( rc!=SQLITE_OK ) return rc; +      sqlite3BtreeBeginTrans(pAgg->pBtree, 1); +      rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0); +      if( rc!=SQLITE_OK ) return rc; +    } +    assert( pAgg->nTab!=0 ); + +    rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1, +        sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr); +    if( rc!=SQLITE_OK ) return rc; +  }else{ +    if( pAgg->pBtree ){ +      sqlite3BtreeClose(pAgg->pBtree); +      pAgg->pBtree = 0; +      pAgg->nTab = 0; +    } +    pAgg->pCsr = 0; +  } + +  if( pAgg->apFunc ){  +    sqliteFree(pAgg->apFunc); +    pAgg->apFunc = 0; +  } +  pAgg->pCurrent = 0; +  pAgg->nMem = 0; +  pAgg->searching = 0; +  return SQLITE_OK; +} + + +/* +** Delete a keylist +*/ +void sqlite3VdbeKeylistFree(Keylist *p){ +  while( p ){ +    Keylist *pNext = p->pNext; +    sqliteFree(p); +    p = pNext; +  } +} + +/* +** Close a cursor and release all the resources that cursor happens +** to hold. +*/ +void sqlite3VdbeFreeCursor(Cursor *pCx){ +  if( pCx==0 ){ +    return; +  } +  if( pCx->pCursor ){ +    sqlite3BtreeCloseCursor(pCx->pCursor); +  } +  if( pCx->pBt ){ +    sqlite3BtreeClose(pCx->pBt); +  } +  sqliteFree(pCx->pData); +  sqliteFree(pCx->aType); +  sqliteFree(pCx); +} + +/* +** Close all cursors +*/ +static void closeAllCursors(Vdbe *p){ +  int i; +  if( p->apCsr==0 ) return; +  for(i=0; i<p->nCursor; i++){ +    sqlite3VdbeFreeCursor(p->apCsr[i]); +    p->apCsr[i] = 0; +  } +} + +/* +** Clean up the VM after execution. +** +** This routine will automatically close any cursors, lists, and/or +** sorters that were left open.  It also deletes the values of +** variables in the aVar[] array. +*/ +static void Cleanup(Vdbe *p){ +  int i; +  if( p->aStack ){ +    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack)); +    p->pTos = &p->aStack[-1]; +  } +  closeAllCursors(p); +  releaseMemArray(p->aMem, p->nMem); +  if( p->pList ){ +    sqlite3VdbeKeylistFree(p->pList); +    p->pList = 0; +  } +  if( p->contextStack ){ +    for(i=0; i<p->contextStackTop; i++){ +      sqlite3VdbeKeylistFree(p->contextStack[i].pList); +    } +    sqliteFree(p->contextStack); +  } +  sqlite3VdbeSorterReset(p); +  sqlite3VdbeAggReset(0, &p->agg, 0); +  p->contextStack = 0; +  p->contextStackDepth = 0; +  p->contextStackTop = 0; +  sqliteFree(p->zErrMsg); +  p->zErrMsg = 0; +} + +/* +** Set the number of result columns that will be returned by this SQL +** statement. This is now set at compile time, rather than during +** execution of the vdbe program so that sqlite3_column_count() can +** be called on an SQL statement before sqlite3_step(). +*/ +void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ +  Mem *pColName; +  int n; +  assert( 0==p->nResColumn ); +  p->nResColumn = nResColumn; +  n = nResColumn*2; +  p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n ); +  if( p->aColName==0 ) return; +  while( n-- > 0 ){ +    (pColName++)->flags = MEM_Null; +  } +} + +/* +** Set the name of the idx'th column to be returned by the SQL statement. +** zName must be a pointer to a nul terminated string. +** +** This call must be made after a call to sqlite3VdbeSetNumCols(). +** +** If N==P3_STATIC  it means that zName is a pointer to a constant static +** string and we can just copy the pointer. If it is P3_DYNAMIC, then  +** the string is freed using sqliteFree() when the vdbe is finished with +** it. Otherwise, N bytes of zName are copied. +*/ +int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ +  int rc; +  Mem *pColName; +  assert( idx<(2*p->nResColumn) ); +  if( sqlite3_malloc_failed ) return SQLITE_NOMEM; +  assert( p->aColName!=0 ); +  pColName = &(p->aColName[idx]); +  if( N==P3_DYNAMIC || N==P3_STATIC ){ +    rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); +  }else{ +    rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT); +  } +  if( rc==SQLITE_OK && N==P3_DYNAMIC ){ +    pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn; +    pColName->xDel = 0; +  } +  return rc; +} + +/* +** A read or write transaction may or may not be active on database handle +** db. If a transaction is active, commit it. If there is a +** write-transaction spanning more than one database file, this routine +** takes care of the master journal trickery. +*/ +static int vdbeCommit(sqlite3 *db){ +  int i; +  int nTrans = 0;  /* Number of databases with an active write-transaction */ +  int rc = SQLITE_OK; +  int needXcommit = 0; + +  for(i=0; i<db->nDb; i++){  +    Btree *pBt = db->aDb[i].pBt; +    if( pBt && sqlite3BtreeIsInTrans(pBt) ){ +      needXcommit = 1; +      if( i!=1 ) nTrans++; +    } +  } + +  /* If there are any write-transactions at all, invoke the commit hook */ +  if( needXcommit && db->xCommitCallback ){ +    int rc; +    sqlite3SafetyOff(db); +    rc = db->xCommitCallback(db->pCommitArg); +    sqlite3SafetyOn(db); +    if( rc ){ +      return SQLITE_CONSTRAINT; +    } +  } + +  /* The simple case - no more than one database file (not counting the +  ** TEMP database) has a transaction active.   There is no need for the +  ** master-journal. +  ** +  ** If the return value of sqlite3BtreeGetFilename() is a zero length +  ** string, it means the main database is :memory:.  In that case we do +  ** not support atomic multi-file commits, so use the simple case then +  ** too. +  */ +  if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){ +    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){  +      Btree *pBt = db->aDb[i].pBt; +      if( pBt ){ +        rc = sqlite3BtreeSync(pBt, 0); +      } +    } + +    /* Do the commit only if all databases successfully synced */ +    if( rc==SQLITE_OK ){ +      for(i=0; i<db->nDb; i++){ +        Btree *pBt = db->aDb[i].pBt; +        if( pBt ){ +          sqlite3BtreeCommit(pBt); +        } +      } +    } +  } + +  /* The complex case - There is a multi-file write-transaction active. +  ** This requires a master journal file to ensure the transaction is +  ** committed atomicly. +  */ +  else{ +    char *zMaster = 0;   /* File-name for the master journal */ +    char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); +    OsFile master; + +    /* Select a master journal file name */ +    do { +      u32 random; +      sqliteFree(zMaster); +      sqlite3Randomness(sizeof(random), &random); +      zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff); +      if( !zMaster ){ +        return SQLITE_NOMEM; +      } +    }while( sqlite3OsFileExists(zMaster) ); + +    /* Open the master journal. */ +    memset(&master, 0, sizeof(master)); +    rc = sqlite3OsOpenExclusive(zMaster, &master, 0); +    if( rc!=SQLITE_OK ){ +      sqliteFree(zMaster); +      return rc; +    } +  +    /* Write the name of each database file in the transaction into the new +    ** master journal file. If an error occurs at this point close +    ** and delete the master journal file. All the individual journal files +    ** still have 'null' as the master journal pointer, so they will roll +    ** back independantly if a failure occurs. +    */ +    for(i=0; i<db->nDb; i++){  +      Btree *pBt = db->aDb[i].pBt; +      if( i==1 ) continue;   /* Ignore the TEMP database */ +      if( pBt && sqlite3BtreeIsInTrans(pBt) ){ +        char const *zFile = sqlite3BtreeGetJournalname(pBt); +        if( zFile[0]==0 ) continue;  /* Ignore :memory: databases */ +        rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1); +        if( rc!=SQLITE_OK ){ +          sqlite3OsClose(&master); +          sqlite3OsDelete(zMaster); +          sqliteFree(zMaster); +          return rc; +        } +      } +    } + + +    /* Sync the master journal file. Before doing this, open the directory +    ** the master journal file is store in so that it gets synced too. +    */ +    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); +    rc = sqlite3OsOpenDirectory(zMainFile, &master); +    if( rc!=SQLITE_OK ){ +      sqlite3OsClose(&master); +      sqlite3OsDelete(zMaster); +      sqliteFree(zMaster); +      return rc; +    } +    rc = sqlite3OsSync(&master); +    if( rc!=SQLITE_OK ){ +      sqlite3OsClose(&master); +      sqliteFree(zMaster); +      return rc; +    } + +    /* Sync all the db files involved in the transaction. The same call +    ** sets the master journal pointer in each individual journal. If +    ** an error occurs here, do not delete the master journal file. +    ** +    ** If the error occurs during the first call to sqlite3BtreeSync(), +    ** then there is a chance that the master journal file will be +    ** orphaned. But we cannot delete it, in case the master journal +    ** file name was written into the journal file before the failure +    ** occured. +    */ +    for(i=0; i<db->nDb; i++){  +      Btree *pBt = db->aDb[i].pBt; +      if( pBt && sqlite3BtreeIsInTrans(pBt) ){ +        rc = sqlite3BtreeSync(pBt, zMaster); +        if( rc!=SQLITE_OK ){ +          sqlite3OsClose(&master); +          sqliteFree(zMaster); +          return rc; +        } +      } +    } +    sqlite3OsClose(&master); + +    /* Delete the master journal file. This commits the transaction. After +    ** doing this the directory is synced again before any individual +    ** transaction files are deleted. +    */ +    rc = sqlite3OsDelete(zMaster); +    assert( rc==SQLITE_OK ); +    sqliteFree(zMaster); +    zMaster = 0; +    rc = sqlite3OsSyncDirectory(zMainFile); +    if( rc!=SQLITE_OK ){ +      /* This is not good. The master journal file has been deleted, but +      ** the directory sync failed. There is no completely safe course of +      ** action from here. The individual journals contain the name of the +      ** master journal file, but there is no way of knowing if that +      ** master journal exists now or if it will exist after the operating +      ** system crash that may follow the fsync() failure. +      */ +      assert(0); +      sqliteFree(zMaster); +      return rc; +    } + +    /* All files and directories have already been synced, so the following +    ** calls to sqlite3BtreeCommit() are only closing files and deleting +    ** journals. If something goes wrong while this is happening we don't +    ** really care. The integrity of the transaction is already guaranteed, +    ** but some stray 'cold' journals may be lying around. Returning an +    ** error code won't help matters. +    */ +    for(i=0; i<db->nDb; i++){  +      Btree *pBt = db->aDb[i].pBt; +      if( pBt ){ +        sqlite3BtreeCommit(pBt); +      } +    } +  } + +  return rc; +} + +/* +** Find every active VM other than pVdbe and change its status to +** aborted.  This happens when one VM causes a rollback due to an +** ON CONFLICT ROLLBACK clause (for example).  The other VMs must be +** aborted so that they do not have data rolled out from underneath +** them leading to a segfault. +*/ +static void abortOtherActiveVdbes(Vdbe *pVdbe){ +  Vdbe *pOther; +  for(pOther=pVdbe->db->pVdbe; pOther; pOther=pOther->pNext){ +    if( pOther==pVdbe ) continue; +    if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue; +    closeAllCursors(pOther); +    pOther->aborted = 1; +  } +} + +/*  +** This routine checks that the sqlite3.activeVdbeCnt count variable +** matches the number of vdbe's in the list sqlite3.pVdbe that are +** currently active. An assertion fails if the two counts do not match. +** This is an internal self-check only - it is not an essential processing +** step. +** +** This is a no-op if NDEBUG is defined. +*/ +#ifndef NDEBUG +static void checkActiveVdbeCnt(sqlite3 *db){ +  Vdbe *p; +  int cnt = 0; +  p = db->pVdbe; +  while( p ){ +    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ +      cnt++; +    } +    p = p->pNext; +  } +  assert( cnt==db->activeVdbeCnt ); +} +#else +#define checkActiveVdbeCnt(x) +#endif + +/* +** This routine is called the when a VDBE tries to halt.  If the VDBE +** has made changes and is in autocommit mode, then commit those +** changes.  If a rollback is needed, then do the rollback. +** +** This routine is the only way to move the state of a VM from +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. +** +** Return an error code.  If the commit could not complete because of +** lock contention, return SQLITE_BUSY.  If SQLITE_BUSY is returned, it +** means the close did not happen and needs to be repeated. +*/ +int sqlite3VdbeHalt(Vdbe *p){ +  sqlite3 *db = p->db; +  int i; +  int (*xFunc)(Btree *pBt) = 0;  /* Function to call on each btree backend */ + +  if( p->magic!=VDBE_MAGIC_RUN ){ +    /* Already halted.  Nothing to do. */ +    assert( p->magic==VDBE_MAGIC_HALT ); +    return SQLITE_OK; +  } +  closeAllCursors(p); +  checkActiveVdbeCnt(db); +  if( db->autoCommit && db->activeVdbeCnt==1 ){ +    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ +      /* The auto-commit flag is true, there are no other active queries +      ** using this handle and the vdbe program was successful or hit an +      ** 'OR FAIL' constraint. This means a commit is required. +      */ +      int rc = vdbeCommit(db); +      if( rc==SQLITE_BUSY ){ +        return SQLITE_BUSY; +      }else if( rc!=SQLITE_OK ){ +        p->rc = rc; +        xFunc = sqlite3BtreeRollback; +      } +    }else{ +      xFunc = sqlite3BtreeRollback; +    } +  }else{ +    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ +      xFunc = sqlite3BtreeCommitStmt; +    }else if( p->errorAction==OE_Abort ){ +      xFunc = sqlite3BtreeRollbackStmt; +    }else{ +      xFunc = sqlite3BtreeRollback; +      db->autoCommit = 1; +      abortOtherActiveVdbes(p); +    } +  } + +  /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback, +  ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on +  ** each backend. If an error occurs and the return code is still +  ** SQLITE_OK, set the return code to the new error value. +  */ +  for(i=0; xFunc && i<db->nDb; i++){  +    int rc; +    Btree *pBt = db->aDb[i].pBt; +    if( pBt ){ +      rc = xFunc(pBt); +      if( p->rc==SQLITE_OK ) p->rc = rc; +    } +  } + +  /* If this was an INSERT, UPDATE or DELETE, set the change counter. */ +  if( p->changeCntOn ){ +    if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){ +      sqlite3VdbeSetChanges(db, p->nChange); +    }else{ +      sqlite3VdbeSetChanges(db, 0); +    } +    p->nChange = 0; +  } + +  /* Rollback or commit any schema changes that occurred. */ +  if( p->rc!=SQLITE_OK ){ +    sqlite3RollbackInternalChanges(db); +  }else if( db->flags & SQLITE_InternChanges ){ +    sqlite3CommitInternalChanges(db); +  } + +  /* We have successfully halted and closed the VM.  Record this fact. */ +  if( p->pc>=0 ){ +    db->activeVdbeCnt--; +  } +  p->magic = VDBE_MAGIC_HALT; +  checkActiveVdbeCnt(db); + +  return SQLITE_OK; +} + +/* +** Clean up a VDBE after execution but do not delete the VDBE just yet. +** Write any error messages into *pzErrMsg.  Return the result code. +** +** After this routine is run, the VDBE should be ready to be executed +** again. +** +** To look at it another way, this routine resets the state of the +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to +** VDBE_MAGIC_INIT. +*/ +int sqlite3VdbeReset(Vdbe *p){ +  if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ +    sqlite3Error(p->db, SQLITE_MISUSE, 0); +    return SQLITE_MISUSE; +  } + +  /* If the VM did not run to completion or if it encountered an +  ** error, then it might not have been halted properly.  So halt +  ** it now. +  */ +  sqlite3VdbeHalt(p); + +  /* Transfer the error code and error message from the VDBE into the +  ** main database structure. +  */ +  if( p->zErrMsg ){ +    sqlite3Error(p->db, p->rc, "%s", p->zErrMsg); +    sqliteFree(p->zErrMsg); +    p->zErrMsg = 0; +  }else if( p->rc ){ +    sqlite3Error(p->db, p->rc, 0); +  }else{ +    sqlite3Error(p->db, SQLITE_OK, 0); +  } + +  /* Reclaim all memory used by the VDBE +  */ +  Cleanup(p); + +  /* Save profiling information from this VDBE run. +  */ +  assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 ); +#ifdef VDBE_PROFILE +  { +    FILE *out = fopen("vdbe_profile.out", "a"); +    if( out ){ +      int i; +      fprintf(out, "---- "); +      for(i=0; i<p->nOp; i++){ +        fprintf(out, "%02x", p->aOp[i].opcode); +      } +      fprintf(out, "\n"); +      for(i=0; i<p->nOp; i++){ +        fprintf(out, "%6d %10lld %8lld ", +           p->aOp[i].cnt, +           p->aOp[i].cycles, +           p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 +        ); +        sqlite3VdbePrintOp(out, i, &p->aOp[i]); +      } +      fclose(out); +    } +  } +#endif +  p->magic = VDBE_MAGIC_INIT; +  p->aborted = 0; +  return p->rc; +} +  +/* +** Clean up and delete a VDBE after execution.  Return an integer which is +** the result code.  Write any error message text into *pzErrMsg. +*/ +int sqlite3VdbeFinalize(Vdbe *p){ +  int rc = SQLITE_OK; +  sqlite3 *db = p->db; + +  if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ +    rc = sqlite3VdbeReset(p); +  }else if( p->magic!=VDBE_MAGIC_INIT ){ +    /* sqlite3Error(p->db, SQLITE_MISUSE, 0); */ +    return SQLITE_MISUSE; +  } +  sqlite3VdbeDelete(p); +  if( rc==SQLITE_SCHEMA ){ +    sqlite3ResetInternalSchema(db, 0); +  } +  return rc; +} + +/* +** Call the destructor for each auxdata entry in pVdbeFunc for which +** the corresponding bit in mask is clear.  Auxdata entries beyond 31 +** are always destroyed.  To destroy all auxdata entries, call this +** routine with mask==0. +*/ +void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ +  int i; +  for(i=0; i<pVdbeFunc->nAux; i++){ +    struct AuxData *pAux = &pVdbeFunc->apAux[i]; +    if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){ +      if( pAux->xDelete ){ +        pAux->xDelete(pAux->pAux); +      } +      pAux->pAux = 0; +    } +  } +} + +/* +** Delete an entire VDBE. +*/ +void sqlite3VdbeDelete(Vdbe *p){ +  int i; +  if( p==0 ) return; +  Cleanup(p); +  if( p->pPrev ){ +    p->pPrev->pNext = p->pNext; +  }else{ +    assert( p->db->pVdbe==p ); +    p->db->pVdbe = p->pNext; +  } +  if( p->pNext ){ +    p->pNext->pPrev = p->pPrev; +  } +  if( p->aOp ){ +    for(i=0; i<p->nOp; i++){ +      Op *pOp = &p->aOp[i]; +      if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){ +        sqliteFree(pOp->p3); +      } +      if( pOp->p3type==P3_VDBEFUNC ){ +        VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; +        sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); +        sqliteFree(pVdbeFunc); +      } +    } +    sqliteFree(p->aOp); +  } +  releaseMemArray(p->aVar, p->nVar); +  sqliteFree(p->aLabel); +  sqliteFree(p->aStack); +  releaseMemArray(p->aColName, p->nResColumn*2); +  sqliteFree(p->aColName); +  p->magic = VDBE_MAGIC_DEAD; +  sqliteFree(p); +} + +/* +** If a MoveTo operation is pending on the given cursor, then do that +** MoveTo now.  Return an error code.  If no MoveTo is pending, this +** routine does nothing and returns SQLITE_OK. +*/ +int sqlite3VdbeCursorMoveto(Cursor *p){ +  if( p->deferredMoveto ){ +    int res; +    extern int sqlite3_search_count; +    assert( p->intKey ); +    if( p->intKey ){ +      sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res); +    }else{ +      sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,sizeof(i64),&res); +    } +    *p->pIncrKey = 0; +    p->lastRecno = keyToInt(p->movetoTarget); +    p->recnoIsValid = res==0; +    if( res<0 ){ +      sqlite3BtreeNext(p->pCursor, &res); +    } +    sqlite3_search_count++; +    p->deferredMoveto = 0; +    p->cacheValid = 0; +  } +  return SQLITE_OK; +} + +/* +** The following functions: +** +** sqlite3VdbeSerialType() +** sqlite3VdbeSerialTypeLen() +** sqlite3VdbeSerialRead() +** sqlite3VdbeSerialLen() +** sqlite3VdbeSerialWrite() +** +** encapsulate the code that serializes values for storage in SQLite +** data and index records. Each serialized value consists of a +** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned +** integer, stored as a varint. +** +** In an SQLite index record, the serial type is stored directly before +** the blob of data that it corresponds to. In a table record, all serial +** types are stored at the start of the record, and the blobs of data at +** the end. Hence these functions allow the caller to handle the +** serial-type and data blob seperately. +** +** The following table describes the various storage classes for data: +** +**   serial type        bytes of data      type +**   --------------     ---------------    --------------- +**      0                     0            NULL +**      1                     1            signed integer +**      2                     2            signed integer +**      3                     3            signed integer +**      4                     4            signed integer +**      5                     6            signed integer +**      6                     8            signed integer +**      7                     8            IEEE float +**     8-11                                reserved for expansion +**    N>=12 and even       (N-12)/2        BLOB +**    N>=13 and odd        (N-13)/2        text +** +*/ + +/* +** Return the serial-type for the value stored in pMem. +*/ +u32 sqlite3VdbeSerialType(Mem *pMem){ +  int flags = pMem->flags; + +  if( flags&MEM_Null ){ +    return 0; +  } +  if( flags&MEM_Int ){ +    /* Figure out whether to use 1, 2, 4 or 8 bytes. */ +    i64 i = pMem->i; +    if( i>=-127 && i<=127 ) return 1; +    if( i>=-32767 && i<=32767 ) return 2; +    if( i>=-8388607 && i<=8388607 ) return 3; +    if( i>=-2147483647 && i<=2147483647 ) return 4; +    if( i>=-140737488355328L && i<=140737488355328L ) return 5; +    return 6; +  } +  if( flags&MEM_Real ){ +    return 7; +  } +  if( flags&MEM_Str ){ +    int n = pMem->n; +    assert( n>=0 ); +    return ((n*2) + 13); +  } +  if( flags&MEM_Blob ){ +    return (pMem->n*2 + 12); +  } +  return 0; +} + +/* +** Return the length of the data corresponding to the supplied serial-type. +*/ +int sqlite3VdbeSerialTypeLen(u32 serial_type){ +  if( serial_type>=12 ){ +    return (serial_type-12)/2; +  }else{ +    static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; +    return aSize[serial_type]; +  } +} + +/* +** Write the serialized data blob for the value stored in pMem into  +** buf. It is assumed that the caller has allocated sufficient space. +** Return the number of bytes written. +*/  +int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem){ +  u32 serial_type = sqlite3VdbeSerialType(pMem); +  int len; + +  /* NULL */ +  if( serial_type==0 ){ +    return 0; +  } +  +  /* Integer and Real */ +  if( serial_type<=7 ){ +    u64 v; +    int i; +    if( serial_type==7 ){ +      v = *(u64*)&pMem->r; +    }else{ +      v = *(u64*)&pMem->i; +    } +    len = i = sqlite3VdbeSerialTypeLen(serial_type); +    while( i-- ){ +      buf[i] = (v&0xFF); +      v >>= 8; +    } +    return len; +  } +   +  /* String or blob */ +  assert( serial_type>=12 ); +  len = sqlite3VdbeSerialTypeLen(serial_type); +  memcpy(buf, pMem->z, len); +  return len; +} + +/* +** Deserialize the data blob pointed to by buf as serial type serial_type +** and store the result in pMem.  Return the number of bytes read. +*/  +int sqlite3VdbeSerialGet( +  const unsigned char *buf,     /* Buffer to deserialize from */ +  u32 serial_type,              /* Serial type to deserialize */ +  Mem *pMem                     /* Memory cell to write value into */ +){ +  int len; + +  if( serial_type==0 ){ +    /* NULL */ +    pMem->flags = MEM_Null; +    return 0; +  } +  len = sqlite3VdbeSerialTypeLen(serial_type); +  if( serial_type<=7 ){ +    /* Integer and Real */ +    if( serial_type<=4 ){ +      /* 32-bit integer type.  This is handled by a special case for +      ** performance reasons. */ +      int v = buf[0]; +      int n; +      if( v&0x80 ){ +        v |= -256; +      } +      for(n=1; n<len; n++){ +        v = (v<<8) | buf[n]; +      } +      pMem->flags = MEM_Int; +      pMem->i = v; +      return n; +    }else{ +      u64 v = 0; +      int n; + +      if( buf[0]&0x80 ){ +        v = -1; +      } +      for(n=0; n<len; n++){ +        v = (v<<8) | buf[n]; +      } +      if( serial_type==7 ){ +        pMem->flags = MEM_Real; +        pMem->r = *(double*)&v; +      }else{ +        pMem->flags = MEM_Int; +        pMem->i = *(i64*)&v; +      } +    } +  }else{ +    /* String or blob */ +    assert( serial_type>=12 ); +    pMem->z = (char *)buf; +    pMem->n = len; +    pMem->xDel = 0; +    if( serial_type&0x01 ){ +      pMem->flags = MEM_Str | MEM_Ephem; +    }else{ +      pMem->flags = MEM_Blob | MEM_Ephem; +    } +  } +  return len; +} + +/* +** This function compares the two table rows or index records specified by  +** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero +** or positive integer if {nKey1, pKey1} is less than, equal to or  +** greater than {nKey2, pKey2}.  Both Key1 and Key2 must be byte strings +** composed by the OP_MakeRecord opcode of the VDBE. +*/ +int sqlite3VdbeRecordCompare( +  void *userData, +  int nKey1, const void *pKey1,  +  int nKey2, const void *pKey2 +){ +  KeyInfo *pKeyInfo = (KeyInfo*)userData; +  u32 d1, d2;          /* Offset into aKey[] of next data element */ +  u32 idx1, idx2;      /* Offset into aKey[] of next header element */ +  u32 szHdr1, szHdr2;  /* Number of bytes in header */ +  int i = 0; +  int nField; +  int rc = 0; +  const unsigned char *aKey1 = (const unsigned char *)pKey1; +  const unsigned char *aKey2 = (const unsigned char *)pKey2; + +  Mem mem1; +  Mem mem2; +  mem1.enc = pKeyInfo->enc; +  mem2.enc = pKeyInfo->enc; +   +  idx1 = sqlite3GetVarint32(pKey1, &szHdr1); +  d1 = szHdr1; +  idx2 = sqlite3GetVarint32(pKey2, &szHdr2); +  d2 = szHdr2; +  nField = pKeyInfo->nField; +  while( idx1<szHdr1 && idx2<szHdr2 ){ +    u32 serial_type1; +    u32 serial_type2; + +    /* Read the serial types for the next element in each key. */ +    idx1 += sqlite3GetVarint32(&aKey1[idx1], &serial_type1); +    if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; +    idx2 += sqlite3GetVarint32(&aKey2[idx2], &serial_type2); +    if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break; + +    /* Assert that there is enough space left in each key for the blob of +    ** data to go with the serial type just read. This assert may fail if +    ** the file is corrupted.  Then read the value from each key into mem1 +    ** and mem2 respectively. +    */ +    d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); +    d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2); + +    rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0); +    sqlite3VdbeMemRelease(&mem1); +    sqlite3VdbeMemRelease(&mem2); +    if( rc!=0 ){ +      break; +    } +    i++; +  } + +  /* One of the keys ran out of fields, but all the fields up to that point +  ** were equal. If the incrKey flag is true, then the second key is +  ** treated as larger. +  */ +  if( rc==0 ){ +    if( pKeyInfo->incrKey ){ +      rc = -1; +    }else if( d1<nKey1 ){ +      rc = 1; +    }else if( d2<nKey2 ){ +      rc = -1; +    } +  } + +  if( pKeyInfo->aSortOrder && i<pKeyInfo->nField && pKeyInfo->aSortOrder[i] ){ +    rc = -rc; +  } + +  return rc; +} + +/* +** The argument is an index entry composed using the OP_MakeRecord opcode. +** The last entry in this record should be an integer (specifically +** an integer rowid).  This routine returns the number of bytes in +** that integer. +*/ +int sqlite3VdbeIdxRowidLen(int nKey, const u8 *aKey){ +  u32 szHdr;        /* Size of the header */ +  u32 typeRowid;    /* Serial type of the rowid */ + +  sqlite3GetVarint32(aKey, &szHdr); +  sqlite3GetVarint32(&aKey[szHdr-1], &typeRowid); +  return sqlite3VdbeSerialTypeLen(typeRowid); +} +   + +/* +** pCur points at an index entry created using the OP_MakeRecord opcode. +** Read the rowid (the last field in the record) and store it in *rowid. +** Return SQLITE_OK if everything works, or an error code otherwise. +*/ +int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ +  i64 nCellKey; +  int rc; +  u32 szHdr;        /* Size of the header */ +  u32 typeRowid;    /* Serial type of the rowid */ +  u32 lenRowid;     /* Size of the rowid */ +  Mem m, v; + +  sqlite3BtreeKeySize(pCur, &nCellKey); +  if( nCellKey<=0 ){ +    return SQLITE_CORRUPT; +  } +  rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); +  if( rc ){ +    return rc; +  } +  sqlite3GetVarint32(m.z, &szHdr); +  sqlite3GetVarint32(&m.z[szHdr-1], &typeRowid); +  lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); +  sqlite3VdbeSerialGet(&m.z[m.n-lenRowid], typeRowid, &v); +  *rowid = v.i; +  sqlite3VdbeMemRelease(&m); +  return SQLITE_OK; +} + +/* +** Compare the key of the index entry that cursor pC is point to against +** the key string in pKey (of length nKey).  Write into *pRes a number +** that is negative, zero, or positive if pC is less than, equal to, +** or greater than pKey.  Return SQLITE_OK on success. +** +** pKey is either created without a rowid or is truncated so that it +** omits the rowid at the end.  The rowid at the end of the index entry +** is ignored as well. +*/ +int sqlite3VdbeIdxKeyCompare( +  Cursor *pC,                 /* The cursor to compare against */ +  int nKey, const u8 *pKey,   /* The key to compare */ +  int *res                    /* Write the comparison result here */ +){ +  i64 nCellKey; +  int rc; +  BtCursor *pCur = pC->pCursor; +  int lenRowid; +  Mem m; + +  sqlite3BtreeKeySize(pCur, &nCellKey); +  if( nCellKey<=0 ){ +    *res = 0; +    return SQLITE_OK; +  } +  rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); +  if( rc ){ +    return rc; +  } +  lenRowid = sqlite3VdbeIdxRowidLen(m.n, m.z); +  *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey); +  sqlite3VdbeMemRelease(&m); +  return SQLITE_OK; +} + +/* +** This routine sets the value to be returned by subsequent calls to +** sqlite3_changes() on the database handle 'db'.  +*/ +void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ +  db->nChange = nChange; +  db->nTotalChange += nChange; +} + +/* +** Set a flag in the vdbe to update the change counter when it is finalised +** or reset. +*/ +void sqlite3VdbeCountChanges(Vdbe *p){ +  p->changeCntOn = 1; +} diff --git a/ext/pdo_sqlite/sqlite/src/vdbemem.c b/ext/pdo_sqlite/sqlite/src/vdbemem.c new file mode 100644 index 0000000000..c6cd94e634 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/vdbemem.c @@ -0,0 +1,724 @@ +/* +** 2004 May 26 +** +** 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 use to manipulate "Mem" structure.  A "Mem" +** stores a single value in the VDBE.  Mem is an opaque structure visible +** only within the VDBE.  Interface routines refer to a Mem using the +** name sqlite_value +*/ +#include "sqliteInt.h" +#include "os.h" +#include <ctype.h> +#include "vdbeInt.h" + +/* +** If pMem is an object with a valid string representation, this routine +** ensures the internal encoding for the string representation is +** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. +** +** If pMem is not a string object, or the encoding of the string +** representation is already stored using the requested encoding, then this +** routine is a no-op. +** +** SQLITE_OK is returned if the conversion is successful (or not required). +** SQLITE_NOMEM may be returned if a malloc() fails during conversion +** between formats. +*/ +int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ +  if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ +    return SQLITE_OK; +  } +  return sqlite3VdbeMemTranslate(pMem, desiredEnc); +} + +/* +** Make the given Mem object MEM_Dyn. +** +** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. +*/ +int sqlite3VdbeMemDynamicify(Mem *pMem){ +  int n = pMem->n; +  u8 *z; +  if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){ +    return SQLITE_OK; +  } +  assert( (pMem->flags & MEM_Dyn)==0 ); +  assert( pMem->flags & (MEM_Str|MEM_Blob) ); +  z = sqliteMallocRaw( n+2 ); +  if( z==0 ){ +    return SQLITE_NOMEM; +  } +  pMem->flags |= MEM_Dyn|MEM_Term; +  pMem->xDel = 0; +  memcpy(z, pMem->z, n ); +  z[n] = 0; +  z[n+1] = 0; +  pMem->z = z; +  pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short); +  return SQLITE_OK; +} + +/* +** Make the given Mem object either MEM_Short or MEM_Dyn so that bytes +** of the Mem.z[] array can be modified. +** +** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. +*/ +int sqlite3VdbeMemMakeWriteable(Mem *pMem){ +  int n; +  u8 *z; +  if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){ +    return SQLITE_OK; +  } +  assert( (pMem->flags & MEM_Dyn)==0 ); +  assert( pMem->flags & (MEM_Str|MEM_Blob) ); +  if( (n = pMem->n)+2<sizeof(pMem->zShort) ){ +    z = pMem->zShort; +    pMem->flags |= MEM_Short|MEM_Term; +  }else{ +    z = sqliteMallocRaw( n+2 ); +    if( z==0 ){ +      return SQLITE_NOMEM; +    } +    pMem->flags |= MEM_Dyn|MEM_Term; +    pMem->xDel = 0; +  } +  memcpy(z, pMem->z, n ); +  z[n] = 0; +  z[n+1] = 0; +  pMem->z = z; +  pMem->flags &= ~(MEM_Ephem|MEM_Static); +  return SQLITE_OK; +} + +/* +** Make sure the given Mem is \u0000 terminated. +*/ +int sqlite3VdbeMemNulTerminate(Mem *pMem){ +  /* In SQLite, a string without a nul terminator occurs when a string +  ** is loaded from disk (in this case the memory management is ephemeral), +  ** or when it is supplied by the user as a bound variable or function +  ** return value. Therefore, the memory management of the string must be +  ** either ephemeral, static or controlled by a user-supplied destructor. +  */ +  assert(                          +    !(pMem->flags&MEM_Str) ||                /* it's not a string, or      */ +    (pMem->flags&MEM_Term) ||                /* it's nul term. already, or */ +    (pMem->flags&(MEM_Ephem|MEM_Static)) ||  /* it's static or ephem, or   */ +    (pMem->flags&MEM_Dyn && pMem->xDel)      /* external management        */ +  ); +  if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){ +    return SQLITE_OK;   /* Nothing to do */ +  } + +  if( pMem->flags & (MEM_Static|MEM_Ephem) ){ +    return sqlite3VdbeMemMakeWriteable(pMem); +  }else{ +    char *z = sqliteMalloc(pMem->n+2); +    if( !z ) return SQLITE_NOMEM; +    memcpy(z, pMem->z, pMem->n); +    z[pMem->n] = 0; +    z[pMem->n+1] = 0; +    pMem->xDel(pMem->z); +    pMem->xDel = 0; +    pMem->z = z; +  } +  return SQLITE_OK; +} + +/* +** Add MEM_Str to the set of representations for the given Mem.  Numbers +** are converted using sqlite3_snprintf().  Converting a BLOB to a string +** is a no-op. +** +** Existing representations MEM_Int and MEM_Real are *not* invalidated. +** +** A MEM_Null value will never be passed to this function. This function is +** used for converting values to text for returning to the user (i.e. via +** sqlite3_value_text()), or for ensuring that values to be used as btree +** keys are strings. In the former case a NULL pointer is returned the +** user and the later is an internal programming error. +*/ +int sqlite3VdbeMemStringify(Mem *pMem, int enc){ +  int rc = SQLITE_OK; +  int fg = pMem->flags; +  u8 *z = pMem->zShort; + +  assert( !(fg&(MEM_Str|MEM_Blob)) ); +  assert( fg&(MEM_Int|MEM_Real) ); + +  /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 +  ** string representation of the value. Then, if the required encoding +  ** is UTF-16le or UTF-16be do a translation. +  **  +  ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. +  */ +  if( fg & MEM_Real ){ +    sqlite3_snprintf(NBFS, z, "%.15g", pMem->r); +  }else{ +    assert( fg & MEM_Int ); +    sqlite3_snprintf(NBFS, z, "%lld", pMem->i); +  } +  pMem->n = strlen(z); +  pMem->z = z; +  pMem->enc = SQLITE_UTF8; +  pMem->flags |= MEM_Str | MEM_Short | MEM_Term; +  sqlite3VdbeChangeEncoding(pMem, enc); +  return rc; +} + +/* +** Release any memory held by the Mem. This may leave the Mem in an +** inconsistent state, for example with (Mem.z==0) and +** (Mem.type==SQLITE_TEXT). +*/ +void sqlite3VdbeMemRelease(Mem *p){ +  if( p->flags & MEM_Dyn ){ +    if( p->xDel ){ +      p->xDel((void *)p->z); +    }else{ +      sqliteFree(p->z); +    } +    p->z = 0; +    p->xDel = 0; +  } +} + +/* +** Return some kind of integer value which is the best we can do +** at representing the value that *pMem describes as an integer. +** If pMem is an integer, then the value is exact.  If pMem is +** a floating-point then the value returned is the integer part. +** If pMem is a string or blob, then we make an attempt to convert +** it into a integer and return that.  If pMem is NULL, return 0. +** +** If pMem is a string, its encoding might be changed. +*/ +i64 sqlite3VdbeIntValue(Mem *pMem){ +  int flags = pMem->flags; +  if( flags & MEM_Int ){ +    return pMem->i; +  }else if( flags & MEM_Real ){ +    return (i64)pMem->r; +  }else if( flags & (MEM_Str|MEM_Blob) ){ +    i64 value; +    if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) +       || sqlite3VdbeMemNulTerminate(pMem) ){ +      return SQLITE_NOMEM; +    } +    assert( pMem->z ); +    sqlite3atoi64(pMem->z, &value); +    return value; +  }else{ +    return 0; +  } +} + +/* +** Convert pMem to type integer.  Invalidate any prior representations. +*/ +int sqlite3VdbeMemIntegerify(Mem *pMem){ +  pMem->i = sqlite3VdbeIntValue(pMem); +  sqlite3VdbeMemRelease(pMem); +  pMem->flags = MEM_Int; +  return SQLITE_OK; +} + +/* +** Return the best representation of pMem that we can get into a +** double.  If pMem is already a double or an integer, return its +** value.  If it is a string or blob, try to convert it to a double. +** If it is a NULL, return 0.0. +*/ +double sqlite3VdbeRealValue(Mem *pMem){ +  if( pMem->flags & MEM_Real ){ +    return pMem->r; +  }else if( pMem->flags & MEM_Int ){ +    return (double)pMem->i; +  }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ +    if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) +       || sqlite3VdbeMemNulTerminate(pMem) ){ +      return SQLITE_NOMEM; +    } +    assert( pMem->z ); +    return sqlite3AtoF(pMem->z, 0); +  }else{ +    return 0.0; +  } +} + +/* +** Convert pMem so that it is of type MEM_Real.  Invalidate any +** prior representations. +*/ +int sqlite3VdbeMemRealify(Mem *pMem){ +  pMem->r = sqlite3VdbeRealValue(pMem); +  sqlite3VdbeMemRelease(pMem); +  pMem->flags = MEM_Real; +  return SQLITE_OK; +} + +/* +** Delete any previous value and set the value stored in *pMem to NULL. +*/ +void sqlite3VdbeMemSetNull(Mem *pMem){ +  sqlite3VdbeMemRelease(pMem); +  pMem->flags = MEM_Null; +  pMem->type = SQLITE_NULL; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type INTEGER. +*/ +void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ +  sqlite3VdbeMemRelease(pMem); +  pMem->i = val; +  pMem->flags = MEM_Int; +  pMem->type = SQLITE_INTEGER; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type REAL. +*/ +void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ +  sqlite3VdbeMemRelease(pMem); +  pMem->r = val; +  pMem->flags = MEM_Real; +  pMem->type = SQLITE_FLOAT; +} + +/* +** Make an shallow copy of pFrom into pTo.  Prior contents of +** pTo are overwritten.  The pFrom->z field is not duplicated.  If +** pFrom->z is used, then pTo->z points to the same thing as pFrom->z +** and flags gets srcType (either MEM_Ephem or MEM_Static). +*/ +void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ +  memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort)); +  pTo->xDel = 0; +  if( pTo->flags & (MEM_Str|MEM_Blob) ){ +    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem); +    assert( srcType==MEM_Ephem || srcType==MEM_Static ); +    pTo->flags |= srcType; +  } +} + +/* +** Make a full copy of pFrom into pTo.  Prior contents of pTo are +** freed before the copy is made. +*/ +int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ +  int rc; +  if( pTo->flags & MEM_Dyn ){ +    sqlite3VdbeMemRelease(pTo); +  } +  sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem); +  if( pTo->flags & MEM_Ephem ){ +    rc = sqlite3VdbeMemMakeWriteable(pTo); +  }else{ +    rc = SQLITE_OK; +  } +  return rc; +} + +/* +** Transfer the contents of pFrom to pTo. Any existing value in pTo is +** freed. If pFrom contains ephemeral data, a copy is made. +** +** pFrom contains an SQL NULL when this routine returns.  SQLITE_NOMEM +** might be returned if pFrom held ephemeral data and we were unable +** to allocate enough space to make a copy. +*/ +int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ +  int rc; +  if( pTo->flags & MEM_Dyn ){ +    sqlite3VdbeMemRelease(pTo); +  } +  memcpy(pTo, pFrom, sizeof(Mem)); +  if( pFrom->flags & MEM_Short ){ +    pTo->z = pTo->zShort; +  } +  pFrom->flags = MEM_Null; +  pFrom->xDel = 0; +  if( pTo->flags & MEM_Ephem ){ +    rc = sqlite3VdbeMemMakeWriteable(pTo); +  }else{ +    rc = SQLITE_OK; +  } +  return rc; +} + +/* +** Change the value of a Mem to be a string or a BLOB. +*/ +int sqlite3VdbeMemSetStr( +  Mem *pMem,          /* Memory cell to set to string value */ +  const char *z,      /* String pointer */ +  int n,              /* Bytes in string, or negative */ +  u8 enc,             /* Encoding of z.  0 for BLOBs */ +  void (*xDel)(void*) /* Destructor function */ +){ +  sqlite3VdbeMemRelease(pMem); +  if( !z ){ +    pMem->flags = MEM_Null; +    pMem->type = SQLITE_NULL; +    return SQLITE_OK; +  } + +  pMem->z = (char *)z; +  if( xDel==SQLITE_STATIC ){ +    pMem->flags = MEM_Static; +  }else if( xDel==SQLITE_TRANSIENT ){ +    pMem->flags = MEM_Ephem; +  }else{ +    pMem->flags = MEM_Dyn; +    pMem->xDel = xDel; +  } + +  pMem->enc = enc; +  pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT; +  pMem->n = n; + +  switch( enc ){ +    case 0: +      pMem->flags |= MEM_Blob; +      break; + +    case SQLITE_UTF8: +      pMem->flags |= MEM_Str; +      if( n<0 ){ +        pMem->n = strlen(z); +        pMem->flags |= MEM_Term; +      } +      break; + +    case SQLITE_UTF16LE: +    case SQLITE_UTF16BE: +      pMem->flags |= MEM_Str; +      if( pMem->n<0 ){ +        pMem->n = sqlite3utf16ByteLen(pMem->z,-1); +        pMem->flags |= MEM_Term; +      } +      if( sqlite3VdbeMemHandleBom(pMem) ){ +        return SQLITE_NOMEM; +      } +      break; + +    default: +      assert(0); +  } +  if( pMem->flags&MEM_Ephem ){ +    return sqlite3VdbeMemMakeWriteable(pMem); +  } +  return SQLITE_OK; +} + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ +  int rc; +  int f1, f2; +  int combined_flags; + +  /* Interchange pMem1 and pMem2 if the collating sequence specifies +  ** DESC order. +  */ +  f1 = pMem1->flags; +  f2 = pMem2->flags; +  combined_flags = f1|f2; +  +  /* If one value is NULL, it is less than the other. If both values +  ** are NULL, return 0. +  */ +  if( combined_flags&MEM_Null ){ +    return (f2&MEM_Null) - (f1&MEM_Null); +  } + +  /* If one value is a number and the other is not, the number is less. +  ** If both are numbers, compare as reals if one is a real, or as integers +  ** if both values are integers. +  */ +  if( combined_flags&(MEM_Int|MEM_Real) ){ +    if( !(f1&(MEM_Int|MEM_Real)) ){ +      return 1; +    } +    if( !(f2&(MEM_Int|MEM_Real)) ){ +      return -1; +    } +    if( (f1 & f2 & MEM_Int)==0 ){ +      double r1, r2; +      if( (f1&MEM_Real)==0 ){ +        r1 = pMem1->i; +      }else{ +        r1 = pMem1->r; +      } +      if( (f2&MEM_Real)==0 ){ +        r2 = pMem2->i; +      }else{ +        r2 = pMem2->r; +      } +      if( r1<r2 ) return -1; +      if( r1>r2 ) return 1; +      return 0; +    }else{ +      assert( f1&MEM_Int ); +      assert( f2&MEM_Int ); +      if( pMem1->i < pMem2->i ) return -1; +      if( pMem1->i > pMem2->i ) return 1; +      return 0; +    } +  } + +  /* If one value is a string and the other is a blob, the string is less. +  ** If both are strings, compare using the collating functions. +  */ +  if( combined_flags&MEM_Str ){ +    if( (f1 & MEM_Str)==0 ){ +      return 1; +    } +    if( (f2 & MEM_Str)==0 ){ +      return -1; +    } + +    assert( pMem1->enc==pMem2->enc ); +    assert( pMem1->enc==SQLITE_UTF8 ||  +            pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); + +    /* This assert may fail if the collation sequence is deleted after this +    ** vdbe program is compiled. The documentation defines this as an +    ** undefined condition. A crash is usual result. +    */ +    assert( !pColl || pColl->xCmp ); + +    if( pColl ){ +      if( pMem1->enc==pColl->enc ){ +        return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); +      }else{ +        u8 origEnc = pMem1->enc; +        rc = pColl->xCmp( +          pColl->pUser, +          sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc), +          sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc), +          sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc), +          sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc) +        ); +        sqlite3ValueBytes((sqlite3_value*)pMem1, origEnc); +        sqlite3ValueText((sqlite3_value*)pMem1, origEnc); +        sqlite3ValueBytes((sqlite3_value*)pMem2, origEnc); +        sqlite3ValueText((sqlite3_value*)pMem2, origEnc); +        return rc; +      } +    } +    /* If a NULL pointer was passed as the collate function, fall through +    ** to the blob case and use memcmp().  */ +  } +  +  /* Both values must be blobs.  Compare using memcmp().  */ +  rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); +  if( rc==0 ){ +    rc = pMem1->n - pMem2->n; +  } +  return rc; +} + +/* +** Move data out of a btree key or data field and into a Mem structure. +** The data or key is taken from the entry that pCur is currently pointing +** to.  offset and amt determine what portion of the data or key to retrieve. +** key is true to get the key or false to get data.  The result is written +** into the pMem element. +** +** The pMem structure is assumed to be uninitialized.  Any prior content +** is overwritten without being freed. +** +** If this routine fails for any reason (malloc returns NULL or unable +** to read from the disk) then the pMem is left in an inconsistent state. +*/ +int sqlite3VdbeMemFromBtree( +  BtCursor *pCur,   /* Cursor pointing at record to retrieve. */ +  int offset,       /* Offset from the start of data to return bytes from. */ +  int amt,          /* Number of bytes to return. */ +  int key,          /* If true, retrieve from the btree key, not data. */ +  Mem *pMem         /* OUT: Return data in this Mem structure. */ +){ +  char *zData;      /* Data from the btree layer */ +  int available;    /* Number of bytes available on the local btree page */ + +  if( key ){ +    zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); +  }else{ +    zData = (char *)sqlite3BtreeDataFetch(pCur, &available); +  } + +  pMem->n = amt; +  if( offset+amt<=available ){ +    pMem->z = &zData[offset]; +    pMem->flags = MEM_Blob|MEM_Ephem; +  }else{ +    int rc; +    if( amt>NBFS-2 ){ +      zData = (char *)sqliteMallocRaw(amt+2); +      if( !zData ){ +        return SQLITE_NOMEM; +      } +      pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; +      pMem->xDel = 0; +    }else{ +      zData = &(pMem->zShort[0]); +      pMem->flags = MEM_Blob|MEM_Short|MEM_Term; +    } +    pMem->z = zData; +    pMem->enc = 0; +    pMem->type = SQLITE_BLOB; + +    if( key ){ +      rc = sqlite3BtreeKey(pCur, offset, amt, zData); +    }else{ +      rc = sqlite3BtreeData(pCur, offset, amt, zData); +    } +    zData[amt] = 0; +    zData[amt+1] = 0; +    if( rc!=SQLITE_OK ){ +      if( amt>NBFS ){ +        sqliteFree(zData); +      } +      return rc; +    } +  } + +  return SQLITE_OK; +} + +#ifndef NDEBUG +/* +** Perform various checks on the memory cell pMem. An assert() will +** fail if pMem is internally inconsistent. +*/ +void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){ +  int flags = pMem->flags; +  assert( flags!=0 );  /* Must define some type */ +  if( pMem->flags & (MEM_Str|MEM_Blob) ){ +    int x = pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); +    assert( x!=0 );            /* Strings must define a string subtype */ +    assert( (x & (x-1))==0 );  /* Only one string subtype can be defined */ +    assert( pMem->z!=0 );      /* Strings must have a value */ +    /* Mem.z points to Mem.zShort iff the subtype is MEM_Short */ +    assert( (pMem->flags & MEM_Short)==0 || pMem->z==pMem->zShort ); +    assert( (pMem->flags & MEM_Short)!=0 || pMem->z!=pMem->zShort ); +    /* No destructor unless there is MEM_Dyn */ +    assert( pMem->xDel==0 || (pMem->flags & MEM_Dyn)!=0 ); + +    if( (flags & MEM_Str) ){ +      assert( pMem->enc==SQLITE_UTF8 ||  +              pMem->enc==SQLITE_UTF16BE || +              pMem->enc==SQLITE_UTF16LE  +      ); +      /* If the string is UTF-8 encoded and nul terminated, then pMem->n +      ** must be the length of the string.  (Later:)  If the database file +      ** has been corrupted, '\000' characters might have been inserted +      ** into the middle of the string.  In that case, the strlen() might +      ** be less. +      */ +      if( pMem->enc==SQLITE_UTF8 && (flags & MEM_Term) ){  +        assert( strlen(pMem->z)<=pMem->n ); +        assert( pMem->z[pMem->n]==0 ); +      } +    } +  }else{ +    /* Cannot define a string subtype for non-string objects */ +    assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); +    assert( pMem->xDel==0 ); +  } +  /* MEM_Null excludes all other types */ +  assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 +          || (pMem->flags&MEM_Null)==0 ); +  if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){ +    assert( pMem->r==pMem->i ); +  } +} +#endif + +/* This function is only available internally, it is not part of the +** external API. It works in a similar way to sqlite3_value_text(), +** except the data returned is in the encoding specified by the second +** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or +** SQLITE_UTF8. +*/ +const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ +  if( !pVal ) return 0; +  assert( enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE || enc==SQLITE_UTF8); + +  if( pVal->flags&MEM_Null ){ +    return 0; +  } +  if( pVal->flags&MEM_Str ){ +    sqlite3VdbeChangeEncoding(pVal, enc); +  }else if( !(pVal->flags&MEM_Blob) ){ +    sqlite3VdbeMemStringify(pVal, enc); +  } +  return (const void *)(pVal->z); +} + +/* +** Create a new sqlite3_value object. +*/ +sqlite3_value* sqlite3ValueNew(){ +  Mem *p = sqliteMalloc(sizeof(*p)); +  if( p ){ +    p->flags = MEM_Null; +    p->type = SQLITE_NULL; +  } +  return p; +} + +/* +** Change the string value of an sqlite3_value object +*/ +void sqlite3ValueSetStr( +  sqlite3_value *v,  +  int n,  +  const void *z,  +  u8 enc, +  void (*xDel)(void*) +){ +  if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); +} + +/* +** Free an sqlite3_value object +*/ +void sqlite3ValueFree(sqlite3_value *v){ +  if( !v ) return; +  sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC); +  sqliteFree(v); +} + +/* +** Return the number of bytes in the sqlite3_value object assuming +** that it uses the encoding "enc" +*/ +int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ +  Mem *p = (Mem*)pVal; +  if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ +    return p->n; +  } +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/src/where.c b/ext/pdo_sqlite/sqlite/src/where.c new file mode 100644 index 0000000000..08c174e934 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/where.c @@ -0,0 +1,1210 @@ +/* +** 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 module contains C code that generates VDBE code used to process +** the WHERE clause of SQL statements. +** +** $Id$ +*/ +#include "sqliteInt.h" + +/* +** The query generator uses an array of instances of this structure to +** help it analyze the subexpressions of the WHERE clause.  Each WHERE +** clause subexpression is separated from the others by an AND operator. +*/ +typedef struct ExprInfo ExprInfo; +struct ExprInfo { +  Expr *p;                /* Pointer to the subexpression */ +  u8 indexable;           /* True if this subexprssion is usable by an index */ +  short int idxLeft;      /* p->pLeft is a column in this table number. -1 if +                          ** p->pLeft is not the column of any table */ +  short int idxRight;     /* p->pRight is a column in this table number. -1 if +                          ** p->pRight is not the column of any table */ +  unsigned prereqLeft;    /* Bitmask of tables referenced by p->pLeft */ +  unsigned prereqRight;   /* Bitmask of tables referenced by p->pRight */ +  unsigned prereqAll;     /* Bitmask of tables referenced by p */ +}; + +/* +** An instance of the following structure keeps track of a mapping +** between VDBE cursor numbers and bitmasks.  The VDBE cursor numbers +** are small integers contained in SrcList_item.iCursor and Expr.iTable +** fields.  For any given WHERE clause, we want to track which cursors +** are being used, so we assign a single bit in a 32-bit word to track +** that cursor.  Then a 32-bit integer is able to show the set of all +** cursors being used. +*/ +typedef struct ExprMaskSet ExprMaskSet; +struct ExprMaskSet { +  int n;          /* Number of assigned cursor values */ +  int ix[31];     /* Cursor assigned to each bit */ +}; + +/* +** Determine the number of elements in an array. +*/ +#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0])) + +/* +** This routine is used to divide the WHERE expression into subexpressions +** separated by the AND operator. +** +** aSlot[] is an array of subexpressions structures. +** There are nSlot spaces left in this array.  This routine attempts to +** split pExpr into subexpressions and fills aSlot[] with those subexpressions. +** The return value is the number of slots filled. +*/ +static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){ +  int cnt = 0; +  if( pExpr==0 || nSlot<1 ) return 0; +  if( nSlot==1 || pExpr->op!=TK_AND ){ +    aSlot[0].p = pExpr; +    return 1; +  } +  if( pExpr->pLeft->op!=TK_AND ){ +    aSlot[0].p = pExpr->pLeft; +    cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight); +  }else{ +    cnt = exprSplit(nSlot, aSlot, pExpr->pLeft); +    cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight); +  } +  return cnt; +} + +/* +** Initialize an expression mask set +*/ +#define initMaskSet(P)  memset(P, 0, sizeof(*P)) + +/* +** Return the bitmask for the given cursor.  Assign a new bitmask +** if this is the first time the cursor has been seen. +*/ +static int getMask(ExprMaskSet *pMaskSet, int iCursor){ +  int i; +  for(i=0; i<pMaskSet->n; i++){ +    if( pMaskSet->ix[i]==iCursor ) return 1<<i; +  } +  if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){ +    pMaskSet->n++; +    pMaskSet->ix[i] = iCursor; +    return 1<<i; +  } +  return 0; +} + +/* +** Destroy an expression mask set +*/ +#define freeMaskSet(P)   /* NO-OP */ + +/* +** This routine walks (recursively) an expression tree and generates +** a bitmask indicating which tables are used in that expression +** tree. +** +** In order for this routine to work, the calling function must have +** previously invoked sqlite3ExprResolveIds() on the expression.  See +** the header comment on that routine for additional information. +** The sqlite3ExprResolveIds() routines looks for column names and +** sets their opcodes to TK_COLUMN and their Expr.iTable fields to +** the VDBE cursor number of the table. +*/ +static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){ +  unsigned int mask = 0; +  if( p==0 ) return 0; +  if( p->op==TK_COLUMN ){ +    mask = getMask(pMaskSet, p->iTable); +    if( mask==0 ) mask = -1; +    return mask; +  } +  if( p->pRight ){ +    mask = exprTableUsage(pMaskSet, p->pRight); +  } +  if( p->pLeft ){ +    mask |= exprTableUsage(pMaskSet, p->pLeft); +  } +  if( p->pList ){ +    int i; +    for(i=0; i<p->pList->nExpr; i++){ +      mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr); +    } +  } +  return mask; +} + +/* +** Return TRUE if the given operator is one of the operators that is +** allowed for an indexable WHERE clause.  The allowed operators are +** "=", "<", ">", "<=", ">=", and "IN". +*/ +static int allowedOp(int op){ +  assert( TK_GT==TK_LE-1 && TK_LE==TK_LT-1 && TK_LT==TK_GE-1 && TK_EQ==TK_GT-1); +  return op==TK_IN || (op>=TK_EQ && op<=TK_GE); +} + +/* +** Swap two integers. +*/ +#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} + +/* +** Return the index in the SrcList that uses cursor iCur.  If iCur is +** used by the first entry in SrcList return 0.  If iCur is used by +** the second entry return 1.  And so forth. +** +** SrcList is the set of tables in the FROM clause in the order that +** they will be processed.  The value returned here gives us an index +** of which tables will be processed first. +*/ +static int tableOrder(SrcList *pList, int iCur){ +  int i; +  for(i=0; i<pList->nSrc; i++){ +    if( pList->a[i].iCursor==iCur ) return i; +  } +  return -1; +} + +/* +** The input to this routine is an ExprInfo structure with only the +** "p" field filled in.  The job of this routine is to analyze the +** subexpression and populate all the other fields of the ExprInfo +** structure. +*/ +static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){ +  Expr *pExpr = pInfo->p; +  pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); +  pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); +  pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr); +  pInfo->indexable = 0; +  pInfo->idxLeft = -1; +  pInfo->idxRight = -1; +  if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){ +    if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){ +      pInfo->idxRight = pExpr->pRight->iTable; +      pInfo->indexable = 1; +    } +    if( pExpr->pLeft->op==TK_COLUMN ){ +      pInfo->idxLeft = pExpr->pLeft->iTable; +      pInfo->indexable = 1; +    } +  } +  if( pInfo->indexable ){ +    assert( pInfo->idxLeft!=pInfo->idxRight ); + +    /* We want the expression to be of the form "X = expr", not "expr = X". +    ** So flip it over if necessary.  If the expression is "X = Y", then +    ** we want Y to come from an earlier table than X. +    ** +    ** The collating sequence rule is to always choose the left expression. +    ** So if we do a flip, we also have to move the collating sequence. +    */ +    if( tableOrder(pSrc,pInfo->idxLeft)<tableOrder(pSrc,pInfo->idxRight) ){ +      assert( pExpr->op!=TK_IN ); +      SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); +      SWAP(Expr*,pExpr->pRight,pExpr->pLeft); +      if( pExpr->op>=TK_GT ){ +        assert( TK_LT==TK_GT+2 ); +        assert( TK_GE==TK_LE+2 ); +        assert( TK_GT>TK_EQ ); +        assert( TK_GT<TK_LE ); +        assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); +        pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; +      } +      SWAP(unsigned, pInfo->prereqLeft, pInfo->prereqRight); +      SWAP(short int, pInfo->idxLeft, pInfo->idxRight); +    } +  }       + +} + +/* +** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the +** left-most table in the FROM clause of that same SELECT statement and +** the table has a cursor number of "base". +** +** This routine attempts to find an index for pTab that generates the +** correct record sequence for the given ORDER BY clause.  The return value +** is a pointer to an index that does the job.  NULL is returned if the +** table has no index that will generate the correct sort order. +** +** If there are two or more indices that generate the correct sort order +** and pPreferredIdx is one of those indices, then return pPreferredIdx. +** +** nEqCol is the number of columns of pPreferredIdx that are used as +** equality constraints.  Any index returned must have exactly this same +** set of columns.  The ORDER BY clause only matches index columns beyond the +** the first nEqCol columns. +** +** All terms of the ORDER BY clause must be either ASC or DESC.  The +** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is +** set to 0 if the ORDER BY clause is all ASC. +*/ +static Index *findSortingIndex( +  Parse *pParse, +  Table *pTab,            /* The table to be sorted */ +  int base,               /* Cursor number for pTab */ +  ExprList *pOrderBy,     /* The ORDER BY clause */ +  Index *pPreferredIdx,   /* Use this index, if possible and not NULL */ +  int nEqCol,             /* Number of index columns used with == constraints */ +  int *pbRev              /* Set to 1 if ORDER BY is DESC */ +){ +  int i, j; +  Index *pMatch; +  Index *pIdx; +  int sortOrder; +  sqlite3 *db = pParse->db; + +  assert( pOrderBy!=0 ); +  assert( pOrderBy->nExpr>0 ); +  sortOrder = pOrderBy->a[0].sortOrder; +  for(i=0; i<pOrderBy->nExpr; i++){ +    Expr *p; +    if( pOrderBy->a[i].sortOrder!=sortOrder ){ +      /* Indices can only be used if all ORDER BY terms are either +      ** DESC or ASC.  Indices cannot be used on a mixture. */ +      return 0; +    } +    p = pOrderBy->a[i].pExpr; +    if( p->op!=TK_COLUMN || p->iTable!=base ){ +      /* Can not use an index sort on anything that is not a column in the +      ** left-most table of the FROM clause */ +      return 0; +    } +  } + +  /* If we get this far, it means the ORDER BY clause consists only of +  ** ascending columns in the left-most table of the FROM clause.  Now +  ** check for a matching index. +  */ +  pMatch = 0; +  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +    int nExpr = pOrderBy->nExpr; +    if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue; +    for(i=j=0; i<nEqCol; i++){ +      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[j].pExpr); +      if( !pColl ) pColl = db->pDfltColl; +      if( pPreferredIdx->aiColumn[i]!=pIdx->aiColumn[i] ) break; +      if( pPreferredIdx->keyInfo.aColl[i]!=pIdx->keyInfo.aColl[i] ) break; +      if( j<nExpr &&  +          pOrderBy->a[j].pExpr->iColumn==pIdx->aiColumn[i] && +          pColl==pIdx->keyInfo.aColl[i] +      ){  +        j++;  +      } +    } +    if( i<nEqCol ) continue; +    for(i=0; i+j<nExpr; i++){ +      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[i+j].pExpr); +      if( !pColl ) pColl = db->pDfltColl; +      if( pOrderBy->a[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] || +          pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break; +    } +    if( i+j>=nExpr ){ +      pMatch = pIdx; +      if( pIdx==pPreferredIdx ) break; +    } +  } +  if( pMatch && pbRev ){ +    *pbRev = sortOrder==SQLITE_SO_DESC; +  } +  return pMatch; +} + +/* +** Disable a term in the WHERE clause.  Except, do not disable the term +** if it controls a LEFT OUTER JOIN and it did not originate in the ON +** or USING clause of that join. +** +** Consider the term t2.z='ok' in the following queries: +** +**   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' +**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' +**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' +** +** The t2.z='ok' is disabled in the in (2) because it did not originate +** in the ON clause.  The term is disabled in (3) because it is not part +** of a LEFT OUTER JOIN.  In (1), the term is not disabled. +** +** Disabling a term causes that term to not be tested in the inner loop +** of the join.  Disabling is an optimization.  We would get the correct +** results if nothing were ever disabled, but joins might run a little +** slower.  The trick is to disable as much as we can without disabling +** too much.  If we disabled in (1), we'd get the wrong answer. +** See ticket #813. +*/ +static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){ +  Expr *pExpr = *ppExpr; +  if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){ +    *ppExpr = 0; +  } +} + +/* +** Generate code that builds a probe for an index.  Details: +** +**    *  Check the top nColumn entries on the stack.  If any +**       of those entries are NULL, jump immediately to brk, +**       which is the loop exit, since no index entry will match +**       if any part of the key is NULL. +** +**    *  Construct a probe entry from the top nColumn entries in +**       the stack with affinities appropriate for index pIdx. +*/ +static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ +  sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); +  sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); +  sqlite3VdbeAddOp(v, OP_Goto, 0, brk); +  sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); +  sqlite3IndexAffinityStr(v, pIdx); +} + +/* +** Generate code for an equality term of the WHERE clause.  An equality +** term can be either X=expr  or X IN (...).   pTerm is the X.   +*/ +static void codeEqualityTerm( +  Parse *pParse,      /* The parsing context */ +  ExprInfo *pTerm,    /* The term of the WHERE clause to be coded */ +  int brk,            /* Jump here to abandon the loop */ +  WhereLevel *pLevel  /* When level of the FROM clause we are working on */ +){ +  Expr *pX = pTerm->p; +  if( pX->op!=TK_IN ){ +    assert( pX->op==TK_EQ ); +    sqlite3ExprCode(pParse, pX->pRight); +  }else{ +    int iTab = pX->iTable; +    Vdbe *v = pParse->pVdbe; +    sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); +    sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); +    pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, iTab, 0); +    pLevel->inOp = OP_Next; +    pLevel->inP1 = iTab; +  } +  disableTerm(pLevel, &pTerm->p); +} + + +/* +** Generate the beginning of the loop used for WHERE clause processing. +** The return value is a pointer to an (opaque) structure that contains +** information needed to terminate the loop.  Later, the calling routine +** should invoke sqlite3WhereEnd() with the return value of this function +** in order to complete the WHERE clause processing. +** +** If an error occurs, this routine returns NULL. +** +** The basic idea is to do a nested loop, one loop for each table in +** the FROM clause of a select.  (INSERT and UPDATE statements are the +** same as a SELECT with only a single table in the FROM clause.)  For +** example, if the SQL is this: +** +**       SELECT * FROM t1, t2, t3 WHERE ...; +** +** Then the code generated is conceptually like the following: +** +**      foreach row1 in t1 do       \    Code generated +**        foreach row2 in t2 do      |-- by sqlite3WhereBegin() +**          foreach row3 in t3 do   / +**            ... +**          end                     \    Code generated +**        end                        |-- by sqlite3WhereEnd() +**      end                         / +** +** There are Btree cursors associated with each table.  t1 uses cursor +** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor. +** And so forth.  This routine generates code to open those VDBE cursors +** and sqlite3WhereEnd() generates the code to close them. +** +** If the WHERE clause is empty, the foreach loops must each scan their +** entire tables.  Thus a three-way join is an O(N^3) operation.  But if +** the tables have indices and there are terms in the WHERE clause that +** refer to those indices, a complete table scan can be avoided and the +** code will run much faster.  Most of the work of this routine is checking +** to see if there are indices that can be used to speed up the loop. +** +** Terms of the WHERE clause are also used to limit which rows actually +** make it to the "..." in the middle of the loop.  After each "foreach", +** terms of the WHERE clause that use only terms in that loop and outer +** loops are evaluated and if false a jump is made around all subsequent +** inner loops (or around the "..." if the test occurs within the inner- +** most loop) +** +** OUTER JOINS +** +** An outer join of tables t1 and t2 is conceptally coded as follows: +** +**    foreach row1 in t1 do +**      flag = 0 +**      foreach row2 in t2 do +**        start: +**          ... +**          flag = 1 +**      end +**      if flag==0 then +**        move the row2 cursor to a null row +**        goto start +**      fi +**    end +** +** ORDER BY CLAUSE PROCESSING +** +** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement, +** if there is one.  If there is no ORDER BY clause or if this routine +** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL. +** +** If an index can be used so that the natural output order of the table +** scan is correct for the ORDER BY clause, then that index is used and +** *ppOrderBy is set to NULL.  This is an optimization that prevents an +** unnecessary sort of the result set if an index appropriate for the +** ORDER BY clause already exists. +** +** If the where clause loops cannot be arranged to provide the correct +** output order, then the *ppOrderBy is unchanged. +*/ +WhereInfo *sqlite3WhereBegin( +  Parse *pParse,       /* The parser context */ +  SrcList *pTabList,   /* A list of all tables to be scanned */ +  Expr *pWhere,        /* The WHERE clause */ +  int pushKey,         /* If TRUE, leave the table key on the stack */ +  ExprList **ppOrderBy /* An ORDER BY clause, or NULL */ +){ +  int i;                     /* Loop counter */ +  WhereInfo *pWInfo;         /* Will become the return value of this function */ +  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */ +  int brk, cont = 0;         /* Addresses used during code generation */ +  int nExpr;           /* Number of subexpressions in the WHERE clause */ +  int loopMask;        /* One bit set for each outer loop */ +  int haveKey = 0;     /* True if KEY is on the stack */ +  ExprInfo *pTerm;     /* A single term in the WHERE clause; ptr to aExpr[] */ +  ExprMaskSet maskSet; /* The expression mask set */ +  int iDirectEq[32];   /* Term of the form ROWID==X for the N-th table */ +  int iDirectLt[32];   /* Term of the form ROWID<X or ROWID<=X */ +  int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */ +  ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */ + +  /* pushKey is only allowed if there is a single table (as in an INSERT or +  ** UPDATE statement) +  */ +  assert( pushKey==0 || pTabList->nSrc==1 ); + +  /* Split the WHERE clause into separate subexpressions where each +  ** subexpression is separated by an AND operator.  If the aExpr[] +  ** array fills up, the last entry might point to an expression which +  ** contains additional unfactored AND operators. +  */ +  initMaskSet(&maskSet); +  memset(aExpr, 0, sizeof(aExpr)); +  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere); +  if( nExpr==ARRAYSIZE(aExpr) ){ +    sqlite3ErrorMsg(pParse, "WHERE clause too complex - no more " +       "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1); +    return 0; +  } +   +  /* Allocate and initialize the WhereInfo structure that will become the +  ** return value. +  */ +  pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); +  if( sqlite3_malloc_failed ){ +    /* sqliteFree(pWInfo); // Leak memory when malloc fails */ +    return 0; +  } +  pWInfo->pParse = pParse; +  pWInfo->pTabList = pTabList; +  pWInfo->iBreak = sqlite3VdbeMakeLabel(v); + +  /* Special case: a WHERE clause that is constant.  Evaluate the +  ** expression and either jump over all of the code or fall thru. +  */ +  if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstant(pWhere)) ){ +    sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); +    pWhere = 0; +  } + +  /* Analyze all of the subexpressions. +  */ +  for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){ +    TriggerStack *pStack; +    exprAnalyze(pTabList, &maskSet, pTerm); + +    /* If we are executing a trigger body, remove all references to +    ** new.* and old.* tables from the prerequisite masks. +    */ +    if( (pStack = pParse->trigStack)!=0 ){ +      int x; +      if( (x=pStack->newIdx) >= 0 ){ +        int mask = ~getMask(&maskSet, x); +        pTerm->prereqRight &= mask; +        pTerm->prereqLeft &= mask; +        pTerm->prereqAll &= mask; +      } +      if( (x=pStack->oldIdx) >= 0 ){ +        int mask = ~getMask(&maskSet, x); +        pTerm->prereqRight &= mask; +        pTerm->prereqLeft &= mask; +        pTerm->prereqAll &= mask; +      } +    } +  } + +  /* Figure out what index to use (if any) for each nested loop. +  ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested +  ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner +  ** loop.  +  ** +  ** If terms exist that use the ROWID of any table, then set the +  ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table +  ** to the index of the term containing the ROWID.  We always prefer +  ** to use a ROWID which can directly access a table rather than an +  ** index which requires reading an index first to get the rowid then +  ** doing a second read of the actual database table. +  ** +  ** Actually, if there are more than 32 tables in the join, only the +  ** first 32 tables are candidates for indices.  This is (again) due +  ** to the limit of 32 bits in an integer bitmask. +  */ +  loopMask = 0; +  for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){ +    int j; +    WhereLevel *pLevel = &pWInfo->a[i]; +    int iCur = pTabList->a[i].iCursor;    /* The cursor for this table */ +    int mask = getMask(&maskSet, iCur);   /* Cursor mask for this table */ +    Table *pTab = pTabList->a[i].pTab; +    Index *pIdx; +    Index *pBestIdx = 0; +    int bestScore = 0; + +    /* Check to see if there is an expression that uses only the +    ** ROWID field of this table.  For terms of the form ROWID==expr +    ** set iDirectEq[i] to the index of the term.  For terms of the +    ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index. +    ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i]. +    ** +    ** (Added:) Treat ROWID IN expr like ROWID=expr. +    */ +    pLevel->iCur = -1; +    iDirectEq[i] = -1; +    iDirectLt[i] = -1; +    iDirectGt[i] = -1; +    for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ +      Expr *pX = pTerm->p; +      if( pTerm->idxLeft==iCur && pX->pLeft->iColumn<0 +            && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){ +        switch( pX->op ){ +          case TK_IN: +          case TK_EQ: iDirectEq[i] = j; break; +          case TK_LE: +          case TK_LT: iDirectLt[i] = j; break; +          case TK_GE: +          case TK_GT: iDirectGt[i] = j;  break; +        } +      } +    } +    if( iDirectEq[i]>=0 ){ +      loopMask |= mask; +      pLevel->pIdx = 0; +      continue; +    } + +    /* Do a search for usable indices.  Leave pBestIdx pointing to +    ** the "best" index.  pBestIdx is left set to NULL if no indices +    ** are usable. +    ** +    ** The best index is determined as follows.  For each of the +    ** left-most terms that is fixed by an equality operator, add +    ** 8 to the score.  The right-most term of the index may be +    ** constrained by an inequality.  Add 1 if for an "x<..." constraint +    ** and add 2 for an "x>..." constraint.  Chose the index that +    ** gives the best score. +    ** +    ** This scoring system is designed so that the score can later be +    ** used to determine how the index is used.  If the score&7 is 0 +    ** then all constraints are equalities.  If score&1 is not 0 then +    ** there is an inequality used as a termination key.  (ex: "x<...") +    ** If score&2 is not 0 then there is an inequality used as the +    ** start key.  (ex: "x>...").  A score or 4 is the special case +    ** of an IN operator constraint.  (ex:  "x IN ..."). +    ** +    ** The IN operator (as in "<expr> IN (...)") is treated the same as +    ** an equality comparison except that it can only be used on the +    ** left-most column of an index and other terms of the WHERE clause +    ** cannot be used in conjunction with the IN operator to help satisfy +    ** other columns of the index. +    */ +    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +      int eqMask = 0;  /* Index columns covered by an x=... term */ +      int ltMask = 0;  /* Index columns covered by an x<... term */ +      int gtMask = 0;  /* Index columns covered by an x>... term */ +      int inMask = 0;  /* Index columns covered by an x IN .. term */ +      int nEq, m, score; + +      if( pIdx->nColumn>32 ) continue;  /* Ignore indices too many columns */ +      for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ +        Expr *pX = pTerm->p; +        CollSeq *pColl = sqlite3ExprCollSeq(pParse, pX->pLeft); +        if( !pColl && pX->pRight ){ +          pColl = sqlite3ExprCollSeq(pParse, pX->pRight); +        } +        if( !pColl ){ +          pColl = pParse->db->pDfltColl; +        } +        if( pTerm->idxLeft==iCur  +             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){ +          int iColumn = pX->pLeft->iColumn; +          int k; +          char idxaff = pIdx->pTable->aCol[iColumn].affinity;  +          for(k=0; k<pIdx->nColumn; k++){ +            /* If the collating sequences or affinities don't match,  +            ** ignore this index.  */ +            if( pColl!=pIdx->keyInfo.aColl[k] ) continue; +            if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; +            if( pIdx->aiColumn[k]==iColumn ){ +              switch( pX->op ){ +                case TK_IN: { +                  if( k==0 ) inMask |= 1; +                  break; +                } +                case TK_EQ: { +                  eqMask |= 1<<k; +                  break; +                } +                case TK_LE: +                case TK_LT: { +                  ltMask |= 1<<k; +                  break; +                } +                case TK_GE: +                case TK_GT: { +                  gtMask |= 1<<k; +                  break; +                } +                default: { +                  /* CANT_HAPPEN */ +                  assert( 0 ); +                  break; +                } +              } +              break; +            } +          } +        } +      } + +      /* The following loop ends with nEq set to the number of columns +      ** on the left of the index with == constraints. +      */ +      for(nEq=0; nEq<pIdx->nColumn; nEq++){ +        m = (1<<(nEq+1))-1; +        if( (m & eqMask)!=m ) break; +      } +      score = nEq*8;   /* Base score is 8 times number of == constraints */ +      m = 1<<nEq; +      if( m & ltMask ) score++;    /* Increase score for a < constraint */ +      if( m & gtMask ) score+=2;   /* Increase score for a > constraint */ +      if( score==0 && inMask ) score = 4;  /* Default score for IN constraint */ +      if( score>bestScore ){ +        pBestIdx = pIdx; +        bestScore = score; +      } +    } +    pLevel->pIdx = pBestIdx; +    pLevel->score = bestScore; +    pLevel->bRev = 0; +    loopMask |= mask; +    if( pBestIdx ){ +      pLevel->iCur = pParse->nTab++; +    } +  } + +  /* Check to see if the ORDER BY clause is or can be satisfied by the +  ** use of an index on the first table. +  */ +  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){ +     Index *pSortIdx; +     Index *pIdx; +     Table *pTab; +     int bRev = 0; + +     pTab = pTabList->a[0].pTab; +     pIdx = pWInfo->a[0].pIdx; +     if( pIdx && pWInfo->a[0].score==4 ){ +       /* If there is already an IN index on the left-most table, +       ** it will not give the correct sort order. +       ** So, pretend that no suitable index is found. +       */ +       pSortIdx = 0; +     }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){ +       /* If the left-most column is accessed using its ROWID, then do +       ** not try to sort by index. +       */ +       pSortIdx = 0; +     }else{ +       int nEqCol = (pWInfo->a[0].score+4)/8; +       pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor,  +                                   *ppOrderBy, pIdx, nEqCol, &bRev); +     } +     if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){ +       if( pIdx==0 ){ +         pWInfo->a[0].pIdx = pSortIdx; +         pWInfo->a[0].iCur = pParse->nTab++; +       } +       pWInfo->a[0].bRev = bRev; +       *ppOrderBy = 0; +     } +  } + +  /* Open all tables in the pTabList and all indices used by those tables. +  */ +  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ +  for(i=0; i<pTabList->nSrc; i++){ +    Table *pTab; +    Index *pIx; + +    pTab = pTabList->a[i].pTab; +    if( pTab->isTransient || pTab->pSelect ) continue; +    sqlite3OpenTableForReading(v, pTabList->a[i].iCursor, pTab); +    sqlite3CodeVerifySchema(pParse, pTab->iDb); +    if( (pIx = pWInfo->a[i].pIdx)!=0 ){ +      sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0); +      sqlite3VdbeOp3(v, OP_OpenRead, pWInfo->a[i].iCur, pIx->tnum, +                     (char*)&pIx->keyInfo, P3_KEYINFO); +    } +  } + +  /* Generate the code to do the search +  */ +  loopMask = 0; +  for(i=0; i<pTabList->nSrc; i++){ +    int j, k; +    int iCur = pTabList->a[i].iCursor; +    Index *pIdx; +    WhereLevel *pLevel = &pWInfo->a[i]; + +    /* If this is the right table of a LEFT OUTER JOIN, allocate and +    ** initialize a memory cell that records if this table matches any +    ** row of the left table of the join. +    */ +    if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){ +      if( !pParse->nMem ) pParse->nMem++; +      pLevel->iLeftJoin = pParse->nMem++; +      sqlite3VdbeAddOp(v, OP_String8, 0, 0); +      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1); +      VdbeComment((v, "# init LEFT JOIN no-match flag")); +    } + +    pIdx = pLevel->pIdx; +    pLevel->inOp = OP_Noop; +    if( i<ARRAYSIZE(iDirectEq) && (k = iDirectEq[i])>=0 ){ +      /* Case 1:  We can directly reference a single row using an +      **          equality comparison against the ROWID field.  Or +      **          we reference multiple rows using a "rowid IN (...)" +      **          construct. +      */ +      assert( k<nExpr ); +      pTerm = &aExpr[k]; +      assert( pTerm->p!=0 ); +      assert( pTerm->idxLeft==iCur ); +      brk = pLevel->brk = sqlite3VdbeMakeLabel(v); +      codeEqualityTerm(pParse, pTerm, brk, pLevel); +      cont = pLevel->cont = sqlite3VdbeMakeLabel(v); +      sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk); +      haveKey = 0; +      sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk); +      pLevel->op = OP_Noop; +    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){ +      /* Case 2:  There is an index and all terms of the WHERE clause that +      **          refer to the index use the "==" or "IN" operators. +      */ +      int start; +      int nColumn = (pLevel->score+4)/8; +      brk = pLevel->brk = sqlite3VdbeMakeLabel(v); + +      /* For each column of the index, find the term of the WHERE clause that +      ** constraints that column.  If the WHERE clause term is X=expr, then +      ** evaluation expr and leave the result on the stack */ +      for(j=0; j<nColumn; j++){ +        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ +          Expr *pX = pTerm->p; +          if( pX==0 ) continue; +          if( pTerm->idxLeft==iCur +             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight  +             && pX->pLeft->iColumn==pIdx->aiColumn[j] +          ){ +            char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity; +            if( sqlite3IndexAffinityOk(pX, idxaff) ){ +              codeEqualityTerm(pParse, pTerm, brk, pLevel); +              break; +            } +          } +        } +      } +      pLevel->iMem = pParse->nMem++; +      cont = pLevel->cont = sqlite3VdbeMakeLabel(v); +      buildIndexProbe(v, nColumn, brk, pIdx); +      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); + +      /* Generate code (1) to move to the first matching element of the table. +      ** Then generate code (2) that jumps to "brk" after the cursor is past +      ** the last matching element of the table.  The code (1) is executed +      ** once to initialize the search, the code (2) is executed before each +      ** iteration of the scan to see if the scan has finished. */ +      if( pLevel->bRev ){ +        /* Scan in reverse order */ +        sqlite3VdbeAddOp(v, OP_MoveLe, pLevel->iCur, brk); +        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); +        sqlite3VdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk); +        pLevel->op = OP_Prev; +      }else{ +        /* Scan in the forward order */ +        sqlite3VdbeAddOp(v, OP_MoveGe, pLevel->iCur, brk); +        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); +        sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC); +        pLevel->op = OP_Next; +      } +      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0); +      sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont); +      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0); +      if( i==pTabList->nSrc-1 && pushKey ){ +        haveKey = 1; +      }else{ +        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); +        haveKey = 0; +      } +      pLevel->p1 = pLevel->iCur; +      pLevel->p2 = start; +    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){ +      /* Case 3:  We have an inequality comparison against the ROWID field. +      */ +      int testOp = OP_Noop; +      int start; + +      brk = pLevel->brk = sqlite3VdbeMakeLabel(v); +      cont = pLevel->cont = sqlite3VdbeMakeLabel(v); +      if( iDirectGt[i]>=0 ){ +        Expr *pX; +        k = iDirectGt[i]; +        assert( k<nExpr ); +        pTerm = &aExpr[k]; +        pX = pTerm->p; +        assert( pX!=0 ); +        assert( pTerm->idxLeft==iCur ); +        sqlite3ExprCode(pParse, pX->pRight); +        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LT || pX->op==TK_GT, brk); +        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk); +        disableTerm(pLevel, &pTerm->p); +      }else{ +        sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk); +      } +      if( iDirectLt[i]>=0 ){ +        Expr *pX; +        k = iDirectLt[i]; +        assert( k<nExpr ); +        pTerm = &aExpr[k]; +        pX = pTerm->p; +        assert( pX!=0 ); +        assert( pTerm->idxLeft==iCur ); +        sqlite3ExprCode(pParse, pX->pRight); +        pLevel->iMem = pParse->nMem++; +        sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); +        if( pX->op==TK_LT || pX->op==TK_GT ){ +          testOp = OP_Ge; +        }else{ +          testOp = OP_Gt; +        } +        disableTerm(pLevel, &pTerm->p); +      } +      start = sqlite3VdbeCurrentAddr(v); +      pLevel->op = OP_Next; +      pLevel->p1 = iCur; +      pLevel->p2 = start; +      if( testOp!=OP_Noop ){ +        sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); +        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); +        sqlite3VdbeAddOp(v, testOp, 0, brk); +      } +      haveKey = 0; +    }else if( pIdx==0 ){ +      /* Case 4:  There is no usable index.  We must do a complete +      **          scan of the entire database table. +      */ +      int start; + +      brk = pLevel->brk = sqlite3VdbeMakeLabel(v); +      cont = pLevel->cont = sqlite3VdbeMakeLabel(v); +      sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk); +      start = sqlite3VdbeCurrentAddr(v); +      pLevel->op = OP_Next; +      pLevel->p1 = iCur; +      pLevel->p2 = start; +      haveKey = 0; +    }else{ +      /* Case 5: The WHERE clause term that refers to the right-most +      **         column of the index is an inequality.  For example, if +      **         the index is on (x,y,z) and the WHERE clause is of the +      **         form "x=5 AND y<10" then this case is used.  Only the +      **         right-most column can be an inequality - the rest must +      **         use the "==" operator. +      ** +      **         This case is also used when there are no WHERE clause +      **         constraints but an index is selected anyway, in order +      **         to force the output order to conform to an ORDER BY. +      */ +      int score = pLevel->score; +      int nEqColumn = score/8; +      int start; +      int leFlag=0, geFlag=0; +      int testOp; + +      /* Evaluate the equality constraints +      */ +      for(j=0; j<nEqColumn; j++){ +        int iIdxCol = pIdx->aiColumn[j]; +        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ +          Expr *pX = pTerm->p; +          if( pX==0 ) continue; +          if( pTerm->idxLeft==iCur +             && pX->op==TK_EQ +             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight  +             && pX->pLeft->iColumn==iIdxCol +          ){ +            sqlite3ExprCode(pParse, pX->pRight); +            disableTerm(pLevel, &pTerm->p); +            break; +          } +        } +      } + +      /* Duplicate the equality term values because they will all be +      ** used twice: once to make the termination key and once to make the +      ** start key. +      */ +      for(j=0; j<nEqColumn; j++){ +        sqlite3VdbeAddOp(v, OP_Dup, nEqColumn-1, 0); +      } + +      /* Labels for the beginning and end of the loop +      */ +      cont = pLevel->cont = sqlite3VdbeMakeLabel(v); +      brk = pLevel->brk = sqlite3VdbeMakeLabel(v); + +      /* Generate the termination key.  This is the key value that +      ** will end the search.  There is no termination key if there +      ** are no equality terms and no "X<..." term. +      ** +      ** 2002-Dec-04: On a reverse-order scan, the so-called "termination" +      ** key computed here really ends up being the start key. +      */ +      if( (score & 1)!=0 ){ +        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ +          Expr *pX = pTerm->p; +          if( pX==0 ) continue; +          if( pTerm->idxLeft==iCur +             && (pX->op==TK_LT || pX->op==TK_LE) +             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight  +             && pX->pLeft->iColumn==pIdx->aiColumn[j] +          ){ +            sqlite3ExprCode(pParse, pX->pRight); +            leFlag = pX->op==TK_LE; +            disableTerm(pLevel, &pTerm->p); +            break; +          } +        } +        testOp = OP_IdxGE; +      }else{ +        testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop; +        leFlag = 1; +      } +      if( testOp!=OP_Noop ){ +        int nCol = nEqColumn + (score & 1); +        pLevel->iMem = pParse->nMem++; +        buildIndexProbe(v, nCol, brk, pIdx); +        if( pLevel->bRev ){ +          int op = leFlag ? OP_MoveLe : OP_MoveLt; +          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk); +        }else{ +          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); +        } +      }else if( pLevel->bRev ){ +        sqlite3VdbeAddOp(v, OP_Last, pLevel->iCur, brk); +      } + +      /* Generate the start key.  This is the key that defines the lower +      ** bound on the search.  There is no start key if there are no +      ** equality terms and if there is no "X>..." term.  In +      ** that case, generate a "Rewind" instruction in place of the +      ** start key search. +      ** +      ** 2002-Dec-04: In the case of a reverse-order search, the so-called +      ** "start" key really ends up being used as the termination key. +      */ +      if( (score & 2)!=0 ){ +        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ +          Expr *pX = pTerm->p; +          if( pX==0 ) continue; +          if( pTerm->idxLeft==iCur +             && (pX->op==TK_GT || pX->op==TK_GE) +             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight  +             && pX->pLeft->iColumn==pIdx->aiColumn[j] +          ){ +            sqlite3ExprCode(pParse, pX->pRight); +            geFlag = pX->op==TK_GE; +            disableTerm(pLevel, &pTerm->p); +            break; +          } +        } +      }else{ +        geFlag = 1; +      } +      if( nEqColumn>0 || (score&2)!=0 ){ +        int nCol = nEqColumn + ((score&2)!=0); +        buildIndexProbe(v, nCol, brk, pIdx); +        if( pLevel->bRev ){ +          pLevel->iMem = pParse->nMem++; +          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); +          testOp = OP_IdxLT; +        }else{ +          int op = geFlag ? OP_MoveGe : OP_MoveGt; +          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk); +        } +      }else if( pLevel->bRev ){ +        testOp = OP_Noop; +      }else{ +        sqlite3VdbeAddOp(v, OP_Rewind, pLevel->iCur, brk); +      } + +      /* Generate the the top of the loop.  If there is a termination +      ** key we have to test for that key and abort at the top of the +      ** loop. +      */ +      start = sqlite3VdbeCurrentAddr(v); +      if( testOp!=OP_Noop ){ +        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); +        sqlite3VdbeAddOp(v, testOp, pLevel->iCur, brk); +        if( (leFlag && !pLevel->bRev) || (!geFlag && pLevel->bRev) ){ +          sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC); +        } +      } +      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0); +      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont); +      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0); +      if( i==pTabList->nSrc-1 && pushKey ){ +        haveKey = 1; +      }else{ +        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); +        haveKey = 0; +      } + +      /* Record the instruction used to terminate the loop. +      */ +      pLevel->op = pLevel->bRev ? OP_Prev : OP_Next; +      pLevel->p1 = pLevel->iCur; +      pLevel->p2 = start; +    } +    loopMask |= getMask(&maskSet, iCur); + +    /* Insert code to test every subexpression that can be completely +    ** computed using the current set of tables. +    */ +    for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ +      if( pTerm->p==0 ) continue; +      if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue; +      if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){ +        continue; +      } +      if( haveKey ){ +        haveKey = 0; +        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); +      } +      sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); +      pTerm->p = 0; +    } +    brk = cont; + +    /* For a LEFT OUTER JOIN, generate code that will record the fact that +    ** at least one row of the right table has matched the left table.   +    */ +    if( pLevel->iLeftJoin ){ +      pLevel->top = sqlite3VdbeCurrentAddr(v); +      sqlite3VdbeAddOp(v, OP_Integer, 1, 0); +      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1); +      VdbeComment((v, "# record LEFT JOIN hit")); +      for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ +        if( pTerm->p==0 ) continue; +        if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue; +        if( haveKey ){ +          /* Cannot happen.  "haveKey" can only be true if pushKey is true +          ** an pushKey can only be true for DELETE and UPDATE and there are +          ** no outer joins with DELETE and UPDATE. +          */ +          haveKey = 0; +          sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); +        } +        sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); +        pTerm->p = 0; +      } +    } +  } +  pWInfo->iContinue = cont; +  if( pushKey && !haveKey ){ +    sqlite3VdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0); +  } +  freeMaskSet(&maskSet); +  return pWInfo; +} + +/* +** Generate the end of the WHERE loop.  See comments on  +** sqlite3WhereBegin() for additional information. +*/ +void sqlite3WhereEnd(WhereInfo *pWInfo){ +  Vdbe *v = pWInfo->pParse->pVdbe; +  int i; +  WhereLevel *pLevel; +  SrcList *pTabList = pWInfo->pTabList; + +  for(i=pTabList->nSrc-1; i>=0; i--){ +    pLevel = &pWInfo->a[i]; +    sqlite3VdbeResolveLabel(v, pLevel->cont); +    if( pLevel->op!=OP_Noop ){ +      sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2); +    } +    sqlite3VdbeResolveLabel(v, pLevel->brk); +    if( pLevel->inOp!=OP_Noop ){ +      sqlite3VdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2); +    } +    if( pLevel->iLeftJoin ){ +      int addr; +      addr = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0); +      sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0)); +      sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0); +      if( pLevel->iCur>=0 ){ +        sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iCur, 0); +      } +      sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top); +    } +  } +  sqlite3VdbeResolveLabel(v, pWInfo->iBreak); +  for(i=0; i<pTabList->nSrc; i++){ +    Table *pTab = pTabList->a[i].pTab; +    assert( pTab!=0 ); +    if( pTab->isTransient || pTab->pSelect ) continue; +    pLevel = &pWInfo->a[i]; +    sqlite3VdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0); +    if( pLevel->pIdx!=0 ){ +      sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0); +    } +  } +  sqliteFree(pWInfo); +  return; +} diff --git a/ext/pdo_sqlite/sqlite/tool/diffdb.c b/ext/pdo_sqlite/sqlite/tool/diffdb.c new file mode 100644 index 0000000000..0537d38723 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/diffdb.c @@ -0,0 +1,44 @@ +/* +** A utility for printing the differences between two SQLite database files. +*/ +#include <stdio.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + + +#define PAGESIZE 1024 +static int db1 = -1; +static int db2 = -1; + +int main(int argc, char **argv){ +  int iPg; +  unsigned char a1[PAGESIZE], a2[PAGESIZE]; +  if( argc!=3 ){ +    fprintf(stderr,"Usage: %s FILENAME FILENAME\n", argv[0]); +    exit(1); +  } +  db1 = open(argv[1], O_RDONLY); +  if( db1<0 ){ +    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); +    exit(1); +  } +  db2 = open(argv[2], O_RDONLY); +  if( db2<0 ){ +    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[2]); +    exit(1); +  } +  iPg = 1; +  while( read(db1, a1, PAGESIZE)==PAGESIZE && read(db2,a2,PAGESIZE)==PAGESIZE ){ +    if( memcmp(a1,a2,PAGESIZE) ){ +      printf("Page %d\n", iPg); +    } +    iPg++; +  } +  printf("%d pages checked\n", iPg-1); +  close(db1); +  close(db2); +} diff --git a/ext/pdo_sqlite/sqlite/tool/lemon.c b/ext/pdo_sqlite/sqlite/tool/lemon.c new file mode 100644 index 0000000000..708b3538d7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/lemon.c @@ -0,0 +1,4588 @@ +/* +** This file contains all sources (including headers) to the LEMON +** LALR(1) parser generator.  The sources have been combined into a +** single file to make it easy to include LEMON in the source tree +** and Makefile of another program. +** +** The author of this program disclaims copyright. +*/ +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +#ifndef __WIN32__ +#   if defined(_WIN32) || defined(WIN32) +#	define __WIN32__ +#   endif +#endif + +/* #define PRIVATE static */ +#define PRIVATE + +#ifdef TEST +#define MAXRHS 5       /* Set low to exercise exception code */ +#else +#define MAXRHS 1000 +#endif + +char *msort(); +extern void *malloc(); + +/******** From the file "action.h" *************************************/ +struct action *Action_new(); +struct action *Action_sort(); + +/********* From the file "assert.h" ************************************/ +void myassert(); +#ifndef NDEBUG +#  define assert(X) if(!(X))myassert(__FILE__,__LINE__) +#else +#  define assert(X) +#endif + +/********** From the file "build.h" ************************************/ +void FindRulePrecedences(); +void FindFirstSets(); +void FindStates(); +void FindLinks(); +void FindFollowSets(); +void FindActions(); + +/********* From the file "configlist.h" *********************************/ +void Configlist_init(/* void */); +struct config *Configlist_add(/* struct rule *, int */); +struct config *Configlist_addbasis(/* struct rule *, int */); +void Configlist_closure(/* void */); +void Configlist_sort(/* void */); +void Configlist_sortbasis(/* void */); +struct config *Configlist_return(/* void */); +struct config *Configlist_basis(/* void */); +void Configlist_eat(/* struct config * */); +void Configlist_reset(/* void */); + +/********* From the file "error.h" ***************************************/ +void ErrorMsg(const char *, int,const char *, ...); + +/****** From the file "option.h" ******************************************/ +struct s_options { +  enum { OPT_FLAG=1,  OPT_INT,  OPT_DBL,  OPT_STR, +         OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type; +  char *label; +  char *arg; +  char *message; +}; +int    OptInit(/* char**,struct s_options*,FILE* */); +int    OptNArgs(/* void */); +char  *OptArg(/* int */); +void   OptErr(/* int */); +void   OptPrint(/* void */); + +/******** From the file "parse.h" *****************************************/ +void Parse(/* struct lemon *lemp */); + +/********* From the file "plink.h" ***************************************/ +struct plink *Plink_new(/* void */); +void Plink_add(/* struct plink **, struct config * */); +void Plink_copy(/* struct plink **, struct plink * */); +void Plink_delete(/* struct plink * */); + +/********** From the file "report.h" *************************************/ +void Reprint(/* struct lemon * */); +void ReportOutput(/* struct lemon * */); +void ReportTable(/* struct lemon * */); +void ReportHeader(/* struct lemon * */); +void CompressTables(/* struct lemon * */); + +/********** From the file "set.h" ****************************************/ +void  SetSize(/* int N */);             /* All sets will be of size N */ +char *SetNew(/* void */);               /* A new set for element 0..N */ +void  SetFree(/* char* */);             /* Deallocate a set */ + +int SetAdd(/* char*,int */);            /* Add element to a set */ +int SetUnion(/* char *A,char *B */);    /* A <- A U B, thru element N */ + +#define SetFind(X,Y) (X[Y])       /* True if Y is in set X */ + +/********** From the file "struct.h" *************************************/ +/* +** Principal data structures for the LEMON parser generator. +*/ + +typedef enum {B_FALSE=0, B_TRUE} Boolean; + +/* Symbols (terminals and nonterminals) of the grammar are stored +** in the following: */ +struct symbol { +  char *name;              /* Name of the symbol */ +  int index;               /* Index number for this symbol */ +  enum { +    TERMINAL, +    NONTERMINAL +  } type;                  /* Symbols are all either TERMINALS or NTs */ +  struct rule *rule;       /* Linked list of rules of this (if an NT) */ +  struct symbol *fallback; /* fallback token in case this token doesn't parse */ +  int prec;                /* Precedence if defined (-1 otherwise) */ +  enum e_assoc { +    LEFT, +    RIGHT, +    NONE, +    UNK +  } assoc;                 /* Associativity if predecence is defined */ +  char *firstset;          /* First-set for all rules of this symbol */ +  Boolean lambda;          /* True if NT and can generate an empty string */ +  char *destructor;        /* Code which executes whenever this symbol is +                           ** popped from the stack during error processing */ +  int destructorln;        /* Line number of destructor code */ +  char *datatype;          /* The data type of information held by this +                           ** object. Only used if type==NONTERMINAL */ +  int dtnum;               /* The data type number.  In the parser, the value +                           ** stack is a union.  The .yy%d element of this +                           ** union is the correct data type for this object */ +}; + +/* Each production rule in the grammar is stored in the following +** structure.  */ +struct rule { +  struct symbol *lhs;      /* Left-hand side of the rule */ +  char *lhsalias;          /* Alias for the LHS (NULL if none) */ +  int ruleline;            /* Line number for the rule */ +  int nrhs;                /* Number of RHS symbols */ +  struct symbol **rhs;     /* The RHS symbols */ +  char **rhsalias;         /* An alias for each RHS symbol (NULL if none) */ +  int line;                /* Line number at which code begins */ +  char *code;              /* The code executed when this rule is reduced */ +  struct symbol *precsym;  /* Precedence symbol for this rule */ +  int index;               /* An index number for this rule */ +  Boolean canReduce;       /* True if this rule is ever reduced */ +  struct rule *nextlhs;    /* Next rule with the same LHS */ +  struct rule *next;       /* Next rule in the global list */ +}; + +/* A configuration is a production rule of the grammar together with +** a mark (dot) showing how much of that rule has been processed so far. +** Configurations also contain a follow-set which is a list of terminal +** symbols which are allowed to immediately follow the end of the rule. +** Every configuration is recorded as an instance of the following: */ +struct config { +  struct rule *rp;         /* The rule upon which the configuration is based */ +  int dot;                 /* The parse point */ +  char *fws;               /* Follow-set for this configuration only */ +  struct plink *fplp;      /* Follow-set forward propagation links */ +  struct plink *bplp;      /* Follow-set backwards propagation links */ +  struct state *stp;       /* Pointer to state which contains this */ +  enum { +    COMPLETE,              /* The status is used during followset and */ +    INCOMPLETE             /*    shift computations */ +  } status; +  struct config *next;     /* Next configuration in the state */ +  struct config *bp;       /* The next basis configuration */ +}; + +/* Every shift or reduce operation is stored as one of the following */ +struct action { +  struct symbol *sp;       /* The look-ahead symbol */ +  enum e_action { +    SHIFT, +    ACCEPT, +    REDUCE, +    ERROR, +    CONFLICT,                /* Was a reduce, but part of a conflict */ +    SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */ +    RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */ +    NOT_USED                 /* Deleted by compression */ +  } type; +  union { +    struct state *stp;     /* The new state, if a shift */ +    struct rule *rp;       /* The rule, if a reduce */ +  } x; +  struct action *next;     /* Next action for this state */ +  struct action *collide;  /* Next action with the same hash */ +}; + +/* Each state of the generated parser's finite state machine +** is encoded as an instance of the following structure. */ +struct state { +  struct config *bp;       /* The basis configurations for this state */ +  struct config *cfp;      /* All configurations in this set */ +  int index;               /* Sequencial number for this state */ +  struct action *ap;       /* Array of actions for this state */ +  int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */ +  int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */ +  int iDflt;               /* Default action */ +}; +#define NO_OFFSET (-2147483647) + +/* A followset propagation link indicates that the contents of one +** configuration followset should be propagated to another whenever +** the first changes. */ +struct plink { +  struct config *cfp;      /* The configuration to which linked */ +  struct plink *next;      /* The next propagate link */ +}; + +/* The state vector for the entire parser generator is recorded as +** follows.  (LEMON uses no global variables and makes little use of +** static variables.  Fields in the following structure can be thought +** of as begin global variables in the program.) */ +struct lemon { +  struct state **sorted;   /* Table of states sorted by state number */ +  struct rule *rule;       /* List of all rules */ +  int nstate;              /* Number of states */ +  int nrule;               /* Number of rules */ +  int nsymbol;             /* Number of terminal and nonterminal symbols */ +  int nterminal;           /* Number of terminal symbols */ +  struct symbol **symbols; /* Sorted array of pointers to symbols */ +  int errorcnt;            /* Number of errors */ +  struct symbol *errsym;   /* The error symbol */ +  char *name;              /* Name of the generated parser */ +  char *arg;               /* Declaration of the 3th argument to parser */ +  char *tokentype;         /* Type of terminal symbols in the parser stack */ +  char *vartype;           /* The default type of non-terminal symbols */ +  char *start;             /* Name of the start symbol for the grammar */ +  char *stacksize;         /* Size of the parser stack */ +  char *include;           /* Code to put at the start of the C file */ +  int  includeln;          /* Line number for start of include code */ +  char *error;             /* Code to execute when an error is seen */ +  int  errorln;            /* Line number for start of error code */ +  char *overflow;          /* Code to execute on a stack overflow */ +  int  overflowln;         /* Line number for start of overflow code */ +  char *failure;           /* Code to execute on parser failure */ +  int  failureln;          /* Line number for start of failure code */ +  char *accept;            /* Code to execute when the parser excepts */ +  int  acceptln;           /* Line number for the start of accept code */ +  char *extracode;         /* Code appended to the generated file */ +  int  extracodeln;        /* Line number for the start of the extra code */ +  char *tokendest;         /* Code to execute to destroy token data */ +  int  tokendestln;        /* Line number for token destroyer code */ +  char *vardest;           /* Code for the default non-terminal destructor */ +  int  vardestln;          /* Line number for default non-term destructor code*/ +  char *filename;          /* Name of the input file */ +  char *outname;           /* Name of the current output file */ +  char *tokenprefix;       /* A prefix added to token names in the .h file */ +  int nconflict;           /* Number of parsing conflicts */ +  int tablesize;           /* Size of the parse tables */ +  int basisflag;           /* Print only basis configurations */ +  int has_fallback;        /* True if any %fallback is seen in the grammer */ +  char *argv0;             /* Name of the program */ +}; + +#define MemoryCheck(X) if((X)==0){ \ +  extern void memory_error(); \ +  memory_error(); \ +} + +/**************** From the file "table.h" *********************************/ +/* +** All code in this file has been automatically generated +** from a specification in the file +**              "table.q" +** by the associative array code building program "aagen". +** Do not edit this file!  Instead, edit the specification +** file, then rerun aagen. +*/ +/* +** Code for processing tables in the LEMON parser generator. +*/ + +/* Routines for handling a strings */ + +char *Strsafe(); + +void Strsafe_init(/* void */); +int Strsafe_insert(/* char * */); +char *Strsafe_find(/* char * */); + +/* Routines for handling symbols of the grammar */ + +struct symbol *Symbol_new(); +int Symbolcmpp(/* struct symbol **, struct symbol ** */); +void Symbol_init(/* void */); +int Symbol_insert(/* struct symbol *, char * */); +struct symbol *Symbol_find(/* char * */); +struct symbol *Symbol_Nth(/* int */); +int Symbol_count(/*  */); +struct symbol **Symbol_arrayof(/*  */); + +/* Routines to manage the state table */ + +int Configcmp(/* struct config *, struct config * */); +struct state *State_new(); +void State_init(/* void */); +int State_insert(/* struct state *, struct config * */); +struct state *State_find(/* struct config * */); +struct state **State_arrayof(/*  */); + +/* Routines used for efficiency in Configlist_add */ + +void Configtable_init(/* void */); +int Configtable_insert(/* struct config * */); +struct config *Configtable_find(/* struct config * */); +void Configtable_clear(/* int(*)(struct config *) */); +/****************** From the file "action.c" *******************************/ +/* +** Routines processing parser actions in the LEMON parser generator. +*/ + +/* Allocate a new parser action */ +struct action *Action_new(){ +  static struct action *freelist = 0; +  struct action *new; + +  if( freelist==0 ){ +    int i; +    int amt = 100; +    freelist = (struct action *)malloc( sizeof(struct action)*amt ); +    if( freelist==0 ){ +      fprintf(stderr,"Unable to allocate memory for a new parser action."); +      exit(1); +    } +    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1]; +    freelist[amt-1].next = 0; +  } +  new = freelist; +  freelist = freelist->next; +  return new; +} + +/* Compare two actions */ +static int actioncmp(ap1,ap2) +struct action *ap1; +struct action *ap2; +{ +  int rc; +  rc = ap1->sp->index - ap2->sp->index; +  if( rc==0 ) rc = (int)ap1->type - (int)ap2->type; +  if( rc==0 ){ +    assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT); +    assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT); +    rc = ap1->x.rp->index - ap2->x.rp->index; +  } +  return rc; +} + +/* Sort parser actions */ +struct action *Action_sort(ap) +struct action *ap; +{ +  ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp); +  return ap; +} + +void Action_add(app,type,sp,arg) +struct action **app; +enum e_action type; +struct symbol *sp; +char *arg; +{ +  struct action *new; +  new = Action_new(); +  new->next = *app; +  *app = new; +  new->type = type; +  new->sp = sp; +  if( type==SHIFT ){ +    new->x.stp = (struct state *)arg; +  }else{ +    new->x.rp = (struct rule *)arg; +  } +} +/********************** New code to implement the "acttab" module ***********/ +/* +** This module implements routines use to construct the yy_action[] table. +*/ + +/* +** The state of the yy_action table under construction is an instance of +** the following structure +*/ +typedef struct acttab acttab; +struct acttab { +  int nAction;                 /* Number of used slots in aAction[] */ +  int nActionAlloc;            /* Slots allocated for aAction[] */ +  struct { +    int lookahead;             /* Value of the lookahead token */ +    int action;                /* Action to take on the given lookahead */ +  } *aAction,                  /* The yy_action[] table under construction */ +    *aLookahead;               /* A single new transaction set */ +  int mnLookahead;             /* Minimum aLookahead[].lookahead */ +  int mnAction;                /* Action associated with mnLookahead */ +  int mxLookahead;             /* Maximum aLookahead[].lookahead */ +  int nLookahead;              /* Used slots in aLookahead[] */ +  int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */ +}; + +/* Return the number of entries in the yy_action table */ +#define acttab_size(X) ((X)->nAction) + +/* The value for the N-th entry in yy_action */ +#define acttab_yyaction(X,N)  ((X)->aAction[N].action) + +/* The value for the N-th entry in yy_lookahead */ +#define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead) + +/* Free all memory associated with the given acttab */ +void acttab_free(acttab *p){ +  free( p->aAction ); +  free( p->aLookahead ); +  free( p ); +} + +/* Allocate a new acttab structure */ +acttab *acttab_alloc(void){ +  acttab *p = malloc( sizeof(*p) ); +  if( p==0 ){ +    fprintf(stderr,"Unable to allocate memory for a new acttab."); +    exit(1); +  } +  memset(p, 0, sizeof(*p)); +  return p; +} + +/* Add a new action to the current transaction set +*/ +void acttab_action(acttab *p, int lookahead, int action){ +  if( p->nLookahead>=p->nLookaheadAlloc ){ +    p->nLookaheadAlloc += 25; +    p->aLookahead = realloc( p->aLookahead, +                             sizeof(p->aLookahead[0])*p->nLookaheadAlloc ); +    if( p->aLookahead==0 ){ +      fprintf(stderr,"malloc failed\n"); +      exit(1); +    } +  } +  if( p->nLookahead==0 ){ +    p->mxLookahead = lookahead; +    p->mnLookahead = lookahead; +    p->mnAction = action; +  }else{ +    if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead; +    if( p->mnLookahead>lookahead ){ +      p->mnLookahead = lookahead; +      p->mnAction = action; +    } +  } +  p->aLookahead[p->nLookahead].lookahead = lookahead; +  p->aLookahead[p->nLookahead].action = action; +  p->nLookahead++; +} + +/* +** Add the transaction set built up with prior calls to acttab_action() +** into the current action table.  Then reset the transaction set back +** to an empty set in preparation for a new round of acttab_action() calls. +** +** Return the offset into the action table of the new transaction. +*/ +int acttab_insert(acttab *p){ +  int i, j, k, n; +  assert( p->nLookahead>0 ); + +  /* Make sure we have enough space to hold the expanded action table +  ** in the worst case.  The worst case occurs if the transaction set +  ** must be appended to the current action table +  */ +  n = p->mxLookahead + 1; +  if( p->nAction + n >= p->nActionAlloc ){ +    int oldAlloc = p->nActionAlloc; +    p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; +    p->aAction = realloc( p->aAction, +                          sizeof(p->aAction[0])*p->nActionAlloc); +    if( p->aAction==0 ){ +      fprintf(stderr,"malloc failed\n"); +      exit(1); +    } +    for(i=oldAlloc; i<p->nActionAlloc; i++){ +      p->aAction[i].lookahead = -1; +      p->aAction[i].action = -1; +    } +  } + +  /* Scan the existing action table looking for an offset where we can +  ** insert the current transaction set.  Fall out of the loop when that +  ** offset is found.  In the worst case, we fall out of the loop when +  ** i reaches p->nAction, which means we append the new transaction set. +  ** +  ** i is the index in p->aAction[] where p->mnLookahead is inserted. +  */ +  for(i=0; i<p->nAction+p->mnLookahead; i++){ +    if( p->aAction[i].lookahead<0 ){ +      for(j=0; j<p->nLookahead; j++){ +        k = p->aLookahead[j].lookahead - p->mnLookahead + i; +        if( k<0 ) break; +        if( p->aAction[k].lookahead>=0 ) break; +      } +      if( j<p->nLookahead ) continue; +      for(j=0; j<p->nAction; j++){ +        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break; +      } +      if( j==p->nAction ){ +        break;  /* Fits in empty slots */ +      } +    }else if( p->aAction[i].lookahead==p->mnLookahead ){ +      if( p->aAction[i].action!=p->mnAction ) continue; +      for(j=0; j<p->nLookahead; j++){ +        k = p->aLookahead[j].lookahead - p->mnLookahead + i; +        if( k<0 || k>=p->nAction ) break; +        if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break; +        if( p->aLookahead[j].action!=p->aAction[k].action ) break; +      } +      if( j<p->nLookahead ) continue; +      n = 0; +      for(j=0; j<p->nAction; j++){ +        if( p->aAction[j].lookahead<0 ) continue; +        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++; +      } +      if( n==p->nLookahead ){ +        break;  /* Same as a prior transaction set */ +      } +    } +  } +  /* Insert transaction set at index i. */ +  for(j=0; j<p->nLookahead; j++){ +    k = p->aLookahead[j].lookahead - p->mnLookahead + i; +    p->aAction[k] = p->aLookahead[j]; +    if( k>=p->nAction ) p->nAction = k+1; +  } +  p->nLookahead = 0; + +  /* Return the offset that is added to the lookahead in order to get the +  ** index into yy_action of the action */ +  return i - p->mnLookahead; +} + +/********************** From the file "assert.c" ****************************/ +/* +** A more efficient way of handling assertions. +*/ +void myassert(file,line) +char *file; +int line; +{ +  fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file); +  exit(1); +} +/********************** From the file "build.c" *****************************/ +/* +** Routines to construction the finite state machine for the LEMON +** parser generator. +*/ + +/* Find a precedence symbol of every rule in the grammar. +**  +** Those rules which have a precedence symbol coded in the input +** grammar using the "[symbol]" construct will already have the +** rp->precsym field filled.  Other rules take as their precedence +** symbol the first RHS symbol with a defined precedence.  If there +** are not RHS symbols with a defined precedence, the precedence +** symbol field is left blank. +*/ +void FindRulePrecedences(xp) +struct lemon *xp; +{ +  struct rule *rp; +  for(rp=xp->rule; rp; rp=rp->next){ +    if( rp->precsym==0 ){ +      int i; +      for(i=0; i<rp->nrhs; i++){ +        if( rp->rhs[i]->prec>=0 ){ +          rp->precsym = rp->rhs[i]; +          break; +	} +      } +    } +  } +  return; +} + +/* Find all nonterminals which will generate the empty string. +** Then go back and compute the first sets of every nonterminal. +** The first set is the set of all terminal symbols which can begin +** a string generated by that nonterminal. +*/ +void FindFirstSets(lemp) +struct lemon *lemp; +{ +  int i; +  struct rule *rp; +  int progress; + +  for(i=0; i<lemp->nsymbol; i++){ +    lemp->symbols[i]->lambda = B_FALSE; +  } +  for(i=lemp->nterminal; i<lemp->nsymbol; i++){ +    lemp->symbols[i]->firstset = SetNew(); +  } + +  /* First compute all lambdas */ +  do{ +    progress = 0; +    for(rp=lemp->rule; rp; rp=rp->next){ +      if( rp->lhs->lambda ) continue; +      for(i=0; i<rp->nrhs; i++){ +         if( rp->rhs[i]->lambda==B_FALSE ) break; +      } +      if( i==rp->nrhs ){ +        rp->lhs->lambda = B_TRUE; +        progress = 1; +      } +    } +  }while( progress ); + +  /* Now compute all first sets */ +  do{ +    struct symbol *s1, *s2; +    progress = 0; +    for(rp=lemp->rule; rp; rp=rp->next){ +      s1 = rp->lhs; +      for(i=0; i<rp->nrhs; i++){ +        s2 = rp->rhs[i]; +        if( s2->type==TERMINAL ){ +          progress += SetAdd(s1->firstset,s2->index); +          break; +	}else if( s1==s2 ){ +          if( s1->lambda==B_FALSE ) break; +	}else{ +          progress += SetUnion(s1->firstset,s2->firstset); +          if( s2->lambda==B_FALSE ) break; +	} +      } +    } +  }while( progress ); +  return; +} + +/* Compute all LR(0) states for the grammar.  Links +** are added to between some states so that the LR(1) follow sets +** can be computed later. +*/ +PRIVATE struct state *getstate(/* struct lemon * */);  /* forward reference */ +void FindStates(lemp) +struct lemon *lemp; +{ +  struct symbol *sp; +  struct rule *rp; + +  Configlist_init(); + +  /* Find the start symbol */ +  if( lemp->start ){ +    sp = Symbol_find(lemp->start); +    if( sp==0 ){ +      ErrorMsg(lemp->filename,0, +"The specified start symbol \"%s\" is not \ +in a nonterminal of the grammar.  \"%s\" will be used as the start \ +symbol instead.",lemp->start,lemp->rule->lhs->name); +      lemp->errorcnt++; +      sp = lemp->rule->lhs; +    } +  }else{ +    sp = lemp->rule->lhs; +  } + +  /* Make sure the start symbol doesn't occur on the right-hand side of +  ** any rule.  Report an error if it does.  (YACC would generate a new +  ** start symbol in this case.) */ +  for(rp=lemp->rule; rp; rp=rp->next){ +    int i; +    for(i=0; i<rp->nrhs; i++){ +      if( rp->rhs[i]==sp ){ +        ErrorMsg(lemp->filename,0, +"The start symbol \"%s\" occurs on the \ +right-hand side of a rule. This will result in a parser which \ +does not work properly.",sp->name); +        lemp->errorcnt++; +      } +    } +  } + +  /* The basis configuration set for the first state +  ** is all rules which have the start symbol as their +  ** left-hand side */ +  for(rp=sp->rule; rp; rp=rp->nextlhs){ +    struct config *newcfp; +    newcfp = Configlist_addbasis(rp,0); +    SetAdd(newcfp->fws,0); +  } + +  /* Compute the first state.  All other states will be +  ** computed automatically during the computation of the first one. +  ** The returned pointer to the first state is not used. */ +  (void)getstate(lemp); +  return; +} + +/* Return a pointer to a state which is described by the configuration +** list which has been built from calls to Configlist_add. +*/ +PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */ +PRIVATE struct state *getstate(lemp) +struct lemon *lemp; +{ +  struct config *cfp, *bp; +  struct state *stp; + +  /* Extract the sorted basis of the new state.  The basis was constructed +  ** by prior calls to "Configlist_addbasis()". */ +  Configlist_sortbasis(); +  bp = Configlist_basis(); + +  /* Get a state with the same basis */ +  stp = State_find(bp); +  if( stp ){ +    /* A state with the same basis already exists!  Copy all the follow-set +    ** propagation links from the state under construction into the +    ** preexisting state, then return a pointer to the preexisting state */ +    struct config *x, *y; +    for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){ +      Plink_copy(&y->bplp,x->bplp); +      Plink_delete(x->fplp); +      x->fplp = x->bplp = 0; +    } +    cfp = Configlist_return(); +    Configlist_eat(cfp); +  }else{ +    /* This really is a new state.  Construct all the details */ +    Configlist_closure(lemp);    /* Compute the configuration closure */ +    Configlist_sort();           /* Sort the configuration closure */ +    cfp = Configlist_return();   /* Get a pointer to the config list */ +    stp = State_new();           /* A new state structure */ +    MemoryCheck(stp); +    stp->bp = bp;                /* Remember the configuration basis */ +    stp->cfp = cfp;              /* Remember the configuration closure */ +    stp->index = lemp->nstate++; /* Every state gets a sequence number */ +    stp->ap = 0;                 /* No actions, yet. */ +    State_insert(stp,stp->bp);   /* Add to the state table */ +    buildshifts(lemp,stp);       /* Recursively compute successor states */ +  } +  return stp; +} + +/* Construct all successor states to the given state.  A "successor" +** state is any state which can be reached by a shift action. +*/ +PRIVATE void buildshifts(lemp,stp) +struct lemon *lemp; +struct state *stp;     /* The state from which successors are computed */ +{ +  struct config *cfp;  /* For looping thru the config closure of "stp" */ +  struct config *bcfp; /* For the inner loop on config closure of "stp" */ +  struct config *new;  /* */ +  struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */ +  struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */ +  struct state *newstp; /* A pointer to a successor state */ + +  /* Each configuration becomes complete after it contibutes to a successor +  ** state.  Initially, all configurations are incomplete */ +  for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE; + +  /* Loop through all configurations of the state "stp" */ +  for(cfp=stp->cfp; cfp; cfp=cfp->next){ +    if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */ +    if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */ +    Configlist_reset();                      /* Reset the new config set */ +    sp = cfp->rp->rhs[cfp->dot];             /* Symbol after the dot */ + +    /* For every configuration in the state "stp" which has the symbol "sp" +    ** following its dot, add the same configuration to the basis set under +    ** construction but with the dot shifted one symbol to the right. */ +    for(bcfp=cfp; bcfp; bcfp=bcfp->next){ +      if( bcfp->status==COMPLETE ) continue;    /* Already used */ +      if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */ +      bsp = bcfp->rp->rhs[bcfp->dot];           /* Get symbol after dot */ +      if( bsp!=sp ) continue;                   /* Must be same as for "cfp" */ +      bcfp->status = COMPLETE;                  /* Mark this config as used */ +      new = Configlist_addbasis(bcfp->rp,bcfp->dot+1); +      Plink_add(&new->bplp,bcfp); +    } + +    /* Get a pointer to the state described by the basis configuration set +    ** constructed in the preceding loop */ +    newstp = getstate(lemp); + +    /* The state "newstp" is reached from the state "stp" by a shift action +    ** on the symbol "sp" */ +    Action_add(&stp->ap,SHIFT,sp,(char *)newstp); +  } +} + +/* +** Construct the propagation links +*/ +void FindLinks(lemp) +struct lemon *lemp; +{ +  int i; +  struct config *cfp, *other; +  struct state *stp; +  struct plink *plp; + +  /* Housekeeping detail: +  ** Add to every propagate link a pointer back to the state to +  ** which the link is attached. */ +  for(i=0; i<lemp->nstate; i++){ +    stp = lemp->sorted[i]; +    for(cfp=stp->cfp; cfp; cfp=cfp->next){ +      cfp->stp = stp; +    } +  } + +  /* Convert all backlinks into forward links.  Only the forward +  ** links are used in the follow-set computation. */ +  for(i=0; i<lemp->nstate; i++){ +    stp = lemp->sorted[i]; +    for(cfp=stp->cfp; cfp; cfp=cfp->next){ +      for(plp=cfp->bplp; plp; plp=plp->next){ +        other = plp->cfp; +        Plink_add(&other->fplp,cfp); +      } +    } +  } +} + +/* Compute all followsets. +** +** A followset is the set of all symbols which can come immediately +** after a configuration. +*/ +void FindFollowSets(lemp) +struct lemon *lemp; +{ +  int i; +  struct config *cfp; +  struct plink *plp; +  int progress; +  int change; + +  for(i=0; i<lemp->nstate; i++){ +    for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ +      cfp->status = INCOMPLETE; +    } +  } +   +  do{ +    progress = 0; +    for(i=0; i<lemp->nstate; i++){ +      for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ +        if( cfp->status==COMPLETE ) continue; +        for(plp=cfp->fplp; plp; plp=plp->next){ +          change = SetUnion(plp->cfp->fws,cfp->fws); +          if( change ){ +            plp->cfp->status = INCOMPLETE; +            progress = 1; +	  } +	} +        cfp->status = COMPLETE; +      } +    } +  }while( progress ); +} + +static int resolve_conflict(); + +/* Compute the reduce actions, and resolve conflicts. +*/ +void FindActions(lemp) +struct lemon *lemp; +{ +  int i,j; +  struct config *cfp; +  struct state *stp; +  struct symbol *sp; +  struct rule *rp; + +  /* Add all of the reduce actions  +  ** A reduce action is added for each element of the followset of +  ** a configuration which has its dot at the extreme right. +  */ +  for(i=0; i<lemp->nstate; i++){   /* Loop over all states */ +    stp = lemp->sorted[i]; +    for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */ +      if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */ +        for(j=0; j<lemp->nterminal; j++){ +          if( SetFind(cfp->fws,j) ){ +            /* Add a reduce action to the state "stp" which will reduce by the +            ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ +            Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); +          } +	} +      } +    } +  } + +  /* Add the accepting token */ +  if( lemp->start ){ +    sp = Symbol_find(lemp->start); +    if( sp==0 ) sp = lemp->rule->lhs; +  }else{ +    sp = lemp->rule->lhs; +  } +  /* Add to the first state (which is always the starting state of the +  ** finite state machine) an action to ACCEPT if the lookahead is the +  ** start nonterminal.  */ +  Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); + +  /* Resolve conflicts */ +  for(i=0; i<lemp->nstate; i++){ +    struct action *ap, *nap; +    struct state *stp; +    stp = lemp->sorted[i]; +    assert( stp->ap ); +    stp->ap = Action_sort(stp->ap); +    for(ap=stp->ap; ap && ap->next; ap=ap->next){ +      for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ +         /* The two actions "ap" and "nap" have the same lookahead. +         ** Figure out which one should be used */ +         lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym); +      } +    } +  } + +  /* Report an error for each rule that can never be reduced. */ +  for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE; +  for(i=0; i<lemp->nstate; i++){ +    struct action *ap; +    for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ +      if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE; +    } +  } +  for(rp=lemp->rule; rp; rp=rp->next){ +    if( rp->canReduce ) continue; +    ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n"); +    lemp->errorcnt++; +  } +} + +/* Resolve a conflict between the two given actions.  If the +** conflict can't be resolve, return non-zero. +** +** NO LONGER TRUE: +**   To resolve a conflict, first look to see if either action +**   is on an error rule.  In that case, take the action which +**   is not associated with the error rule.  If neither or both +**   actions are associated with an error rule, then try to +**   use precedence to resolve the conflict. +** +** If either action is a SHIFT, then it must be apx.  This +** function won't work if apx->type==REDUCE and apy->type==SHIFT. +*/ +static int resolve_conflict(apx,apy,errsym) +struct action *apx; +struct action *apy; +struct symbol *errsym;   /* The error symbol (if defined.  NULL otherwise) */ +{ +  struct symbol *spx, *spy; +  int errcnt = 0; +  assert( apx->sp==apy->sp );  /* Otherwise there would be no conflict */ +  if( apx->type==SHIFT && apy->type==REDUCE ){ +    spx = apx->sp; +    spy = apy->x.rp->precsym; +    if( spy==0 || spx->prec<0 || spy->prec<0 ){ +      /* Not enough precedence information. */ +      apy->type = CONFLICT; +      errcnt++; +    }else if( spx->prec>spy->prec ){    /* Lower precedence wins */ +      apy->type = RD_RESOLVED; +    }else if( spx->prec<spy->prec ){ +      apx->type = SH_RESOLVED; +    }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ +      apy->type = RD_RESOLVED;                             /* associativity */ +    }else if( spx->prec==spy->prec && spx->assoc==LEFT ){  /* to break tie */ +      apx->type = SH_RESOLVED; +    }else{ +      assert( spx->prec==spy->prec && spx->assoc==NONE ); +      apy->type = CONFLICT; +      errcnt++; +    } +  }else if( apx->type==REDUCE && apy->type==REDUCE ){ +    spx = apx->x.rp->precsym; +    spy = apy->x.rp->precsym; +    if( spx==0 || spy==0 || spx->prec<0 || +    spy->prec<0 || spx->prec==spy->prec ){ +      apy->type = CONFLICT; +      errcnt++; +    }else if( spx->prec>spy->prec ){ +      apy->type = RD_RESOLVED; +    }else if( spx->prec<spy->prec ){ +      apx->type = RD_RESOLVED; +    } +  }else{ +    assert(  +      apx->type==SH_RESOLVED || +      apx->type==RD_RESOLVED || +      apx->type==CONFLICT || +      apy->type==SH_RESOLVED || +      apy->type==RD_RESOLVED || +      apy->type==CONFLICT +    ); +    /* The REDUCE/SHIFT case cannot happen because SHIFTs come before +    ** REDUCEs on the list.  If we reach this point it must be because +    ** the parser conflict had already been resolved. */ +  } +  return errcnt; +} +/********************* From the file "configlist.c" *************************/ +/* +** Routines to processing a configuration list and building a state +** in the LEMON parser generator. +*/ + +static struct config *freelist = 0;      /* List of free configurations */ +static struct config *current = 0;       /* Top of list of configurations */ +static struct config **currentend = 0;   /* Last on list of configs */ +static struct config *basis = 0;         /* Top of list of basis configs */ +static struct config **basisend = 0;     /* End of list of basis configs */ + +/* Return a pointer to a new configuration */ +PRIVATE struct config *newconfig(){ +  struct config *new; +  if( freelist==0 ){ +    int i; +    int amt = 3; +    freelist = (struct config *)malloc( sizeof(struct config)*amt ); +    if( freelist==0 ){ +      fprintf(stderr,"Unable to allocate memory for a new configuration."); +      exit(1); +    } +    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1]; +    freelist[amt-1].next = 0; +  } +  new = freelist; +  freelist = freelist->next; +  return new; +} + +/* The configuration "old" is no longer used */ +PRIVATE void deleteconfig(old) +struct config *old; +{ +  old->next = freelist; +  freelist = old; +} + +/* Initialized the configuration list builder */ +void Configlist_init(){ +  current = 0; +  currentend = ¤t; +  basis = 0; +  basisend = &basis; +  Configtable_init(); +  return; +} + +/* Initialized the configuration list builder */ +void Configlist_reset(){ +  current = 0; +  currentend = ¤t; +  basis = 0; +  basisend = &basis; +  Configtable_clear(0); +  return; +} + +/* Add another configuration to the configuration list */ +struct config *Configlist_add(rp,dot) +struct rule *rp;    /* The rule */ +int dot;            /* Index into the RHS of the rule where the dot goes */ +{ +  struct config *cfp, model; + +  assert( currentend!=0 ); +  model.rp = rp; +  model.dot = dot; +  cfp = Configtable_find(&model); +  if( cfp==0 ){ +    cfp = newconfig(); +    cfp->rp = rp; +    cfp->dot = dot; +    cfp->fws = SetNew(); +    cfp->stp = 0; +    cfp->fplp = cfp->bplp = 0; +    cfp->next = 0; +    cfp->bp = 0; +    *currentend = cfp; +    currentend = &cfp->next; +    Configtable_insert(cfp); +  } +  return cfp; +} + +/* Add a basis configuration to the configuration list */ +struct config *Configlist_addbasis(rp,dot) +struct rule *rp; +int dot; +{ +  struct config *cfp, model; + +  assert( basisend!=0 ); +  assert( currentend!=0 ); +  model.rp = rp; +  model.dot = dot; +  cfp = Configtable_find(&model); +  if( cfp==0 ){ +    cfp = newconfig(); +    cfp->rp = rp; +    cfp->dot = dot; +    cfp->fws = SetNew(); +    cfp->stp = 0; +    cfp->fplp = cfp->bplp = 0; +    cfp->next = 0; +    cfp->bp = 0; +    *currentend = cfp; +    currentend = &cfp->next; +    *basisend = cfp; +    basisend = &cfp->bp; +    Configtable_insert(cfp); +  } +  return cfp; +} + +/* Compute the closure of the configuration list */ +void Configlist_closure(lemp) +struct lemon *lemp; +{ +  struct config *cfp, *newcfp; +  struct rule *rp, *newrp; +  struct symbol *sp, *xsp; +  int i, dot; + +  assert( currentend!=0 ); +  for(cfp=current; cfp; cfp=cfp->next){ +    rp = cfp->rp; +    dot = cfp->dot; +    if( dot>=rp->nrhs ) continue; +    sp = rp->rhs[dot]; +    if( sp->type==NONTERMINAL ){ +      if( sp->rule==0 && sp!=lemp->errsym ){ +        ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.", +          sp->name); +        lemp->errorcnt++; +      } +      for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){ +        newcfp = Configlist_add(newrp,0); +        for(i=dot+1; i<rp->nrhs; i++){ +          xsp = rp->rhs[i]; +          if( xsp->type==TERMINAL ){ +            SetAdd(newcfp->fws,xsp->index); +            break; +	  }else{ +            SetUnion(newcfp->fws,xsp->firstset); +            if( xsp->lambda==B_FALSE ) break; +	  } +	} +        if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); +      } +    } +  } +  return; +} + +/* Sort the configuration list */ +void Configlist_sort(){ +  current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); +  currentend = 0; +  return; +} + +/* Sort the basis configuration list */ +void Configlist_sortbasis(){ +  basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp); +  basisend = 0; +  return; +} + +/* Return a pointer to the head of the configuration list and +** reset the list */ +struct config *Configlist_return(){ +  struct config *old; +  old = current; +  current = 0; +  currentend = 0; +  return old; +} + +/* Return a pointer to the head of the configuration list and +** reset the list */ +struct config *Configlist_basis(){ +  struct config *old; +  old = basis; +  basis = 0; +  basisend = 0; +  return old; +} + +/* Free all elements of the given configuration list */ +void Configlist_eat(cfp) +struct config *cfp; +{ +  struct config *nextcfp; +  for(; cfp; cfp=nextcfp){ +    nextcfp = cfp->next; +    assert( cfp->fplp==0 ); +    assert( cfp->bplp==0 ); +    if( cfp->fws ) SetFree(cfp->fws); +    deleteconfig(cfp); +  } +  return; +} +/***************** From the file "error.c" *********************************/ +/* +** Code for printing error message. +*/ + +/* Find a good place to break "msg" so that its length is at least "min" +** but no more than "max".  Make the point as close to max as possible. +*/ +static int findbreak(msg,min,max) +char *msg; +int min; +int max; +{ +  int i,spot; +  char c; +  for(i=spot=min; i<=max; i++){ +    c = msg[i]; +    if( c=='\t' ) msg[i] = ' '; +    if( c=='\n' ){ msg[i] = ' '; spot = i; break; } +    if( c==0 ){ spot = i; break; } +    if( c=='-' && i<max-1 ) spot = i+1; +    if( c==' ' ) spot = i; +  } +  return spot; +} + +/* +** The error message is split across multiple lines if necessary.  The +** splits occur at a space, if there is a space available near the end +** of the line. +*/ +#define ERRMSGSIZE  10000 /* Hope this is big enough.  No way to error check */ +#define LINEWIDTH      79 /* Max width of any output line */ +#define PREFIXLIMIT    30 /* Max width of the prefix on each line */ +void ErrorMsg(const char *filename, int lineno, const char *format, ...){ +  char errmsg[ERRMSGSIZE]; +  char prefix[PREFIXLIMIT+10]; +  int errmsgsize; +  int prefixsize; +  int availablewidth; +  va_list ap; +  int end, restart, base; + +  va_start(ap, format); +  /* Prepare a prefix to be prepended to every output line */ +  if( lineno>0 ){ +    sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno); +  }else{ +    sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename); +  } +  prefixsize = strlen(prefix); +  availablewidth = LINEWIDTH - prefixsize; + +  /* Generate the error message */ +  vsprintf(errmsg,format,ap); +  va_end(ap); +  errmsgsize = strlen(errmsg); +  /* Remove trailing '\n's from the error message. */ +  while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){ +     errmsg[--errmsgsize] = 0; +  } + +  /* Print the error message */ +  base = 0; +  while( errmsg[base]!=0 ){ +    end = restart = findbreak(&errmsg[base],0,availablewidth); +    restart += base; +    while( errmsg[restart]==' ' ) restart++; +    fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]); +    base = restart; +  } +} +/**************** From the file "main.c" ************************************/ +/* +** Main program file for the LEMON parser generator. +*/ + +/* Report an out-of-memory condition and abort.  This function +** is used mostly by the "MemoryCheck" macro in struct.h +*/ +void memory_error(){ +  fprintf(stderr,"Out of memory.  Aborting...\n"); +  exit(1); +} + +static int nDefine = 0;      /* Number of -D options on the command line */ +static char **azDefine = 0;  /* Name of the -D macros */ + +/* This routine is called with the argument to each -D command-line option. +** Add the macro defined to the azDefine array. +*/ +static void handle_D_option(char *z){ +  char **paz; +  nDefine++; +  azDefine = realloc(azDefine, sizeof(azDefine[0])*nDefine); +  if( azDefine==0 ){ +    fprintf(stderr,"out of memory\n"); +    exit(1); +  } +  paz = &azDefine[nDefine-1]; +  *paz = malloc( strlen(z)+1 ); +  if( *paz==0 ){ +    fprintf(stderr,"out of memory\n"); +    exit(1); +  } +  strcpy(*paz, z); +  for(z=*paz; *z && *z!='='; z++){} +  *z = 0; +} + + +/* The main program.  Parse the command line and do it... */ +int main(argc,argv) +int argc; +char **argv; +{ +  static int version = 0; +  static int rpflag = 0; +  static int basisflag = 0; +  static int compress = 0; +  static int quiet = 0; +  static int statistics = 0; +  static int mhflag = 0; +  static struct s_options options[] = { +    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, +    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, +    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, +    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, +    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"}, +    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, +    {OPT_FLAG, "s", (char*)&statistics, +                                   "Print parser stats to standard output."}, +    {OPT_FLAG, "x", (char*)&version, "Print the version number."}, +    {OPT_FLAG,0,0,0} +  }; +  int i; +  struct lemon lem; + +  OptInit(argv,options,stderr); +  if( version ){ +     printf("Lemon version 1.0\n"); +     exit(0);  +  } +  if( OptNArgs()!=1 ){ +    fprintf(stderr,"Exactly one filename argument is required.\n"); +    exit(1); +  } +  lem.errorcnt = 0; + +  /* Initialize the machine */ +  Strsafe_init(); +  Symbol_init(); +  State_init(); +  lem.argv0 = argv[0]; +  lem.filename = OptArg(0); +  lem.basisflag = basisflag; +  lem.has_fallback = 0; +  lem.nconflict = 0; +  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0; +  lem.vartype = 0; +  lem.stacksize = 0; +  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest = +     lem.tokenprefix = lem.outname = lem.extracode = 0; +  lem.vardest = 0; +  lem.tablesize = 0; +  Symbol_new("$"); +  lem.errsym = Symbol_new("error"); + +  /* Parse the input file */ +  Parse(&lem); +  if( lem.errorcnt ) exit(lem.errorcnt); +  if( lem.rule==0 ){ +    fprintf(stderr,"Empty grammar.\n"); +    exit(1); +  } + +  /* Count and index the symbols of the grammar */ +  lem.nsymbol = Symbol_count(); +  Symbol_new("{default}"); +  lem.symbols = Symbol_arrayof(); +  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; +  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), +        (int(*)())Symbolcmpp); +  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; +  for(i=1; isupper(lem.symbols[i]->name[0]); i++); +  lem.nterminal = i; + +  /* Generate a reprint of the grammar, if requested on the command line */ +  if( rpflag ){ +    Reprint(&lem); +  }else{ +    /* Initialize the size for all follow and first sets */ +    SetSize(lem.nterminal); + +    /* Find the precedence for every production rule (that has one) */ +    FindRulePrecedences(&lem); + +    /* Compute the lambda-nonterminals and the first-sets for every +    ** nonterminal */ +    FindFirstSets(&lem); + +    /* Compute all LR(0) states.  Also record follow-set propagation +    ** links so that the follow-set can be computed later */ +    lem.nstate = 0; +    FindStates(&lem); +    lem.sorted = State_arrayof(); + +    /* Tie up loose ends on the propagation links */ +    FindLinks(&lem); + +    /* Compute the follow set of every reducible configuration */ +    FindFollowSets(&lem); + +    /* Compute the action tables */ +    FindActions(&lem); + +    /* Compress the action tables */ +    if( compress==0 ) CompressTables(&lem); + +    /* Generate a report of the parser generated.  (the "y.output" file) */ +    if( !quiet ) ReportOutput(&lem); + +    /* Generate the source code for the parser */ +    ReportTable(&lem, mhflag); + +    /* Produce a header file for use by the scanner.  (This step is +    ** omitted if the "-m" option is used because makeheaders will +    ** generate the file for us.) */ +    if( !mhflag ) ReportHeader(&lem); +  } +  if( statistics ){ +    printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n", +      lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); +    printf("                   %d states, %d parser table entries, %d conflicts\n", +      lem.nstate, lem.tablesize, lem.nconflict); +  } +  if( lem.nconflict ){ +    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); +  } +  exit(lem.errorcnt + lem.nconflict); +  return (lem.errorcnt + lem.nconflict); +} +/******************** From the file "msort.c" *******************************/ +/* +** A generic merge-sort program. +** +** USAGE: +** Let "ptr" be a pointer to some structure which is at the head of +** a null-terminated list.  Then to sort the list call: +** +**     ptr = msort(ptr,&(ptr->next),cmpfnc); +** +** In the above, "cmpfnc" is a pointer to a function which compares +** two instances of the structure and returns an integer, as in +** strcmp.  The second argument is a pointer to the pointer to the +** second element of the linked list.  This address is used to compute +** the offset to the "next" field within the structure.  The offset to +** the "next" field must be constant for all structures in the list. +** +** The function returns a new pointer which is the head of the list +** after sorting. +** +** ALGORITHM: +** Merge-sort. +*/ + +/* +** Return a pointer to the next structure in the linked list. +*/ +#define NEXT(A) (*(char**)(((unsigned long)A)+offset)) + +/* +** Inputs: +**   a:       A sorted, null-terminated linked list.  (May be null). +**   b:       A sorted, null-terminated linked list.  (May be null). +**   cmp:     A pointer to the comparison function. +**   offset:  Offset in the structure to the "next" field. +** +** Return Value: +**   A pointer to the head of a sorted list containing the elements +**   of both a and b. +** +** Side effects: +**   The "next" pointers for elements in the lists a and b are +**   changed. +*/ +static char *merge(a,b,cmp,offset) +char *a; +char *b; +int (*cmp)(); +int offset; +{ +  char *ptr, *head; + +  if( a==0 ){ +    head = b; +  }else if( b==0 ){ +    head = a; +  }else{ +    if( (*cmp)(a,b)<0 ){ +      ptr = a; +      a = NEXT(a); +    }else{ +      ptr = b; +      b = NEXT(b); +    } +    head = ptr; +    while( a && b ){ +      if( (*cmp)(a,b)<0 ){ +        NEXT(ptr) = a; +        ptr = a; +        a = NEXT(a); +      }else{ +        NEXT(ptr) = b; +        ptr = b; +        b = NEXT(b); +      } +    } +    if( a ) NEXT(ptr) = a; +    else    NEXT(ptr) = b; +  } +  return head; +} + +/* +** Inputs: +**   list:      Pointer to a singly-linked list of structures. +**   next:      Pointer to pointer to the second element of the list. +**   cmp:       A comparison function. +** +** Return Value: +**   A pointer to the head of a sorted list containing the elements +**   orginally in list. +** +** Side effects: +**   The "next" pointers for elements in list are changed. +*/ +#define LISTSIZE 30 +char *msort(list,next,cmp) +char *list; +char **next; +int (*cmp)(); +{ +  unsigned long offset; +  char *ep; +  char *set[LISTSIZE]; +  int i; +  offset = (unsigned long)next - (unsigned long)list; +  for(i=0; i<LISTSIZE; i++) set[i] = 0; +  while( list ){ +    ep = list; +    list = NEXT(list); +    NEXT(ep) = 0; +    for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ +      ep = merge(ep,set[i],cmp,offset); +      set[i] = 0; +    } +    set[i] = ep; +  } +  ep = 0; +  for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset); +  return ep; +} +/************************ From the file "option.c" **************************/ +static char **argv; +static struct s_options *op; +static FILE *errstream; + +#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0) + +/* +** Print the command line with a carrot pointing to the k-th character +** of the n-th field. +*/ +static void errline(n,k,err) +int n; +int k; +FILE *err; +{ +  int spcnt, i; +  spcnt = 0; +  if( argv[0] ) fprintf(err,"%s",argv[0]); +  spcnt = strlen(argv[0]) + 1; +  for(i=1; i<n && argv[i]; i++){ +    fprintf(err," %s",argv[i]); +    spcnt += strlen(argv[i]+1); +  } +  spcnt += k; +  for(; argv[i]; i++) fprintf(err," %s",argv[i]); +  if( spcnt<20 ){ +    fprintf(err,"\n%*s^-- here\n",spcnt,""); +  }else{ +    fprintf(err,"\n%*shere --^\n",spcnt-7,""); +  } +} + +/* +** Return the index of the N-th non-switch argument.  Return -1 +** if N is out of range. +*/ +static int argindex(n) +int n; +{ +  int i; +  int dashdash = 0; +  if( argv!=0 && *argv!=0 ){ +    for(i=1; argv[i]; i++){ +      if( dashdash || !ISOPT(argv[i]) ){ +        if( n==0 ) return i; +        n--; +      } +      if( strcmp(argv[i],"--")==0 ) dashdash = 1; +    } +  } +  return -1; +} + +static char emsg[] = "Command line syntax error: "; + +/* +** Process a flag command line argument. +*/ +static int handleflags(i,err) +int i; +FILE *err; +{ +  int v; +  int errcnt = 0; +  int j; +  for(j=0; op[j].label; j++){ +    if( strncmp(&argv[i][1],op[j].label,strlen(op[j].label))==0 ) break; +  } +  v = argv[i][0]=='-' ? 1 : 0; +  if( op[j].label==0 ){ +    if( err ){ +      fprintf(err,"%sundefined option.\n",emsg); +      errline(i,1,err); +    } +    errcnt++; +  }else if( op[j].type==OPT_FLAG ){ +    *((int*)op[j].arg) = v; +  }else if( op[j].type==OPT_FFLAG ){ +    (*(void(*)())(op[j].arg))(v); +  }else if( op[j].type==OPT_FSTR ){ +    (*(void(*)())(op[j].arg))(&argv[i][2]); +  }else{ +    if( err ){ +      fprintf(err,"%smissing argument on switch.\n",emsg); +      errline(i,1,err); +    } +    errcnt++; +  } +  return errcnt; +} + +/* +** Process a command line switch which has an argument. +*/ +static int handleswitch(i,err) +int i; +FILE *err; +{ +  int lv = 0; +  double dv = 0.0; +  char *sv = 0, *end; +  char *cp; +  int j; +  int errcnt = 0; +  cp = strchr(argv[i],'='); +  *cp = 0; +  for(j=0; op[j].label; j++){ +    if( strcmp(argv[i],op[j].label)==0 ) break; +  } +  *cp = '='; +  if( op[j].label==0 ){ +    if( err ){ +      fprintf(err,"%sundefined option.\n",emsg); +      errline(i,0,err); +    } +    errcnt++; +  }else{ +    cp++; +    switch( op[j].type ){ +      case OPT_FLAG: +      case OPT_FFLAG: +        if( err ){ +          fprintf(err,"%soption requires an argument.\n",emsg); +          errline(i,0,err); +        } +        errcnt++; +        break; +      case OPT_DBL: +      case OPT_FDBL: +        dv = strtod(cp,&end); +        if( *end ){ +          if( err ){ +            fprintf(err,"%sillegal character in floating-point argument.\n",emsg); +            errline(i,((unsigned long)end)-(unsigned long)argv[i],err); +          } +          errcnt++; +        } +        break; +      case OPT_INT: +      case OPT_FINT: +        lv = strtol(cp,&end,0); +        if( *end ){ +          if( err ){ +            fprintf(err,"%sillegal character in integer argument.\n",emsg); +            errline(i,((unsigned long)end)-(unsigned long)argv[i],err); +          } +          errcnt++; +        } +        break; +      case OPT_STR: +      case OPT_FSTR: +        sv = cp; +        break; +    } +    switch( op[j].type ){ +      case OPT_FLAG: +      case OPT_FFLAG: +        break; +      case OPT_DBL: +        *(double*)(op[j].arg) = dv; +        break; +      case OPT_FDBL: +        (*(void(*)())(op[j].arg))(dv); +        break; +      case OPT_INT: +        *(int*)(op[j].arg) = lv; +        break; +      case OPT_FINT: +        (*(void(*)())(op[j].arg))((int)lv); +        break; +      case OPT_STR: +        *(char**)(op[j].arg) = sv; +        break; +      case OPT_FSTR: +        (*(void(*)())(op[j].arg))(sv); +        break; +    } +  } +  return errcnt; +} + +int OptInit(a,o,err) +char **a; +struct s_options *o; +FILE *err; +{ +  int errcnt = 0; +  argv = a; +  op = o; +  errstream = err; +  if( argv && *argv && op ){ +    int i; +    for(i=1; argv[i]; i++){ +      if( argv[i][0]=='+' || argv[i][0]=='-' ){ +        errcnt += handleflags(i,err); +      }else if( strchr(argv[i],'=') ){ +        errcnt += handleswitch(i,err); +      } +    } +  } +  if( errcnt>0 ){ +    fprintf(err,"Valid command line options for \"%s\" are:\n",*a); +    OptPrint(); +    exit(1); +  } +  return 0; +} + +int OptNArgs(){ +  int cnt = 0; +  int dashdash = 0; +  int i; +  if( argv!=0 && argv[0]!=0 ){ +    for(i=1; argv[i]; i++){ +      if( dashdash || !ISOPT(argv[i]) ) cnt++; +      if( strcmp(argv[i],"--")==0 ) dashdash = 1; +    } +  } +  return cnt; +} + +char *OptArg(n) +int n; +{ +  int i; +  i = argindex(n); +  return i>=0 ? argv[i] : 0; +} + +void OptErr(n) +int n; +{ +  int i; +  i = argindex(n); +  if( i>=0 ) errline(i,0,errstream); +} + +void OptPrint(){ +  int i; +  int max, len; +  max = 0; +  for(i=0; op[i].label; i++){ +    len = strlen(op[i].label) + 1; +    switch( op[i].type ){ +      case OPT_FLAG: +      case OPT_FFLAG: +        break; +      case OPT_INT: +      case OPT_FINT: +        len += 9;       /* length of "<integer>" */ +        break; +      case OPT_DBL: +      case OPT_FDBL: +        len += 6;       /* length of "<real>" */ +        break; +      case OPT_STR: +      case OPT_FSTR: +        len += 8;       /* length of "<string>" */ +        break; +    } +    if( len>max ) max = len; +  } +  for(i=0; op[i].label; i++){ +    switch( op[i].type ){ +      case OPT_FLAG: +      case OPT_FFLAG: +        fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message); +        break; +      case OPT_INT: +      case OPT_FINT: +        fprintf(errstream,"  %s=<integer>%*s  %s\n",op[i].label, +          (int)(max-strlen(op[i].label)-9),"",op[i].message); +        break; +      case OPT_DBL: +      case OPT_FDBL: +        fprintf(errstream,"  %s=<real>%*s  %s\n",op[i].label, +          (int)(max-strlen(op[i].label)-6),"",op[i].message); +        break; +      case OPT_STR: +      case OPT_FSTR: +        fprintf(errstream,"  %s=<string>%*s  %s\n",op[i].label, +          (int)(max-strlen(op[i].label)-8),"",op[i].message); +        break; +    } +  } +} +/*********************** From the file "parse.c" ****************************/ +/* +** Input file parser for the LEMON parser generator. +*/ + +/* The state of the parser */ +struct pstate { +  char *filename;       /* Name of the input file */ +  int tokenlineno;      /* Linenumber at which current token starts */ +  int errorcnt;         /* Number of errors so far */ +  char *tokenstart;     /* Text of current token */ +  struct lemon *gp;     /* Global state vector */ +  enum e_state { +    INITIALIZE, +    WAITING_FOR_DECL_OR_RULE, +    WAITING_FOR_DECL_KEYWORD, +    WAITING_FOR_DECL_ARG, +    WAITING_FOR_PRECEDENCE_SYMBOL, +    WAITING_FOR_ARROW, +    IN_RHS, +    LHS_ALIAS_1, +    LHS_ALIAS_2, +    LHS_ALIAS_3, +    RHS_ALIAS_1, +    RHS_ALIAS_2, +    PRECEDENCE_MARK_1, +    PRECEDENCE_MARK_2, +    RESYNC_AFTER_RULE_ERROR, +    RESYNC_AFTER_DECL_ERROR, +    WAITING_FOR_DESTRUCTOR_SYMBOL, +    WAITING_FOR_DATATYPE_SYMBOL, +    WAITING_FOR_FALLBACK_ID +  } state;                   /* The state of the parser */ +  struct symbol *fallback;   /* The fallback token */ +  struct symbol *lhs;        /* Left-hand side of current rule */ +  char *lhsalias;            /* Alias for the LHS */ +  int nrhs;                  /* Number of right-hand side symbols seen */ +  struct symbol *rhs[MAXRHS];  /* RHS symbols */ +  char *alias[MAXRHS];       /* Aliases for each RHS symbol (or NULL) */ +  struct rule *prevrule;     /* Previous rule parsed */ +  char *declkeyword;         /* Keyword of a declaration */ +  char **declargslot;        /* Where the declaration argument should be put */ +  int *decllnslot;           /* Where the declaration linenumber is put */ +  enum e_assoc declassoc;    /* Assign this association to decl arguments */ +  int preccounter;           /* Assign this precedence to decl arguments */ +  struct rule *firstrule;    /* Pointer to first rule in the grammar */ +  struct rule *lastrule;     /* Pointer to the most recently parsed rule */ +}; + +/* Parse a single token */ +static void parseonetoken(psp) +struct pstate *psp; +{ +  char *x; +  x = Strsafe(psp->tokenstart);     /* Save the token permanently */ +#if 0 +  printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno, +    x,psp->state); +#endif +  switch( psp->state ){ +    case INITIALIZE: +      psp->prevrule = 0; +      psp->preccounter = 0; +      psp->firstrule = psp->lastrule = 0; +      psp->gp->nrule = 0; +      /* Fall thru to next case */ +    case WAITING_FOR_DECL_OR_RULE: +      if( x[0]=='%' ){ +        psp->state = WAITING_FOR_DECL_KEYWORD; +      }else if( islower(x[0]) ){ +        psp->lhs = Symbol_new(x); +        psp->nrhs = 0; +        psp->lhsalias = 0; +        psp->state = WAITING_FOR_ARROW; +      }else if( x[0]=='{' ){ +        if( psp->prevrule==0 ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +"There is not prior rule opon which to attach the code \ +fragment which begins on this line."); +          psp->errorcnt++; +	}else if( psp->prevrule->code!=0 ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +"Code fragment beginning on this line is not the first \ +to follow the previous rule."); +          psp->errorcnt++; +        }else{ +          psp->prevrule->line = psp->tokenlineno; +          psp->prevrule->code = &x[1]; +	} +      }else if( x[0]=='[' ){ +        psp->state = PRECEDENCE_MARK_1; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Token \"%s\" should be either \"%%\" or a nonterminal name.", +          x); +        psp->errorcnt++; +      } +      break; +    case PRECEDENCE_MARK_1: +      if( !isupper(x[0]) ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "The precedence symbol must be a terminal."); +        psp->errorcnt++; +      }else if( psp->prevrule==0 ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "There is no prior rule to assign precedence \"[%s]\".",x); +        psp->errorcnt++; +      }else if( psp->prevrule->precsym!=0 ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +"Precedence mark on this line is not the first \ +to follow the previous rule."); +        psp->errorcnt++; +      }else{ +        psp->prevrule->precsym = Symbol_new(x); +      } +      psp->state = PRECEDENCE_MARK_2; +      break; +    case PRECEDENCE_MARK_2: +      if( x[0]!=']' ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Missing \"]\" on precedence mark."); +        psp->errorcnt++; +      } +      psp->state = WAITING_FOR_DECL_OR_RULE; +      break; +    case WAITING_FOR_ARROW: +      if( x[0]==':' && x[1]==':' && x[2]=='=' ){ +        psp->state = IN_RHS; +      }else if( x[0]=='(' ){ +        psp->state = LHS_ALIAS_1; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Expected to see a \":\" following the LHS symbol \"%s\".", +          psp->lhs->name); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case LHS_ALIAS_1: +      if( isalpha(x[0]) ){ +        psp->lhsalias = x; +        psp->state = LHS_ALIAS_2; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "\"%s\" is not a valid alias for the LHS \"%s\"\n", +          x,psp->lhs->name); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case LHS_ALIAS_2: +      if( x[0]==')' ){ +        psp->state = LHS_ALIAS_3; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case LHS_ALIAS_3: +      if( x[0]==':' && x[1]==':' && x[2]=='=' ){ +        psp->state = IN_RHS; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Missing \"->\" following: \"%s(%s)\".", +           psp->lhs->name,psp->lhsalias); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case IN_RHS: +      if( x[0]=='.' ){ +        struct rule *rp; +        rp = (struct rule *)malloc( sizeof(struct rule) +  +             sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs ); +        if( rp==0 ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +            "Can't allocate enough memory for this rule."); +          psp->errorcnt++; +          psp->prevrule = 0; +	}else{ +          int i; +          rp->ruleline = psp->tokenlineno; +          rp->rhs = (struct symbol**)&rp[1]; +          rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]); +          for(i=0; i<psp->nrhs; i++){ +            rp->rhs[i] = psp->rhs[i]; +            rp->rhsalias[i] = psp->alias[i]; +	  } +          rp->lhs = psp->lhs; +          rp->lhsalias = psp->lhsalias; +          rp->nrhs = psp->nrhs; +          rp->code = 0; +          rp->precsym = 0; +          rp->index = psp->gp->nrule++; +          rp->nextlhs = rp->lhs->rule; +          rp->lhs->rule = rp; +          rp->next = 0; +          if( psp->firstrule==0 ){ +            psp->firstrule = psp->lastrule = rp; +	  }else{ +            psp->lastrule->next = rp; +            psp->lastrule = rp; +	  } +          psp->prevrule = rp; +	} +        psp->state = WAITING_FOR_DECL_OR_RULE; +      }else if( isalpha(x[0]) ){ +        if( psp->nrhs>=MAXRHS ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +            "Too many symbol on RHS or rule beginning at \"%s\".", +            x); +          psp->errorcnt++; +          psp->state = RESYNC_AFTER_RULE_ERROR; +	}else{ +          psp->rhs[psp->nrhs] = Symbol_new(x); +          psp->alias[psp->nrhs] = 0; +          psp->nrhs++; +	} +      }else if( x[0]=='(' && psp->nrhs>0 ){ +        psp->state = RHS_ALIAS_1; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Illegal character on RHS of rule: \"%s\".",x); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case RHS_ALIAS_1: +      if( isalpha(x[0]) ){ +        psp->alias[psp->nrhs-1] = x; +        psp->state = RHS_ALIAS_2; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", +          x,psp->rhs[psp->nrhs-1]->name); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case RHS_ALIAS_2: +      if( x[0]==')' ){ +        psp->state = IN_RHS; +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_RULE_ERROR; +      } +      break; +    case WAITING_FOR_DECL_KEYWORD: +      if( isalpha(x[0]) ){ +        psp->declkeyword = x; +        psp->declargslot = 0; +        psp->decllnslot = 0; +        psp->state = WAITING_FOR_DECL_ARG; +        if( strcmp(x,"name")==0 ){ +          psp->declargslot = &(psp->gp->name); +	}else if( strcmp(x,"include")==0 ){ +          psp->declargslot = &(psp->gp->include); +          psp->decllnslot = &psp->gp->includeln; +	}else if( strcmp(x,"code")==0 ){ +          psp->declargslot = &(psp->gp->extracode); +          psp->decllnslot = &psp->gp->extracodeln; +	}else if( strcmp(x,"token_destructor")==0 ){ +          psp->declargslot = &psp->gp->tokendest; +          psp->decllnslot = &psp->gp->tokendestln; +	}else if( strcmp(x,"default_destructor")==0 ){ +          psp->declargslot = &psp->gp->vardest; +          psp->decllnslot = &psp->gp->vardestln; +	}else if( strcmp(x,"token_prefix")==0 ){ +          psp->declargslot = &psp->gp->tokenprefix; +	}else if( strcmp(x,"syntax_error")==0 ){ +          psp->declargslot = &(psp->gp->error); +          psp->decllnslot = &psp->gp->errorln; +	}else if( strcmp(x,"parse_accept")==0 ){ +          psp->declargslot = &(psp->gp->accept); +          psp->decllnslot = &psp->gp->acceptln; +	}else if( strcmp(x,"parse_failure")==0 ){ +          psp->declargslot = &(psp->gp->failure); +          psp->decllnslot = &psp->gp->failureln; +	}else if( strcmp(x,"stack_overflow")==0 ){ +          psp->declargslot = &(psp->gp->overflow); +          psp->decllnslot = &psp->gp->overflowln; +        }else if( strcmp(x,"extra_argument")==0 ){ +          psp->declargslot = &(psp->gp->arg); +        }else if( strcmp(x,"token_type")==0 ){ +          psp->declargslot = &(psp->gp->tokentype); +        }else if( strcmp(x,"default_type")==0 ){ +          psp->declargslot = &(psp->gp->vartype); +        }else if( strcmp(x,"stack_size")==0 ){ +          psp->declargslot = &(psp->gp->stacksize); +        }else if( strcmp(x,"start_symbol")==0 ){ +          psp->declargslot = &(psp->gp->start); +        }else if( strcmp(x,"left")==0 ){ +          psp->preccounter++; +          psp->declassoc = LEFT; +          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; +        }else if( strcmp(x,"right")==0 ){ +          psp->preccounter++; +          psp->declassoc = RIGHT; +          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; +        }else if( strcmp(x,"nonassoc")==0 ){ +          psp->preccounter++; +          psp->declassoc = NONE; +          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; +	}else if( strcmp(x,"destructor")==0 ){ +          psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; +	}else if( strcmp(x,"type")==0 ){ +          psp->state = WAITING_FOR_DATATYPE_SYMBOL; +        }else if( strcmp(x,"fallback")==0 ){ +          psp->fallback = 0; +          psp->state = WAITING_FOR_FALLBACK_ID; +        }else{ +          ErrorMsg(psp->filename,psp->tokenlineno, +            "Unknown declaration keyword: \"%%%s\".",x); +          psp->errorcnt++; +          psp->state = RESYNC_AFTER_DECL_ERROR; +	} +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Illegal declaration keyword: \"%s\".",x); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_DECL_ERROR; +      } +      break; +    case WAITING_FOR_DESTRUCTOR_SYMBOL: +      if( !isalpha(x[0]) ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Symbol name missing after %destructor keyword"); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_DECL_ERROR; +      }else{ +        struct symbol *sp = Symbol_new(x); +        psp->declargslot = &sp->destructor; +        psp->decllnslot = &sp->destructorln; +        psp->state = WAITING_FOR_DECL_ARG; +      } +      break; +    case WAITING_FOR_DATATYPE_SYMBOL: +      if( !isalpha(x[0]) ){ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Symbol name missing after %destructor keyword"); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_DECL_ERROR; +      }else{ +        struct symbol *sp = Symbol_new(x); +        psp->declargslot = &sp->datatype; +        psp->decllnslot = 0; +        psp->state = WAITING_FOR_DECL_ARG; +      } +      break; +    case WAITING_FOR_PRECEDENCE_SYMBOL: +      if( x[0]=='.' ){ +        psp->state = WAITING_FOR_DECL_OR_RULE; +      }else if( isupper(x[0]) ){ +        struct symbol *sp; +        sp = Symbol_new(x); +        if( sp->prec>=0 ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +            "Symbol \"%s\" has already be given a precedence.",x); +          psp->errorcnt++; +	}else{ +          sp->prec = psp->preccounter; +          sp->assoc = psp->declassoc; +	} +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Can't assign a precedence to \"%s\".",x); +        psp->errorcnt++; +      } +      break; +    case WAITING_FOR_DECL_ARG: +      if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){ +        if( *(psp->declargslot)!=0 ){ +          ErrorMsg(psp->filename,psp->tokenlineno, +            "The argument \"%s\" to declaration \"%%%s\" is not the first.", +            x[0]=='\"' ? &x[1] : x,psp->declkeyword); +          psp->errorcnt++; +          psp->state = RESYNC_AFTER_DECL_ERROR; +	}else{ +          *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x; +          if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno; +          psp->state = WAITING_FOR_DECL_OR_RULE; +	} +      }else{ +        ErrorMsg(psp->filename,psp->tokenlineno, +          "Illegal argument to %%%s: %s",psp->declkeyword,x); +        psp->errorcnt++; +        psp->state = RESYNC_AFTER_DECL_ERROR; +      } +      break; +    case WAITING_FOR_FALLBACK_ID: +      if( x[0]=='.' ){ +        psp->state = WAITING_FOR_DECL_OR_RULE; +      }else if( !isupper(x[0]) ){ +        ErrorMsg(psp->filename, psp->tokenlineno, +          "%%fallback argument \"%s\" should be a token", x); +        psp->errorcnt++; +      }else{ +        struct symbol *sp = Symbol_new(x); +        if( psp->fallback==0 ){ +          psp->fallback = sp; +        }else if( sp->fallback ){ +          ErrorMsg(psp->filename, psp->tokenlineno, +            "More than one fallback assigned to token %s", x); +          psp->errorcnt++; +        }else{ +          sp->fallback = psp->fallback; +          psp->gp->has_fallback = 1; +        } +      } +      break; +    case RESYNC_AFTER_RULE_ERROR: +/*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; +**      break; */ +    case RESYNC_AFTER_DECL_ERROR: +      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; +      if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; +      break; +  } +} + +/* Run the proprocessor over the input file text.  The global variables +** azDefine[0] through azDefine[nDefine-1] contains the names of all defined +** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and +** comments them out.  Text in between is also commented out as appropriate. +*/ +static preprocess_input(char *z){ +  int i, j, k, n; +  int exclude = 0; +  int start; +  int lineno = 1; +  int start_lineno; +  for(i=0; z[i]; i++){ +    if( z[i]=='\n' ) lineno++; +    if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; +    if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){ +      if( exclude ){ +        exclude--; +        if( exclude==0 ){ +          for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' '; +        } +      } +      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; +    }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6])) +          || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){ +      if( exclude ){ +        exclude++; +      }else{ +        for(j=i+7; isspace(z[j]); j++){} +        for(n=0; z[j+n] && !isspace(z[j+n]); n++){} +        exclude = 1; +        for(k=0; k<nDefine; k++){ +          if( strncmp(azDefine[k],&z[j],n)==0 && strlen(azDefine[k])==n ){ +            exclude = 0; +            break; +          } +        } +        if( z[i+3]=='n' ) exclude = !exclude; +        if( exclude ){ +          start = i; +          start_lineno = lineno; +        } +      } +      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; +    } +  } +  if( exclude ){ +    fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno); +    exit(1); +  } +} + +/* In spite of its name, this function is really a scanner.  It read +** in the entire input file (all at once) then tokenizes it.  Each +** token is passed to the function "parseonetoken" which builds all +** the appropriate data structures in the global state vector "gp". +*/ +void Parse(gp) +struct lemon *gp; +{ +  struct pstate ps; +  FILE *fp; +  char *filebuf; +  int filesize; +  int lineno; +  int c; +  char *cp, *nextcp; +  int startline = 0; + +  ps.gp = gp; +  ps.filename = gp->filename; +  ps.errorcnt = 0; +  ps.state = INITIALIZE; + +  /* Begin by reading the input file */ +  fp = fopen(ps.filename,"rb"); +  if( fp==0 ){ +    ErrorMsg(ps.filename,0,"Can't open this file for reading."); +    gp->errorcnt++; +    return; +  } +  fseek(fp,0,2); +  filesize = ftell(fp); +  rewind(fp); +  filebuf = (char *)malloc( filesize+1 ); +  if( filebuf==0 ){ +    ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", +      filesize+1); +    gp->errorcnt++; +    return; +  } +  if( fread(filebuf,1,filesize,fp)!=filesize ){ +    ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", +      filesize); +    free(filebuf); +    gp->errorcnt++; +    return; +  } +  fclose(fp); +  filebuf[filesize] = 0; + +  /* Make an initial pass through the file to handle %ifdef and %ifndef */ +  preprocess_input(filebuf); + +  /* Now scan the text of the input file */ +  lineno = 1; +  for(cp=filebuf; (c= *cp)!=0; ){ +    if( c=='\n' ) lineno++;              /* Keep track of the line number */ +    if( isspace(c) ){ cp++; continue; }  /* Skip all white space */ +    if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */ +      cp+=2; +      while( (c= *cp)!=0 && c!='\n' ) cp++; +      continue; +    } +    if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */ +      cp+=2; +      while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){ +        if( c=='\n' ) lineno++; +        cp++; +      } +      if( c ) cp++; +      continue; +    } +    ps.tokenstart = cp;                /* Mark the beginning of the token */ +    ps.tokenlineno = lineno;           /* Linenumber on which token begins */ +    if( c=='\"' ){                     /* String literals */ +      cp++; +      while( (c= *cp)!=0 && c!='\"' ){ +        if( c=='\n' ) lineno++; +        cp++; +      } +      if( c==0 ){ +        ErrorMsg(ps.filename,startline, +"String starting on this line is not terminated before the end of the file."); +        ps.errorcnt++; +        nextcp = cp; +      }else{ +        nextcp = cp+1; +      } +    }else if( c=='{' ){               /* A block of C code */ +      int level; +      cp++; +      for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){ +        if( c=='\n' ) lineno++; +        else if( c=='{' ) level++; +        else if( c=='}' ) level--; +        else if( c=='/' && cp[1]=='*' ){  /* Skip comments */ +          int prevc; +          cp = &cp[2]; +          prevc = 0; +          while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ +            if( c=='\n' ) lineno++; +            prevc = c; +            cp++; +	  } +	}else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */ +          cp = &cp[2]; +          while( (c= *cp)!=0 && c!='\n' ) cp++; +          if( c ) lineno++; +	}else if( c=='\'' || c=='\"' ){    /* String a character literals */ +          int startchar, prevc; +          startchar = c; +          prevc = 0; +          for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ +            if( c=='\n' ) lineno++; +            if( prevc=='\\' ) prevc = 0; +            else              prevc = c; +	  } +	} +      } +      if( c==0 ){ +        ErrorMsg(ps.filename,ps.tokenlineno, +"C code starting on this line is not terminated before the end of the file."); +        ps.errorcnt++; +        nextcp = cp; +      }else{ +        nextcp = cp+1; +      } +    }else if( isalnum(c) ){          /* Identifiers */ +      while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++; +      nextcp = cp; +    }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ +      cp += 3; +      nextcp = cp; +    }else{                          /* All other (one character) operators */ +      cp++; +      nextcp = cp; +    } +    c = *cp; +    *cp = 0;                        /* Null terminate the token */ +    parseonetoken(&ps);             /* Parse the token */ +    *cp = c;                        /* Restore the buffer */ +    cp = nextcp; +  } +  free(filebuf);                    /* Release the buffer after parsing */ +  gp->rule = ps.firstrule; +  gp->errorcnt = ps.errorcnt; +} +/*************************** From the file "plink.c" *********************/ +/* +** Routines processing configuration follow-set propagation links +** in the LEMON parser generator. +*/ +static struct plink *plink_freelist = 0; + +/* Allocate a new plink */ +struct plink *Plink_new(){ +  struct plink *new; + +  if( plink_freelist==0 ){ +    int i; +    int amt = 100; +    plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt ); +    if( plink_freelist==0 ){ +      fprintf(stderr, +      "Unable to allocate memory for a new follow-set propagation link.\n"); +      exit(1); +    } +    for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1]; +    plink_freelist[amt-1].next = 0; +  } +  new = plink_freelist; +  plink_freelist = plink_freelist->next; +  return new; +} + +/* Add a plink to a plink list */ +void Plink_add(plpp,cfp) +struct plink **plpp; +struct config *cfp; +{ +  struct plink *new; +  new = Plink_new(); +  new->next = *plpp; +  *plpp = new; +  new->cfp = cfp; +} + +/* Transfer every plink on the list "from" to the list "to" */ +void Plink_copy(to,from) +struct plink **to; +struct plink *from; +{ +  struct plink *nextpl; +  while( from ){ +    nextpl = from->next; +    from->next = *to; +    *to = from; +    from = nextpl; +  } +} + +/* Delete every plink on the list */ +void Plink_delete(plp) +struct plink *plp; +{ +  struct plink *nextpl; + +  while( plp ){ +    nextpl = plp->next; +    plp->next = plink_freelist; +    plink_freelist = plp; +    plp = nextpl; +  } +} +/*********************** From the file "report.c" **************************/ +/* +** Procedures for generating reports and tables in the LEMON parser generator. +*/ + +/* Generate a filename with the given suffix.  Space to hold the +** name comes from malloc() and must be freed by the calling +** function. +*/ +PRIVATE char *file_makename(lemp,suffix) +struct lemon *lemp; +char *suffix; +{ +  char *name; +  char *cp; + +  name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 ); +  if( name==0 ){ +    fprintf(stderr,"Can't allocate space for a filename.\n"); +    exit(1); +  } +  strcpy(name,lemp->filename); +  cp = strrchr(name,'.'); +  if( cp ) *cp = 0; +  strcat(name,suffix); +  return name; +} + +/* Open a file with a name based on the name of the input file, +** but with a different (specified) suffix, and return a pointer +** to the stream */ +PRIVATE FILE *file_open(lemp,suffix,mode) +struct lemon *lemp; +char *suffix; +char *mode; +{ +  FILE *fp; + +  if( lemp->outname ) free(lemp->outname); +  lemp->outname = file_makename(lemp, suffix); +  fp = fopen(lemp->outname,mode); +  if( fp==0 && *mode=='w' ){ +    fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); +    lemp->errorcnt++; +    return 0; +  } +  return fp; +} + +/* Duplicate the input file without comments and without actions  +** on rules */ +void Reprint(lemp) +struct lemon *lemp; +{ +  struct rule *rp; +  struct symbol *sp; +  int i, j, maxlen, len, ncolumns, skip; +  printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename); +  maxlen = 10; +  for(i=0; i<lemp->nsymbol; i++){ +    sp = lemp->symbols[i]; +    len = strlen(sp->name); +    if( len>maxlen ) maxlen = len; +  } +  ncolumns = 76/(maxlen+5); +  if( ncolumns<1 ) ncolumns = 1; +  skip = (lemp->nsymbol + ncolumns - 1)/ncolumns; +  for(i=0; i<skip; i++){ +    printf("//"); +    for(j=i; j<lemp->nsymbol; j+=skip){ +      sp = lemp->symbols[j]; +      assert( sp->index==j ); +      printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); +    } +    printf("\n"); +  } +  for(rp=lemp->rule; rp; rp=rp->next){ +    printf("%s",rp->lhs->name); +/*    if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ +    printf(" ::="); +    for(i=0; i<rp->nrhs; i++){ +      printf(" %s",rp->rhs[i]->name); +/*      if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ +    } +    printf("."); +    if( rp->precsym ) printf(" [%s]",rp->precsym->name); +/*    if( rp->code ) printf("\n    %s",rp->code); */ +    printf("\n"); +  } +} + +void ConfigPrint(fp,cfp) +FILE *fp; +struct config *cfp; +{ +  struct rule *rp; +  int i; +  rp = cfp->rp; +  fprintf(fp,"%s ::=",rp->lhs->name); +  for(i=0; i<=rp->nrhs; i++){ +    if( i==cfp->dot ) fprintf(fp," *"); +    if( i==rp->nrhs ) break; +    fprintf(fp," %s",rp->rhs[i]->name); +  } +} + +/* #define TEST */ +#ifdef TEST +/* Print a set */ +PRIVATE void SetPrint(out,set,lemp) +FILE *out; +char *set; +struct lemon *lemp; +{ +  int i; +  char *spacer; +  spacer = ""; +  fprintf(out,"%12s[",""); +  for(i=0; i<lemp->nterminal; i++){ +    if( SetFind(set,i) ){ +      fprintf(out,"%s%s",spacer,lemp->symbols[i]->name); +      spacer = " "; +    } +  } +  fprintf(out,"]\n"); +} + +/* Print a plink chain */ +PRIVATE void PlinkPrint(out,plp,tag) +FILE *out; +struct plink *plp; +char *tag; +{ +  while( plp ){ +    fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index); +    ConfigPrint(out,plp->cfp); +    fprintf(out,"\n"); +    plp = plp->next; +  } +} +#endif + +/* Print an action to the given file descriptor.  Return FALSE if +** nothing was actually printed. +*/ +int PrintAction(struct action *ap, FILE *fp, int indent){ +  int result = 1; +  switch( ap->type ){ +    case SHIFT: +      fprintf(fp,"%*s shift  %d",indent,ap->sp->name,ap->x.stp->index); +      break; +    case REDUCE: +      fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index); +      break; +    case ACCEPT: +      fprintf(fp,"%*s accept",indent,ap->sp->name); +      break; +    case ERROR: +      fprintf(fp,"%*s error",indent,ap->sp->name); +      break; +    case CONFLICT: +      fprintf(fp,"%*s reduce %-3d ** Parsing conflict **", +        indent,ap->sp->name,ap->x.rp->index); +      break; +    case SH_RESOLVED: +    case RD_RESOLVED: +    case NOT_USED: +      result = 0; +      break; +  } +  return result; +} + +/* Generate the "y.output" log file */ +void ReportOutput(lemp) +struct lemon *lemp; +{ +  int i; +  struct state *stp; +  struct config *cfp; +  struct action *ap; +  FILE *fp; + +  fp = file_open(lemp,".out","wb"); +  if( fp==0 ) return; +  fprintf(fp," \b"); +  for(i=0; i<lemp->nstate; i++){ +    stp = lemp->sorted[i]; +    fprintf(fp,"State %d:\n",stp->index); +    if( lemp->basisflag ) cfp=stp->bp; +    else                  cfp=stp->cfp; +    while( cfp ){ +      char buf[20]; +      if( cfp->dot==cfp->rp->nrhs ){ +        sprintf(buf,"(%d)",cfp->rp->index); +        fprintf(fp,"    %5s ",buf); +      }else{ +        fprintf(fp,"          "); +      } +      ConfigPrint(fp,cfp); +      fprintf(fp,"\n"); +#ifdef TEST +      SetPrint(fp,cfp->fws,lemp); +      PlinkPrint(fp,cfp->fplp,"To  "); +      PlinkPrint(fp,cfp->bplp,"From"); +#endif +      if( lemp->basisflag ) cfp=cfp->bp; +      else                  cfp=cfp->next; +    } +    fprintf(fp,"\n"); +    for(ap=stp->ap; ap; ap=ap->next){ +      if( PrintAction(ap,fp,30) ) fprintf(fp,"\n"); +    } +    fprintf(fp,"\n"); +  } +  fclose(fp); +  return; +} + +/* Search for the file "name" which is in the same directory as +** the exacutable */ +PRIVATE char *pathsearch(argv0,name,modemask) +char *argv0; +char *name; +int modemask; +{ +  char *pathlist; +  char *path,*cp; +  char c; +  extern int access(); + +#ifdef __WIN32__ +  cp = strrchr(argv0,'\\'); +#else +  cp = strrchr(argv0,'/'); +#endif +  if( cp ){ +    c = *cp; +    *cp = 0; +    path = (char *)malloc( strlen(argv0) + strlen(name) + 2 ); +    if( path ) sprintf(path,"%s/%s",argv0,name); +    *cp = c; +  }else{ +    extern char *getenv(); +    pathlist = getenv("PATH"); +    if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; +    path = (char *)malloc( strlen(pathlist)+strlen(name)+2 ); +    if( path!=0 ){ +      while( *pathlist ){ +        cp = strchr(pathlist,':'); +        if( cp==0 ) cp = &pathlist[strlen(pathlist)]; +        c = *cp; +        *cp = 0; +        sprintf(path,"%s/%s",pathlist,name); +        *cp = c; +        if( c==0 ) pathlist = ""; +        else pathlist = &cp[1]; +        if( access(path,modemask)==0 ) break; +      } +    } +  } +  return path; +} + +/* Given an action, compute the integer value for that action +** which is to be put in the action table of the generated machine. +** Return negative if no action should be generated. +*/ +PRIVATE int compute_action(lemp,ap) +struct lemon *lemp; +struct action *ap; +{ +  int act; +  switch( ap->type ){ +    case SHIFT:  act = ap->x.stp->index;               break; +    case REDUCE: act = ap->x.rp->index + lemp->nstate; break; +    case ERROR:  act = lemp->nstate + lemp->nrule;     break; +    case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break; +    default:     act = -1; break; +  } +  return act; +} + +#define LINESIZE 1000 +/* The next cluster of routines are for reading the template file +** and writing the results to the generated parser */ +/* The first function transfers data from "in" to "out" until +** a line is seen which begins with "%%".  The line number is +** tracked. +** +** if name!=0, then any word that begin with "Parse" is changed to +** begin with *name instead. +*/ +PRIVATE void tplt_xfer(name,in,out,lineno) +char *name; +FILE *in; +FILE *out; +int *lineno; +{ +  int i, iStart; +  char line[LINESIZE]; +  while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ +    (*lineno)++; +    iStart = 0; +    if( name ){ +      for(i=0; line[i]; i++){ +        if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 +          && (i==0 || !isalpha(line[i-1])) +        ){ +          if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); +          fprintf(out,"%s",name); +          i += 4; +          iStart = i+1; +        } +      } +    } +    fprintf(out,"%s",&line[iStart]); +  } +} + +/* The next function finds the template file and opens it, returning +** a pointer to the opened file. */ +PRIVATE FILE *tplt_open(lemp) +struct lemon *lemp; +{ +  static char templatename[] = "lempar.c"; +  char buf[1000]; +  FILE *in; +  char *tpltname; +  char *cp; + +  cp = strrchr(lemp->filename,'.'); +  if( cp ){ +    sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); +  }else{ +    sprintf(buf,"%s.lt",lemp->filename); +  } +  if( access(buf,004)==0 ){ +    tpltname = buf; +  }else if( access(templatename,004)==0 ){ +    tpltname = templatename; +  }else{ +    tpltname = pathsearch(lemp->argv0,templatename,0); +  } +  if( tpltname==0 ){ +    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", +    templatename); +    lemp->errorcnt++; +    return 0; +  } +  in = fopen(tpltname,"rb"); +  if( in==0 ){ +    fprintf(stderr,"Can't open the template file \"%s\".\n",templatename); +    lemp->errorcnt++; +    return 0; +  } +  return in; +} + +/* Print a #line directive line to the output file. */ +PRIVATE void tplt_linedir(out,lineno,filename) +FILE *out; +int lineno; +char *filename; +{ +  fprintf(out,"#line %d \"",lineno); +  while( *filename ){ +    if( *filename == '\\' ) putc('\\',out); +    putc(*filename,out); +    filename++; +  } +  fprintf(out,"\"\n"); +} + +/* Print a string to the file and keep the linenumber up to date */ +PRIVATE void tplt_print(out,lemp,str,strln,lineno) +FILE *out; +struct lemon *lemp; +char *str; +int strln; +int *lineno; +{ +  if( str==0 ) return; +  tplt_linedir(out,strln,lemp->filename); +  (*lineno)++; +  while( *str ){ +    if( *str=='\n' ) (*lineno)++; +    putc(*str,out); +    str++; +  } +  if( str[-1]!='\n' ){ +    putc('\n',out); +    (*lineno)++; +  } +  tplt_linedir(out,*lineno+2,lemp->outname);  +  (*lineno)+=2; +  return; +} + +/* +** The following routine emits code for the destructor for the +** symbol sp +*/ +void emit_destructor_code(out,sp,lemp,lineno) +FILE *out; +struct symbol *sp; +struct lemon *lemp; +int *lineno; +{ + char *cp = 0; + + int linecnt = 0; + if( sp->type==TERMINAL ){ +   cp = lemp->tokendest; +   if( cp==0 ) return; +   tplt_linedir(out,lemp->tokendestln,lemp->filename); +   fprintf(out,"{"); + }else if( sp->destructor ){ +   cp = sp->destructor; +   tplt_linedir(out,sp->destructorln,lemp->filename); +   fprintf(out,"{"); + }else if( lemp->vardest ){ +   cp = lemp->vardest; +   if( cp==0 ) return; +   tplt_linedir(out,lemp->vardestln,lemp->filename); +   fprintf(out,"{"); + }else{ +   assert( 0 );  /* Cannot happen */ + } + for(; *cp; cp++){ +   if( *cp=='$' && cp[1]=='$' ){ +     fprintf(out,"(yypminor->yy%d)",sp->dtnum); +     cp++; +     continue; +   } +   if( *cp=='\n' ) linecnt++; +   fputc(*cp,out); + } + (*lineno) += 3 + linecnt; + fprintf(out,"}\n"); + tplt_linedir(out,*lineno,lemp->outname); + return; +} + +/* +** Return TRUE (non-zero) if the given symbol has a destructor. +*/ +int has_destructor(sp, lemp) +struct symbol *sp; +struct lemon *lemp; +{ +  int ret; +  if( sp->type==TERMINAL ){ +    ret = lemp->tokendest!=0; +  }else{ +    ret = lemp->vardest!=0 || sp->destructor!=0; +  } +  return ret; +} + +/* +** Append text to a dynamically allocated string.  If zText is 0 then +** reset the string to be empty again.  Always return the complete text +** of the string (which is overwritten with each call). +** +** n bytes of zText are stored.  If n==0 then all of zText up to the first +** \000 terminator is stored.  zText can contain up to two instances of +** %d.  The values of p1 and p2 are written into the first and second +** %d. +** +** If n==-1, then the previous character is overwritten. +*/ +PRIVATE char *append_str(char *zText, int n, int p1, int p2){ +  static char *z = 0; +  static int alloced = 0; +  static int used = 0; +  int c; +  char zInt[40]; + +  if( zText==0 ){ +    used = 0; +    return z; +  } +  if( n<=0 ){ +    if( n<0 ){ +      used += n; +      assert( used>=0 ); +    } +    n = strlen(zText); +  } +  if( n+sizeof(zInt)*2+used >= alloced ){ +    alloced = n + sizeof(zInt)*2 + used + 200; +    z = realloc(z,  alloced); +  } +  if( z==0 ) return ""; +  while( n-- > 0 ){ +    c = *(zText++); +    if( c=='%' && zText[0]=='d' ){ +      sprintf(zInt, "%d", p1); +      p1 = p2; +      strcpy(&z[used], zInt); +      used += strlen(&z[used]); +      zText++; +      n--; +    }else{ +      z[used++] = c; +    } +  } +  z[used] = 0; +  return z; +} + +/* +** zCode is a string that is the action associated with a rule.  Expand +** the symbols in this string so that the refer to elements of the parser +** stack. +*/ +PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ +  char *cp, *xp; +  int i; +  char lhsused = 0;    /* True if the LHS element has been used */ +  char used[MAXRHS];   /* True for each RHS element which is used */ + +  for(i=0; i<rp->nrhs; i++) used[i] = 0; +  lhsused = 0; + +  append_str(0,0,0,0); +  for(cp=rp->code; *cp; cp++){ +    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ +      char saved; +      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); +      saved = *xp; +      *xp = 0; +      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ +        append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); +        cp = xp; +        lhsused = 1; +      }else{ +        for(i=0; i<rp->nrhs; i++){ +          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ +            if( cp!=rp->code && cp[-1]=='@' ){ +              /* If the argument is of the form @X then substituted +              ** the token number of X, not the value of X */ +              append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0); +            }else{ +              append_str("yymsp[%d].minor.yy%d",0, +                         i-rp->nrhs+1,rp->rhs[i]->dtnum); +            } +            cp = xp; +            used[i] = 1; +            break; +          } +        } +      } +      *xp = saved; +    } +    append_str(cp, 1, 0, 0); +  } /* End loop */ + +  /* Check to make sure the LHS has been used */ +  if( rp->lhsalias && !lhsused ){ +    ErrorMsg(lemp->filename,rp->ruleline, +      "Label \"%s\" for \"%s(%s)\" is never used.", +        rp->lhsalias,rp->lhs->name,rp->lhsalias); +    lemp->errorcnt++; +  } + +  /* Generate destructor code for RHS symbols which are not used in the +  ** reduce code */ +  for(i=0; i<rp->nrhs; i++){ +    if( rp->rhsalias[i] && !used[i] ){ +      ErrorMsg(lemp->filename,rp->ruleline, +        "Label %s for \"%s(%s)\" is never used.", +        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); +      lemp->errorcnt++; +    }else if( rp->rhsalias[i]==0 ){ +      if( has_destructor(rp->rhs[i],lemp) ){ +        append_str("  yy_destructor(%d,&yymsp[%d].minor);\n", 0, +           rp->rhs[i]->index,i-rp->nrhs+1); +      }else{ +        /* No destructor defined for this term */ +      } +    } +  } +  cp = append_str(0,0,0,0); +  rp->code = Strsafe(cp); +} + +/*  +** Generate code which executes when the rule "rp" is reduced.  Write +** the code to "out".  Make sure lineno stays up-to-date. +*/ +PRIVATE void emit_code(out,rp,lemp,lineno) +FILE *out; +struct rule *rp; +struct lemon *lemp; +int *lineno; +{ + char *cp; + int linecnt = 0; + + /* Generate code to do the reduce action */ + if( rp->code ){ +   tplt_linedir(out,rp->line,lemp->filename); +   fprintf(out,"{%s",rp->code); +   for(cp=rp->code; *cp; cp++){ +     if( *cp=='\n' ) linecnt++; +   } /* End loop */ +   (*lineno) += 3 + linecnt; +   fprintf(out,"}\n"); +   tplt_linedir(out,*lineno,lemp->outname); + } /* End if( rp->code ) */ + + return; +} + +/* +** Print the definition of the union used for the parser's data stack. +** This union contains fields for every possible data type for tokens +** and nonterminals.  In the process of computing and printing this +** union, also set the ".dtnum" field of every terminal and nonterminal +** symbol. +*/ +void print_stack_union(out,lemp,plineno,mhflag) +FILE *out;                  /* The output stream */ +struct lemon *lemp;         /* The main info structure for this parser */ +int *plineno;               /* Pointer to the line number */ +int mhflag;                 /* True if generating makeheaders output */ +{ +  int lineno = *plineno;    /* The line number of the output */ +  char **types;             /* A hash table of datatypes */ +  int arraysize;            /* Size of the "types" array */ +  int maxdtlength;          /* Maximum length of any ".datatype" field. */ +  char *stddt;              /* Standardized name for a datatype */ +  int i,j;                  /* Loop counters */ +  int hash;                 /* For hashing the name of a type */ +  char *name;               /* Name of the parser */ + +  /* Allocate and initialize types[] and allocate stddt[] */ +  arraysize = lemp->nsymbol * 2; +  types = (char**)malloc( arraysize * sizeof(char*) ); +  for(i=0; i<arraysize; i++) types[i] = 0; +  maxdtlength = 0; +  if( lemp->vartype ){ +    maxdtlength = strlen(lemp->vartype); +  } +  for(i=0; i<lemp->nsymbol; i++){ +    int len; +    struct symbol *sp = lemp->symbols[i]; +    if( sp->datatype==0 ) continue; +    len = strlen(sp->datatype); +    if( len>maxdtlength ) maxdtlength = len; +  } +  stddt = (char*)malloc( maxdtlength*2 + 1 ); +  if( types==0 || stddt==0 ){ +    fprintf(stderr,"Out of memory.\n"); +    exit(1); +  } + +  /* Build a hash table of datatypes. The ".dtnum" field of each symbol +  ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is +  ** used for terminal symbols.  If there is no %default_type defined then +  ** 0 is also used as the .dtnum value for nonterminals which do not specify +  ** a datatype using the %type directive. +  */ +  for(i=0; i<lemp->nsymbol; i++){ +    struct symbol *sp = lemp->symbols[i]; +    char *cp; +    if( sp==lemp->errsym ){ +      sp->dtnum = arraysize+1; +      continue; +    } +    if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ +      sp->dtnum = 0; +      continue; +    } +    cp = sp->datatype; +    if( cp==0 ) cp = lemp->vartype; +    j = 0; +    while( isspace(*cp) ) cp++; +    while( *cp ) stddt[j++] = *cp++; +    while( j>0 && isspace(stddt[j-1]) ) j--; +    stddt[j] = 0; +    hash = 0; +    for(j=0; stddt[j]; j++){ +      hash = hash*53 + stddt[j]; +    } +    hash = (hash & 0x7fffffff)%arraysize; +    while( types[hash] ){ +      if( strcmp(types[hash],stddt)==0 ){ +        sp->dtnum = hash + 1; +        break; +      } +      hash++; +      if( hash>=arraysize ) hash = 0; +    } +    if( types[hash]==0 ){ +      sp->dtnum = hash + 1; +      types[hash] = (char*)malloc( strlen(stddt)+1 ); +      if( types[hash]==0 ){ +        fprintf(stderr,"Out of memory.\n"); +        exit(1); +      } +      strcpy(types[hash],stddt); +    } +  } + +  /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ +  name = lemp->name ? lemp->name : "Parse"; +  lineno = *plineno; +  if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } +  fprintf(out,"#define %sTOKENTYPE %s\n",name, +    lemp->tokentype?lemp->tokentype:"void*");  lineno++; +  if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } +  fprintf(out,"typedef union {\n"); lineno++; +  fprintf(out,"  %sTOKENTYPE yy0;\n",name); lineno++; +  for(i=0; i<arraysize; i++){ +    if( types[i]==0 ) continue; +    fprintf(out,"  %s yy%d;\n",types[i],i+1); lineno++; +    free(types[i]); +  } +  fprintf(out,"  int yy%d;\n",lemp->errsym->dtnum); lineno++; +  free(stddt); +  free(types); +  fprintf(out,"} YYMINORTYPE;\n"); lineno++; +  *plineno = lineno; +} + +/* +** Return the name of a C datatype able to represent values between +** lwr and upr, inclusive. +*/ +static const char *minimum_size_type(int lwr, int upr){ +  if( lwr>=0 ){ +    if( upr<=255 ){ +      return "unsigned char"; +    }else if( upr<65535 ){ +      return "unsigned short int"; +    }else{ +      return "unsigned int"; +    } +  }else if( lwr>=-127 && upr<=127 ){ +    return "signed char"; +  }else if( lwr>=-32767 && upr<32767 ){ +    return "short"; +  }else{ +    return "int"; +  } +} + +/* +** Each state contains a set of token transaction and a set of +** nonterminal transactions.  Each of these sets makes an instance +** of the following structure.  An array of these structures is used +** to order the creation of entries in the yy_action[] table. +*/ +struct axset { +  struct state *stp;   /* A pointer to a state */ +  int isTkn;           /* True to use tokens.  False for non-terminals */ +  int nAction;         /* Number of actions */ +}; + +/* +** Compare to axset structures for sorting purposes +*/ +static int axset_compare(const void *a, const void *b){ +  struct axset *p1 = (struct axset*)a; +  struct axset *p2 = (struct axset*)b; +  return p2->nAction - p1->nAction; +} + +/* Generate C source code for the parser */ +void ReportTable(lemp, mhflag) +struct lemon *lemp; +int mhflag;     /* Output in makeheaders format if true */ +{ +  FILE *out, *in; +  char line[LINESIZE]; +  int  lineno; +  struct state *stp; +  struct action *ap; +  struct rule *rp; +  struct acttab *pActtab; +  int i, j, n; +  char *name; +  int mnTknOfst, mxTknOfst; +  int mnNtOfst, mxNtOfst; +  struct axset *ax; + +  in = tplt_open(lemp); +  if( in==0 ) return; +  out = file_open(lemp,".c","wb"); +  if( out==0 ){ +    fclose(in); +    return; +  } +  lineno = 1; +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate the include code, if any */ +  tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno); +  if( mhflag ){ +    char *name = file_makename(lemp, ".h"); +    fprintf(out,"#include \"%s\"\n", name); lineno++; +    free(name); +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate #defines for all tokens */ +  if( mhflag ){ +    char *prefix; +    fprintf(out,"#if INTERFACE\n"); lineno++; +    if( lemp->tokenprefix ) prefix = lemp->tokenprefix; +    else                    prefix = ""; +    for(i=1; i<lemp->nterminal; i++){ +      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); +      lineno++; +    } +    fprintf(out,"#endif\n"); lineno++; +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate the defines */ +  fprintf(out,"#define YYCODETYPE %s\n", +    minimum_size_type(0, lemp->nsymbol+5)); lineno++; +  fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1);  lineno++; +  fprintf(out,"#define YYACTIONTYPE %s\n", +    minimum_size_type(0, lemp->nstate+lemp->nrule+5));  lineno++; +  print_stack_union(out,lemp,&lineno,mhflag); +  if( lemp->stacksize ){ +    if( atoi(lemp->stacksize)<=0 ){ +      ErrorMsg(lemp->filename,0, +"Illegal stack size: [%s].  The stack size should be an integer constant.", +        lemp->stacksize); +      lemp->errorcnt++; +      lemp->stacksize = "100"; +    } +    fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize);  lineno++; +  }else{ +    fprintf(out,"#define YYSTACKDEPTH 100\n");  lineno++; +  } +  if( mhflag ){ +    fprintf(out,"#if INTERFACE\n"); lineno++; +  } +  name = lemp->name ? lemp->name : "Parse"; +  if( lemp->arg && lemp->arg[0] ){ +    int i; +    i = strlen(lemp->arg); +    while( i>=1 && isspace(lemp->arg[i-1]) ) i--; +    while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; +    fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg);  lineno++; +    fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg);  lineno++; +    fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", +                 name,lemp->arg,&lemp->arg[i]);  lineno++; +    fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", +                 name,&lemp->arg[i],&lemp->arg[i]);  lineno++; +  }else{ +    fprintf(out,"#define %sARG_SDECL\n",name);  lineno++; +    fprintf(out,"#define %sARG_PDECL\n",name);  lineno++; +    fprintf(out,"#define %sARG_FETCH\n",name); lineno++; +    fprintf(out,"#define %sARG_STORE\n",name); lineno++; +  } +  if( mhflag ){ +    fprintf(out,"#endif\n"); lineno++; +  } +  fprintf(out,"#define YYNSTATE %d\n",lemp->nstate);  lineno++; +  fprintf(out,"#define YYNRULE %d\n",lemp->nrule);  lineno++; +  fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index);  lineno++; +  fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum);  lineno++; +  if( lemp->has_fallback ){ +    fprintf(out,"#define YYFALLBACK 1\n");  lineno++; +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate the action table and its associates: +  ** +  **  yy_action[]        A single table containing all actions. +  **  yy_lookahead[]     A table containing the lookahead for each entry in +  **                     yy_action.  Used to detect hash collisions. +  **  yy_shift_ofst[]    For each state, the offset into yy_action for +  **                     shifting terminals. +  **  yy_reduce_ofst[]   For each state, the offset into yy_action for +  **                     shifting non-terminals after a reduce. +  **  yy_default[]       Default action for each state. +  */ + +  /* Compute the actions on all states and count them up */ +  ax = malloc( sizeof(ax[0])*lemp->nstate*2 ); +  if( ax==0 ){ +    fprintf(stderr,"malloc failed\n"); +    exit(1); +  } +  for(i=0; i<lemp->nstate; i++){ +    stp = lemp->sorted[i]; +    stp->nTknAct = stp->nNtAct = 0; +    stp->iDflt = lemp->nstate + lemp->nrule; +    stp->iTknOfst = NO_OFFSET; +    stp->iNtOfst = NO_OFFSET; +    for(ap=stp->ap; ap; ap=ap->next){ +      if( compute_action(lemp,ap)>=0 ){ +        if( ap->sp->index<lemp->nterminal ){ +          stp->nTknAct++; +        }else if( ap->sp->index<lemp->nsymbol ){ +          stp->nNtAct++; +        }else{ +          stp->iDflt = compute_action(lemp, ap); +        } +      } +    } +    ax[i*2].stp = stp; +    ax[i*2].isTkn = 1; +    ax[i*2].nAction = stp->nTknAct; +    ax[i*2+1].stp = stp; +    ax[i*2+1].isTkn = 0; +    ax[i*2+1].nAction = stp->nNtAct; +  } +  mxTknOfst = mnTknOfst = 0; +  mxNtOfst = mnNtOfst = 0; + +  /* Compute the action table.  In order to try to keep the size of the +  ** action table to a minimum, the heuristic of placing the largest action +  ** sets first is used. +  */ +  qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare); +  pActtab = acttab_alloc(); +  for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){ +    stp = ax[i].stp; +    if( ax[i].isTkn ){ +      for(ap=stp->ap; ap; ap=ap->next){ +        int action; +        if( ap->sp->index>=lemp->nterminal ) continue; +        action = compute_action(lemp, ap); +        if( action<0 ) continue; +        acttab_action(pActtab, ap->sp->index, action); +      } +      stp->iTknOfst = acttab_insert(pActtab); +      if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst; +      if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst; +    }else{ +      for(ap=stp->ap; ap; ap=ap->next){ +        int action; +        if( ap->sp->index<lemp->nterminal ) continue; +        if( ap->sp->index==lemp->nsymbol ) continue; +        action = compute_action(lemp, ap); +        if( action<0 ) continue; +        acttab_action(pActtab, ap->sp->index, action); +      } +      stp->iNtOfst = acttab_insert(pActtab); +      if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst; +      if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; +    } +  } +  free(ax); + +  /* Output the yy_action table */ +  fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; +  n = acttab_size(pActtab); +  for(i=j=0; i<n; i++){ +    int action = acttab_yyaction(pActtab, i); +    if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2; +    if( j==0 ) fprintf(out," /* %5d */ ", i); +    fprintf(out, " %4d,", action); +    if( j==9 || i==n-1 ){ +      fprintf(out, "\n"); lineno++; +      j = 0; +    }else{ +      j++; +    } +  } +  fprintf(out, "};\n"); lineno++; + +  /* Output the yy_lookahead table */ +  fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++; +  for(i=j=0; i<n; i++){ +    int la = acttab_yylookahead(pActtab, i); +    if( la<0 ) la = lemp->nsymbol; +    if( j==0 ) fprintf(out," /* %5d */ ", i); +    fprintf(out, " %4d,", la); +    if( j==9 || i==n-1 ){ +      fprintf(out, "\n"); lineno++; +      j = 0; +    }else{ +      j++; +    } +  } +  fprintf(out, "};\n"); lineno++; + +  /* Output the yy_shift_ofst[] table */ +  fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; +  fprintf(out, "static const %s yy_shift_ofst[] = {\n",  +          minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; +  n = lemp->nstate; +  for(i=j=0; i<n; i++){ +    int ofst; +    stp = lemp->sorted[i]; +    ofst = stp->iTknOfst; +    if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; +    if( j==0 ) fprintf(out," /* %5d */ ", i); +    fprintf(out, " %4d,", ofst); +    if( j==9 || i==n-1 ){ +      fprintf(out, "\n"); lineno++; +      j = 0; +    }else{ +      j++; +    } +  } +  fprintf(out, "};\n"); lineno++; + +  /* Output the yy_reduce_ofst[] table */ +  fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; +  fprintf(out, "static const %s yy_reduce_ofst[] = {\n",  +          minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; +  n = lemp->nstate; +  for(i=j=0; i<n; i++){ +    int ofst; +    stp = lemp->sorted[i]; +    ofst = stp->iNtOfst; +    if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1; +    if( j==0 ) fprintf(out," /* %5d */ ", i); +    fprintf(out, " %4d,", ofst); +    if( j==9 || i==n-1 ){ +      fprintf(out, "\n"); lineno++; +      j = 0; +    }else{ +      j++; +    } +  } +  fprintf(out, "};\n"); lineno++; + +  /* Output the default action table */ +  fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++; +  n = lemp->nstate; +  for(i=j=0; i<n; i++){ +    stp = lemp->sorted[i]; +    if( j==0 ) fprintf(out," /* %5d */ ", i); +    fprintf(out, " %4d,", stp->iDflt); +    if( j==9 || i==n-1 ){ +      fprintf(out, "\n"); lineno++; +      j = 0; +    }else{ +      j++; +    } +  } +  fprintf(out, "};\n"); lineno++; +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate the table of fallback tokens. +  */ +  if( lemp->has_fallback ){ +    for(i=0; i<lemp->nterminal; i++){ +      struct symbol *p = lemp->symbols[i]; +      if( p->fallback==0 ){ +        fprintf(out, "    0,  /* %10s => nothing */\n", p->name); +      }else{ +        fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index, +          p->name, p->fallback->name); +      } +      lineno++; +    } +  } +  tplt_xfer(lemp->name, in, out, &lineno); + +  /* Generate a table containing the symbolic name of every symbol +  */ +  for(i=0; i<lemp->nsymbol; i++){ +    sprintf(line,"\"%s\",",lemp->symbols[i]->name); +    fprintf(out,"  %-15s",line); +    if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } +  } +  if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate a table containing a text string that describes every +  ** rule in the rule set of the grammer.  This information is used +  ** when tracing REDUCE actions. +  */ +  for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ +    assert( rp->index==i ); +    fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name); +    for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name); +    fprintf(out,"\",\n"); lineno++; +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which executes every time a symbol is popped from +  ** the stack while processing errors or while destroying the parser.  +  ** (In other words, generate the %destructor actions) +  */ +  if( lemp->tokendest ){ +    for(i=0; i<lemp->nsymbol; i++){ +      struct symbol *sp = lemp->symbols[i]; +      if( sp==0 || sp->type!=TERMINAL ) continue; +      fprintf(out,"    case %d:\n",sp->index); lineno++; +    } +    for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++); +    if( i<lemp->nsymbol ){ +      emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); +      fprintf(out,"      break;\n"); lineno++; +    } +  } +  for(i=0; i<lemp->nsymbol; i++){ +    struct symbol *sp = lemp->symbols[i]; +    if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; +    fprintf(out,"    case %d:\n",sp->index); lineno++; + +    /* Combine duplicate destructors into a single case */ +    for(j=i+1; j<lemp->nsymbol; j++){ +      struct symbol *sp2 = lemp->symbols[j]; +      if( sp2 && sp2->type!=TERMINAL && sp2->destructor +          && sp2->dtnum==sp->dtnum +          && strcmp(sp->destructor,sp2->destructor)==0 ){ +         fprintf(out,"    case %d:\n",sp2->index); lineno++; +         sp2->destructor = 0; +      } +    } + +    emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); +    fprintf(out,"      break;\n"); lineno++; +  } +  if( lemp->vardest ){ +    struct symbol *dflt_sp = 0; +    for(i=0; i<lemp->nsymbol; i++){ +      struct symbol *sp = lemp->symbols[i]; +      if( sp==0 || sp->type==TERMINAL || +          sp->index<=0 || sp->destructor!=0 ) continue; +      fprintf(out,"    case %d:\n",sp->index); lineno++; +      dflt_sp = sp; +    } +    if( dflt_sp!=0 ){ +      emit_destructor_code(out,dflt_sp,lemp,&lineno); +      fprintf(out,"      break;\n"); lineno++; +    } +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which executes whenever the parser stack overflows */ +  tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno); +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate the table of rule information  +  ** +  ** Note: This code depends on the fact that rules are number +  ** sequentually beginning with 0. +  */ +  for(rp=lemp->rule; rp; rp=rp->next){ +    fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which execution during each REDUCE action */ +  for(rp=lemp->rule; rp; rp=rp->next){ +    if( rp->code ) translate_code(lemp, rp); +  } +  for(rp=lemp->rule; rp; rp=rp->next){ +    struct rule *rp2; +    if( rp->code==0 ) continue; +    fprintf(out,"      case %d:\n",rp->index); lineno++; +    for(rp2=rp->next; rp2; rp2=rp2->next){ +      if( rp2->code==rp->code ){ +        fprintf(out,"      case %d:\n",rp2->index); lineno++; +        rp2->code = 0; +      } +    } +    emit_code(out,rp,lemp,&lineno); +    fprintf(out,"        break;\n"); lineno++; +  } +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which executes if a parse fails */ +  tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno); +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which executes when a syntax error occurs */ +  tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno); +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Generate code which executes when the parser accepts its input */ +  tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno); +  tplt_xfer(lemp->name,in,out,&lineno); + +  /* Append any addition code the user desires */ +  tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno); + +  fclose(in); +  fclose(out); +  return; +} + +/* Generate a header file for the parser */ +void ReportHeader(lemp) +struct lemon *lemp; +{ +  FILE *out, *in; +  char *prefix; +  char line[LINESIZE]; +  char pattern[LINESIZE]; +  int i; + +  if( lemp->tokenprefix ) prefix = lemp->tokenprefix; +  else                    prefix = ""; +  in = file_open(lemp,".h","rb"); +  if( in ){ +    for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ +      sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); +      if( strcmp(line,pattern) ) break; +    } +    fclose(in); +    if( i==lemp->nterminal ){ +      /* No change in the file.  Don't rewrite it. */ +      return; +    } +  } +  out = file_open(lemp,".h","wb"); +  if( out ){ +    for(i=1; i<lemp->nterminal; i++){ +      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); +    } +    fclose(out);   +  } +  return; +} + +/* Reduce the size of the action tables, if possible, by making use +** of defaults. +** +** In this version, we take the most frequent REDUCE action and make +** it the default.  Only default a reduce if there are more than one. +*/ +void CompressTables(lemp) +struct lemon *lemp; +{ +  struct state *stp; +  struct action *ap, *ap2; +  struct rule *rp, *rp2, *rbest; +  int nbest, n; +  int i; + +  for(i=0; i<lemp->nstate; i++){ +    stp = lemp->sorted[i]; +    nbest = 0; +    rbest = 0; + +    for(ap=stp->ap; ap; ap=ap->next){ +      if( ap->type!=REDUCE ) continue; +      rp = ap->x.rp; +      if( rp==rbest ) continue; +      n = 1; +      for(ap2=ap->next; ap2; ap2=ap2->next){ +        if( ap2->type!=REDUCE ) continue; +        rp2 = ap2->x.rp; +        if( rp2==rbest ) continue; +        if( rp2==rp ) n++; +      } +      if( n>nbest ){ +        nbest = n; +        rbest = rp; +      } +    } +  +    /* Do not make a default if the number of rules to default +    ** is not at least 2 */ +    if( nbest<2 ) continue; + + +    /* Combine matching REDUCE actions into a single default */ +    for(ap=stp->ap; ap; ap=ap->next){ +      if( ap->type==REDUCE && ap->x.rp==rbest ) break; +    } +    assert( ap ); +    ap->sp = Symbol_new("{default}"); +    for(ap=ap->next; ap; ap=ap->next){ +      if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED; +    } +    stp->ap = Action_sort(stp->ap); +  } +} + +/***************** From the file "set.c" ************************************/ +/* +** Set manipulation routines for the LEMON parser generator. +*/ + +static int size = 0; + +/* Set the set size */ +void SetSize(n) +int n; +{ +  size = n+1; +} + +/* Allocate a new set */ +char *SetNew(){ +  char *s; +  int i; +  s = (char*)malloc( size ); +  if( s==0 ){ +    extern void memory_error(); +    memory_error(); +  } +  for(i=0; i<size; i++) s[i] = 0; +  return s; +} + +/* Deallocate a set */ +void SetFree(s) +char *s; +{ +  free(s); +} + +/* Add a new element to the set.  Return TRUE if the element was added +** and FALSE if it was already there. */ +int SetAdd(s,e) +char *s; +int e; +{ +  int rv; +  rv = s[e]; +  s[e] = 1; +  return !rv; +} + +/* Add every element of s2 to s1.  Return TRUE if s1 changes. */ +int SetUnion(s1,s2) +char *s1; +char *s2; +{ +  int i, progress; +  progress = 0; +  for(i=0; i<size; i++){ +    if( s2[i]==0 ) continue; +    if( s1[i]==0 ){ +      progress = 1; +      s1[i] = 1; +    } +  } +  return progress; +} +/********************** From the file "table.c" ****************************/ +/* +** All code in this file has been automatically generated +** from a specification in the file +**              "table.q" +** by the associative array code building program "aagen". +** Do not edit this file!  Instead, edit the specification +** file, then rerun aagen. +*/ +/* +** Code for processing tables in the LEMON parser generator. +*/ + +PRIVATE int strhash(x) +char *x; +{ +  int h = 0; +  while( *x) h = h*13 + *(x++); +  return h; +} + +/* Works like strdup, sort of.  Save a string in malloced memory, but +** keep strings in a table so that the same string is not in more +** than one place. +*/ +char *Strsafe(y) +char *y; +{ +  char *z; + +  z = Strsafe_find(y); +  if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){ +    strcpy(z,y); +    Strsafe_insert(z); +  } +  MemoryCheck(z); +  return z; +} + +/* There is one instance of the following structure for each +** associative array of type "x1". +*/ +struct s_x1 { +  int size;               /* The number of available slots. */ +                          /*   Must be a power of 2 greater than or */ +                          /*   equal to 1 */ +  int count;              /* Number of currently slots filled */ +  struct s_x1node *tbl;  /* The data stored here */ +  struct s_x1node **ht;  /* Hash table for lookups */ +}; + +/* There is one instance of this structure for every data element +** in an associative array of type "x1". +*/ +typedef struct s_x1node { +  char *data;                  /* The data */ +  struct s_x1node *next;   /* Next entry with the same hash */ +  struct s_x1node **from;  /* Previous link */ +} x1node; + +/* There is only one instance of the array, which is the following */ +static struct s_x1 *x1a; + +/* Allocate a new associative array */ +void Strsafe_init(){ +  if( x1a ) return; +  x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); +  if( x1a ){ +    x1a->size = 1024; +    x1a->count = 0; +    x1a->tbl = (x1node*)malloc(  +      (sizeof(x1node) + sizeof(x1node*))*1024 ); +    if( x1a->tbl==0 ){ +      free(x1a); +      x1a = 0; +    }else{ +      int i; +      x1a->ht = (x1node**)&(x1a->tbl[1024]); +      for(i=0; i<1024; i++) x1a->ht[i] = 0; +    } +  } +} +/* Insert a new record into the array.  Return TRUE if successful. +** Prior data with the same key is NOT overwritten */ +int Strsafe_insert(data) +char *data; +{ +  x1node *np; +  int h; +  int ph; + +  if( x1a==0 ) return 0; +  ph = strhash(data); +  h = ph & (x1a->size-1); +  np = x1a->ht[h]; +  while( np ){ +    if( strcmp(np->data,data)==0 ){ +      /* An existing entry with the same key is found. */ +      /* Fail because overwrite is not allows. */ +      return 0; +    } +    np = np->next; +  } +  if( x1a->count>=x1a->size ){ +    /* Need to make the hash table bigger */ +    int i,size; +    struct s_x1 array; +    array.size = size = x1a->size*2; +    array.count = x1a->count; +    array.tbl = (x1node*)malloc( +      (sizeof(x1node) + sizeof(x1node*))*size ); +    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ +    array.ht = (x1node**)&(array.tbl[size]); +    for(i=0; i<size; i++) array.ht[i] = 0; +    for(i=0; i<x1a->count; i++){ +      x1node *oldnp, *newnp; +      oldnp = &(x1a->tbl[i]); +      h = strhash(oldnp->data) & (size-1); +      newnp = &(array.tbl[i]); +      if( array.ht[h] ) array.ht[h]->from = &(newnp->next); +      newnp->next = array.ht[h]; +      newnp->data = oldnp->data; +      newnp->from = &(array.ht[h]); +      array.ht[h] = newnp; +    } +    free(x1a->tbl); +    *x1a = array; +  } +  /* Insert the new data */ +  h = ph & (x1a->size-1); +  np = &(x1a->tbl[x1a->count++]); +  np->data = data; +  if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next); +  np->next = x1a->ht[h]; +  x1a->ht[h] = np; +  np->from = &(x1a->ht[h]); +  return 1; +} + +/* Return a pointer to data assigned to the given key.  Return NULL +** if no such key. */ +char *Strsafe_find(key) +char *key; +{ +  int h; +  x1node *np; + +  if( x1a==0 ) return 0; +  h = strhash(key) & (x1a->size-1); +  np = x1a->ht[h]; +  while( np ){ +    if( strcmp(np->data,key)==0 ) break; +    np = np->next; +  } +  return np ? np->data : 0; +} + +/* Return a pointer to the (terminal or nonterminal) symbol "x". +** Create a new symbol if this is the first time "x" has been seen. +*/ +struct symbol *Symbol_new(x) +char *x; +{ +  struct symbol *sp; + +  sp = Symbol_find(x); +  if( sp==0 ){ +    sp = (struct symbol *)malloc( sizeof(struct symbol) ); +    MemoryCheck(sp); +    sp->name = Strsafe(x); +    sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; +    sp->rule = 0; +    sp->fallback = 0; +    sp->prec = -1; +    sp->assoc = UNK; +    sp->firstset = 0; +    sp->lambda = B_FALSE; +    sp->destructor = 0; +    sp->datatype = 0; +    Symbol_insert(sp,sp->name); +  } +  return sp; +} + +/* Compare two symbols for working purposes +** +** Symbols that begin with upper case letters (terminals or tokens) +** must sort before symbols that begin with lower case letters +** (non-terminals).  Other than that, the order does not matter. +** +** We find experimentally that leaving the symbols in their original +** order (the order they appeared in the grammar file) gives the +** smallest parser tables in SQLite. +*/ +int Symbolcmpp(struct symbol **a, struct symbol **b){ +  int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); +  int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); +  return i1-i2; +} + +/* There is one instance of the following structure for each +** associative array of type "x2". +*/ +struct s_x2 { +  int size;               /* The number of available slots. */ +                          /*   Must be a power of 2 greater than or */ +                          /*   equal to 1 */ +  int count;              /* Number of currently slots filled */ +  struct s_x2node *tbl;  /* The data stored here */ +  struct s_x2node **ht;  /* Hash table for lookups */ +}; + +/* There is one instance of this structure for every data element +** in an associative array of type "x2". +*/ +typedef struct s_x2node { +  struct symbol *data;                  /* The data */ +  char *key;                   /* The key */ +  struct s_x2node *next;   /* Next entry with the same hash */ +  struct s_x2node **from;  /* Previous link */ +} x2node; + +/* There is only one instance of the array, which is the following */ +static struct s_x2 *x2a; + +/* Allocate a new associative array */ +void Symbol_init(){ +  if( x2a ) return; +  x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); +  if( x2a ){ +    x2a->size = 128; +    x2a->count = 0; +    x2a->tbl = (x2node*)malloc(  +      (sizeof(x2node) + sizeof(x2node*))*128 ); +    if( x2a->tbl==0 ){ +      free(x2a); +      x2a = 0; +    }else{ +      int i; +      x2a->ht = (x2node**)&(x2a->tbl[128]); +      for(i=0; i<128; i++) x2a->ht[i] = 0; +    } +  } +} +/* Insert a new record into the array.  Return TRUE if successful. +** Prior data with the same key is NOT overwritten */ +int Symbol_insert(data,key) +struct symbol *data; +char *key; +{ +  x2node *np; +  int h; +  int ph; + +  if( x2a==0 ) return 0; +  ph = strhash(key); +  h = ph & (x2a->size-1); +  np = x2a->ht[h]; +  while( np ){ +    if( strcmp(np->key,key)==0 ){ +      /* An existing entry with the same key is found. */ +      /* Fail because overwrite is not allows. */ +      return 0; +    } +    np = np->next; +  } +  if( x2a->count>=x2a->size ){ +    /* Need to make the hash table bigger */ +    int i,size; +    struct s_x2 array; +    array.size = size = x2a->size*2; +    array.count = x2a->count; +    array.tbl = (x2node*)malloc( +      (sizeof(x2node) + sizeof(x2node*))*size ); +    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ +    array.ht = (x2node**)&(array.tbl[size]); +    for(i=0; i<size; i++) array.ht[i] = 0; +    for(i=0; i<x2a->count; i++){ +      x2node *oldnp, *newnp; +      oldnp = &(x2a->tbl[i]); +      h = strhash(oldnp->key) & (size-1); +      newnp = &(array.tbl[i]); +      if( array.ht[h] ) array.ht[h]->from = &(newnp->next); +      newnp->next = array.ht[h]; +      newnp->key = oldnp->key; +      newnp->data = oldnp->data; +      newnp->from = &(array.ht[h]); +      array.ht[h] = newnp; +    } +    free(x2a->tbl); +    *x2a = array; +  } +  /* Insert the new data */ +  h = ph & (x2a->size-1); +  np = &(x2a->tbl[x2a->count++]); +  np->key = key; +  np->data = data; +  if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next); +  np->next = x2a->ht[h]; +  x2a->ht[h] = np; +  np->from = &(x2a->ht[h]); +  return 1; +} + +/* Return a pointer to data assigned to the given key.  Return NULL +** if no such key. */ +struct symbol *Symbol_find(key) +char *key; +{ +  int h; +  x2node *np; + +  if( x2a==0 ) return 0; +  h = strhash(key) & (x2a->size-1); +  np = x2a->ht[h]; +  while( np ){ +    if( strcmp(np->key,key)==0 ) break; +    np = np->next; +  } +  return np ? np->data : 0; +} + +/* Return the n-th data.  Return NULL if n is out of range. */ +struct symbol *Symbol_Nth(n) +int n; +{ +  struct symbol *data; +  if( x2a && n>0 && n<=x2a->count ){ +    data = x2a->tbl[n-1].data; +  }else{ +    data = 0; +  } +  return data; +} + +/* Return the size of the array */ +int Symbol_count() +{ +  return x2a ? x2a->count : 0; +} + +/* Return an array of pointers to all data in the table. +** The array is obtained from malloc.  Return NULL if memory allocation +** problems, or if the array is empty. */ +struct symbol **Symbol_arrayof() +{ +  struct symbol **array; +  int i,size; +  if( x2a==0 ) return 0; +  size = x2a->count; +  array = (struct symbol **)malloc( sizeof(struct symbol *)*size ); +  if( array ){ +    for(i=0; i<size; i++) array[i] = x2a->tbl[i].data; +  } +  return array; +} + +/* Compare two configurations */ +int Configcmp(a,b) +struct config *a; +struct config *b; +{ +  int x; +  x = a->rp->index - b->rp->index; +  if( x==0 ) x = a->dot - b->dot; +  return x; +} + +/* Compare two states */ +PRIVATE int statecmp(a,b) +struct config *a; +struct config *b; +{ +  int rc; +  for(rc=0; rc==0 && a && b;  a=a->bp, b=b->bp){ +    rc = a->rp->index - b->rp->index; +    if( rc==0 ) rc = a->dot - b->dot; +  } +  if( rc==0 ){ +    if( a ) rc = 1; +    if( b ) rc = -1; +  } +  return rc; +} + +/* Hash a state */ +PRIVATE int statehash(a) +struct config *a; +{ +  int h=0; +  while( a ){ +    h = h*571 + a->rp->index*37 + a->dot; +    a = a->bp; +  } +  return h; +} + +/* Allocate a new state structure */ +struct state *State_new() +{ +  struct state *new; +  new = (struct state *)malloc( sizeof(struct state) ); +  MemoryCheck(new); +  return new; +} + +/* There is one instance of the following structure for each +** associative array of type "x3". +*/ +struct s_x3 { +  int size;               /* The number of available slots. */ +                          /*   Must be a power of 2 greater than or */ +                          /*   equal to 1 */ +  int count;              /* Number of currently slots filled */ +  struct s_x3node *tbl;  /* The data stored here */ +  struct s_x3node **ht;  /* Hash table for lookups */ +}; + +/* There is one instance of this structure for every data element +** in an associative array of type "x3". +*/ +typedef struct s_x3node { +  struct state *data;                  /* The data */ +  struct config *key;                   /* The key */ +  struct s_x3node *next;   /* Next entry with the same hash */ +  struct s_x3node **from;  /* Previous link */ +} x3node; + +/* There is only one instance of the array, which is the following */ +static struct s_x3 *x3a; + +/* Allocate a new associative array */ +void State_init(){ +  if( x3a ) return; +  x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); +  if( x3a ){ +    x3a->size = 128; +    x3a->count = 0; +    x3a->tbl = (x3node*)malloc(  +      (sizeof(x3node) + sizeof(x3node*))*128 ); +    if( x3a->tbl==0 ){ +      free(x3a); +      x3a = 0; +    }else{ +      int i; +      x3a->ht = (x3node**)&(x3a->tbl[128]); +      for(i=0; i<128; i++) x3a->ht[i] = 0; +    } +  } +} +/* Insert a new record into the array.  Return TRUE if successful. +** Prior data with the same key is NOT overwritten */ +int State_insert(data,key) +struct state *data; +struct config *key; +{ +  x3node *np; +  int h; +  int ph; + +  if( x3a==0 ) return 0; +  ph = statehash(key); +  h = ph & (x3a->size-1); +  np = x3a->ht[h]; +  while( np ){ +    if( statecmp(np->key,key)==0 ){ +      /* An existing entry with the same key is found. */ +      /* Fail because overwrite is not allows. */ +      return 0; +    } +    np = np->next; +  } +  if( x3a->count>=x3a->size ){ +    /* Need to make the hash table bigger */ +    int i,size; +    struct s_x3 array; +    array.size = size = x3a->size*2; +    array.count = x3a->count; +    array.tbl = (x3node*)malloc( +      (sizeof(x3node) + sizeof(x3node*))*size ); +    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ +    array.ht = (x3node**)&(array.tbl[size]); +    for(i=0; i<size; i++) array.ht[i] = 0; +    for(i=0; i<x3a->count; i++){ +      x3node *oldnp, *newnp; +      oldnp = &(x3a->tbl[i]); +      h = statehash(oldnp->key) & (size-1); +      newnp = &(array.tbl[i]); +      if( array.ht[h] ) array.ht[h]->from = &(newnp->next); +      newnp->next = array.ht[h]; +      newnp->key = oldnp->key; +      newnp->data = oldnp->data; +      newnp->from = &(array.ht[h]); +      array.ht[h] = newnp; +    } +    free(x3a->tbl); +    *x3a = array; +  } +  /* Insert the new data */ +  h = ph & (x3a->size-1); +  np = &(x3a->tbl[x3a->count++]); +  np->key = key; +  np->data = data; +  if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next); +  np->next = x3a->ht[h]; +  x3a->ht[h] = np; +  np->from = &(x3a->ht[h]); +  return 1; +} + +/* Return a pointer to data assigned to the given key.  Return NULL +** if no such key. */ +struct state *State_find(key) +struct config *key; +{ +  int h; +  x3node *np; + +  if( x3a==0 ) return 0; +  h = statehash(key) & (x3a->size-1); +  np = x3a->ht[h]; +  while( np ){ +    if( statecmp(np->key,key)==0 ) break; +    np = np->next; +  } +  return np ? np->data : 0; +} + +/* Return an array of pointers to all data in the table. +** The array is obtained from malloc.  Return NULL if memory allocation +** problems, or if the array is empty. */ +struct state **State_arrayof() +{ +  struct state **array; +  int i,size; +  if( x3a==0 ) return 0; +  size = x3a->count; +  array = (struct state **)malloc( sizeof(struct state *)*size ); +  if( array ){ +    for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; +  } +  return array; +} + +/* Hash a configuration */ +PRIVATE int confighash(a) +struct config *a; +{ +  int h=0; +  h = h*571 + a->rp->index*37 + a->dot; +  return h; +} + +/* There is one instance of the following structure for each +** associative array of type "x4". +*/ +struct s_x4 { +  int size;               /* The number of available slots. */ +                          /*   Must be a power of 2 greater than or */ +                          /*   equal to 1 */ +  int count;              /* Number of currently slots filled */ +  struct s_x4node *tbl;  /* The data stored here */ +  struct s_x4node **ht;  /* Hash table for lookups */ +}; + +/* There is one instance of this structure for every data element +** in an associative array of type "x4". +*/ +typedef struct s_x4node { +  struct config *data;                  /* The data */ +  struct s_x4node *next;   /* Next entry with the same hash */ +  struct s_x4node **from;  /* Previous link */ +} x4node; + +/* There is only one instance of the array, which is the following */ +static struct s_x4 *x4a; + +/* Allocate a new associative array */ +void Configtable_init(){ +  if( x4a ) return; +  x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); +  if( x4a ){ +    x4a->size = 64; +    x4a->count = 0; +    x4a->tbl = (x4node*)malloc(  +      (sizeof(x4node) + sizeof(x4node*))*64 ); +    if( x4a->tbl==0 ){ +      free(x4a); +      x4a = 0; +    }else{ +      int i; +      x4a->ht = (x4node**)&(x4a->tbl[64]); +      for(i=0; i<64; i++) x4a->ht[i] = 0; +    } +  } +} +/* Insert a new record into the array.  Return TRUE if successful. +** Prior data with the same key is NOT overwritten */ +int Configtable_insert(data) +struct config *data; +{ +  x4node *np; +  int h; +  int ph; + +  if( x4a==0 ) return 0; +  ph = confighash(data); +  h = ph & (x4a->size-1); +  np = x4a->ht[h]; +  while( np ){ +    if( Configcmp(np->data,data)==0 ){ +      /* An existing entry with the same key is found. */ +      /* Fail because overwrite is not allows. */ +      return 0; +    } +    np = np->next; +  } +  if( x4a->count>=x4a->size ){ +    /* Need to make the hash table bigger */ +    int i,size; +    struct s_x4 array; +    array.size = size = x4a->size*2; +    array.count = x4a->count; +    array.tbl = (x4node*)malloc( +      (sizeof(x4node) + sizeof(x4node*))*size ); +    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ +    array.ht = (x4node**)&(array.tbl[size]); +    for(i=0; i<size; i++) array.ht[i] = 0; +    for(i=0; i<x4a->count; i++){ +      x4node *oldnp, *newnp; +      oldnp = &(x4a->tbl[i]); +      h = confighash(oldnp->data) & (size-1); +      newnp = &(array.tbl[i]); +      if( array.ht[h] ) array.ht[h]->from = &(newnp->next); +      newnp->next = array.ht[h]; +      newnp->data = oldnp->data; +      newnp->from = &(array.ht[h]); +      array.ht[h] = newnp; +    } +    free(x4a->tbl); +    *x4a = array; +  } +  /* Insert the new data */ +  h = ph & (x4a->size-1); +  np = &(x4a->tbl[x4a->count++]); +  np->data = data; +  if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next); +  np->next = x4a->ht[h]; +  x4a->ht[h] = np; +  np->from = &(x4a->ht[h]); +  return 1; +} + +/* Return a pointer to data assigned to the given key.  Return NULL +** if no such key. */ +struct config *Configtable_find(key) +struct config *key; +{ +  int h; +  x4node *np; + +  if( x4a==0 ) return 0; +  h = confighash(key) & (x4a->size-1); +  np = x4a->ht[h]; +  while( np ){ +    if( Configcmp(np->data,key)==0 ) break; +    np = np->next; +  } +  return np ? np->data : 0; +} + +/* Remove all data from the table.  Pass each data to the function "f" +** as it is removed.  ("f" may be null to avoid this step.) */ +void Configtable_clear(f) +int(*f)(/* struct config * */); +{ +  int i; +  if( x4a==0 || x4a->count==0 ) return; +  if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); +  for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; +  x4a->count = 0; +  return; +} diff --git a/ext/pdo_sqlite/sqlite/tool/lempar.c b/ext/pdo_sqlite/sqlite/tool/lempar.c new file mode 100644 index 0000000000..aac842f10c --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/lempar.c @@ -0,0 +1,687 @@ +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. +*/ +/* First off, code is include which follows the "include" declaration +** in the input file. */ +#include <stdio.h> +%% +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/*  +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands.  +** +** Each symbol here is a terminal symbol in the grammar. +*/ +%% +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control +** various aspects of the generated parser. +**    YYCODETYPE         is the data type used for storing terminal +**                       and nonterminal numbers.  "unsigned char" is +**                       used if there are fewer than 250 terminals +**                       and nonterminals.  "int" is used otherwise. +**    YYNOCODE           is a number of type YYCODETYPE which corresponds +**                       to no legal terminal or nonterminal number.  This +**                       number is used to fill in empty slots of the hash  +**                       table. +**    YYFALLBACK         If defined, this indicates that one or more tokens +**                       have fall-back values which should be used if the +**                       original value of the token will not parse. +**    YYACTIONTYPE       is the data type used for storing terminal +**                       and nonterminal numbers.  "unsigned char" is +**                       used if there are fewer than 250 rules and +**                       states combined.  "int" is used otherwise. +**    ParseTOKENTYPE     is the data type used for minor tokens given  +**                       directly to the parser from the tokenizer. +**    YYMINORTYPE        is the data type used for all minor tokens. +**                       This is typically a union of many types, one of +**                       which is ParseTOKENTYPE.  The entry in the union +**                       for base tokens is called "yy0". +**    YYSTACKDEPTH       is the maximum depth of the parser's stack. +**    ParseARG_SDECL     A static variable declaration for the %extra_argument +**    ParseARG_PDECL     A parameter declaration for the %extra_argument +**    ParseARG_STORE     Code to store %extra_argument into yypParser +**    ParseARG_FETCH     Code to extract %extra_argument from yypParser +**    YYNSTATE           the combined number of states. +**    YYNRULE            the number of rules in the grammar +**    YYERRORSYMBOL      is the code number of the error symbol.  If not +**                       defined, then do no error processing. +*/ +%% +#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE) + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token.  These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer.   +** +** Suppose the action integer is N.  Then the action is determined as +** follows +** +**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead +**                                      token onto the stack and goto state N. +** +**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE. +** +**   N == YYNSTATE+YYNRULE              A syntax error has occurred. +** +**   N == YYNSTATE+YYNRULE+1            The parser accepts its input. +** +**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused +**                                      slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as +** +**      yy_action[ yy_shift_ofst[S] + X ] +** +** If the index value yy_shift_ofst[S]+X is out of range or if the value +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table +** and that yy_default[S] should be used instead.   +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol.  If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +**  yy_action[]        A single table containing all actions. +**  yy_lookahead[]     A table containing the lookahead for each entry in +**                     yy_action.  Used to detect hash collisions. +**  yy_shift_ofst[]    For each state, the offset into yy_action for +**                     shifting terminals. +**  yy_reduce_ofst[]   For each state, the offset into yy_action for +**                     shifting non-terminals after a reduce. +**  yy_default[]       Default action for each state. +*/ +%% +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) + +/* The next table maps tokens into fallback tokens.  If a construct +** like the following: +**  +**      %fallback ID X Y Z. +** +** appears in the grammer, then ID becomes a fallback token for X, Y, +** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +*/ +#ifdef YYFALLBACK +static const YYCODETYPE yyFallback[] = { +%% +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack.  Information stored includes: +** +**   +  The state number for the parser at this level of the stack. +** +**   +  The value of the token stored at this level of the stack. +**      (In other words, the "major" token.) +** +**   +  The semantic value stored at this level of the stack.  This is +**      the information used by the action routines in the grammar. +**      It is sometimes called the "minor" token. +*/ +struct yyStackEntry { +  int stateno;       /* The state-number */ +  int major;         /* The major token value.  This is the code +                     ** number for the token at this stack level */ +  YYMINORTYPE minor; /* The user-supplied minor token value.  This +                     ** is the value of the token  */ +}; +typedef struct yyStackEntry yyStackEntry; + +/* The state of the parser is completely contained in an instance of +** the following structure */ +struct yyParser { +  int yyidx;                    /* Index of top element in stack */ +  int yyerrcnt;                 /* Shifts left before out of the error */ +  ParseARG_SDECL                /* A place to hold %extra_argument */ +  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */ +}; +typedef struct yyParser yyParser; + +#ifndef NDEBUG +#include <stdio.h> +static FILE *yyTraceFILE = 0; +static char *yyTracePrompt = 0; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/*  +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message.  Tracing is turned off +** by making either argument NULL  +** +** Inputs: +** <ul> +** <li> A FILE* to which trace output should be written. +**      If NULL, then tracing is turned off. +** <li> A prefix string written at the beginning of every +**      line of trace output.  If NULL, then tracing is +**      turned off. +** </ul> +** +** Outputs: +** None. +*/ +void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ +  yyTraceFILE = TraceFILE; +  yyTracePrompt = zTracePrompt; +  if( yyTraceFILE==0 ) yyTracePrompt = 0; +  else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required.  The following table supplies these names */ +static const char *const yyTokenName[] = {  +%% +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +static const char *const yyRuleName[] = { +%% +}; +#endif /* NDEBUG */ + +/* +** This function returns the symbolic name associated with a token +** value. +*/ +const char *ParseTokenName(int tokenType){ +#ifndef NDEBUG +  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ +    return yyTokenName[tokenType]; +  }else{ +    return "Unknown"; +  } +#else +  return ""; +#endif +} + +/*  +** This function allocates a new parser. +** The only argument is a pointer to a function which works like +** malloc. +** +** Inputs: +** A pointer to the function used to allocate memory. +** +** Outputs: +** A pointer to a parser.  This pointer is used in subsequent calls +** to Parse and ParseFree. +*/ +void *ParseAlloc(void *(*mallocProc)(size_t)){ +  yyParser *pParser; +  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); +  if( pParser ){ +    pParser->yyidx = -1; +  } +  return pParser; +} + +/* The following function deletes the value associated with a +** symbol.  The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. +*/ +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ +  switch( yymajor ){ +    /* Here is inserted the actions which take place when a +    ** terminal or non-terminal is destroyed.  This can happen +    ** when the symbol is popped from the stack during a +    ** reduce or during error processing or when a parser is  +    ** being destroyed before it is finished parsing. +    ** +    ** Note: during a reduce, the only symbols destroyed are those +    ** which appear on the RHS of the rule, but which are not used +    ** inside the C code. +    */ +%% +    default:  break;   /* If no destructor action specified: do nothing */ +  } +} + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. +*/ +static int yy_pop_parser_stack(yyParser *pParser){ +  YYCODETYPE yymajor; +  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + +  if( pParser->yyidx<0 ) return 0; +#ifndef NDEBUG +  if( yyTraceFILE && pParser->yyidx>=0 ){ +    fprintf(yyTraceFILE,"%sPopping %s\n", +      yyTracePrompt, +      yyTokenName[yytos->major]); +  } +#endif +  yymajor = yytos->major; +  yy_destructor( yymajor, &yytos->minor); +  pParser->yyidx--; +  return yymajor; +} + +/*  +** Deallocate and destroy a parser.  Destructors are all called for +** all stack elements before shutting the parser down. +** +** Inputs: +** <ul> +** <li>  A pointer to the parser.  This should be a pointer +**       obtained from ParseAlloc. +** <li>  A pointer to a function used to reclaim memory obtained +**       from malloc. +** </ul> +*/ +void ParseFree( +  void *p,                    /* The parser to be deleted */ +  void (*freeProc)(void*)     /* Function used to reclaim memory */ +){ +  yyParser *pParser = (yyParser*)p; +  if( pParser==0 ) return; +  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +  (*freeProc)((void*)pParser); +} + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead.  If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_shift_action( +  yyParser *pParser,        /* The parser */ +  int iLookAhead            /* The look-ahead token */ +){ +  int i; +  int stateno = pParser->yystack[pParser->yyidx].stateno; +  +  /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */ +  i = yy_shift_ofst[stateno]; +  if( i==YY_SHIFT_USE_DFLT ){ +    return yy_default[stateno]; +  } +  if( iLookAhead==YYNOCODE ){ +    return YY_NO_ACTION; +  } +  i += iLookAhead; +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ +#ifdef YYFALLBACK +    int iFallback;            /* Fallback token */ +    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) +           && (iFallback = yyFallback[iLookAhead])!=0 ){ +#ifndef NDEBUG +      if( yyTraceFILE ){ +        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", +           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); +      } +#endif +      return yy_find_shift_action(pParser, iFallback); +    } +#endif +    return yy_default[stateno]; +  }else{ +    return yy_action[i]; +  } +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead.  If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_reduce_action( +  yyParser *pParser,        /* The parser */ +  int iLookAhead            /* The look-ahead token */ +){ +  int i; +  int stateno = pParser->yystack[pParser->yyidx].stateno; +  +  i = yy_reduce_ofst[stateno]; +  if( i==YY_REDUCE_USE_DFLT ){ +    return yy_default[stateno]; +  } +  if( iLookAhead==YYNOCODE ){ +    return YY_NO_ACTION; +  } +  i += iLookAhead; +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ +    return yy_default[stateno]; +  }else{ +    return yy_action[i]; +  } +} + +/* +** Perform a shift action. +*/ +static void yy_shift( +  yyParser *yypParser,          /* The parser to be shifted */ +  int yyNewState,               /* The new state to shift in */ +  int yyMajor,                  /* The major token to shift in */ +  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */ +){ +  yyStackEntry *yytos; +  yypParser->yyidx++; +  if( yypParser->yyidx>=YYSTACKDEPTH ){ +     ParseARG_FETCH; +     yypParser->yyidx--; +#ifndef NDEBUG +     if( yyTraceFILE ){ +       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); +     } +#endif +     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +     /* Here code is inserted which will execute if the parser +     ** stack every overflows */ +%% +     ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ +     return; +  } +  yytos = &yypParser->yystack[yypParser->yyidx]; +  yytos->stateno = yyNewState; +  yytos->major = yyMajor; +  yytos->minor = *yypMinor; +#ifndef NDEBUG +  if( yyTraceFILE && yypParser->yyidx>0 ){ +    int i; +    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); +    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); +    for(i=1; i<=yypParser->yyidx; i++) +      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); +    fprintf(yyTraceFILE,"\n"); +  } +#endif +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { +  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */ +  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */ +} yyRuleInfo[] = { +%% +}; + +static void yy_accept(yyParser*);  /* Forward Declaration */ + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +static void yy_reduce( +  yyParser *yypParser,         /* The parser */ +  int yyruleno                 /* Number of the rule by which to reduce */ +){ +  int yygoto;                     /* The next state */ +  int yyact;                      /* The next action */ +  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */ +  yyStackEntry *yymsp;            /* The top of the parser's stack */ +  int yysize;                     /* Amount to pop the stack */ +  ParseARG_FETCH; +  yymsp = &yypParser->yystack[yypParser->yyidx]; +#ifndef NDEBUG +  if( yyTraceFILE && yyruleno>=0  +        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ +    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, +      yyRuleName[yyruleno]); +  } +#endif /* NDEBUG */ + +  switch( yyruleno ){ +  /* Beginning here are the reduction cases.  A typical example +  ** follows: +  **   case 0: +  **  #line <lineno> <grammarfile> +  **     { ... }           // User supplied code +  **  #line <lineno> <thisfile> +  **     break; +  */ +%% +  }; +  yygoto = yyRuleInfo[yyruleno].lhs; +  yysize = yyRuleInfo[yyruleno].nrhs; +  yypParser->yyidx -= yysize; +  yyact = yy_find_reduce_action(yypParser,yygoto); +  if( yyact < YYNSTATE ){ +    yy_shift(yypParser,yyact,yygoto,&yygotominor); +  }else if( yyact == YYNSTATE + YYNRULE + 1 ){ +    yy_accept(yypParser); +  } +} + +/* +** The following code executes when the parse fails +*/ +static void yy_parse_failed( +  yyParser *yypParser           /* The parser */ +){ +  ParseARG_FETCH; +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); +  } +#endif +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +  /* Here code is inserted which will be executed whenever the +  ** parser fails */ +%% +  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following code executes when a syntax error first occurs. +*/ +static void yy_syntax_error( +  yyParser *yypParser,           /* The parser */ +  int yymajor,                   /* The major type of the error token */ +  YYMINORTYPE yyminor            /* The minor type of the error token */ +){ +  ParseARG_FETCH; +#define TOKEN (yyminor.yy0) +%% +  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following is executed when the parser accepts +*/ +static void yy_accept( +  yyParser *yypParser           /* The parser */ +){ +  ParseARG_FETCH; +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); +  } +#endif +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +  /* Here code is inserted which will be executed whenever the +  ** parser accepts */ +%% +  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "ParseAlloc" which describes the current state of the parser. +** The second argument is the major token number.  The third is +** the minor token.  The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +** <ul> +** <li> A pointer to the parser (an opaque structure.) +** <li> The major token number. +** <li> The minor token number. +** <li> An option argument of a grammar-specified type. +** </ul> +** +** Outputs: +** None. +*/ +void Parse( +  void *yyp,                   /* The parser */ +  int yymajor,                 /* The major token code number */ +  ParseTOKENTYPE yyminor       /* The value for the token */ +  ParseARG_PDECL               /* Optional %extra_argument parameter */ +){ +  YYMINORTYPE yyminorunion; +  int yyact;            /* The parser action. */ +  int yyendofinput;     /* True if we are at the end of input */ +  int yyerrorhit = 0;   /* True if yymajor has invoked an error */ +  yyParser *yypParser;  /* The parser */ + +  /* (re)initialize the parser, if necessary */ +  yypParser = (yyParser*)yyp; +  if( yypParser->yyidx<0 ){ +    if( yymajor==0 ) return; +    yypParser->yyidx = 0; +    yypParser->yyerrcnt = -1; +    yypParser->yystack[0].stateno = 0; +    yypParser->yystack[0].major = 0; +  } +  yyminorunion.yy0 = yyminor; +  yyendofinput = (yymajor==0); +  ParseARG_STORE; + +#ifndef NDEBUG +  if( yyTraceFILE ){ +    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); +  } +#endif + +  do{ +    yyact = yy_find_shift_action(yypParser,yymajor); +    if( yyact<YYNSTATE ){ +      yy_shift(yypParser,yyact,yymajor,&yyminorunion); +      yypParser->yyerrcnt--; +      if( yyendofinput && yypParser->yyidx>=0 ){ +        yymajor = 0; +      }else{ +        yymajor = YYNOCODE; +      } +    }else if( yyact < YYNSTATE + YYNRULE ){ +      yy_reduce(yypParser,yyact-YYNSTATE); +    }else if( yyact == YY_ERROR_ACTION ){ +      int yymx; +#ifndef NDEBUG +      if( yyTraceFILE ){ +        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); +      } +#endif +#ifdef YYERRORSYMBOL +      /* A syntax error has occurred. +      ** The response to an error depends upon whether or not the +      ** grammar defines an error token "ERROR".   +      ** +      ** This is what we do if the grammar does define ERROR: +      ** +      **  * Call the %syntax_error function. +      ** +      **  * Begin popping the stack until we enter a state where +      **    it is legal to shift the error symbol, then shift +      **    the error symbol. +      ** +      **  * Set the error count to three. +      ** +      **  * Begin accepting and shifting new tokens.  No new error +      **    processing will occur until three tokens have been +      **    shifted successfully. +      ** +      */ +      if( yypParser->yyerrcnt<0 ){ +        yy_syntax_error(yypParser,yymajor,yyminorunion); +      } +      yymx = yypParser->yystack[yypParser->yyidx].major; +      if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG +        if( yyTraceFILE ){ +          fprintf(yyTraceFILE,"%sDiscard input token %s\n", +             yyTracePrompt,yyTokenName[yymajor]); +        } +#endif +        yy_destructor(yymajor,&yyminorunion); +        yymajor = YYNOCODE; +      }else{ +         while( +          yypParser->yyidx >= 0 && +          yymx != YYERRORSYMBOL && +          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE +        ){ +          yy_pop_parser_stack(yypParser); +        } +        if( yypParser->yyidx < 0 || yymajor==0 ){ +          yy_destructor(yymajor,&yyminorunion); +          yy_parse_failed(yypParser); +          yymajor = YYNOCODE; +        }else if( yymx!=YYERRORSYMBOL ){ +          YYMINORTYPE u2; +          u2.YYERRSYMDT = 0; +          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); +        } +      } +      yypParser->yyerrcnt = 3; +      yyerrorhit = 1; +#else  /* YYERRORSYMBOL is not defined */ +      /* This is what we do if the grammar does not define ERROR: +      ** +      **  * Report an error message, and throw away the input token. +      ** +      **  * If the input token is $, then fail the parse. +      ** +      ** As before, subsequent error messages are suppressed until +      ** three input tokens have been successfully shifted. +      */ +      if( yypParser->yyerrcnt<=0 ){ +        yy_syntax_error(yypParser,yymajor,yyminorunion); +      } +      yypParser->yyerrcnt = 3; +      yy_destructor(yymajor,&yyminorunion); +      if( yyendofinput ){ +        yy_parse_failed(yypParser); +      } +      yymajor = YYNOCODE; +#endif +    }else{ +      yy_accept(yypParser); +      yymajor = YYNOCODE; +    } +  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); +  return; +} diff --git a/ext/pdo_sqlite/sqlite/tool/memleak.awk b/ext/pdo_sqlite/sqlite/tool/memleak.awk new file mode 100644 index 0000000000..185f174897 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/memleak.awk @@ -0,0 +1,29 @@ +# +# This script looks for memory leaks by analyzing the output of "sqlite"  +# when compiled with the MEMORY_DEBUG=2 option. +# +/[0-9]+ malloc / { +  mem[$6] = $0 +} +/[0-9]+ realloc / { +  mem[$8] = ""; +  mem[$10] = $0 +} +/[0-9]+ free / { +  if (mem[$6]=="") { +    print "*** free without a malloc at",$6 +  } +  mem[$6] = ""; +  str[$6] = "" +} +/^string at / { +  addr = $4 +  sub("string at " addr " is ","") +  str[addr] = $0 +} +END { +  for(addr in mem){ +    if( mem[addr]=="" ) continue +    print mem[addr], str[addr] +  } +} diff --git a/ext/pdo_sqlite/sqlite/tool/memleak2.awk b/ext/pdo_sqlite/sqlite/tool/memleak2.awk new file mode 100644 index 0000000000..5d81b70d8d --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/memleak2.awk @@ -0,0 +1,29 @@ +# This AWK script reads the output of testfixture when compiled for memory +# debugging.  It generates SQL commands that can be fed into an sqlite  +# instance to determine what memory is never freed.  A typical usage would +# be as follows: +# +#     make -f memleak.mk fulltest 2>mem.out +#     awk -f ../sqlite/tool/memleak2.awk mem.out | ./sqlite :memory: +# +# The job performed by this script is the same as that done by memleak.awk. +# The difference is that this script uses much less memory when the size +# of the mem.out file is huge. +# +BEGIN { +  print "CREATE TABLE mem(loc INTEGER PRIMARY KEY, src);" +} +/[0-9]+ malloc / { +  print "INSERT INTO mem VALUES(" strtonum($6) ",'" $0 "');" +} +/[0-9]+ realloc / { +  print "INSERT INTO mem VALUES(" strtonum($10) \ +           ",(SELECT src FROM mem WHERE loc=" strtonum($8) "));" +  print "DELETE FROM mem WHERE loc=" strtonum($8) ";" +} +/[0-9]+ free / { +  print "DELETE FROM mem WHERE loc=" strtonum($6) ";" +} +END { +  print "SELECT src FROM mem;" +} diff --git a/ext/pdo_sqlite/sqlite/tool/memleak3.tcl b/ext/pdo_sqlite/sqlite/tool/memleak3.tcl new file mode 100644 index 0000000000..69bc4ae88e --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/memleak3.tcl @@ -0,0 +1,106 @@ +#/bin/sh +# \ +exec `which tclsh` $0 "$@" +# +# The author disclaims copyright to this source code.  In place of +# a legal notice, here is a blessing: +# +#    May you do good and not evil. +#    May you find forgiveness for yourself and forgive others. +#    May you share freely, never taking more than you give. +###################################################################### + +set doco " +This script is a tool to help track down memory leaks in the sqlite +library. The library must be compiled with the preprocessor symbol +SQLITE_DEBUG set to at least 2. It must be set to 3 to enable stack traces. + +To use, run the leaky application and save the standard error output. +Then, execute this program with the first argument the name of the +application binary (or interpreter) and the second argument the name of the +text file that contains the collected stderr output. + +If all goes well a summary of unfreed allocations is printed out. If the +GNU C library is in use and SQLITE_DEBUG is 3 or greater a stack trace is +printed out for each unmatched allocation. + +Example: + +$ ./testfixture ../sqlite/test/select1.test 2> memtrace.out +$ tclsh $argv0 ./testfixture memtrace.out +" + +# If stack traces are enabled, the 'addr2line' program is called to +# translate a binary stack address into a human-readable form. +set addr2line addr2line + +if { [llength $argv]!=2 } { +  puts "Usage: $argv0 <binary file> <mem trace file>" +  puts "" +  puts [string trim $doco] +  exit -1 +} + + +proc process_input {input_file array_name} { +  upvar $array_name mem  +  set input [open $input_file] + +  set MALLOC {([[:digit:]]+) malloc ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)} +  set STACK {^STACK: (.*)$} +  set FREE {[[:digit:]]+ free ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)} +  set REALLOC {([[:digit:]]+) realloc ([[:digit:]]+) to ([[:digit:]]+)} +  append REALLOC { bytes at 0x([[:xdigit:]]+) to 0x([[:xdigit:]]+)} + +  set stack "" +  while { ![eof $input] } { +    set line [gets $input] +    if {[regexp $STACK $line dummy stack]} { +      # Do nothing. The variable $stack now stores the hexadecimal stack dump +      # for the next malloc() or realloc(). + +    } elseif { [regexp $MALLOC $line dummy mallocid bytes addr]  } { +      # If this is a 'malloc' line, set an entry in the mem array. Each entry +      # is a list of length three, the number of bytes allocated , the malloc +      # number and the stack dump when it was allocated. +      set mem($addr) [list $bytes "malloc $mallocid" $stack] +      set stack "" + +    } elseif { [regexp $FREE $line dummy bytes addr] } { +      # If this is a 'free' line, remove the entry from the mem array. If the  +      # entry does not exist, or is the wrong number of bytes, announce a +      # problem. This is more likely a bug in the regular expressions for +      # this script than an SQLite defect. +      if { [lindex $mem($addr) 0] != $bytes } { +        error "byte count mismatch" +      } +      unset mem($addr)  + +    } elseif { [regexp $REALLOC $line dummy mallocid ob b oa a] } { +      # If it is a realloc line, remove the old mem entry and add a new one. +      unset mem($oa); +      set mem($a) [list $b "realloc $mallocid" $stack] +      set stack "" +    } else { +      # puts "REJECT: $line" +    } +  } + +  close $input +} + +process_input [lindex $argv 1] mem +set exe [lindex $argv 0] + +foreach key [array names mem] { +  set bytes [lindex $mem($key) 0] +  set mallocid [lindex $mem($key) 1] +  set stack [lindex $mem($key) 2] +  puts "Leaked $bytes bytes at 0x$key: $mallocid" +  foreach frame [lrange $stack 1 10] { +    foreach {f l} [split [exec $addr2line -f --exe=$exe $frame] \n] {} +    puts [format "%-30s %s" $f $l] +  } +  if {[llength $stack]>0 } {puts ""} +} + diff --git a/ext/pdo_sqlite/sqlite/tool/mkkeywordhash.c b/ext/pdo_sqlite/sqlite/tool/mkkeywordhash.c new file mode 100644 index 0000000000..1e51d0ebb2 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/mkkeywordhash.c @@ -0,0 +1,312 @@ +/* +** Compile and run this standalone program in order to generate code that +** implements a function that will translate alphabetic identifiers into +** parser token codes. +*/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +/* +** All the keywords of the SQL language are stored as in a hash +** table composed of instances of the following structure. +*/ +typedef struct Keyword Keyword; +struct Keyword { +  char *zName;         /* The keyword name */ +  char *zTokenType;    /* Token value for this keyword */ +  int hash;            /* Hash on the keyword */ +  int offset;          /* Offset to start of name string */ +  int len;             /* Length of this keyword, not counting final \000 */ +  int iNext;           /* Index in aKeywordTable[] of next with same hash */ +}; + +/* +** These are the keywords +*/ +static Keyword aKeywordTable[] = { +  { "ABORT",            "TK_ABORT",        }, +  { "AFTER",            "TK_AFTER",        }, +  { "ALL",              "TK_ALL",          }, +  { "AND",              "TK_AND",          }, +  { "AS",               "TK_AS",           }, +  { "ASC",              "TK_ASC",          }, +  { "ATTACH",           "TK_ATTACH",       }, +  { "BEFORE",           "TK_BEFORE",       }, +  { "BEGIN",            "TK_BEGIN",        }, +  { "BETWEEN",          "TK_BETWEEN",      }, +  { "BY",               "TK_BY",           }, +  { "CASCADE",          "TK_CASCADE",      }, +  { "CASE",             "TK_CASE",         }, +  { "CHECK",            "TK_CHECK",        }, +  { "COLLATE",          "TK_COLLATE",      }, +  { "COMMIT",           "TK_COMMIT",       }, +  { "CONFLICT",         "TK_CONFLICT",     }, +  { "CONSTRAINT",       "TK_CONSTRAINT",   }, +  { "CREATE",           "TK_CREATE",       }, +  { "CROSS",            "TK_JOIN_KW",      }, +  { "DATABASE",         "TK_DATABASE",     }, +  { "DEFAULT",          "TK_DEFAULT",      }, +  { "DEFERRED",         "TK_DEFERRED",     }, +  { "DEFERRABLE",       "TK_DEFERRABLE",   }, +  { "DELETE",           "TK_DELETE",       }, +  { "DESC",             "TK_DESC",         }, +  { "DETACH",           "TK_DETACH",       }, +  { "DISTINCT",         "TK_DISTINCT",     }, +  { "DROP",             "TK_DROP",         }, +  { "END",              "TK_END",          }, +  { "EACH",             "TK_EACH",         }, +  { "ELSE",             "TK_ELSE",         }, +  { "EXCEPT",           "TK_EXCEPT",       }, +  { "EXCLUSIVE",        "TK_EXCLUSIVE",    }, +  { "EXPLAIN",          "TK_EXPLAIN",      }, +  { "FAIL",             "TK_FAIL",         }, +  { "FOR",              "TK_FOR",          }, +  { "FOREIGN",          "TK_FOREIGN",      }, +  { "FROM",             "TK_FROM",         }, +  { "FULL",             "TK_JOIN_KW",      }, +  { "GLOB",             "TK_GLOB",         }, +  { "GROUP",            "TK_GROUP",        }, +  { "HAVING",           "TK_HAVING",       }, +  { "IGNORE",           "TK_IGNORE",       }, +  { "IMMEDIATE",        "TK_IMMEDIATE",    }, +  { "IN",               "TK_IN",           }, +  { "INDEX",            "TK_INDEX",        }, +  { "INITIALLY",        "TK_INITIALLY",    }, +  { "INNER",            "TK_JOIN_KW",      }, +  { "INSERT",           "TK_INSERT",       }, +  { "INSTEAD",          "TK_INSTEAD",      }, +  { "INTERSECT",        "TK_INTERSECT",    }, +  { "INTO",             "TK_INTO",         }, +  { "IS",               "TK_IS",           }, +  { "ISNULL",           "TK_ISNULL",       }, +  { "JOIN",             "TK_JOIN",         }, +  { "KEY",              "TK_KEY",          }, +  { "LEFT",             "TK_JOIN_KW",      }, +  { "LIKE",             "TK_LIKE",         }, +  { "LIMIT",            "TK_LIMIT",        }, +  { "MATCH",            "TK_MATCH",        }, +  { "NATURAL",          "TK_JOIN_KW",      }, +  { "NOT",              "TK_NOT",          }, +  { "NOTNULL",          "TK_NOTNULL",      }, +  { "NULL",             "TK_NULL",         }, +  { "OF",               "TK_OF",           }, +  { "OFFSET",           "TK_OFFSET",       }, +  { "ON",               "TK_ON",           }, +  { "OR",               "TK_OR",           }, +  { "ORDER",            "TK_ORDER",        }, +  { "OUTER",            "TK_JOIN_KW",      }, +  { "PRAGMA",           "TK_PRAGMA",       }, +  { "PRIMARY",          "TK_PRIMARY",      }, +  { "RAISE",            "TK_RAISE",        }, +  { "REFERENCES",       "TK_REFERENCES",   }, +  { "REPLACE",          "TK_REPLACE",      }, +  { "RESTRICT",         "TK_RESTRICT",     }, +  { "RIGHT",            "TK_JOIN_KW",      }, +  { "ROLLBACK",         "TK_ROLLBACK",     }, +  { "ROW",              "TK_ROW",          }, +  { "SELECT",           "TK_SELECT",       }, +  { "SET",              "TK_SET",          }, +  { "STATEMENT",        "TK_STATEMENT",    }, +  { "TABLE",            "TK_TABLE",        }, +  { "TEMP",             "TK_TEMP",         }, +  { "TEMPORARY",        "TK_TEMP",         }, +  { "THEN",             "TK_THEN",         }, +  { "TRANSACTION",      "TK_TRANSACTION",  }, +  { "TRIGGER",          "TK_TRIGGER",      }, +  { "UNION",            "TK_UNION",        }, +  { "UNIQUE",           "TK_UNIQUE",       }, +  { "UPDATE",           "TK_UPDATE",       }, +  { "USING",            "TK_USING",        }, +  { "VACUUM",           "TK_VACUUM",       }, +  { "VALUES",           "TK_VALUES",       }, +  { "VIEW",             "TK_VIEW",         }, +  { "WHEN",             "TK_WHEN",         }, +  { "WHERE",            "TK_WHERE",        }, +}; + +/* Number of keywords */ +#define NKEYWORD (sizeof(aKeywordTable)/sizeof(aKeywordTable[0])) + +/* An array to map all upper-case characters into their corresponding +** lower-case character.  +*/ +const unsigned char sqlite3UpperToLower[] = { +      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, +     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, +    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, +    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, +    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, +    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, +    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, +    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, +    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, +    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, +    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, +    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, +    252,253,254,255 +}; +#define UpperToLower sqlite3UpperToLower + +/* +** Comparision function for two Keyword records +*/ +static int keywordCompare(const void *a, const void *b){ +  const Keyword *pA = (Keyword*)a; +  const Keyword *pB = (Keyword*)b; +  return strcmp(pA->zName, pB->zName); +} + +/* +** This routine does the work.  The generated code is printed on standard +** output. +*/ +int main(int argc, char **argv){ +  int i, j, h; +  int bestSize, bestCount; +  int count; +  int nChar; +  int aHash[1000];  /* 1000 is much bigger than NKEYWORD */ + +  /* Make sure the table is sorted */ +  qsort(aKeywordTable, NKEYWORD, sizeof(aKeywordTable[0]), keywordCompare); + +  /* Fill in the hash value, length, and offset for all entries */ +  nChar = 0; +  for(i=0; i<NKEYWORD; i++){ +    Keyword *p = &aKeywordTable[i]; +    p->len = strlen(p->zName); +    /* p->hash = sqlite3HashNoCase(p->zName, p->len); */ +    p->hash = UpperToLower[p->zName[0]]*5 + +              UpperToLower[p->zName[p->len-1]]*3 + p->len; +    p->offset = nChar; +    if( i<NKEYWORD-1 && strncmp(p->zName, aKeywordTable[i+1].zName,p->len)==0 ){ +      /* This entry is a prefix of the one that follows.  Do not advance +      ** the offset */ +    }else{ +      nChar += p->len; +    } +  } + +  /* Figure out how big to make the hash table in order to minimize the +  ** number of collisions */ +  bestSize = NKEYWORD; +  bestCount = NKEYWORD*NKEYWORD; +  for(i=NKEYWORD/2; i<=2*NKEYWORD; i++){ +    for(j=0; j<i; j++) aHash[j] = 0; +    for(j=0; j<NKEYWORD; j++){ +      h = aKeywordTable[j].hash % i; +      aHash[h] *= 2; +      aHash[h]++; +    } +    for(j=count=0; j<i; j++) count += aHash[j]; +    if( count<bestCount ){ +      bestCount = count; +      bestSize = i; +    } +  } + +  /* Compute the hash */ +  for(i=0; i<bestSize; i++) aHash[i] = 0; +  for(i=0; i<NKEYWORD; i++){ +    h = aKeywordTable[i].hash % bestSize; +    aKeywordTable[i].iNext = aHash[h]; +    aHash[h] = i+1; +  } + +  /* Begin generating code */ +  printf("int sqlite3KeywordCode(const char *z, int n){\n"); + +  printf("  static const char zText[%d] =\n", nChar+1); +  for(i=j=0; i<NKEYWORD; i++){ +    Keyword *p = &aKeywordTable[i]; +    if( i<NKEYWORD-1 && p->offset==aKeywordTable[i+1].offset ) continue; +    if( j==0 ) printf("    \""); +    printf("%s", p->zName); +    j += p->len; +    if( j>60 ){ +      printf("\"\n"); +      j = 0; +    } +  } +  printf("%s;\n", j>0 ? "\"" : "  "); + +  printf("  static const unsigned char aHash[%d] = {\n", bestSize); +  for(i=j=0; i<bestSize; i++){ +    if( j==0 ) printf("    "); +    printf(" %3d,", aHash[i]); +    j++; +    if( j>12 ){ +      printf("\n"); +      j = 0; +    } +  } +  printf("%s  };\n", j==0 ? "" : "\n");     + +  printf("  static const unsigned char aNext[%d] = {\n", NKEYWORD); +  for(i=j=0; i<NKEYWORD; i++){ +    if( j==0 ) printf("    "); +    printf(" %3d,", aKeywordTable[i].iNext); +    j++; +    if( j>12 ){ +      printf("\n"); +      j = 0; +    } +  } +  printf("%s  };\n", j==0 ? "" : "\n");     + +  printf("  static const unsigned char aLen[%d] = {\n", NKEYWORD); +  for(i=j=0; i<NKEYWORD; i++){ +    if( j==0 ) printf("    "); +    printf(" %3d,", aKeywordTable[i].len); +    j++; +    if( j>12 ){ +      printf("\n"); +      j = 0; +    } +  } +  printf("%s  };\n", j==0 ? "" : "\n");     + +  printf("  static const unsigned short int aOffset[%d] = {\n", NKEYWORD); +  for(i=j=0; i<NKEYWORD; i++){ +    if( j==0 ) printf("    "); +    printf(" %3d,", aKeywordTable[i].offset); +    j++; +    if( j>12 ){ +      printf("\n"); +      j = 0; +    } +  } +  printf("%s  };\n", j==0 ? "" : "\n"); + +  printf("  static const unsigned char aCode[%d] = {\n", NKEYWORD); +  for(i=j=0; i<NKEYWORD; i++){ +    char *zToken = aKeywordTable[i].zTokenType; +    if( j==0 ) printf("    "); +    printf("%s,%*s", zToken, (int)(14-strlen(zToken)), ""); +    j++; +    if( j>=5 ){ +      printf("\n"); +      j = 0; +    } +  } +  printf("%s  };\n", j==0 ? "" : "\n"); + +  printf("  int h, i;\n"); +  printf("  if( n<2 ) return TK_ID;\n"); +  printf("  h = (sqlite3UpperToLower[((unsigned char*)z)[0]]*5 + \n" +         "      sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3 +\n" +         "      n) %% %d;\n", bestSize); +  printf("  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n"); +  printf("    if( aLen[i]==n &&" +                   " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n"); +  printf("      return aCode[i];\n"); +  printf("    }\n"); +  printf("  }\n"); +  printf("  return TK_ID;\n"); +  printf("}\n"); + +  return 0; +} diff --git a/ext/pdo_sqlite/sqlite/tool/mkopts.tcl b/ext/pdo_sqlite/sqlite/tool/mkopts.tcl new file mode 100755 index 0000000000..e3ddcb9eeb --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/mkopts.tcl @@ -0,0 +1,51 @@ +#!/usr/bin/tclsh +# +# This script is used to generate the array of strings and the enum +# that appear at the beginning of the C code implementation of a +# a TCL command and that define the available subcommands for that +# TCL command. + +set prefix {} +while {![eof stdin]} { +  set line [gets stdin] +  if {$line==""} continue +  regsub -all "\[ \t\n,\]+" [string trim $line] { } line +  foreach token [split $line { }] { +    if {![regexp {(([a-zA-Z]+)_)?([_a-zA-Z]+)} $token all px p2 name]} continue +    lappend namelist [string tolower $name] +    if {$px!=""} {set prefix $p2} +  } +} + +puts "  static const char *${prefix}_strs\[\] = \173" +set col 0 +proc put_item x { +  global col +  if {$col==0} {puts -nonewline "   "} +  if {$col<2} { +    puts -nonewline [format " %-21s" $x] +    incr col +  } else { +    puts $x +    set col 0 +  } +} +proc finalize {} { +  global col +  if {$col>0} {puts {}} +  set col 0 +} + +foreach name [lsort $namelist] { +  put_item \"$name\", +} +put_item 0 +finalize +puts "  \175;" +puts "  enum ${prefix}_enum \173" +foreach name [lsort $namelist] { +  regsub -all {@} $name {} name +  put_item ${prefix}_[string toupper $name], +} +finalize +puts "  \175;" diff --git a/ext/pdo_sqlite/sqlite/tool/opcodeDoc.awk b/ext/pdo_sqlite/sqlite/tool/opcodeDoc.awk new file mode 100644 index 0000000000..492010624f --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/opcodeDoc.awk @@ -0,0 +1,23 @@ +# +# Extract opcode documentation for sqliteVdbe.c and generate HTML +# +BEGIN { +  print "<html><body bgcolor=white>" +  print "<h1>SQLite Virtual Database Engine Opcodes</h1>" +  print "<table>" +} +/ Opcode: /,/\*\// { +  if( $2=="Opcode:" ){ +    printf "<tr><td>%s %s %s %s</td>\n<td>\n", $3, $4, $5, $6 +  }else if( $1=="*/" ){ +    printf "</td></tr>\n" +  }else if( NF>1 ){ +    sub(/^ *\*\* /,"") +    gsub(/</,"<") +    gsub(/&/,"&") +    print +  } +} +END { +  print "</table></body></html>" +} diff --git a/ext/pdo_sqlite/sqlite/tool/report1.txt b/ext/pdo_sqlite/sqlite/tool/report1.txt new file mode 100644 index 0000000000..7820b8ccf6 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/report1.txt @@ -0,0 +1,66 @@ +The SQL database used for ACD contains 113 tables and indices implemented +in GDBM.  The following are statistics on the sizes of keys and data +within these tables and indices. + +Entries:      962080 +Size:         45573853 +Avg Size:     48 +Key Size:     11045299 +Avg Key Size: 12 +Max Key Size: 99 + + + Size of key              Cummulative +  and data     Instances  Percentage +------------  ----------  ----------- +    0..8            266    0% +    9..12          5485    0% +   13..16         73633    8% +   17..24        180918   27% +   25..32        209823   48% +   33..40        148995   64% +   41..48         76304   72% +   49..56         14346   73% +   57..64         15725   75% +   65..80         44916   80% +   81..96        127815   93% +   97..112        34769   96% +  113..128        13314   98% +  129..144         8098   99% +  145..160         3355   99% +  161..176         1159   99% +  177..192          629   99% +  193..208          221   99% +  209..224          210   99% +  225..240          129   99% +  241..256           57   99% +  257..288          496   99% +  289..320           60   99% +  321..352           37   99% +  353..384           46   99% +  385..416           22   99% +  417..448           24   99% +  449..480           26   99% +  481..512           27   99% +  513..1024         471   99% + 1025..2048         389   99% + 2049..4096         182   99% + 4097..8192          74   99% + 8193..16384         34   99% +16385..32768         17   99% +32769..65536          5   99% +65537..131073         3  100% + + +This information is gathered to help design the new built-in +backend for sqlite 2.0.  Note in particular that 99% of all +database entries have a combined key and data size of less than +144 bytes.  So if a leaf node in the new database is able to +store 144 bytes of combined key and data, only 1% of the leaves +will require overflow pages.  Furthermore, note that no key +is larger than 99 bytes, so if the key will never be on an +overflow page. + +The average combined size of key+data is 48.  Add in 16 bytes of +overhead for a total of 64.  That means that a 1K page will +store (on average) about 16 entries. diff --git a/ext/pdo_sqlite/sqlite/tool/showdb.c b/ext/pdo_sqlite/sqlite/tool/showdb.c new file mode 100644 index 0000000000..fe105c7bb2 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/showdb.c @@ -0,0 +1,85 @@ +/* +** A utility for printing all or part of an SQLite database file. +*/ +#include <stdio.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + + +static int pagesize = 1024; +static int db = -1; +static int mxPage = 0; + +static void out_of_memory(void){ +  fprintf(stderr,"Out of memory...\n"); +  exit(1); +} + +static print_page(int iPg){ +  unsigned char *aData; +  int i, j; +  aData = malloc(pagesize); +  if( aData==0 ) out_of_memory(); +  lseek(db, (iPg-1)*pagesize, SEEK_SET); +  read(db, aData, pagesize); +  fprintf(stdout, "Page %d:\n", iPg); +  for(i=0; i<pagesize; i += 16){ +    fprintf(stdout, " %03x: ",i); +    for(j=0; j<16; j++){ +      fprintf(stdout,"%02x ", aData[i+j]); +    } +    for(j=0; j<16; j++){ +      fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.'); +    } +    fprintf(stdout,"\n"); +  } +  free(aData); +} + +int main(int argc, char **argv){ +  struct stat sbuf; +  if( argc<2 ){ +    fprintf(stderr,"Usage: %s FILENAME ?PAGE? ...\n", argv[0]); +    exit(1); +  } +  db = open(argv[1], O_RDONLY); +  if( db<0 ){ +    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); +    exit(1); +  } +  fstat(db, &sbuf); +  mxPage = sbuf.st_size/pagesize + 1; +  if( argc==2 ){ +    int i; +    for(i=1; i<=mxPage; i++) print_page(i); +  }else{ +    int i; +    for(i=2; i<argc; i++){ +      int iStart, iEnd; +      char *zLeft; +      iStart = strtol(argv[i], &zLeft, 0); +      if( zLeft && strcmp(zLeft,"..end")==0 ){ +        iEnd = mxPage; +      }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){ +        iEnd = strtol(&zLeft[2], 0, 0); +      }else{ +        iEnd = iStart; +      } +      if( iStart<1 || iEnd<iStart || iEnd>mxPage ){ +        fprintf(stderr, +          "Page argument should be LOWER?..UPPER?.  Range 1 to %d\n", +          mxPage); +        exit(1); +      } +      while( iStart<=iEnd ){ +        print_page(iStart); +        iStart++; +      } +    } +  } +  close(db); +} diff --git a/ext/pdo_sqlite/sqlite/tool/showjournal.c b/ext/pdo_sqlite/sqlite/tool/showjournal.c new file mode 100644 index 0000000000..ec93c91905 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/showjournal.c @@ -0,0 +1,76 @@ +/* +** A utility for printing an SQLite database journal. +*/ +#include <stdio.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + + +static int pagesize = 1024; +static int db = -1; +static int mxPage = 0; + +static void out_of_memory(void){ +  fprintf(stderr,"Out of memory...\n"); +  exit(1); +} + +static print_page(int iPg){ +  unsigned char *aData; +  int i, j; +  aData = malloc(pagesize); +  if( aData==0 ) out_of_memory(); +  read(db, aData, pagesize); +  fprintf(stdout, "Page %d:\n", iPg); +  for(i=0; i<pagesize; i += 16){ +    fprintf(stdout, " %03x: ",i); +    for(j=0; j<16; j++){ +      fprintf(stdout,"%02x ", aData[i+j]); +    } +    for(j=0; j<16; j++){ +      fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.'); +    } +    fprintf(stdout,"\n"); +  } +  free(aData); +} + +int main(int argc, char **argv){ +  struct stat sbuf; +  unsigned int u; +  int rc; +  unsigned char zBuf[10]; +  unsigned char zBuf2[sizeof(u)]; +  if( argc!=2 ){ +    fprintf(stderr,"Usage: %s FILENAME\n", argv[0]); +    exit(1); +  } +  db = open(argv[1], O_RDONLY); +  if( db<0 ){ +    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); +    exit(1); +  } +  read(db, zBuf, 8); +  if( zBuf[7]==0xd6 ){ +    read(db, &u, sizeof(u)); +    printf("Records in Journal: %u\n", u); +    read(db, &u, sizeof(u)); +    printf("Magic Number: 0x%08x\n", u); +  } +  read(db, zBuf2, sizeof(zBuf2)); +  u = zBuf2[0]<<24 | zBuf2[1]<<16 | zBuf2[2]<<8 | zBuf2[3]; +  printf("Database Size: %u\n", u); +  while( read(db, zBuf2, sizeof(zBuf2))==sizeof(zBuf2) ){ +    u = zBuf2[0]<<24 | zBuf2[1]<<16 | zBuf2[2]<<8 | zBuf2[3]; +    print_page(u); +    if( zBuf[7]==0xd6 ){ +      read(db, &u, sizeof(u)); +      printf("Checksum: 0x%08x\n", u); +    } +  } +  close(db); +} diff --git a/ext/pdo_sqlite/sqlite/tool/space_used.tcl b/ext/pdo_sqlite/sqlite/tool/space_used.tcl new file mode 100644 index 0000000000..2044aa38c5 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/space_used.tcl @@ -0,0 +1,111 @@ +# Run this TCL script using "testfixture" in order get a report that shows +# how much disk space is used by a particular data to actually store data +# versus how much space is unused. +# + +# Get the name of the database to analyze +# +if {[llength $argv]!=1} { +  puts stderr "Usage: $argv0 database-name" +  exit 1 +} +set file_to_analyze [lindex $argv 0] + +# Open the database +# +sqlite db [lindex $argv 0] +set DB [btree_open [lindex $argv 0]] + +# Output the schema for the generated report +# +puts \ +{BEGIN; +CREATE TABLE space_used( +   name clob,        -- Name of a table or index in the database file +   is_index boolean, -- TRUE if it is an index, false for a table +   payload int,      -- Total amount of data stored in this table or index +   pri_pages int,    -- Number of primary pages used +   ovfl_pages int,   -- Number of overflow pages used +   pri_unused int,   -- Number of unused bytes on primary pages +   ovfl_unused int   -- Number of unused bytes on overflow pages +);} + +# This query will be used to find the root page number for every index and +# table in the database. +# +set sql { +  SELECT name, type, rootpage FROM sqlite_master +  UNION ALL +  SELECT 'sqlite_master', 'table', 2 +  ORDER BY 1 +} + +# Initialize variables used for summary statistics. +# +set total_size 0 +set total_primary 0 +set total_overflow 0 +set total_unused_primary 0 +set total_unused_ovfl 0 + +# Analyze every table in the database, one at a time. +# +foreach {name type rootpage} [db eval $sql] { +  set cursor [btree_cursor $DB $rootpage 0] +  set go [btree_first $cursor] +  set size 0 +  catch {unset pg_used} +  set unused_ovfl 0 +  set n_overflow 0 +  while {$go==0} { +    set payload [btree_payload_size $cursor] +    incr size $payload +    set stat [btree_cursor_dump $cursor] +    set pgno [lindex $stat 0] +    set freebytes [lindex $stat 4] +    set pg_used($pgno) $freebytes +    if {$payload>238} { +      set n [expr {($payload-238+1019)/1020}] +      incr n_overflow $n +      incr unused_ovfl [expr {$n*1020+238-$payload}] +    } +    set go [btree_next $cursor] +  } +  btree_close_cursor $cursor +  set n_primary [llength [array names pg_used]] +  set unused_primary 0 +  foreach x [array names pg_used] {incr unused_primary $pg_used($x)} +  regsub -all ' $name '' name +  puts -nonewline "INSERT INTO space_used VALUES('$name'" +  puts -nonewline ",[expr {$type=="index"}]" +  puts ",$size,$n_primary,$n_overflow,$unused_primary,$unused_ovfl);" +  incr total_size $size +  incr total_primary $n_primary +  incr total_overflow $n_overflow +  incr total_unused_primary $unused_primary +  incr total_unused_ovfl $unused_ovfl +} + +# Output summary statistics: +# +puts "-- Total payload size: $total_size" +puts "-- Total pages used: $total_primary primary and $total_overflow overflow" +set file_pgcnt [expr {[file size [lindex $argv 0]]/1024}] +puts -nonewline "-- Total unused bytes on primary pages: $total_unused_primary" +if {$total_primary>0} { +  set upp [expr {$total_unused_primary/$total_primary}] +  puts " (avg $upp bytes/page)" +} else { +  puts "" +} +puts -nonewline "-- Total unused bytes on overflow pages: $total_unused_ovfl" +if {$total_overflow>0} { +  set upp [expr {$total_unused_ovfl/$total_overflow}] +  puts " (avg $upp bytes/page)" +} else { +  puts "" +} +set n_free [expr {$file_pgcnt-$total_primary-$total_overflow}] +if {$n_free>0} {incr n_free -1} +puts "-- Total pages on freelist: $n_free" +puts "COMMIT;" diff --git a/ext/pdo_sqlite/sqlite/tool/spaceanal.tcl b/ext/pdo_sqlite/sqlite/tool/spaceanal.tcl new file mode 100644 index 0000000000..e42fb28de4 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/spaceanal.tcl @@ -0,0 +1,559 @@ +# Run this TCL script using "testfixture" in order get a report that shows +# how much disk space is used by a particular data to actually store data +# versus how much space is unused. +# + +# Get the name of the database to analyze +# +set argv $argv0 +if {[llength $argv]!=1} { +  puts stderr "Usage: $argv0 database-name" +  exit 1 +} +set file_to_analyze [lindex $argv 0] +if {![file exists $file_to_analyze]} { +  puts stderr "No such file: $file_to_analyze" +  exit 1 +} +if {![file readable $file_to_analyze]} { +  puts stderr "File is not readable: $file_to_analyze" +  exit 1 +} +if {[file size $file_to_analyze]<512} { +  puts stderr "Empty or malformed database: $file_to_analyze" +  exit 1 +} + +# Open the database +# +sqlite3 db [lindex $argv 0] +set DB [btree_open [lindex $argv 0] 1000 0] + +# In-memory database for collecting statistics +# +sqlite3 mem :memory: +set tabledef\ +{CREATE TABLE space_used( +   name clob,        -- Name of a table or index in the database file +   tblname clob,     -- Name of associated table +   is_index boolean, -- TRUE if it is an index, false for a table +   nentry int,       -- Number of entries in the BTree +   leaf_entries int, -- Number of leaf entries +   payload int,      -- Total amount of data stored in this table or index +   ovfl_payload int, -- Total amount of data stored on overflow pages +   ovfl_cnt int,     -- Number of entries that use overflow +   mx_payload int,   -- Maximum payload size +   int_pages int,    -- Number of interior pages used +   leaf_pages int,   -- Number of leaf pages used +   ovfl_pages int,   -- Number of overflow pages used +   int_unused int,   -- Number of unused bytes on interior pages +   leaf_unused int,  -- Number of unused bytes on primary pages +   ovfl_unused int   -- Number of unused bytes on overflow pages +);} +mem eval $tabledef + +# This query will be used to find the root page number for every table +# in the database. +# +set sql { +  SELECT name, rootpage  +    FROM sqlite_master WHERE type='table' +  UNION ALL +  SELECT 'sqlite_master', 1 +  ORDER BY 1 +} + +# Quote a string for SQL +# +proc quote txt { +  regsub -all ' $txt '' q +  return '$q' +} + +# Analyze every table in the database, one at a time. +# +set pageSize [db eval {PRAGMA page_size}] +foreach {name rootpage} [db eval $sql] { +  puts stderr "Analyzing table $name..." +  set cursor [btree_cursor $DB $rootpage 0] +  set go [btree_first $cursor] +  catch {unset seen} +  set total_payload 0        ;# Payload space used by all entries +  set total_ovfl 0           ;# Payload space on overflow pages +  set unused_int 0           ;# Unused space on interior nodes +  set unused_leaf 0          ;# Unused space on leaf nodes +  set unused_ovfl 0          ;# Unused space on overflow pages +  set cnt_ovfl 0             ;# Number of entries that use overflows +  set cnt_leaf_entry 0       ;# Number of leaf entries +  set cnt_int_entry 0        ;# Number of interor entries +  set mx_payload 0           ;# Maximum payload size +  set ovfl_pages 0           ;# Number of overflow pages used +  set leaf_pages 0           ;# Number of leaf pages +  set int_pages 0            ;# Number of interior pages +  while {$go==0} { +    incr cnt_leaf_entry +    set stat [btree_cursor_info $cursor] +    set payload [lindex $stat 6] +    if {$payload>$mx_payload} {set mx_payload $payload} +    incr total_payload $payload +    set local [lindex $stat 8]     +    set ovfl [expr {$payload-$local}] +    if {$ovfl} { +      incr cnt_ovfl +      incr total_ovfl $ovfl +      set n [expr {int(ceil($ovfl/($pageSize-4.0)))}] +      incr ovfl_pages $n +      incr unused_ovfl [expr {$n*($pageSize-4) - $ovfl}] +    } +    set pgno [lindex $stat 0] +    if {![info exists seen($pgno)]} { +      set seen($pgno) 1 +      incr leaf_pages +      incr unused_leaf [lindex $stat 4] +      set parent [lindex $stat 9] +      set up 0 +      while {$parent!=0 && ![info exists seen($parent)]} { +        incr up +        set stat [btree_cursor_info $cursor $up] +        set seen($parent) 1 +        incr int_pages +        incr cnt_int_entry [lindex $stat 2] +        incr unused_int [lindex $stat 4] +        set parent [lindex $stat 9] +      } +    } +    set go [btree_next $cursor] +  } +  btree_close_cursor $cursor +  if {[llength [array names seen]]==0} { +    set leaf_pages 1 +    set unused_leaf [expr {$pageSize-8}] +  } elseif {$rootpage==1 && ![info exists seen(1)]} { +    incr int_pages +    incr unused_int [expr {$pageSize-112}] +  } +  set sql "INSERT INTO space_used VALUES(" +  append sql [quote $name] +  append sql ",[quote $name]" +  append sql ",0" +  append sql ",[expr {$cnt_leaf_entry+$cnt_int_entry}]" +  append sql ",$cnt_leaf_entry" +  append sql ",$total_payload" +  append sql ",$total_ovfl" +  append sql ",$cnt_ovfl" +  append sql ",$mx_payload" +  append sql ",$int_pages" +  append sql ",$leaf_pages" +  append sql ",$ovfl_pages" +  append sql ",$unused_int" +  append sql ",$unused_leaf" +  append sql ",$unused_ovfl" +  append sql ); +  mem eval $sql +} + +# This query will be used to find the root page number for every index +# in the database. +# +set sql { +  SELECT name, tbl_name, rootpage  +    FROM sqlite_master WHERE type='index' +  ORDER BY 2, 1 +} + +# Analyze every index in the database, one at a time. +# +set pageSize [db eval {PRAGMA page_size}] +foreach {name tbl_name rootpage} [db eval $sql] { +  puts stderr "Analyzing index $name of table $tbl_name..." +  set cursor [btree_cursor $DB $rootpage 0] +  set go [btree_first $cursor] +  catch {unset seen} +  set total_payload 0        ;# Payload space used by all entries +  set total_ovfl 0           ;# Payload space on overflow pages +  set unused_leaf 0          ;# Unused space on leaf nodes +  set unused_ovfl 0          ;# Unused space on overflow pages +  set cnt_ovfl 0             ;# Number of entries that use overflows +  set cnt_leaf_entry 0       ;# Number of leaf entries +  set mx_payload 0           ;# Maximum payload size +  set ovfl_pages 0           ;# Number of overflow pages used +  set leaf_pages 0           ;# Number of leaf pages +  while {$go==0} { +    incr cnt_leaf_entry +    set stat [btree_cursor_info $cursor] +    set payload [btree_keysize $cursor] +    if {$payload>$mx_payload} {set mx_payload $payload} +    incr total_payload $payload +    set local [lindex $stat 8]     +    set ovfl [expr {$payload-$local}] +    if {$ovfl} { +      incr cnt_ovfl +      incr total_ovfl $ovfl +      set n [expr {int(ceil($ovfl/($pageSize-4.0)))}] +      incr ovfl_pages $n +      incr unused_ovfl [expr {$n*($pageSize-4) - $ovfl}] +    } +    set pgno [lindex $stat 0] +    if {![info exists seen($pgno)]} { +      set seen($pgno) 1 +      incr leaf_pages +      incr unused_leaf [lindex $stat 4] +    } +    set go [btree_next $cursor] +  } +  btree_close_cursor $cursor +  if {[llength [array names seen]]==0} { +    set leaf_pages 1 +    set unused_leaf [expr {$pageSize-8}] +  } +  set sql "INSERT INTO space_used VALUES(" +  append sql [quote $name] +  append sql ",[quote $tbl_name]" +  append sql ",1" +  append sql ",$cnt_leaf_entry" +  append sql ",$cnt_leaf_entry" +  append sql ",$total_payload" +  append sql ",$total_ovfl" +  append sql ",$cnt_ovfl" +  append sql ",$mx_payload" +  append sql ",0" +  append sql ",$leaf_pages" +  append sql ",$ovfl_pages" +  append sql ",0" +  append sql ",$unused_leaf" +  append sql ",$unused_ovfl" +  append sql ); +  mem eval $sql +} + +# Generate a single line of output in the statistics section of the +# report. +# +proc statline {title value {extra {}}} { +  set len [string length $title] +  set dots [string range {......................................} $len end] +  set len [string length $value] +  set sp2 [string range {          } $len end] +  if {$extra ne ""} { +    set extra " $extra" +  } +  puts "$title$dots $value$sp2$extra" +} + +# Generate a formatted percentage value for $num/$denom +# +proc percent {num denom {of {}}} { +  if {$denom==0.0} {return ""} +  set v [expr {$num*100.0/$denom}] +  set of {} +  if {$v==1.0 || $v==0.0 || ($v>1.0 && $v<99.0)} { +    return [format {%5.1f%% %s} $v $of] +  } elseif {$v<0.1 || $v>99.9} { +    return [format {%7.3f%% %s} $v $of] +  } else { +    return [format {%6.2f%% %s} $v $of] +  } +} + +# Generate a subreport that covers some subset of the database. +# the $where clause determines which subset to analyze. +# +proc subreport {title where} { +  global pageSize +  set hit 0 +  mem eval " +    SELECT +      sum(nentry) AS nentry, +      sum(leaf_entries) AS nleaf, +      sum(payload) AS payload, +      sum(ovfl_payload) AS ovfl_payload, +      max(mx_payload) AS mx_payload, +      sum(ovfl_cnt) as ovfl_cnt, +      sum(leaf_pages) AS leaf_pages, +      sum(int_pages) AS int_pages, +      sum(ovfl_pages) AS ovfl_pages, +      sum(leaf_unused) AS leaf_unused, +      sum(int_unused) AS int_unused, +      sum(ovfl_unused) AS ovfl_unused +    FROM space_used WHERE $where" {} {set hit 1} +  if {!$hit} {return 0} +  puts "" +  set len [string length $title] +  incr len 5 +  set stars "***********************************" +  append stars $stars +  set stars [string range $stars $len end] +  puts "*** $title $stars" +  puts "" +  set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}] +  statline "Percentage of total database" [percent $total_pages $::file_pgcnt] +  statline "Number of entries" $nleaf +  set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}] +  set storage [expr {$total_pages*$pageSize}] +  statline "Bytes of storage consumed" $storage +  statline "Bytes of payload" $payload \ +       [percent $payload $storage {of storage consumed}] +  statline "Average payload per entry" [expr {$nleaf>0?$payload/$nleaf:0}] +  set avgunused [expr {$nleaf>0?$total_unused/$nleaf:0}] +  statline "Average unused bytes per entry" $avgunused +  set nint [expr {$nentry-$nleaf}] +  if {$int_pages>0} { +    statline "Average fanout" [format %.2f [expr {($nint+0.0)/$int_pages}]] +  } +  statline "Maximum payload per entry" $mx_payload +  statline "Entries that use overflow" $ovfl_cnt \ +        [percent $ovfl_cnt $nleaf {of all entries}] +  if {$int_pages>0} { +    statline "Index pages used" $int_pages +  } +  statline "Primary pages used" $leaf_pages +  statline "Overflow pages used" $ovfl_pages +  statline "Total pages used" $total_pages +  if {$int_unused>0} { +    statline "Unused bytes on index pages" $int_unused \ +         [percent $int_unused [expr {$int_pages*$pageSize}] {of index space}] +  } +  statline "Unused bytes on primary pages" $leaf_unused \ +     [percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}] +  statline "Unused bytes on overflow pages" $ovfl_unused \ +     [percent $ovfl_unused [expr {$ovfl_pages*$pageSize}] {of overflow space}] +  statline "Unused bytes on all pages" $total_unused \ +               [percent $total_unused $storage {of all space}] +  return 1 +} + +# Output summary statistics: +# +puts "/** Disk-Space Utilization Report For $file_to_analyze" +puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]" +puts "" +statline {Page size in bytes} $pageSize +set fsize [file size $file_to_analyze] +set file_pgcnt [expr {$fsize/$pageSize}] +set usedcnt [mem eval \ +              {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}] +set freecnt [expr {$file_pgcnt-$usedcnt}] +set freecnt2 [lindex [btree_get_meta $DB] 0] +statline {Pages in the whole file (measured)} $file_pgcnt +set file_pgcnt2 [expr {$usedcnt+$freecnt2}] +statline {Pages in the whole file (calculated)} $file_pgcnt2 +statline {Pages that store data} $usedcnt [percent $usedcnt $file_pgcnt] +statline {Pages on the freelist (per header)}\ +   $freecnt2 [percent $freecnt2 $file_pgcnt] +statline {Pages on the freelist (calculated)}\ +   $freecnt [percent $freecnt $file_pgcnt] + +set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}] +statline {Number of tables in the database} $ntable +set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}] +set autoindex [db eval {SELECT count(*) FROM sqlite_master +                        WHERE type='index' AND name LIKE '(% autoindex %)'}] +set manindex [expr {$nindex-$autoindex}] +statline {Number of indices} $nindex +statline {Number of named indices} $manindex +statline {Automatically generated indices} $autoindex +set total_payload [mem eval "SELECT sum(payload) FROM space_used"] +statline "Size of the file in bytes" $fsize +set user_payload [mem one {SELECT sum(payload) FROM space_used +     WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}] +statline "Bytes of user payload stored" $user_payload \ +    [percent $user_payload $fsize] + +# Output table rankings +# +puts "" +puts "*** Page counts for all tables with their indices ********************" +puts "" +mem eval {SELECT tblname, count(*) AS cnt,  +              sum(int_pages+leaf_pages+ovfl_pages) AS size +          FROM space_used GROUP BY tblname ORDER BY size DESC, tblname} {} { +  statline [string toupper $tblname] $size [percent $size $file_pgcnt] +} + +# Output subreports +# +if {$nindex>0} { +  subreport {All tables and indices} 1 +} +subreport {All tables} {NOT is_index} +if {$nindex>0} { +  subreport {All indices} {is_index} +} +foreach tbl [mem eval {SELECT name FROM space_used WHERE NOT is_index +                       ORDER BY name}] { +  regsub ' $tbl '' qn +  set name [string toupper $tbl] +  set n [mem eval "SELECT count(*) FROM space_used WHERE tblname='$qn'"] +  if {$n>1} { +    subreport "Table $name and all its indices" "tblname='$qn'" +    subreport "Table $name w/o any indices" "name='$qn'" +    subreport "Indices of table $name" "tblname='$qn' AND is_index" +  } else { +    subreport "Table $name" "name='$qn'" +  } +} + +# Output instructions on what the numbers above mean. +# +puts { +*** Definitions ****************************************************** + +Page size in bytes + +    The number of bytes in a single page of the database file.   +    Usually 1024. + +Number of pages in the whole file +} +puts \ +"    The number of $pageSize-byte pages that go into forming the complete +    database" +puts \ +{ +Pages that store data + +    The number of pages that store data, either as primary B*Tree pages or +    as overflow pages.  The number at the right is the data pages divided by +    the total number of pages in the file. + +Pages on the freelist + +    The number of pages that are not currently in use but are reserved for +    future use.  The percentage at the right is the number of freelist pages +    divided by the total number of pages in the file. + +Number of tables in the database + +    The number of tables in the database, including the SQLITE_MASTER table +    used to store schema information. + +Number of indices + +    The total number of indices in the database. + +Number of named indices + +    The number of indices created using an explicit CREATE INDEX statement. + +Automatically generated indices + +    The number of indices used to implement PRIMARY KEY or UNIQUE constraints +    on tables. + +Size of the file in bytes + +    The total amount of disk space used by the entire database files. + +Bytes of user payload stored + +    The total number of bytes of user payload stored in the database. The +    schema information in the SQLITE_MASTER table is not counted when +    computing this number.  The percentage at the right shows the payload +    divided by the total file size. + +Percentage of total database + +    The amount of the complete database file that is devoted to storing +    information described by this category. + +Number of entries + +    The total number of B-Tree key/value pairs stored under this category. + +Bytes of storage consumed + +    The total amount of disk space required to store all B-Tree entries +    under this category.  The is the total number of pages used times +    the pages size. + +Bytes of payload + +    The amount of payload stored under this category.  Payload is the data +    part of table entries and the key part of index entries.  The percentage +    at the right is the bytes of payload divided by the bytes of storage  +    consumed. + +Average payload per entry + +    The average amount of payload on each entry.  This is just the bytes of +    payload divided by the number of entries. + +Average unused bytes per entry + +    The average amount of free space remaining on all pages under this +    category on a per-entry basis.  This is the number of unused bytes on +    all pages divided by the number of entries. + +Maximum payload per entry + +    The largest payload size of any entry. + +Entries that use overflow + +    The number of entries that user one or more overflow pages. + +Total pages used + +    This is the number of pages used to hold all information in the current +    category.  This is the sum of index, primary, and overflow pages. + +Index pages used + +    This is the number of pages in a table B-tree that hold only key (rowid) +    information and no data. + +Primary pages used + +    This is the number of B-tree pages that hold both key and data. + +Overflow pages used + +    The total number of overflow pages used for this category. + +Unused bytes on index pages + +    The total number of bytes of unused space on all index pages.  The +    percentage at the right is the number of unused bytes divided by the +    total number of bytes on index pages. + +Unused bytes on primary pages + +    The total number of bytes of unused space on all primary pages.  The +    percentage at the right is the number of unused bytes divided by the +    total number of bytes on primary pages. + +Unused bytes on overflow pages + +    The total number of bytes of unused space on all overflow pages.  The +    percentage at the right is the number of unused bytes divided by the +    total number of bytes on overflow pages. + +Unused bytes on all pages + +    The total number of bytes of unused space on all primary and overflow  +    pages.  The percentage at the right is the number of unused bytes  +    divided by the total number of bytes. +} + +# Output the database +# +puts "**********************************************************************" +puts "The entire text of this report can be sourced into any SQL database" +puts "engine for further analysis.  All of the text above is an SQL comment." +puts "The data used to generate this report follows:" +puts "*/" +puts "BEGIN;" +puts $tabledef +unset -nocomplain x +mem eval {SELECT * FROM space_used} x { +  puts -nonewline "INSERT INTO space_used VALUES" +  set sep ( +  foreach col $x(*) { +    set v $x($col) +    if {$v=="" || ![string is double $v]} {set v [quote $v]} +    puts -nonewline $sep$v +    set sep , +  } +  puts ");" +} +puts "COMMIT;" diff --git a/ext/pdo_sqlite/sqlite/tool/speedtest.tcl b/ext/pdo_sqlite/sqlite/tool/speedtest.tcl new file mode 100644 index 0000000000..ef39dc5461 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/speedtest.tcl @@ -0,0 +1,275 @@ +#!/usr/bin/tclsh +# +# Run this script using TCLSH to do a speed comparison between +# various versions of SQLite and PostgreSQL and MySQL +# + +# Run a test +# +set cnt 1 +proc runtest {title} { +  global cnt +  set sqlfile test$cnt.sql +  puts "<h2>Test $cnt: $title</h2>" +  incr cnt +  set fd [open $sqlfile r] +  set sql [string trim [read $fd [file size $sqlfile]]] +  close $fd +  set sx [split $sql \n] +  set n [llength $sx] +  if {$n>8} { +    set sql {} +    for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n} +    append sql  "<i>... [expr {$n-6}] lines omitted</i><br>\n" +    for {set i [expr {$n-3}]} {$i<$n} {incr i} { +      append sql [lindex $sx $i]<br>\n +    } +  } else { +    regsub -all \n [string trim $sql] <br> sql +  } +  puts "<blockquote>" +  puts "$sql" +  puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>" +  set format {<tr><td>%s</td><td align="right">   %.3f</td></tr>} +  set delay 1000 +#  exec sync; after $delay; +#  set t [time "exec psql drh <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format PostgreSQL: $t] +  exec sync; after $delay; +  set t [time "exec mysql -f drh <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format MySQL: $t] +#  set t [time "exec ./sqlite232 s232.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.3.2:} $t] +#  set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.4 (cache=100):} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite248 s2k.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4.8:} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite248 sns.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4.8 (nosync):} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite2412 s2kb.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4.12:} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite2412 snsb.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4.12 (nosync):} $t] +#  set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.4 (test):} $t] +  puts "</table>" +} + +# Initialize the environment +# +expr srand(1) +catch {exec /bin/sh -c {rm -f s*.db}} +set fd [open clear.sql w] +puts $fd { +  drop table t1; +  drop table t2; +} +close $fd +catch {exec psql drh <clear.sql} +catch {exec mysql drh <clear.sql} +set fd [open 2kinit.sql w] +puts $fd { +  PRAGMA default_cache_size=2000; +  PRAGMA default_synchronous=on; +} +close $fd +exec ./sqlite248 s2k.db <2kinit.sql +exec ./sqlite2412 s2kb.db <2kinit.sql +set fd [open nosync-init.sql w] +puts $fd { +  PRAGMA default_cache_size=2000; +  PRAGMA default_synchronous=off; +} +close $fd +exec ./sqlite248 sns.db <nosync-init.sql +exec ./sqlite2412 snsb.db <nosync-init.sql +set ones {zero one two three four five six seven eight nine +          ten eleven twelve thirteen fourteen fifteen sixteen seventeen +          eighteen nineteen} +set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} +proc number_name {n} { +  if {$n>=1000} { +    set txt "[number_name [expr {$n/1000}]] thousand" +    set n [expr {$n%1000}] +  } else { +    set txt {} +  } +  if {$n>=100} { +    append txt " [lindex $::ones [expr {$n/100}]] hundred" +    set n [expr {$n%100}] +  } +  if {$n>=20} { +    append txt " [lindex $::tens [expr {$n/10}]]" +    set n [expr {$n%10}] +  } +  if {$n>0} { +    append txt " [lindex $::ones $n]" +  } +  set txt [string trim $txt] +  if {$txt==""} {set txt zero} +  return $txt +} + + + +set fd [open test$cnt.sql w] +puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));" +for {set i 1} {$i<=1000} {incr i} { +  set r [expr {int(rand()*100000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +close $fd +runtest {1000 INSERTs} + + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +puts $fd "CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + + +set fd [open test$cnt.sql w] +for {set i 0} {$i<100} {incr i} { +  set lwr [expr {$i*100}] +  set upr [expr {($i+10)*100}] +  puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" +} +close $fd +runtest {100 SELECTs without an index} + + + +set fd [open test$cnt.sql w] +for {set i 1} {$i<=100} {incr i} { +  puts $fd "SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%[number_name $i]%';" +} +close $fd +runtest {100 SELECTs on a string comparison} + + + +set fd [open test$cnt.sql w] +puts $fd {CREATE INDEX i2a ON t2(a);} +puts $fd {CREATE INDEX i2b ON t2(b);} +close $fd +runtest {Creating an index} + + + +set fd [open test$cnt.sql w] +for {set i 0} {$i<5000} {incr i} { +  set lwr [expr {$i*100}] +  set upr [expr {($i+1)*100}] +  puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" +} +close $fd +runtest {5000 SELECTs with an index} + + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 0} {$i<1000} {incr i} { +  set lwr [expr {$i*10}] +  set upr [expr {($i+1)*10}] +  puts $fd "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;" +} +puts $fd "COMMIT;" +close $fd +runtest {1000 UPDATEs without an index} + + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "UPDATE t2 SET b=$r WHERE a=$i;" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 UPDATEs with an index} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "UPDATE t2 SET c='[number_name $r]' WHERE a=$i;" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 text UPDATEs with an index} + + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +puts $fd "INSERT INTO t1 SELECT * FROM t2;" +puts $fd "INSERT INTO t2 SELECT * FROM t1;" +puts $fd "COMMIT;" +close $fd +runtest {INSERTs from a SELECT} + + + +set fd [open test$cnt.sql w] +puts $fd {DELETE FROM t2 WHERE c LIKE '%fifty%';} +close $fd +runtest {DELETE without an index} + + + +set fd [open test$cnt.sql w] +puts $fd {DELETE FROM t2 WHERE a>10 AND a<20000;} +close $fd +runtest {DELETE with an index} + + + +set fd [open test$cnt.sql w] +puts $fd {INSERT INTO t2 SELECT * FROM t1;} +close $fd +runtest {A big INSERT after a big DELETE} + + + +set fd [open test$cnt.sql w] +puts $fd {BEGIN;} +puts $fd {DELETE FROM t1;} +for {set i 1} {$i<=3000} {incr i} { +  set r [expr {int(rand()*100000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd {COMMIT;} +close $fd +runtest {A big DELETE followed by many small INSERTs} + + + +set fd [open test$cnt.sql w] +puts $fd {DROP TABLE t1;} +puts $fd {DROP TABLE t2;} +close $fd +runtest {DROP TABLE} diff --git a/ext/pdo_sqlite/sqlite/tool/speedtest2.tcl b/ext/pdo_sqlite/sqlite/tool/speedtest2.tcl new file mode 100644 index 0000000000..4fd632d4c7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/tool/speedtest2.tcl @@ -0,0 +1,207 @@ +#!/usr/bin/tclsh +# +# Run this script using TCLSH to do a speed comparison between +# various versions of SQLite and PostgreSQL and MySQL +# + +# Run a test +# +set cnt 1 +proc runtest {title} { +  global cnt +  set sqlfile test$cnt.sql +  puts "<h2>Test $cnt: $title</h2>" +  incr cnt +  set fd [open $sqlfile r] +  set sql [string trim [read $fd [file size $sqlfile]]] +  close $fd +  set sx [split $sql \n] +  set n [llength $sx] +  if {$n>8} { +    set sql {} +    for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n} +    append sql  "<i>... [expr {$n-6}] lines omitted</i><br>\n" +    for {set i [expr {$n-3}]} {$i<$n} {incr i} { +      append sql [lindex $sx $i]<br>\n +    } +  } else { +    regsub -all \n [string trim $sql] <br> sql +  } +  puts "<blockquote>" +  puts "$sql" +  puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>" +  set format {<tr><td>%s</td><td align="right">   %.3f</td></tr>} +  set delay 1000 +  exec sync; after $delay; +  set t [time "exec psql drh <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format PostgreSQL: $t] +  exec sync; after $delay; +  set t [time "exec mysql -f drh <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format MySQL: $t] +#  set t [time "exec ./sqlite232 s232.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.3.2:} $t] +#  set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.4 (cache=100):} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4:} $t] +  exec sync; after $delay; +  set t [time "exec ./sqlite240 sns.db <$sqlfile" 1] +  set t [expr {[lindex $t 0]/1000000.0}] +  puts [format $format {SQLite 2.4 (nosync):} $t] +#  set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1] +#  set t [expr {[lindex $t 0]/1000000.0}] +#  puts [format $format {SQLite 2.4 (test):} $t] +  puts "</table>" +} + +# Initialize the environment +# +expr srand(1) +catch {exec /bin/sh -c {rm -f s*.db}} +set fd [open clear.sql w] +puts $fd { +  drop table t1; +  drop table t2; +} +close $fd +catch {exec psql drh <clear.sql} +catch {exec mysql drh <clear.sql} +set fd [open 2kinit.sql w] +puts $fd { +  PRAGMA default_cache_size=2000; +  PRAGMA default_synchronous=on; +} +close $fd +exec ./sqlite240 s2k.db <2kinit.sql +exec ./sqlite-t1 st1.db <2kinit.sql +set fd [open nosync-init.sql w] +puts $fd { +  PRAGMA default_cache_size=2000; +  PRAGMA default_synchronous=off; +} +close $fd +exec ./sqlite240 sns.db <nosync-init.sql +set ones {zero one two three four five six seven eight nine +          ten eleven twelve thirteen fourteen fifteen sixteen seventeen +          eighteen nineteen} +set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} +proc number_name {n} { +  if {$n>=1000} { +    set txt "[number_name [expr {$n/1000}]] thousand" +    set n [expr {$n%1000}] +  } else { +    set txt {} +  } +  if {$n>=100} { +    append txt " [lindex $::ones [expr {$n/100}]] hundred" +    set n [expr {$n%100}] +  } +  if {$n>=20} { +    append txt " [lindex $::tens [expr {$n/10}]]" +    set n [expr {$n%10}] +  } +  if {$n>0} { +    append txt " [lindex $::ones $n]" +  } +  set txt [string trim $txt] +  if {$txt==""} {set txt zero} +  return $txt +} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + +set fd [open test$cnt.sql w] +puts $fd "DELETE FROM t1;" +close $fd +runtest {DELETE everything} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + +set fd [open test$cnt.sql w] +puts $fd "DELETE FROM t1;" +close $fd +runtest {DELETE everything} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + +set fd [open test$cnt.sql w] +puts $fd "DELETE FROM t1;" +close $fd +runtest {DELETE everything} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + +set fd [open test$cnt.sql w] +puts $fd "DELETE FROM t1;" +close $fd +runtest {DELETE everything} + + +set fd [open test$cnt.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { +  set r [expr {int(rand()*500000)}] +  puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} + + +set fd [open test$cnt.sql w] +puts $fd "DELETE FROM t1;" +close $fd +runtest {DELETE everything} + + +set fd [open test$cnt.sql w] +puts $fd {DROP TABLE t1;} +close $fd +runtest {DROP TABLE}  | 
