summaryrefslogtreecommitdiffstats
path: root/dev-php
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2019-09-01 00:00:32 +0200
committerSuren A. Chilingaryan <csa@suren.me>2019-09-01 00:00:32 +0200
commitca9627e70852f6b2e835660df870fe3ab405882d (patch)
tree0a008b1d5b16fa0679a195ed7b5662c7891f591c /dev-php
downloaddarklin4-ca9627e70852f6b2e835660df870fe3ab405882d.tar.gz
darklin4-ca9627e70852f6b2e835660df870fe3ab405882d.tar.bz2
darklin4-ca9627e70852f6b2e835660df870fe3ab405882d.tar.xz
darklin4-ca9627e70852f6b2e835660df870fe3ab405882d.zip
Initial import
Diffstat (limited to 'dev-php')
-rw-r--r--dev-php/pecl-rrd/Manifest2
-rw-r--r--dev-php/pecl-rrd/pecl-rrd-1.0.5.ebuild20
-rw-r--r--dev-php/pecl-sqlite/Manifest3
-rw-r--r--dev-php/pecl-sqlite/files/sqlite-svn.patch12200
-rw-r--r--dev-php/pecl-sqlite/pecl-sqlite-1.0.3.ebuild32
-rw-r--r--dev-php/pecl-stats/Manifest3
-rw-r--r--dev-php/pecl-stats/files/stats-php54.diff7930
-rw-r--r--dev-php/pecl-stats/pecl-stats-1.0.2.ebuild31
8 files changed, 20221 insertions, 0 deletions
diff --git a/dev-php/pecl-rrd/Manifest b/dev-php/pecl-rrd/Manifest
new file mode 100644
index 0000000..16e9f85
--- /dev/null
+++ b/dev-php/pecl-rrd/Manifest
@@ -0,0 +1,2 @@
+DIST rrd-1.0.5.tgz 18676 SHA256 f336a0a56963e0c6a34e335401483f84adde4c09fd6fbe8fe1a4c74596dc4eab SHA512 6e1b1d42e3cabb141052b10547f00b4c2de69518769aa661429cf59f424063ec68416a5f41f10cb4e8a9c079aa1dbc2743750db469acf35b0a37a146273f858b WHIRLPOOL 0b8727f42fcbec38b37d93291e37ab8b9660b111b627342b20de1e96ecd5fcc42073855fd4dca1aef247092054dc13193c01113ede8623e45afadebdaac9e22f
+EBUILD pecl-rrd-1.0.5.ebuild 446 SHA256 3bca2ef02ed73e12c2a34362642ff0d37aa81619d6be9e91c0415a545d8c979d SHA512 264072c47f5afabc33201b6d75220021343aa5f5e147b59415815cca56c1812aedd29b1dcbcae095db9da9398324d2227764d252555262a4bbbc25495fc287e1 WHIRLPOOL ff2940722af5dd69ccd4d4e5a11b0c4578eea1745c6f24c007a87ceb132c93525170dfa702c968e78bf3bc124b463602a9d2ec2432a11779a6f44a1afa1d2ab3
diff --git a/dev-php/pecl-rrd/pecl-rrd-1.0.5.ebuild b/dev-php/pecl-rrd/pecl-rrd-1.0.5.ebuild
new file mode 100644
index 0000000..270016d
--- /dev/null
+++ b/dev-php/pecl-rrd/pecl-rrd-1.0.5.ebuild
@@ -0,0 +1,20 @@
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-php/pecl-rrd/pecl-rrd-1.0.5.ebuild,v 1.1 2012/02/22 22:04:03 mabi Exp $
+
+EAPI=6
+
+USE_PHP="php5-6 php5-5 php5-4 php5-3"
+
+inherit php-ext-pecl-r3
+
+KEYWORDS="amd64 x86"
+
+DESCRIPTION="RRDtool bindings for PHP"
+LICENSE="BSD"
+
+SLOT="0"
+IUSE=""
+
+DEPEND=">=net-analyzer/rrdtool-1.4.5-r1"
+RDEPEND="${DEPEND}"
diff --git a/dev-php/pecl-sqlite/Manifest b/dev-php/pecl-sqlite/Manifest
new file mode 100644
index 0000000..5b8e91c
--- /dev/null
+++ b/dev-php/pecl-sqlite/Manifest
@@ -0,0 +1,3 @@
+AUX sqlite-svn.patch 374879 SHA256 385835716faffe78fec4366b2e82993d4be2f9fb869acc56da258d0e204e94e9 SHA512 6d6a8e0971235acf50a7d97bdc6342ce3bfe8cdcc66190c53d0449e2f50509af1ca7dc49d0e42bb6cd13bb7f65bc1a7c029a3d15855d373cc3ed07233f3c1f21 WHIRLPOOL db0809c740ec75a1766468cce0c3093a7c2c59ef32ce17bf7e6fd4513f08d78c1eefcff172caf5a72b3b365d53001a5235d07e7284785a022331758f334c540c
+DIST SQLite-1.0.3.tgz 371189 SHA256 19edf52557c75a764e021d60414fe4ce347cbdab55377d4aafbecb30785d79a5 SHA512 0f566c3f95364a9b76e7b87aa10536a31f852359edad6ae4d3a702299c5dabf892e2b6758cc1aa642f729ad1d5549732c21863562193a41b9772d3725de6c166 WHIRLPOOL b229882aafb45360cb62f51b6aa4a9f6b8ab30dcb8cf1c3dc41efa550e9fc4447cdc560eb4631959ffd2274eb2baefd5a6fa05a6e4ff0941671f0741de741d31
+EBUILD pecl-sqlite-1.0.3.ebuild 783 SHA256 253d2f7c45c1a6b169bd5d0dac137aff3748d8ae29c9b0a7f14ab5548646f1bb SHA512 75a2cf970366a89fbb0007a7d3c695fe8eeec107fe05644021a58087978cde42ec529e465358ebbd65661371ff404b3a3a84242783978b500f7511202405a324 WHIRLPOOL a42265f6273215f9cb227ec308414cbc22c78fd291f22dbf3c02191fa3254d8c3a5e81fa6cb58f3781bb3fa7ba556a8ed8ca8604a814d32efd94db0e2f52f726
diff --git a/dev-php/pecl-sqlite/files/sqlite-svn.patch b/dev-php/pecl-sqlite/files/sqlite-svn.patch
new file mode 100644
index 0000000..95b111b
--- /dev/null
+++ b/dev-php/pecl-sqlite/files/sqlite-svn.patch
@@ -0,0 +1,12200 @@
+diff -dPNur sqlite-1.0.3/CREDITS sqlite-svn/CREDITS
+--- sqlite-1.0.3/CREDITS 2004-04-29 22:58:31.000000000 +0000
++++ sqlite-svn/CREDITS 2012-10-09 13:36:42.760063980 +0000
+@@ -1,2 +1,2 @@
+-sqlite
++SQLite
+ Wez Furlong, Tal Peer, Marcus Boerger, Ilia Alshanetsky
+diff -dPNur sqlite-1.0.3/Makefile.frag sqlite-svn/Makefile.frag
+--- sqlite-1.0.3/Makefile.frag 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/Makefile.frag 2012-10-09 13:36:42.760063980 +0000
+@@ -0,0 +1,2 @@
++$(srcdir)/libsqlite/src/parse.c: $(srcdir)/libsqlite/src/parse.y
++ @$(LEMON) $(srcdir)/libsqlite/src/parse.y
+diff -dPNur sqlite-1.0.3/README sqlite-svn/README
+--- sqlite-1.0.3/README 2003-04-17 01:37:42.000000000 +0000
++++ sqlite-svn/README 2012-10-09 13:36:42.760063980 +0000
+@@ -1,4 +1,4 @@
+-This is an extension for the SQLite Embeddable SQL Database Engine.
++This is an extension for the SQLite 2 Embeddable SQL Database Engine.
+ http://www.sqlite.org/
+
+ SQLite is a C library that implements an embeddable SQL database engine.
+diff -dPNur sqlite-1.0.3/TODO sqlite-svn/TODO
+--- sqlite-1.0.3/TODO 2003-06-26 18:30:12.000000000 +0000
++++ sqlite-svn/TODO 2012-10-09 13:36:42.760063980 +0000
+@@ -1,3 +1,20 @@
++CURRENT
++--------------------------------------
++- Discuss the pdo_sqlite2 situation. Either split into two extensions,
++ or research/implement alternatives. Currently configure does not
++ implement this pdo driver. sqlite_*() should always exist/work
++
++- Update notes/changelog to reflect (or inform) users of php-src changes
++ since version 1.0.3
++
++- Clarify that this extension exists for BC reasons, and is barely maintained
++
++- Consider moving ext/sqlite bugs to the PECL bug tracker
++
++OLD
++--------------------------------------
++- Implement a PDO driver, called sqlite2
++
+ - Transparent binary encoding of return values from PHP callback functions.
+
+ - Add user-space callback for the authorizer function (this is potentially
+@@ -5,8 +22,6 @@
+
+ - Add user-space callback to handle busy databases.
+
+-- Test-suite
+-
+ o Test how robust we are when a user-space function is registered as
+ a callback for a persistent connection in script A, then script B is
+ called that doesn't register the callback but does make use of the
+@@ -14,9 +29,6 @@
+ --> Our test suite doesn't allow us to test persistent connections
+ at this time :/
+
+-- If building a ZTS build, -DTHREADSAFE while compiling libsqlite
+-
+-- If building a non-debug build, -DNDEBUG will disable the expensive
+- asserts in the inner loop. (and double performance)
++- Use later version of built-in library
+
+ vim:tw=78
+diff -dPNur sqlite-1.0.3/config.m4 sqlite-svn/config.m4
+--- sqlite-1.0.3/config.m4 2004-07-10 12:50:18.000000000 +0000
++++ sqlite-svn/config.m4 2012-10-09 13:36:42.760063980 +0000
+@@ -1,55 +1,96 @@
+-dnl $Id: config.m4,v 1.16.2.5 2004/07/10 12:50:18 wez Exp $
++dnl $Id: config.m4 291414 2009-11-29 06:13:22Z rasmus $
+ dnl config.m4 for extension sqlite
+ dnl vim:et:ts=2:sw=2
+
+ PHP_ARG_WITH(sqlite, for sqlite support,
+-[ --with-sqlite Include sqlite support])
++[ --without-sqlite=DIR Do not include sqlite support. DIR is the sqlite base
++ install directory [BUNDLED]], yes)
++
++PHP_ARG_ENABLE(sqlite-utf8, whether to enable UTF-8 support in sqlite (default: ISO-8859-1),
++[ --enable-sqlite-utf8 SQLite: Enable UTF-8 support for SQLite], no, no)
++
++
++
++dnl
++dnl PHP_PROG_LEMON
++dnl
++dnl Search for lemon binary and check its version
++dnl
++AC_DEFUN([PHP_PROG_LEMON],[
++ # we only support certain lemon versions
++ lemon_version_list="1.0"
++
++ AC_CHECK_PROG(LEMON, lemon, lemon)
++ if test "$LEMON"; then
++ AC_CACHE_CHECK([for lemon version], php_cv_lemon_version, [
++ lemon_version=`$LEMON -x 2>/dev/null | $SED -e 's/^.* //'`
++ php_cv_lemon_version=invalid
++ for lemon_check_version in $lemon_version_list; do
++ if test "$lemon_version" = "$lemon_check_version"; then
++ php_cv_lemon_version="$lemon_check_version (ok)"
++ fi
++ done
++ ])
++ else
++ lemon_version=none
++ fi
++ case $php_cv_lemon_version in
++ ""|invalid[)]
++ lemon_msg="lemon versions supported for regeneration of libsqlite parsers: $lemon_version_list (found: $lemon_version)."
++ AC_MSG_WARN([$lemon_msg])
++ LEMON="exit 0;"
++ ;;
++ esac
++ PHP_SUBST(LEMON)
++])
++
+
+ if test "$PHP_SQLITE" != "no"; then
++ if test "$PHP_PDO" != "no"; then
++ PHP_CHECK_PDO_INCLUDES([], [AC_MSG_WARN([Cannot find php_pdo_driver.h.])])
++ if test -n "$pdo_inc_path"; then
++ AC_DEFINE([PHP_SQLITE2_HAVE_PDO], [1], [Have PDO])
++ pdo_inc_path="-I$pdo_inc_path"
++ fi
++ fi
+
+ if test "$PHP_SQLITE" != "yes"; then
+ SEARCH_PATH="/usr/local /usr"
+ SEARCH_FOR="/include/sqlite.h"
+ if test -r $PHP_SQLITE/; then # path given as parameter
+- SQLITE_DIR=$PHP_SQLITE
++ SQLITE_DIR=$PHP_SQLITE
+ else # search default path list
+- AC_MSG_CHECKING([for sqlite files in default path])
+- for i in $SEARCH_PATH ; do
++ AC_MSG_CHECKING([for sqlite files in default path])
++ for i in $SEARCH_PATH ; do
+ if test -r $i/$SEARCH_FOR; then
+- SQLITE_DIR=$i
+- AC_MSG_RESULT(found in $i)
++ SQLITE_DIR=$i
++ AC_MSG_RESULT(found in $i)
+ fi
+- done
++ done
+ fi
+
+ if test -z "$SQLITE_DIR"; then
+- AC_MSG_RESULT([not found])
+- AC_MSG_ERROR([Please reinstall the sqlite distribution from http://www.sqlite.org])
++ AC_MSG_RESULT([not found])
++ AC_MSG_ERROR([Please reinstall the sqlite distribution from http://www.sqlite.org])
+ fi
+
+- PHP_ADD_INCLUDE($SQLITE_DIR/include)
+-
+- LIBNAME=sqlite
+- LIBSYMBOL=sqlite_open
+-
+- PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+- [
+- PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SQLITE_DIR/lib, SQLITE_SHARED_LIBADD)
+- AC_DEFINE(HAVE_SQLITELIB,1,[ ])
++ PHP_CHECK_LIBRARY(sqlite, sqlite_open, [
++ PHP_ADD_LIBRARY_WITH_PATH(sqlite, $SQLITE_DIR/$PHP_LIBDIR, SQLITE_SHARED_LIBADD)
++ PHP_ADD_INCLUDE($SQLITE_DIR/include)
+ ],[
+- AC_MSG_ERROR([wrong sqlite lib version or lib not found])
++ AC_MSG_ERROR([wrong sqlite lib version or lib not found])
+ ],[
+- -L$SQLITE_DIR/lib -lm
++ -L$SQLITE_DIR/$PHP_LIBDIR -lm
+ ])
+-
+- PHP_SUBST(SQLITE_SHARED_LIBADD)
+- PHP_NEW_EXTENSION(sqlite, sqlite.c libsqlite/src/encode.c, $ext_shared)
++ SQLITE_MODULE_TYPE=external
++ PHP_SQLITE_CFLAGS=$pdo_inc_path
++ sqlite_extra_sources="libsqlite/src/encode.c"
+ else
+ # use bundled library
+-
+- PHP_SQLITE_CFLAGS="-I@ext_srcdir@/libsqlite/src"
+-
+- sources="libsqlite/src/opcodes.c
++ PHP_PROG_LEMON
++ SQLITE_MODULE_TYPE=builtin
++ PHP_SQLITE_CFLAGS="-I@ext_srcdir@/libsqlite/src -I@ext_builddir@/libsqlite/src $pdo_inc_path"
++ sqlite_extra_sources="libsqlite/src/opcodes.c \
+ libsqlite/src/parse.c libsqlite/src/encode.c \
+ libsqlite/src/auth.c libsqlite/src/btree.c libsqlite/src/build.c \
+ libsqlite/src/delete.c libsqlite/src/expr.c libsqlite/src/func.c \
+@@ -62,35 +103,46 @@
+ libsqlite/src/vacuum.c libsqlite/src/copy.c \
+ libsqlite/src/vdbeaux.c libsqlite/src/date.c \
+ libsqlite/src/where.c libsqlite/src/trigger.c"
+-
+- PHP_NEW_EXTENSION(sqlite, sqlite.c $sources, $ext_shared,,$PHP_SQLITE_CFLAGS)
+- PHP_ADD_BUILD_DIR($ext_builddir/libsqlite)
+- PHP_ADD_BUILD_DIR($ext_builddir/libsqlite/src)
+- AC_CHECK_SIZEOF(char *,4)
++ fi
++ dnl
++ dnl Common for both bundled/external
++ dnl
++ sqlite_sources="sqlite.c sess_sqlite.c pdo_sqlite2.c $sqlite_extra_sources"
++ PHP_NEW_EXTENSION(sqlite, $sqlite_sources, $ext_shared,,$PHP_SQLITE_CFLAGS)
++ PHP_ADD_EXTENSION_DEP(sqlite, spl, true)
++ PHP_ADD_EXTENSION_DEP(sqlite, pdo, true)
++
++ PHP_ADD_MAKEFILE_FRAGMENT
++ PHP_SUBST(SQLITE_SHARED_LIBADD)
++ PHP_INSTALL_HEADERS([$ext_builddir/libsqlite/src/sqlite.h])
++
++ if test "$SQLITE_MODULE_TYPE" = "builtin"; then
++ PHP_ADD_BUILD_DIR($ext_builddir/libsqlite/src, 1)
++ AC_CHECK_SIZEOF(char *, 4)
+ AC_DEFINE(SQLITE_PTR_SZ, SIZEOF_CHAR_P, [Size of a pointer])
+ dnl use latin 1 for SQLite older than 2.8.9; the utf-8 handling
+ dnl in funcs.c uses assert(), which is a bit silly and something
+ dnl we want to avoid. This assert() was removed in SQLite 2.8.9.
+ if test "$PHP_SQLITE_UTF8" = "yes"; then
+- SQLITE_ENCODING="UTF8"
+- AC_DEFINE(SQLITE_UTF8, 1, [ ])
++ SQLITE_ENCODING="UTF8"
++ AC_DEFINE(SQLITE_UTF8, 1, [ ])
+ else
+- SQLITE_ENCODING="ISO8859"
++ SQLITE_ENCODING="ISO8859"
+ fi
+ PHP_SUBST(SQLITE_ENCODING)
+
+ SQLITE_VERSION=`cat $ext_srcdir/libsqlite/VERSION`
+ PHP_SUBST(SQLITE_VERSION)
+-
+- sed -e s/--VERS--/$SQLITE_VERSION/ -e s/--ENCODING--/$SQLITE_ENCODING/ $ext_srcdir/libsqlite/src/sqlite.h.in >$ext_srcdir/libsqlite/src/sqlite.h
+
+- if test "$ext_shared" = "no"; then
+- echo '#include "php_config.h"' > $ext_srcdir/libsqlite/src/config.h
++ sed -e s/--VERS--/$SQLITE_VERSION/ -e s/--ENCODING--/$SQLITE_ENCODING/ $ext_srcdir/libsqlite/src/sqlite.h.in > $ext_builddir/libsqlite/src/sqlite.h
++
++ if test "$ext_shared" = "no" || test "$ext_srcdir" != "$abs_srcdir"; then
++ echo '#include <php_config.h>' > $ext_builddir/libsqlite/src/config.h
+ else
+- echo "#include \"$abs_builddir/config.h\"" > $ext_srcdir/libsqlite/src/config.h
++ echo "#include \"$abs_builddir/config.h\"" > $ext_builddir/libsqlite/src/config.h
+ fi
+
+- cat >> $ext_srcdir/libsqlite/src/config.h <<EOF
++ cat >> $ext_builddir/libsqlite/src/config.h <<EOF
+ #if ZTS
+ # define THREADSAFE 1
+ #endif
+@@ -98,9 +150,8 @@
+ # define NDEBUG
+ #endif
+ EOF
+-
+ fi
+-
++
+ AC_CHECK_FUNCS(usleep nanosleep)
+ AC_CHECK_HEADERS(time.h)
+ fi
+diff -dPNur sqlite-1.0.3/config.w32 sqlite-svn/config.w32
+--- sqlite-1.0.3/config.w32 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/config.w32 2012-10-09 13:36:42.760063980 +0000
+@@ -0,0 +1,39 @@
++// $Id: config.w32 242949 2007-09-26 15:44:16Z cvs2svn $
++// vim:ft=javascript
++
++ARG_WITH("sqlite", "SQLite support", "no");
++
++if (PHP_SQLITE != "no") {
++ copy_and_subst(configure_module_dirname + "\\libsqlite\\src\\sqlite.h.in",
++ configure_module_dirname + "\\libsqlite\\src\\sqlite.h", new Array(
++ "--VERS--", file_get_contents(configure_module_dirname + "\\libsqlite\\VERSION").replace(new RegExp("[\r\n]+", "g"), ""),
++ "--ENCODING--", "ISO8859"
++ ));
++
++ FSO.CopyFile(configure_module_dirname + "\\libsqlite\\src\\sqlite_config.w32.h",
++ configure_module_dirname + "\\libsqlite\\src\\config.h");
++
++ if (FSO.FileExists(configure_module_dirname + "\\..\\pdo\\php_pdo_driver.h")) {
++ PHP_SQLITE2_PDO_CFLAGS = " /DPHP_SQLITE2_HAVE_PDO=1 /I " + configure_module_dirname + "\\..";
++ ADD_EXTENSION_DEP('sqlite', 'pdo')
++ } else {
++ PHP_SQLITE2_PDO_CFLAGS = "";
++ }
++
++ EXTENSION("sqlite", "sqlite.c sess_sqlite.c pdo_sqlite2.c", null,
++ "/D PHP_SQLITE_EXPORTS /I " + configure_module_dirname + "/libsqlite/src" +
++ PHP_SQLITE2_PDO_CFLAGS);
++
++
++ ADD_SOURCES(configure_module_dirname + "/libsqlite/src", "opcodes.c parse.c encode.c \
++ auth.c btree.c build.c delete.c expr.c func.c hash.c insert.c \
++ main.c os.c pager.c printf.c random.c select.c table.c tokenize.c \
++ update.c util.c vdbe.c attach.c btree_rb.c pragma.c vacuum.c \
++ copy.c where.c trigger.c vdbeaux.c date.c", "sqlite");
++
++ AC_DEFINE("HAVE_SQLITE", 1, "SQLite support");
++ if (!PHP_SQLITE_SHARED) {
++ ADD_DEF_FILE(configure_module_dirname + "\\php_sqlite.def");
++ }
++ ADD_EXTENSION_DEP('sqlite', 'spl')
++}
+diff -dPNur sqlite-1.0.3/libsqlite/VERSION sqlite-svn/libsqlite/VERSION
+--- sqlite-1.0.3/libsqlite/VERSION 2004-07-10 11:43:20.000000000 +0000
++++ sqlite-svn/libsqlite/VERSION 2012-10-09 13:36:42.661358144 +0000
+@@ -1 +1 @@
+-2.8.14
++2.8.17
+diff -dPNur sqlite-1.0.3/libsqlite/src/attach.c sqlite-svn/libsqlite/src/attach.c
+--- sqlite-1.0.3/libsqlite/src/attach.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/attach.c 2012-10-09 13:36:42.531952680 +0000
+@@ -11,7 +11,7 @@
+ *************************************************************************
+ ** This file contains code used to implement the ATTACH and DETACH commands.
+ **
+-** $Id: attach.c,v 1.2.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: attach.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/auth.c sqlite-svn/libsqlite/src/auth.c
+--- sqlite-1.0.3/libsqlite/src/auth.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/auth.c 2012-10-09 13:36:42.541252205 +0000
+@@ -14,7 +14,7 @@
+ ** systems that do not need this facility may omit it by recompiling
+ ** the library with -DSQLITE_OMIT_AUTHORIZATION=1
+ **
+-** $Id: auth.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: auth.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+@@ -111,6 +111,7 @@
+ 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 );
+@@ -119,15 +120,14 @@
+ }
+ if( iSrc>=0 && iSrc<pTabList->nSrc ){
+ pTab = pTabList->a[iSrc].pTab;
+- }else{
++ }else if( (pStack = pParse->trigStack)!=0 ){
+ /* This must be an attempt to read the NEW or OLD pseudo-tables
+ ** of a trigger.
+ */
+- TriggerStack *pStack; /* The stack of current triggers */
+- pStack = pParse->trigStack;
+- assert( pStack!=0 );
+ assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
+ pTab = pStack->pTab;
++ }else{
++ return;
+ }
+ if( pTab==0 ) return;
+ if( pExpr->iColumn>=0 ){
+diff -dPNur sqlite-1.0.3/libsqlite/src/btree.c sqlite-svn/libsqlite/src/btree.c
+--- sqlite-1.0.3/libsqlite/src/btree.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/btree.c 2012-10-09 13:36:42.531952680 +0000
+@@ -9,7 +9,7 @@
+ ** May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** $Id: btree.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: btree.c 195361 2005-09-07 15:11:33Z iliaa $
+ **
+ ** This file implements a external (disk-based) database using BTrees.
+ ** For a detailed discussion of BTrees, refer to
+diff -dPNur sqlite-1.0.3/libsqlite/src/btree.h sqlite-svn/libsqlite/src/btree.h
+--- sqlite-1.0.3/libsqlite/src/btree.h 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/btree.h 2012-10-09 13:36:42.531952680 +0000
+@@ -13,7 +13,7 @@
+ ** subsystem. See comments in the source code for a detailed description
+ ** of what each interface routine does.
+ **
+-** @(#) $Id: btree.h,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: btree.h 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #ifndef _BTREE_H_
+ #define _BTREE_H_
+diff -dPNur sqlite-1.0.3/libsqlite/src/btree_rb.c sqlite-svn/libsqlite/src/btree_rb.c
+--- sqlite-1.0.3/libsqlite/src/btree_rb.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/btree_rb.c 2012-10-09 13:36:42.551252050 +0000
+@@ -9,7 +9,7 @@
+ ** May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** $Id: btree_rb.c,v 1.2.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: btree_rb.c 195361 2005-09-07 15:11:33Z iliaa $
+ **
+ ** This file implements an in-core database using Red-Black balanced
+ ** binary trees.
+@@ -259,17 +259,16 @@
+ * concatenation of orig and val is returned. The original orig is deleted
+ * (using sqliteFree()).
+ */
+-static char *append_val(char * orig, char const * val)
+-{
++static char *append_val(char * orig, char const * val){
++ char *z;
+ if( !orig ){
+- return sqliteStrDup( val );
++ z = sqliteStrDup( val );
+ } else{
+- char * ret = 0;
+- sqliteSetString(&ret, orig, val, (char*)0);
++ z = 0;
++ sqliteSetString(&z, orig, val, (char*)0);
+ sqliteFree( orig );
+- return ret;
+ }
+- assert(0);
++ return z;
+ }
+
+ /*
+@@ -723,13 +722,13 @@
+ pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
+ if( sqlite_malloc_failed ) return SQLITE_NOMEM;
+ pCur->pTree = sqliteHashFind(&tree->tblHash, 0, iTable);
++ assert( pCur->pTree );
+ pCur->pRbtree = tree;
+ pCur->iTree = iTable;
+ pCur->pOps = &sqliteRbtreeCursorOps;
+ pCur->wrFlag = wrFlag;
+ pCur->pShared = pCur->pTree->pCursors;
+ pCur->pTree->pCursors = pCur;
+-
+
+ assert( (*ppCur)->pTree );
+ return SQLITE_OK;
+@@ -1178,12 +1177,11 @@
+ if( !pCur->pNode ) return 0;
+ if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
+ memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
+- return amt;
+ }else{
+ memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
+- return pCur->pNode->nKey-offset;
++ amt = pCur->pNode->nKey-offset;
+ }
+- assert(0);
++ return amt;
+ }
+
+ static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
+@@ -1201,12 +1199,11 @@
+ if( !pCur->pNode ) return 0;
+ if( (amt + offset) <= pCur->pNode->nData ){
+ memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
+- return amt;
+ }else{
+ memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
+- return pCur->pNode->nData-offset;
++ amt = pCur->pNode->nData-offset;
+ }
+- assert(0);
++ return amt;
+ }
+
+ static int memRbtreeCloseCursor(RbtCursor* pCur)
+@@ -1421,13 +1418,12 @@
+ assert(!"Cannot call sqliteRbtreeCursorDump");
+ return SQLITE_OK;
+ }
++#endif
+
+ static struct Pager *memRbtreePager(Rbtree* tree)
+ {
+- assert(!"Cannot call sqliteRbtreePager");
+- return SQLITE_OK;
++ return 0;
+ }
+-#endif
+
+ /*
+ ** Return the full pathname of the underlying database file.
+@@ -1463,10 +1459,9 @@
+ (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
+ (const char*(*)(Btree*)) memRbtreeGetFilename,
+ (int(*)(Btree*,Btree*)) memRbtreeCopyFile,
+-
++ (struct Pager*(*)(Btree*)) memRbtreePager,
+ #ifdef SQLITE_TEST
+ (int(*)(Btree*,int,int)) memRbtreePageDump,
+- (struct Pager*(*)(Btree*)) memRbtreePager
+ #endif
+ };
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/build.c sqlite-svn/libsqlite/src/build.c
+--- sqlite-1.0.3/libsqlite/src/build.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/build.c 2012-10-09 13:36:42.520091164 +0000
+@@ -23,7 +23,7 @@
+ ** ROLLBACK
+ ** PRAGMA
+ **
+-** $Id: build.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: build.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include <ctype.h>
+@@ -1537,7 +1537,7 @@
+ if( pName && !db->init.busy ){
+ Index *pISameName; /* Another index with the same name */
+ Table *pTSameName; /* A table with same name as the index */
+- zName = sqliteStrNDup(pName->z, pName->n);
++ zName = sqliteTableNameFromToken(pName);
+ if( zName==0 ) goto exit_create_index;
+ if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
+ sqliteErrorMsg(pParse, "index %s already exists", zName);
+@@ -1557,7 +1557,7 @@
+ sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
+ if( zName==0 ) goto exit_create_index;
+ }else{
+- zName = sqliteStrNDup(pName->z, pName->n);
++ zName = sqliteTableNameFromToken(pName);
+ }
+
+ /* Check for authorization to create an index.
+diff -dPNur sqlite-1.0.3/libsqlite/src/config_static.w32.h sqlite-svn/libsqlite/src/config_static.w32.h
+--- sqlite-1.0.3/libsqlite/src/config_static.w32.h 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/libsqlite/src/config_static.w32.h 2012-10-09 13:36:42.551252050 +0000
+@@ -0,0 +1 @@
++#define SQLITE_PTR_SZ 4
+\ No newline at end of file
+diff -dPNur sqlite-1.0.3/libsqlite/src/copy.c sqlite-svn/libsqlite/src/copy.c
+--- sqlite-1.0.3/libsqlite/src/copy.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/copy.c 2012-10-09 13:36:42.541252205 +0000
+@@ -11,7 +11,7 @@
+ *************************************************************************
+ ** This file contains code used to implement the COPY command.
+ **
+-** $Id: copy.c,v 1.2.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: copy.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/date.c sqlite-svn/libsqlite/src/date.c
+--- sqlite-1.0.3/libsqlite/src/date.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/date.c 2012-10-09 13:36:42.541252205 +0000
+@@ -16,7 +16,7 @@
+ ** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
+ ** All other code has file scope.
+ **
+-** $Id: date.c,v 1.2.2.2 2004/07/10 12:25:34 wez Exp $
++** $Id: date.c 278363 2009-04-07 11:45:13Z kalle $
+ **
+ ** NOTES:
+ **
+@@ -53,6 +53,9 @@
+ #include <stdlib.h>
+ #include <assert.h>
+ #include <time.h>
++#ifndef PHP_WIN32
++#include "main/php_reentrancy.h"
++#endif
+
+ #ifndef SQLITE_OMIT_DATETIME_FUNCS
+
+@@ -397,7 +400,7 @@
+ static double localtimeOffset(DateTime *p){
+ DateTime x, y;
+ time_t t;
+- struct tm *pTm;
++ struct tm *pTm, tmbuf;
+ x = *p;
+ computeYMD_HMS(&x);
+ if( x.Y<1971 || x.Y>=2038 ){
+@@ -416,7 +419,10 @@
+ computeJD(&x);
+ t = (x.rJD-2440587.5)*86400.0 + 0.5;
+ sqliteOsEnterMutex();
+- pTm = localtime(&t);
++ pTm = php_localtime_r(&t, &tmbuf);
++ if (!pTm) {
++ return 0;
++ }
+ y.Y = pTm->tm_year + 1900;
+ y.M = pTm->tm_mon + 1;
+ y.D = pTm->tm_mday;
+@@ -800,18 +806,20 @@
+ case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
+ case 'W': /* Fall thru */
+ case 'j': {
+- int n;
++ 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 + 1;
++ n = x.rJD - y.rJD;
+ if( zFmt[i]=='W' ){
+- sprintf(&z[j],"%02d",(n+6)/7);
++ 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);
++ sprintf(&z[j],"%03d",n+1);
+ j += 3;
+ }
+ break;
+@@ -847,19 +855,18 @@
+ ** external linkage.
+ */
+ void sqliteRegisterDateTimeFunctions(sqlite *db){
++#ifndef SQLITE_OMIT_DATETIME_FUNCS
+ static struct {
+ char *zName;
+ int nArg;
+ int dataType;
+ void (*xFunc)(sqlite_func*,int,const char**);
+ } aFuncs[] = {
+-#ifndef SQLITE_OMIT_DATETIME_FUNCS
+ { "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
+ { "date", -1, SQLITE_TEXT, dateFunc },
+ { "time", -1, SQLITE_TEXT, timeFunc },
+ { "datetime", -1, SQLITE_TEXT, datetimeFunc },
+ { "strftime", -1, SQLITE_TEXT, strftimeFunc },
+-#endif
+ };
+ int i;
+
+@@ -870,4 +877,5 @@
+ sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
+ }
+ }
++#endif
+ }
+diff -dPNur sqlite-1.0.3/libsqlite/src/delete.c sqlite-svn/libsqlite/src/delete.c
+--- sqlite-1.0.3/libsqlite/src/delete.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/delete.c 2012-10-09 13:36:42.531952680 +0000
+@@ -12,7 +12,7 @@
+ ** This file contains C code routines that are called by the parser
+ ** to handle DELETE FROM statements.
+ **
+-** $Id: delete.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: delete.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/encode.c sqlite-svn/libsqlite/src/encode.c
+--- sqlite-1.0.3/libsqlite/src/encode.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/encode.c 2012-10-09 13:36:42.551252050 +0000
+@@ -15,7 +15,7 @@
+ ** data in an SQLite database. The code in this file is not used by any other
+ ** part of the SQLite library.
+ **
+-** $Id: encode.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: encode.c 225725 2006-12-24 20:50:02Z iliaa $
+ */
+ #include <string.h>
+ #include <assert.h>
+@@ -176,9 +176,12 @@
+ int i, e;
+ unsigned char c;
+ e = *(in++);
++ if (e == 0) {
++ return 0;
++ }
+ i = 0;
+ while( (c = *(in++))!=0 ){
+- if( c==1 ){
++ if (c == 1) {
+ c = *(in++) - 1;
+ }
+ out[i++] = c + e;
+diff -dPNur sqlite-1.0.3/libsqlite/src/expr.c sqlite-svn/libsqlite/src/expr.c
+--- sqlite-1.0.3/libsqlite/src/expr.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/expr.c 2012-10-09 13:36:42.551252050 +0000
+@@ -12,7 +12,7 @@
+ ** This file contains routines used for analyzing expressions and
+ ** for generating VDBE code that evaluates expressions in SQLite.
+ **
+-** $Id: expr.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: expr.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include <ctype.h>
+@@ -124,7 +124,7 @@
+ if( pNew==0 ) return 0;
+ memcpy(pNew, p, sizeof(*pNew));
+ if( p->token.z!=0 ){
+- pNew->token.z = sqliteStrDup(p->token.z);
++ pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
+ pNew->token.dyn = 1;
+ }else{
+ assert( pNew->token.z==0 );
+@@ -155,7 +155,10 @@
+ if( pNew==0 ) return 0;
+ pNew->nExpr = pNew->nAlloc = p->nExpr;
+ pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
+- if( pItem==0 ) return 0; /* Leaks memory after a malloc failure */
++ if( pItem==0 ){
++ sqliteFree(pNew);
++ return 0;
++ }
+ for(i=0; i<p->nExpr; i++, pItem++){
+ Expr *pNewExpr, *pOldExpr;
+ pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
+diff -dPNur sqlite-1.0.3/libsqlite/src/func.c sqlite-svn/libsqlite/src/func.c
+--- sqlite-1.0.3/libsqlite/src/func.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/func.c 2012-10-09 13:36:42.551252050 +0000
+@@ -16,7 +16,7 @@
+ ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
+ ** All other code has file scope.
+ **
+-** $Id: func.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: func.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include <ctype.h>
+ #include <math.h>
+@@ -157,20 +157,20 @@
+ ** Implementation of the upper() and lower() SQL functions.
+ */
+ static void upperFunc(sqlite_func *context, int argc, const char **argv){
+- char *z;
++ unsigned char *z;
+ int i;
+ if( argc<1 || argv[0]==0 ) return;
+- z = sqlite_set_result_string(context, argv[0], -1);
++ z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
+ if( z==0 ) return;
+ for(i=0; z[i]; i++){
+ if( islower(z[i]) ) z[i] = toupper(z[i]);
+ }
+ }
+ static void lowerFunc(sqlite_func *context, int argc, const char **argv){
+- char *z;
++ unsigned char *z;
+ int i;
+ if( argc<1 || argv[0]==0 ) return;
+- z = sqlite_set_result_string(context, argv[0], -1);
++ z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
+ if( z==0 ) return;
+ for(i=0; z[i]; i++){
+ if( isupper(z[i]) ) z[i] = tolower(z[i]);
+@@ -517,26 +517,28 @@
+ int mask; /* 0 for min() or 0xffffffff for max() */
+
+ assert( argc==2 );
++ if( argv[0]==0 ) return; /* Ignore NULL values */
+ if( argv[1][0]=='n' ){
+ xCompare = sqliteCompare;
+ }else{
+ xCompare = strcmp;
+ }
+ mask = (int)sqlite_user_data(context);
++ assert( mask==0 || mask==-1 );
+ p = sqlite_aggregate_context(context, sizeof(*p));
+- if( p==0 || argc<1 || argv[0]==0 ) return;
++ if( p==0 || argc<1 ) return;
+ if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
+ int len;
+- if( !p->zBuf[0] ){
++ if( p->zBuf[0] ){
+ sqliteFree(p->z);
+ }
+ len = strlen(argv[0]);
+ if( len < sizeof(p->zBuf)-1 ){
+ p->z = &p->zBuf[1];
+- p->zBuf[0] = 1;
++ p->zBuf[0] = 0;
+ }else{
+ p->z = sqliteMalloc( len+1 );
+- p->zBuf[0] = 0;
++ p->zBuf[0] = 1;
+ if( p->z==0 ) return;
+ }
+ strcpy(p->z, argv[0]);
+@@ -545,10 +547,10 @@
+ static void minMaxFinalize(sqlite_func *context){
+ MinMaxCtx *p;
+ p = sqlite_aggregate_context(context, sizeof(*p));
+- if( p && p->z ){
++ if( p && p->z && p->zBuf[0]<2 ){
+ sqlite_set_result_string(context, p->z, strlen(p->z));
+ }
+- if( p && !p->zBuf[0] ){
++ if( p && p->zBuf[0] ){
+ sqliteFree(p->z);
+ }
+ }
+@@ -621,7 +623,12 @@
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+- void *pArg = aFuncs[i].argType==2 ? (void*)(-1) : db;
++ void *pArg;
++ switch( aFuncs[i].argType ){
++ case 0: pArg = 0; break;
++ case 1: pArg = db; break;
++ case 2: pArg = (void*)(-1); break;
++ }
+ sqlite_create_function(db, aFuncs[i].zName,
+ aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
+ if( aFuncs[i].xFunc ){
+@@ -629,7 +636,12 @@
+ }
+ }
+ for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
+- void *pArg = aAggs[i].argType==2 ? (void*)(-1) : db;
++ void *pArg;
++ switch( aAggs[i].argType ){
++ case 0: pArg = 0; break;
++ case 1: pArg = db; break;
++ case 2: pArg = (void*)(-1); break;
++ }
+ sqlite_create_aggregate(db, aAggs[i].zName,
+ aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
+ sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
+diff -dPNur sqlite-1.0.3/libsqlite/src/hash.c sqlite-svn/libsqlite/src/hash.c
+--- sqlite-1.0.3/libsqlite/src/hash.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/hash.c 2012-10-09 13:36:42.541252205 +0000
+@@ -12,7 +12,7 @@
+ ** This is the implementation of generic hash-tables
+ ** used in SQLite.
+ **
+-** $Id: hash.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: hash.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include <assert.h>
+diff -dPNur sqlite-1.0.3/libsqlite/src/hash.h sqlite-svn/libsqlite/src/hash.h
+--- sqlite-1.0.3/libsqlite/src/hash.h 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/hash.h 2012-10-09 13:36:42.541252205 +0000
+@@ -12,7 +12,7 @@
+ ** This is the header file for the generic hash-table implemenation
+ ** used in SQLite.
+ **
+-** $Id: hash.h,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: hash.h 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #ifndef _SQLITE_HASH_H_
+ #define _SQLITE_HASH_H_
+diff -dPNur sqlite-1.0.3/libsqlite/src/insert.c sqlite-svn/libsqlite/src/insert.c
+--- sqlite-1.0.3/libsqlite/src/insert.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/insert.c 2012-10-09 13:36:42.541252205 +0000
+@@ -12,7 +12,7 @@
+ ** This file contains C code routines that are called by the parser
+ ** to handle INSERT statements in SQLite.
+ **
+-** $Id: insert.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: insert.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/libsqlite.dsp sqlite-svn/libsqlite/src/libsqlite.dsp
+--- sqlite-1.0.3/libsqlite/src/libsqlite.dsp 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/libsqlite/src/libsqlite.dsp 2012-10-09 13:36:42.541252205 +0000
+@@ -0,0 +1,353 @@
++# Microsoft Developer Studio Project File - Name="libsqlite" - Package Owner=<4>
++# Microsoft Developer Studio Generated Build File, Format Version 6.00
++# ** DO NOT EDIT **
++
++# TARGTYPE "Win32 (x86) Static Library" 0x0104
++
++CFG=libsqlite - Win32 Debug_TS
++!MESSAGE This is not a valid makefile. To build this project using NMAKE,
++!MESSAGE use the Export Makefile command and run
++!MESSAGE
++!MESSAGE NMAKE /f "libsqlite.mak".
++!MESSAGE
++!MESSAGE You can specify a configuration when running NMAKE
++!MESSAGE by defining the macro CFG on the command line. For example:
++!MESSAGE
++!MESSAGE NMAKE /f "libsqlite.mak" CFG="libsqlite - Win32 Debug_TS"
++!MESSAGE
++!MESSAGE Possible choices for configuration are:
++!MESSAGE
++!MESSAGE "libsqlite - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
++!MESSAGE "libsqlite - Win32 Release_TS" (based on "Win32 (x86) Static Library")
++!MESSAGE "libsqlite - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
++!MESSAGE
++
++# Begin Project
++# PROP AllowPerConfigDependencies 0
++# PROP Scc_ProjName ""
++# PROP Scc_LocalPath ""
++CPP=cl.exe
++RSC=rc.exe
++
++!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
++
++# PROP BASE Use_MFC 0
++# PROP BASE Use_Debug_Libraries 1
++# PROP BASE Output_Dir "Debug_TS"
++# PROP BASE Intermediate_Dir "Debug_TS"
++# PROP BASE Target_Dir ""
++# PROP Use_MFC 0
++# PROP Use_Debug_Libraries 1
++# PROP Output_Dir "..\..\Debug_TS"
++# PROP Intermediate_Dir "..\..\Debug_TS"
++# PROP Target_Dir ""
++# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
++# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /GZ /c
++# ADD BASE RSC /l 0x406 /d "_DEBUG"
++# ADD RSC /l 0x406 /d "_DEBUG"
++BSC32=bscmake.exe
++# ADD BASE BSC32 /nologo
++# ADD BSC32 /nologo
++LIB32=link.exe -lib
++# ADD BASE LIB32 /nologo
++# ADD LIB32 /nologo
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
++
++# PROP BASE Use_MFC 0
++# PROP BASE Use_Debug_Libraries 0
++# PROP BASE Output_Dir "Release_TS"
++# PROP BASE Intermediate_Dir "Release_TS"
++# PROP BASE Target_Dir ""
++# PROP Use_MFC 0
++# PROP Use_Debug_Libraries 0
++# PROP Output_Dir "..\..\Release_TS"
++# PROP Intermediate_Dir "..\..\Release_TS"
++# PROP Target_Dir ""
++# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
++# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
++# ADD BASE RSC /l 0x406 /d "NDEBUG"
++# ADD RSC /l 0x406 /d "NDEBUG"
++BSC32=bscmake.exe
++# ADD BASE BSC32 /nologo
++# ADD BSC32 /nologo
++LIB32=link.exe -lib
++# ADD BASE LIB32 /nologo
++# ADD LIB32 /nologo
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
++
++# PROP BASE Use_MFC 0
++# PROP BASE Use_Debug_Libraries 0
++# PROP BASE Output_Dir "libsqlite___Win32_Release_TSDbg"
++# PROP BASE Intermediate_Dir "libsqlite___Win32_Release_TSDbg"
++# PROP BASE Target_Dir ""
++# PROP Use_MFC 0
++# PROP Use_Debug_Libraries 0
++# PROP Output_Dir "..\..\Release_TSDbg"
++# PROP Intermediate_Dir "..\..\Release_TSDbg"
++# PROP Target_Dir ""
++# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
++# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
++# ADD BASE RSC /l 0x406 /d "NDEBUG"
++# ADD RSC /l 0x406 /d "NDEBUG"
++BSC32=bscmake.exe
++# ADD BASE BSC32 /nologo
++# ADD BSC32 /nologo
++LIB32=link.exe -lib
++# ADD BASE LIB32 /nologo /out:"Release_TS\libsqlite.lib"
++# ADD LIB32 /nologo
++
++!ENDIF
++
++# Begin Target
++
++# Name "libsqlite - Win32 Debug_TS"
++# Name "libsqlite - Win32 Release_TS"
++# Name "libsqlite - Win32 Release_TSDbg"
++# Begin Group "Source Files"
++
++# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
++# Begin Source File
++
++SOURCE=attach.c
++# End Source File
++# Begin Source File
++
++SOURCE=auth.c
++# End Source File
++# Begin Source File
++
++SOURCE=btree.c
++# End Source File
++# Begin Source File
++
++SOURCE=btree_rb.c
++# End Source File
++# Begin Source File
++
++SOURCE=build.c
++# End Source File
++# Begin Source File
++
++SOURCE=copy.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\date.c
++# End Source File
++# Begin Source File
++
++SOURCE=delete.c
++# End Source File
++# Begin Source File
++
++SOURCE=encode.c
++# End Source File
++# Begin Source File
++
++SOURCE=expr.c
++# End Source File
++# Begin Source File
++
++SOURCE=func.c
++# End Source File
++# Begin Source File
++
++SOURCE=hash.c
++# End Source File
++# Begin Source File
++
++SOURCE=insert.c
++# End Source File
++# Begin Source File
++
++SOURCE=main.c
++# End Source File
++# Begin Source File
++
++SOURCE=opcodes.c
++# End Source File
++# Begin Source File
++
++SOURCE=os.c
++# End Source File
++# Begin Source File
++
++SOURCE=pager.c
++# End Source File
++# Begin Source File
++
++SOURCE=parse.c
++# End Source File
++# Begin Source File
++
++SOURCE=pragma.c
++# End Source File
++# Begin Source File
++
++SOURCE=printf.c
++# End Source File
++# Begin Source File
++
++SOURCE=random.c
++# End Source File
++# Begin Source File
++
++SOURCE=select.c
++# End Source File
++# Begin Source File
++
++SOURCE=table.c
++# End Source File
++# Begin Source File
++
++SOURCE=tokenize.c
++# End Source File
++# Begin Source File
++
++SOURCE=trigger.c
++# End Source File
++# Begin Source File
++
++SOURCE=update.c
++# End Source File
++# Begin Source File
++
++SOURCE=util.c
++# End Source File
++# Begin Source File
++
++SOURCE=vacuum.c
++# End Source File
++# Begin Source File
++
++SOURCE=vdbe.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\vdbeaux.c
++# End Source File
++# Begin Source File
++
++SOURCE=where.c
++# End Source File
++# End Group
++# Begin Group "Header Files"
++
++# PROP Default_Filter "h;hpp;hxx;hm;inl"
++# Begin Source File
++
++SOURCE=btree.h
++# End Source File
++# Begin Source File
++
++SOURCE=config_static.w32.h
++
++!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
++
++# Begin Custom Build
++InputDir=.
++InputPath=config_static.w32.h
++
++"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\config.h
++
++# End Custom Build
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
++
++# Begin Custom Build
++InputDir=.
++InputPath=config_static.w32.h
++
++"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\config.h
++
++# End Custom Build
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
++
++# Begin Custom Build
++InputDir=.
++InputPath=config_static.w32.h
++
++"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\config.h
++
++# End Custom Build
++
++!ENDIF
++
++# End Source File
++# Begin Source File
++
++SOURCE=hash.h
++# End Source File
++# Begin Source File
++
++SOURCE=opcodes.h
++# End Source File
++# Begin Source File
++
++SOURCE=os.h
++# End Source File
++# Begin Source File
++
++SOURCE=pager.h
++# End Source File
++# Begin Source File
++
++SOURCE=parse.h
++# End Source File
++# Begin Source File
++
++SOURCE=sqlite.w32.h
++
++!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
++
++# Begin Custom Build
++InputDir=.
++InputPath=sqlite.w32.h
++
++"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\sqlite.h
++
++# End Custom Build
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
++
++# Begin Custom Build
++InputDir=.
++InputPath=sqlite.w32.h
++
++"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\sqlite.h
++
++# End Custom Build
++
++!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
++
++# Begin Custom Build
++InputDir=.
++InputPath=sqlite.w32.h
++
++"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
++ copy $(InputPath) $(InputDir)\sqlite.h
++
++# End Custom Build
++
++!ENDIF
++
++# End Source File
++# Begin Source File
++
++SOURCE=sqliteInt.h
++# End Source File
++# Begin Source File
++
++SOURCE=vdbe.h
++# End Source File
++# End Group
++# End Target
++# End Project
+diff -dPNur sqlite-1.0.3/libsqlite/src/main.c sqlite-svn/libsqlite/src/main.c
+--- sqlite-1.0.3/libsqlite/src/main.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/main.c 2012-10-09 13:36:42.551252050 +0000
+@@ -14,7 +14,7 @@
+ ** other files are for internal use by SQLite and should not be
+ ** accessed by users of the library.
+ **
+-** $Id: main.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: main.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include "os.h"
+@@ -189,10 +189,13 @@
+ BtCursor *curMain;
+ int size;
+ Table *pTab;
+- char *azArg[6];
++ char const *azArg[6];
+ char zDbNum[30];
+ int meta[SQLITE_N_BTREE_META];
+ InitData initData;
++ char const *zMasterSchema;
++ char const *zMasterName;
++ char *zSql = 0;
+
+ /*
+ ** The master database table has a structure like this
+@@ -216,62 +219,38 @@
+ ")"
+ ;
+
+- /* The following SQL will read the schema from the master tables.
+- ** The first version works with SQLite file formats 2 or greater.
+- ** The second version is for format 1 files.
+- **
+- ** Beginning with file format 2, the rowid for new table entries
+- ** (including entries in sqlite_master) is an increasing integer.
+- ** So for file format 2 and later, we can play back sqlite_master
+- ** and all the CREATE statements will appear in the right order.
+- ** But with file format 1, table entries were random and so we
+- ** have to make sure the CREATE TABLEs occur before their corresponding
+- ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
+- ** CREATE TRIGGER in file format 1 because those constructs did
+- ** not exist then.)
+- */
+- static char init_script[] =
+- "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
+- "UNION ALL "
+- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
+- static char older_init_script[] =
+- "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
+- "UNION ALL "
+- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
+- "WHERE type='table' "
+- "UNION ALL "
+- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
+- "WHERE type='index'";
+-
++ assert( iDb>=0 && iDb<db->nDb );
+
+- assert( iDb>=0 && iDb!=1 && 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: sqlite_master and sqlite_temp_master
++ /* Construct the schema table.
+ */
+ sqliteSafetyOff(db);
+ azArg[0] = "table";
+- azArg[1] = MASTER_NAME;
++ azArg[1] = zMasterName;
+ azArg[2] = "2";
+- azArg[3] = master_schema;
++ azArg[3] = zMasterSchema;
+ sprintf(zDbNum, "%d", iDb);
+ azArg[4] = zDbNum;
+ azArg[5] = 0;
+ initData.db = db;
+ initData.pzErrMsg = pzErrMsg;
+- sqliteInitCallback(&initData, 5, azArg, 0);
+- pTab = sqliteFindTable(db, MASTER_NAME, "main");
++ sqliteInitCallback(&initData, 5, (char **)azArg, 0);
++ pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
+ if( pTab ){
+ pTab->readOnly = 1;
+- }
+- if( iDb==0 ){
+- azArg[1] = TEMP_MASTER_NAME;
+- azArg[3] = temp_master_schema;
+- azArg[4] = "1";
+- sqliteInitCallback(&initData, 5, azArg, 0);
+- pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
+- if( pTab ){
+- pTab->readOnly = 1;
+- }
++ }else{
++ return SQLITE_NOMEM;
+ }
+ sqliteSafetyOn(db);
+
+@@ -320,7 +299,7 @@
+ sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
+ return SQLITE_ERROR;
+ }
+- }else if( db->file_format!=meta[2] || db->file_format<4 ){
++ }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
+ assert( db->file_format>=4 );
+ if( meta[2]==0 ){
+ sqliteSetString(pzErrMsg, "cannot attach empty database: ",
+@@ -340,18 +319,35 @@
+ */
+ assert( db->init.busy );
+ sqliteSafetyOff(db);
+- if( iDb==0 ){
+- rc = sqlite_exec(db,
+- db->file_format>=2 ? init_script : older_init_script,
+- sqliteInitCallback, &initData, 0);
++
++ /* The following SQL will read the schema from the master tables.
++ ** The first version works with SQLite file formats 2 or greater.
++ ** The second version is for format 1 files.
++ **
++ ** Beginning with file format 2, the rowid for new table entries
++ ** (including entries in sqlite_master) is an increasing integer.
++ ** So for file format 2 and later, we can play back sqlite_master
++ ** and all the CREATE statements will appear in the right order.
++ ** But with file format 1, table entries were random and so we
++ ** have to make sure the CREATE TABLEs occur before their corresponding
++ ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
++ ** CREATE TRIGGER in file format 1 because those constructs did
++ ** not exist then.)
++ */
++ if( db->file_format>=2 ){
++ sqliteSetString(&zSql,
++ "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
++ db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
+ }else{
+- char *zSql = 0;
+ sqliteSetString(&zSql,
+- "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
+- db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
+- rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
+- sqliteFree(zSql);
++ "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
++ db->aDb[iDb].zName, "\".", zMasterName,
++ " WHERE type IN ('table', 'index')"
++ " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
+ }
++ rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
++
++ sqliteFree(zSql);
+ sqliteSafetyOn(db);
+ sqliteBtreeCloseCursor(curMain);
+ if( sqlite_malloc_failed ){
+@@ -361,9 +357,6 @@
+ }
+ if( rc==SQLITE_OK ){
+ DbSetProperty(db, iDb, DB_SchemaLoaded);
+- if( iDb==0 ){
+- DbSetProperty(db, 1, DB_SchemaLoaded);
+- }
+ }else{
+ sqliteResetInternalSchema(db, iDb);
+ }
+@@ -391,13 +384,24 @@
+ rc = SQLITE_OK;
+ db->init.busy = 1;
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+- if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
+- assert( i!=1 ); /* Should have been initialized together with 0 */
++ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
+ rc = sqliteInitOne(db, i, pzErrMsg);
+ if( rc ){
+ sqliteResetInternalSchema(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 = sqliteInitOne(db, 1, pzErrMsg);
++ if( rc ){
++ sqliteResetInternalSchema(db, 1);
++ }
++ }
++
+ db->init.busy = 0;
+ if( rc==SQLITE_OK ){
+ db->flags |= SQLITE_Initialized;
+diff -dPNur sqlite-1.0.3/libsqlite/src/os.c sqlite-svn/libsqlite/src/os.c
+--- sqlite-1.0.3/libsqlite/src/os.c 2004-07-10 11:47:26.000000000 +0000
++++ sqlite-svn/libsqlite/src/os.c 2012-10-09 13:36:42.541252205 +0000
+@@ -830,7 +830,7 @@
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ int i, j;
+- char *zDir;
++ const char *zDir;
+ char zTempPath[SQLITE_TEMPNAME_SIZE];
+ if( sqlite_temp_directory==0 ){
+ GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
+@@ -1116,6 +1116,10 @@
+ #endif
+ }
+
++#ifdef SQLITE_NOSYNC
++# define fsync(X) 0
++#endif
++
+ /*
+ ** Make sure all writes to a particular file are committed to disk.
+ **
+@@ -1774,6 +1778,7 @@
+ sqliteSetString(&zFull, zRelative, (char*)0);
+ }else{
+ char zBuf[5000];
++ zBuf[0] = 0;
+ sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
+ (char*)0);
+ }
+diff -dPNur sqlite-1.0.3/libsqlite/src/pager.c sqlite-svn/libsqlite/src/pager.c
+--- sqlite-1.0.3/libsqlite/src/pager.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/pager.c 2012-10-09 13:36:42.541252205 +0000
+@@ -18,7 +18,7 @@
+ ** file simultaneously, or one process from reading the database while
+ ** another is writing.
+ **
+-** @(#) $Id: pager.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: pager.c 203289 2005-12-20 15:26:26Z iliaa $
+ */
+ #include "os.h" /* Must be first to enable large file support */
+ #include "sqliteInt.h"
+@@ -1929,7 +1929,7 @@
+
+ pPg = pager_lookup(pPager, pgno);
+ pPg->alwaysRollback = 1;
+- if( pPg && pPg->dirty ){
++ if( pPg && pPg->dirty && !pPager->ckptInUse ){
+ 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.
+diff -dPNur sqlite-1.0.3/libsqlite/src/pager.h sqlite-svn/libsqlite/src/pager.h
+--- sqlite-1.0.3/libsqlite/src/pager.h 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/pager.h 2012-10-09 13:36:42.541252205 +0000
+@@ -13,7 +13,7 @@
+ ** subsystem. The page cache subsystem reads and writes a file a page
+ ** at a time and provides a journal for rollback.
+ **
+-** @(#) $Id: pager.h,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: pager.h 195361 2005-09-07 15:11:33Z iliaa $
+ */
+
+ /*
+diff -dPNur sqlite-1.0.3/libsqlite/src/parse.c sqlite-svn/libsqlite/src/parse.c
+--- sqlite-1.0.3/libsqlite/src/parse.c 2004-07-18 10:29:42.000000000 +0000
++++ sqlite-svn/libsqlite/src/parse.c 2012-10-09 13:36:42.541252205 +0000
+@@ -4,7 +4,7 @@
+ /* First off, code is include which follows the "include" declaration
+ ** in the input file. */
+ #include <stdio.h>
+-#line 33 "parse.y"
++#line 33 "ext/sqlite/libsqlite/src/parse.y"
+
+ #include "sqliteInt.h"
+ #include "parse.h"
+@@ -29,8 +29,7 @@
+ */
+ struct TrigEvent { int a; IdList * b; };
+
+-
+-#line 34 "parse.c"
++#line 34 "ext/sqlite/libsqlite/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.
+ */
+@@ -79,7 +78,6 @@
+ ** YYERRORSYMBOL is the code number of the error symbol. If not
+ ** defined, then do no error processing.
+ */
+-/*  */
+ #define YYCODETYPE unsigned char
+ #define YYNOCODE 221
+ #define YYACTIONTYPE unsigned short int
+@@ -161,7 +159,7 @@
+ ** shifting non-terminals after a reduce.
+ ** yy_default[] Default action for each state.
+ */
+-static YYACTIONTYPE yy_action[] = {
++static const YYACTIONTYPE yy_action[] = {
+ /* 0 */ 264, 5, 262, 119, 123, 117, 121, 129, 131, 133,
+ /* 10 */ 135, 144, 146, 148, 150, 152, 154, 568, 106, 106,
+ /* 20 */ 143, 857, 1, 562, 3, 142, 129, 131, 133, 135,
+@@ -292,7 +290,7 @@
+ /* 1270 */ 556, 550, 850, 547, 549, 851, 555, 558, 551, 855,
+ /* 1280 */ 553, 559,
+ };
+-static YYCODETYPE yy_lookahead[] = {
++static const YYCODETYPE yy_lookahead[] = {
+ /* 0 */ 21, 9, 23, 70, 71, 72, 73, 74, 75, 76,
+ /* 10 */ 77, 78, 79, 80, 81, 82, 83, 9, 140, 140,
+ /* 20 */ 41, 132, 133, 134, 135, 46, 74, 75, 76, 77,
+@@ -424,7 +422,7 @@
+ /* 1280 */ 219, 140,
+ };
+ #define YY_SHIFT_USE_DFLT (-68)
+-static short yy_shift_ofst[] = {
++static const short yy_shift_ofst[] = {
+ /* 0 */ 170, 113, -68, 746, -8, -68, 8, 127, 288, 239,
+ /* 10 */ 348, 167, -68, -68, -68, -68, -68, -68, 547, -68,
+ /* 20 */ -68, -68, -68, 115, 613, 115, 723, 115, 761, 44,
+@@ -484,7 +482,7 @@
+ /* 560 */ -68, -68, -68,
+ };
+ #define YY_REDUCE_USE_DFLT (-123)
+-static short yy_reduce_ofst[] = {
++static const short yy_reduce_ofst[] = {
+ /* 0 */ -111, 55, -123, 643, -123, -123, -123, -100, 82, -123,
+ /* 10 */ -123, 233, -123, -123, -123, -123, -123, -123, 310, -123,
+ /* 20 */ -123, -123, -123, 442, -123, 448, -123, 542, -123, 540,
+@@ -543,7 +541,7 @@
+ /* 550 */ -123, 1129, 1061, -123, 1124, -123, -123, 1059, 1141, -123,
+ /* 560 */ -123, -123, -123,
+ };
+-static YYACTIONTYPE yy_default[] = {
++static const YYACTIONTYPE yy_default[] = {
+ /* 0 */ 570, 570, 564, 856, 856, 566, 856, 572, 856, 856,
+ /* 10 */ 856, 856, 652, 655, 656, 657, 658, 659, 573, 574,
+ /* 20 */ 591, 592, 593, 856, 856, 856, 856, 856, 856, 856,
+@@ -816,7 +814,7 @@
+ #ifndef NDEBUG
+ /* For tracing shifts, the names of all terminals and nonterminals
+ ** are required. The following table supplies these names */
+-static const char *yyTokenName[] = {
++static const char *const yyTokenName[] = {
+ "$", "END_OF_FILE", "ILLEGAL", "SPACE",
+ "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN",
+ "AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN",
+@@ -878,7 +876,7 @@
+ #ifndef NDEBUG
+ /* For tracing reduce actions, the names of all rules are required.
+ */
+-static const char *yyRuleName[] = {
++static const char *const yyRuleName[] = {
+ /* 0 */ "input ::= cmdlist",
+ /* 1 */ "cmdlist ::= cmdlist ecmd",
+ /* 2 */ "cmdlist ::= ecmd",
+@@ -1230,149 +1228,61 @@
+ ** inside the C code.
+ */
+ case 146:
+-#line 286 "parse.y"
++ case 171:
++ case 189:
++#line 286 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteSelectDelete((yypminor->yy179));}
+-#line 1235 "parse.c"
++#line 1237 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 158:
+-#line 533 "parse.y"
++ case 176:
++ case 178:
++ case 187:
++ case 192:
++ case 204:
++#line 533 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteExprDelete((yypminor->yy242));}
+-#line 1240 "parse.c"
++#line 1247 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 159:
+-#line 746 "parse.y"
+-{sqliteIdListDelete((yypminor->yy320));}
+-#line 1245 "parse.c"
+- break;
+ case 167:
+-#line 744 "parse.y"
++ case 188:
++ case 197:
++ case 199:
++#line 746 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteIdListDelete((yypminor->yy320));}
+-#line 1250 "parse.c"
+- break;
+- case 171:
+-#line 288 "parse.y"
+-{sqliteSelectDelete((yypminor->yy179));}
+-#line 1255 "parse.c"
++#line 1256 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 174:
+-#line 322 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1260 "parse.c"
+- break;
+- case 175:
+-#line 353 "parse.y"
+-{sqliteSrcListDelete((yypminor->yy307));}
+-#line 1265 "parse.c"
+- break;
+- case 176:
+-#line 483 "parse.y"
+-{sqliteExprDelete((yypminor->yy242));}
+-#line 1270 "parse.c"
+- break;
+ case 177:
+-#line 459 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1275 "parse.c"
+- break;
+- case 178:
+-#line 464 "parse.y"
+-{sqliteExprDelete((yypminor->yy242));}
+-#line 1280 "parse.c"
+- break;
+ case 179:
+-#line 431 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1285 "parse.c"
+- break;
+ case 181:
+-#line 324 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1290 "parse.c"
+- break;
+- case 183:
+-#line 349 "parse.y"
+-{sqliteSrcListDelete((yypminor->yy307));}
+-#line 1295 "parse.c"
+- break;
+- case 184:
+-#line 351 "parse.y"
+-{sqliteSrcListDelete((yypminor->yy307));}
+-#line 1300 "parse.c"
+- break;
+- case 187:
+-#line 420 "parse.y"
+-{sqliteExprDelete((yypminor->yy242));}
+-#line 1305 "parse.c"
+- break;
+- case 188:
+-#line 425 "parse.y"
+-{sqliteIdListDelete((yypminor->yy320));}
+-#line 1310 "parse.c"
+- break;
+- case 189:
+-#line 400 "parse.y"
+-{sqliteSelectDelete((yypminor->yy179));}
+-#line 1315 "parse.c"
+- break;
+ case 191:
+-#line 433 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1320 "parse.c"
+- break;
+- case 192:
+-#line 435 "parse.y"
+-{sqliteExprDelete((yypminor->yy242));}
+-#line 1325 "parse.c"
+- break;
+ case 194:
+-#line 719 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1330 "parse.c"
+- break;
+ case 195:
+-#line 489 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1335 "parse.c"
+- break;
+- case 197:
+-#line 520 "parse.y"
+-{sqliteIdListDelete((yypminor->yy320));}
+-#line 1340 "parse.c"
+- break;
+ case 198:
+-#line 514 "parse.y"
+-{sqliteExprListDelete((yypminor->yy322));}
+-#line 1345 "parse.c"
+- break;
+- case 199:
+-#line 522 "parse.y"
+-{sqliteIdListDelete((yypminor->yy320));}
+-#line 1350 "parse.c"
+- break;
+ case 202:
+-#line 702 "parse.y"
++#line 322 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteExprListDelete((yypminor->yy322));}
+-#line 1355 "parse.c"
++#line 1269 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+- case 204:
+-#line 721 "parse.y"
+-{sqliteExprDelete((yypminor->yy242));}
+-#line 1360 "parse.c"
++ case 175:
++ case 183:
++ case 184:
++#line 353 "ext/sqlite/libsqlite/src/parse.y"
++{sqliteSrcListDelete((yypminor->yy307));}
++#line 1276 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 212:
+-#line 828 "parse.y"
++ case 217:
++#line 828 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteDeleteTriggerStep((yypminor->yy19));}
+-#line 1365 "parse.c"
++#line 1282 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 214:
+-#line 812 "parse.y"
++#line 812 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteIdListDelete((yypminor->yy290).b);}
+-#line 1370 "parse.c"
+- break;
+- case 217:
+-#line 836 "parse.y"
+-{sqliteDeleteTriggerStep((yypminor->yy19));}
+-#line 1375 "parse.c"
++#line 1287 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ default: break; /* If no destructor action specified: do nothing */
+ }
+@@ -1479,11 +1389,11 @@
+ ** return YY_NO_ACTION.
+ */
+ static int yy_find_reduce_action(
+- yyParser *pParser, /* The parser */
++ int stateno, /* Current state number */
+ int iLookAhead /* The look-ahead token */
+ ){
+ int i;
+- int stateno = pParser->yystack[pParser->yyidx].stateno;
++ /* int stateno = pParser->yystack[pParser->yyidx].stateno; */
+
+ i = yy_reduce_ofst[stateno];
+ if( i==YY_REDUCE_USE_DFLT ){
+@@ -1544,7 +1454,7 @@
+ /* The following table contains information about every rule that
+ ** is used during the reduce.
+ */
+-static struct {
++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[] = {
+@@ -1868,6 +1778,18 @@
+ }
+ #endif /* NDEBUG */
+
++#ifndef NDEBUG
++ /* Silence complaints from purify about yygotominor being uninitialized
++ ** in some cases when it is copied into the stack after the following
++ ** switch. yygotominor is uninitialized when a rule reduces that does
++ ** not set the value of its left-hand side nonterminal. Leaving the
++ ** value of the nonterminal uninitialized is utterly harmless as long
++ ** as the value is never used. So really the only thing this code
++ ** accomplishes is to quieten purify.
++ */
++ memset(&yygotominor, 0, sizeof(yygotominor));
++#endif
++
+ switch( yyruleno ){
+ /* Beginning here are the reduction cases. A typical example
+ ** follows:
+@@ -1877,596 +1799,330 @@
+ ** #line <lineno> <thisfile>
+ ** break;
+ */
+- case 0:
+- /* No destructor defined for cmdlist */
+- break;
+- case 1:
+- /* No destructor defined for cmdlist */
+- /* No destructor defined for ecmd */
+- break;
+- case 2:
+- /* No destructor defined for ecmd */
+- break;
+- case 3:
+- /* No destructor defined for explain */
+- /* No destructor defined for cmdx */
+- /* No destructor defined for SEMI */
+- break;
+- case 4:
+- /* No destructor defined for SEMI */
+- break;
+ case 5:
+-#line 72 "parse.y"
++#line 72 "ext/sqlite/libsqlite/src/parse.y"
+ { sqliteExec(pParse); }
+-#line 1901 "parse.c"
+- /* No destructor defined for cmd */
++#line 1807 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 6:
+-#line 73 "parse.y"
++#line 73 "ext/sqlite/libsqlite/src/parse.y"
+ { sqliteBeginParse(pParse, 1); }
+-#line 1907 "parse.c"
+- /* No destructor defined for EXPLAIN */
++#line 1812 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 7:
+-#line 74 "parse.y"
++#line 74 "ext/sqlite/libsqlite/src/parse.y"
+ { sqliteBeginParse(pParse, 0); }
+-#line 1913 "parse.c"
++#line 1817 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 8:
+-#line 79 "parse.y"
++#line 79 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteBeginTransaction(pParse,yymsp[0].minor.yy372);}
+-#line 1918 "parse.c"
+- /* No destructor defined for BEGIN */
+- /* No destructor defined for trans_opt */
+- break;
+- case 9:
+- break;
+- case 10:
+- /* No destructor defined for TRANSACTION */
+- break;
+- case 11:
+- /* No destructor defined for TRANSACTION */
+- /* No destructor defined for nm */
++#line 1822 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 12:
+-#line 83 "parse.y"
+-{sqliteCommitTransaction(pParse);}
+-#line 1934 "parse.c"
+- /* No destructor defined for COMMIT */
+- /* No destructor defined for trans_opt */
+- break;
+ case 13:
+-#line 84 "parse.y"
++#line 83 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCommitTransaction(pParse);}
+-#line 1941 "parse.c"
+- /* No destructor defined for END */
+- /* No destructor defined for trans_opt */
++#line 1828 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 14:
+-#line 85 "parse.y"
++#line 85 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteRollbackTransaction(pParse);}
+-#line 1948 "parse.c"
+- /* No destructor defined for ROLLBACK */
+- /* No destructor defined for trans_opt */
+- break;
+- case 15:
+- /* No destructor defined for create_table */
+- /* No destructor defined for create_table_args */
++#line 1833 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 16:
+-#line 90 "parse.y"
++#line 90 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteStartTable(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy298,yymsp[-2].minor.yy372,0);
+ }
+-#line 1961 "parse.c"
+- /* No destructor defined for TABLE */
++#line 1840 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 17:
+-#line 94 "parse.y"
++ case 74:
++ case 108:
++#line 94 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = 1;}
+-#line 1967 "parse.c"
+- /* No destructor defined for TEMP */
++#line 1847 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 18:
+-#line 95 "parse.y"
++ case 73:
++ case 75:
++ case 86:
++ case 109:
++ case 110:
++#line 95 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = 0;}
+-#line 1973 "parse.c"
++#line 1857 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 19:
+-#line 96 "parse.y"
++#line 96 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteEndTable(pParse,&yymsp[0].minor.yy0,0);
+ }
+-#line 1980 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for columnlist */
+- /* No destructor defined for conslist_opt */
++#line 1864 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 20:
+-#line 99 "parse.y"
++#line 99 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteEndTable(pParse,0,yymsp[0].minor.yy179);
+ sqliteSelectDelete(yymsp[0].minor.yy179);
+ }
+-#line 1991 "parse.c"
+- /* No destructor defined for AS */
+- break;
+- case 21:
+- /* No destructor defined for columnlist */
+- /* No destructor defined for COMMA */
+- /* No destructor defined for column */
+- break;
+- case 22:
+- /* No destructor defined for column */
+- break;
+- case 23:
+- /* No destructor defined for columnid */
+- /* No destructor defined for type */
+- /* No destructor defined for carglist */
++#line 1872 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 24:
+-#line 111 "parse.y"
++#line 111 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddColumn(pParse,&yymsp[0].minor.yy298);}
+-#line 2010 "parse.c"
++#line 1877 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 25:
+-#line 117 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2015 "parse.c"
+- break;
+ case 26:
+-#line 149 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2020 "parse.c"
+- break;
+ case 27:
+-#line 150 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2025 "parse.c"
+- break;
+ case 28:
+-#line 155 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2030 "parse.c"
+- break;
+ case 29:
+-#line 156 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2035 "parse.c"
+- break;
+ case 30:
+-#line 157 "parse.y"
++ case 256:
++ case 257:
++#line 117 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 2040 "parse.c"
+- break;
+- case 31:
++#line 1889 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 32:
+-#line 160 "parse.y"
++#line 160 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddColumnType(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298);}
+-#line 2047 "parse.c"
++#line 1894 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 33:
+-#line 161 "parse.y"
++#line 161 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddColumnType(pParse,&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0);}
+-#line 2052 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for signed */
++#line 1899 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 34:
+-#line 163 "parse.y"
++#line 163 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddColumnType(pParse,&yymsp[-5].minor.yy298,&yymsp[0].minor.yy0);}
+-#line 2059 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for signed */
+- /* No destructor defined for COMMA */
+- /* No destructor defined for signed */
++#line 1904 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 35:
+-#line 165 "parse.y"
++ case 128:
++ case 254:
++ case 255:
++#line 165 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy298 = yymsp[0].minor.yy298;}
+-#line 2068 "parse.c"
++#line 1912 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 36:
+-#line 166 "parse.y"
++ case 242:
++#line 166 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy298 = yymsp[-1].minor.yy298;}
+-#line 2073 "parse.c"
+- /* No destructor defined for ids */
++#line 1918 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 37:
+-#line 168 "parse.y"
+-{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); }
+-#line 2079 "parse.c"
+- break;
+ case 38:
+-#line 169 "parse.y"
++#line 168 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); }
+-#line 2084 "parse.c"
+- /* No destructor defined for PLUS */
++#line 1924 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 39:
+-#line 170 "parse.y"
++#line 170 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = -atoi(yymsp[0].minor.yy0.z); }
+-#line 2090 "parse.c"
+- /* No destructor defined for MINUS */
+- break;
+- case 40:
+- /* No destructor defined for carglist */
+- /* No destructor defined for carg */
+- break;
+- case 41:
+- break;
+- case 42:
+- /* No destructor defined for CONSTRAINT */
+- /* No destructor defined for nm */
+- /* No destructor defined for ccons */
+- break;
+- case 43:
+- /* No destructor defined for ccons */
++#line 1929 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 44:
+-#line 175 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2110 "parse.c"
+- /* No destructor defined for DEFAULT */
+- break;
+ case 45:
+-#line 176 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2116 "parse.c"
+- /* No destructor defined for DEFAULT */
+- break;
+ case 46:
+-#line 177 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2122 "parse.c"
+- /* No destructor defined for DEFAULT */
+- break;
+ case 47:
+-#line 178 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2128 "parse.c"
+- /* No destructor defined for DEFAULT */
+- /* No destructor defined for PLUS */
+- break;
+- case 48:
+-#line 179 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);}
+-#line 2135 "parse.c"
+- /* No destructor defined for DEFAULT */
+- /* No destructor defined for MINUS */
+- break;
+ case 49:
+-#line 180 "parse.y"
+-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2142 "parse.c"
+- /* No destructor defined for DEFAULT */
+- break;
+ case 50:
+-#line 181 "parse.y"
++#line 175 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
+-#line 2148 "parse.c"
+- /* No destructor defined for DEFAULT */
+- /* No destructor defined for PLUS */
++#line 1939 "ext/sqlite/libsqlite/src/parse.c"
+ break;
++ case 48:
+ case 51:
+-#line 182 "parse.y"
++#line 179 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);}
+-#line 2155 "parse.c"
+- /* No destructor defined for DEFAULT */
+- /* No destructor defined for MINUS */
+- break;
+- case 52:
+- /* No destructor defined for DEFAULT */
+- /* No destructor defined for NULL */
+- break;
+- case 53:
+- /* No destructor defined for NULL */
+- /* No destructor defined for onconf */
++#line 1945 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 54:
+-#line 189 "parse.y"
++#line 189 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddNotNull(pParse, yymsp[0].minor.yy372);}
+-#line 2170 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for NULL */
++#line 1950 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 55:
+-#line 190 "parse.y"
++#line 190 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddPrimaryKey(pParse,0,yymsp[0].minor.yy372);}
+-#line 2177 "parse.c"
+- /* No destructor defined for PRIMARY */
+- /* No destructor defined for KEY */
+- /* No destructor defined for sortorder */
++#line 1955 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 56:
+-#line 191 "parse.y"
++#line 191 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCreateIndex(pParse,0,0,0,yymsp[0].minor.yy372,0,0);}
+-#line 2185 "parse.c"
+- /* No destructor defined for UNIQUE */
+- break;
+- case 57:
+- /* No destructor defined for CHECK */
+- /* No destructor defined for LP */
+- yy_destructor(158,&yymsp[-2].minor);
+- /* No destructor defined for RP */
+- /* No destructor defined for onconf */
++#line 1960 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 58:
+-#line 194 "parse.y"
++#line 194 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCreateForeignKey(pParse,0,&yymsp[-2].minor.yy298,yymsp[-1].minor.yy320,yymsp[0].minor.yy372);}
+-#line 2198 "parse.c"
+- /* No destructor defined for REFERENCES */
++#line 1965 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 59:
+-#line 195 "parse.y"
++#line 195 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteDeferForeignKey(pParse,yymsp[0].minor.yy372);}
+-#line 2204 "parse.c"
++#line 1970 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 60:
+-#line 196 "parse.y"
++#line 196 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteAddCollateType(pParse, sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n));
+ }
+-#line 2211 "parse.c"
+- /* No destructor defined for COLLATE */
++#line 1977 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 61:
+-#line 206 "parse.y"
++#line 206 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Restrict * 0x010101; }
+-#line 2217 "parse.c"
++#line 1982 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 62:
+-#line 207 "parse.y"
++#line 207 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = (yymsp[-1].minor.yy372 & yymsp[0].minor.yy407.mask) | yymsp[0].minor.yy407.value; }
+-#line 2222 "parse.c"
++#line 1987 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 63:
+-#line 209 "parse.y"
++#line 209 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy407.value = 0; yygotominor.yy407.mask = 0x000000; }
+-#line 2227 "parse.c"
+- /* No destructor defined for MATCH */
+- /* No destructor defined for nm */
++#line 1992 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 64:
+-#line 210 "parse.y"
++#line 210 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy407.value = yymsp[0].minor.yy372; yygotominor.yy407.mask = 0x0000ff; }
+-#line 2234 "parse.c"
+- /* No destructor defined for ON */
+- /* No destructor defined for DELETE */
++#line 1997 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 65:
+-#line 211 "parse.y"
++#line 211 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy407.value = yymsp[0].minor.yy372<<8; yygotominor.yy407.mask = 0x00ff00; }
+-#line 2241 "parse.c"
+- /* No destructor defined for ON */
+- /* No destructor defined for UPDATE */
++#line 2002 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 66:
+-#line 212 "parse.y"
++#line 212 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy407.value = yymsp[0].minor.yy372<<16; yygotominor.yy407.mask = 0xff0000; }
+-#line 2248 "parse.c"
+- /* No destructor defined for ON */
+- /* No destructor defined for INSERT */
++#line 2007 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 67:
+-#line 214 "parse.y"
++#line 214 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_SetNull; }
+-#line 2255 "parse.c"
+- /* No destructor defined for SET */
+- /* No destructor defined for NULL */
++#line 2012 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 68:
+-#line 215 "parse.y"
++#line 215 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_SetDflt; }
+-#line 2262 "parse.c"
+- /* No destructor defined for SET */
+- /* No destructor defined for DEFAULT */
++#line 2017 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 69:
+-#line 216 "parse.y"
++#line 216 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Cascade; }
+-#line 2269 "parse.c"
+- /* No destructor defined for CASCADE */
++#line 2022 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 70:
+-#line 217 "parse.y"
++#line 217 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Restrict; }
+-#line 2275 "parse.c"
+- /* No destructor defined for RESTRICT */
++#line 2027 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 71:
+-#line 219 "parse.y"
+-{yygotominor.yy372 = yymsp[0].minor.yy372;}
+-#line 2281 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for DEFERRABLE */
+- break;
+ case 72:
+-#line 220 "parse.y"
++ case 87:
++ case 164:
++#line 219 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = yymsp[0].minor.yy372;}
+-#line 2288 "parse.c"
+- /* No destructor defined for DEFERRABLE */
+- break;
+- case 73:
+-#line 222 "parse.y"
+-{yygotominor.yy372 = 0;}
+-#line 2294 "parse.c"
+- break;
+- case 74:
+-#line 223 "parse.y"
+-{yygotominor.yy372 = 1;}
+-#line 2299 "parse.c"
+- /* No destructor defined for INITIALLY */
+- /* No destructor defined for DEFERRED */
+- break;
+- case 75:
+-#line 224 "parse.y"
+-{yygotominor.yy372 = 0;}
+-#line 2306 "parse.c"
+- /* No destructor defined for INITIALLY */
+- /* No destructor defined for IMMEDIATE */
+- break;
+- case 76:
+- break;
+- case 77:
+- /* No destructor defined for COMMA */
+- /* No destructor defined for conslist */
+- break;
+- case 78:
+- /* No destructor defined for conslist */
+- /* No destructor defined for COMMA */
+- /* No destructor defined for tcons */
+- break;
+- case 79:
+- /* No destructor defined for conslist */
+- /* No destructor defined for tcons */
+- break;
+- case 80:
+- /* No destructor defined for tcons */
+- break;
+- case 81:
+- /* No destructor defined for CONSTRAINT */
+- /* No destructor defined for nm */
++#line 2035 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 82:
+-#line 236 "parse.y"
++#line 236 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteAddPrimaryKey(pParse,yymsp[-2].minor.yy320,yymsp[0].minor.yy372);}
+-#line 2335 "parse.c"
+- /* No destructor defined for PRIMARY */
+- /* No destructor defined for KEY */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 2040 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 83:
+-#line 238 "parse.y"
++#line 238 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCreateIndex(pParse,0,0,yymsp[-2].minor.yy320,yymsp[0].minor.yy372,0,0);}
+-#line 2344 "parse.c"
+- /* No destructor defined for UNIQUE */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
+- break;
+- case 84:
+- /* No destructor defined for CHECK */
+- yy_destructor(158,&yymsp[-1].minor);
+- /* No destructor defined for onconf */
++#line 2045 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 85:
+-#line 241 "parse.y"
++#line 241 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteCreateForeignKey(pParse, yymsp[-6].minor.yy320, &yymsp[-3].minor.yy298, yymsp[-2].minor.yy320, yymsp[-1].minor.yy372);
+ sqliteDeferForeignKey(pParse, yymsp[0].minor.yy372);
+ }
+-#line 2360 "parse.c"
+- /* No destructor defined for FOREIGN */
+- /* No destructor defined for KEY */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
+- /* No destructor defined for REFERENCES */
+- break;
+- case 86:
+-#line 246 "parse.y"
+-{yygotominor.yy372 = 0;}
+-#line 2370 "parse.c"
+- break;
+- case 87:
+-#line 247 "parse.y"
+-{yygotominor.yy372 = yymsp[0].minor.yy372;}
+-#line 2375 "parse.c"
++#line 2053 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 88:
+-#line 255 "parse.y"
+-{ yygotominor.yy372 = OE_Default; }
+-#line 2380 "parse.c"
+- break;
+- case 89:
+-#line 256 "parse.y"
+-{ yygotominor.yy372 = yymsp[0].minor.yy372; }
+-#line 2385 "parse.c"
+- /* No destructor defined for ON */
+- /* No destructor defined for CONFLICT */
+- break;
+ case 90:
+-#line 257 "parse.y"
++#line 255 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Default; }
+-#line 2392 "parse.c"
++#line 2059 "ext/sqlite/libsqlite/src/parse.c"
+ break;
++ case 89:
+ case 91:
+-#line 258 "parse.y"
++#line 256 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = yymsp[0].minor.yy372; }
+-#line 2397 "parse.c"
+- /* No destructor defined for OR */
++#line 2065 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 92:
+-#line 259 "parse.y"
++#line 259 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Rollback; }
+-#line 2403 "parse.c"
+- /* No destructor defined for ROLLBACK */
++#line 2070 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 93:
+-#line 260 "parse.y"
++ case 236:
++#line 260 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Abort; }
+-#line 2409 "parse.c"
+- /* No destructor defined for ABORT */
++#line 2076 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 94:
+-#line 261 "parse.y"
++#line 261 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Fail; }
+-#line 2415 "parse.c"
+- /* No destructor defined for FAIL */
++#line 2081 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 95:
+-#line 262 "parse.y"
++#line 262 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Ignore; }
+-#line 2421 "parse.c"
+- /* No destructor defined for IGNORE */
++#line 2086 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 96:
+-#line 263 "parse.y"
++#line 263 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_Replace; }
+-#line 2427 "parse.c"
+- /* No destructor defined for REPLACE */
++#line 2091 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 97:
+-#line 267 "parse.y"
++#line 267 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteDropTable(pParse,&yymsp[0].minor.yy298,0);}
+-#line 2433 "parse.c"
+- /* No destructor defined for DROP */
+- /* No destructor defined for TABLE */
++#line 2096 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 98:
+-#line 271 "parse.y"
++#line 271 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteCreateView(pParse, &yymsp[-5].minor.yy0, &yymsp[-2].minor.yy298, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);
+ }
+-#line 2442 "parse.c"
+- /* No destructor defined for VIEW */
+- /* No destructor defined for AS */
++#line 2103 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 99:
+-#line 274 "parse.y"
++#line 274 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteDropTable(pParse, &yymsp[0].minor.yy298, 1);
+ }
+-#line 2451 "parse.c"
+- /* No destructor defined for DROP */
+- /* No destructor defined for VIEW */
++#line 2110 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 100:
+-#line 280 "parse.y"
++#line 280 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteSelect(pParse, yymsp[0].minor.yy179, SRT_Callback, 0, 0, 0, 0);
+ sqliteSelectDelete(yymsp[0].minor.yy179);
+ }
+-#line 2461 "parse.c"
++#line 2118 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 101:
+-#line 290 "parse.y"
++ case 125:
++#line 290 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy179 = yymsp[0].minor.yy179;}
+-#line 2466 "parse.c"
++#line 2124 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 102:
+-#line 291 "parse.y"
++#line 291 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ if( yymsp[0].minor.yy179 ){
+ yymsp[0].minor.yy179->op = yymsp[-1].minor.yy372;
+@@ -2474,137 +2130,107 @@
+ }
+ yygotominor.yy179 = yymsp[0].minor.yy179;
+ }
+-#line 2477 "parse.c"
++#line 2135 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 103:
+-#line 299 "parse.y"
++#line 299 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_UNION;}
+-#line 2482 "parse.c"
+- /* No destructor defined for UNION */
++#line 2140 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 104:
+-#line 300 "parse.y"
++#line 300 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_ALL;}
+-#line 2488 "parse.c"
+- /* No destructor defined for UNION */
+- /* No destructor defined for ALL */
++#line 2145 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 105:
+-#line 301 "parse.y"
++#line 301 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_INTERSECT;}
+-#line 2495 "parse.c"
+- /* No destructor defined for INTERSECT */
++#line 2150 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 106:
+-#line 302 "parse.y"
++#line 302 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_EXCEPT;}
+-#line 2501 "parse.c"
+- /* No destructor defined for EXCEPT */
++#line 2155 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 107:
+-#line 304 "parse.y"
++#line 304 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy179 = sqliteSelectNew(yymsp[-6].minor.yy322,yymsp[-5].minor.yy307,yymsp[-4].minor.yy242,yymsp[-3].minor.yy322,yymsp[-2].minor.yy242,yymsp[-1].minor.yy322,yymsp[-7].minor.yy372,yymsp[0].minor.yy124.limit,yymsp[0].minor.yy124.offset);
+ }
+-#line 2509 "parse.c"
+- /* No destructor defined for SELECT */
+- break;
+- case 108:
+-#line 312 "parse.y"
+-{yygotominor.yy372 = 1;}
+-#line 2515 "parse.c"
+- /* No destructor defined for DISTINCT */
+- break;
+- case 109:
+-#line 313 "parse.y"
+-{yygotominor.yy372 = 0;}
+-#line 2521 "parse.c"
+- /* No destructor defined for ALL */
+- break;
+- case 110:
+-#line 314 "parse.y"
+-{yygotominor.yy372 = 0;}
+-#line 2527 "parse.c"
++#line 2162 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 111:
+-#line 325 "parse.y"
++#line 325 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = yymsp[-1].minor.yy322;}
+-#line 2532 "parse.c"
+- /* No destructor defined for COMMA */
++#line 2167 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 112:
+-#line 326 "parse.y"
++ case 138:
++ case 148:
++#line 326 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = 0;}
+-#line 2538 "parse.c"
++#line 2174 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 113:
+-#line 327 "parse.y"
++#line 327 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[-1].minor.yy242,yymsp[0].minor.yy298.n?&yymsp[0].minor.yy298:0);
+ }
+-#line 2545 "parse.c"
++#line 2181 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 114:
+-#line 330 "parse.y"
++#line 330 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(yymsp[-1].minor.yy322, sqliteExpr(TK_ALL, 0, 0, 0), 0);
+ }
+-#line 2552 "parse.c"
+- /* No destructor defined for STAR */
++#line 2188 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 115:
+-#line 333 "parse.y"
++#line 333 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0);
+ Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
+ yygotominor.yy322 = sqliteExprListAppend(yymsp[-3].minor.yy322, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0);
+ }
+-#line 2562 "parse.c"
+- /* No destructor defined for DOT */
+- /* No destructor defined for STAR */
++#line 2197 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 116:
+-#line 343 "parse.y"
+-{ yygotominor.yy298 = yymsp[0].minor.yy298; }
+-#line 2569 "parse.c"
+- /* No destructor defined for AS */
+- break;
+ case 117:
+-#line 344 "parse.y"
++ case 288:
++#line 343 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy298 = yymsp[0].minor.yy298; }
+-#line 2575 "parse.c"
++#line 2204 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 118:
+-#line 345 "parse.y"
++#line 345 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy298.n = 0; }
+-#line 2580 "parse.c"
++#line 2209 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 119:
+-#line 357 "parse.y"
++#line 357 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy307 = sqliteMalloc(sizeof(*yygotominor.yy307));}
+-#line 2585 "parse.c"
++#line 2214 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 120:
+-#line 358 "parse.y"
++#line 358 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy307 = yymsp[0].minor.yy307;}
+-#line 2590 "parse.c"
+- /* No destructor defined for FROM */
++#line 2219 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 121:
+-#line 363 "parse.y"
++#line 363 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy307 = yymsp[-1].minor.yy307;
+ if( yygotominor.yy307 && yygotominor.yy307->nSrc>0 ) yygotominor.yy307->a[yygotominor.yy307->nSrc-1].jointype = yymsp[0].minor.yy372;
+ }
+-#line 2599 "parse.c"
++#line 2227 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 122:
+-#line 367 "parse.y"
++#line 367 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy307 = 0;}
+-#line 2604 "parse.c"
++#line 2232 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 123:
+-#line 368 "parse.y"
++#line 368 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy307 = sqliteSrcListAppend(yymsp[-5].minor.yy307,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298);
+ if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298);
+@@ -2617,10 +2243,10 @@
+ else { sqliteIdListDelete(yymsp[0].minor.yy320); }
+ }
+ }
+-#line 2620 "parse.c"
++#line 2248 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 124:
+-#line 381 "parse.y"
++#line 381 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy307 = sqliteSrcListAppend(yymsp[-6].minor.yy307,0,0);
+ yygotominor.yy307->a[yygotominor.yy307->nSrc-1].pSelect = yymsp[-4].minor.yy179;
+@@ -2634,330 +2260,227 @@
+ else { sqliteIdListDelete(yymsp[0].minor.yy320); }
+ }
+ }
+-#line 2637 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
+- break;
+- case 125:
+-#line 401 "parse.y"
+-{yygotominor.yy179 = yymsp[0].minor.yy179;}
+-#line 2644 "parse.c"
++#line 2265 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 126:
+-#line 402 "parse.y"
++#line 402 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy179 = sqliteSelectNew(0,yymsp[0].minor.yy307,0,0,0,0,0,-1,0);
+ }
+-#line 2651 "parse.c"
++#line 2272 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 127:
+-#line 407 "parse.y"
++#line 407 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy298.z=0; yygotominor.yy298.n=0;}
+-#line 2656 "parse.c"
+- break;
+- case 128:
+-#line 408 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy298;}
+-#line 2661 "parse.c"
+- /* No destructor defined for DOT */
++#line 2277 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 129:
+-#line 412 "parse.y"
+-{ yygotominor.yy372 = JT_INNER; }
+-#line 2667 "parse.c"
+- /* No destructor defined for COMMA */
+- break;
+ case 130:
+-#line 413 "parse.y"
++#line 412 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = JT_INNER; }
+-#line 2673 "parse.c"
+- /* No destructor defined for JOIN */
++#line 2283 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 131:
+-#line 414 "parse.y"
++#line 414 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+-#line 2679 "parse.c"
+- /* No destructor defined for JOIN */
++#line 2288 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 132:
+-#line 415 "parse.y"
++#line 415 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy298,0); }
+-#line 2685 "parse.c"
+- /* No destructor defined for JOIN */
++#line 2293 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 133:
+-#line 417 "parse.y"
++#line 417 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298); }
+-#line 2691 "parse.c"
+- /* No destructor defined for JOIN */
++#line 2298 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 134:
+-#line 421 "parse.y"
++ case 142:
++ case 151:
++ case 158:
++ case 227:
++ case 229:
++ case 233:
++#line 421 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 2697 "parse.c"
+- /* No destructor defined for ON */
++#line 2309 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 135:
+-#line 422 "parse.y"
++ case 150:
++ case 157:
++ case 228:
++ case 230:
++ case 234:
++#line 422 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = 0;}
+-#line 2703 "parse.c"
++#line 2319 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 136:
+-#line 426 "parse.y"
++ case 169:
++ case 239:
++#line 426 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy320 = yymsp[-1].minor.yy320;}
+-#line 2708 "parse.c"
+- /* No destructor defined for USING */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 2326 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 137:
+-#line 427 "parse.y"
++ case 168:
++ case 238:
++#line 427 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy320 = 0;}
+-#line 2716 "parse.c"
+- break;
+- case 138:
+-#line 437 "parse.y"
+-{yygotominor.yy322 = 0;}
+-#line 2721 "parse.c"
++#line 2333 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 139:
+-#line 438 "parse.y"
++ case 149:
++#line 438 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = yymsp[0].minor.yy322;}
+-#line 2726 "parse.c"
+- /* No destructor defined for ORDER */
+- /* No destructor defined for BY */
++#line 2339 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 140:
+-#line 439 "parse.y"
++#line 439 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[-2].minor.yy242,0);
+ if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
+ }
+-#line 2736 "parse.c"
+- /* No destructor defined for COMMA */
++#line 2347 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 141:
+-#line 443 "parse.y"
++#line 443 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(0,yymsp[-2].minor.yy242,0);
+ if( yygotominor.yy322 ) yygotominor.yy322->a[0].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
+ }
+-#line 2745 "parse.c"
+- break;
+- case 142:
+-#line 447 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 2750 "parse.c"
++#line 2355 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 143:
+-#line 452 "parse.y"
++ case 145:
++#line 452 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = SQLITE_SO_ASC;}
+-#line 2755 "parse.c"
+- /* No destructor defined for ASC */
++#line 2361 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 144:
+-#line 453 "parse.y"
++#line 453 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = SQLITE_SO_DESC;}
+-#line 2761 "parse.c"
+- /* No destructor defined for DESC */
+- break;
+- case 145:
+-#line 454 "parse.y"
+-{yygotominor.yy372 = SQLITE_SO_ASC;}
+-#line 2767 "parse.c"
++#line 2366 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 146:
+-#line 455 "parse.y"
++#line 455 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = SQLITE_SO_UNK;}
+-#line 2772 "parse.c"
++#line 2371 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 147:
+-#line 456 "parse.y"
++#line 456 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n);}
+-#line 2777 "parse.c"
+- /* No destructor defined for COLLATE */
+- break;
+- case 148:
+-#line 460 "parse.y"
+-{yygotominor.yy322 = 0;}
+-#line 2783 "parse.c"
+- break;
+- case 149:
+-#line 461 "parse.y"
+-{yygotominor.yy322 = yymsp[0].minor.yy322;}
+-#line 2788 "parse.c"
+- /* No destructor defined for GROUP */
+- /* No destructor defined for BY */
+- break;
+- case 150:
+-#line 465 "parse.y"
+-{yygotominor.yy242 = 0;}
+-#line 2795 "parse.c"
+- break;
+- case 151:
+-#line 466 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 2800 "parse.c"
+- /* No destructor defined for HAVING */
++#line 2376 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 152:
+-#line 469 "parse.y"
++#line 469 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy124.limit = -1; yygotominor.yy124.offset = 0;}
+-#line 2806 "parse.c"
++#line 2381 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 153:
+-#line 470 "parse.y"
++#line 470 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = 0;}
+-#line 2811 "parse.c"
+- /* No destructor defined for LIMIT */
++#line 2386 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 154:
+-#line 472 "parse.y"
++#line 472 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy124.limit = yymsp[-2].minor.yy372; yygotominor.yy124.offset = yymsp[0].minor.yy372;}
+-#line 2817 "parse.c"
+- /* No destructor defined for LIMIT */
+- /* No destructor defined for OFFSET */
++#line 2391 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 155:
+-#line 474 "parse.y"
++#line 474 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = yymsp[-2].minor.yy372;}
+-#line 2824 "parse.c"
+- /* No destructor defined for LIMIT */
+- /* No destructor defined for COMMA */
++#line 2396 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 156:
+-#line 478 "parse.y"
++#line 478 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298), yymsp[0].minor.yy242);
+ }
+-#line 2833 "parse.c"
+- /* No destructor defined for DELETE */
+- /* No destructor defined for FROM */
+- break;
+- case 157:
+-#line 485 "parse.y"
+-{yygotominor.yy242 = 0;}
+-#line 2840 "parse.c"
+- break;
+- case 158:
+-#line 486 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 2845 "parse.c"
+- /* No destructor defined for WHERE */
++#line 2403 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 159:
+-#line 494 "parse.y"
++#line 494 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteUpdate(pParse,sqliteSrcListAppend(0,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298),yymsp[-1].minor.yy322,yymsp[0].minor.yy242,yymsp[-5].minor.yy372);}
+-#line 2851 "parse.c"
+- /* No destructor defined for UPDATE */
+- /* No destructor defined for SET */
++#line 2408 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 160:
+-#line 497 "parse.y"
++#line 497 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);}
+-#line 2858 "parse.c"
+- /* No destructor defined for COMMA */
+- /* No destructor defined for EQ */
++#line 2413 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 161:
+-#line 498 "parse.y"
++#line 498 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);}
+-#line 2865 "parse.c"
+- /* No destructor defined for EQ */
++#line 2418 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 162:
+-#line 504 "parse.y"
++#line 504 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298), yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy320, yymsp[-8].minor.yy372);}
+-#line 2871 "parse.c"
+- /* No destructor defined for INTO */
+- /* No destructor defined for VALUES */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 2423 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 163:
+-#line 506 "parse.y"
++#line 506 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298), 0, yymsp[0].minor.yy179, yymsp[-1].minor.yy320, yymsp[-5].minor.yy372);}
+-#line 2880 "parse.c"
+- /* No destructor defined for INTO */
+- break;
+- case 164:
+-#line 509 "parse.y"
+-{yygotominor.yy372 = yymsp[0].minor.yy372;}
+-#line 2886 "parse.c"
+- /* No destructor defined for INSERT */
++#line 2428 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 165:
+-#line 510 "parse.y"
++#line 510 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = OE_Replace;}
+-#line 2892 "parse.c"
+- /* No destructor defined for REPLACE */
++#line 2433 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 166:
+-#line 516 "parse.y"
++ case 231:
++#line 516 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);}
+-#line 2898 "parse.c"
+- /* No destructor defined for COMMA */
++#line 2439 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 167:
+-#line 517 "parse.y"
++ case 232:
++#line 517 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);}
+-#line 2904 "parse.c"
+- break;
+- case 168:
+-#line 524 "parse.y"
+-{yygotominor.yy320 = 0;}
+-#line 2909 "parse.c"
+- break;
+- case 169:
+-#line 525 "parse.y"
+-{yygotominor.yy320 = yymsp[-1].minor.yy320;}
+-#line 2914 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 2445 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 170:
+-#line 526 "parse.y"
++ case 240:
++#line 526 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);}
+-#line 2921 "parse.c"
+- /* No destructor defined for COMMA */
++#line 2451 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 171:
+-#line 527 "parse.y"
++ case 241:
++#line 527 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);}
+-#line 2927 "parse.c"
++#line 2457 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 172:
+-#line 535 "parse.y"
++#line 535 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = yymsp[-1].minor.yy242; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+-#line 2932 "parse.c"
++#line 2462 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 173:
+-#line 536 "parse.y"
++#line 536 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_NULL, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2937 "parse.c"
++#line 2467 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 174:
+-#line 537 "parse.y"
+-{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2942 "parse.c"
+- break;
+ case 175:
+-#line 538 "parse.y"
++#line 537 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2947 "parse.c"
++#line 2473 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 176:
+-#line 539 "parse.y"
++#line 539 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
+ Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298);
+ yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp2, 0);
+ }
+-#line 2956 "parse.c"
+- /* No destructor defined for DOT */
++#line 2482 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 177:
+-#line 544 "parse.y"
++#line 544 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-4].minor.yy298);
+ Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
+@@ -2965,126 +2488,109 @@
+ Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0);
+ yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp4, 0);
+ }
+-#line 2968 "parse.c"
+- /* No destructor defined for DOT */
+- /* No destructor defined for DOT */
++#line 2493 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 178:
+-#line 551 "parse.y"
++#line 551 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_INTEGER, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2975 "parse.c"
++#line 2498 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 179:
+-#line 552 "parse.y"
++#line 552 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_FLOAT, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2980 "parse.c"
++#line 2503 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 180:
+-#line 553 "parse.y"
++#line 553 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_STRING, 0, 0, &yymsp[0].minor.yy0);}
+-#line 2985 "parse.c"
++#line 2508 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 181:
+-#line 554 "parse.y"
++#line 554 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_VARIABLE, 0, 0, &yymsp[0].minor.yy0);
+ if( yygotominor.yy242 ) yygotominor.yy242->iTable = ++pParse->nVar;
+ }
+-#line 2993 "parse.c"
++#line 2516 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 182:
+-#line 558 "parse.y"
++#line 558 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExprFunction(yymsp[-1].minor.yy322, &yymsp[-3].minor.yy0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ }
+-#line 3001 "parse.c"
+- /* No destructor defined for LP */
++#line 2524 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 183:
+-#line 562 "parse.y"
++#line 562 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExprFunction(0, &yymsp[-3].minor.yy0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ }
+-#line 3010 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for STAR */
++#line 2532 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 184:
+-#line 566 "parse.y"
++#line 566 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_AND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3017 "parse.c"
+- /* No destructor defined for AND */
++#line 2537 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 185:
+-#line 567 "parse.y"
++#line 567 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_OR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3023 "parse.c"
+- /* No destructor defined for OR */
++#line 2542 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 186:
+-#line 568 "parse.y"
++#line 568 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_LT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3029 "parse.c"
+- /* No destructor defined for LT */
++#line 2547 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 187:
+-#line 569 "parse.y"
++#line 569 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_GT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3035 "parse.c"
+- /* No destructor defined for GT */
++#line 2552 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 188:
+-#line 570 "parse.y"
++#line 570 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_LE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3041 "parse.c"
+- /* No destructor defined for LE */
++#line 2557 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 189:
+-#line 571 "parse.y"
++#line 571 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_GE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3047 "parse.c"
+- /* No destructor defined for GE */
++#line 2562 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 190:
+-#line 572 "parse.y"
++#line 572 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_NE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3053 "parse.c"
+- /* No destructor defined for NE */
++#line 2567 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 191:
+-#line 573 "parse.y"
++#line 573 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_EQ, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3059 "parse.c"
+- /* No destructor defined for EQ */
++#line 2572 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 192:
+-#line 574 "parse.y"
++#line 574 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_BITAND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3065 "parse.c"
+- /* No destructor defined for BITAND */
++#line 2577 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 193:
+-#line 575 "parse.y"
++#line 575 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_BITOR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3071 "parse.c"
+- /* No destructor defined for BITOR */
++#line 2582 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 194:
+-#line 576 "parse.y"
++#line 576 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_LSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3077 "parse.c"
+- /* No destructor defined for LSHIFT */
++#line 2587 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 195:
+-#line 577 "parse.y"
++#line 577 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_RSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3083 "parse.c"
+- /* No destructor defined for RSHIFT */
++#line 2592 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 196:
+-#line 578 "parse.y"
++#line 578 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
+ pList = sqliteExprListAppend(pList, yymsp[-2].minor.yy242, 0);
+@@ -3092,10 +2598,10 @@
+ if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-2].minor.yy242->span, &yymsp[0].minor.yy242->span);
+ }
+-#line 3095 "parse.c"
++#line 2603 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 197:
+-#line 585 "parse.y"
++#line 585 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
+ pList = sqliteExprListAppend(pList, yymsp[-3].minor.yy242, 0);
+@@ -3104,144 +2610,131 @@
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy242->span);
+ }
+-#line 3107 "parse.c"
+- /* No destructor defined for NOT */
++#line 2615 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 198:
+-#line 594 "parse.y"
++#line 594 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_LIKE;}
+-#line 3113 "parse.c"
+- /* No destructor defined for LIKE */
++#line 2620 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 199:
+-#line 595 "parse.y"
++#line 595 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy372 = TK_GLOB;}
+-#line 3119 "parse.c"
+- /* No destructor defined for GLOB */
++#line 2625 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 200:
+-#line 596 "parse.y"
++#line 596 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_PLUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3125 "parse.c"
+- /* No destructor defined for PLUS */
++#line 2630 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 201:
+-#line 597 "parse.y"
++#line 597 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_MINUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3131 "parse.c"
+- /* No destructor defined for MINUS */
++#line 2635 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 202:
+-#line 598 "parse.y"
++#line 598 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_STAR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3137 "parse.c"
+- /* No destructor defined for STAR */
++#line 2640 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 203:
+-#line 599 "parse.y"
++#line 599 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_SLASH, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3143 "parse.c"
+- /* No destructor defined for SLASH */
++#line 2645 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 204:
+-#line 600 "parse.y"
++#line 600 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_REM, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3149 "parse.c"
+- /* No destructor defined for REM */
++#line 2650 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 205:
+-#line 601 "parse.y"
++#line 601 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy242 = sqliteExpr(TK_CONCAT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
+-#line 3155 "parse.c"
+- /* No destructor defined for CONCAT */
++#line 2655 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 206:
+-#line 602 "parse.y"
++#line 602 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-1].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3164 "parse.c"
++#line 2663 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 207:
+-#line 606 "parse.y"
++#line 606 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-2].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3172 "parse.c"
+- /* No destructor defined for IS */
++#line 2671 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 208:
+-#line 610 "parse.y"
++#line 610 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-1].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3181 "parse.c"
++#line 2679 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 209:
+-#line 614 "parse.y"
++#line 614 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-2].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3189 "parse.c"
+- /* No destructor defined for NOT */
++#line 2687 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 210:
+-#line 618 "parse.y"
++#line 618 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-3].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3198 "parse.c"
+- /* No destructor defined for IS */
+- /* No destructor defined for NOT */
++#line 2695 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 211:
+-#line 622 "parse.y"
++#line 622 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yymsp[0].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
+ }
+-#line 3208 "parse.c"
++#line 2703 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 212:
+-#line 626 "parse.y"
++#line 626 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_BITNOT, yymsp[0].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
+ }
+-#line 3216 "parse.c"
++#line 2711 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 213:
+-#line 630 "parse.y"
++#line 630 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_UMINUS, yymsp[0].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
+ }
+-#line 3224 "parse.c"
++#line 2719 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 214:
+-#line 634 "parse.y"
++#line 634 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_UPLUS, yymsp[0].minor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
+ }
+-#line 3232 "parse.c"
++#line 2727 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 215:
+-#line 638 "parse.y"
++#line 638 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ }
+-#line 3241 "parse.c"
++#line 2736 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 216:
+-#line 643 "parse.y"
++#line 643 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
+ pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
+@@ -3249,12 +2742,10 @@
+ if( yygotominor.yy242 ) yygotominor.yy242->pList = pList;
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy242->span);
+ }
+-#line 3252 "parse.c"
+- /* No destructor defined for BETWEEN */
+- /* No destructor defined for AND */
++#line 2747 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 217:
+-#line 650 "parse.y"
++#line 650 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
+ pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
+@@ -3263,72 +2754,58 @@
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy242->span);
+ }
+-#line 3266 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for BETWEEN */
+- /* No destructor defined for AND */
++#line 2759 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 218:
+-#line 658 "parse.y"
++#line 658 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3278 "parse.c"
+- /* No destructor defined for IN */
+- /* No destructor defined for LP */
++#line 2768 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 219:
+-#line 663 "parse.y"
++#line 663 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3289 "parse.c"
+- /* No destructor defined for IN */
+- /* No destructor defined for LP */
++#line 2777 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 220:
+-#line 668 "parse.y"
++#line 668 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3301 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for IN */
+- /* No destructor defined for LP */
++#line 2787 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 221:
+-#line 674 "parse.y"
++#line 674 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
+ }
+-#line 3314 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for IN */
+- /* No destructor defined for LP */
++#line 2797 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 222:
+-#line 680 "parse.y"
++#line 680 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-3].minor.yy242, 0, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298);
+ }
+-#line 3327 "parse.c"
+- /* No destructor defined for IN */
++#line 2807 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 223:
+-#line 686 "parse.y"
++#line 686 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
+ yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
+@@ -3336,489 +2813,298 @@
+ yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
+ sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298);
+ }
+-#line 3339 "parse.c"
+- /* No destructor defined for NOT */
+- /* No destructor defined for IN */
++#line 2818 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 224:
+-#line 696 "parse.y"
++#line 696 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_CASE, yymsp[-3].minor.yy242, yymsp[-1].minor.yy242, 0);
+ if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-2].minor.yy322;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+ }
+-#line 3350 "parse.c"
++#line 2827 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 225:
+-#line 703 "parse.y"
++#line 703 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322, yymsp[-2].minor.yy242, 0);
+ yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
+ }
+-#line 3358 "parse.c"
+- /* No destructor defined for WHEN */
+- /* No destructor defined for THEN */
++#line 2835 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 226:
+-#line 707 "parse.y"
++#line 707 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy322 = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
+ yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
+ }
+-#line 3368 "parse.c"
+- /* No destructor defined for WHEN */
+- /* No destructor defined for THEN */
+- break;
+- case 227:
+-#line 712 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 3375 "parse.c"
+- /* No destructor defined for ELSE */
+- break;
+- case 228:
+-#line 713 "parse.y"
+-{yygotominor.yy242 = 0;}
+-#line 3381 "parse.c"
+- break;
+- case 229:
+-#line 715 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 3386 "parse.c"
+- break;
+- case 230:
+-#line 716 "parse.y"
+-{yygotominor.yy242 = 0;}
+-#line 3391 "parse.c"
+- break;
+- case 231:
+-#line 724 "parse.y"
+-{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);}
+-#line 3396 "parse.c"
+- /* No destructor defined for COMMA */
+- break;
+- case 232:
+-#line 725 "parse.y"
+-{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);}
+-#line 3402 "parse.c"
+- break;
+- case 233:
+-#line 726 "parse.y"
+-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+-#line 3407 "parse.c"
+- break;
+- case 234:
+-#line 727 "parse.y"
+-{yygotominor.yy242 = 0;}
+-#line 3412 "parse.c"
++#line 2843 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 235:
+-#line 732 "parse.y"
++#line 732 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-5].minor.yy298, &yymsp[-4].minor.yy298);
+ if( yymsp[-9].minor.yy372!=OE_None ) yymsp[-9].minor.yy372 = yymsp[0].minor.yy372;
+ if( yymsp[-9].minor.yy372==OE_Default) yymsp[-9].minor.yy372 = OE_Abort;
+ sqliteCreateIndex(pParse, &yymsp[-7].minor.yy298, pSrc, yymsp[-2].minor.yy320, yymsp[-9].minor.yy372, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+ }
+-#line 3422 "parse.c"
+- /* No destructor defined for INDEX */
+- /* No destructor defined for ON */
+- /* No destructor defined for LP */
+- break;
+- case 236:
+-#line 740 "parse.y"
+-{ yygotominor.yy372 = OE_Abort; }
+-#line 3430 "parse.c"
+- /* No destructor defined for UNIQUE */
++#line 2853 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 237:
+-#line 741 "parse.y"
++#line 741 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = OE_None; }
+-#line 3436 "parse.c"
+- break;
+- case 238:
+-#line 749 "parse.y"
+-{yygotominor.yy320 = 0;}
+-#line 3441 "parse.c"
+- break;
+- case 239:
+-#line 750 "parse.y"
+-{yygotominor.yy320 = yymsp[-1].minor.yy320;}
+-#line 3446 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
+- break;
+- case 240:
+-#line 751 "parse.y"
+-{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);}
+-#line 3453 "parse.c"
+- /* No destructor defined for COMMA */
+- break;
+- case 241:
+-#line 752 "parse.y"
+-{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);}
+-#line 3459 "parse.c"
+- break;
+- case 242:
+-#line 753 "parse.y"
+-{yygotominor.yy298 = yymsp[-1].minor.yy298;}
+-#line 3464 "parse.c"
+- /* No destructor defined for sortorder */
++#line 2858 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 243:
+-#line 758 "parse.y"
++#line 758 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteDropIndex(pParse, sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298));
+ }
+-#line 3472 "parse.c"
+- /* No destructor defined for DROP */
+- /* No destructor defined for INDEX */
++#line 2865 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 244:
+-#line 766 "parse.y"
++#line 766 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298),&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0,yymsp[-7].minor.yy372);}
+-#line 3479 "parse.c"
+- /* No destructor defined for COPY */
+- /* No destructor defined for FROM */
+- /* No destructor defined for USING */
+- /* No destructor defined for DELIMITERS */
++#line 2870 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 245:
+-#line 768 "parse.y"
++#line 768 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298),&yymsp[0].minor.yy298,0,yymsp[-4].minor.yy372);}
+-#line 3488 "parse.c"
+- /* No destructor defined for COPY */
+- /* No destructor defined for FROM */
++#line 2875 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 246:
+-#line 772 "parse.y"
++#line 772 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteVacuum(pParse,0);}
+-#line 3495 "parse.c"
+- /* No destructor defined for VACUUM */
++#line 2880 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 247:
+-#line 773 "parse.y"
++#line 773 "ext/sqlite/libsqlite/src/parse.y"
+ {sqliteVacuum(pParse,&yymsp[0].minor.yy298);}
+-#line 3501 "parse.c"
+- /* No destructor defined for VACUUM */
++#line 2885 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 248:
+-#line 777 "parse.y"
++ case 250:
++#line 777 "ext/sqlite/libsqlite/src/parse.y"
+ {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);}
+-#line 3507 "parse.c"
+- /* No destructor defined for PRAGMA */
+- /* No destructor defined for EQ */
++#line 2891 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 249:
+-#line 778 "parse.y"
++#line 778 "ext/sqlite/libsqlite/src/parse.y"
+ {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy0,0);}
+-#line 3514 "parse.c"
+- /* No destructor defined for PRAGMA */
+- /* No destructor defined for EQ */
+- break;
+- case 250:
+-#line 779 "parse.y"
+-{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);}
+-#line 3521 "parse.c"
+- /* No destructor defined for PRAGMA */
+- /* No destructor defined for EQ */
++#line 2896 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 251:
+-#line 780 "parse.y"
++#line 780 "ext/sqlite/libsqlite/src/parse.y"
+ {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,1);}
+-#line 3528 "parse.c"
+- /* No destructor defined for PRAGMA */
+- /* No destructor defined for EQ */
++#line 2901 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 252:
+-#line 781 "parse.y"
++#line 781 "ext/sqlite/libsqlite/src/parse.y"
+ {sqlitePragma(pParse,&yymsp[-3].minor.yy298,&yymsp[-1].minor.yy298,0);}
+-#line 3535 "parse.c"
+- /* No destructor defined for PRAGMA */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 2906 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 253:
+-#line 782 "parse.y"
++#line 782 "ext/sqlite/libsqlite/src/parse.y"
+ {sqlitePragma(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298,0);}
+-#line 3543 "parse.c"
+- /* No destructor defined for PRAGMA */
+- break;
+- case 254:
+-#line 783 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy298;}
+-#line 3549 "parse.c"
+- /* No destructor defined for plus_opt */
+- break;
+- case 255:
+-#line 784 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy298;}
+-#line 3555 "parse.c"
+- /* No destructor defined for MINUS */
+- break;
+- case 256:
+-#line 785 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 3561 "parse.c"
+- break;
+- case 257:
+-#line 786 "parse.y"
+-{yygotominor.yy298 = yymsp[0].minor.yy0;}
+-#line 3566 "parse.c"
+- break;
+- case 258:
+- /* No destructor defined for PLUS */
+- break;
+- case 259:
++#line 2911 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 260:
+-#line 792 "parse.y"
++#line 792 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ Token all;
+ all.z = yymsp[-4].minor.yy0.z;
+ all.n = (yymsp[0].minor.yy0.z - yymsp[-4].minor.yy0.z) + yymsp[0].minor.yy0.n;
+ sqliteFinishTrigger(pParse, yymsp[-1].minor.yy19, &all);
+ }
+-#line 3581 "parse.c"
+- /* No destructor defined for trigger_decl */
+- /* No destructor defined for BEGIN */
++#line 2921 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 261:
+-#line 800 "parse.y"
++#line 800 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ SrcList *pTab = sqliteSrcListAppend(0, &yymsp[-3].minor.yy298, &yymsp[-2].minor.yy298);
+ sqliteBeginTrigger(pParse, &yymsp[-7].minor.yy298, yymsp[-6].minor.yy372, yymsp[-5].minor.yy290.a, yymsp[-5].minor.yy290.b, pTab, yymsp[-1].minor.yy372, yymsp[0].minor.yy182, yymsp[-9].minor.yy372);
+ }
+-#line 3591 "parse.c"
+- /* No destructor defined for TRIGGER */
+- /* No destructor defined for ON */
++#line 2929 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 262:
+-#line 806 "parse.y"
++ case 265:
++#line 806 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = TK_BEFORE; }
+-#line 3598 "parse.c"
+- /* No destructor defined for BEFORE */
++#line 2935 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 263:
+-#line 807 "parse.y"
++#line 807 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = TK_AFTER; }
+-#line 3604 "parse.c"
+- /* No destructor defined for AFTER */
++#line 2940 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 264:
+-#line 808 "parse.y"
++#line 808 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = TK_INSTEAD;}
+-#line 3610 "parse.c"
+- /* No destructor defined for INSTEAD */
+- /* No destructor defined for OF */
+- break;
+- case 265:
+-#line 809 "parse.y"
+-{ yygotominor.yy372 = TK_BEFORE; }
+-#line 3617 "parse.c"
++#line 2945 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 266:
+-#line 813 "parse.y"
++#line 813 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy290.a = TK_DELETE; yygotominor.yy290.b = 0; }
+-#line 3622 "parse.c"
+- /* No destructor defined for DELETE */
++#line 2950 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 267:
+-#line 814 "parse.y"
++#line 814 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy290.a = TK_INSERT; yygotominor.yy290.b = 0; }
+-#line 3628 "parse.c"
+- /* No destructor defined for INSERT */
++#line 2955 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 268:
+-#line 815 "parse.y"
++#line 815 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = 0;}
+-#line 3634 "parse.c"
+- /* No destructor defined for UPDATE */
++#line 2960 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 269:
+-#line 816 "parse.y"
++#line 816 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = yymsp[0].minor.yy320; }
+-#line 3640 "parse.c"
+- /* No destructor defined for UPDATE */
+- /* No destructor defined for OF */
++#line 2965 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 270:
+-#line 819 "parse.y"
+-{ yygotominor.yy372 = TK_ROW; }
+-#line 3647 "parse.c"
+- break;
+ case 271:
+-#line 820 "parse.y"
++#line 819 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = TK_ROW; }
+-#line 3652 "parse.c"
+- /* No destructor defined for FOR */
+- /* No destructor defined for EACH */
+- /* No destructor defined for ROW */
++#line 2971 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 272:
+-#line 821 "parse.y"
++#line 821 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy372 = TK_STATEMENT; }
+-#line 3660 "parse.c"
+- /* No destructor defined for FOR */
+- /* No destructor defined for EACH */
+- /* No destructor defined for STATEMENT */
++#line 2976 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 273:
+-#line 824 "parse.y"
++#line 824 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy182 = 0; }
+-#line 3668 "parse.c"
++#line 2981 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 274:
+-#line 825 "parse.y"
++#line 825 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy182 = yymsp[0].minor.yy242; }
+-#line 3673 "parse.c"
+- /* No destructor defined for WHEN */
++#line 2986 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 275:
+-#line 829 "parse.y"
++#line 829 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yymsp[-2].minor.yy19->pNext = yymsp[0].minor.yy19;
+ yygotominor.yy19 = yymsp[-2].minor.yy19;
+ }
+-#line 3682 "parse.c"
+- /* No destructor defined for SEMI */
++#line 2994 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 276:
+-#line 833 "parse.y"
++#line 833 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy19 = 0; }
+-#line 3688 "parse.c"
++#line 2999 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 277:
+-#line 839 "parse.y"
++#line 839 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy19 = sqliteTriggerUpdateStep(&yymsp[-3].minor.yy298, yymsp[-1].minor.yy322, yymsp[0].minor.yy242, yymsp[-4].minor.yy372); }
+-#line 3693 "parse.c"
+- /* No destructor defined for UPDATE */
+- /* No destructor defined for SET */
++#line 3004 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 278:
+-#line 844 "parse.y"
++#line 844 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-5].minor.yy298, yymsp[-4].minor.yy320, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy372);}
+-#line 3700 "parse.c"
+- /* No destructor defined for INTO */
+- /* No destructor defined for VALUES */
+- /* No destructor defined for LP */
+- /* No destructor defined for RP */
++#line 3009 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 279:
+-#line 847 "parse.y"
++#line 847 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-2].minor.yy298, yymsp[-1].minor.yy320, 0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);}
+-#line 3709 "parse.c"
+- /* No destructor defined for INTO */
++#line 3014 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 280:
+-#line 851 "parse.y"
++#line 851 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy19 = sqliteTriggerDeleteStep(&yymsp[-1].minor.yy298, yymsp[0].minor.yy242);}
+-#line 3715 "parse.c"
+- /* No destructor defined for DELETE */
+- /* No destructor defined for FROM */
++#line 3019 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 281:
+-#line 854 "parse.y"
++#line 854 "ext/sqlite/libsqlite/src/parse.y"
+ {yygotominor.yy19 = sqliteTriggerSelectStep(yymsp[0].minor.yy179); }
+-#line 3722 "parse.c"
++#line 3024 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 282:
+-#line 857 "parse.y"
++#line 857 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, 0);
+ yygotominor.yy242->iColumn = OE_Ignore;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+ }
+-#line 3731 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for IGNORE */
++#line 3033 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 283:
+-#line 862 "parse.y"
++#line 862 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
+ yygotominor.yy242->iColumn = OE_Rollback;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
+-#line 3742 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for ROLLBACK */
+- /* No destructor defined for COMMA */
++#line 3042 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 284:
+-#line 867 "parse.y"
++#line 867 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
+ yygotominor.yy242->iColumn = OE_Abort;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
+-#line 3754 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for ABORT */
+- /* No destructor defined for COMMA */
++#line 3051 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 285:
+-#line 872 "parse.y"
++#line 872 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
+ yygotominor.yy242->iColumn = OE_Fail;
+ sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
+-#line 3766 "parse.c"
+- /* No destructor defined for LP */
+- /* No destructor defined for FAIL */
+- /* No destructor defined for COMMA */
++#line 3060 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 286:
+-#line 879 "parse.y"
++#line 879 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298));
+ }
+-#line 3776 "parse.c"
+- /* No destructor defined for DROP */
+- /* No destructor defined for TRIGGER */
++#line 3067 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 287:
+-#line 884 "parse.y"
++#line 884 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteAttach(pParse, &yymsp[-3].minor.yy298, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
+ }
+-#line 3785 "parse.c"
+- /* No destructor defined for ATTACH */
+- /* No destructor defined for database_kw_opt */
+- /* No destructor defined for AS */
+- break;
+- case 288:
+-#line 888 "parse.y"
+-{ yygotominor.yy298 = yymsp[0].minor.yy298; }
+-#line 3793 "parse.c"
+- /* No destructor defined for USING */
++#line 3074 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 289:
+-#line 889 "parse.y"
++#line 889 "ext/sqlite/libsqlite/src/parse.y"
+ { yygotominor.yy298.z = 0; yygotominor.yy298.n = 0; }
+-#line 3799 "parse.c"
+- break;
+- case 290:
+- /* No destructor defined for DATABASE */
+- break;
+- case 291:
++#line 3079 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ case 292:
+-#line 895 "parse.y"
++#line 895 "ext/sqlite/libsqlite/src/parse.y"
+ {
+ sqliteDetach(pParse, &yymsp[0].minor.yy298);
+ }
+-#line 3811 "parse.c"
+- /* No destructor defined for DETACH */
+- /* No destructor defined for database_kw_opt */
++#line 3086 "ext/sqlite/libsqlite/src/parse.c"
+ break;
+ };
+ yygoto = yyRuleInfo[yyruleno].lhs;
+ yysize = yyRuleInfo[yyruleno].nrhs;
+ yypParser->yyidx -= yysize;
+- yyact = yy_find_reduce_action(yypParser,yygoto);
++ yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
+ if( yyact < YYNSTATE ){
+- yy_shift(yypParser,yyact,yygoto,&yygotominor);
++#ifdef NDEBUG
++ /* If we are not debugging and the reduce action popped at least
++ ** one element off the stack, then we can push the new element back
++ ** onto the stack here, and skip the stack overflow test in yy_shift().
++ ** That gives a significant speed improvement. */
++ if( yysize ){
++ yypParser->yyidx++;
++ yymsp -= yysize-1;
++ yymsp->stateno = yyact;
++ yymsp->major = yygoto;
++ yymsp->minor = yygotominor;
++ }else
++#endif
++ {
++ yy_shift(yypParser,yyact,yygoto,&yygotominor);
++ }
+ }else if( yyact == YYNSTATE + YYNRULE + 1 ){
+ yy_accept(yypParser);
+ }
+@@ -3852,7 +3138,7 @@
+ ){
+ sqliteParserARG_FETCH;
+ #define TOKEN (yyminor.yy0)
+-#line 23 "parse.y"
++#line 23 "ext/sqlite/libsqlite/src/parse.y"
+
+ if( pParse->zErrMsg==0 ){
+ if( TOKEN.z[0] ){
+@@ -3861,8 +3147,7 @@
+ sqliteErrorMsg(pParse, "incomplete SQL statement");
+ }
+ }
+-
+-#line 3865 "parse.c"
++#line 3153 "ext/sqlite/libsqlite/src/parse.c"
+ sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
+ }
+
+@@ -3918,7 +3203,7 @@
+ /* (re)initialize the parser, if necessary */
+ yypParser = (yyParser*)yyp;
+ if( yypParser->yyidx<0 ){
+- if( yymajor==0 ) return;
++ /* if( yymajor==0 ) return; // not sure why this was here... */
+ yypParser->yyidx = 0;
+ yypParser->yyerrcnt = -1;
+ yypParser->yystack[0].stateno = 0;
+diff -dPNur sqlite-1.0.3/libsqlite/src/parse.y sqlite-svn/libsqlite/src/parse.y
+--- sqlite-1.0.3/libsqlite/src/parse.y 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/parse.y 2012-10-09 13:36:42.531952680 +0000
+@@ -14,7 +14,7 @@
+ ** the parser. Lemon will also generate a header file containing
+ ** numeric codes for all of the tokens.
+ **
+-** @(#) $Id: parse.y,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: parse.y 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ %token_prefix TK_
+ %token_type {Token}
+diff -dPNur sqlite-1.0.3/libsqlite/src/pragma.c sqlite-svn/libsqlite/src/pragma.c
+--- sqlite-1.0.3/libsqlite/src/pragma.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/pragma.c 2012-10-09 13:36:42.531952680 +0000
+@@ -11,7 +11,7 @@
+ *************************************************************************
+ ** This file contains code used to implement the PRAGMA command.
+ **
+-** $Id: pragma.c,v 1.2.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: pragma.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include <ctype.h>
+diff -dPNur sqlite-1.0.3/libsqlite/src/printf.c sqlite-svn/libsqlite/src/printf.c
+--- sqlite-1.0.3/libsqlite/src/printf.c 2004-07-10 11:47:26.000000000 +0000
++++ sqlite-svn/libsqlite/src/printf.c 2012-10-09 13:36:42.531952680 +0000
+@@ -227,6 +227,7 @@
+ int nsd; /* Number of significant digits returned */
+ #endif
+
++ func(arg,"",0);
+ count = length = 0;
+ bufpt = 0;
+ for(; (c=(*fmt))!=0; ++fmt){
+@@ -673,9 +674,11 @@
+ }
+ }
+ }
+- if( pM->zText && nNewChar>0 ){
+- memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
+- pM->nChar += nNewChar;
++ if( pM->zText ){
++ if( nNewChar>0 ){
++ memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
++ pM->nChar += nNewChar;
++ }
+ pM->zText[pM->nChar] = 0;
+ }
+ }
+diff -dPNur sqlite-1.0.3/libsqlite/src/random.c sqlite-svn/libsqlite/src/random.c
+--- sqlite-1.0.3/libsqlite/src/random.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/random.c 2012-10-09 13:36:42.551252050 +0000
+@@ -15,7 +15,7 @@
+ ** Random numbers are used by some of the database backends in order
+ ** to generate random integer keys for tables or random filenames.
+ **
+-** $Id: random.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: random.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include "os.h"
+diff -dPNur sqlite-1.0.3/libsqlite/src/select.c sqlite-svn/libsqlite/src/select.c
+--- sqlite-1.0.3/libsqlite/src/select.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/select.c 2012-10-09 13:36:42.531952680 +0000
+@@ -12,7 +12,7 @@
+ ** This file contains C code routines that are called by the parser
+ ** to handle SELECT statements in SQLite.
+ **
+-** $Id: select.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: select.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+@@ -365,6 +365,30 @@
+ }
+
+ /*
++** 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 = sqliteVdbeCurrentAddr(v) + 2;
++ if( nPop>0 ) addr++;
++ sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
++ if( nPop>0 ){
++ sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
++ }
++ sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
++ }
++ if( p->iLimit>=0 ){
++ sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
++ }
++}
++
++/*
+ ** This routine generates the code for the inside of the inner loop
+ ** of a SELECT.
+ **
+@@ -388,6 +412,7 @@
+ ){
+ Vdbe *v = pParse->pVdbe;
+ int i;
++ int hasDistinct; /* True if the DISTINCT keyword is present */
+
+ if( v==0 ) return 0;
+ assert( pEList!=0 );
+@@ -395,15 +420,9 @@
+ /* If there was a LIMIT clause on the SELECT statement, then do the check
+ ** to see if this row should be output.
+ */
+- if( pOrderBy==0 ){
+- if( p->iOffset>=0 ){
+- int addr = sqliteVdbeCurrentAddr(v);
+- sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
+- sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
+- }
+- if( p->iLimit>=0 ){
+- sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
+- }
++ hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
++ if( pOrderBy==0 && !hasDistinct ){
++ codeLimiter(v, p, iContinue, iBreak, 0);
+ }
+
+ /* Pull the requested columns.
+@@ -423,7 +442,7 @@
+ ** and this row has been seen before, then do not make this row
+ ** part of the result.
+ */
+- if( distinct>=0 && pEList && pEList->nExpr>0 ){
++ if( hasDistinct ){
+ #if NULL_ALWAYS_DISTINCT
+ sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
+ #endif
+@@ -434,6 +453,9 @@
+ sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
+ sqliteVdbeAddOp(v, OP_String, 0, 0);
+ sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
++ if( pOrderBy==0 ){
++ codeLimiter(v, p, iContinue, iBreak, nColumn);
++ }
+ }
+
+ switch( eDest ){
+@@ -570,14 +592,7 @@
+ if( eDest==SRT_Sorter ) return;
+ sqliteVdbeAddOp(v, OP_Sort, 0, 0);
+ addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
+- if( p->iOffset>=0 ){
+- sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
+- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
+- sqliteVdbeAddOp(v, OP_Goto, 0, addr);
+- }
+- if( p->iLimit>=0 ){
+- sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
+- }
++ codeLimiter(v, p, addr, end2, 1);
+ switch( eDest ){
+ case SRT_Callback: {
+ sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
+@@ -810,8 +825,9 @@
+ }else{
+ char zBuf[30];
+ sprintf(zBuf, "column%d", i+1);
+- pTab->aCol[i].zName = sqliteStrDup(zBuf);
++ aCol[i].zName = sqliteStrDup(zBuf);
+ }
++ sqliteDequote(aCol[i].zName);
+ }
+ pTab->iPKey = -1;
+ return pTab;
+@@ -943,11 +959,11 @@
+ /* This expression is a "*" or a "TABLE.*" and needs to be
+ ** expanded. */
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
+- Token *pName; /* text of name of TABLE */
++ char *zTName; /* text of name of TABLE */
+ if( pE->op==TK_DOT && pE->pLeft ){
+- pName = &pE->pLeft->token;
++ zTName = sqliteTableNameFromToken(&pE->pLeft->token);
+ }else{
+- pName = 0;
++ zTName = 0;
+ }
+ for(i=0; i<pTabList->nSrc; i++){
+ Table *pTab = pTabList->a[i].pTab;
+@@ -955,9 +971,8 @@
+ if( zTabName==0 || zTabName[0]==0 ){
+ zTabName = pTab->zName;
+ }
+- if( pName && (zTabName==0 || zTabName[0]==0 ||
+- sqliteStrNICmp(pName->z, zTabName, pName->n)!=0 ||
+- zTabName[pName->n]!=0) ){
++ if( zTName && (zTabName==0 || zTabName[0]==0 ||
++ sqliteStrICmp(zTName, zTabName)!=0) ){
+ continue;
+ }
+ tableSeen = 1;
+@@ -1002,13 +1017,14 @@
+ }
+ }
+ if( !tableSeen ){
+- if( pName ){
+- sqliteErrorMsg(pParse, "no such table: %T", pName);
++ if( zTName ){
++ sqliteErrorMsg(pParse, "no such table: %s", zTName);
+ }else{
+ sqliteErrorMsg(pParse, "no tables specified");
+ }
+ rc = 1;
+ }
++ sqliteFree(zTName);
+ }
+ }
+ sqliteExprListDelete(pEList);
+@@ -1916,6 +1932,12 @@
+ }else{
+ sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
+ sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
++ if( seekOp==OP_Rewind ){
++ sqliteVdbeAddOp(v, OP_String, 0, 0);
++ sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
++ sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
++ seekOp = OP_MoveTo;
++ }
+ sqliteVdbeAddOp(v, seekOp, base+1, 0);
+ sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
+ sqliteVdbeAddOp(v, OP_Close, base+1, 0);
+diff -dPNur sqlite-1.0.3/libsqlite/src/sqlite.h.in sqlite-svn/libsqlite/src/sqlite.h.in
+--- sqlite-1.0.3/libsqlite/src/sqlite.h.in 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/sqlite.h.in 2012-10-09 13:36:42.541252205 +0000
+@@ -12,7 +12,7 @@
+ ** This header file defines the interface that the SQLite library
+ ** presents to client programs.
+ **
+-** @(#) $Id: sqlite.h.in,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: sqlite.h.in 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #ifndef _SQLITE_H_
+ #define _SQLITE_H_
+@@ -28,7 +28,11 @@
+ /*
+ ** The version of the SQLite library.
+ */
+-#define SQLITE_VERSION "--VERS--"
++#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
+@@ -479,10 +483,24 @@
+ int datatype /* The datatype for this function */
+ );
+ #define SQLITE_NUMERIC (-1)
+-#define SQLITE_TEXT (-2)
++/* #define SQLITE_TEXT (-2) // See below */
+ #define SQLITE_ARGS (-3)
+
+ /*
++** SQLite version 3 defines SQLITE_TEXT differently. To allow both
++** version 2 and version 3 to be included, undefine them both if a
++** conflict is seen. Define SQLITE2_TEXT to be the version 2 value.
++*/
++#ifdef SQLITE_TEXT
++# undef SQLITE_TEXT
++#else
++# define SQLITE_TEXT (-2)
++#endif
++#define SQLITE2_TEXT (-2)
++
++
++
++/*
+ ** The user function implementations call one of the following four routines
+ ** in order to return their results. The first parameter to each of these
+ ** routines is a copy of the first argument to xFunc() or xFinialize().
+diff -dPNur sqlite-1.0.3/libsqlite/src/sqlite.w32.h sqlite-svn/libsqlite/src/sqlite.w32.h
+--- sqlite-1.0.3/libsqlite/src/sqlite.w32.h 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/sqlite.w32.h 2012-10-09 13:36:42.551252050 +0000
+@@ -12,7 +12,7 @@
+ ** This header file defines the interface that the SQLite library
+ ** presents to client programs.
+ **
+-** @(#) $Id: sqlite.w32.h,v 1.3.6.3 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: sqlite.w32.h 203289 2005-12-20 15:26:26Z iliaa $
+ */
+ #ifndef _SQLITE_H_
+ #define _SQLITE_H_
+@@ -28,7 +28,7 @@
+ /*
+ ** The version of the SQLite library.
+ */
+-#define SQLITE_VERSION "2.8.14"
++#define SQLITE_VERSION "2.8.17"
+
+ /*
+ ** The version string is also compiled into the library so that a program
+@@ -204,32 +204,6 @@
+ */
+ int sqlite_changes(sqlite*);
+
+-/*
+-** This function returns the number of database rows that were changed
+-** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(),
+-** or by the last VM to run to completion. The change count is not updated
+-** by SQL statements other than INSERT, UPDATE or DELETE.
+-**
+-** Changes are counted, even if they are later undone by a ROLLBACK or
+-** ABORT. Changes associated with trigger programs that execute as a
+-** result of the INSERT, UPDATE, or DELETE statement are not counted.
+-**
+-** If a callback invokes sqlite_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.
+-**
+-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+-*/
+-int sqlite_last_statement_changes(sqlite*);
+-
+ /* If the parameter to this routine is one of the return value constants
+ ** defined above, then this routine returns a constant text string which
+ ** descripts (in English) the meaning of the return value.
+@@ -466,12 +440,13 @@
+ ** Use the following routine to define the datatype returned by a
+ ** user-defined function. The second argument can be one of the
+ ** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it
+-** can be an integer greater than or equal to zero. When the datatype
+-** parameter is non-negative, the type of the result will be the
+-** same as the datatype-th argument. If datatype==SQLITE_NUMERIC
+-** then the result is always numeric. If datatype==SQLITE_TEXT then
+-** the result is always text. If datatype==SQLITE_ARGS then the result
+-** is numeric if any argument is numeric and is text otherwise.
++** can be an integer greater than or equal to zero. The datatype
++** will be numeric or text (the only two types supported) if the
++** argument is SQLITE_NUMERIC or SQLITE_TEXT. If the argument is
++** SQLITE_ARGS, then the datatype is numeric if any argument to the
++** function is numeric and is text otherwise. If the second argument
++** is an integer, then the datatype of the result is the same as the
++** parameter to the function that corresponds to that integer.
+ */
+ int sqlite_function_type(
+ sqlite *db, /* The database there the function is registered */
+@@ -779,88 +754,9 @@
+ ** 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 sqlite_exec() call returns SQLITE_ABORT.
+-**
+-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+ */
+ void sqlite_progress_handler(sqlite*, 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 *sqlite_commit_hook(sqlite*, int(*)(void*), void*);
+-
+-/*
+-** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine
+-** is the same as sqlite_open().
+-**
+-** The code to implement this API is not available in the public release
+-** of SQLite.
+-*/
+-sqlite *sqlite_open_encrypted(
+- const char *zFilename, /* Name of the encrypted database */
+- const void *pKey, /* Pointer to the key */
+- int nKey, /* Number of bytes in the key */
+- int *pErrcode, /* Write error code here */
+- char **pzErrmsg /* Write error message here */
+-);
+-
+-/*
+-** 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 sqlite_rekey(
+- sqlite *db, /* Database to be rekeyed */
+- const void *pKey, int nKey /* The new key */
+-);
+-
+-/*
+-** Encode a binary buffer "in" of size n bytes so that it contains
+-** no instances of characters '\'' or '\000'. The output is
+-** null-terminated and can be used as a string value in an INSERT
+-** or UPDATE statement. Use sqlite_decode_binary() to convert the
+-** string back into its original binary.
+-**
+-** The result is written into a preallocated output buffer "out".
+-** "out" must be able to hold at least 2 +(257*n)/254 bytes.
+-** In other words, the output will be expanded by as much as 3
+-** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
+-** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
+-**
+-** The return value is the number of characters in the encoded
+-** string, excluding the "\000" terminator.
+-**
+-** If out==NULL then no output is generated but the routine still returns
+-** the number of characters that would have been generated if out had
+-** not been NULL.
+-*/
+-int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
+-
+-/*
+-** Decode the string "in" into binary data and write it into "out".
+-** This routine reverses the encoding created by sqlite_encode_binary().
+-** The output will always be a few bytes less than the input. The number
+-** of bytes of output is returned. If the input is not a well-formed
+-** encoding, -1 is returned.
+-**
+-** The "in" and "out" parameters may point to the same buffer in order
+-** to decode a string in place.
+-*/
+-int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
+-
+ #ifdef __cplusplus
+ } /* End of the 'extern "C"' block */
+ #endif
+diff -dPNur sqlite-1.0.3/libsqlite/src/sqliteInt.h sqlite-svn/libsqlite/src/sqliteInt.h
+--- sqlite-1.0.3/libsqlite/src/sqliteInt.h 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/sqliteInt.h 2012-10-09 13:36:42.551252050 +0000
+@@ -11,7 +11,7 @@
+ *************************************************************************
+ ** Internal interface definitions for SQLite.
+ **
+-** @(#) $Id: sqliteInt.h,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** @(#) $Id: sqliteInt.h 203289 2005-12-20 15:26:26Z iliaa $
+ */
+ #include "config.h"
+ #include "sqlite.h"
+@@ -102,6 +102,9 @@
+ #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
+@@ -117,6 +120,7 @@
+ #endif
+ 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 */
+@@ -762,8 +766,8 @@
+ ** now be identified by a database name, a dot, then the table name: ID.ID.
+ */
+ struct SrcList {
+- u16 nSrc; /* Number of tables or subqueries in the FROM clause */
+- u16 nAlloc; /* Number of entries allocated in a[] below */
++ 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 */
+@@ -1116,7 +1120,7 @@
+ #endif
+ char *sqliteMPrintf(const char*, ...);
+ char *sqliteVMPrintf(const char*, va_list);
+-void sqliteSetString(char **, const char *, ...);
++void sqliteSetString(char **, ...);
+ void sqliteSetNString(char **, ...);
+ void sqliteErrorMsg(Parse*, const char*, ...);
+ void sqliteDequote(char*);
+diff -dPNur sqlite-1.0.3/libsqlite/src/tokenize.c sqlite-svn/libsqlite/src/tokenize.c
+--- sqlite-1.0.3/libsqlite/src/tokenize.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/tokenize.c 2012-10-09 13:36:42.541252205 +0000
+@@ -15,7 +15,7 @@
+ ** individual tokens and sends those tokens one-by-one over to the
+ ** parser for analysis.
+ **
+-** $Id: tokenize.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: tokenize.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include "os.h"
+diff -dPNur sqlite-1.0.3/libsqlite/src/update.c sqlite-svn/libsqlite/src/update.c
+--- sqlite-1.0.3/libsqlite/src/update.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/update.c 2012-10-09 13:36:42.551252050 +0000
+@@ -12,7 +12,7 @@
+ ** This file contains C code routines that are called by the parser
+ ** to handle UPDATE statements.
+ **
+-** $Id: update.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: update.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+diff -dPNur sqlite-1.0.3/libsqlite/src/util.c sqlite-svn/libsqlite/src/util.c
+--- sqlite-1.0.3/libsqlite/src/util.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/util.c 2012-10-09 13:36:42.531952680 +0000
+@@ -14,7 +14,7 @@
+ ** This file contains functions for allocating memory, comparing
+ ** strings, and stuff like that.
+ **
+-** $Id: util.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: util.c 203289 2005-12-20 15:26:26Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include <stdarg.h>
+@@ -330,15 +330,15 @@
+ ** point to that string. The 1st argument must either be NULL or
+ ** point to memory obtained from sqliteMalloc().
+ */
+-void sqliteSetString(char **pz, const char *zFirst, ...){
++void sqliteSetString(char **pz, ...){
+ va_list ap;
+ int nByte;
+ const char *z;
+ char *zResult;
+
+ if( pz==0 ) return;
+- nByte = strlen(zFirst) + 1;
+- va_start(ap, zFirst);
++ nByte = 1;
++ va_start(ap, pz);
+ while( (z = va_arg(ap, const char*))!=0 ){
+ nByte += strlen(z);
+ }
+@@ -348,9 +348,8 @@
+ if( zResult==0 ){
+ return;
+ }
+- strcpy(zResult, zFirst);
+- zResult += strlen(zResult);
+- va_start(ap, zFirst);
++ *zResult = 0;
++ va_start(ap, pz);
+ while( (z = va_arg(ap, const char*))!=0 ){
+ strcpy(zResult, z);
+ zResult += strlen(zResult);
+@@ -504,14 +503,14 @@
+ a = (unsigned char *)zLeft;
+ b = (unsigned char *)zRight;
+ while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
+- return *a - *b;
++ return UpperToLower[*a] - UpperToLower[*b];
+ }
+ int sqliteStrNICmp(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 : *a - *b;
++ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
+ }
+
+ /*
+diff -dPNur sqlite-1.0.3/libsqlite/src/vacuum.c sqlite-svn/libsqlite/src/vacuum.c
+--- sqlite-1.0.3/libsqlite/src/vacuum.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/vacuum.c 2012-10-09 13:36:42.541252205 +0000
+@@ -14,7 +14,7 @@
+ ** Most of the code in this file may be omitted by defining the
+ ** SQLITE_OMIT_VACUUM macro.
+ **
+-** $Id: vacuum.c,v 1.2.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: vacuum.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+ #include "os.h"
+@@ -164,24 +164,6 @@
+ }
+
+ /*
+-** This callback is used to transfer PRAGMA settings from one database
+-** to the other. The value in argv[0] should be passed to a pragma
+-** identified by ((vacuumStruct*)pArg)->zPragma.
+-*/
+-static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){
+- vacuumStruct *p = (vacuumStruct*)pArg;
+- char zBuf[200];
+- assert( argc==1 );
+- if( argv==0 ) return 0;
+- assert( argv[0]!=0 );
+- assert( strlen(p->zPragma)<100 );
+- assert( strlen(argv[0])<30 );
+- sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]);
+- p->rc = execsql(p->pzErrMsg, p->dbNew, zBuf);
+- return p->rc;
+-}
+-
+-/*
+ ** Generate a random name of 20 character in length.
+ */
+ static void randomName(unsigned char *zBuf){
+@@ -226,14 +208,6 @@
+ char *zErrMsg; /* Error message */
+ vacuumStruct sVac; /* Information passed to callbacks */
+
+- /* These are all of the pragmas that need to be transferred over
+- ** to the new database */
+- static const char *zPragma[] = {
+- "default_synchronous",
+- "default_cache_size",
+- /* "default_temp_store", */
+- };
+-
+ if( db->flags & SQLITE_InTrans ){
+ sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
+ (char*)0);
+@@ -283,13 +257,6 @@
+ sVac.dbOld = db;
+ sVac.dbNew = dbNew;
+ sVac.pzErrMsg = pzErrMsg;
+- for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){
+- char zBuf[200];
+- assert( strlen(zPragma[i])<100 );
+- sprintf(zBuf, "PRAGMA %s;", zPragma[i]);
+- sVac.zPragma = zPragma[i];
+- rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
+- }
+ if( rc==SQLITE_OK ){
+ rc = sqlite_exec(db,
+ "SELECT type, name, sql FROM sqlite_master "
+@@ -300,6 +267,17 @@
+ vacuumCallback1, &sVac, &zErrMsg);
+ }
+ if( rc==SQLITE_OK ){
++ int meta1[SQLITE_N_BTREE_META];
++ int meta2[SQLITE_N_BTREE_META];
++ sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
++ sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
++ meta2[1] = meta1[1]+1;
++ meta2[3] = meta1[3];
++ meta2[4] = meta1[4];
++ meta2[6] = meta1[6];
++ rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
++ }
++ if( rc==SQLITE_OK ){
+ rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
+ sqlite_exec(db, "COMMIT", 0, 0, 0);
+ sqliteResetInternalSchema(db, 0);
+diff -dPNur sqlite-1.0.3/libsqlite/src/vdbe.c sqlite-svn/libsqlite/src/vdbe.c
+--- sqlite-1.0.3/libsqlite/src/vdbe.c 2004-07-10 12:25:34.000000000 +0000
++++ sqlite-svn/libsqlite/src/vdbe.c 2012-10-09 13:36:42.551252050 +0000
+@@ -43,7 +43,7 @@
+ ** in this file for details. If in doubt, do not deviate from existing
+ ** commenting and indentation practices when changing or adding code.
+ **
+-** $Id: vdbe.c,v 1.3.6.2 2004/07/10 12:25:34 wez Exp $
++** $Id: vdbe.c 219681 2006-09-09 10:59:05Z tony2001 $
+ */
+ #include "sqliteInt.h"
+ #include "os.h"
+@@ -114,7 +114,7 @@
+ sqlite *db;
+ int rc;
+
+- if( p->magic!=VDBE_MAGIC_RUN ){
++ if( !p || p->magic!=VDBE_MAGIC_RUN ){
+ return SQLITE_MISUSE;
+ }
+ db = p->db;
+@@ -4545,6 +4545,10 @@
+ pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
+ pTos->flags |= MEM_Ephem;
+ }
++ if( pTos->flags & MEM_AggCtx ){
++ Release(pTos);
++ pTos->flags = MEM_Null;
++ }
+ break;
+ }
+
+@@ -4695,8 +4699,9 @@
+ break;
+ }
+ }else{
+- assert( pSet->prev );
+- pSet->prev = sqliteHashNext(pSet->prev);
++ if( pSet->prev ){
++ pSet->prev = sqliteHashNext(pSet->prev);
++ }
+ if( pSet->prev==0 ){
+ break;
+ }else{
+diff -dPNur sqlite-1.0.3/libsqlite/src/vdbe.h sqlite-svn/libsqlite/src/vdbe.h
+--- sqlite-1.0.3/libsqlite/src/vdbe.h 2004-07-10 12:25:35.000000000 +0000
++++ sqlite-svn/libsqlite/src/vdbe.h 2012-10-09 13:36:42.551252050 +0000
+@@ -15,7 +15,7 @@
+ ** or VDBE. The VDBE implements an abstract machine that runs a
+ ** simple program to access and modify the underlying database.
+ **
+-** $Id: vdbe.h,v 1.3.6.2 2004/07/10 12:25:35 wez Exp $
++** $Id: vdbe.h 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #ifndef _SQLITE_VDBE_H_
+ #define _SQLITE_VDBE_H_
+diff -dPNur sqlite-1.0.3/libsqlite/src/where.c sqlite-svn/libsqlite/src/where.c
+--- sqlite-1.0.3/libsqlite/src/where.c 2004-07-10 12:25:35.000000000 +0000
++++ sqlite-svn/libsqlite/src/where.c 2012-10-09 13:36:42.541252205 +0000
+@@ -12,7 +12,7 @@
+ ** This module contains C code that generates VDBE code used to process
+ ** the WHERE clause of SQL statements.
+ **
+-** $Id: where.c,v 1.3.6.2 2004/07/10 12:25:35 wez Exp $
++** $Id: where.c 195361 2005-09-07 15:11:33Z iliaa $
+ */
+ #include "sqliteInt.h"
+
+@@ -46,7 +46,7 @@
+ typedef struct ExprMaskSet ExprMaskSet;
+ struct ExprMaskSet {
+ int n; /* Number of assigned cursor values */
+- int ix[32]; /* Cursor assigned to each bit */
++ int ix[31]; /* Cursor assigned to each bit */
+ };
+
+ /*
+@@ -123,7 +123,9 @@
+ unsigned int mask = 0;
+ if( p==0 ) return 0;
+ if( p->op==TK_COLUMN ){
+- return getMask(pMaskSet, p->iTable);
++ mask = getMask(pMaskSet, p->iTable);
++ if( mask==0 ) mask = -1;
++ return mask;
+ }
+ if( p->pRight ){
+ mask = exprTableUsage(pMaskSet, p->pRight);
+@@ -270,6 +272,35 @@
+ }
+
+ /*
++** 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 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
+@@ -736,7 +767,7 @@
+ }else{
+ sqliteExprCode(pParse, aExpr[k].p->pLeft);
+ }
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ cont = pLevel->cont = sqliteVdbeMakeLabel(v);
+ sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
+ haveKey = 0;
+@@ -760,7 +791,7 @@
+ ){
+ if( pX->op==TK_EQ ){
+ sqliteExprCode(pParse, pX->pRight);
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ if( pX->op==TK_IN && nColumn==1 ){
+@@ -777,7 +808,7 @@
+ pLevel->inOp = OP_Next;
+ pLevel->inP1 = pX->iTable;
+ }
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ }
+@@ -787,7 +818,7 @@
+ && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
+ ){
+ sqliteExprCode(pParse, aExpr[k].p->pLeft);
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ }
+@@ -854,7 +885,7 @@
+ sqliteVdbeAddOp(v, OP_ForceInt,
+ aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
+ sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ }else{
+ sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
+ }
+@@ -876,7 +907,7 @@
+ }else{
+ testOp = OP_Gt;
+ }
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ }
+ start = sqliteVdbeCurrentAddr(v);
+ pLevel->op = OP_Next;
+@@ -931,7 +962,7 @@
+ && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
+ ){
+ sqliteExprCode(pParse, aExpr[k].p->pRight);
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ if( aExpr[k].idxRight==iCur
+@@ -940,7 +971,7 @@
+ && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
+ ){
+ sqliteExprCode(pParse, aExpr[k].p->pLeft);
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ }
+@@ -977,7 +1008,7 @@
+ ){
+ sqliteExprCode(pParse, pExpr->pRight);
+ leFlag = pExpr->op==TK_LE;
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ if( aExpr[k].idxRight==iCur
+@@ -987,7 +1018,7 @@
+ ){
+ sqliteExprCode(pParse, pExpr->pLeft);
+ leFlag = pExpr->op==TK_GE;
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ }
+@@ -1036,7 +1067,7 @@
+ ){
+ sqliteExprCode(pParse, pExpr->pRight);
+ geFlag = pExpr->op==TK_GE;
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ if( aExpr[k].idxRight==iCur
+@@ -1046,7 +1077,7 @@
+ ){
+ sqliteExprCode(pParse, pExpr->pLeft);
+ geFlag = pExpr->op==TK_LE;
+- aExpr[k].p = 0;
++ disableTerm(pLevel, &aExpr[k].p);
+ break;
+ }
+ }
+diff -dPNur sqlite-1.0.3/package.xml sqlite-svn/package.xml
+--- sqlite-1.0.3/package.xml 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/package.xml 2012-10-09 13:36:42.760063980 +0000
+@@ -0,0 +1,158 @@
++<?xml version="1.0" encoding="UTF-8" ?>
++<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
++ xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
++ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
++ xsi:schemaLocation="
++ http://pear.php.net/dtd/tasks-1.0
++ http://pear.php.net/dtd/tasks-1.0.xsd
++ http://pear.php.net/dtd/package-2.0
++ http://pear.php.net/dtd/package-2.0.xsd">
++ <name>SQLite</name>
++ <channel>pecl.php.net</channel>
++ <summary>SQLite 2 database bindings</summary>
++ <description><![CDATA[
++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.
++This extension allows access to SQLite 2 databases from within PHP
++using sqlite_* and pdo_sqlite2 functions.
++
++This extension does not work with SQLite 3 databases; use pdo_sqlite or ext/sqlite3
++for that.
++]]></description>
++ <lead>
++ <name>Wez Furlong</name>
++ <user>wez</user>
++ <email>wez@php.net</email>
++ <active>no</active>
++ </lead>
++ <lead>
++ <name>Marcus Borger</name>
++ <user>helly</user>
++ <email>helly@php.net</email>
++ <active>no</active>
++ </lead>
++ <developer>
++ <name>Ilia Alshanetsky</name>
++ <user>iliaa</user>
++ <email>ilia@php.net</email>
++ <active>no</active>
++ </developer>
++ <developer>
++ <name>Tal Peer</name>
++ <user>tal</user>
++ <email>tal@php.net</email>
++ <active>no</active>
++ </developer>
++ <date>2011-07-08</date>
++ <version>
++ <release>2.0.0</release>
++ <api>2.0.0</api>
++ </version>
++ <stability>
++ <release>stable</release>
++ <api>stable</api>
++ </stability>
++ <license uri="http://www.php.net/license">PHP License</license>
++ <notes><![CDATA[
++ * Moved from php-src back to PECL, and released as version 2.0.0
++ * Upgraded package.xml file from v1 to v2
++]]></notes>
++ <contents>
++ <dir name="/">
++ <file role="src" name="config.m4"/>
++ <file role="src" name="config.w32"/>
++ <file role="src" name="sqlite.c"/>
++ <file role="src" name="sqlite.dsp"/>
++ <file role="src" name="php_sqlite.h"/>
++ <file role="src" name="php_sqlite.def"/>
++ <file role="doc" name="CREDITS"/>
++ <file role="doc" name="README"/>
++ <file role="doc" name="TODO"/>
++ <file role="doc" name="sqlite.php"/>
++ <file role="test" name="tests/sqlite_001.phpt"/>
++ <file role="test" name="tests/sqlite_002.phpt"/>
++ <file role="test" name="tests/sqlite_003.phpt"/>
++ <file role="test" name="tests/sqlite_004.phpt"/>
++ <file role="test" name="tests/sqlite_005.phpt"/>
++ <file role="test" name="tests/sqlite_006.phpt"/>
++ <file role="test" name="tests/sqlite_007.phpt"/>
++ <file role="test" name="tests/sqlite_008.phpt"/>
++ <file role="test" name="tests/sqlite_009.phpt"/>
++ <file role="test" name="tests/sqlite_010.phpt"/>
++ <file role="test" name="tests/sqlite_011.phpt"/>
++ <file role="test" name="tests/sqlite_012.phpt"/>
++ <file role="test" name="tests/sqlite_013.phpt"/>
++ <file role="test" name="tests/sqlite_014.phpt"/>
++ <file role="test" name="tests/sqlite_015.phpt"/>
++ <file role="test" name="tests/sqlite_016.phpt"/>
++ <file role="test" name="tests/sqlite_017.phpt"/>
++ <file role="test" name="tests/blankdb.inc"/>
++
++ <dir name="libsqlite">
++ <file role="doc" name="README"/>
++ <file role="src" name="VERSION"/>
++
++ <dir name="src">
++ <file role="src" name="attach.c"/>
++ <file role="src" name="auth.c"/>
++ <file role="src" name="btree.c"/>
++ <file role="src" name="btree_rb.c"/>
++ <file role="src" name="build.c"/>
++ <file role="src" name="copy.c"/>
++ <file role="src" name="delete.c"/>
++ <file role="src" name="encode.c"/>
++ <file role="src" name="expr.c"/>
++ <file role="src" name="func.c"/>
++ <file role="src" name="hash.c"/>
++ <file role="src" name="insert.c"/>
++ <file role="src" name="main.c"/>
++ <file role="src" name="opcodes.c"/>
++ <file role="src" name="os.c"/>
++ <file role="src" name="pager.c"/>
++ <file role="src" name="parse.c"/>
++ <file role="src" name="parse.y"/>
++ <file role="src" name="pragma.c"/>
++ <file role="src" name="printf.c"/>
++ <file role="src" name="random.c"/>
++ <file role="src" name="select.c"/>
++ <file role="src" name="table.c"/>
++ <file role="src" name="tokenize.c"/>
++ <file role="src" name="trigger.c"/>
++ <file role="src" name="update.c"/>
++ <file role="src" name="util.c"/>
++ <file role="src" name="vacuum.c"/>
++ <file role="src" name="vdbe.c"/>
++ <file role="src" name="where.c"/>
++ <file role="src" name="btree.h"/>
++ <file role="src" name="hash.h"/>
++ <file role="src" name="opcodes.h"/>
++ <file role="src" name="os.h"/>
++ <file role="src" name="pager.h"/>
++ <file role="src" name="parse.h"/>
++ <file role="src" name="sqlite_config.w32.h"/>
++ <file role="src" name="sqlite.h.in"/>
++ <file role="src" name="sqliteInt.h"/>
++ <file role="src" name="sqlite.w32.h"/>
++ <file role="src" name="vdbe.h"/>
++ </dir>
++ </dir>
++ </dir>
++ </contents>
++ <dependencies>
++ <required>
++ <php>
++ <min>5.1.0</min>
++ </php>
++ <pearinstaller>
++ <min>1.4.1</min>
++ </pearinstaller>
++ </required>
++ </dependencies>
++ <providesextension>SQLite</providesextension>
++ <changelog />
++ <extsrcrelease />
++</package>
++<!--
++vim:et:ts=1:sw=1
++-->
+diff -dPNur sqlite-1.0.3/pdo_sqlite2.c sqlite-svn/pdo_sqlite2.c
+--- sqlite-1.0.3/pdo_sqlite2.c 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/pdo_sqlite2.c 2012-10-09 13:36:42.760063980 +0000
+@@ -0,0 +1,633 @@
++/*
++ +----------------------------------------------------------------------+
++ | PHP Version 5 |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 1997-2010 The PHP Group |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 3.01 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available through the world-wide-web at the following url: |
++ | http://www.php.net/license/3_01.txt |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Wez Furlong <wez@php.net> |
++ +----------------------------------------------------------------------+
++*/
++
++/* $Id: pdo_sqlite2.c 300612 2010-06-20 14:12:06Z felipe $ */
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++#include "php.h"
++
++#ifdef PHP_SQLITE2_HAVE_PDO
++#include "sqlite.h"
++#include "pdo/php_pdo.h"
++#include "pdo/php_pdo_driver.h"
++#include "zend_exceptions.h"
++
++#define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
++#define php_sqlite_decode_binary(in, out) sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out)
++
++
++typedef struct {
++ const char *file;
++ int line;
++ unsigned int errcode;
++ char *errmsg;
++} pdo_sqlite2_error_info;
++
++typedef struct {
++ sqlite *db;
++ pdo_sqlite2_error_info einfo;
++} pdo_sqlite2_db_handle;
++
++typedef struct {
++ pdo_sqlite2_db_handle *H;
++ sqlite_vm *vm;
++ const char **rowdata, **colnames;
++ int ncols;
++ unsigned pre_fetched:1;
++ unsigned done:1;
++ pdo_sqlite2_error_info einfo;
++} pdo_sqlite2_stmt;
++
++extern int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC);
++#define pdo_sqlite2_error(msg, s) _pdo_sqlite2_error(s, NULL, msg, __FILE__, __LINE__ TSRMLS_CC)
++#define pdo_sqlite2_error_stmt(msg, s) _pdo_sqlite2_error(stmt->dbh, stmt, msg, __FILE__, __LINE__ TSRMLS_CC)
++
++extern struct pdo_stmt_methods sqlite2_stmt_methods;
++
++static int pdo_sqlite2_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
++{
++ pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
++
++ if (S->vm) {
++ char *errmsg = NULL;
++ sqlite_finalize(S->vm, &errmsg);
++ if (errmsg) {
++ sqlite_freemem(errmsg);
++ }
++ S->vm = NULL;
++ }
++ if (S->einfo.errmsg) {
++ pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
++ }
++ efree(S);
++ return 1;
++}
++
++static int pdo_sqlite2_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
++{
++ pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
++ char *errmsg = NULL;
++ const char *tail;
++
++ if (stmt->executed && !S->done) {
++ sqlite_finalize(S->vm, &errmsg);
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ errmsg = NULL;
++ S->vm = NULL;
++ }
++
++ S->einfo.errcode = sqlite_compile(S->H->db, stmt->active_query_string, &tail, &S->vm, &errmsg);
++ if (S->einfo.errcode != SQLITE_OK) {
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ return 0;
++ }
++
++ S->done = 0;
++ S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
++ switch (S->einfo.errcode) {
++ case SQLITE_ROW:
++ S->pre_fetched = 1;
++ stmt->column_count = S->ncols;
++ return 1;
++
++ case SQLITE_DONE:
++ stmt->column_count = S->ncols;
++ stmt->row_count = sqlite_changes(S->H->db);
++ S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
++ if (S->einfo.errcode != SQLITE_OK) {
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ }
++ S->done = 1;
++ return 1;
++
++ case SQLITE_ERROR:
++ case SQLITE_MISUSE:
++ case SQLITE_BUSY:
++ default:
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ return 0;
++ }
++}
++
++static int pdo_sqlite2_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
++ enum pdo_param_event event_type TSRMLS_DC)
++{
++ return 1;
++}
++
++static int pdo_sqlite2_stmt_fetch(pdo_stmt_t *stmt,
++ enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
++{
++ pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
++ char *errmsg = NULL;
++
++ if (!S->vm) {
++ return 0;
++ }
++ if (S->pre_fetched) {
++ S->pre_fetched = 0;
++ return 1;
++ }
++ if (S->done) {
++ return 0;
++ }
++
++ S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
++ switch (S->einfo.errcode) {
++ case SQLITE_ROW:
++ return 1;
++
++ case SQLITE_DONE:
++ S->done = 1;
++ S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
++ if (S->einfo.errcode != SQLITE_OK) {
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ errmsg = NULL;
++ }
++ return 0;
++
++ default:
++ pdo_sqlite2_error_stmt(errmsg, stmt);
++ return 0;
++ }
++}
++
++static int pdo_sqlite2_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
++{
++ pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
++
++ if(colno >= S->ncols) {
++ /* error invalid column */
++ pdo_sqlite2_error_stmt(NULL, stmt);
++ return 0;
++ }
++
++ stmt->columns[colno].name = estrdup(S->colnames[colno]);
++ stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
++ stmt->columns[colno].maxlen = 0xffffffff;
++ stmt->columns[colno].precision = 0;
++ stmt->columns[colno].param_type = PDO_PARAM_STR;
++
++ return 1;
++}
++
++static int pdo_sqlite2_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
++{
++ pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
++ if (!S->vm) {
++ return 0;
++ }
++ if(colno >= S->ncols) {
++ /* error invalid column */
++ pdo_sqlite2_error_stmt(NULL, stmt);
++ return 0;
++ }
++ if (S->rowdata[colno]) {
++ if (S->rowdata[colno][0] == '\x01') {
++ /* encoded */
++ *caller_frees = 1;
++ *ptr = emalloc(strlen(S->rowdata[colno]));
++ *len = php_sqlite_decode_binary(S->rowdata[colno]+1, *ptr);
++ (*(char**)ptr)[*len] = '\0';
++ } else {
++ *ptr = (char*)S->rowdata[colno];
++ *len = strlen(*ptr);
++ }
++ } else {
++ *ptr = NULL;
++ *len = 0;
++ }
++ return 1;
++}
++
++struct pdo_stmt_methods sqlite2_stmt_methods = {
++ pdo_sqlite2_stmt_dtor,
++ pdo_sqlite2_stmt_execute,
++ pdo_sqlite2_stmt_fetch,
++ pdo_sqlite2_stmt_describe,
++ pdo_sqlite2_stmt_get_col,
++ pdo_sqlite2_stmt_param_hook,
++ NULL, /* set_attr */
++ NULL, /* get_attr */
++ NULL
++};
++
++
++int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC) /* {{{ */
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
++ pdo_sqlite2_error_info *einfo = &H->einfo;
++ pdo_sqlite2_stmt *S;
++
++ if (stmt) {
++ S = stmt->driver_data;
++ einfo = &S->einfo;
++ }
++
++ einfo->file = file;
++ einfo->line = line;
++
++ if (einfo->errmsg) {
++ pefree(einfo->errmsg, dbh->is_persistent);
++ einfo->errmsg = NULL;
++ }
++
++ if (einfo->errcode != SQLITE_OK) {
++ if (errmsg) {
++ einfo->errmsg = pestrdup(errmsg, dbh->is_persistent);
++ sqlite_freemem(errmsg);
++ } else {
++ einfo->errmsg = pestrdup(sqlite_error_string(einfo->errcode), dbh->is_persistent);
++ }
++ } else { /* no error */
++ strcpy(*pdo_err, PDO_ERR_NONE);
++ return 0;
++ }
++ switch (einfo->errcode) {
++ case SQLITE_NOTFOUND:
++ strcpy(*pdo_err, "42S02");
++ break;
++
++ case SQLITE_INTERRUPT:
++ strcpy(*pdo_err, "01002");
++ break;
++
++ case SQLITE_NOLFS:
++ strcpy(*pdo_err, "HYC00");
++ break;
++
++ case SQLITE_TOOBIG:
++ strcpy(*pdo_err, "22001");
++ break;
++
++ case SQLITE_CONSTRAINT:
++ strcpy(*pdo_err, "23000");
++ break;
++
++ case SQLITE_ERROR:
++ default:
++ strcpy(*pdo_err, "HY000");
++ break;
++ }
++
++ if (!dbh->methods) {
++ zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
++ *pdo_err, einfo->errcode, einfo->errmsg);
++ }
++
++ return einfo->errcode;
++}
++/* }}} */
++
++static int pdo_sqlite2_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ pdo_sqlite2_error_info *einfo = &H->einfo;
++ pdo_sqlite2_stmt *S;
++
++ if (stmt) {
++ S = stmt->driver_data;
++ einfo = &S->einfo;
++ }
++
++ if (einfo->errcode) {
++ add_next_index_long(info, einfo->errcode);
++ if (einfo->errmsg) {
++ add_next_index_string(info, einfo->errmsg, 1);
++ }
++ }
++
++ return 1;
++}
++
++static int sqlite2_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++
++ if (H) {
++ if (H->db) {
++ sqlite_close(H->db);
++ H->db = NULL;
++ }
++ if (H->einfo.errmsg) {
++ pefree(H->einfo.errmsg, dbh->is_persistent);
++ H->einfo.errmsg = NULL;
++ }
++ pefree(H, dbh->is_persistent);
++ dbh->driver_data = NULL;
++ }
++ return 0;
++}
++/* }}} */
++
++static int sqlite2_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ pdo_sqlite2_stmt *S = ecalloc(1, sizeof(pdo_sqlite2_stmt));
++
++ S->H = H;
++ stmt->driver_data = S;
++ stmt->methods = &sqlite2_stmt_methods;
++ stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
++
++ if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
++ H->einfo.errcode = SQLITE_ERROR;
++ pdo_sqlite2_error(NULL, dbh);
++ return 0;
++ }
++
++ return 1;
++}
++
++static long sqlite2_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ char *errmsg = NULL;
++
++ if ((H->einfo.errcode = sqlite_exec(H->db, sql, NULL, NULL, &errmsg)) != SQLITE_OK) {
++ pdo_sqlite2_error(errmsg, dbh);
++ return -1;
++ } else {
++ return sqlite_changes(H->db);
++ }
++}
++
++static char *pdo_sqlite2_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ char *id;
++
++ id = php_pdo_int64_to_str(sqlite_last_insert_rowid(H->db) TSRMLS_CC);
++ *len = strlen(id);
++ return id;
++}
++
++static int sqlite2_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
++{
++ char *ret;
++
++ if (unquotedlen && (unquoted[0] == '\x01' || memchr(unquoted, '\0', unquotedlen) != NULL)) {
++ /* binary string */
++ int len;
++ ret = safe_emalloc(1 + unquotedlen / 254, 257, 5);
++ ret[0] = '\'';
++ ret[1] = '\x01';
++ len = php_sqlite_encode_binary(unquoted, unquotedlen, ret+2);
++ ret[len + 2] = '\'';
++ ret[len + 3] = '\0';
++ *quoted = ret;
++ *quotedlen = len + 3;
++ /* fprintf(stderr, "Quoting:%d:%.*s:\n", *quotedlen, *quotedlen, *quoted); */
++ return 1;
++ } else if (unquotedlen) {
++ ret = sqlite_mprintf("'%q'", unquoted);
++ if (ret) {
++ *quoted = estrdup(ret);
++ *quotedlen = strlen(ret);
++ sqlite_freemem(ret);
++ return 1;
++ }
++ return 0;
++ } else {
++ *quoted = estrdup("''");
++ *quotedlen = 2;
++ return 1;
++ }
++}
++
++static int sqlite2_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ char *errmsg = NULL;
++
++ if (sqlite_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
++ pdo_sqlite2_error(errmsg, dbh);
++ return 0;
++ }
++ return 1;
++}
++
++static int sqlite2_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ char *errmsg = NULL;
++
++ if (sqlite_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
++ pdo_sqlite2_error(errmsg, dbh);
++ return 0;
++ }
++ return 1;
++}
++
++static int sqlite2_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++ char *errmsg = NULL;
++
++ if (sqlite_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
++ pdo_sqlite2_error(errmsg, dbh);
++ return 0;
++ }
++ return 1;
++}
++
++static int pdo_sqlite2_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
++{
++ switch (attr) {
++ case PDO_ATTR_CLIENT_VERSION:
++ case PDO_ATTR_SERVER_VERSION:
++ ZVAL_STRING(return_value, (char *)sqlite_libversion(), 1);
++ break;
++
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++static int pdo_sqlite2_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
++{
++ pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
++
++ switch (attr) {
++ case PDO_ATTR_TIMEOUT:
++ convert_to_long(val);
++ sqlite_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
++ return 1;
++ }
++ return 0;
++}
++
++static PHP_FUNCTION(sqlite2_create_function)
++{
++ /* TODO: implement this stuff */
++}
++
++static const zend_function_entry dbh_methods[] = {
++ PHP_FE(sqlite2_create_function, NULL)
++ {NULL, NULL, NULL}
++};
++
++static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
++{
++ switch (kind) {
++ case PDO_DBH_DRIVER_METHOD_KIND_DBH:
++ return dbh_methods;
++
++ default:
++ return NULL;
++ }
++}
++
++static struct pdo_dbh_methods sqlite2_methods = {
++ sqlite2_handle_closer,
++ sqlite2_handle_preparer,
++ sqlite2_handle_doer,
++ sqlite2_handle_quoter,
++ sqlite2_handle_begin,
++ sqlite2_handle_commit,
++ sqlite2_handle_rollback,
++ pdo_sqlite2_set_attr,
++ pdo_sqlite2_last_insert_id,
++ pdo_sqlite2_fetch_error_func,
++ pdo_sqlite2_get_attribute,
++ NULL, /* check_liveness: not needed */
++ get_driver_methods
++};
++
++static char *make_filename_safe(const char *filename TSRMLS_DC)
++{
++ if (*filename && strncmp(filename, ":memory:", sizeof(":memory:")-1)) {
++ char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
++
++ if (!fullpath) {
++ return NULL;
++ }
++
++ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
++ efree(fullpath);
++ return NULL;
++ }
++ return fullpath;
++ }
++ return estrdup(filename);
++}
++
++static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
++ const char *arg5, const char *arg6)
++{
++ char *filename;
++ switch (access_type) {
++ case SQLITE_COPY: {
++ TSRMLS_FETCH();
++ filename = make_filename_safe(arg4 TSRMLS_CC);
++ if (!filename) {
++ return SQLITE_DENY;
++ }
++ efree(filename);
++ return SQLITE_OK;
++ }
++
++ case SQLITE_ATTACH: {
++ TSRMLS_FETCH();
++ filename = make_filename_safe(arg3 TSRMLS_CC);
++ if (!filename) {
++ return SQLITE_DENY;
++ }
++ efree(filename);
++ return SQLITE_OK;
++ }
++
++ default:
++ /* access allowed */
++ return SQLITE_OK;
++ }
++}
++
++static int pdo_sqlite2_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
++{
++ pdo_sqlite2_db_handle *H;
++ int ret = 0;
++ long timeout = 60;
++ char *filename;
++ char *errmsg = NULL;
++
++ H = pecalloc(1, sizeof(pdo_sqlite2_db_handle), dbh->is_persistent);
++
++ H->einfo.errcode = 0;
++ H->einfo.errmsg = NULL;
++ dbh->driver_data = H;
++
++ filename = make_filename_safe(dbh->data_source TSRMLS_CC);
++
++ if (!filename) {
++ zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
++ "open_basedir prohibits opening %s",
++ dbh->data_source);
++ goto cleanup;
++ }
++
++ H->db = sqlite_open(filename, 0666, &errmsg);
++ efree(filename);
++
++ if (!H->db) {
++ H->einfo.errcode = SQLITE_ERROR;
++ pdo_sqlite2_error(errmsg, dbh);
++ goto cleanup;
++ }
++
++ sqlite_set_authorizer(H->db, authorizer, NULL);
++
++ if (driver_options) {
++ timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
++ }
++ sqlite_busy_timeout(H->db, timeout * 1000);
++
++ dbh->alloc_own_columns = 1;
++ dbh->max_escaped_char_length = 2;
++
++ ret = 1;
++
++cleanup:
++ dbh->methods = &sqlite2_methods;
++
++ return ret;
++}
++/* }}} */
++
++pdo_driver_t pdo_sqlite2_driver = {
++ PDO_DRIVER_HEADER(sqlite2),
++ pdo_sqlite2_handle_factory
++};
++
++
++
++#endif
++
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: noet sw=4 ts=4 fdm=marker
++ * vim<600: noet sw=4 ts=4
++ */
+diff -dPNur sqlite-1.0.3/php_sqlite.def sqlite-svn/php_sqlite.def
+--- sqlite-1.0.3/php_sqlite.def 2003-06-12 23:22:33.000000000 +0000
++++ sqlite-svn/php_sqlite.def 2012-10-09 13:36:42.760063980 +0000
+@@ -35,3 +35,9 @@
+ sqlite_compile
+ sqlite_step
+ sqlite_finalize
++; some experimental stuff
++sqlite_last_statement_changes
++sqlite_reset
++sqlite_bind
++sqlite_progress_handler
++sqlite_commit_hook
+diff -dPNur sqlite-1.0.3/php_sqlite.h sqlite-svn/php_sqlite.h
+--- sqlite-1.0.3/php_sqlite.h 2004-05-13 14:54:55.000000000 +0000
++++ sqlite-svn/php_sqlite.h 2012-10-09 13:36:42.760063980 +0000
+@@ -1,13 +1,13 @@
+ /*
+ +----------------------------------------------------------------------+
+- | PHP Version 4 |
++ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+- | Copyright (c) 1997-2003 The PHP Group |
++ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+- | This source file is subject to version 3.0 of the PHP license, |
++ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+- | http://www.php.net/license/3_0.txt. |
++ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+@@ -17,7 +17,7 @@
+ | Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+
+- $Id: php_sqlite.h,v 1.23.2.3 2004/05/13 14:54:55 stas Exp $
++ $Id: php_sqlite.h 293036 2010-01-03 09:23:27Z sebastian $
+ */
+
+ #ifndef PHP_SQLITE_H
+@@ -26,19 +26,12 @@
+ extern zend_module_entry sqlite_module_entry;
+ #define phpext_sqlite_ptr &sqlite_module_entry
+
+-#ifdef PHP_WIN32
+-#define PHP_SQLITE_API __declspec(dllexport)
+-#else
+-#define PHP_SQLITE_API
+-#endif
+-
+ #ifdef ZTS
+ #include "TSRM.h"
+ #endif
+
+ PHP_MINIT_FUNCTION(sqlite);
+ PHP_MSHUTDOWN_FUNCTION(sqlite);
+-PHP_RINIT_FUNCTION(sqlite);
+ PHP_RSHUTDOWN_FUNCTION(sqlite);
+ PHP_MINFO_FUNCTION(sqlite);
+
+@@ -52,6 +45,7 @@
+ PHP_FUNCTION(sqlite_single_query);
+
+ PHP_FUNCTION(sqlite_fetch_array);
++PHP_FUNCTION(sqlite_fetch_object);
+ PHP_FUNCTION(sqlite_fetch_single);
+ PHP_FUNCTION(sqlite_fetch_all);
+ PHP_FUNCTION(sqlite_current);
+@@ -63,7 +57,11 @@
+ PHP_FUNCTION(sqlite_seek);
+ PHP_FUNCTION(sqlite_rewind);
+ PHP_FUNCTION(sqlite_next);
+-PHP_FUNCTION(sqlite_has_more);
++PHP_FUNCTION(sqlite_prev);
++PHP_FUNCTION(sqlite_key);
++
++PHP_FUNCTION(sqlite_valid);
++PHP_FUNCTION(sqlite_has_prev);
+
+ PHP_FUNCTION(sqlite_libversion);
+ PHP_FUNCTION(sqlite_libencoding);
+@@ -83,6 +81,10 @@
+ PHP_FUNCTION(sqlite_udf_decode_binary);
+ PHP_FUNCTION(sqlite_udf_encode_binary);
+
++PHP_FUNCTION(sqlite_factory);
++
++PHP_FUNCTION(sqlite_fetch_column_types);
++
+ ZEND_BEGIN_MODULE_GLOBALS(sqlite)
+ long assoc_case;
+ ZEND_END_MODULE_GLOBALS(sqlite)
+diff -dPNur sqlite-1.0.3/sess_sqlite.c sqlite-svn/sess_sqlite.c
+--- sqlite-1.0.3/sess_sqlite.c 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/sess_sqlite.c 2012-10-09 13:36:42.760063980 +0000
+@@ -0,0 +1,200 @@
++/*
++ +----------------------------------------------------------------------+
++ | PHP Version 5 |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 1997-2010 The PHP Group |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 3.01 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available through the world-wide-web at the following url: |
++ | http://www.php.net/license/3_01.txt |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Authors: John Coggeshall <john@php.net> |
++ | Wez Furlong <wez@thebrainroom.com> |
++ +----------------------------------------------------------------------+
++ */
++
++/* $Id: sess_sqlite.c 298625 2010-04-26 23:53:30Z kalle $ */
++
++#include "php.h"
++
++#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
++
++#include "ext/session/php_session.h"
++#include "ext/standard/php_lcg.h"
++#include <sqlite.h>
++#define SQLITE_RETVAL(__r) ((__r) == SQLITE_OK ? SUCCESS : FAILURE)
++#define PS_SQLITE_DATA sqlite *db = (sqlite*)PS_GET_MOD_DATA()
++extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
++extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
++
++PS_FUNCS(sqlite);
++
++ps_module ps_mod_sqlite = {
++ PS_MOD(sqlite)
++};
++
++PS_OPEN_FUNC(sqlite)
++{
++ char *errmsg = NULL;
++ sqlite *db;
++
++ db = sqlite_open(save_path, 0666, &errmsg);
++ if (db == NULL) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING,
++ "SQLite: failed to open/create session database `%s' - %s", save_path, errmsg);
++ sqlite_freemem(errmsg);
++ return FAILURE;
++ }
++
++ /* allow up to 1 minute when busy */
++ sqlite_busy_timeout(db, 60000);
++
++ sqlite_exec(db, "PRAGMA default_synchronous = OFF", NULL, NULL, NULL);
++ sqlite_exec(db, "PRAGMA count_changes = OFF", NULL, NULL, NULL);
++
++ /* This will fail if the table already exists, but that's not a big problem. I'm
++ unclear as to how to check for a table's existence in SQLite -- that would be better here. */
++ sqlite_exec(db,
++ "CREATE TABLE session_data ("
++ " sess_id PRIMARY KEY,"
++ " value TEXT, "
++ " updated INTEGER "
++ ")", NULL, NULL, NULL);
++
++ PS_SET_MOD_DATA(db);
++
++ return SUCCESS;
++}
++
++PS_CLOSE_FUNC(sqlite)
++{
++ PS_SQLITE_DATA;
++
++ sqlite_close(db);
++
++ return SUCCESS;
++}
++
++PS_READ_FUNC(sqlite)
++{
++ PS_SQLITE_DATA;
++ char *query;
++ const char *tail;
++ sqlite_vm *vm;
++ int colcount, result;
++ const char **rowdata, **colnames;
++ char *error;
++
++ *val = NULL;
++ *vallen = 0;
++
++ query = sqlite_mprintf("SELECT value FROM session_data WHERE sess_id='%q' LIMIT 1", key);
++ if (query == NULL) {
++ /* no memory */
++ return FAILURE;
++ }
++
++ if (sqlite_compile(db, query, &tail, &vm, &error) != SQLITE_OK) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: Could not compile session read query: %s", error);
++ sqlite_freemem(error);
++ sqlite_freemem(query);
++ return FAILURE;
++ }
++
++ switch ((result = sqlite_step(vm, &colcount, &rowdata, &colnames))) {
++ case SQLITE_ROW:
++ if (rowdata[0] != NULL) {
++ *vallen = strlen(rowdata[0]);
++ if (*vallen) {
++ *val = emalloc(*vallen);
++ *vallen = sqlite_decode_binary(rowdata[0], *val);
++ (*val)[*vallen] = '\0';
++ } else {
++ *val = STR_EMPTY_ALLOC();
++ }
++ }
++ break;
++ default:
++ sqlite_freemem(error);
++ error = NULL;
++ }
++
++ if (SQLITE_OK != sqlite_finalize(vm, &error)) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session read: error %s", error);
++ sqlite_freemem(error);
++ error = NULL;
++ }
++
++ sqlite_freemem(query);
++
++ return *val == NULL ? FAILURE : SUCCESS;
++}
++
++PS_WRITE_FUNC(sqlite)
++{
++ PS_SQLITE_DATA;
++ char *error;
++ time_t t;
++ char *binary;
++ int binlen;
++ int rv;
++
++ t = time(NULL);
++
++ binary = safe_emalloc(1 + vallen / 254, 257, 3);
++ binlen = sqlite_encode_binary((const unsigned char*)val, vallen, binary);
++
++ rv = sqlite_exec_printf(db, "REPLACE INTO session_data VALUES('%q', '%q', %d)", NULL, NULL, &error, key, binary, t);
++ if (rv != SQLITE_OK) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session write query failed: %s", error);
++ sqlite_freemem(error);
++ }
++ efree(binary);
++
++ return SQLITE_RETVAL(rv);
++}
++
++PS_DESTROY_FUNC(sqlite)
++{
++ int rv;
++ PS_SQLITE_DATA;
++
++ rv = sqlite_exec_printf(db, "DELETE FROM session_data WHERE sess_id='%q'", NULL, NULL, NULL, key);
++
++ return SQLITE_RETVAL(rv);
++}
++
++PS_GC_FUNC(sqlite)
++{
++ PS_SQLITE_DATA;
++ int rv;
++ time_t t = time(NULL);
++
++ rv = sqlite_exec_printf(db,
++ "DELETE FROM session_data WHERE (%d - updated) > %d",
++ NULL, NULL, NULL, t, maxlifetime);
++
++ /* because SQLite does not actually clear the deleted data from the database
++ * we need to occassionaly do so manually to prevent the sessions database
++ * from growing endlessly.
++ */
++ if ((int) ((float) PS(gc_divisor) * PS(gc_divisor) * php_combined_lcg(TSRMLS_C)) < PS(gc_probability)) {
++ rv = sqlite_exec_printf(db, "VACUUM", NULL, NULL, NULL);
++ }
++ return SQLITE_RETVAL(rv);
++}
++
++#endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: sw=4 ts=4 fdm=marker
++ * vim<600: sw=4 ts=4
++ */
+diff -dPNur sqlite-1.0.3/sqlite.c sqlite-svn/sqlite.c
+--- sqlite-1.0.3/sqlite.c 2004-07-18 10:23:18.000000000 +0000
++++ sqlite-svn/sqlite.c 2012-10-09 13:36:42.760063980 +0000
+@@ -1,13 +1,13 @@
+ /*
+ +----------------------------------------------------------------------+
+- | PHP Version 4 |
++ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+- | Copyright (c) 1997-2003 The PHP Group |
++ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+- | This source file is subject to version 3.0 of the PHP license, |
++ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+- | http://www.php.net/license/3_0.txt. |
++ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+@@ -17,43 +17,65 @@
+ | Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+
+- $Id: sqlite.c,v 1.62.2.25 2004/07/10 12:25:33 wez Exp $
++ $Id: sqlite.c 299692 2010-05-24 14:11:39Z dmitry $
+ */
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
+-#define PHP_SQLITE_MODULE_VERSION "1.0.3"
++#define PHP_SQLITE_MODULE_VERSION "2.0-dev"
+
+ #include "php.h"
+ #include "php_ini.h"
+ #include "ext/standard/info.h"
++#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
++#include "ext/session/php_session.h"
++#endif
+ #include "php_sqlite.h"
+
+ #if HAVE_TIME_H
+ # include <time.h>
+ #endif
+-#ifdef HAVE_UNISTD_H
++#if HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+
+ #include <sqlite.h>
+
+-#ifndef safe_emalloc
+-# define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
++#include "zend_exceptions.h"
++#include "zend_interfaces.h"
++
++#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
++extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
++extern PHPAPI zend_class_entry *spl_ce_Countable;
+ #endif
+
+-#ifndef ZEND_ENGINE_2
+-# define OnUpdateLong OnUpdateInt
++#if PHP_SQLITE2_HAVE_PDO
++# include "pdo/php_pdo.h"
++# include "pdo/php_pdo_driver.h"
++extern pdo_driver_t pdo_sqlite2_driver;
++#endif
++
++#ifndef safe_emalloc
++# define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
+ #endif
+
+ ZEND_DECLARE_MODULE_GLOBALS(sqlite)
++static PHP_GINIT_FUNCTION(sqlite);
++
++#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
++extern ps_module ps_mod_sqlite;
++#define ps_sqlite_ptr &ps_mod_sqlite
++#endif
+
+ extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
+ extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
+
+-static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
++#define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
++#define php_sqlite_decode_binary(in, out) in && *in ? sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out) : 0
++
++static int sqlite_count_elements(zval *object, long *count TSRMLS_DC);
+
+ static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb;
+
+@@ -80,11 +102,34 @@
+ PHP_INI_END()
+ /* }}} */
+
+-
+ #define DB_FROM_ZVAL(db, zv) ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb)
+
++#define DB_FROM_OBJECT(db, object) \
++ { \
++ sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
++ db = obj->u.db; \
++ if (!db) { \
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \
++ RETURN_NULL(); \
++ } \
++ }
++
++#define RES_FROM_OBJECT_RESTORE_ERH(res, object, error_handling) \
++ { \
++ sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
++ res = obj->u.res; \
++ if (!res) { \
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No result set available"); \
++ if (error_handling) \
++ zend_restore_error_handling(error_handling TSRMLS_CC); \
++ RETURN_NULL(); \
++ } \
++ }
++
++#define RES_FROM_OBJECT(res, object) RES_FROM_OBJECT_RESTORE_ERH(res, object, NULL)
++
+ #define PHP_SQLITE_EMPTY_QUERY \
+- if (!sql_len) { \
++ if (!sql_len || !*sql) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute empty query."); \
+ RETURN_FALSE; \
+ }
+@@ -98,15 +143,15 @@
+ int curr_row;
+ char **col_names;
+ int alloc_rows;
+- char **table;
+ int mode;
++ char **table;
+ };
+
+ struct php_sqlite_db {
+ sqlite *db;
+ int last_err_code;
+- int is_persistent;
+- int rsrc_id;
++ zend_bool is_persistent;
++ long rsrc_id;
+
+ HashTable callbacks;
+ };
+@@ -118,62 +163,475 @@
+ zval *fini;
+ };
+
++static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC);
++static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC);
+
+ enum { PHPSQLITE_ASSOC = 1, PHPSQLITE_NUM = 2, PHPSQLITE_BOTH = PHPSQLITE_ASSOC|PHPSQLITE_NUM };
+
+-function_entry sqlite_functions[] = {
+- PHP_FE(sqlite_open, arg3_force_ref)
+- PHP_FE(sqlite_popen, arg3_force_ref)
+- PHP_FE(sqlite_close, NULL)
+- PHP_FE(sqlite_query, NULL)
+- PHP_FE(sqlite_exec, NULL)
+- PHP_FE(sqlite_array_query, NULL)
+- PHP_FE(sqlite_single_query, NULL)
+- PHP_FE(sqlite_fetch_array, NULL)
+- PHP_FE(sqlite_fetch_single, NULL)
+- PHP_FALIAS(sqlite_fetch_string, sqlite_fetch_single, NULL)
+- PHP_FE(sqlite_fetch_all, NULL)
+- PHP_FE(sqlite_current, NULL)
+- PHP_FE(sqlite_column, NULL)
+- PHP_FE(sqlite_libversion, NULL)
+- PHP_FE(sqlite_libencoding, NULL)
+- PHP_FE(sqlite_changes, NULL)
+- PHP_FE(sqlite_last_insert_rowid, NULL)
+- PHP_FE(sqlite_num_rows, NULL)
+- PHP_FE(sqlite_num_fields, NULL)
+- PHP_FE(sqlite_field_name, NULL)
+- PHP_FE(sqlite_seek, NULL)
+- PHP_FE(sqlite_rewind, NULL)
+- PHP_FE(sqlite_next, NULL)
+- PHP_FE(sqlite_has_more, NULL)
+- PHP_FE(sqlite_escape_string, NULL)
+- PHP_FE(sqlite_busy_timeout, NULL)
+- PHP_FE(sqlite_last_error, NULL)
+- PHP_FE(sqlite_error_string, NULL)
+- PHP_FE(sqlite_unbuffered_query, NULL)
+- PHP_FE(sqlite_create_aggregate, NULL)
+- PHP_FE(sqlite_create_function, NULL)
+- PHP_FE(sqlite_udf_encode_binary, NULL)
+- PHP_FE(sqlite_udf_decode_binary, NULL)
++/* {{{ arginfo */
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_popen, 0, 0, 1)
++ ZEND_ARG_INFO(0, filename)
++ ZEND_ARG_INFO(0, mode)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_open, 0, 0, 1)
++ ZEND_ARG_INFO(0, filename)
++ ZEND_ARG_INFO(0, mode)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_factory, 0, 0, 1)
++ ZEND_ARG_INFO(0, filename)
++ ZEND_ARG_INFO(0, mode)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_busy_timeout, 0, 0, 2)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, ms)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_busy_timeout, 0, 0, 1)
++ ZEND_ARG_INFO(0, ms)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_close, 0, 0, 1)
++ ZEND_ARG_INFO(0, db)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_unbuffered_query, 0, 0, 2)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_unbuffered_query, 0, 0, 1)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_column_types, 0, 0, 2)
++ ZEND_ARG_INFO(0, table_name)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, result_type)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_column_types, 0, 0, 1)
++ ZEND_ARG_INFO(0, table_name)
++ ZEND_ARG_INFO(0, result_type)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_query, 0, 0, 2)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_query, 0, 0, 1)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_exec, 0, 0, 2)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_exec, 0, 0, 1)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(1, error_message)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_all, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_all, 0, 0, 0)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_array, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_array, 0, 0, 0)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_object, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, class_name)
++ ZEND_ARG_INFO(0, ctor_params)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_object, 0, 0, 0)
++ ZEND_ARG_INFO(0, class_name)
++ ZEND_ARG_INFO(0, ctor_params)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_array_query, 0, 0, 2)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_array_query, 0, 0, 1)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_single_query, 0, 0, 2)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, first_row_only)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_single_query, 0, 0, 1)
++ ZEND_ARG_INFO(0, query)
++ ZEND_ARG_INFO(0, first_row_only)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_single, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_single, 0, 0, 0)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_current, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_current, 0, 0, 0)
++ ZEND_ARG_INFO(0, result_type)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_column, 0, 0, 2)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, index_or_name)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_column, 0, 0, 1)
++ ZEND_ARG_INFO(0, index_or_name)
++ ZEND_ARG_INFO(0, decode_binary)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_libversion, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_libencoding, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_changes, 0, 0, 1)
++ ZEND_ARG_INFO(0, db)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_changes, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_last_insert_rowid, 0, 0, 1)
++ ZEND_ARG_INFO(0, db)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_last_insert_rowid, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_num_rows, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_num_rows, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_valid, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_valid, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_has_prev, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_has_prev, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_num_fields, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_num_fields, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_field_name, 0, 0, 2)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, field_index)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_field_name, 0, 0, 1)
++ ZEND_ARG_INFO(0, field_index)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_seek, 0, 0, 2)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(0, row)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_seek, 0, 0, 1)
++ ZEND_ARG_INFO(0, row)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_rewind, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_rewind, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_next, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_next, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_key, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_key, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_prev, 0, 0, 1)
++ ZEND_ARG_INFO(0, result)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_prev, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_escape_string, 0, 0, 1)
++ ZEND_ARG_INFO(0, item)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_last_error, 0, 0, 1)
++ ZEND_ARG_INFO(0, db)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_last_error, 0)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_error_string, 0, 0, 1)
++ ZEND_ARG_INFO(0, error_code)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_create_aggregate, 0, 0, 4)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, funcname)
++ ZEND_ARG_INFO(0, step_func)
++ ZEND_ARG_INFO(0, finalize_func)
++ ZEND_ARG_INFO(0, num_args)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_create_aggregate, 0, 0, 3)
++ ZEND_ARG_INFO(0, funcname)
++ ZEND_ARG_INFO(0, step_func)
++ ZEND_ARG_INFO(0, finalize_func)
++ ZEND_ARG_INFO(0, num_args)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_create_function, 0, 0, 3)
++ ZEND_ARG_INFO(0, db)
++ ZEND_ARG_INFO(0, funcname)
++ ZEND_ARG_INFO(0, callback)
++ ZEND_ARG_INFO(0, num_args)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_create_function, 0, 0, 2)
++ ZEND_ARG_INFO(0, funcname)
++ ZEND_ARG_INFO(0, callback)
++ ZEND_ARG_INFO(0, num_args)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_udf_encode_binary, 0, 0, 1)
++ ZEND_ARG_INFO(0, data)
++ZEND_END_ARG_INFO()
++
++ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_udf_decode_binary, 0, 0, 1)
++ ZEND_ARG_INFO(0, data)
++ZEND_END_ARG_INFO()
++/* }}} */
++
++const zend_function_entry sqlite_functions[] = {
++ PHP_FE(sqlite_open, arginfo_sqlite_open)
++ PHP_FE(sqlite_popen, arginfo_sqlite_popen)
++ PHP_FE(sqlite_close, arginfo_sqlite_close)
++ PHP_FE(sqlite_query, arginfo_sqlite_query)
++ PHP_FE(sqlite_exec, arginfo_sqlite_exec)
++ PHP_FE(sqlite_array_query, arginfo_sqlite_array_query)
++ PHP_FE(sqlite_single_query, arginfo_sqlite_single_query)
++ PHP_FE(sqlite_fetch_array, arginfo_sqlite_fetch_array)
++ PHP_FE(sqlite_fetch_object, arginfo_sqlite_fetch_object)
++ PHP_FE(sqlite_fetch_single, arginfo_sqlite_fetch_single)
++ PHP_FALIAS(sqlite_fetch_string, sqlite_fetch_single, arginfo_sqlite_fetch_single)
++ PHP_FE(sqlite_fetch_all, arginfo_sqlite_fetch_all)
++ PHP_FE(sqlite_current, arginfo_sqlite_current)
++ PHP_FE(sqlite_column, arginfo_sqlite_column)
++ PHP_FE(sqlite_libversion, arginfo_sqlite_libversion)
++ PHP_FE(sqlite_libencoding, arginfo_sqlite_libencoding)
++ PHP_FE(sqlite_changes, arginfo_sqlite_changes)
++ PHP_FE(sqlite_last_insert_rowid, arginfo_sqlite_last_insert_rowid)
++ PHP_FE(sqlite_num_rows, arginfo_sqlite_num_rows)
++ PHP_FE(sqlite_num_fields, arginfo_sqlite_num_fields)
++ PHP_FE(sqlite_field_name, arginfo_sqlite_field_name)
++ PHP_FE(sqlite_seek, arginfo_sqlite_seek)
++ PHP_FE(sqlite_rewind, arginfo_sqlite_rewind)
++ PHP_FE(sqlite_next, arginfo_sqlite_next)
++ PHP_FE(sqlite_prev, arginfo_sqlite_prev)
++ PHP_FE(sqlite_valid, arginfo_sqlite_valid)
++ PHP_FALIAS(sqlite_has_more, sqlite_valid, arginfo_sqlite_valid)
++ PHP_FE(sqlite_has_prev, arginfo_sqlite_has_prev)
++ PHP_FE(sqlite_escape_string, arginfo_sqlite_escape_string)
++ PHP_FE(sqlite_busy_timeout, arginfo_sqlite_busy_timeout)
++ PHP_FE(sqlite_last_error, arginfo_sqlite_last_error)
++ PHP_FE(sqlite_error_string, arginfo_sqlite_error_string)
++ PHP_FE(sqlite_unbuffered_query, arginfo_sqlite_unbuffered_query)
++ PHP_FE(sqlite_create_aggregate, arginfo_sqlite_create_aggregate)
++ PHP_FE(sqlite_create_function, arginfo_sqlite_create_function)
++ PHP_FE(sqlite_factory, arginfo_sqlite_factory)
++ PHP_FE(sqlite_udf_encode_binary, arginfo_sqlite_udf_encode_binary)
++ PHP_FE(sqlite_udf_decode_binary, arginfo_sqlite_udf_decode_binary)
++ PHP_FE(sqlite_fetch_column_types, arginfo_sqlite_fetch_column_types)
++ {NULL, NULL, NULL}
++};
++
++const zend_function_entry sqlite_funcs_db[] = {
++ PHP_ME_MAPPING(__construct, sqlite_open, arginfo_sqlite_open, 0)
++/* PHP_ME_MAPPING(close, sqlite_close, NULL, 0)*/
++ PHP_ME_MAPPING(query, sqlite_query, arginfo_sqlite_method_query, 0)
++ PHP_ME_MAPPING(queryExec, sqlite_exec, arginfo_sqlite_method_exec, 0)
++ PHP_ME_MAPPING(arrayQuery, sqlite_array_query, arginfo_sqlite_method_array_query, 0)
++ PHP_ME_MAPPING(singleQuery, sqlite_single_query, arginfo_sqlite_method_single_query, 0)
++ PHP_ME_MAPPING(unbufferedQuery, sqlite_unbuffered_query, arginfo_sqlite_method_unbuffered_query, 0)
++ PHP_ME_MAPPING(lastInsertRowid, sqlite_last_insert_rowid, arginfo_sqlite_method_last_insert_rowid, 0)
++ PHP_ME_MAPPING(changes, sqlite_changes, arginfo_sqlite_method_changes, 0)
++ PHP_ME_MAPPING(createAggregate, sqlite_create_aggregate, arginfo_sqlite_method_create_aggregate, 0)
++ PHP_ME_MAPPING(createFunction, sqlite_create_function, arginfo_sqlite_method_create_function, 0)
++ PHP_ME_MAPPING(busyTimeout, sqlite_busy_timeout, arginfo_sqlite_method_busy_timeout, 0)
++ PHP_ME_MAPPING(lastError, sqlite_last_error, arginfo_sqlite_method_last_error, 0)
++ PHP_ME_MAPPING(fetchColumnTypes, sqlite_fetch_column_types, arginfo_sqlite_method_fetch_column_types, 0)
++/* PHP_ME_MAPPING(error_string, sqlite_error_string, NULL, 0) static */
++/* PHP_ME_MAPPING(escape_string, sqlite_escape_string, NULL, 0) static */
++ {NULL, NULL, NULL}
++};
++
++const zend_function_entry sqlite_funcs_query[] = {
++ PHP_ME_MAPPING(fetch, sqlite_fetch_array, arginfo_sqlite_method_fetch_array, 0)
++ PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, arginfo_sqlite_method_fetch_object, 0)
++ PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, arginfo_sqlite_method_fetch_single, 0)
++ PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, arginfo_sqlite_method_fetch_all, 0)
++ PHP_ME_MAPPING(column, sqlite_column, arginfo_sqlite_method_column, 0)
++ PHP_ME_MAPPING(numFields, sqlite_num_fields, arginfo_sqlite_method_num_fields, 0)
++ PHP_ME_MAPPING(fieldName, sqlite_field_name, arginfo_sqlite_method_field_name, 0)
++ /* iterator */
++ PHP_ME_MAPPING(current, sqlite_current, arginfo_sqlite_method_current, 0)
++ PHP_ME_MAPPING(key, sqlite_key, arginfo_sqlite_method_key, 0)
++ PHP_ME_MAPPING(next, sqlite_next, arginfo_sqlite_method_next, 0)
++ PHP_ME_MAPPING(valid, sqlite_valid, arginfo_sqlite_method_valid, 0)
++ PHP_ME_MAPPING(rewind, sqlite_rewind, arginfo_sqlite_method_rewind, 0)
++ /* countable */
++ PHP_ME_MAPPING(count, sqlite_num_rows, arginfo_sqlite_method_num_rows, 0)
++ /* additional */
++ PHP_ME_MAPPING(prev, sqlite_prev, arginfo_sqlite_method_prev, 0)
++ PHP_ME_MAPPING(hasPrev, sqlite_has_prev, arginfo_sqlite_method_has_prev, 0)
++ PHP_ME_MAPPING(numRows, sqlite_num_rows, arginfo_sqlite_method_num_rows, 0)
++ PHP_ME_MAPPING(seek, sqlite_seek, arginfo_sqlite_method_seek, 0)
++ {NULL, NULL, NULL}
++};
++
++const zend_function_entry sqlite_funcs_ub_query[] = {
++ PHP_ME_MAPPING(fetch, sqlite_fetch_array, arginfo_sqlite_method_fetch_array, 0)
++ PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, arginfo_sqlite_method_fetch_object, 0)
++ PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, arginfo_sqlite_method_fetch_single, 0)
++ PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, arginfo_sqlite_method_fetch_all, 0)
++ PHP_ME_MAPPING(column, sqlite_column, arginfo_sqlite_method_column, 0)
++ PHP_ME_MAPPING(numFields, sqlite_num_fields, arginfo_sqlite_method_num_fields, 0)
++ PHP_ME_MAPPING(fieldName, sqlite_field_name, arginfo_sqlite_method_field_name, 0)
++ /* iterator */
++ PHP_ME_MAPPING(current, sqlite_current, arginfo_sqlite_method_current, 0)
++ PHP_ME_MAPPING(next, sqlite_next, arginfo_sqlite_method_next, 0)
++ PHP_ME_MAPPING(valid, sqlite_valid, arginfo_sqlite_method_valid, 0)
+ {NULL, NULL, NULL}
+ };
+
++const zend_function_entry sqlite_funcs_exception[] = {
++ {NULL, NULL, NULL}
++};
++
++/* Dependancies */
++static const zend_module_dep sqlite_deps[] = {
++#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
++ ZEND_MOD_REQUIRED("spl")
++#endif
++#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
++ ZEND_MOD_REQUIRED("session")
++#endif
++#ifdef PHP_SQLITE2_HAVE_PDO
++ ZEND_MOD_REQUIRED("pdo")
++#endif
++ {NULL, NULL, NULL}
++};
+
+ zend_module_entry sqlite_module_entry = {
+-#if ZEND_MODULE_API_NO >= 20010901
++#if ZEND_MODULE_API_NO >= 20050922
++ STANDARD_MODULE_HEADER_EX, NULL,
++ sqlite_deps,
++#elif ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+ #endif
+- "sqlite",
++ "SQLite",
+ sqlite_functions,
+ PHP_MINIT(sqlite),
+- NULL,
++ PHP_MSHUTDOWN(sqlite),
+ NULL,
+ PHP_RSHUTDOWN(sqlite),
+ PHP_MINFO(sqlite),
+ #if ZEND_MODULE_API_NO >= 20010901
+ PHP_SQLITE_MODULE_VERSION,
+ #endif
++#if ZEND_MODULE_API_NO >= 20060613
++ PHP_MODULE_GLOBALS(sqlite),
++ PHP_GINIT(sqlite),
++ NULL,
++ NULL,
++ STANDARD_MODULE_PROPERTIES_EX
++#else
+ STANDARD_MODULE_PROPERTIES
++#endif
+ };
+
+
+@@ -218,11 +676,11 @@
+ {
+ if (rsrc->ptr) {
+ struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
+-
++
+ sqlite_close(db->db);
+
+ zend_hash_destroy(&db->callbacks);
+-
++
+ pefree(db, db->is_persistent);
+
+ rsrc->ptr = NULL;
+@@ -264,6 +722,17 @@
+ efree(res);
+ }
+
++static int _clean_unfinished_results(zend_rsrc_list_entry *le, void *db TSRMLS_DC)
++{
++ if (Z_TYPE_P(le) == le_sqlite_result) {
++ struct php_sqlite_result *res = (struct php_sqlite_result *)le->ptr;
++ if (res->db->rsrc_id == ((struct php_sqlite_db*)db)->rsrc_id) {
++ return ZEND_HASH_APPLY_REMOVE;
++ }
++ }
++ return ZEND_HASH_APPLY_KEEP;
++}
++
+ static ZEND_RSRC_DTOR_FUNC(php_sqlite_result_dtor)
+ {
+ struct php_sqlite_result *res = (struct php_sqlite_result *)rsrc->ptr;
+@@ -280,12 +749,12 @@
+
+ /* prevent bad mojo if someone tries to use a previously registered function in the next request */
+ zend_hash_apply(&db->callbacks, (apply_func_t)php_sqlite_callback_invalidator TSRMLS_CC);
+-
++
+ db->rsrc_id = FAILURE;
+
+ /* don't leave pending commits hanging around */
+ sqlite_exec(db->db, "ROLLBACK", NULL, NULL, NULL);
+-
++
+ return 0;
+ }
+
+@@ -310,21 +779,21 @@
+ sqlite_set_result_error(func, "not enough parameters", -1);
+ return;
+ }
+-
+- ZVAL_STRING(&funcname, (char*)argv[0], 0);
+
+- if (!zend_is_callable(&funcname, 0, &callable)) {
+- spprintf(&errbuf, 0, "function `%s' is not callable", callable);
++ ZVAL_STRING(&funcname, (char*)argv[0], 1);
++
++ if (!zend_make_callable(&funcname, &callable TSRMLS_CC)) {
++ spprintf(&errbuf, 0, "function `%s' is not a function name", callable);
+ sqlite_set_result_error(func, errbuf, -1);
+ efree(errbuf);
+ efree(callable);
++ zval_dtor(&funcname);
+ return;
+ }
+- efree(callable);
+-
++
+ if (argc > 1) {
+ zargs = (zval ***)safe_emalloc((argc - 1), sizeof(zval **), 0);
+-
++
+ for (i = 0; i < argc-1; i++) {
+ zargs[i] = emalloc(sizeof(zval *));
+ MAKE_STD_ZVAL(*zargs[i]);
+@@ -340,6 +809,8 @@
+ zargs,
+ 0, NULL TSRMLS_CC);
+
++ zval_dtor(&funcname);
++
+ if (res == SUCCESS) {
+ if (retval == NULL) {
+ sqlite_set_result_string(func, NULL, 0);
+@@ -361,9 +832,14 @@
+ }
+ }
+ } else {
+- sqlite_set_result_error(func, "call_user_function_ex failed", -1);
++ char *errbuf;
++ spprintf(&errbuf, 0, "call_user_function_ex failed for function %s()", callable);
++ sqlite_set_result_error(func, errbuf, -1);
++ efree(errbuf);
+ }
+
++ efree(callable);
++
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+@@ -394,7 +870,7 @@
+
+ if (argc > 0) {
+ zargs = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
+-
++
+ for (i = 0; i < argc; i++) {
+ zargs[i] = emalloc(sizeof(zval *));
+ MAKE_STD_ZVAL(*zargs[i]);
+@@ -473,16 +949,16 @@
+ if (argc < 1) {
+ return;
+ }
+-
++
+ zargc = argc + 1;
+ zargs = (zval ***)safe_emalloc(zargc, sizeof(zval **), 0);
+-
++
+ /* first arg is always the context zval */
+ context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
+
+ if (*context_p == NULL) {
+ MAKE_STD_ZVAL(*context_p);
+- (*context_p)->is_ref = 1;
++ Z_SET_ISREF_PP(context_p);
+ Z_TYPE_PP(context_p) = IS_NULL;
+ }
+
+@@ -538,9 +1014,9 @@
+ sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
+ return;
+ }
+-
++
+ context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
+-
++
+ res = call_user_function_ex(EG(function_table),
+ NULL,
+ funcs->fini,
+@@ -590,9 +1066,6 @@
+ case SQLITE_COPY:
+ if (strncmp(arg4, ":memory:", sizeof(":memory:") - 1)) {
+ TSRMLS_FETCH();
+- if (PG(safe_mode) && (!php_checkuid(arg4, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+- return SQLITE_DENY;
+- }
+
+ if (php_check_open_basedir(arg4 TSRMLS_CC)) {
+ return SQLITE_DENY;
+@@ -603,9 +1076,6 @@
+ case SQLITE_ATTACH:
+ if (strncmp(arg3, ":memory:", sizeof(":memory:") - 1)) {
+ TSRMLS_FETCH();
+- if (PG(safe_mode) && (!php_checkuid(arg3, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+- return SQLITE_DENY;
+- }
+
+ if (php_check_open_basedir(arg3 TSRMLS_CC)) {
+ return SQLITE_DENY;
+@@ -621,18 +1091,303 @@
+ }
+ /* }}} */
+
+-static int init_sqlite_globals(zend_sqlite_globals *g)
++/* {{{ OO init/structure stuff */
++#define REGISTER_SQLITE_CLASS(name, c_name, parent) \
++ { \
++ zend_class_entry ce; \
++ INIT_CLASS_ENTRY(ce, "SQLite" # name, sqlite_funcs_ ## c_name); \
++ ce.create_object = sqlite_object_new_ ## c_name; \
++ sqlite_ce_ ## c_name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
++ memcpy(&sqlite_object_handlers_ ## c_name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
++ sqlite_object_handlers_ ## c_name.clone_obj = NULL; \
++ sqlite_ce_ ## c_name->ce_flags |= ZEND_ACC_FINAL_CLASS; \
++ }
++
++zend_class_entry *sqlite_ce_db, *sqlite_ce_exception;
++zend_class_entry *sqlite_ce_query, *sqlite_ce_ub_query;
++
++static zend_object_handlers sqlite_object_handlers_db;
++static zend_object_handlers sqlite_object_handlers_query;
++static zend_object_handlers sqlite_object_handlers_ub_query;
++static zend_object_handlers sqlite_object_handlers_exception;
++
++typedef enum {
++ is_db,
++ is_result
++} sqlite_obj_type;
++
++typedef struct _sqlite_object {
++ zend_object std;
++ sqlite_obj_type type;
++ union {
++ struct php_sqlite_db *db;
++ struct php_sqlite_result *res;
++ void *ptr;
++ } u;
++} sqlite_object;
++
++static int sqlite_free_persistent(zend_rsrc_list_entry *le, void *ptr TSRMLS_DC)
+ {
+- g->assoc_case = 0;
+- return SUCCESS;
++ return le->ptr == ptr ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP;
+ }
+
+-PHP_MINIT_FUNCTION(sqlite)
++static void sqlite_object_free_storage(void *object TSRMLS_DC)
+ {
+- ZEND_INIT_MODULE_GLOBALS(sqlite, init_sqlite_globals, NULL);
++ sqlite_object *intern = (sqlite_object *)object;
++
++ zend_object_std_dtor(&intern->std TSRMLS_CC);
++
++ if (intern->u.ptr) {
++ if (intern->type == is_db) {
++ if (intern->u.db->rsrc_id) {
++ zend_list_delete(intern->u.db->rsrc_id);
++ zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) sqlite_free_persistent, &intern->u.ptr TSRMLS_CC);
++ }
++ } else {
++ real_result_dtor(intern->u.res TSRMLS_CC);
++ }
++ }
++
++ efree(object);
++}
++
++static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
++{
++ sqlite_object *intern;
++
++ intern = emalloc(sizeof(sqlite_object));
++ memset(intern, 0, sizeof(sqlite_object));
++
++ zend_object_std_init(&intern->std, class_type TSRMLS_CC);
++ object_properties_init(&intern->std, class_type);
+
++ retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC);
++ retval->handlers = handlers;
++}
++
++static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC)
++{
++ zend_object_value retval;
++
++ sqlite_object_new(class_type, &sqlite_object_handlers_db, &retval TSRMLS_CC);
++ return retval;
++}
++
++static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC)
++{
++ zend_object_value retval;
++
++ sqlite_object_new(class_type, &sqlite_object_handlers_query, &retval TSRMLS_CC);
++ return retval;
++}
++
++static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC)
++{
++ zend_object_value retval;
++
++ sqlite_object_new(class_type, &sqlite_object_handlers_ub_query, &retval TSRMLS_CC);
++ return retval;
++}
++
++static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
++{
++ zend_object_value retval;
++
++ sqlite_object_new(class_type, &sqlite_object_handlers_exception, &retval TSRMLS_CC);
++ return retval;
++}
++
++#define SQLITE_REGISTER_OBJECT(_type, _object, _ptr) \
++ { \
++ sqlite_object *obj; \
++ obj = (sqlite_object*)zend_object_store_get_object(_object TSRMLS_CC); \
++ obj->type = is_ ## _type; \
++ obj->u._type = _ptr; \
++ }
++
++static zend_class_entry *sqlite_get_ce_query(const zval *object TSRMLS_DC)
++{
++ return sqlite_ce_query;
++}
++
++static zend_class_entry *sqlite_get_ce_ub_query(const zval *object TSRMLS_DC)
++{
++ return sqlite_ce_ub_query;
++}
++
++static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
++{
++ if (!object) {
++ ALLOC_ZVAL(object);
++ }
++ Z_TYPE_P(object) = IS_OBJECT;
++ object_init_ex(object, pce);
++ Z_SET_REFCOUNT_P(object, 1);
++ Z_SET_ISREF_P(object);
++ return object;
++}
++
++typedef struct _sqlite_object_iterator {
++ zend_object_iterator it;
++ struct php_sqlite_result *res;
++ zval *value;
++} sqlite_object_iterator;
++
++void sqlite_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
++{
++ zval *object = (zval*)((sqlite_object_iterator*)iter)->it.data;
++
++ if (((sqlite_object_iterator*)iter)->value) {
++ zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
++ ((sqlite_object_iterator*)iter)->value = NULL;
++ }
++ zval_ptr_dtor(&object);
++ efree(iter);
++}
++
++void sqlite_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
++{
++ struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
++
++ if (((sqlite_object_iterator*)iter)->value) {
++ zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
++ ((sqlite_object_iterator*)iter)->value = NULL;
++ }
++ if (res) {
++ res->curr_row = 0;
++ }
++}
++
++int sqlite_iterator_valid(zend_object_iterator *iter TSRMLS_DC)
++{
++ struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
++
++ if (res && res->curr_row < res->nrows && res->nrows) { /* curr_row may be -1 */
++ return SUCCESS;
++ } else {
++ return FAILURE;
++ }
++}
++
++void sqlite_iterator_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
++{
++ struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
++
++ *data = &((sqlite_object_iterator*)iter)->value;
++ if (res && !**data) {
++ MAKE_STD_ZVAL(**data);
++ php_sqlite_fetch_array(res, res->mode, 1, 0, **data TSRMLS_CC);
++ }
++
++}
++
++int sqlite_iterator_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
++{
++ struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
++
++ *str_key = NULL;
++ *str_key_len = 0;
++ *int_key = res ? res->curr_row : 0;
++ return HASH_KEY_IS_LONG;
++}
++
++void sqlite_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
++{
++ struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
++
++ if (((sqlite_object_iterator*)iter)->value) {
++ zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
++ ((sqlite_object_iterator*)iter)->value = NULL;
++ }
++ if (res) {
++ if (!res->buffered && res->vm) {
++ php_sqlite_fetch(res TSRMLS_CC);
++ }
++ if (res->curr_row >= res->nrows) {
++ /* php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available"); */
++ return;
++ }
++
++ res->curr_row++;
++ }
++}
++
++zend_object_iterator_funcs sqlite_ub_query_iterator_funcs = {
++ sqlite_iterator_dtor,
++ sqlite_iterator_valid,
++ sqlite_iterator_get_current_data,
++ sqlite_iterator_get_current_key,
++ sqlite_iterator_move_forward,
++ NULL
++};
++
++zend_object_iterator_funcs sqlite_query_iterator_funcs = {
++ sqlite_iterator_dtor,
++ sqlite_iterator_valid,
++ sqlite_iterator_get_current_data,
++ sqlite_iterator_get_current_key,
++ sqlite_iterator_move_forward,
++ sqlite_iterator_rewind
++};
++
++zend_object_iterator *sqlite_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
++{
++ sqlite_object_iterator *iterator = emalloc(sizeof(sqlite_object_iterator));
++
++ sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
++
++ if (by_ref) {
++ zend_error(E_RECOVERABLE_ERROR, "An iterator cannot be used with foreach by reference");
++ }
++ Z_ADDREF_P(object);
++ iterator->it.data = (void*)object;
++ iterator->it.funcs = ce->iterator_funcs.funcs;
++ iterator->res = obj->u.res;
++ iterator->value = NULL;
++ return (zend_object_iterator*)iterator;
++}
++/* }}} */
++
++static PHP_GINIT_FUNCTION(sqlite)
++{
++ sqlite_globals->assoc_case = 0;
++}
++
++PHP_MINIT_FUNCTION(sqlite)
++{
++ REGISTER_SQLITE_CLASS(Database, db, NULL);
++ REGISTER_SQLITE_CLASS(Result, query, NULL);
++ REGISTER_SQLITE_CLASS(Unbuffered, ub_query, NULL);
++#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
++ REGISTER_SQLITE_CLASS(Exception, exception, spl_ce_RuntimeException);
++#else
++ REGISTER_SQLITE_CLASS(Exception, exception, zend_exception_get_default(TSRMLS_C));
++#endif
++
++ sqlite_ce_db->ce_flags &= ~ZEND_ACC_FINAL_CLASS;
++ sqlite_ce_db->constructor->common.fn_flags |= ZEND_ACC_FINAL;
++
++ sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
++ sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
++ sqlite_object_handlers_ub_query.count_elements = sqlite_count_elements;
++
++ sqlite_ce_ub_query->get_iterator = sqlite_get_iterator;
++ sqlite_ce_ub_query->iterator_funcs.funcs = &sqlite_ub_query_iterator_funcs;
++
++#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
++ zend_class_implements(sqlite_ce_query TSRMLS_CC, 2, zend_ce_iterator, spl_ce_Countable);
++#else
++ zend_class_implements(sqlite_ce_query TSRMLS_CC, 1, zend_ce_iterator);
++#endif
++ sqlite_ce_query->get_iterator = sqlite_get_iterator;
++ sqlite_ce_query->iterator_funcs.funcs = &sqlite_query_iterator_funcs;
++
+ REGISTER_INI_ENTRIES();
+
++#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
++ php_session_register_module(ps_sqlite_ptr);
++#endif
++
+ le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number);
+ le_sqlite_pdb = zend_register_list_destructors_ex(NULL, php_sqlite_db_dtor, "sqlite database (persistent)", module_number);
+ le_sqlite_result = zend_register_list_destructors_ex(php_sqlite_result_dtor, NULL, "sqlite result", module_number);
+@@ -640,7 +1395,7 @@
+ REGISTER_LONG_CONSTANT("SQLITE_BOTH", PHPSQLITE_BOTH, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_NUM", PHPSQLITE_NUM, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_ASSOC", PHPSQLITE_ASSOC, CONST_CS|CONST_PERSISTENT);
+-
++
+ REGISTER_LONG_CONSTANT("SQLITE_OK", SQLITE_OK, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_ERROR", SQLITE_ERROR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_INTERNAL", SQLITE_INTERNAL, CONST_CS|CONST_PERSISTENT);
+@@ -665,18 +1420,30 @@
+ REGISTER_LONG_CONSTANT("SQLITE_MISUSE", SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_NOLFS", SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_AUTH", SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
++ REGISTER_LONG_CONSTANT("SQLITE_NOTADB", SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
+ #ifdef SQLITE_FORMAT
+ REGISTER_LONG_CONSTANT("SQLITE_FORMAT", SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
+ #endif
+-#ifdef SQLITE_RANGE
+- REGISTER_LONG_CONSTANT("SQLITE_RANGE", SQLITE_RANGE, CONST_CS|CONST_PERSISTENT);
+-#endif
+-#ifdef SQLITE_NOTADB
+- REGISTER_LONG_CONSTANT("SQLITE_NOTADB", SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
+-#endif
+ REGISTER_LONG_CONSTANT("SQLITE_ROW", SQLITE_ROW, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLITE_DONE", SQLITE_DONE, CONST_CS|CONST_PERSISTENT);
+
++#ifdef PHP_SQLITE2_HAVE_PDO
++ if (FAILURE == php_pdo_register_driver(&pdo_sqlite2_driver)) {
++ return FAILURE;
++ }
++#endif
++
++ return SUCCESS;
++}
++
++PHP_MSHUTDOWN_FUNCTION(sqlite)
++{
++ UNREGISTER_INI_ENTRIES();
++
++#ifdef PHP_SQLITE2_HAVE_PDO
++ php_pdo_unregister_driver(&pdo_sqlite2_driver);
++#endif
++
+ return SUCCESS;
+ }
+
+@@ -684,7 +1451,7 @@
+ {
+ php_info_print_table_start();
+ php_info_print_table_header(2, "SQLite support", "enabled");
+- php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id: sqlite.c,v 1.62.2.25 2004/07/10 12:25:33 wez Exp $");
++ php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id: sqlite.c 299692 2010-05-24 14:11:39Z dmitry $");
+ php_info_print_table_row(2, "SQLite Library", sqlite_libversion());
+ php_info_print_table_row(2, "SQLite Encoding", sqlite_libencoding());
+ php_info_print_table_end();
+@@ -692,7 +1459,7 @@
+ DISPLAY_INI_ENTRIES();
+ }
+
+-static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg TSRMLS_DC)
++static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg, zval *object TSRMLS_DC)
+ {
+ char *errtext = NULL;
+ sqlite *sdb = NULL;
+@@ -710,7 +1477,12 @@
+
+ sqlite_freemem(errtext);
+
+- RETVAL_FALSE;
++ /* if object is not an object then we're called from the factory() function */
++ if (object && Z_TYPE_P(object) != IS_OBJECT) {
++ RETVAL_NULL();
++ } else {
++ RETVAL_FALSE;
++ }
+ return NULL;
+ }
+
+@@ -720,7 +1492,7 @@
+ db->db = sdb;
+
+ zend_hash_init(&db->callbacks, 0, NULL, php_sqlite_callback_dtor, db->is_persistent);
+-
++
+ /* register the PHP functions */
+ sqlite_create_function(sdb, "php", -1, php_sqlite_generic_function_callback, 0);
+
+@@ -731,12 +1503,22 @@
+ /* authorizer hook so we can enforce safe mode
+ * Note: the declaration of php_sqlite_authorizer is correct for 2.8.2 of libsqlite,
+ * and IS backwards binary compatible with earlier versions */
+- sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL);
+-
+- db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db);
++ if (PG(open_basedir) && *PG(open_basedir)) {
++ sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL);
++ }
++
++ db->rsrc_id = ZEND_REGISTER_RESOURCE(object ? NULL : return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db);
++ if (object) {
++ /* if object is not an object then we're called from the factory() function */
++ if (Z_TYPE_P(object) != IS_OBJECT) {
++ sqlite_instanciate(sqlite_ce_db, object TSRMLS_CC);
++ }
++ /* and now register the object */
++ SQLITE_REGISTER_OBJECT(db, object, db)
++ }
+
+ if (persistent_id) {
+- list_entry le;
++ zend_rsrc_list_entry le;
+
+ Z_TYPE(le) = le_sqlite_pdb;
+ le.ptr = db;
+@@ -747,51 +1529,51 @@
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent resource");
+ }
+ }
+-
++
+ return db;
+ }
+
+-/* {{{ proto resource sqlite_popen(string filename [, int mode, string &errmessage])
+- Opens a persistent handle to an SQLite database. Will create the database if it does not exist */
++/* {{{ proto resource sqlite_popen(string filename [, int mode [, string &error_message]])
++ Opens a persistent handle to a SQLite database. Will create the database if it does not exist. */
+ PHP_FUNCTION(sqlite_popen)
+ {
+- int mode = 0666;
++ long mode = 0666;
+ char *filename, *fullpath, *hashkey;
+- long filename_len, hashkeylen;
++ int filename_len, hashkeylen;
+ zval *errmsg = NULL;
+ struct php_sqlite_db *db = NULL;
+- list_entry *le;
+-
++ zend_rsrc_list_entry *le;
++
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
+ &filename, &filename_len, &mode, &errmsg)) {
+ return;
+ }
+ if (errmsg) {
+ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
+ }
+
+ if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
+ /* resolve the fully-qualified path name to use as the hash key */
+- fullpath = expand_filepath(filename, NULL TSRMLS_CC);
+-
+- if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
++ if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
+ RETURN_FALSE;
+ }
+
+ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
++ efree(fullpath);
+ RETURN_FALSE;
+ }
+ } else {
+ fullpath = estrndup(filename, filename_len);
+ }
+
+- hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%d", fullpath, mode);
+-
++ hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%ld", fullpath, mode);
++
+ /* do we have an existing persistent connection ? */
+ if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkeylen+1, (void*)&le)) {
+ if (Z_TYPE_P(le) == le_sqlite_pdb) {
+ db = (struct php_sqlite_db*)le->ptr;
+-
++
+ if (db->rsrc_id == FAILURE) {
+ /* give it a valid resource id for this request */
+ db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
+@@ -799,7 +1581,7 @@
+ int type;
+ /* sanity check to ensure that the resource is still a valid regular resource
+ * number */
+- if (_zend_list_find(db->rsrc_id, &type TSRMLS_CC) == db) {
++ if (zend_list_find(db->rsrc_id, &type) == db) {
+ /* already accessed this request; map it */
+ zend_list_addref(db->rsrc_id);
+ ZVAL_RESOURCE(return_value, db->rsrc_id);
+@@ -809,109 +1591,174 @@
+ }
+
+ /* all set */
+- efree(fullpath);
+- efree(hashkey);
+- return;
++ goto done;
+ }
+
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Some other type of persistent resource is using this hash key!?");
+- RETURN_FALSE;
++ RETVAL_FALSE;
++ goto done;
+ }
+
+ /* now we need to open the database */
+- php_sqlite_open(fullpath, mode, hashkey, return_value, errmsg TSRMLS_CC);
+-
++ php_sqlite_open(fullpath, (int)mode, hashkey, return_value, errmsg, NULL TSRMLS_CC);
++done:
+ efree(fullpath);
+ efree(hashkey);
+ }
+ /* }}} */
+
+-/* {{{ proto resource sqlite_open(string filename [, int mode, string &errmessage])
+- Opens an SQLite database. Will create the database if it does not exist */
++/* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]])
++ Opens a SQLite database. Will create the database if it does not exist. */
+ PHP_FUNCTION(sqlite_open)
+ {
+- int mode = 0666;
++ long mode = 0666;
+ char *filename, *fullpath = NULL;
+- long filename_len;
++ int filename_len;
+ zval *errmsg = NULL;
++ zval *object = getThis();
++ zend_error_handling error_handling;
+
++ zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
+ &filename, &filename_len, &mode, &errmsg)) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ return;
+ }
+ if (errmsg) {
+ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
+ }
+
+ if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
+ /* resolve the fully-qualified path name to use as the hash key */
+- fullpath = expand_filepath(filename, NULL TSRMLS_CC);
+-
+- if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
++ if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ if (object) {
++ RETURN_NULL();
++ } else {
++ RETURN_FALSE;
++ }
++ }
++
++ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
+ efree(fullpath);
+- RETURN_FALSE;
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ if (object) {
++ RETURN_NULL();
++ } else {
++ RETURN_FALSE;
++ }
++ }
++ }
++
++ php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, object TSRMLS_CC);
++
++ if (fullpath) {
++ efree(fullpath);
++ }
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++}
++/* }}} */
++
++/* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]])
++ Opens a SQLite database and creates an object for it. Will create the database if it does not exist. */
++PHP_FUNCTION(sqlite_factory)
++{
++ long mode = 0666;
++ char *filename, *fullpath = NULL;
++ int filename_len;
++ zval *errmsg = NULL;
++ zend_error_handling error_handling;
++
++ zend_replace_error_handling(EH_THROW, sqlite_ce_exception, &error_handling TSRMLS_CC);
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
++ &filename, &filename_len, &mode, &errmsg)) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ RETURN_NULL();
++ }
++ if (errmsg) {
++ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
++ }
++
++ if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
++ /* resolve the fully-qualified path name to use as the hash key */
++ if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ RETURN_NULL();
+ }
+
+ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
+ efree(fullpath);
+- RETURN_FALSE;
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ RETURN_NULL();
+ }
+ }
+-
+- php_sqlite_open(fullpath ? fullpath : filename, mode, NULL, return_value, errmsg TSRMLS_CC);
+
++ php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, return_value TSRMLS_CC);
+ if (fullpath) {
+ efree(fullpath);
+ }
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ }
+ /* }}} */
+
+ /* {{{ proto void sqlite_busy_timeout(resource db, int ms)
+- Set busy timeout duration. If ms <= 0, all busy handlers are disabled */
++ Set busy timeout duration. If ms <= 0, all busy handlers are disabled. */
+ PHP_FUNCTION(sqlite_busy_timeout)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
+ long ms;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
+-
+ sqlite_busy_timeout(db->db, ms);
+ }
+ /* }}} */
+
+ /* {{{ proto void sqlite_close(resource db)
+- Closes an open sqlite database */
++ Closes an open sqlite database. */
+ PHP_FUNCTION(sqlite_close)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
+- return;
+- }
+- DB_FROM_ZVAL(db, &zdb);
+-
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
+- return;
++ if (object) {
++ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead");
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
++ zend_hash_apply_with_argument(&EG(regular_list),
++ (apply_func_arg_t) _clean_unfinished_results,
++ db TSRMLS_CC);
+
+ zend_list_delete(Z_RESVAL_P(zdb));
+ }
+ /* }}} */
+
+ /* {{{ php_sqlite_fetch */
+-int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
++static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
+ {
+ const char **rowdata, **colnames;
+ int ret, i, base;
+- char *errtext = NULL, *colname;
++ char *errtext = NULL;
+
+ next_row:
+ ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
+@@ -919,14 +1766,13 @@
+ /* first row - lets copy the column names */
+ rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
+ for (i = 0; i < rres->ncolumns; i++) {
+- colname = (char*)colnames[i];
++ rres->col_names[i] = estrdup((char*)colnames[i]);
+
+ if (SQLITE_G(assoc_case) == 1) {
+- php_sqlite_strtoupper(colname);
++ php_sqlite_strtoupper(rres->col_names[i]);
+ } else if (SQLITE_G(assoc_case) == 2) {
+- php_sqlite_strtolower(colname);
++ php_sqlite_strtolower(rres->col_names[i]);
+ }
+- rres->col_names[i] = estrdup(colname);
+ }
+ if (!rres->buffered) {
+ /* non buffered mode - also fetch memory for on single row */
+@@ -940,7 +1786,7 @@
+ /* add the row to our collection */
+ if (rres->nrows + 1 >= rres->alloc_rows) {
+ rres->alloc_rows = rres->alloc_rows ? rres->alloc_rows * 2 : 16;
+- rres->table = erealloc(rres->table, rres->alloc_rows * rres->ncolumns * sizeof(char *));
++ rres->table = safe_erealloc(rres->table, rres->alloc_rows, rres->ncolumns*sizeof(char *), 0);
+ }
+ base = rres->nrows * rres->ncolumns;
+ for (i = 0; i < rres->ncolumns; i++) {
+@@ -994,9 +1840,9 @@
+ /* }}} */
+
+ /* {{{ sqlite_query */
+-void sqlite_query(struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result *rres TSRMLS_DC)
++void sqlite_query(zval *object, struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result **prres, zval *errmsg TSRMLS_DC)
+ {
+- struct php_sqlite_result res;
++ struct php_sqlite_result res, *rres;
+ int ret;
+ char *errtext = NULL;
+ const char *tail;
+@@ -1010,61 +1856,92 @@
+
+ if (ret != SQLITE_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
++ if (errmsg) {
++ ZVAL_STRING(errmsg, errtext, 1);
++ }
+ sqlite_freemem(errtext);
+ goto terminate;
+- } else if (!res.vm) { /* emptry query */
++ } else if (!res.vm) { /* empty query */
+ terminate:
+ if (return_value) {
+ RETURN_FALSE;
+ } else {
+- efree(rres);
+ return;
+ }
+ }
+
+- if (!rres) {
+- rres = (struct php_sqlite_result*)emalloc(sizeof(*rres));
++ if (!prres) {
++ rres = NULL;
++ prres = &rres;
+ }
+- memcpy(rres, &res, sizeof(*rres));
+- rres->db = db;
++ if (!*prres) {
++ *prres = (struct php_sqlite_result*)emalloc(sizeof(**prres));
++ }
++ memcpy(*prres, &res, sizeof(**prres));
++ (*prres)->db = db;
+ zend_list_addref(db->rsrc_id);
+
++
+ /* now the result set is ready for stepping: get first row */
+- if (php_sqlite_fetch(rres TSRMLS_CC) != SQLITE_OK) {
+- real_result_dtor(rres TSRMLS_CC);
++ if (php_sqlite_fetch((*prres) TSRMLS_CC) != SQLITE_OK) {
++ real_result_dtor((*prres) TSRMLS_CC);
++ *prres = NULL;
+ if (return_value) {
+ RETURN_FALSE;
+ } else {
+- return;
++ return;
+ }
+ }
+-
+- rres->curr_row = 0;
+
+- if (return_value) {
+- ZEND_REGISTER_RESOURCE(return_value, rres, le_sqlite_result);
++ (*prres)->curr_row = 0;
++
++ if (object) {
++ sqlite_object *obj;
++ if (buffered) {
++ sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC);
++ } else {
++ sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC);
++ }
++ obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC);
++ obj->type = is_result;
++ obj->u.res = (*prres);
++ } else if (return_value) {
++ ZEND_REGISTER_RESOURCE(object ? NULL : return_value, (*prres), le_sqlite_result);
+ }
+ }
+ /* }}} */
+
+-/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type ])
+- Execute a query that does not prefetch and buffer all data */
++/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]])
++ Executes a query that does not prefetch and buffer all data. */
+ PHP_FUNCTION(sqlite_unbuffered_query)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
+ char *sql;
+- long sql_len;
+- int mode = PHPSQLITE_BOTH;
++ int sql_len;
++ long mode = PHPSQLITE_BOTH;
+ char *errtext = NULL;
++ zval *errmsg = NULL;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
+- ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) &&
+- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
++ if (errmsg) {
++ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
++ }
+
+ PHP_SQLITE_EMPTY_QUERY;
+
+@@ -1074,32 +1951,124 @@
+
+ if (db->last_err_code != SQLITE_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
++ if (errmsg) {
++ ZVAL_STRING(errmsg, errtext, 1);
++ }
+ sqlite_freemem(errtext);
+ }
+ return;
+ }
+-
+- sqlite_query(db, sql, sql_len, mode, 0, return_value, NULL TSRMLS_CC);
++
++ sqlite_query(object, db, sql, sql_len, (int)mode, 0, return_value, NULL, errmsg TSRMLS_CC);
+ }
+ /* }}} */
+
+-/* {{{ proto resource sqlite_query(string query, resource db [ , int result_type ])
+- Executes a query against a given database and returns a result handle */
++/* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type])
++ Return an array of column types from a particular table. */
++PHP_FUNCTION(sqlite_fetch_column_types)
++{
++ zval *zdb;
++ struct php_sqlite_db *db;
++ char *tbl, *sql;
++ int tbl_len;
++ char *errtext = NULL;
++ zval *object = getThis();
++ struct php_sqlite_result res;
++ const char **rowdata, **colnames, *tail;
++ int i, ncols;
++ long result_type = PHPSQLITE_ASSOC;
++
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &tbl, &tbl_len, &result_type)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &tbl, &tbl_len, &zdb, &result_type) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &tbl, &tbl_len, &result_type)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
++ }
++
++ if (!(sql = sqlite_mprintf("SELECT * FROM '%q' LIMIT 1", tbl))) {
++ RETURN_FALSE;
++ }
++
++ sqlite_exec(db->db, "PRAGMA show_datatypes = ON", NULL, NULL, NULL);
++
++ db->last_err_code = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
++
++ sqlite_freemem(sql);
++
++ if (db->last_err_code != SQLITE_OK) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
++ sqlite_freemem(errtext);
++ RETVAL_FALSE;
++ goto done;
++ }
++
++ sqlite_step(res.vm, &ncols, &rowdata, &colnames);
++
++ array_init(return_value);
++
++ for (i = 0; i < ncols; i++) {
++ if (result_type == PHPSQLITE_ASSOC) {
++ char *colname = estrdup((char *)colnames[i]);
++
++ if (SQLITE_G(assoc_case) == 1) {
++ php_sqlite_strtoupper(colname);
++ } else if (SQLITE_G(assoc_case) == 2) {
++ php_sqlite_strtolower(colname);
++ }
++
++ add_assoc_string(return_value, colname, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
++ efree(colname);
++ }
++ if (result_type == PHPSQLITE_NUM) {
++ add_index_string(return_value, i, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
++ }
++ }
++ if (res.vm) {
++ sqlite_finalize(res.vm, NULL);
++ }
++done:
++ sqlite_exec(db->db, "PRAGMA show_datatypes = OFF", NULL, NULL, NULL);
++}
++/* }}} */
++
++/* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]])
++ Executes a query against a given database and returns a result handle. */
+ PHP_FUNCTION(sqlite_query)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
+ char *sql;
+- long sql_len;
+- int mode = PHPSQLITE_BOTH;
++ int sql_len;
++ long mode = PHPSQLITE_BOTH;
+ char *errtext = NULL;
++ zval *errmsg = NULL;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
+- ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) &&
+- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
++ }
++
++ if (errmsg) {
++ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+ PHP_SQLITE_EMPTY_QUERY;
+
+@@ -1109,31 +2078,48 @@
+
+ if (db->last_err_code != SQLITE_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
++ if (errmsg) {
++ ZVAL_STRING(errmsg, errtext, 1);
++ }
+ sqlite_freemem(errtext);
+ }
+ return;
+ }
+-
+- sqlite_query(db, sql, sql_len, mode, 1, return_value, NULL TSRMLS_CC);
++
++ sqlite_query(object, db, sql, sql_len, (int)mode, 1, return_value, NULL, errmsg TSRMLS_CC);
+ }
+ /* }}} */
+
+-/* {{{ proto boolean sqlite_exec(string query, resource db)
++/* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message])
+ Executes a result-less query against a given database */
+ PHP_FUNCTION(sqlite_exec)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
+ char *sql;
+- long sql_len;
++ int sql_len;
+ char *errtext = NULL;
++ zval *errmsg = NULL;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
+- ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
+- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zdb, &sql, &sql_len)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &sql, &sql_len, &errmsg)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if(FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &zdb, &sql, &sql_len, &errmsg)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
++ }
++
++ if (errmsg) {
++ zval_dtor(errmsg);
++ ZVAL_NULL(errmsg);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+ PHP_SQLITE_EMPTY_QUERY;
+
+@@ -1141,6 +2127,9 @@
+
+ if (db->last_err_code != SQLITE_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
++ if (errmsg) {
++ ZVAL_STRING(errmsg, errtext, 1);
++ }
+ sqlite_freemem(errtext);
+ RETURN_FALSE;
+ }
+@@ -1152,9 +2141,9 @@
+ /* {{{ php_sqlite_fetch_array */
+ static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC)
+ {
+- int j, buffered = res->buffered;
++ int j, n = res->ncolumns, buffered = res->buffered;
+ const char **rowdata, **colnames;
+-
++
+ /* check range of the row */
+ if (res->curr_row >= res->nrows) {
+ /* no more */
+@@ -1170,7 +2159,7 @@
+ /* now populate the result */
+ array_init(return_value);
+
+- for (j = 0; j < res->ncolumns; j++) {
++ for (j = 0; j < n; j++) {
+ zval *decoded;
+ MAKE_STD_ZVAL(decoded);
+
+@@ -1178,7 +2167,7 @@
+ ZVAL_NULL(decoded);
+ } else if (decode_binary && rowdata[j][0] == '\x01') {
+ Z_STRVAL_P(decoded) = emalloc(strlen(rowdata[j]));
+- Z_STRLEN_P(decoded) = sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
++ Z_STRLEN_P(decoded) = php_sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
+ Z_STRVAL_P(decoded)[Z_STRLEN_P(decoded)] = '\0';
+ Z_TYPE_P(decoded) = IS_STRING;
+ if (!buffered) {
+@@ -1195,7 +2184,7 @@
+ if (mode & PHPSQLITE_NUM) {
+ if (mode & PHPSQLITE_ASSOC) {
+ add_index_zval(return_value, j, decoded);
+- ZVAL_ADDREF(decoded);
++ Z_ADDREF_P(decoded);
+ add_assoc_zval(return_value, (char*)colnames[j], decoded);
+ } else {
+ add_next_index_zval(return_value, decoded);
+@@ -1252,10 +2241,10 @@
+
+ if (rowdata[j] == NULL) {
+ RETURN_NULL();
+- } else if (decode_binary && rowdata[j][0] == '\x01') {
++ } else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') {
+ int l = strlen(rowdata[j]);
+ char *decoded = emalloc(l);
+- l = sqlite_decode_binary(rowdata[j]+1, decoded);
++ l = php_sqlite_decode_binary(rowdata[j]+1, decoded);
+ decoded[l] = '\0';
+ RETVAL_STRINGL(decoded, l, 0);
+ if (!res->buffered) {
+@@ -1271,26 +2260,37 @@
+ }
+ /* }}} */
+
+-/* {{{ proto array sqlite_fetch_all(resource result [, int result_type, bool decode_binary])
+- Fetches all rows from a result set as an array */
++/* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]])
++ Fetches all rows from a result set as an array of arrays. */
+ PHP_FUNCTION(sqlite_fetch_all)
+ {
+ zval *zres, *ent;
+- int mode = PHPSQLITE_BOTH;
++ long mode = PHPSQLITE_BOTH;
+ zend_bool decode_binary = 1;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
+- return;
+- }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+- if (ZEND_NUM_ARGS() < 2) {
+- mode = res->mode;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ if (!ZEND_NUM_ARGS()) {
++ mode = res->mode;
++ }
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ if (ZEND_NUM_ARGS() < 2) {
++ mode = res->mode;
++ }
+ }
+
+ if (res->curr_row >= res->nrows && res->nrows) {
+ if (!res->buffered) {
+- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "One or more rowsets were already returned");
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "One or more rowsets were already returned; returning NULL this time");
+ } else {
+ res->curr_row = 0;
+ }
+@@ -1306,46 +2306,184 @@
+ }
+ /* }}} */
+
+-/* {{{ proto array sqlite_fetch_array(resource result [, int result_type, bool decode_binary])
+- Fetches the next row from a result set as an array */
++/* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]])
++ Fetches the next row from a result set as an array. */
+ PHP_FUNCTION(sqlite_fetch_array)
+ {
+ zval *zres;
+- int mode = PHPSQLITE_BOTH;
++ long mode = PHPSQLITE_BOTH;
+ zend_bool decode_binary = 1;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ if (!ZEND_NUM_ARGS()) {
++ mode = res->mode;
++ }
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ if (ZEND_NUM_ARGS() < 2) {
++ mode = res->mode;
++ }
++ }
++
++ php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
++}
++/* }}} */
++
++/* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]])
++ Fetches the next row from a result set as an object. */
++ /* note that you can do array(&$val) for param ctor_params */
++PHP_FUNCTION(sqlite_fetch_object)
++{
++ zval *zres;
++ zend_bool decode_binary = 1;
++ struct php_sqlite_result *res;
++ zval *object = getThis();
++ char *class_name = NULL;
++ int class_name_len;
++ zend_class_entry *ce;
++ zval dataset;
++ zend_fcall_info fci;
++ zend_fcall_info_cache fcc;
++ zval *retval_ptr;
++ zval *ctor_params = NULL;
++ zend_error_handling error_handling;
++
++ zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szb", &class_name, &class_name_len, &ctor_params, &decode_binary)) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ return;
++ }
++ RES_FROM_OBJECT_RESTORE_ERH(res, object, &error_handling);
++ if (!class_name) {
++ ce = zend_standard_class_def;
++ } else {
++ ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
++ }
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|szb", &zres, &class_name, &class_name_len, &ctor_params, &decode_binary)) {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ if (!class_name) {
++ ce = zend_standard_class_def;
++ } else {
++ ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
++ }
++ }
++
++ if (!ce) {
++ zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not find class '%s'", class_name);
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ return;
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+- if (ZEND_NUM_ARGS() < 2) {
+- mode = res->mode;
++
++ if (res->curr_row < res->nrows) {
++ php_sqlite_fetch_array(res, PHPSQLITE_ASSOC, decode_binary, 1, &dataset TSRMLS_CC);
++ } else {
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++ RETURN_FALSE;
+ }
+
+- php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
++ object_and_properties_init(return_value, ce, NULL);
++ zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
++
++ zend_restore_error_handling(&error_handling TSRMLS_CC);
++
++ if (ce->constructor) {
++ fci.size = sizeof(fci);
++ fci.function_table = &ce->function_table;
++ fci.function_name = NULL;
++ fci.symbol_table = NULL;
++ fci.object_ptr = return_value;
++ fci.retval_ptr_ptr = &retval_ptr;
++ if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
++ if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
++ HashTable *ht = Z_ARRVAL_P(ctor_params);
++ Bucket *p;
++
++ fci.param_count = 0;
++ fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
++ p = ht->pListHead;
++ while (p != NULL) {
++ fci.params[fci.param_count++] = (zval**)p->pData;
++ p = p->pListNext;
++ }
++ } else {
++ /* Two problems why we throw exceptions here: PHP is typeless
++ * and hence passing one argument that's not an array could be
++ * by mistake and the other way round is possible, too. The
++ * single value is an array. Also we'd have to make that one
++ * argument passed by reference.
++ */
++ zend_throw_exception(sqlite_ce_exception, "Parameter ctor_params must be an array", 0 TSRMLS_CC);
++ return;
++ }
++ } else {
++ fci.param_count = 0;
++ fci.params = NULL;
++ }
++ fci.no_separation = 1;
++
++ fcc.initialized = 1;
++ fcc.function_handler = ce->constructor;
++ fcc.calling_scope = EG(scope);
++ fcc.called_scope = Z_OBJCE_P(return_value);
++ fcc.object_ptr = return_value;
++
++ if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
++ zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not execute %s::%s()", class_name, ce->constructor->common.function_name);
++ } else {
++ if (retval_ptr) {
++ zval_ptr_dtor(&retval_ptr);
++ }
++ }
++ if (fci.params) {
++ efree(fci.params);
++ }
++ } else if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
++ zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Class %s does not have a constructor, use NULL for parameter ctor_params or omit it", class_name);
++ }
+ }
+ /* }}} */
+
+-/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type, bool decode_binary ])
+- Executes a query against a given database and returns an array */
++/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]])
++ Executes a query against a given database and returns an array of arrays. */
+ PHP_FUNCTION(sqlite_array_query)
+ {
+ zval *zdb, *ent;
+ struct php_sqlite_db *db;
+ struct php_sqlite_result *rres;
+ char *sql;
+- long sql_len;
+- int mode = PHPSQLITE_BOTH;
++ int sql_len;
++ long mode = PHPSQLITE_BOTH;
+ char *errtext = NULL;
+ zend_bool decode_binary = 1;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
+- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
+- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+ PHP_SQLITE_EMPTY_QUERY;
+
+@@ -1360,10 +2498,12 @@
+ return;
+ }
+
+- rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
+- sqlite_query(db, sql, sql_len, mode, 0, NULL, rres TSRMLS_CC);
++ rres = (struct php_sqlite_result *)ecalloc(1, sizeof(*rres));
++ sqlite_query(NULL, db, sql, sql_len, (int)mode, 0, NULL, &rres, NULL TSRMLS_CC);
+ if (db->last_err_code != SQLITE_OK) {
+- /* no need to free rres, as it will be freed by sqlite_query() for us */
++ if (rres) {
++ efree(rres);
++ }
+ RETURN_FALSE;
+ }
+
+@@ -1384,13 +2524,13 @@
+ const char **rowdata;
+ char *decoded;
+ int decoded_len;
+-
++
+ /* check range of the row */
+ if (res->curr_row >= res->nrows) {
+ /* no more */
+ RETURN_FALSE;
+ }
+-
++
+ if (res->buffered) {
+ rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
+ } else {
+@@ -1399,7 +2539,7 @@
+
+ if (decode_binary && rowdata[0] != NULL && rowdata[0][0] == '\x01') {
+ decoded = emalloc(strlen(rowdata[0]));
+- decoded_len = sqlite_decode_binary(rowdata[0]+1, decoded);
++ decoded_len = php_sqlite_decode_binary(rowdata[0]+1, decoded);
+ if (!res->buffered) {
+ efree((char*)rowdata[0]);
+ rowdata[0] = NULL;
+@@ -1432,25 +2572,34 @@
+ }
+ /* }}} */
+
+-/* {{{ proto array sqlite_single_query(resource db, string query [ , bool single_row, bool decode_binary ])
+- Executes a query against a given database and returns an array */
++
++/* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]])
++ Executes a query and returns either an array for one single column or the value of the first row. */
+ PHP_FUNCTION(sqlite_single_query)
+ {
+ zval *zdb, *ent;
+ struct php_sqlite_db *db;
+ struct php_sqlite_result *rres;
+ char *sql;
+- long sql_len;
++ int sql_len;
+ char *errtext = NULL;
+ zend_bool decode_binary = 1;
+ zend_bool srow = 1;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
+- ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
+- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
++ ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
++ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+ PHP_SQLITE_EMPTY_QUERY;
+
+@@ -1465,10 +2614,12 @@
+ return;
+ }
+
+- rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
+- sqlite_query(db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, rres TSRMLS_CC);
++ rres = (struct php_sqlite_result *)ecalloc(1, sizeof(*rres));
++ sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, &rres, NULL TSRMLS_CC);
+ if (db->last_err_code != SQLITE_OK) {
+- /* no need to free rres, as it will be freed by sqlite_query() for us */
++ if (rres) {
++ efree(rres);
++ }
+ RETURN_FALSE;
+ }
+
+@@ -1501,38 +2652,57 @@
+ /* }}} */
+
+
+-/* {{{ proto string sqlite_fetch_array(resource result [, bool decode_binary])
+- Fetches first column of a result set as a string */
++/* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary])
++ Fetches the first column of a result set as a string. */
+ PHP_FUNCTION(sqlite_fetch_single)
+ {
+ zval *zres;
+ zend_bool decode_binary = 1;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+
+ php_sqlite_fetch_single(res, decode_binary, return_value TSRMLS_CC);
+ }
+ /* }}} */
+
+-/* {{{ proto array sqlite_fetch_array(resource result [, int result_type, bool decode_binary])
+- Fetches the current row from a result set as an array */
++/* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]])
++ Fetches the current row from a result set as an array. */
+ PHP_FUNCTION(sqlite_current)
+ {
+ zval *zres;
+- int mode = PHPSQLITE_BOTH;
++ long mode = PHPSQLITE_BOTH;
+ zend_bool decode_binary = 1;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
+- return;
+- }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+- if (ZEND_NUM_ARGS() < 2) {
+- mode = res->mode;
++ if (object) {
++ if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ if (!ZEND_NUM_ARGS()) {
++ mode = res->mode;
++ }
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ if (ZEND_NUM_ARGS() < 2) {
++ mode = res->mode;
++ }
+ }
+
+ php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC);
+@@ -1540,92 +2710,139 @@
+ /* }}} */
+
+ /* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
+- Fetches a column from the current row of a result set */
++ Fetches a column from the current row of a result set. */
+ PHP_FUNCTION(sqlite_column)
+ {
+ zval *zres;
+ zval *which;
+ zend_bool decode_binary = 1;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+
+ php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC);
+ }
+ /* }}} */
+
+ /* {{{ proto string sqlite_libversion()
+- Returns the version of the linked SQLite library */
++ Returns the version of the linked SQLite library. */
+ PHP_FUNCTION(sqlite_libversion)
+ {
+- if (ZEND_NUM_ARGS() != 0) {
+- WRONG_PARAM_COUNT;
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
+ }
+ RETURN_STRING((char*)sqlite_libversion(), 1);
+ }
+ /* }}} */
+
+ /* {{{ proto string sqlite_libencoding()
+- Returns the encoding (iso8859 or UTF-8) of the linked SQLite library */
++ Returns the encoding (iso8859 or UTF-8) of the linked SQLite library. */
+ PHP_FUNCTION(sqlite_libencoding)
+ {
+- if (ZEND_NUM_ARGS() != 0) {
+- WRONG_PARAM_COUNT;
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
+ }
+ RETURN_STRING((char*)sqlite_libencoding(), 1);
+ }
+ /* }}} */
+
+ /* {{{ proto int sqlite_changes(resource db)
+- Returns the number of rows that were changed by the most recent SQL statement */
++ Returns the number of rows that were changed by the most recent SQL statement. */
+ PHP_FUNCTION(sqlite_changes)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
+-
+ RETURN_LONG(sqlite_changes(db->db));
+ }
+ /* }}} */
+
+ /* {{{ proto int sqlite_last_insert_rowid(resource db)
+- Returns the rowid of the most recently inserted row */
++ Returns the rowid of the most recently inserted row. */
+ PHP_FUNCTION(sqlite_last_insert_rowid)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
+-
+ RETURN_LONG(sqlite_last_insert_rowid(db->db));
+ }
+ /* }}} */
+
++static int sqlite_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
++{
++ sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
++
++ if (obj->u.res == NULL) {
++ zend_throw_exception(sqlite_ce_exception, "Row count is not available for this query", 0 TSRMLS_CC);
++ return FAILURE;
++ }
++
++ if (obj->u.res->buffered) {
++ * count = obj->u.res->nrows;
++ return SUCCESS;
++ } else {
++ zend_throw_exception(sqlite_ce_exception, "Row count is not available for unbuffered queries", 0 TSRMLS_CC);
++ return FAILURE;
++ }
++} /* }}} */
++
+ /* {{{ proto int sqlite_num_rows(resource result)
+- Returns the number of rows in a result set */
++ Returns the number of rows in a buffered result set. */
+ PHP_FUNCTION(sqlite_num_rows)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+-
+ if (res->buffered) {
+ RETURN_LONG(res->nrows);
+ } else {
+@@ -1635,55 +2852,106 @@
+ }
+ /* }}} */
+
+-/* {{{ proto bool sqlite_has_more(resource result)
+- Returns whether or not more rows are available */
+-PHP_FUNCTION(sqlite_has_more)
++/* {{{ proto bool sqlite_valid(resource result)
++ Returns whether more rows are available. */
++PHP_FUNCTION(sqlite_valid)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+
+- RETURN_BOOL(res->nrows && res->curr_row < res->nrows); /* curr_row may be -1 */
++ RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */
++}
++/* }}} */
++
++/* {{{ proto bool sqlite_has_prev(resource result)
++ * Returns whether a previous row is available. */
++PHP_FUNCTION(sqlite_has_prev)
++{
++ zval *zres;
++ struct php_sqlite_result *res;
++ zval *object = getThis();
++
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ }
++
++ if(!res->buffered) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_has_prev on unbuffered querys");
++ RETURN_FALSE;
++ }
++
++ RETURN_BOOL(res->curr_row);
+ }
+ /* }}} */
+
+ /* {{{ proto int sqlite_num_fields(resource result)
+- Returns the number of fields in a result set */
++ Returns the number of fields in a result set. */
+ PHP_FUNCTION(sqlite_num_fields)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+-
+ RETURN_LONG(res->ncolumns);
+ }
+ /* }}} */
+
+-/* {{{ proto string sqlite_field_name(resource result, int field)
+- Returns the name of a particular field */
++/* {{{ proto string sqlite_field_name(resource result, int field_index)
++ Returns the name of a particular field of a result set. */
+ PHP_FUNCTION(sqlite_field_name)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
+- int field;
++ long field;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &field)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+-
+ if (field < 0 || field >= res->ncolumns) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %d out of range", field);
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %ld out of range", field);
+ RETURN_FALSE;
+ }
+
+@@ -1692,26 +2960,33 @@
+ /* }}} */
+
+ /* {{{ proto bool sqlite_seek(resource result, int row)
+- Seek to a particular row number */
++ Seek to a particular row number of a buffered result set. */
+ PHP_FUNCTION(sqlite_seek)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
+- int row;
++ long row;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
+- return;
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+-
+ if (!res->buffered) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
+ RETURN_FALSE;
+ }
+-
++
+ if (row < 0 || row >= res->nrows) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %d out of range", row);
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %ld out of range", row);
+ RETURN_FALSE;
+ }
+
+@@ -1721,22 +2996,30 @@
+ /* }}} */
+
+ /* {{{ proto bool sqlite_rewind(resource result)
+- Seek to first row number */
++ Seek to the first row number of a buffered result set. */
+ PHP_FUNCTION(sqlite_rewind)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+
+ if (!res->buffered) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rewind an unbuffered result set");
+ RETURN_FALSE;
+ }
+-
++
+ if (!res->nrows) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "no rows received");
+ RETURN_FALSE;
+@@ -1748,16 +3031,24 @@
+ /* }}} */
+
+ /* {{{ proto bool sqlite_next(resource result)
+- Seek to next row number */
++ Seek to the next row number of a result set. */
+ PHP_FUNCTION(sqlite_next)
+ {
+ zval *zres;
+ struct php_sqlite_result *res;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+ }
+- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
+
+ if (!res->buffered && res->vm) {
+ php_sqlite_fetch(res TSRMLS_CC);
+@@ -1774,12 +3065,72 @@
+ }
+ /* }}} */
+
++/* {{{ proto int sqlite_key(resource result)
++ Return the current row index of a buffered result. */
++PHP_FUNCTION(sqlite_key)
++{
++ zval *zres;
++ struct php_sqlite_result *res;
++ zval *object = getThis();
++
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ }
++
++ RETURN_LONG(res->curr_row);
++}
++/* }}} */
++
++/* {{{ proto bool sqlite_prev(resource result)
++ * Seek to the previous row number of a result set. */
++PHP_FUNCTION(sqlite_prev)
++{
++ zval *zres;
++ struct php_sqlite_result *res;
++ zval *object = getThis();
++
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ RES_FROM_OBJECT(res, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
++ return;
++ }
++ ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
++ }
++
++ if (!res->buffered) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_prev on unbuffered querys");
++ RETURN_FALSE;
++ }
++
++ if (res->curr_row <= 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "no previous row available");
++ RETURN_FALSE;
++ }
++
++ res->curr_row--;
++
++ RETURN_TRUE;
++}
++/* }}} */
++
+ /* {{{ proto string sqlite_escape_string(string item)
+- Escapes a string for use as a query parameter */
++ Escapes a string for use as a query parameter. */
+ PHP_FUNCTION(sqlite_escape_string)
+ {
+ char *string = NULL;
+- long stringlen;
++ int stringlen;
+ char *ret;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
+@@ -1789,41 +3140,50 @@
+ if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) {
+ /* binary string */
+ int enclen;
+-
+- ret = emalloc( 1 + 5 + stringlen * ((float) 256 / (float) 253) );
++
++ ret = safe_emalloc(1 + stringlen / 254, 257, 3);
+ ret[0] = '\x01';
+- enclen = sqlite_encode_binary((const unsigned char*)string, stringlen, ret+1);
++ enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
+ RETVAL_STRINGL(ret, enclen+1, 0);
+-
+- } else {
++
++ } else if (stringlen) {
+ ret = sqlite_mprintf("%q", string);
+ if (ret) {
+ RETVAL_STRING(ret, 1);
+ sqlite_freemem(ret);
+ }
++ } else {
++ RETURN_EMPTY_STRING();
+ }
+ }
+ /* }}} */
+
+ /* {{{ proto int sqlite_last_error(resource db)
+- Returns the error code of the last error for a database */
++ Returns the error code of the last error for a database. */
+ PHP_FUNCTION(sqlite_last_error)
+ {
+ zval *zdb;
+ struct php_sqlite_db *db;
++ zval *object = getThis();
+
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
+- return;
++ if (object) {
++ if (zend_parse_parameters_none() == FAILURE) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+
+- DB_FROM_ZVAL(db, &zdb);
+-
+ RETURN_LONG(db->last_err_code);
+ }
+ /* }}} */
+
+ /* {{{ proto string sqlite_error_string(int error_code)
+- Returns the textual description of an error code */
++ Returns the textual description of an error code. */
+ PHP_FUNCTION(sqlite_error_string)
+ {
+ long code;
+@@ -1832,7 +3192,7 @@
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
+ return;
+ }
+-
++
+ msg = sqlite_error_string(code);
+
+ if (msg) {
+@@ -1890,86 +3250,106 @@
+ MAKE_STD_ZVAL(alloc_funcs->step);
+ *(alloc_funcs->step) = *step;
+ zval_copy_ctor(alloc_funcs->step);
++ INIT_PZVAL(alloc_funcs->step);
+
+ if (is_agg) {
+ MAKE_STD_ZVAL(alloc_funcs->fini);
+ *(alloc_funcs->fini) = *fini;
+ zval_copy_ctor(alloc_funcs->fini);
++ INIT_PZVAL(alloc_funcs->fini);
+ } else {
+ alloc_funcs->fini = NULL;
+ }
+ alloc_funcs->is_valid = 1;
+ *funcs = alloc_funcs;
+-
++
+ return ret;
+ }
+
+
+ /* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
+- Registers an aggregated function for queries*/
++ Registers an aggregate function for queries. */
+ PHP_FUNCTION(sqlite_create_aggregate)
+ {
+ char *funcname = NULL;
+- long funcname_len;
++ int funcname_len;
+ zval *zstep, *zfinal, *zdb;
+ struct php_sqlite_db *db;
+ struct php_sqlite_agg_functions *funcs;
+ char *callable = NULL;
+ long num_args = -1;
+-
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
+- return;
++ zval *object = getThis();
++
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+- if (!zend_is_callable(zstep, 0, &callable)) {
++ if (!zend_is_callable(zstep, 0, &callable TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable);
+ efree(callable);
+ return;
+ }
+ efree(callable);
+-
+- if (!zend_is_callable(zfinal, 0, &callable)) {
++
++ if (!zend_is_callable(zfinal, 0, &callable TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "finalize function `%s' is not callable", callable);
+ efree(callable);
+ return;
+ }
+ efree(callable);
+
++
+ if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) {
+ sqlite_create_aggregate(db->db, funcname, num_args,
+ php_sqlite_agg_step_function_callback,
+ php_sqlite_agg_fini_function_callback, funcs);
+ }
+-
++
+
+ }
+ /* }}} */
+
+ /* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
+- Registers a "regular" function for queries */
++ Registers a "regular" function for queries. */
+ PHP_FUNCTION(sqlite_create_function)
+ {
+ char *funcname = NULL;
+- long funcname_len;
++ int funcname_len;
+ zval *zcall, *zdb;
+ struct php_sqlite_db *db;
+ struct php_sqlite_agg_functions *funcs;
+ char *callable = NULL;
+ long num_args = -1;
+-
+- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
+- return;
++
++ zval *object = getThis();
++
++ if (object) {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &funcname, &funcname_len, &zcall, &num_args)) {
++ return;
++ }
++ DB_FROM_OBJECT(db, object);
++ } else {
++ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
++ return;
++ }
++ DB_FROM_ZVAL(db, &zdb);
+ }
+- DB_FROM_ZVAL(db, &zdb);
+
+- if (!zend_is_callable(zcall, 0, &callable)) {
++ if (!zend_is_callable(zcall, 0, &callable TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable);
+ efree(callable);
+ return;
+ }
+ efree(callable);
+-
++
+ if (prep_callback_struct(db, 0, funcname, zcall, NULL, &funcs) == DO_REG) {
+ sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs);
+ }
+@@ -1977,11 +3357,11 @@
+ /* }}} */
+
+ /* {{{ proto string sqlite_udf_encode_binary(string data)
+- Apply binary encoding (if required) to a string to return from an UDF */
++ Apply binary encoding (if required) to a string to return from an UDF. */
+ PHP_FUNCTION(sqlite_udf_encode_binary)
+ {
+ char *data = NULL;
+- long datalen;
++ int datalen;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
+ return;
+@@ -1994,10 +3374,10 @@
+ /* binary string */
+ int enclen;
+ char *ret;
+-
+- ret = emalloc( 1 + 5 + datalen * ((float) 256 / (float) 253) );
++
++ ret = safe_emalloc(1 + datalen / 254, 257, 3);
+ ret[0] = '\x01';
+- enclen = sqlite_encode_binary((const unsigned char*)data, datalen, ret+1);
++ enclen = php_sqlite_encode_binary(data, datalen, ret+1);
+ RETVAL_STRINGL(ret, enclen+1, 0);
+ } else {
+ RETVAL_STRINGL(data, datalen, 1);
+@@ -2006,11 +3386,11 @@
+ /* }}} */
+
+ /* {{{ proto string sqlite_udf_decode_binary(string data)
+- Decode binary encoding on a string parameter passed to an UDF */
++ Decode binary encoding on a string parameter passed to an UDF. */
+ PHP_FUNCTION(sqlite_udf_decode_binary)
+ {
+ char *data = NULL;
+- long datalen;
++ int datalen;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
+ return;
+@@ -2023,9 +3403,9 @@
+ /* encoded string */
+ int enclen;
+ char *ret;
+-
++
+ ret = emalloc(datalen);
+- enclen = sqlite_decode_binary((const unsigned char*)data+1, ret);
++ enclen = php_sqlite_decode_binary(data+1, ret);
+ ret[enclen] = '\0';
+ RETVAL_STRINGL(ret, enclen, 0);
+ } else {
+diff -dPNur sqlite-1.0.3/sqlite.dsp sqlite-svn/sqlite.dsp
+--- sqlite-1.0.3/sqlite.dsp 2004-01-17 00:33:14.000000000 +0000
++++ sqlite-svn/sqlite.dsp 2012-10-09 13:36:42.760063980 +0000
+@@ -44,7 +44,7 @@
+ # PROP Ignore_Export_Lib 0
+ # PROP Target_Dir ""
+ # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SQLITE_EXPORTS" /YX /FD /c
+-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /FR /YX /FD /c
++# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\win32" /I "..\..\..\php_build" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /FR /YX /FD /c
+ # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+ # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+ # ADD BASE RSC /l 0x407 /d "NDEBUG"
+@@ -54,7 +54,7 @@
+ # ADD BSC32 /nologo
+ LINK32=link.exe
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+-# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS\php_sqlite.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline" /libpath:"..\..\..\php_build\release"
++# ADD LINK32 php5ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS\php_sqlite.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\release"
+
+ !ELSEIF "$(CFG)" == "sqlite - Win32 Debug_TS"
+
+@@ -70,7 +70,7 @@
+ # PROP Ignore_Export_Lib 0
+ # PROP Target_Dir ""
+ # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SQLITE_EXPORTS" /YX /FD /GZ /c
+-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /YX /FD /GZ /c
++# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\win32" /I "..\..\..\php_build" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /YX /FD /GZ /c
+ # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+ # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+ # ADD BASE RSC /l 0x407 /d "_DEBUG"
+@@ -80,7 +80,7 @@
+ # ADD BSC32 /nologo
+ LINK32=link.exe
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+-# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS\php_sqlite.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS" /libpath:"..\..\..\php_build\release"
++# ADD LINK32 php5ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS\php_sqlite.dll" /pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\release"
+
+ !ENDIF
+
+@@ -314,10 +314,6 @@
+ # End Source File
+ # Begin Source File
+
+-SOURCE=.\libsqlite\src\vdbeInt.h
+-# End Source File
+-# Begin Source File
+-
+ SOURCE=.\libsqlite\src\where.c
+ # End Source File
+ # End Group
+diff -dPNur sqlite-1.0.3/sqlite.php sqlite-svn/sqlite.php
+--- sqlite-1.0.3/sqlite.php 2003-04-17 20:08:00.000000000 +0000
++++ sqlite-svn/sqlite.php 2012-10-09 13:36:42.760063980 +0000
+@@ -1,6 +1,9 @@
+ <?php
+ if (!extension_loaded("sqlite")) {
+ dl("sqlite.so");
++ if (!extension_loaded("sqlite")) {
++ exit("Please enable SQLite support\n");
++ }
+ }
+
+ debug_zval_dump(sqlite_libversion());
+diff -dPNur sqlite-1.0.3/tests/blankdb.inc sqlite-svn/tests/blankdb.inc
+--- sqlite-1.0.3/tests/blankdb.inc 2003-04-18 20:53:18.000000000 +0000
++++ sqlite-svn/tests/blankdb.inc 2012-10-09 13:36:42.740092676 +0000
+@@ -1,11 +1,3 @@
+ <?php #vim:ft=php
+-$dbname = tempnam(dirname(__FILE__), "phpsql");
+-function cleanup() {
+- if ($GLOBALS['db']) {
+- sqlite_close($GLOBALS['db']);
+- }
+- unlink($GLOBALS['dbname']);
+-}
+-register_shutdown_function("cleanup");
+-$db = sqlite_open($dbname);
++$db = sqlite_open(":memory:");
+ ?>
+diff -dPNur sqlite-1.0.3/tests/blankdb_oo.inc sqlite-svn/tests/blankdb_oo.inc
+--- sqlite-1.0.3/tests/blankdb_oo.inc 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/blankdb_oo.inc 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,3 @@
++<?php #vim:ft=php
++$db = new SQLiteDatabase(":memory:");
++?>
+diff -dPNur sqlite-1.0.3/tests/bug26911.phpt sqlite-svn/tests/bug26911.phpt
+--- sqlite-1.0.3/tests/bug26911.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/bug26911.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,12 @@
++--TEST--
++Bug #26911 (crash when fetching data from empty queries)
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++ $db = sqlite_open(":memory:");
++ $a = sqlite_query($db, " ");
++ echo "I am ok\n";
++?>
++--EXPECT--
++I am ok
+diff -dPNur sqlite-1.0.3/tests/bug28112.phpt sqlite-svn/tests/bug28112.phpt
+--- sqlite-1.0.3/tests/bug28112.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/bug28112.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,16 @@
++--TEST--
++Bug #28112 (sqlite_query() crashing apache on malformed query)
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++
++if (!($db = sqlite_open(":memory:", 666, $error))) die ("Couldn't open the database");
++sqlite_query($db, "create table frob (foo INTEGER PRIMARY KEY, bar text);");
++$res = @sqlite_array_query($db, "");
++
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/bug35248.phpt sqlite-svn/tests/bug35248.phpt
+--- sqlite-1.0.3/tests/bug35248.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/bug35248.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #35248 (sqlite_query does not return parse error message)
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++ $db = sqlite_open(":memory:");
++ $res = @sqlite_query($db, "asdfesdfa", SQLITE_NUM, $err);
++ var_dump($err);
++ $res = @sqlite_unbuffered_query($db, "asdfesdfa", SQLITE_NUM, $err);
++ var_dump($err);
++?>
++--EXPECT--
++string(30) "near "asdfesdfa": syntax error"
++string(30) "near "asdfesdfa": syntax error"
+diff -dPNur sqlite-1.0.3/tests/bug38759.phpt sqlite-svn/tests/bug38759.phpt
+--- sqlite-1.0.3/tests/bug38759.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/bug38759.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,18 @@
++--TEST--
++Bug #38759 (sqlite2 empty query causes segfault)
++--SKIPIF--
++<?php
++if (!extension_loaded("pdo")) print "skip";
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++
++$dbh = new PDO('sqlite2::memory:');
++var_dump($dbh->query(" "));
++
++echo "Done\n";
++?>
++--EXPECTF--
++bool(false)
++Done
+diff -dPNur sqlite-1.0.3/tests/bug48679.phpt sqlite-svn/tests/bug48679.phpt
+--- sqlite-1.0.3/tests/bug48679.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/bug48679.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,20 @@
++--TEST--
++Bug #48679 (sqlite2 count on unbuffered query causes segfault)
++--SKIPIF--
++<?php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++
++try {
++ $x = new sqliteunbuffered;
++ count($x);
++} catch (SQLiteException $e) {
++ var_dump($e->getMessage());
++}
++echo "Done\n";
++?>
++--EXPECT--
++string(41) "Row count is not available for this query"
++Done
+diff -dPNur sqlite-1.0.3/tests/pdo/common.phpt sqlite-svn/tests/pdo/common.phpt
+--- sqlite-1.0.3/tests/pdo/common.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/pdo/common.phpt 2012-10-09 13:36:42.700706048 +0000
+@@ -0,0 +1,12 @@
++--TEST--
++SQLite2
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded('pdo') || !extension_loaded('sqlite')) print 'skip'; ?>
++--REDIRECTTEST--
++return array(
++ 'ENV' => array(
++ 'PDOTEST_DSN' => 'sqlite2::memory:'
++ ),
++ 'TESTS' => 'ext/pdo/tests'
++ );
+diff -dPNur sqlite-1.0.3/tests/sqlite_001.phpt sqlite-svn/tests/sqlite_001.phpt
+--- sqlite-1.0.3/tests/sqlite_001.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_001.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -9,7 +9,6 @@
+ require_once('blankdb.inc');
+ echo "$db\n";
+ sqlite_close($db);
+-$db = NULL;
+ echo "Done\n";
+ ?>
+ --EXPECTF--
+diff -dPNur sqlite-1.0.3/tests/sqlite_002.phpt sqlite-svn/tests/sqlite_002.phpt
+--- sqlite-1.0.3/tests/sqlite_002.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_002.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -13,6 +13,7 @@
+ sqlite_query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)", $db);
+ $r = sqlite_query("SELECT * from foo", $db);
+ var_dump(sqlite_fetch_array($r));
++sqlite_close($db);
+ ?>
+ --EXPECT--
+ array(6) {
+diff -dPNur sqlite-1.0.3/tests/sqlite_003.phpt sqlite-svn/tests/sqlite_003.phpt
+--- sqlite-1.0.3/tests/sqlite_003.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_003.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -17,6 +17,7 @@
+ var_dump(sqlite_fetch_array($r, SQLITE_NUM));
+ $r = sqlite_query("SELECT * from foo", $db);
+ var_dump(sqlite_fetch_array($r, SQLITE_ASSOC));
++sqlite_close($db);
+ ?>
+ --EXPECT--
+ array(6) {
+diff -dPNur sqlite-1.0.3/tests/sqlite_004.phpt sqlite-svn/tests/sqlite_004.phpt
+--- sqlite-1.0.3/tests/sqlite_004.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_004.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -35,6 +35,9 @@
+ }
+ $i++;
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_005.phpt sqlite-svn/tests/sqlite_005.phpt
+--- sqlite-1.0.3/tests/sqlite_005.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_005.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -37,6 +37,9 @@
+ while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
+ var_dump($row);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_006.phpt sqlite-svn/tests/sqlite_006.phpt
+--- sqlite-1.0.3/tests/sqlite_006.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_006.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -34,6 +34,9 @@
+ while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
+ var_dump($row);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_007.phpt sqlite-svn/tests/sqlite_007.phpt
+--- sqlite-1.0.3/tests/sqlite_007.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_007.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -17,6 +17,7 @@
+ var_dump(sqlite_fetch_array($r, SQLITE_NUM));
+ $r = sqlite_unbuffered_query("SELECT * from foo", $db);
+ var_dump(sqlite_fetch_array($r, SQLITE_ASSOC));
++sqlite_close($db);
+ ?>
+ --EXPECT--
+ array(6) {
+diff -dPNur sqlite-1.0.3/tests/sqlite_008.phpt sqlite-svn/tests/sqlite_008.phpt
+--- sqlite-1.0.3/tests/sqlite_008.phpt 2003-05-02 22:09:54.000000000 +0000
++++ sqlite-svn/tests/sqlite_008.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -25,6 +25,9 @@
+ while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
+ var_dump($row);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_009.phpt sqlite-svn/tests/sqlite_009.phpt
+--- sqlite-1.0.3/tests/sqlite_009.phpt 2003-05-01 13:29:11.000000000 +0000
++++ sqlite-svn/tests/sqlite_009.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -25,6 +25,9 @@
+ while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
+ var_dump($row);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_010.phpt sqlite-svn/tests/sqlite_010.phpt
+--- sqlite-1.0.3/tests/sqlite_010.phpt 2003-05-02 22:09:54.000000000 +0000
++++ sqlite-svn/tests/sqlite_010.phpt 2012-10-09 13:36:42.721252390 +0000
+@@ -22,20 +22,23 @@
+ }
+
+ $r = sqlite_unbuffered_query("SELECT a from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_current($r, SQLITE_NUM));
+ sqlite_next($r);
+ }
+ $r = sqlite_query("SELECT a from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_current($r, SQLITE_NUM));
+ sqlite_next($r);
+ }
+ sqlite_rewind($r);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_current($r, SQLITE_NUM));
+ sqlite_next($r);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_011.phpt sqlite-svn/tests/sqlite_011.phpt
+--- sqlite-1.0.3/tests/sqlite_011.phpt 2003-12-14 18:47:14.000000000 +0000
++++ sqlite-svn/tests/sqlite_011.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -15,6 +15,7 @@
+ sqlite_query("INSERT INTO bar VALUES ('4', '5', '6')", $db);
+ $r = sqlite_query("SELECT * from foo, bar", $db, SQLITE_ASSOC);
+ var_dump(sqlite_fetch_array($r));
++sqlite_close($db);
+ ?>
+ --EXPECT--
+ array(6) {
+diff -dPNur sqlite-1.0.3/tests/sqlite_012.phpt sqlite-svn/tests/sqlite_012.phpt
+--- sqlite-1.0.3/tests/sqlite_012.phpt 2003-05-02 22:09:54.000000000 +0000
++++ sqlite-svn/tests/sqlite_012.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -21,6 +21,9 @@
+ for($i=0; $i<sqlite_num_fields($r); $i++) {
+ var_dump(sqlite_field_name($r, $i));
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_013.phpt sqlite-svn/tests/sqlite_013.phpt
+--- sqlite-1.0.3/tests/sqlite_013.phpt 2003-06-09 23:16:32.000000000 +0000
++++ sqlite-svn/tests/sqlite_013.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -22,7 +22,7 @@
+
+ echo "====BUFFERED====\n";
+ $r = sqlite_query("SELECT a, b from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_current($r, SQLITE_NUM));
+ var_dump(sqlite_column($r, 0));
+ var_dump(sqlite_column($r, 1));
+@@ -32,13 +32,16 @@
+ }
+ echo "====UNBUFFERED====\n";
+ $r = sqlite_unbuffered_query("SELECT a, b from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_column($r, 0));
+ var_dump(sqlite_column($r, 'b'));
+ var_dump(sqlite_column($r, 1));
+ var_dump(sqlite_column($r, 'a'));
+ sqlite_next($r);
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_014.phpt sqlite-svn/tests/sqlite_014.phpt
+--- sqlite-1.0.3/tests/sqlite_014.phpt 2003-06-09 23:21:06.000000000 +0000
++++ sqlite-svn/tests/sqlite_014.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -37,6 +37,8 @@
+ var_dump(sqlite_fetch_array($r));
+ var_dump(sqlite_fetch_all($r));
+
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECTF--
+@@ -59,7 +61,7 @@
+ }
+ }
+
+-Notice: sqlite_fetch_all(): One or more rowsets were already returned in %ssqlite_014.php on line %d
++Warning: sqlite_fetch_all(): One or more rowsets were already returned; returning NULL this time in %ssqlite_014.php on line %d
+ array(0) {
+ }
+ unbuffered with fetch_array
+diff -dPNur sqlite-1.0.3/tests/sqlite_015.phpt sqlite-svn/tests/sqlite_015.phpt
+--- sqlite-1.0.3/tests/sqlite_015.phpt 2003-06-09 23:22:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_015.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -24,6 +24,8 @@
+ $res = sqlite_array_query("SELECT a from strings", $db, SQLITE_NUM);
+ var_dump($res);
+
++$db = null;
++
+ echo "DONE!\n";
+ ?>
+ --EXPECTF--
+diff -dPNur sqlite-1.0.3/tests/sqlite_016.phpt sqlite-svn/tests/sqlite_016.phpt
+--- sqlite-1.0.3/tests/sqlite_016.phpt 2003-06-26 21:32:37.000000000 +0000
++++ sqlite-svn/tests/sqlite_016.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -22,14 +22,17 @@
+
+ echo "====BUFFERED====\n";
+ $r = sqlite_query("SELECT a, b from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_fetch_single($r));
+ }
+ echo "====UNBUFFERED====\n";
+ $r = sqlite_unbuffered_query("SELECT a, b from strings", $db);
+-while (sqlite_has_more($r)) {
++while (sqlite_valid($r)) {
+ var_dump(sqlite_fetch_single($r));
+ }
++
++sqlite_close($db);
++
+ echo "DONE!\n";
+ ?>
+ --EXPECT--
+diff -dPNur sqlite-1.0.3/tests/sqlite_018.phpt sqlite-svn/tests/sqlite_018.phpt
+--- sqlite-1.0.3/tests/sqlite_018.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_018.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,14 @@
++--TEST--
++sqlite: crash on bad queries inside sqlite_array_query()
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++sqlite_array_query($db, "SELECT foo FROM foobar");
++sqlite_close($db);
++?>
++--EXPECTF--
++Warning: sqlite_array_query(): no such table: foobar in %s on line %d
+diff -dPNur sqlite-1.0.3/tests/sqlite_019.phpt sqlite-svn/tests/sqlite_019.phpt
+--- sqlite-1.0.3/tests/sqlite_019.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_019.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,47 @@
++--TEST--
++sqlite: single query
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++sqlite_query($db, "CREATE TABLE test_db ( id INTEGER PRIMARY KEY, data VARCHAR(100) )");
++for ($i = 0; $i < 10; $i++) {
++ sqlite_query($db, "INSERT INTO test_db (data) VALUES('{$i}data')");
++}
++sqlite_query($db, "INSERT INTO test_db (data) VALUES(NULL)");
++
++var_dump(sqlite_single_query($db, "SELECT id FROM test_db WHERE id=5"));
++var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id=4"));
++var_dump(sqlite_single_query($db, "SELECT data FROM test_db WHERE id=6"));
++var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id < 5"));
++var_dump(sqlite_single_query($db, "SELECT * FROM test db WHERE id < 4"));
++var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id=999999"));
++var_dump(sqlite_single_query($db, "SELECT id FROM test_db WHERE id=5", FALSE));
++
++sqlite_close($db);
++?>
++--EXPECTF--
++string(1) "5"
++string(1) "4"
++string(5) "5data"
++array(4) {
++ [0]=>
++ string(1) "1"
++ [1]=>
++ string(1) "2"
++ [2]=>
++ string(1) "3"
++ [3]=>
++ string(1) "4"
++}
++
++Warning: sqlite_single_query(): no such table: test in %s on line %d
++bool(false)
++NULL
++array(1) {
++ [0]=>
++ string(1) "5"
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_022.phpt sqlite-svn/tests/sqlite_022.phpt
+--- sqlite-1.0.3/tests/sqlite_022.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_022.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,101 @@
++--TEST--
++sqlite: sqlite_seek
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++sqlite_query("CREATE TABLE strings(a)", $db);
++
++foreach ($data as $str) {
++ sqlite_query("INSERT INTO strings VALUES('$str')", $db);
++}
++
++$res = sqlite_query("SELECT a FROM strings", $db, SQLITE_NUM);
++for ($idx = -1; $idx < 4; $idx++) {
++ echo "====SEEK:$idx====\n";
++ sqlite_seek($res, $idx);
++ var_dump(sqlite_current($res));
++}
++echo "====AGAIN====\n";
++for ($idx = -1; $idx < 4; $idx++) {
++ echo "====SEEK:$idx====\n";
++ sqlite_seek($res, $idx);
++ var_dump(sqlite_current($res));
++}
++
++sqlite_close($db);
++
++echo "====DONE!====\n";
++?>
++--EXPECTF--
++====SEEK:-1====
++
++Warning: sqlite_seek(): row -1 out of range in %ssqlite_022.php on line %d
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:0====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:1====
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++====SEEK:2====
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:3====
++
++Warning: sqlite_seek(): row 3 out of range in %ssqlite_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====AGAIN====
++====SEEK:-1====
++
++Warning: sqlite_seek(): row -1 out of range in %ssqlite_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:0====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:1====
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++====SEEK:2====
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:3====
++
++Warning: sqlite_seek(): row 3 out of range in %ssqlite_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====DONE!====
+diff -dPNur sqlite-1.0.3/tests/sqlite_023.phpt sqlite-svn/tests/sqlite_023.phpt
+--- sqlite-1.0.3/tests/sqlite_023.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_023.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,105 @@
++--TEST--
++sqlite: sqlite_[has_]prev
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++sqlite_query("CREATE TABLE strings(a)", $db);
++
++foreach ($data as $str) {
++ sqlite_query("INSERT INTO strings VALUES('$str')", $db);
++}
++
++$r = sqlite_query("SELECT a FROM strings", $db, SQLITE_NUM);
++
++echo "====TRAVERSE====\n";
++for(sqlite_rewind($r); sqlite_valid($r); sqlite_next($r)) {
++ var_dump(sqlite_current($r));
++
++}
++echo "====REVERSE====\n";
++do {
++ sqlite_prev($r);
++ var_dump(sqlite_current($r));
++} while(sqlite_has_prev($r));
++
++echo "====UNBUFFERED====\n";
++
++$r = sqlite_unbuffered_query("SELECT a FROM strings", $db, SQLITE_NUM);
++
++echo "====TRAVERSE====\n";
++for(sqlite_rewind($r); sqlite_valid($r); sqlite_next($r)) {
++ var_dump(sqlite_current($r));
++
++}
++echo "====REVERSE====\n";
++do {
++ sqlite_prev($r);
++ var_dump(sqlite_current($r));
++} while(sqlite_has_prev($r));
++
++sqlite_close($db);
++
++echo "====DONE!====\n";
++?>
++--EXPECTF--
++====TRAVERSE====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====REVERSE====
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====UNBUFFERED====
++====TRAVERSE====
++
++Warning: sqlite_rewind(): Cannot rewind an unbuffered result set in %ssqlite_023.php on line %d
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====REVERSE====
++
++Warning: sqlite_prev(): you cannot use sqlite_prev on unbuffered querys in %ssqlite_023.php on line %d
++bool(false)
++
++Warning: sqlite_has_prev(): you cannot use sqlite_has_prev on unbuffered querys in %ssqlite_023.php on line %d
++====DONE!====
+diff -dPNur sqlite-1.0.3/tests/sqlite_024.phpt sqlite-svn/tests/sqlite_024.phpt
+--- sqlite-1.0.3/tests/sqlite_024.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_024.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,76 @@
++--TEST--
++sqlite: sqlite_fetch_object
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++class class24 {
++ function __construct() {
++ echo __METHOD__ . "\n";
++ }
++}
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++sqlite_query($db, "CREATE TABLE strings(a)");
++
++foreach ($data as $str) {
++ sqlite_query($db, "INSERT INTO strings VALUES('$str')");
++}
++
++echo "====class24====\n";
++$res = sqlite_query($db, "SELECT a FROM strings", SQLITE_ASSOC);
++while (sqlite_valid($res)) {
++ var_dump(sqlite_fetch_object($res, 'class24'));
++}
++
++echo "====stdclass====\n";
++$res = sqlite_query($db, "SELECT a FROM strings", SQLITE_ASSOC);
++while (sqlite_valid($res)) {
++ var_dump(sqlite_fetch_object($res));
++}
++
++sqlite_close($db);
++
++echo "====DONE!====\n";
++?>
++--EXPECTF--
++====class24====
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(3) "one"
++}
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(3) "two"
++}
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(5) "three"
++}
++====stdclass====
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(3) "one"
++}
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(3) "two"
++}
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(5) "three"
++}
++====DONE!====
+diff -dPNur sqlite-1.0.3/tests/sqlite_025.phpt sqlite-svn/tests/sqlite_025.phpt
+--- sqlite-1.0.3/tests/sqlite_025.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_025.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,38 @@
++--TEST--
++sqlite: sqlite_fetch_object in a loop
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++sqlite_query($db, "CREATE TABLE strings(a)");
++
++foreach (array("one", "two", "three") as $str) {
++ sqlite_query($db, "INSERT INTO strings VALUES('$str')");
++}
++
++$res = sqlite_query("SELECT * FROM strings", $db);
++
++while (($obj = sqlite_fetch_object($res))) {
++ var_dump($obj);
++}
++
++sqlite_close($db);
++?>
++--EXPECTF--
++object(stdClass)#1 (1) {
++ ["a"]=>
++ string(3) "one"
++}
++object(stdClass)#2 (1) {
++ ["a"]=>
++ string(3) "two"
++}
++object(stdClass)#1 (1) {
++ ["a"]=>
++ string(5) "three"
++}
+\ No newline at end of file
+diff -dPNur sqlite-1.0.3/tests/sqlite_026.phpt sqlite-svn/tests/sqlite_026.phpt
+--- sqlite-1.0.3/tests/sqlite_026.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_026.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,27 @@
++--TEST--
++sqlite: sqlite_fetch_column_types
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++sqlite_query($db, "CREATE TABLE strings(a, b INTEGER, c VARCHAR(10), d)");
++sqlite_query($db, "INSERT INTO strings VALUES('1', '2', '3', 'abc')");
++
++var_dump(sqlite_fetch_column_types($db, "strings"));
++
++sqlite_close($db);
++?>
++--EXPECT--
++array(4) {
++ ["a"]=>
++ string(0) ""
++ ["b"]=>
++ string(7) "INTEGER"
++ ["c"]=>
++ string(11) "VARCHAR(10)"
++ ["d"]=>
++ string(0) ""
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_027.phpt sqlite-svn/tests/sqlite_027.phpt
+--- sqlite-1.0.3/tests/sqlite_027.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_027.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,15 @@
++--TEST--
++sqlite: crash inside sqlite_escape_string() & sqlite_udf_encode_binary
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--INI--
++memory_limit=-1
++--FILE--
++<?php
++ var_dump(strlen(sqlite_escape_string(str_repeat("\0", 20000000))));
++ var_dump(strlen(sqlite_udf_encode_binary(str_repeat("\0", 20000000))));
++?>
++--EXPECT--
++int(20000002)
++int(20000002)
+diff -dPNur sqlite-1.0.3/tests/sqlite_closures_001.phpt sqlite-svn/tests/sqlite_closures_001.phpt
+--- sqlite-1.0.3/tests/sqlite_closures_001.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_closures_001.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,54 @@
++--TEST--
++sqlite: aggregate functions with closures
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++sqlite_query("CREATE TABLE strings(a)", $db);
++
++foreach ($data as $str) {
++ sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db);
++}
++
++function cat_step(&$context, $string)
++{
++ $context .= $string;
++}
++
++function cat_fin(&$context)
++{
++ return $context;
++}
++
++sqlite_create_aggregate($db, "cat", function (&$context, $string) {
++ $context .= $string;
++}, function (&$context) {
++ return $context;
++});
++
++$r = sqlite_query("SELECT cat(a) from strings", $db);
++while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
++ var_dump($row);
++}
++
++sqlite_close($db);
++
++echo "DONE!\n";
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(11) "onetwothree"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_closures_002.phpt sqlite-svn/tests/sqlite_closures_002.phpt
+--- sqlite-1.0.3/tests/sqlite_closures_002.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_closures_002.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,52 @@
++--TEST--
++sqlite: regular functions with closures
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb.inc";
++
++$data = array(
++ array("one", "uno"),
++ array("two", "dos"),
++ array("three", "tres"),
++ );
++
++sqlite_query("CREATE TABLE strings(a,b)", $db);
++
++foreach ($data as $row) {
++ sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($row[0]) . "','" . sqlite_escape_string($row[1]) . "')", $db);
++}
++
++sqlite_create_function($db, "implode", function () {
++ $args = func_get_args();
++ $sep = array_shift($args);
++ return implode($sep, $args);
++});
++
++$r = sqlite_query("SELECT implode('-', a, b) from strings", $db);
++while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
++ var_dump($row);
++}
++
++sqlite_close($db);
++
++echo "DONE!\n";
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(7) "one-uno"
++}
++array(1) {
++ [0]=>
++ string(7) "two-dos"
++}
++array(1) {
++ [0]=>
++ string(10) "three-tres"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_exec_basic.phpt sqlite-svn/tests/sqlite_exec_basic.phpt
+--- sqlite-1.0.3/tests/sqlite_exec_basic.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_exec_basic.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,34 @@
++--TEST--
++Test sqlite_exec() function : basic functionality
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
++--FILE--
++<?php
++/* Prototype : boolean sqlite_exec(string query, resource db[, string &error_message])
++ * Description: Executes a result-less query against a given database
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++ */
++
++echo "*** Testing sqlite_exec() : basic functionality ***\n";
++
++// set up variables
++$query = 'CREATE TABLE foobar (id INTEGER PRIMARY KEY, name CHAR(255));';
++$error_message = null;
++
++// procedural
++$db = sqlite_open(':memory:');
++var_dump( sqlite_exec($db, $query) );
++sqlite_close($db);
++
++// oo-style
++$db = new SQLiteDatabase(':memory:');
++var_dump( $db->queryExec($query, $error_message) );
++
++?>
++===DONE===
++--EXPECTF--
++*** Testing sqlite_exec() : basic functionality ***
++bool(true)
++bool(true)
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_exec_error.phpt sqlite-svn/tests/sqlite_exec_error.phpt
+--- sqlite-1.0.3/tests/sqlite_exec_error.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_exec_error.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,44 @@
++--TEST--
++Test sqlite_exec() function : error behaviour and functionality
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
++--FILE--
++<?php
++/* Prototype : boolean sqlite_exec(string query, resource db[, string &error_message])
++ * Description: Executes a result-less query against a given database
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++ */
++
++echo "*** Testing sqlite_exec() : error functionality ***\n";
++
++// set up variables
++$fail = 'CRE ATE TABLE';
++$error_message = null;
++
++// procedural
++$db = sqlite_open(':memory:');
++var_dump( sqlite_exec($db, $fail, $error_message) );
++var_dump( $error_message );
++var_dump( sqlite_exec($db) );
++sqlite_close($db);
++
++// oo-style
++$db = new SQLiteDatabase(':memory:');
++var_dump( $db->queryExec($fail, $error_message, 'fooparam') );
++
++?>
++===DONE===
++--EXPECTF--
++*** Testing sqlite_exec() : error functionality ***
++
++Warning: sqlite_exec(): near "CRE": syntax error in %s on line %d
++bool(false)
++%string|unicode%(24) "near "CRE": syntax error"
++
++Warning: sqlite_exec() expects at least 2 parameters, 1 given in %s on line %d
++NULL
++
++Warning: SQLiteDatabase::queryExec() expects at most 2 parameters, 3 given in %s on line %d
++NULL
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_last_error_basic.phpt sqlite-svn/tests/sqlite_last_error_basic.phpt
+--- sqlite-1.0.3/tests/sqlite_last_error_basic.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_last_error_basic.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,48 @@
++--TEST--
++Test sqlite_last_error() function : basic functionality
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
++--FILE--
++<?php
++/* Prototype : int sqlite_last_error(resource db)
++ * Description: Returns the error code of the last error for a database.
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++ */
++
++echo "*** Testing sqlite_last_error() : basic functionality ***\n";
++
++// set up variables
++$query = 'CREATE TAB LE foobar (id INTEGER PRIMARY KEY, name CHAR(255));';
++$query_ok = 'CREATE TABLE foobar (id INTEGER, name CHAR(255));';
++
++// procedural
++$db = sqlite_open(':memory:');
++var_dump( sqlite_last_error($db) === SQLITE_OK );
++sqlite_exec($db, $query);
++var_dump( sqlite_last_error($db) === SQLITE_ERROR );
++sqlite_exec($db, $query_ok);
++var_dump( sqlite_last_error($db) === SQLITE_OK );
++sqlite_close($db);
++
++// oo-style
++$db = new SQLiteDatabase(':memory:');
++$db->queryExec($query);
++var_dump( $db->lastError() === SQLITE_ERROR );
++$db->queryExec($query_ok);
++var_dump( $db->lastError() === SQLITE_OK );
++
++?>
++===DONE===
++--EXPECTF--
++*** Testing sqlite_last_error() : basic functionality ***
++bool(true)
++
++Warning: sqlite_exec(): near "TAB": syntax error in %s on line %d
++bool(true)
++bool(true)
++
++Warning: SQLiteDatabase::queryExec(): near "TAB": syntax error in %s on line %d
++bool(true)
++bool(true)
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_last_error_error.phpt sqlite-svn/tests/sqlite_last_error_error.phpt
+--- sqlite-1.0.3/tests/sqlite_last_error_error.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_last_error_error.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,47 @@
++--TEST--
++Test sqlite_last_error() function : error conditions
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
++--FILE--
++<?php
++/* Prototype : int sqlite_last_error(resource db)
++ * Description: Returns the error code of the last error for a database.
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++ */
++
++echo "*** Testing sqlite_last_error() : error conditions ***\n";
++
++// Zero arguments
++echo "\n-- Testing sqlite_last_error() function with Zero arguments --\n";
++var_dump( sqlite_last_error() );
++
++//Test sqlite_last_error with one more than the expected number of arguments
++echo "\n-- Testing sqlite_last_error() function with more than expected no. of arguments --\n";
++
++$db = sqlite_open(':memory:');
++$extra_arg = 10;
++var_dump( sqlite_last_error($db, $extra_arg) );
++sqlite_close($db);
++
++$db = new SQLiteDatabase(':memory:');
++var_dump( $db->lastError($extra_arg) );
++
++?>
++===DONE===
++--EXPECTF--
++*** Testing sqlite_last_error() : error conditions ***
++
++-- Testing sqlite_last_error() function with Zero arguments --
++
++Warning: sqlite_last_error() expects exactly 1 parameter, 0 given in %s on line %d
++NULL
++
++-- Testing sqlite_last_error() function with more than expected no. of arguments --
++
++Warning: sqlite_last_error() expects exactly 1 parameter, 2 given in %s on line %d
++NULL
++
++Warning: SQLiteDatabase::lastError() expects exactly 0 parameters, 1 given in %s on line %d
++NULL
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_001.phpt sqlite-svn/tests/sqlite_oo_001.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_001.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_001.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,17 @@
++--TEST--
++sqlite-oo: sqlite_open/close
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++require_once('blankdb_oo.inc');
++var_dump($db);
++$db = NULL;
++echo "Done\n";
++?>
++--EXPECTF--
++object(SQLiteDatabase)#%d (0) {
++}
++Done
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_002.phpt sqlite-svn/tests/sqlite_oo_002.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_002.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_002.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,41 @@
++--TEST--
++sqlite-oo: Simple insert/select
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++require_once('blankdb_oo.inc');
++var_dump($db);
++
++var_dump($db->query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))"));
++var_dump($db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)"));
++$r = $db->query("SELECT * from foo");
++var_dump($r);
++var_dump($r->fetch());
++?>
++--EXPECTF--
++object(SQLiteDatabase)#%d (0) {
++}
++object(SQLiteResult)#%d (0) {
++}
++object(SQLiteResult)#%d (0) {
++}
++object(SQLiteResult)#%d (0) {
++}
++array(6) {
++ [0]=>
++ string(10) "2002-01-02"
++ ["c1"]=>
++ string(10) "2002-01-02"
++ [1]=>
++ string(8) "12:49:00"
++ ["c2"]=>
++ string(8) "12:49:00"
++ [2]=>
++ NULL
++ ["c3"]=>
++ NULL
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_003.phpt sqlite-svn/tests/sqlite_oo_003.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_003.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_003.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,51 @@
++--TEST--
++sqlite-oo: Simple insert/select, different result representation
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))");
++$db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)");
++$r = $db->query("SELECT * from foo");
++var_dump($r->fetch(SQLITE_BOTH));
++$r = $db->query("SELECT * from foo");
++var_dump($r->fetch(SQLITE_NUM));
++$r = $db->query("SELECT * from foo");
++var_dump($r->fetch(SQLITE_ASSOC));
++?>
++--EXPECT--
++array(6) {
++ [0]=>
++ string(10) "2002-01-02"
++ ["c1"]=>
++ string(10) "2002-01-02"
++ [1]=>
++ string(8) "12:49:00"
++ ["c2"]=>
++ string(8) "12:49:00"
++ [2]=>
++ NULL
++ ["c3"]=>
++ NULL
++}
++array(3) {
++ [0]=>
++ string(10) "2002-01-02"
++ [1]=>
++ string(8) "12:49:00"
++ [2]=>
++ NULL
++}
++array(3) {
++ ["c1"]=>
++ string(10) "2002-01-02"
++ ["c2"]=>
++ string(8) "12:49:00"
++ ["c3"]=>
++ NULL
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_008.phpt sqlite-svn/tests/sqlite_oo_008.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_008.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_008.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,43 @@
++--TEST--
++sqlite-oo: fetch all (buffered)
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++$r = $db->query("SELECT a from strings");
++while ($row = $r->fetch(SQLITE_NUM)) {
++ var_dump($row);
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_009.phpt sqlite-svn/tests/sqlite_oo_009.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_009.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_009.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,43 @@
++--TEST--
++sqlite-oo: fetch all (unbuffered)
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++$r = $db->unbufferedQuery("SELECT a from strings");
++while ($row = $r->fetch(SQLITE_NUM)) {
++ var_dump($row);
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_010.phpt sqlite-svn/tests/sqlite_oo_010.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_010.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_010.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,44 @@
++--TEST--
++sqlite-oo: fetch all (iterator)
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++while ($row = $r->valid()) {
++ var_dump($r->current());
++ $r->next();
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_011.phpt sqlite-svn/tests/sqlite_oo_011.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_011.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_011.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,33 @@
++--TEST--
++sqlite-oo: returned associative column names
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE foo (c1 char, c2 char, c3 char)");
++$db->query("CREATE TABLE bar (c1 char, c2 char, c3 char)");
++$db->query("INSERT INTO foo VALUES ('1', '2', '3')");
++$db->query("INSERT INTO bar VALUES ('4', '5', '6')");
++$r = $db->query("SELECT * from foo, bar", SQLITE_ASSOC);
++var_dump($r->fetch());
++?>
++--EXPECT--
++array(6) {
++ ["foo.c1"]=>
++ string(1) "1"
++ ["foo.c2"]=>
++ string(1) "2"
++ ["foo.c3"]=>
++ string(1) "3"
++ ["bar.c1"]=>
++ string(1) "4"
++ ["bar.c2"]=>
++ string(1) "5"
++ ["bar.c3"]=>
++ string(1) "6"
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_012.phpt sqlite-svn/tests/sqlite_oo_012.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_012.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_012.phpt 2012-10-09 13:36:42.721252390 +0000
+@@ -0,0 +1,35 @@
++--TEST--
++sqlite-oo: read field names
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE strings(foo VARCHAR, bar VARCHAR, baz VARCHAR)");
++
++echo "Buffered\n";
++$r = $db->query("SELECT * from strings");
++for($i=0; $i<$r->numFields(); $i++) {
++ var_dump($r->fieldName($i));
++}
++echo "Unbuffered\n";
++$r = $db->unbufferedQuery("SELECT * from strings");
++for($i=0; $i<$r->numFields(); $i++) {
++ var_dump($r->fieldName($i));
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++Buffered
++string(3) "foo"
++string(3) "bar"
++string(3) "baz"
++Unbuffered
++string(3) "foo"
++string(3) "bar"
++string(3) "baz"
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_013.phpt sqlite-svn/tests/sqlite_oo_013.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_013.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_013.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,75 @@
++--TEST--
++sqlite-oo: fetch column
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ array (0 => 'one', 1 => 'two'),
++ array (0 => 'three', 1 => 'four')
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
++}
++
++echo "====BUFFERED====\n";
++$r = $db->query("SELECT a, b from strings");
++while ($r->valid()) {
++ var_dump($r->current(SQLITE_NUM));
++ var_dump($r->column(0));
++ var_dump($r->column(1));
++ var_dump($r->column('a'));
++ var_dump($r->column('b'));
++ $r->next();
++}
++echo "====UNBUFFERED====\n";
++$r = $db->unbufferedQuery("SELECT a, b from strings");
++while ($r->valid()) {
++ var_dump($r->column(0));
++ var_dump($r->column('b'));
++ var_dump($r->column(1));
++ var_dump($r->column('a'));
++ $r->next();
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++====BUFFERED====
++array(2) {
++ [0]=>
++ string(3) "one"
++ [1]=>
++ string(3) "two"
++}
++string(3) "one"
++string(3) "two"
++string(3) "one"
++string(3) "two"
++array(2) {
++ [0]=>
++ string(5) "three"
++ [1]=>
++ string(4) "four"
++}
++string(5) "three"
++string(4) "four"
++string(5) "three"
++string(4) "four"
++====UNBUFFERED====
++string(3) "one"
++string(3) "two"
++NULL
++NULL
++string(5) "three"
++string(4) "four"
++NULL
++NULL
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_014.phpt sqlite-svn/tests/sqlite_oo_014.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_014.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_014.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,118 @@
++--TEST--
++sqlite-oo: fetch all
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++echo "unbuffered twice\n";
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++var_dump($r->fetchAll());
++var_dump($r->fetchAll());
++
++echo "unbuffered with fetch_array\n";
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++var_dump($r->fetch());
++var_dump($r->fetchAll());
++
++echo "buffered\n";
++$r = $db->query("SELECT a from strings", SQLITE_NUM);
++var_dump($r->fetchAll());
++var_dump($r->fetch());
++var_dump($r->fetchAll());
++
++echo "DONE!\n";
++?>
++--EXPECTF--
++unbuffered twice
++array(3) {
++ [0]=>
++ array(1) {
++ [0]=>
++ string(3) "one"
++ }
++ [1]=>
++ array(1) {
++ [0]=>
++ string(3) "two"
++ }
++ [2]=>
++ array(1) {
++ [0]=>
++ string(5) "three"
++ }
++}
++
++Warning: SQLiteUnbuffered::fetchAll(): One or more rowsets were already returned; returning NULL this time in %ssqlite_oo_014.php on line %d
++array(0) {
++}
++unbuffered with fetch_array
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(2) {
++ [0]=>
++ array(1) {
++ [0]=>
++ string(3) "two"
++ }
++ [1]=>
++ array(1) {
++ [0]=>
++ string(5) "three"
++ }
++}
++buffered
++array(3) {
++ [0]=>
++ array(1) {
++ [0]=>
++ string(3) "one"
++ }
++ [1]=>
++ array(1) {
++ [0]=>
++ string(3) "two"
++ }
++ [2]=>
++ array(1) {
++ [0]=>
++ string(5) "three"
++ }
++}
++bool(false)
++array(3) {
++ [0]=>
++ array(1) {
++ [0]=>
++ string(3) "one"
++ }
++ [1]=>
++ array(1) {
++ [0]=>
++ string(3) "two"
++ }
++ [2]=>
++ array(1) {
++ [0]=>
++ string(5) "three"
++ }
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_015.phpt sqlite-svn/tests/sqlite_oo_015.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_015.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_015.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,47 @@
++--TEST--
++sqlite-oo: array_query
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++$res = $db->arrayQuery("SELECT a from strings", SQLITE_NUM);
++var_dump($res);
++
++echo "DONE!\n";
++?>
++--EXPECTF--
++array(3) {
++ [0]=>
++ array(1) {
++ [0]=>
++ string(3) "one"
++ }
++ [1]=>
++ array(1) {
++ [0]=>
++ string(3) "two"
++ }
++ [2]=>
++ array(1) {
++ [0]=>
++ string(5) "three"
++ }
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_016.phpt sqlite-svn/tests/sqlite_oo_016.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_016.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_016.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,42 @@
++--TEST--
++sqlite-oo: fetch single
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ array (0 => 'one', 1 => 'two'),
++ array (0 => 'three', 1 => 'four')
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
++}
++
++echo "====BUFFERED====\n";
++$r = $db->query("SELECT a, b from strings");
++while ($r->valid()) {
++ var_dump($r->fetchSingle());
++}
++echo "====UNBUFFERED====\n";
++$r = $db->unbufferedQuery("SELECT a, b from strings");
++while ($r->valid()) {
++ var_dump($r->fetchSingle());
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++====BUFFERED====
++string(3) "one"
++string(5) "three"
++====UNBUFFERED====
++string(3) "one"
++string(5) "three"
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_020.phpt sqlite-svn/tests/sqlite_oo_020.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_020.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_020.phpt 2012-10-09 13:36:42.721252390 +0000
+@@ -0,0 +1,66 @@
++--TEST--
++sqlite-oo: factory and exception
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++$dbname = tempnam(dirname(__FILE__), "phpsql");
++function cleanup() {
++ global $db, $dbname;
++
++ $db = NULL;
++ unlink($dbname);
++}
++register_shutdown_function("cleanup");
++
++try {
++ $db = sqlite_factory();
++} catch(SQLiteException $err) {
++ echo "Message: ".$err->getMessage()."\n";
++ echo "File: ".$err->getFile()."\n";
++ //echo "Line: ".$err->getLine()."\n";
++ //print_r($err->getTrace());
++ //echo "BackTrace: ".$err->getTraceAsString()."\n";
++}
++
++$db = sqlite_factory($dbname);
++
++$data = array(
++ array (0 => 'one', 1 => 'two'),
++ array (0 => 'three', 1 => 'four')
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
++}
++
++$r = $db->unbufferedQuery("SELECT a, b from strings");
++while ($r->valid()) {
++ var_dump($r->current(SQLITE_NUM));
++ $r->next();
++}
++$r = null;
++$db = null;
++echo "DONE!\n";
++?>
++--EXPECTF--
++Message: sqlite_factory() expects at least 1 parameter, 0 given
++File: %ssqlite_oo_020.php
++array(2) {
++ [0]=>
++ string(3) "one"
++ [1]=>
++ string(3) "two"
++}
++array(2) {
++ [0]=>
++ string(5) "three"
++ [1]=>
++ string(4) "four"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_021.phpt sqlite-svn/tests/sqlite_oo_021.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_021.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_021.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,48 @@
++--TEST--
++sqlite-oo: single query
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE test_db ( id INTEGER PRIMARY KEY, data VARCHAR(100) )");
++for ($i = 0; $i < 10; $i++) {
++ $db->query("INSERT INTO test_db (data) VALUES('{$i}data')");
++}
++$db->query("INSERT INTO test_db (data) VALUES(NULL)");
++
++var_dump($db->singleQuery("SELECT id FROM test_db WHERE id=5"));
++var_dump($db->singleQuery("SELECT * FROM test_db WHERE id=4"));
++var_dump($db->singleQuery("SELECT data FROM test_db WHERE id=6"));
++var_dump($db->singleQuery("SELECT * FROM test_db WHERE id < 5"));
++var_dump($db->singleQuery("SELECT * FROM test db WHERE id < 4"));
++var_dump($db->singleQuery("SELECT * FROM test_db WHERE id=999999"));
++var_dump($db->singleQuery("SELECT id FROM test_db WHERE id=5", FALSE));
++
++echo "DONE!\n";
++?>
++--EXPECTF--
++string(1) "5"
++string(1) "4"
++string(5) "5data"
++array(4) {
++ [0]=>
++ string(1) "1"
++ [1]=>
++ string(1) "2"
++ [2]=>
++ string(1) "3"
++ [3]=>
++ string(1) "4"
++}
++
++Warning: SQLiteDatabase::singleQuery(): no such table: test in %s on line %d
++bool(false)
++NULL
++array(1) {
++ [0]=>
++ string(1) "5"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_022.phpt sqlite-svn/tests/sqlite_oo_022.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_022.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_022.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,98 @@
++--TEST--
++sqlite-oo: sqlite::seek
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++$res = $db->query("SELECT a FROM strings", SQLITE_NUM);
++for ($idx = -1; $idx < 4; $idx++) {
++ echo "====SEEK:$idx====\n";
++ $res->seek($idx);
++ var_dump($res->current());
++}
++echo "====AGAIN====\n";
++for ($idx = -1; $idx < 4; $idx++) {
++ echo "====SEEK:$idx====\n";
++ $res->seek($idx);
++ var_dump($res->current());
++}
++echo "====DONE!====\n";
++?>
++--EXPECTF--
++====SEEK:-1====
++
++Warning: SQLiteResult::seek(): row -1 out of range in %ssqlite_oo_022.php on line %d
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:0====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:1====
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++====SEEK:2====
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:3====
++
++Warning: SQLiteResult::seek(): row 3 out of range in %ssqlite_oo_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====AGAIN====
++====SEEK:-1====
++
++Warning: SQLiteResult::seek(): row -1 out of range in %ssqlite_oo_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:0====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++====SEEK:1====
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++====SEEK:2====
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====SEEK:3====
++
++Warning: SQLiteResult::seek(): row 3 out of range in %ssqlite_oo_022.php on line %d
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====DONE!====
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_024.phpt sqlite-svn/tests/sqlite_oo_024.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_024.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_024.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,74 @@
++--TEST--
++sqlite-oo: sqlite::fetch_object
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++class class24 {
++ function __construct() {
++ echo __METHOD__ . "\n";
++ }
++}
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++echo "====class24====\n";
++$res = $db->query("SELECT a FROM strings", SQLITE_ASSOC);
++while ($res->valid()) {
++ var_dump($res->fetchObject('class24'));
++}
++
++echo "====stdclass====\n";
++$res = $db->query("SELECT a FROM strings", SQLITE_ASSOC);
++while ($res->valid()) {
++ var_dump($res->fetchObject());
++}
++
++echo "====DONE!====\n";
++?>
++--EXPECTF--
++====class24====
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(3) "one"
++}
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(3) "two"
++}
++class24::__construct
++object(class24)#%d (1) {
++ ["a"]=>
++ string(5) "three"
++}
++====stdclass====
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(3) "one"
++}
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(3) "two"
++}
++object(stdClass)#%d (1) {
++ ["a"]=>
++ string(5) "three"
++}
++====DONE!====
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_025.phpt sqlite-svn/tests/sqlite_oo_025.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_025.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_025.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,103 @@
++--TEST--
++sqlite-oo: sqlite / foreach
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++echo "====UNBUFFERED====\n";
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++//var_dump(class_implements($r));
++foreach($r as $row) {
++ var_dump($row);
++}
++echo "====NO-MORE====\n";
++foreach($r as $row) {
++ var_dump($row);
++}
++echo "====DIRECT====\n";
++foreach($db->unbufferedQuery("SELECT a from strings", SQLITE_NUM) as $row) {
++ var_dump($row);
++}
++echo "====BUFFERED====\n";
++$r = $db->query("SELECT a from strings", SQLITE_NUM);
++//var_dump(class_implements($r));
++foreach($r as $row) {
++ var_dump($row);
++}
++foreach($r as $row) {
++ var_dump($row);
++}
++echo "DONE!\n";
++?>
++--EXPECT--
++====UNBUFFERED====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====NO-MORE====
++====DIRECT====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++====BUFFERED====
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++array(1) {
++ [0]=>
++ string(3) "one"
++}
++array(1) {
++ [0]=>
++ string(3) "two"
++}
++array(1) {
++ [0]=>
++ string(5) "three"
++}
++DONE!
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_026.phpt sqlite-svn/tests/sqlite_oo_026.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_026.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_026.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,56 @@
++--TEST--
++sqlite-oo: unbuffered
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array(
++ "one",
++ "two",
++ "three"
++ );
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++}
++
++echo "====FOREACH====\n";
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++foreach($r as $idx => $row) {
++ var_dump($row[0]);
++ var_dump($row[0]);
++}
++echo "====FOR====\n";
++$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
++for(;$r->valid(); $r->next()) {
++ $v = $r->column(0);
++ var_dump($v);
++ $c = $r->column(0);
++ var_dump(is_null($c) || $c==$v);
++}
++echo "===DONE===\n";
++?>
++--EXPECT--
++====FOREACH====
++string(3) "one"
++string(3) "one"
++string(3) "two"
++string(3) "two"
++string(5) "three"
++string(5) "three"
++====FOR====
++string(3) "one"
++bool(true)
++string(3) "two"
++bool(true)
++string(5) "three"
++bool(true)
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_027.phpt sqlite-svn/tests/sqlite_oo_027.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_027.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_027.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,42 @@
++--TEST--
++sqlite-oo: changes
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$data = array("one", "two", "three");
++
++$db->query("CREATE TABLE strings(a VARCHAR)");
++
++foreach ($data as $str) {
++ $db->query("INSERT INTO strings VALUES('$str')");
++ echo $db->changes() . "\n";
++}
++
++$db->query("UPDATE strings SET a='foo' WHERE a!='two'");
++echo $db->changes() . "\n";
++
++$db->query("DELETE FROM strings WHERE 1");
++echo $db->changes() . "\n";
++
++$str = '';
++foreach ($data as $s) {
++ $str .= "INSERT INTO strings VALUES('".$s."');";
++}
++$db->query($str);
++echo $db->changes() . "\n";
++
++?>
++--EXPECT--
++1
++1
++1
++2
++3
++3
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_028.phpt sqlite-svn/tests/sqlite_oo_028.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_028.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_028.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,25 @@
++--TEST--
++sqlite-oo: sqlite_fetch_column_types
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE strings(a, b INTEGER, c VARCHAR(10), d)");
++$db->query("INSERT INTO strings VALUES('1', '2', '3', 'abc')");
++
++var_dump($db->fetchColumnTypes("strings"));
++?>
++--EXPECT--
++array(4) {
++ ["a"]=>
++ string(0) ""
++ ["b"]=>
++ string(7) "INTEGER"
++ ["c"]=>
++ string(11) "VARCHAR(10)"
++ ["d"]=>
++ string(0) ""
++}
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_029.phpt sqlite-svn/tests/sqlite_oo_029.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_029.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_029.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,53 @@
++--TEST--
++sqlite-oo: call method with $this
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE strings(key VARCHAR(10), var VARCHAR(10))");
++$db->query("INSERT INTO strings VALUES('foo', 'foo')");
++
++class sqlite_help
++{
++ function __construct($db){
++ $this->db = $db;
++ $this->db->createFunction('link_keywords', array(&$this, 'linkers'), 1);
++ }
++
++ function getSingle($key)
++ {
++ return $this->db->singleQuery('SELECT link_keywords(var) FROM strings WHERE key=\''.$key.'\'', 1);
++ }
++
++ function linkers($str)
++ {
++ $str = str_replace('foo', 'bar', $str);
++ return $str;
++ }
++
++ function free()
++ {
++ unset($this->db);
++ }
++
++ function __destruct()
++ {
++ echo "DESTRUCTED\n";
++ }
++}
++
++$obj = new sqlite_help($db);
++echo $obj->getSingle('foo')."\n";
++$obj->free();
++unset($obj);
++
++?>
++===DONE===
++--EXPECT--
++bar
++===DONE===
++DESTRUCTED
+diff -dPNur sqlite-1.0.3/tests/sqlite_oo_030.phpt sqlite-svn/tests/sqlite_oo_030.phpt
+--- sqlite-1.0.3/tests/sqlite_oo_030.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_oo_030.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,44 @@
++--TEST--
++sqlite-oo: calling static methods
++--INI--
++sqlite.assoc_case=0
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++
++require_once('blankdb_oo.inc');
++
++class foo {
++ static function bar($param = NULL) {
++ return $param;
++ }
++}
++
++function baz($param = NULL) {
++ return $param;
++}
++
++var_dump($db->singleQuery("select php('baz')", 1));
++var_dump($db->singleQuery("select php('baz', 1)", 1));
++var_dump($db->singleQuery("select php('baz', \"PHP\")", 1));
++var_dump($db->singleQuery("select php('foo::bar')", 1));
++var_dump($db->singleQuery("select php('foo::bar', 1)", 1));
++var_dump($db->singleQuery("select php('foo::bar', \"PHP\")", 1));
++var_dump($db->singleQuery("select php('foo::bar(\"PHP\")')", 1));
++
++?>
++===DONE===
++--EXPECTF--
++NULL
++string(1) "1"
++string(3) "PHP"
++NULL
++string(1) "1"
++string(3) "PHP"
++
++Warning: SQLiteDatabase::singleQuery(): function `foo::bar("PHP")' is not a function name in %ssqlite_oo_030.php on line %d
++bool(false)
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_popen_basic.phpt sqlite-svn/tests/sqlite_popen_basic.phpt
+--- sqlite-1.0.3/tests/sqlite_popen_basic.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_popen_basic.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,27 @@
++--TEST--
++SQLite: sqlite_popen() basic tests
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip"; ?>
++--FILE--
++<?php
++/* Prototype : resource sqlite_popen(string filename [, int mode [, string &error_message]])
++ * Description: Opens a persistent handle to a SQLite database. Will create the database if it does not exist.
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++*/
++
++ $db1 = sqlite_popen(":memory:");
++ $db2 = sqlite_popen(":memory:");
++
++ var_dump($db1);
++ var_dump($db2);
++
++ list($resourceId1) = sscanf((string) $db1, "resource(%d) of type (sqlite database (persistent))");
++ list($resourceId2) = sscanf((string) $db2, "resource(%d) of type (sqlite database (persistent))");
++
++ var_dump($resourceId1 === $resourceId2);
++?>
++--EXPECTF--
++resource(%d) of type (sqlite database (persistent))
++resource(%d) of type (sqlite database (persistent))
++bool(true)
+diff -dPNur sqlite-1.0.3/tests/sqlite_popen_error.phpt sqlite-svn/tests/sqlite_popen_error.phpt
+--- sqlite-1.0.3/tests/sqlite_popen_error.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_popen_error.phpt 2012-10-09 13:36:42.721252390 +0000
+@@ -0,0 +1,34 @@
++--TEST--
++Test sqlite_popen() function : error conditions
++--SKIPIF--
++<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
++--FILE--
++<?php
++/* Prototype : resource sqlite_popen(string filename [, int mode [, string &error_message]])
++ * Description: Opens a persistent handle to a SQLite database. Will create the database if it does not exist.
++ * Source code: ext/sqlite/sqlite.c
++ * Alias to functions:
++ */
++
++$message = '';
++
++echo "*** Testing sqlite_popen() : error conditions ***\n";
++
++var_dump( sqlite_popen() );
++var_dump( sqlite_popen(":memory:", 0666, $message, 'foobar') );
++var_dump( sqlite_popen("", 0666, $message) );
++var_dump( $message );
++
++?>
++===DONE===
++--EXPECTF--
++*** Testing sqlite_popen() : error conditions ***
++
++Warning: sqlite_popen() expects at least 1 parameter, 0 given in %s on line %d
++NULL
++
++Warning: sqlite_popen() expects at most 3 parameters, 4 given in %s on line %d
++NULL
++bool(false)
++NULL
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_session_001.phpt sqlite-svn/tests/sqlite_session_001.phpt
+--- sqlite-1.0.3/tests/sqlite_session_001.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_session_001.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,46 @@
++--TEST--
++sqlite, session storage test
++--CREDITS--
++Mats Lindh <mats at lindh.no>
++#Testfest php.no
++--INI--
++session.save_handler = sqlite
++--SKIPIF--
++if (!extension_loaded("session"))
++{
++ die("skip Session module not loaded");
++}
++if (!extension_loaded("sqlite"))
++{
++ die("skip Session module not loaded");
++}
++--FILE--
++<?php
++/* Description: Tests that sqlite can be used as a session save handler
++* Source code: ext/sqlite/sess_sqlite.c
++*/
++
++ob_start();
++session_save_path(__DIR__ . "/sessiondb.sdb");
++
++// create the session and set a session value
++session_start();
++$_SESSION["test"] = "foo_bar";
++
++// close the session and unset the value
++session_write_close();
++unset($_SESSION["test"]);
++var_dump(isset($_SESSION["test"]));
++
++// start the session again and check that we have the proper value
++session_start();
++var_dump($_SESSION["test"]);
++ob_end_flush();
++?>
++--EXPECTF--
++bool(false)
++%unicode|string%(7) "foo_bar"
++--CLEAN--
++<?php
++ unlink(__DIR__ . "/sessiondb.sdb")
++?>
+diff -dPNur sqlite-1.0.3/tests/sqlite_session_002.phpt sqlite-svn/tests/sqlite_session_002.phpt
+--- sqlite-1.0.3/tests/sqlite_session_002.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_session_002.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,54 @@
++--TEST--
++sqlite, session destroy test
++--CREDITS--
++Mats Lindh <mats at lindh.no>
++#Testfest php.no
++--INI--
++session.save_handler = sqlite
++--SKIPIF--
++if (!extension_loaded("session"))
++{
++ die("skip Session module not loaded");
++}
++if (!extension_loaded("sqlite"))
++{
++ die("skip sqlite module not loaded");
++}
++--FILE--
++<?php
++/* Description: Tests that sqlite will destroy a session when used as a session handler
++* Source code: ext/sqlite/sess_sqlite.c
++*/
++ob_start();
++session_save_path(__DIR__ . "/sessiondb.sdb");
++
++// start a session and save a value to it before commiting the session to the database
++session_start();
++$_SESSION["test"] = "foo_bar";
++session_write_close();
++
++// remove the session value
++unset($_SESSION["test"]);
++var_dump(isset($_SESSION["test"]));
++
++// start the session again and destroy it
++session_start();
++var_dump($_SESSION["test"]);
++session_destroy();
++session_write_close();
++
++unset($_SESSION["test"]);
++
++// check that the session has been destroyed
++session_start();
++var_dump(isset($_SESSION["test"]));
++ob_end_flush();
++?>
++--EXPECTF--
++bool(false)
++%unicode|string%(7) "foo_bar"
++bool(false)
++--CLEAN--
++<?php
++ unlink(__DIR__ . "/sessiondb.sdb")
++?>
+diff -dPNur sqlite-1.0.3/tests/sqlite_spl_001.phpt sqlite-svn/tests/sqlite_spl_001.phpt
+--- sqlite-1.0.3/tests/sqlite_spl_001.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_spl_001.phpt 2012-10-09 13:36:42.730091166 +0000
+@@ -0,0 +1,125 @@
++--TEST--
++sqlite-spl: Iteration
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++if (!extension_loaded("spl")) print "skip SPL is not present";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE menu(id_l int PRIMARY KEY, id_r int UNIQUE, key VARCHAR(10))");
++$db->query("INSERT INTO menu VALUES( 1, 12, 'A')");
++$db->query("INSERT INTO menu VALUES( 2, 9, 'B')");
++$db->query("INSERT INTO menu VALUES(10, 11, 'F')");
++$db->query("INSERT INTO menu VALUES( 3, 6, 'C')");
++$db->query("INSERT INTO menu VALUES( 7, 8, 'E')");
++$db->query("INSERT INTO menu VALUES( 4, 5, 'D')");
++
++class SqliteNestedsetElement
++{
++ protected $id_l;
++ protected $id_r;
++ protected $key;
++
++ function __construct($db)
++ {
++ $this->db = $db;
++ }
++
++ function getLeft()
++ {
++ return $this->id_l;
++ }
++
++ function getRight()
++ {
++ return $this->id_r;
++ }
++
++ function __toString()
++ {
++ return $this->key;
++ }
++
++ function key()
++ {
++ return $this->key;
++ }
++}
++
++class SqliteNestedset implements RecursiveIterator
++{
++ protected $id;
++ protected $id_l;
++ protected $id_r;
++ protected $entry;
++
++ function __construct($db, $id_l = 1)
++ {
++ $this->db = $db;
++ $this->id_l = $id_l;
++ $this->id_r = $this->db->singleQuery('SELECT id_r FROM menu WHERE id_l='.$id_l, 1);
++ $this->id = $id_l;
++ }
++
++ function rewind()
++ {
++ $this->id = $this->id_l;
++ $this->fetch();
++ }
++
++ function valid()
++ {
++ return is_object($this->entry);
++ }
++
++ function current()
++ {
++ return $this->entry->__toString();
++ }
++
++ function key()
++ {
++ return $this->entry->key();;
++ }
++
++ function next()
++ {
++ $this->id = $this->entry->getRight() + 1;
++ $this->fetch();
++ }
++
++ protected function fetch()
++ {
++ $res = $this->db->unbufferedQuery('SELECT * FROM menu WHERE id_l='.$this->id);
++ $this->entry = $res->fetchObject('SqliteNestedsetElement', array(&$this->db));
++ unset($res);
++ }
++
++ function hasChildren()
++ {
++ return $this->entry->getLeft() + 1 < $this->entry->getRight();
++ }
++
++ function getChildren()
++ {
++ return new SqliteNestedset($this->db, $this->entry->getLeft() + 1, $this->entry->getRight() - 1);
++ }
++}
++
++$menu_iterator = new RecursiveIteratorIterator(new SqliteNestedset($db), RecursiveIteratorIterator::SELF_FIRST);
++foreach($menu_iterator as $entry) {
++ echo $menu_iterator->getDepth() . $entry . "\n";
++}
++?>
++===DONE===
++--EXPECT--
++0A
++1B
++2C
++3D
++2E
++1F
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_spl_002.phpt sqlite-svn/tests/sqlite_spl_002.phpt
+--- sqlite-1.0.3/tests/sqlite_spl_002.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_spl_002.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,29 @@
++--TEST--
++sqlite-spl: Countable
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++if (!extension_loaded("spl")) print "skip SPL is not present";
++?>
++--FILE--
++<?php
++include "blankdb_oo.inc";
++
++$db->query("CREATE TABLE menu(id_l int PRIMARY KEY, id_r int UNIQUE, key VARCHAR(10))");
++$db->query("INSERT INTO menu VALUES( 1, 12, 'A')");
++$db->query("INSERT INTO menu VALUES( 2, 9, 'B')");
++$db->query("INSERT INTO menu VALUES(10, 11, 'F')");
++$db->query("INSERT INTO menu VALUES( 3, 6, 'C')");
++$db->query("INSERT INTO menu VALUES( 7, 8, 'E')");
++$db->query("INSERT INTO menu VALUES( 4, 5, 'D')");
++
++$res = $db->query("SELECT * from menu");
++
++var_dump($res->count());
++var_dump(count($res));
++?>
++===DONE===
++--EXPECT--
++int(6)
++int(6)
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlite_spl_003.phpt sqlite-svn/tests/sqlite_spl_003.phpt
+--- sqlite-1.0.3/tests/sqlite_spl_003.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlite_spl_003.phpt 2012-10-09 13:36:42.740092676 +0000
+@@ -0,0 +1,28 @@
++--TEST--
++sqlite-spl: Exception
++--SKIPIF--
++<?php # vim:ft=php
++if (!extension_loaded("sqlite")) print "skip";
++if (!extension_loaded("spl")) print "skip SPL is not present";
++?>
++--FILE--
++<?php
++
++try
++{
++ $db = sqlite_factory();
++}
++catch(SQLiteException $e)
++{
++ $parents = class_parents($e);
++ if (array_key_exists('RuntimeException', $parents))
++ {
++ echo "GOOD\n";
++ }
++}
++
++?>
++===DONE===
++--EXPECT--
++GOOD
++===DONE===
+diff -dPNur sqlite-1.0.3/tests/sqlitedatabase_arrayquery.phpt sqlite-svn/tests/sqlitedatabase_arrayquery.phpt
+--- sqlite-1.0.3/tests/sqlitedatabase_arrayquery.phpt 1970-01-01 00:00:00.000000000 +0000
++++ sqlite-svn/tests/sqlitedatabase_arrayquery.phpt 2012-10-09 13:36:42.721252390 +0000
+@@ -0,0 +1,23 @@
++--TEST--
++Testing SQLiteDatabase::ArrayQuery with NULL-byte string
++--SKIPIF--
++<?php
++if (!extension_loaded("sqlite")) print "skip";
++?>
++--FILE--
++<?php
++
++$method = new ReflectionMethod('sqlitedatabase::arrayquery');
++
++$class = $method->getDeclaringClass()->newInstanceArgs(array(':memory:'));
++
++$p = "\0";
++
++$method->invokeArgs($class, array_fill(0, 2, $p));
++$method->invokeArgs($class, array_fill(0, 1, $p));
++
++?>
++--EXPECTF--
++Warning: SQLiteDatabase::arrayQuery() expects parameter 2 to be long, string given in %s on line %d
++
++Warning: SQLiteDatabase::arrayQuery(): Cannot execute empty query. in %s on line %d
diff --git a/dev-php/pecl-sqlite/pecl-sqlite-1.0.3.ebuild b/dev-php/pecl-sqlite/pecl-sqlite-1.0.3.ebuild
new file mode 100644
index 0000000..fd26274
--- /dev/null
+++ b/dev-php/pecl-sqlite/pecl-sqlite-1.0.3.ebuild
@@ -0,0 +1,32 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-php/PECL-sqlite/Attic/PECL-sqlite-1.0.3.ebuild,v 1.7 2006/05/21 01:53:28 chtekk dead $
+
+EAPI=6
+
+PHP_EXT_ZENDEXT="no"
+PHP_EXT_INI="yes"
+PHP_EXT_PECL_PKG="SQLite"
+PHP_EXT_NAME="sqlite"
+USE_PHP="php5-6 php5-5 php5-4"
+
+inherit php-ext-pecl-r3
+
+DEPEND="${DEPEND} !dev-php/sqlite-php"
+
+IUSE=""
+DESCRIPTION="PHP bindings for the SQLite database engine"
+HOMEPAGE="http://pear.php.net/SQLite"
+SLOT="0"
+LICENSE="PHP"
+KEYWORDS="alpha amd64 ~ia64 ppc ~sparc x86"
+
+src_prepare() {
+ local slot
+ for slot in $(php_get_slots); do
+ php_init_slot_env ${slot}
+ epatch "${FILESDIR}"/sqlite-svn.patch
+ done
+
+ php-ext-source-r2_src_prepare
+}
diff --git a/dev-php/pecl-stats/Manifest b/dev-php/pecl-stats/Manifest
new file mode 100644
index 0000000..08a393c
--- /dev/null
+++ b/dev-php/pecl-stats/Manifest
@@ -0,0 +1,3 @@
+AUX stats-php54.diff 223990 SHA256 b9aafe8e8f12bc442540e0f917b98b6c35a7115dbdb5305fd70470133159bcd1 SHA512 ed6bf44fc20cd14c70e3b29bd6f864fc9dddaeef7b090f52edddb155e0844f09f6b6cf02f31bed8d9e1e8689042ee7f763ffd45df89391255ada82a6b523fc8d WHIRLPOOL 7314b415118f1f70734b8d5197a5c823688bf7698694416f7960d2f262585a7d00295a099a9bd01632089269066ddeaefdf10ae19a44c2cbe91c144d1ce6b54d
+DIST stats-1.0.2.tgz 99018 SHA256 465d1bbec43c916ecdc8fc59f0d13e24e7e23f6b76866b7172d25ab6e08f2244 SHA512 bb47a73f46ef49aea2f95ed20e315e7bef2f403ffcab1806bb9e4478abffa2a12f3b378108cb3a6b6a8aa930fd7cb9aa0b184fcec24ae88fb9e9abec67fbc1f0 WHIRLPOOL ddd11ccf68d40e16fd6c74428696f4ccc3c7369969b4ff935b69152968c10f43399a868e5c6593855c618149e2914232c15ed90e7b0ef4b60f24990b5121f593
+EBUILD pecl-stats-1.0.2.ebuild 735 SHA256 e910ba0fda3d93665af415aa5f72e664d8e309438883d82076fffefc11c80f81 SHA512 4319ad92cf925e3cfe5a2df4de8b45b9993aa5e6e0913d2f2141b1fa857c9da94c2ba3d0437af92a30be8ddcdc1b67e3234a96d7e64771b481baa506cbc3d359 WHIRLPOOL c46287889ecf9a19d23bc9e4a998bc11c3318b3cc8335f476bcb798de869260bdda25d8c3d76daae13bcbf2a7c98a7013e7faa2edb5616c5cb83aadf7a88f39b
diff --git a/dev-php/pecl-stats/files/stats-php54.diff b/dev-php/pecl-stats/files/stats-php54.diff
new file mode 100644
index 0000000..2c3d39c
--- /dev/null
+++ b/dev-php/pecl-stats/files/stats-php54.diff
@@ -0,0 +1,7930 @@
+diff -dPNur stats-1.0.2/config.m4 trunk/config.m4
+--- stats-1.0.2/config.m4 2006-05-31 19:24:26.000000000 +0200
++++ trunk/config.m4 2012-10-29 17:22:36.000000000 +0100
+@@ -1,9 +1,9 @@
+-dnl $Id: config.m4,v 1.2 2004/01/09 19:22:36 andrey Exp $
++dnl $Id: config.m4 256977 2008-04-08 16:13:17Z sfox $
+ dnl config.m4 for extension stats
+
+ PHP_ARG_ENABLE(stats, whether to enable stats support,
+ [ --enable-stats Enable statistics support])
+
+ if test "$PHP_STATS" != "no"; then
+- PHP_NEW_EXTENSION(stats, statistics.c com.c dcdflib.c ipmpar.c linpack.c randlib.c, $ext_shared)
++ PHP_NEW_EXTENSION(stats, php_stats.c com.c dcdflib.c ipmpar.c linpack.c randlib.c , $ext_shared)
+ fi
+diff -dPNur stats-1.0.2/config.w32 trunk/config.w32
+--- stats-1.0.2/config.w32 2006-05-31 19:24:26.000000000 +0200
++++ trunk/config.w32 2012-10-29 17:22:36.000000000 +0100
+@@ -1,9 +1,9 @@
+-// $Id: config.w32,v 1.2 2006/05/30 17:53:18 andrey Exp $
++// $Id: config.w32 256977 2008-04-08 16:13:17Z sfox $
+ // vim:ft=javascript
+
+ ARG_ENABLE("stats", "statistics support", "no");
+
+ if (PHP_STATS != "no") {
+- EXTENSION('stats', 'statistics.c com.c dcdflib.c ipmpar.c linpack.c randlib.c fd_e_lgamma_r.c fd_e_log.c fd_k_cos.c fd_k_sin.c fd_w_lgamma.c');
++ EXTENSION('stats', 'php_stats.c com.c dcdflib.c ipmpar.c linpack.c randlib.c fd_e_lgamma_r.c fd_e_log.c fd_k_cos.c fd_k_sin.c fd_w_lgamma.c');
+ }
+
+diff -dPNur stats-1.0.2/package.xml trunk/package.xml
+--- stats-1.0.2/package.xml 1970-01-01 01:00:00.000000000 +0100
++++ trunk/package.xml 2012-10-29 17:22:36.000000000 +0100
+@@ -0,0 +1,104 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<package packagerversion="1.4.8" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
++http://pear.php.net/dtd/tasks-1.0.xsd
++http://pear.php.net/dtd/package-2.0
++http://pear.php.net/dtd/package-2.0.xsd">
++ <name>stats</name>
++ <channel>pecl.php.net</channel>
++ <summary>Extension with routines for statistical computation.</summary>
++ <description>Extension that provides few dozens routines for statistical computation.
++ </description>
++ <lead>
++ <name>Andrey Hristov</name>
++ <user>andrey</user>
++ <email>andrey_php_net</email>
++ <active>yes</active>
++ </lead>
++ <date>2006-05-31</date>
++ <time>18:55:52</time>
++ <version>
++ <release>1.0.2</release>
++ <api>1.0.2</api>
++ </version>
++ <stability>
++ <release>stable</release>
++ <api>stable</api>
++ </stability>
++ <license uri="http://www.php.net/license">PHP License</license>
++ <notes>Added fd_lgamma from FDLibM, so now all functions are also available on Windows.
++ Previously some were disabled because Microsoft does not ship lgamma with their C library.
++ </notes>
++ <contents>
++ <dir name="/">
++ <dir name="tests">
++ <file name="common.php" role="test" />
++ <file name="math_abs_dev.phpt" role="test" />
++ <file name="math_covariance.phpt" role="test" />
++ <file name="math_harmonic_mean.phpt" role="test" />
++ <file name="math_skew_kurtosis.phpt" role="test" />
++ <file name="math_std_dev.phpt" role="test" />
++ </dir> <!-- //tests -->
++ <file name="cdflib.h" role="src" />
++ <file name="com.c" role="src" />
++ <file name="config.m4" role="src" />
++ <file name="config.w32" role="src" />
++ <file name="CREDITS" role="doc" />
++ <file name="dcdflib.c" role="src" />
++ <file name="fd_e_lgamma_r.c" role="src" />
++ <file name="fd_e_log.c" role="src" />
++ <file name="fd_k_cos.c" role="src" />
++ <file name="fd_k_sin.c" role="src" />
++ <file name="fdlibm.h" role="src" />
++ <file name="fd_w_lgamma.c" role="src" />
++ <file name="ipmpar.c" role="src" />
++ <file name="linpack.c" role="src" />
++ <file name="php_stats.h" role="src" />
++ <file name="randlib.c" role="src" />
++ <file name="randlib.h" role="src" />
++ <file name="php_stats.c" role="src" />
++ <file name="TODO" role="doc" />
++ </dir> <!-- / -->
++ </contents>
++ <dependencies>
++ <required>
++ <php>
++ <min>4.0.0</min>
++ </php>
++ <pearinstaller>
++ <min>1.4.0</min>
++ </pearinstaller>
++ </required>
++ </dependencies>
++ <providesextension>stats</providesextension>
++ <extsrcrelease />
++ <changelog>
++ <release>
++ <version>
++ <release>1.0.0</release>
++ <api>1.0.0</api>
++ </version>
++ <stability>
++ <release>stable</release>
++ <api>stable</api>
++ </stability>
++ <date>2005-11-24</date>
++ <license uri="http://www.php.net/license">PHP License</license>
++ <notes>Initial release.
++ </notes>
++ </release>
++ <release>
++ <version>
++ <release>1.0.1</release>
++ <api>1.0.1</api>
++ </version>
++ <stability>
++ <release>stable</release>
++ <api>stable</api>
++ </stability>
++ <date>2005-3-25</date>
++ <license uri="http://www.php.net/license">PHP License</license>
++ <notes>Fixed shared build.
++ </notes>
++ </release>
++ </changelog>
++</package>
+diff -dPNur stats-1.0.2/php_statistics.h trunk/php_statistics.h
+--- stats-1.0.2/php_statistics.h 2006-05-31 19:24:26.000000000 +0200
++++ trunk/php_statistics.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,127 +0,0 @@
+-/*
+- +----------------------------------------------------------------------+
+- | PHP Version 5 |
+- +----------------------------------------------------------------------+
+- | Copyright (c) 1997-2004 The PHP Group |
+- +----------------------------------------------------------------------+
+- | This source file is subject to version 3.0 of the PHP license, |
+- | that is bundled with this package in the file LICENSE, and is |
+- | available through the world-wide-web at the following url: |
+- | http://www.php.net/license/3_0.txt. |
+- | If you did not receive a copy of the PHP license and are unable to |
+- | obtain it through the world-wide-web, please send a note to |
+- | license@php.net so we can mail you a copy immediately. |
+- +----------------------------------------------------------------------+
+- | Author: Andrey Hristov <andrey@php.net> |
+- +----------------------------------------------------------------------+
+-*/
+-
+-/* $Id: php_statistics.h,v 1.5 2005/05/13 12:17:07 andrey Exp $ */
+-
+-#ifndef PHP_STATISTICS_H
+-#define PHP_STATISTICS_H
+-
+-extern zend_module_entry stats_module_entry;
+-#define phpext_stats_ptr &stats_module_entry
+-
+-#ifdef PHP_WIN32
+-#define PHP_STATS_API __declspec(dllexport)
+-#else
+-#define PHP_STATS_API
+-#endif
+-
+-
+-PHP_MINFO_FUNCTION(stats);
+-
+-PHP_FUNCTION(stats_bin_counts);
+-PHP_FUNCTION(stats_cdf_t);
+-PHP_FUNCTION(stats_cdf_normal);
+-PHP_FUNCTION(stats_cdf_gamma);
+-PHP_FUNCTION(stats_cdf_chisquare);
+-PHP_FUNCTION(stats_cdf_beta);
+-PHP_FUNCTION(stats_cdf_binomial);
+-PHP_FUNCTION(stats_cdf_noncentral_chisquare);
+-PHP_FUNCTION(stats_cdf_f);
+-PHP_FUNCTION(stats_cdf_noncentral_f);
+-PHP_FUNCTION(stats_cdf_noncentral_t);
+-PHP_FUNCTION(stats_cdf_negative_binomial);
+-PHP_FUNCTION(stats_cdf_poisson);
+-PHP_FUNCTION(stats_cdf_laplace);
+-PHP_FUNCTION(stats_cdf_cauchy);
+-PHP_FUNCTION(stats_cdf_logistic);
+-PHP_FUNCTION(stats_cdf_weibull);
+-PHP_FUNCTION(stats_cdf_uniform);
+-PHP_FUNCTION(stats_cdf_exponential);
+-PHP_FUNCTION(stats_rand_setall);
+-PHP_FUNCTION(stats_rand_getsd);
+-PHP_FUNCTION(stats_rand_gen_iuniform);
+-PHP_FUNCTION(stats_rand_gen_funiform);
+-PHP_FUNCTION(stats_rand_ignlgi);
+-PHP_FUNCTION(stats_rand_ranf);
+-PHP_FUNCTION(stats_rand_gen_beta);
+-PHP_FUNCTION(stats_rand_gen_chisquare);
+-PHP_FUNCTION(stats_rand_gen_exponential);
+-PHP_FUNCTION(stats_rand_gen_f);
+-PHP_FUNCTION(stats_rand_gen_gamma);
+-PHP_FUNCTION(stats_rand_gen_noncentral_chisquare);
+-PHP_FUNCTION(stats_rand_gen_noncenral_f);
+-PHP_FUNCTION(stats_rand_gen_normal);
+-PHP_FUNCTION(stats_rand_phrase_to_seeds);
+-PHP_FUNCTION(stats_rand_ibinomial);
+-PHP_FUNCTION(stats_rand_ibinomial_negative);
+-PHP_FUNCTION(stats_rand_gen_ipoisson);
+-PHP_FUNCTION(stats_rand_gen_noncentral_t);
+-PHP_FUNCTION(stats_rand_gen_t);
+-PHP_FUNCTION(stats_dens_normal);
+-PHP_FUNCTION(stats_dens_cauchy);
+-PHP_FUNCTION(stats_dens_laplace);
+-PHP_FUNCTION(stats_dens_logistic);
+-PHP_FUNCTION(stats_dens_beta);
+-PHP_FUNCTION(stats_dens_weibull);
+-PHP_FUNCTION(stats_dens_uniform);
+-PHP_FUNCTION(stats_dens_chisquare);
+-PHP_FUNCTION(stats_dens_t);
+-PHP_FUNCTION(stats_dens_gamma);
+-PHP_FUNCTION(stats_dens_exponential);
+-PHP_FUNCTION(stats_dens_f);
+-PHP_FUNCTION(stats_dens_pmf_binomial);
+-PHP_FUNCTION(stats_dens_pmf_poisson);
+-PHP_FUNCTION(stats_dens_pmf_negative_binomial);
+-PHP_FUNCTION(stats_dens_pmf_hypergeometric);
+-PHP_FUNCTION(stats_stat_powersum);
+-PHP_FUNCTION(stats_stat_innerproduct);
+-PHP_FUNCTION(stats_stat_independent_t);
+-PHP_FUNCTION(stats_stat_paired_t);
+-PHP_FUNCTION(stats_stat_percentile);
+-PHP_FUNCTION(stats_stat_correlation);
+-PHP_FUNCTION(stats_stat_binomial_coef);
+-PHP_FUNCTION(stats_stat_factorial);
+-PHP_FUNCTION(stats_absolute_deviation);
+-PHP_FUNCTION(stats_standard_deviation);
+-PHP_FUNCTION(stats_variance);
+-PHP_FUNCTION(stats_harmonic_mean);
+-PHP_FUNCTION(stats_skew);
+-PHP_FUNCTION(stats_kurtosis);
+-PHP_FUNCTION(stats_covariance);
+-
+-
+-#ifdef ZTS
+-#define STATS_D zend_stats_globals *stats_globals
+-#define STATS_G(v) (stats_globals->v)
+-#define STATS_FETCH() zend_stats_globals *stats_globals = ts_resource(stats_globals_id)
+-#else
+-#define STATS_D
+-#define STATS_G(v) (stats_globals.v)
+-#define STATS_FETCH()
+-#endif
+-
+-#endif /* PHP_STATISTICS_H */
+-
+-
+-/*
+- * Local variables:
+- * tab-width: 4
+- * c-basic-offset: 4
+- * indent-tabs-mode: t
+- * End:
+- */
+diff -dPNur stats-1.0.2/php_stats.c trunk/php_stats.c
+--- stats-1.0.2/php_stats.c 1970-01-01 01:00:00.000000000 +0100
++++ trunk/php_stats.c 2012-10-29 17:22:36.000000000 +0100
+@@ -0,0 +1,3729 @@
++/*
++ +----------------------------------------------------------------------+
++ | PHP Version 5 |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 1997-2004 The PHP Group |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 3.0 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available through the world-wide-web at the following url: |
++ | http://www.php.net/license/3_0.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Andrey Hristov <andrey@php.net> |
++ +----------------------------------------------------------------------+
++*/
++
++/* $Id: php_stats.c 313529 2011-07-21 12:14:10Z derick $ */
++
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "php.h"
++#include "php_stats.h"
++#include "ext/standard/info.h"
++#include "ext/standard/head.h"
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <math.h>
++#include "randlib.h"
++#include "cdflib.h"
++
++#define STATS_PI 3.14159265358979323846
++
++
++#ifdef PHP_WIN32
++extern double fd_lgamma(double x);
++#define lgamma fd_lgamma
++#endif
++
++static double logistic_quantile(double p);
++static double logistic_cdf(double x);
++static double cauchy_quantile(double p);
++static double cauchy_cdf(double x);
++static double laplace_quantile(double p);
++static double laplace_cdf(double x);
++static double exponential_quantile(double p);
++static double exponential_cdf(double x);
++static double binom(double x, double n);
++
++zend_function_entry statistics_functions[] = {
++ PHP_FE(stats_cdf_t, NULL)
++ PHP_FE(stats_cdf_normal, NULL)
++ PHP_FE(stats_cdf_gamma, NULL)
++ PHP_FE(stats_cdf_chisquare, NULL)
++ PHP_FE(stats_cdf_beta, NULL)
++ PHP_FE(stats_cdf_binomial, NULL)
++ PHP_FE(stats_cdf_noncentral_chisquare,NULL)
++ PHP_FE(stats_cdf_f, NULL)
++ PHP_FE(stats_cdf_noncentral_f, NULL)
++ PHP_FE(stats_cdf_noncentral_t, NULL)
++ PHP_FE(stats_cdf_negative_binomial, NULL)
++ PHP_FE(stats_cdf_poisson, NULL)
++ PHP_FE(stats_cdf_laplace, NULL)
++ PHP_FE(stats_cdf_cauchy, NULL)
++ PHP_FE(stats_cdf_logistic, NULL)
++ PHP_FE(stats_cdf_weibull, NULL)
++ PHP_FE(stats_cdf_uniform, NULL)
++ PHP_FE(stats_cdf_exponential, NULL)
++ PHP_FE(stats_rand_setall, NULL)
++ PHP_FE(stats_rand_getsd, NULL)
++ PHP_FE(stats_rand_gen_iuniform, NULL)
++ PHP_FE(stats_rand_gen_funiform, NULL)
++ PHP_FE(stats_rand_ignlgi, NULL)
++ PHP_FE(stats_rand_ranf, NULL)
++ PHP_FE(stats_rand_gen_beta, NULL)
++ PHP_FE(stats_rand_gen_chisquare, NULL)
++ PHP_FE(stats_rand_gen_exponential, NULL)
++ PHP_FE(stats_rand_gen_f, NULL)
++ PHP_FE(stats_rand_gen_gamma, NULL)
++ PHP_FE(stats_rand_gen_noncentral_chisquare,NULL)
++ PHP_FE(stats_rand_gen_noncenral_f, NULL)
++ PHP_FE(stats_rand_gen_normal, NULL)
++ PHP_FE(stats_rand_phrase_to_seeds, NULL)
++ PHP_FE(stats_rand_ibinomial, NULL)
++ PHP_FE(stats_rand_ibinomial_negative,NULL)
++ PHP_FE(stats_rand_gen_ipoisson, NULL)
++ PHP_FE(stats_rand_gen_noncentral_t, NULL)
++ PHP_FE(stats_rand_gen_t, NULL)
++ PHP_FE(stats_dens_normal, NULL)
++ PHP_FE(stats_dens_cauchy, NULL)
++ PHP_FE(stats_dens_laplace, NULL)
++ PHP_FE(stats_dens_logistic, NULL)
++ PHP_FE(stats_dens_beta, NULL)
++ PHP_FE(stats_dens_weibull, NULL)
++ PHP_FE(stats_dens_uniform, NULL)
++ PHP_FE(stats_dens_chisquare, NULL)
++ PHP_FE(stats_dens_t, NULL)
++ PHP_FE(stats_dens_gamma, NULL)
++ PHP_FE(stats_dens_exponential, NULL)
++ PHP_FE(stats_dens_f, NULL)
++ PHP_FE(stats_dens_pmf_binomial, NULL)
++ PHP_FE(stats_dens_pmf_poisson, NULL)
++ PHP_FE(stats_dens_pmf_negative_binomial,NULL)
++ PHP_FE(stats_dens_pmf_hypergeometric, NULL)
++ PHP_FE(stats_stat_powersum, NULL)
++ PHP_FE(stats_stat_innerproduct, NULL)
++ PHP_FE(stats_stat_independent_t, NULL)
++ PHP_FE(stats_stat_paired_t, NULL)
++ PHP_FE(stats_stat_percentile, NULL)
++ PHP_FE(stats_stat_correlation, NULL)
++ PHP_FE(stats_stat_binomial_coef, NULL)
++ PHP_FE(stats_stat_factorial, NULL)
++ PHP_FE(stats_standard_deviation, NULL)
++ PHP_FE(stats_absolute_deviation, NULL)
++ PHP_FE(stats_variance, NULL)
++ PHP_FE(stats_harmonic_mean, NULL)
++ PHP_FE(stats_skew, NULL)
++ PHP_FE(stats_kurtosis, NULL)
++ PHP_FE(stats_covariance, NULL)
++ {NULL, NULL, NULL}
++};
++
++zend_module_entry stats_module_entry = {
++ STANDARD_MODULE_HEADER,
++ "stats",
++ statistics_functions,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ PHP_MINFO(stats),
++ PHP_STATS_VERSION,
++ STANDARD_MODULE_PROPERTIES,
++};
++
++#ifdef COMPILE_DL_STATS
++ZEND_GET_MODULE(stats)
++#endif
++
++
++PHP_MINFO_FUNCTION(stats)
++{
++ php_info_print_table_start();
++ php_info_print_table_header(2, "Statistics Support", "enabled");
++ php_info_print_table_row(2, "Version", PHP_STATS_VERSION);
++ php_info_print_table_end();
++}
++
++
++
++/* Numbers are always smaller than strings int this function as it
++ * anyway doesn't make much sense to compare two different data types.
++ * This keeps it consistant and simple.
++ *
++ * This is not correct any more, depends on what compare_func is set to.
++ */
++static int stats_array_data_compare(const void *a, const void *b TSRMLS_DC)
++{
++ Bucket *f;
++ Bucket *s;
++ zval result;
++ zval *first;
++ zval *second;
++
++ f = *((Bucket **) a);
++ s = *((Bucket **) b);
++
++ first = *((zval **) f->pData);
++ second = *((zval **) s->pData);
++
++ if (numeric_compare_function(&result, first, second TSRMLS_CC) == FAILURE) {
++ return 0;
++ }
++
++ if (Z_TYPE(result) == IS_DOUBLE) {
++ if (Z_DVAL(result) < 0) {
++ return -1;
++ } else if (Z_DVAL(result) > 0) {
++ return 1;
++ } else {
++ return 0;
++ }
++ }
++
++ convert_to_long(&result);
++
++ if (Z_LVAL(result) < 0) {
++ return -1;
++ } else if (Z_LVAL(result) > 0) {
++ return 1;
++ }
++
++ return 0;
++}
++
++
++
++/**************************************/
++/* Cumulative Distributions Functions */
++/**************************************/
++
++/******************************************************
++ Cumulative Distribution Function
++ T distribution
++
++ Function
++
++
++ Calculates any one parameter of the t distribution given
++ values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which argument
++ values is to be calculated from the others.
++ Legal range: 1..3
++ iwhich = 1 : Calculate P and Q from T and DF
++ iwhich = 2 : Calculate T from P,Q and DF
++ iwhich = 3 : Calculate DF from P,Q and T
++
++ P <--> The integral from -infinity to t of the t-density.
++ Input range: (0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ T <--> Upper limit of integration of the t-density.
++ Input range: ( -infinity, +infinity).
++ Search range: [ -1E100, 1E100 ]
++
++ DF <--> Degrees of freedom of the t-distribution.
++ Input range: (0 , +infinity).
++ Search range: [1e-100, 1E10]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.5.27 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce the computation
++ of the cumulative distribution function to that of an incomplete
++ beta.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++******************************************************/
++
++/* {{{ proto float stats_cdf_t(float par1, float par2, int which)
++ Calculates any one parameter of the T distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_t)
++{
++ double arg1;
++ double arg2;
++ double df;
++ double bound;
++ double p;
++ double q;
++ double t;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddl", &arg1, &arg2, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 3) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 3 ) {
++ df = arg2;
++ } else {
++ t = arg2;
++ }
++ if (which == 1) {
++ t = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdft((int *)&which, &p, &q, &t, &df, &status, &bound);
++
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(t);
++ case 3: RETURN_DOUBLE(df);
++ }
++ RETURN_FALSE; /* should never be reached */
++}
++/* }}} */
++
++/*********************************************************************
++ Cumulative Distribution Function NORmal distribution
++
++ Calculates any one parameter of the normal
++ distribution given values for the others.
++
++
++ Arguments
++
++
++ WHICH --> Integer indicating which of the next parameter
++ values is to be calculated using values of the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from X,MEAN and SD
++ iwhich = 2 : Calculate X from P,Q,MEAN and SD
++ iwhich = 3 : Calculate MEAN from P,Q,X and SD
++ iwhich = 4 : Calculate SD from P,Q,X and MEAN
++
++ P <--> The integral from -infinity to X of the normal density.
++ Input range: (0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ X < --> Upper limit of integration of the normal-density.
++ Input range: ( -infinity, +infinity)
++
++ MEAN <--> The mean of the normal density.
++ Input range: (-infinity, +infinity)
++
++ SD <--> Standard Deviation of the normal density.
++ Input range: (0, +infinity).
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ A slightly modified version of ANORM from
++
++ Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN
++ Package of Special Function Routines and Test Drivers"
++ acm Transactions on Mathematical Software. 19, 22-32.
++
++ is used to calulate the cumulative standard normal distribution.
++
++ The rational functions from pages 90-95 of Kennedy and Gentle,
++ Statistical Computing, Marcel Dekker, NY, 1980 are used as
++ starting values to Newton's Iterations which compute the inverse
++ standard normal. Therefore no searches are necessary for any
++ parameter.
++
++ For X < -15, the asymptotic expansion for the normal is used as
++ the starting value in finding the inverse standard normal.
++ This is formula 26.2.12 of Abramowitz and Stegun.
++
++ Note
++
++ The normal density is proportional to
++ exp( - 0.5 * (( X - MEAN)/SD)**2)
++***********************************************************************/
++
++/* {{{ proto float stats_stat_gennch(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the normal distribution given values for thee others. */
++PHP_FUNCTION(stats_cdf_normal)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double sd;
++ double bound;
++ double p;
++ double q;
++ double x;
++ double mean;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ sd = arg3;
++ } else {
++ mean = arg3;
++ }
++
++ if (which < 3) {
++ mean = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfnor((int *)&which, &p, &q, &x, &mean, &sd, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(mean);
++ case 4: RETURN_DOUBLE(sd);
++ }
++ RETURN_FALSE; /* should never be reached */
++}
++/* }}} */
++
++
++/*********************************************************************
++ Cumulative Distribution Function
++ GAMma Distribution
++
++
++ Function
++
++
++ Calculates any one parameter of the gamma
++ distribution given values for the others.
++
++
++ Arguments
++
++
++ WHICH --> Integer indicating which of the next four argument
++ values is to be calculated from the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from X,SHAPE and SCALE
++ iwhich = 2 : Calculate X from P,Q,SHAPE and SCALE
++ iwhich = 3 : Calculate SHAPE from P,Q,X and SCALE
++ iwhich = 4 : Calculate SCALE from P,Q,X and SHAPE
++
++ P <--> The integral from 0 to X of the gamma density.
++ Input range: [0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ X <--> The upper limit of integration of the gamma density.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ SHAPE <--> The shape parameter of the gamma density.
++ Input range: (0, +infinity).
++ Search range: [1E-100,1E100]
++
++ SCALE <--> The scale parameter of the gamma density.
++ Input range: (0, +infinity).
++ Search range: (1E-100,1E100]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++ 10 if the gamma or inverse gamma routine cannot
++ compute the answer. Usually happens only for
++ X and SHAPE very large (gt 1E10 or more)
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++
++ Method
++
++
++ Cumulative distribution function (P) is calculated directly by
++ the code associated with:
++
++ DiDinato, A. R. and Morris, A. H. Computation of the incomplete
++ gamma function ratios and their inverse. ACM Trans. Math.
++ Softw. 12 (1986), 377-393.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++
++ Note
++
++
++
++ The gamma density is proportional to
++ T**(SHAPE - 1) * EXP(- SCALE * T)
++**************************************************************************/
++/* {{{ proto float stats_cdf_gamma(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the gamma distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_gamma)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double bound;
++ double p;
++ double q;
++ double x;
++ double shape;
++ double scale;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ scale = arg3;
++ } else {
++ shape = arg3;
++ }
++
++ if (which < 3) {
++ shape = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfgam((int *)&which, &p, &q, &x, &shape, &scale, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(shape);
++ case 4: RETURN_DOUBLE(scale);
++ }
++ RETURN_FALSE; /* should never be reached */
++}
++/* }}} */
++
++/*****************************************************************
++ Cumulative Distribution Function
++ CHI-Square distribution
++
++ Function
++
++ Calculates any one parameter of the chi-square
++ distribution given values for the others.
++
++ Arguments
++
++
++ WHICH --> Integer indicating which of the next three argument
++ values is to be calculated from the others.
++ Legal range: 1..3
++ iwhich = 1 : Calculate P and Q from X and DF
++ iwhich = 2 : Calculate X from P,Q and DF
++ iwhich = 3 : Calculate DF from P,Q and X
++
++ P <--> The integral from 0 to X of the chi-square
++ distribution.
++ Input range: [0, 1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ X <--> Upper limit of integration of the non-central
++ chi-square distribution.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ DF <--> Degrees of freedom of the
++ chi-square distribution.
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++ 10 indicates error returned from cumgam. See
++ references in cdfgam
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++
++ Method
++
++
++ Formula 26.4.19 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce the chisqure
++ distribution to the incomplete distribution.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++*****************************************************************/
++/* {{{ proto float stats_cdf_chisquare(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the chi-square distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_chisquare)
++{
++ double arg1;
++ double arg2;
++ double bound;
++ double p;
++ double q;
++ double x;
++ double df;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddl", &arg1, &arg2, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 3) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 3 ) {
++ df = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfchi((int *)&which, &p, &q, &x, &df, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(df);
++ }
++ RETURN_FALSE; /* should never be here */
++}
++/* }}} */
++
++/*******************************************************************
++ Cumulative Distribution Function
++ BETa Distribution
++
++ Function
++
++ Calculates any one parameter of the beta distribution given
++ values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next four argument
++ values is to be calculated from the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from X,Y,A and B
++ iwhich = 2 : Calculate X and Y from P,Q,A and B
++ iwhich = 3 : Calculate A from P,Q,X,Y and B
++ iwhich = 4 : Calculate B from P,Q,X,Y and A
++
++ P <--> The integral from 0 to X of the chi-square
++ distribution.
++ Input range: [0, 1].
++
++ Q <--> 1-P.
++ Input range: [0, 1].
++ P + Q = 1.0.
++
++ X <--> Upper limit of integration of beta density.
++ Input range: [0,1].
++ Search range: [0,1]
++
++ Y <--> 1-X.
++ Input range: [0,1].
++ Search range: [0,1]
++ X + Y = 1.0.
++
++ A <--> The first parameter of the beta density.
++ Input range: (0, +infinity).
++ Search range: [1D-100,1D100]
++
++ B <--> The second parameter of the beta density.
++ Input range: (0, +infinity).
++ Search range: [1D-100,1D100]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++ 4 if X + Y .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Cumulative distribution function (P) is calculated directly by
++ code associated with the following reference.
++
++ DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant
++ Digit Computation of the Incomplete Beta Function Ratios. ACM
++ Trans. Math. Softw. 18 (1993), 360-373.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++ Note
++
++ The beta density is proportional to
++ t^(A-1) * (1-t)^(B-1)
++
++*******************************************************************/
++
++/* {{{ proto float stats_cdf_beta(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the beta distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_beta)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double x;
++ double bound;
++ double y;
++ double a;
++ double b;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++
++ if (which < 4) {
++ b = arg3;
++ } else {
++ a = arg3;
++ }
++
++ if (which < 3) {
++ a = arg2;
++ } else {
++ x = arg2;
++ y = 1.0 - x;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ y = 1.0 - x;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfbet((int *)&which, &p, &q, &x, &y, &a, &b, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(a);
++ case 4: RETURN_DOUBLE(b);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/*********************************************************************
++ Cumulative Distribution Function
++ BINomial distribution
++
++ Function
++
++ Calculates any one parameter of the binomial
++ distribution given values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next four argument
++ values is to be calculated from the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
++ iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
++ iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
++ iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
++
++ P <--> The cumulation from 0 to S of the binomial distribution.
++ (Probablility of S or fewer successes in XN trials each
++ with probability of success PR.)
++ Input range: [0,1].
++
++ Q <--> 1-P.
++ Input range: [0, 1].
++ P + Q = 1.0.
++
++ S <--> The number of successes observed.
++ Input range: [0, XN]
++ Search range: [0, XN]
++
++ XN <--> The number of binomial trials.
++ Input range: (0, +infinity).
++ Search range: [1E-100, 1E100]
++
++ PR <--> The probability of success in each binomial trial.
++ Input range: [0,1].
++ Search range: [0,1]
++
++ OMPR <--> 1-PR
++ Input range: [0,1].
++ Search range: [0,1]
++ PR + OMPR = 1.0
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++ 4 if PR + OMPR .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.5.24 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce the binomial
++ distribution to the cumulative incomplete beta distribution.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++*********************************************************************/
++
++/* {{{ proto float stats_cdf_binomial(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the binomial distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_binomial)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double xn;
++ double bound;
++ double sn;
++ double pr;
++ double ompr;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++
++ if (which < 4) {
++ pr = arg3;
++ ompr = 1.0 - pr;
++ } else {
++ xn = arg3;
++ }
++
++ if (which < 3) {
++ xn = arg2;
++ } else {
++ sn = arg2;
++ }
++
++ if (which == 1) {
++ sn = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfbin((int *)&which, &p, &q, &sn, &xn, &pr, &ompr, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in binomialcdf");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(sn);
++ case 3: RETURN_DOUBLE(xn);
++ case 4: RETURN_DOUBLE(pr);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/*****************************************************************
++ Cumulative Distribution Function
++ Non-central Chi-Square
++
++ Function
++
++ Calculates any one parameter of the non-central chi-square
++ distribution given values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next three argument
++ values is to be calculated from the others.
++ Input range: 1..4
++ iwhich = 1 : Calculate P and Q from X and DF
++ iwhich = 2 : Calculate X from P,DF and PNONC
++ iwhich = 3 : Calculate DF from P,X and PNONC
++ iwhich = 3 : Calculate PNONC from P,X and DF
++
++ P <--> The integral from 0 to X of the non-central chi-square
++ distribution.
++ Input range: [0, 1-1E-16).
++
++ Q <--> 1-P.
++ Q is not used by this subroutine and is only included
++ for similarity with other cdf* routines.
++
++ X <--> Upper limit of integration of the non-central
++ chi-square distribution.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ DF <--> Degrees of freedom of the non-central
++ chi-square distribution.
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ PNONC <--> Non-centrality parameter of the non-central
++ chi-square distribution.
++ Input range: [0, +infinity).
++ Search range: [0,1E4]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.4.25 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to compute the cumulative
++ distribution function.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++ WARNING
++
++ The computation time required for this routine is proportional
++ to the noncentrality parameter (PNONC). Very large values of
++ this parameter can consume immense computer resources. This is
++ why the search range is bounded by 10,000.
++
++*****************************************************************/
++
++/* {{{ proto float stats_cdf_noncentral_chisquare(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the non-central chi-square distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_noncentral_chisquare)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double bound;
++ double q;
++ double x;
++ double df;
++ double pnonc;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ pnonc = arg3;
++ } else {
++ df = arg3;
++ }
++
++ if (which < 3) {
++ df = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfchn((int *)&which, &p, &q, &x, &df, &pnonc, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdfchn");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(df);
++ case 4: RETURN_DOUBLE(pnonc);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/**************************************************************
++ Cumulative Distribution Function F distribution
++
++ Function
++
++ Calculates any one parameter of the F distribution
++ given values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next four argument
++ values is to be calculated from the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from F,DFN and DFD
++ iwhich = 2 : Calculate F from P,Q,DFN and DFD
++ iwhich = 3 : Calculate DFN from P,Q,F and DFD
++ iwhich = 4 : Calculate DFD from P,Q,F and DFN
++
++ P <--> The integral from 0 to F of the f-density.
++ Input range: [0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ F <--> Upper limit of integration of the f-density.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ DFN < --> Degrees of freedom of the numerator sum of squares.
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ DFD < --> Degrees of freedom of the denominator sum of squares.
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.6.2 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce the computation
++ of the cumulative distribution function for the F variate to
++ that of an incomplete beta.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++ WARNING
++
++ The value of the cumulative F distribution is not necessarily
++ monotone in either degrees of freedom. There thus may be two
++ values that provide a given CDF value. This routine assumes
++ monotonicity and will find an arbitrary one of the two values.
++
++**********************************************************************/
++/* {{{ proto float stats_cdf_f(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the F distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_f)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double bound;
++ double dfn;
++ double q;
++ double f;
++ double dfd;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++ if (which < 4) {
++ dfd = arg3;
++ } else {
++ dfn = arg3;
++ }
++ if (which < 3) {
++ dfn = arg2;
++ } else {
++ f = arg2;
++ }
++ if (which == 1) {
++ f = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdff((int *)&which, &p, &q, &f, &dfn, &dfd, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdff");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(f);
++ case 3: RETURN_DOUBLE(dfn);
++ case 4: RETURN_DOUBLE(dfd);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/***********************************************************************
++ Cumulative Distribution Function
++ Non-central F distribution
++
++ Function
++
++ Calculates any one parameter of the Non-central F
++ distribution given values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next five argument
++ values is to be calculated from the others.
++ Legal range: 1..5
++ iwhich = 1 : Calculate P and Q from F,DFN,DFD and PNONC
++ iwhich = 2 : Calculate F from P,Q,DFN,DFD and PNONC
++ iwhich = 3 : Calculate DFN from P,Q,F,DFD and PNONC
++ iwhich = 4 : Calculate DFD from P,Q,F,DFN and PNONC
++ iwhich = 5 : Calculate PNONC from P,Q,F,DFN and DFD
++
++ P <--> The integral from 0 to F of the non-central f-density.
++ Input range: [0,1-1E-16).
++
++ Q <--> 1-P.
++ Q is not used by this subroutine and is only included
++ for similarity with other cdf* routines.
++
++ F <--> Upper limit of integration of the non-central f-density.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ DFN < --> Degrees of freedom of the numerator sum of squares.
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ DFD < --> Degrees of freedom of the denominator sum of squares.
++ Must be in range: (0, +infinity).
++ Input range: (0, +infinity).
++ Search range: [ 1E-100, 1E100]
++
++ PNONC <-> The non-centrality parameter
++ Input range: [0,infinity)
++ Search range: [0,1E4]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.6.20 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to compute the cumulative
++ distribution function.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++ WARNING
++
++ The computation time required for this routine is proportional
++ to the noncentrality parameter (PNONC). Very large values of
++ this parameter can consume immense computer resources. This is
++ why the search range is bounded by 10,000.
++
++ WARNING
++
++ The value of the cumulative noncentral F distribution is not
++ necessarily monotone in either degrees of freedom. There thus
++ may be two values that provide a given CDF value. This routine
++ assumes monotonicity and will find an arbitrary one of the two
++ values.
++
++***********************************************************************/
++
++/* {{{ proto float stats_cdf_noncentral_f(float par1, float par2, float par3, float par4, int which)
++ Calculates any one parameter of the Non-central F distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_noncentral_f)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double arg4;
++ double p;
++ double q;
++ double f;
++ double dfn;
++ double dfd;
++ double pnonc;
++ double bound;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddddl", &arg1, &arg2, &arg3, &arg4, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 5) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fifth parameter should be in the 1..5 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 5) {
++ pnonc = arg4;
++ } else {
++ dfd = arg4;
++ }
++
++ if (which < 4) {
++ dfd = arg3;
++ } else {
++ dfn = arg3;
++ }
++
++ if (which < 3) {
++ dfn = arg2;
++ } else {
++ f = arg2;
++ }
++
++ if (which == 1) {
++ f = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdffnc((int *)&which, &p, &q, &f, &dfn, &dfd, &pnonc, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdffnc");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(f);
++ case 3: RETURN_DOUBLE(dfn);
++ case 4: RETURN_DOUBLE(dfd);
++ case 5: RETURN_DOUBLE(pnonc);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/************************************************************************
++ Cumulative Distribution Function Non-Central T distribution
++
++ Function
++
++ Calculates any one parameter of the noncentral t distribution give
++ values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which argument
++ values is to be calculated from the others.
++ Legal range: 1..3
++ iwhich = 1 : Calculate P and Q from T,DF,PNONC
++ iwhich = 2 : Calculate T from P,Q,DF,PNONC
++ iwhich = 3 : Calculate DF from P,Q,T
++ iwhich = 4 : Calculate PNONC from P,Q,DF,T
++
++ P <--> The integral from -infinity to t of the noncentral t-den
++ Input range: (0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ T <--> Upper limit of integration of the noncentral t-density.
++ Input range: ( -infinity, +infinity).
++ Search range: [ -1E100, 1E100 ]
++
++ DF <--> Degrees of freedom of the noncentral t-distribution.
++ Input range: (0 , +infinity).
++ Search range: [1e-100, 1E10]
++
++ PNONC <--> Noncentrality parameter of the noncentral t-distributio
++ Input range: [-infinity , +infinity).
++ Search range: [-1e4, 1E4]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Upper tail of the cumulative noncentral t is calculated usin
++ formulae from page 532 of Johnson, Kotz, Balakrishnan, Coninuou
++ Univariate Distributions, Vol 2, 2nd Edition. Wiley (1995)
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++************************************************************************/
++
++/* {{{ proto float stats_stat_noncentral_t(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the noncentral t distribution give values for the others. */
++PHP_FUNCTION(stats_cdf_noncentral_t)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double pnonc;
++ double bound;
++ double p;
++ double q;
++ double t;
++ double df;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ pnonc = arg3;
++ } else {
++ df = arg3;
++ }
++ if (which < 3) {
++ df = arg2;
++ } else {
++ t = arg2;
++ }
++
++ if (which == 1) {
++ t = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdftnc((int *)&which, &p, &q, &t, &df, &pnonc, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(t);
++ case 3: RETURN_DOUBLE(df);
++ case 4: RETURN_DOUBLE(pnonc);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/************************************************************************
++ Cumulative Distribution Function Negative BiNomial distribution
++
++ Function
++
++ Calculates any one parameter of the negative binomial
++ distribution given values for the others.
++
++ The cumulative negative binomial distribution returns the
++ probability that there will be F or fewer failures before the
++ XNth success in binomial trials each of which has probability of
++ success PR.
++
++ The individual term of the negative binomial is the probability of
++ S failures before XN successes and is
++ Choose( S, XN+S-1 ) * PR^(XN) * (1-PR)^S
++
++ Arguments
++
++ WHICH --> Integer indicating which of the next four argument
++ values is to be calculated from the others.
++ Legal range: 1..4
++ iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
++ iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
++ iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
++ iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
++
++ P <--> The cumulation from 0 to S of the negative
++ binomial distribution.
++ Input range: [0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ S <--> The upper limit of cumulation of the binomial distribution.
++ There are F or fewer failures before the XNth success.
++ Input range: [0, +infinity).
++ Search range: [0, 1E100]
++
++ XN <--> The number of successes.
++ Input range: [0, +infinity).
++ Search range: [0, 1E100]
++
++ PR <--> The probability of success in each binomial trial.
++ Input range: [0,1].
++ Search range: [0,1].
++
++ OMPR <--> 1-PR
++ Input range: [0,1].
++ Search range: [0,1]
++ PR + OMPR = 1.0
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++ 4 if PR + OMPR .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.5.26 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce calculation of
++ the cumulative distribution function to that of an incomplete
++ beta.
++
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++************************************************************************/
++
++/* {{{ proto float stats_cdf_negative_binomial(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the negative binomial distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_negative_binomial)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double bound;
++ double sn;
++ double xn;
++ double pr;
++ double ompr;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ pr = arg3;
++ ompr = 1.0 - pr;
++ } else {
++ xn = arg3;
++ }
++
++ if (which < 3) {
++ xn = arg2;
++ } else {
++ sn = arg2;
++ }
++
++ if (which == 1) {
++ sn = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfnbn((int *)&which, &p, &q, &sn, &xn, &pr, &ompr, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdfnbn");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(sn);
++ case 3: RETURN_DOUBLE(xn);
++ case 4: RETURN_DOUBLE(pr);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/**********************************************************************
++ Cumulative Distribution Function POIsson distribution
++
++ Function
++
++ Calculates any one parameter of the Poisson
++ distribution given values for the others.
++
++ Arguments
++
++ WHICH --> Integer indicating which argument
++ value is to be calculated from the others.
++ Legal range: 1..3
++ iwhich = 1 : Calculate P and Q from S and XLAM
++ iwhich = 2 : Calculate A from P,Q and XLAM
++ iwhich = 3 : Calculate XLAM from P,Q and S
++
++ P <--> The cumulation from 0 to S of the poisson density.
++ Input range: [0,1].
++
++ Q <--> 1-P.
++ Input range: (0, 1].
++ P + Q = 1.0.
++
++ S <--> Upper limit of cumulation of the Poisson.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ XLAM <--> Mean of the Poisson distribution.
++ Input range: [0, +infinity).
++ Search range: [0,1E100]
++
++ STATUS <-- 0 if calculation completed correctly
++ -I if input parameter number I is out of range
++ 1 if answer appears to be lower than lowest
++ search bound
++ 2 if answer appears to be higher than greatest
++ search bound
++ 3 if P + Q .ne. 1
++
++ BOUND <-- Undefined if STATUS is 0
++
++ Bound exceeded by parameter number I if STATUS
++ is negative.
++
++ Lower search bound if STATUS is 1.
++
++ Upper search bound if STATUS is 2.
++
++ Method
++
++ Formula 26.4.21 of Abramowitz and Stegun, Handbook of
++ Mathematical Functions (1966) is used to reduce the computation
++ of the cumulative distribution function to that of computing a
++ chi-square, hence an incomplete gamma function.
++
++ Cumulative distribution function (P) is calculated directly.
++ Computation of other parameters involve a seach for a value that
++ produces the desired value of P. The search relies on the
++ monotinicity of P with the other parameter.
++
++**********************************************************************/
++
++/* {{{ proto float stats_cdf_poisson(float par1, float par2, float par3, int which)
++ Calculates any one parameter of the Poisson distribution given values for the others. */
++PHP_FUNCTION(stats_cdf_poisson)
++{
++ double arg1;
++ double arg2;
++ double p;
++ double q;
++ double x;
++ double xlam;
++ double bound;
++ long which;
++ int status = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddl", &arg1, &arg2, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 3) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 3 ) {
++ xlam = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ cdfpoi((int *)&which, &p, &q, &x, &xlam, &status, &bound);
++ if (status != 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
++ RETURN_FALSE;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(xlam);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++
++static double laplace_quantile(double p)
++{
++ if (p <= 0.5) {
++ return log(2.0*p);
++ } else {
++ return (-log(2.0*(1.0-p)));
++ }
++}
++
++static double laplace_cdf(double x)
++{
++ if (x <= 0) {
++ return (0.5*exp(x));
++ } else {
++ return (1.0 - 0.5*exp(-x));
++ }
++}
++
++
++/* {{{ proto float stats_cdf_laplace(float par1, float par2, float par3, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_laplace)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double x;
++ double t;
++ double mean;
++ double sd;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ sd = arg3;
++ } else {
++ mean = arg3;
++ }
++
++ if (which < 3) {
++ mean = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ if (which == 1) {
++ t = (x - mean) / sd;
++ p = laplace_cdf(t);
++ } else {
++ t = laplace_quantile(p);
++ }
++
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(mean + (sd * t));
++ case 3: RETURN_DOUBLE(x - (sd * t));
++ case 4: RETURN_DOUBLE((x - mean) / t);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++static double cauchy_quantile(double p)
++{
++ return (tan(STATS_PI*(p-0.5)));
++}
++
++static double cauchy_cdf (double x)
++{
++ return (0.5+(atan(x)/STATS_PI));
++}
++
++/* {{{ proto float stats_cdf_cauchy(float par1, float par2, float par3, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_cauchy)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double x;
++ double t;
++ double mean;
++ double sd;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ sd = arg3;
++ } else {
++ mean = arg3;
++ }
++
++ if (which < 3) {
++ mean = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ if (which == 1) {
++ t = (x - mean) / sd;
++ p = cauchy_cdf(t);
++ } else {
++ t = cauchy_quantile(p);
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(mean + (sd * t));
++ case 3: RETURN_DOUBLE(x - (sd * t));
++ case 4: RETURN_DOUBLE((x - mean) / t);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++static double logistic_cdf(double x)
++{
++ return (1.0/(1.0+exp(-x)));
++}
++
++static double logistic_quantile (double p)
++{
++ return (log(p/(1.0-p)));
++}
++
++/* {{{ proto float stats_cdf_logistic(float par1, float par2, float par3, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_logistic)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double sd;
++ double p;
++ double q;
++ double x;
++ double t;
++ double mean;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ sd = arg3;
++ } else {
++ mean = arg3;
++ }
++
++ if (which < 3) {
++ mean = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ if (which == 1) {
++ t = (x - mean) / sd;
++ p = logistic_cdf(t);
++ } else {
++ t = logistic_quantile(p);
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(mean + (sd * t));
++ case 3: RETURN_DOUBLE(x - (sd * t));
++ case 4: RETURN_DOUBLE((x - mean) / t);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/* {{{ proto float stats_cdf_weibull(float par1, float par2, float par3, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_weibull)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double x;
++ double a;
++ double b;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ b = arg3;
++ } else {
++ a = arg3;
++ }
++
++ if (which < 3) {
++ a = arg2;
++ } else {
++ x = arg2;
++ }
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ if (which == 1) {
++ p = 1 - exp(-pow(x / b, a));
++ } else {
++ x = b * pow(-log(1.0 - p), 1.0 / a);
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(p);
++ case 2: RETURN_DOUBLE(x);
++ case 3: RETURN_DOUBLE(log(-log(1.0 - p)) / log(x / b));
++ case 4: RETURN_DOUBLE(x / pow(-log(1.0 - p), 1.0 / a));
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++/* {{{ proto float stats_cdf_uniform(float par1, float par2, float par3, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_uniform)
++{
++ double arg1;
++ double arg2;
++ double arg3;
++ double p;
++ double q;
++ double x;
++ double a;
++ double b;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 4) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 4) {
++ b = arg3;
++ } else {
++ a = arg3;
++ }
++
++ if (which < 3) {
++ a = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ if (which == 1) {
++ p = 1 - exp(-pow(x / b, a));
++ } else {
++ x = b * pow(-log(1.0 - p), 1.0 / a);
++ }
++
++ switch (which) {
++ case 4: RETURN_DOUBLE((x - (1.0 - p) * a) / p);
++ case 3: RETURN_DOUBLE((x - p * b) / (1.0 - p));
++ case 2: RETURN_DOUBLE(a + p * (b - a));
++ case 1:
++ if (x < a) {
++ p = 0;
++ } else {
++ if (x > b) {
++ p = 1;
++ } else {
++ p = (x - a) / ( b - a);
++ }
++ }
++ RETURN_DOUBLE(p);
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++static double exponential_quantile(double p)
++{
++ return -log(1.0-p);
++}
++
++static double exponential_cdf(double x)
++{
++ return (1.0 - exp(-x));
++}
++
++/* {{{ proto float stats_cdf_exponential(float par1, float par2, int which)
++ Not documented */
++PHP_FUNCTION(stats_cdf_exponential)
++{
++ double arg1;
++ double arg2;
++ double p;
++ double q;
++ double x;
++ double scale;
++ long which;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddl", &arg1, &arg2, &which) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (which < 1 || which > 3) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
++ RETURN_FALSE;
++ }
++
++ if (which < 3) {
++ scale = arg2;
++ } else {
++ x = arg2;
++ }
++
++ if (which == 1) {
++ x = arg1;
++ } else {
++ p = arg1;
++ q = 1.0 - p;
++ }
++
++ switch (which) {
++ case 1: RETURN_DOUBLE(exponential_cdf(x / scale));
++ case 2: RETURN_DOUBLE(scale * exponential_quantile(p));
++ case 3: RETURN_DOUBLE(x / exponential_quantile(p));
++ }
++ RETURN_FALSE; /* never here */
++}
++/* }}} */
++
++
++/*********************/
++/* RANDLIB functions */
++/*********************/
++
++/* {{{ proto void stats_rand_setall(int iseed1, int iseed2)
++ Not documented */
++PHP_FUNCTION(stats_rand_setall)
++{
++ long iseed_1;
++ long iseed_2;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &iseed_1, &iseed_2) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ setall(iseed_1, iseed_2);
++}
++/* }}} */
++
++/* {{{ proto array stats_rand_get_seeds(void)
++ Not documented */
++PHP_FUNCTION(stats_rand_getsd)
++{
++ long iseed_1;
++ long iseed_2;
++
++ if (ZEND_NUM_ARGS() != 0) {
++ WRONG_PARAM_COUNT;
++ }
++ getsd(&iseed_1, &iseed_2);
++
++ array_init(return_value);
++ add_next_index_long(return_value, iseed_1);
++ add_next_index_long(return_value, iseed_2);
++}
++/* }}} */
++
++/* {{{ proto int stats_rand_gen_iuniform(int low, int high)
++ Generates integer uniformly distributed between LOW (inclusive) and HIGH (inclusive) */
++PHP_FUNCTION(stats_rand_gen_iuniform)
++{
++ long low;
++ long high;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &low, &high) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (high - low > 2147483561L) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "high - low too large. low : %16ld high %16ld", low, high);
++ RETURN_FALSE;
++ }
++ if (low > high) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "low greater than high. low : %16ld high %16ld", low, high);
++ RETURN_FALSE;
++ }
++
++ RETURN_LONG(ignuin(low, high));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_funiform(float low, float high)
++ Generates uniform float between low (exclusive) and high (exclusive) */
++PHP_FUNCTION(stats_rand_gen_funiform)
++{
++ double low;
++ double high;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &low, &high) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (low > high) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "low greater than high. low : %16.6E high : %16.6E", low, high);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(genunf(low, high));
++}
++/* }}} */
++
++/* {{{ proto int stats_rand_gen_int(void)
++ Generates random integer between 1 and 2147483562 */
++PHP_FUNCTION(stats_rand_ignlgi)
++{
++ if (ZEND_NUM_ARGS() != 0) {
++ WRONG_PARAM_COUNT;
++ }
++
++ RETURN_LONG(ignlgi());
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_ranf(void)
++ Returns a random floating point number from a uniform distribution over 0 - 1 (endpoints of this interval are not returned) using the current generator */
++PHP_FUNCTION(stats_rand_ranf)
++{
++ if (ZEND_NUM_ARGS() != 0) {
++ WRONG_PARAM_COUNT;
++ }
++
++ RETURN_DOUBLE(ranf());
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_beta(float a, float b)
++ Generates beta random deviate. Returns a random deviate from the beta distribution with parameters A and B. The density of the beta is x^(a-1) * (1-x)^(b-1) / B(a,b) for 0<x<1. aa - first parameter of the beta distribution. bb - second parameter of the beta distribution. Method R. C. H. Cheng */
++PHP_FUNCTION(stats_rand_gen_beta)
++{
++ double a;
++ double b;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &a, &b) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (a < 1.0E-37 || b < 1.0E-37) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'a' or 'b' lower than 1.0E-37. 'a' value : %16.6E 'b' value : %16.6E", a, b);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(genbet(a, b));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_chisquare(float df)
++ Generates random deviate from the distribution of a chisquare with "df" degrees of freedom random variable. */
++PHP_FUNCTION(stats_rand_gen_chisquare)
++{
++ double df;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &df) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (df <= 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0.0. df : %16.6E", df);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(genchi(df));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_exponential(float av)
++ Generates a single random deviate from an exponential distribution with mean "av" */
++PHP_FUNCTION(stats_rand_gen_exponential)
++{
++ double av;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &av) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (av < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "av < 0.0");
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(genexp(av));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_f(float dfn, float dfd)
++ Generates a random deviate from the F (variance ratio) distribution with "dfn" degrees of freedom in the numerator and "dfd" degrees of freedom in the denominator. Method : directly generates ratio of chisquare variates*/
++PHP_FUNCTION(stats_rand_gen_f)
++{
++ double dfn;
++ double dfd;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &dfn, &dfd) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (dfn < 0.0 || dfd < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Degrees of freedom nonpositive. DFN value:%16.6E DFD value:%16.6E", dfn, dfd);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(genf(dfn, dfd));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_gamma(float a, float r)
++ Generates random deviates from the gamma distribution whose density is (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X). Parameters : a - location parameter of Gamma distribution (a > 0), r - shape parameter of Gamma distribution (r > 0) */
++PHP_FUNCTION(stats_rand_gen_gamma)
++{
++ double a;
++ double r;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &a, &r) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (!(a > 0.0 && r > 0.0)) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "A or R nonpositive. A value : %16.6E , R value : %16.6E", a, r);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gengam(a, r));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_noncenral_chisquare(float df, float xnonc)
++ Generates random deviate from the distribution of a noncentral chisquare with "df" degrees of freedom and noncentrality parameter "xnonc". d must be >= 1.0, xnonc must >= 0.0 */
++PHP_FUNCTION(stats_rand_gen_noncentral_chisquare)
++{
++ double df;
++ double xnonc;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &df, &xnonc) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (df < 1.0 || xnonc < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "df < 1 or xnonc < 0. df value : %16.6E xnonc value : %16.6E", df, xnonc);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gennch(df, xnonc));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_noncentral_f(float dfn, float dfd, float xnonc)
++ Generates a random deviate from the noncentral F (variance ratio) distribution with "dfn" degrees of freedom in the numerator, and "dfd" degrees of freedom in the denominator, and noncentrality parameter "xnonc". Method : directly generates ratio of noncentral numerator chisquare variate to central denominator chisquare variate. */
++PHP_FUNCTION(stats_rand_gen_noncenral_f)
++{
++ double dfn;
++ double dfd;
++ double xnonc;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &dfn, &dfd, &xnonc) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (dfn < 1.0 || dfd <= 0.0 || xnonc < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Either (1) Numerator df < 1.0 or (2) Denominator df <= 0.0 or (3) Noncentrality parameter < 0.0. dfn: %16.6E dfd: %16.6E xnonc: %16.6E", dfn, dfd, xnonc);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gennf(dfn, dfd, xnonc));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_normal(float av, float sd)
++ Generates a single random deviate from a normal distribution with mean, av, and standard deviation, sd (sd >= 0). Method : Renames SNORM from TOMS as slightly modified by BWB to use RANF instead of SUNIF. */
++PHP_FUNCTION(stats_rand_gen_normal)
++{
++ double av;
++ double sd;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &av, &sd) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (sd < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "sd < 0.0 . sd : %16.6E", sd);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gennor(av, sd));
++}
++/* }}} */
++
++/* {{{ proto array stats_rand_phrase_to_seeds(string phrase)
++ Uses a phrase (characted string) to generate two seeds for the RGN random number generator. Trailing blanks are eliminated before the seeds are generated. Generated seed values will fall in the range 1..2^30. */
++PHP_FUNCTION(stats_rand_phrase_to_seeds)
++{
++ zval **par1;
++ char *arg1 = NULL;
++ long seed_1;
++ long seed_2;
++
++ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &par1) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++ convert_to_string_ex(par1);
++
++ arg1 = estrndup(Z_STRVAL_PP(par1), Z_STRLEN_PP(par1));
++ phrtsd(arg1, &seed_1, &seed_2);
++ efree(arg1);
++
++ array_init(return_value);
++ add_next_index_long(return_value, seed_1);
++ add_next_index_long(return_value, seed_2);
++}
++/* }}} */
++
++/* {{{ proto int stats_rand_gen_ibinomial(int n, float pp)
++ Generates a single random deviate from a binomial distribution whose number of trials is "n" (n >= 0) and whose probability of an event in each trial is "pp" ([0;1]). Method : algorithm BTPE */
++PHP_FUNCTION(stats_rand_ibinomial)
++{
++ long n;
++ double pp;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &n, &pp) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if ((n < 0) || (pp < 0.0) || (pp > 1.0)) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad values for the arguments. n : %ld pp : %16.6E", n, pp);
++ RETURN_FALSE;
++ }
++
++ RETURN_LONG(ignbin(n, pp));
++}
++/* }}} */
++
++/* {{{ proto int stats_rand_gen_ibinomial_negative(int n, float p)
++ Generates a single random deviate from a negative binomial distribution. Arguments : n - the number of trials in the negative binomial distribution from which a random deviate is to be generated (n > 0), p - the probability of an event (0 < p < 1)). */
++PHP_FUNCTION(stats_rand_ibinomial_negative)
++{
++ long n;
++ double p;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &n, &p) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (n <= 0L) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "n < 0. n : %ld", n);
++ RETURN_FALSE;
++ }
++ if (p < 0.0F || p > 1.0F) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "p is out of range. p : %16.E", p);
++ RETURN_FALSE;
++ }
++
++ RETURN_LONG(ignnbn(n, p));
++}
++/* }}} */
++
++/* {{{ proto int stats_rand_gen_ipoisson(float mu)
++ Generates a single random deviate from a Poisson distribution with mean "mu" (mu >= 0.0). */
++PHP_FUNCTION(stats_rand_gen_ipoisson)
++{
++ double mu;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &mu) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (mu < 0.0F) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "mu < 0.0 . mu : %16.6E", mu);
++ RETURN_FALSE;
++ }
++
++ RETURN_LONG(ignpoi(mu));
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_noncentral_t(float df, float xnonc)
++ Generates a single random deviate from a noncentral T distribution. xnonc - noncentrality parameter. df must be >= 0.0*/
++PHP_FUNCTION(stats_rand_gen_noncentral_t)
++{
++ double df;
++ double xnonc;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &df, &xnonc) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (df < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0 . df : %16.6E", df);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gennor(xnonc, 1) / sqrt(genchi(df) / df) );
++}
++/* }}} */
++
++/* {{{ proto float stats_rand_gen_t(float df)
++ Generates a single random deviate from a T distribution. df must be >= 0.0 */
++PHP_FUNCTION(stats_rand_gen_t)
++{
++ zval **arg1;
++ double df;
++
++ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ convert_to_double_ex(arg1);
++ df = Z_DVAL_PP(arg1);
++
++ if (df < 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0 . df : %16.6E", df);
++ RETURN_FALSE;
++ }
++
++ RETURN_DOUBLE(gennor(0, 1) / sqrt(genchi(df) / df));
++}
++/* }}} */
++
++/***************************/
++/* Start density functions */
++/***************************/
++
++/* {{{ proto float stats_dens_normal(float x, float ave, float stdev)
++ Not documented */
++PHP_FUNCTION(stats_dens_normal)
++{
++ double stdev;
++ double ave;
++ double x;
++ double y;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &ave, &stdev) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (stdev == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
++ RETURN_FALSE;
++ }
++
++ z = (x - ave) / stdev;
++ y = (1.0 / (stdev * sqrt(2.0 * STATS_PI))) * exp (-0.5 * z * z);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_cauchy(float x, float ave, float stdev)
++ Not documented */
++PHP_FUNCTION(stats_dens_cauchy)
++{
++ double stdev;
++ double ave;
++ double x;
++ double y;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &ave, &stdev) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (stdev == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
++ RETURN_FALSE;
++ }
++
++ z = (x - ave) / stdev;
++ y = 1.0 / (stdev*STATS_PI * (1.0 + (z * z)));
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_laplace(float x, float ave, float stdev)
++ Not documented */
++PHP_FUNCTION(stats_dens_laplace)
++{
++ double stdev;
++ double ave;
++ double x;
++ double y;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &ave, &stdev) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (stdev == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
++ RETURN_FALSE;
++ }
++
++ z = fabs((x - ave) / stdev);
++ y = (1.0 / (2.0 * stdev)) * exp(- z);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_logistic(float x, float ave, float stdev)
++ Not documented */
++PHP_FUNCTION(stats_dens_logistic)
++{
++ double stdev;
++ double ave;
++ double x;
++ double y;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &ave, &stdev) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (stdev == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
++ RETURN_FALSE;
++ }
++
++ z = exp((x - ave) / stdev);
++ y = z / (stdev * pow(1 + z, 2.0));
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_beta(float x, float a, float b)
++ Not documented */
++PHP_FUNCTION(stats_dens_beta)
++{
++ double a;
++ double b;
++ double beta;
++ double x;
++ double y;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &a, &b) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ beta = 1.0 / exp(lgamma(a) + lgamma(b) - lgamma(a + b));
++ y = beta * pow(x, a - 1.0) * pow(1.0 - x, b - 1.0);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_weibull(float x, float a, float b)
++ Not documented */
++PHP_FUNCTION(stats_dens_weibull)
++{
++ double a;
++ double b;
++ double x;
++ double y;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &a, &b) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (b == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "b is 0.0");
++ RETURN_FALSE;
++ }
++
++ y = (a / b) * pow(x / b, a - 1.0) * exp(pow(- x / b, a));
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_uniform(float x, float a, float b)
++ Not documented */
++PHP_FUNCTION(stats_dens_uniform)
++{
++ double a;
++ double b;
++ double x;
++ double y;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &a, &b) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (a == b) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "b == a == %16.6E", a);
++ RETURN_FALSE;
++ }
++
++ if ((x <= b) && (x >= a)) {
++ y = 1.0 / (b - a);
++ } else {
++ y = 0.0;
++ }
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_chisquare(float x, float dfr)
++ Not documented */
++PHP_FUNCTION(stats_dens_chisquare)
++{
++ double dfr;
++ double e;
++ double x;
++ double y;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "dd", &x, &dfr) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ e = dfr / 2.0;
++ z = ((e - 1.0) * log(x)) - ((x / 2.0) +(e * log(2.0)) + lgamma(e));
++ y = exp (z);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_t(float x, float dfr)
++ Not documented */
++PHP_FUNCTION(stats_dens_t)
++{
++ double dfr;
++ double e;
++ double f;
++ double fac1;
++ double fac2;
++ double fac3;
++ double x;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &dfr) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (dfr == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "dfr == 0.0");
++ RETURN_FALSE;
++ }
++
++ e = dfr / 2.0;
++ f = e + 0.5;
++ fac1 = lgamma(f);
++ fac2 = f * log(1.0 + (x * x) / dfr);
++ fac3 = lgamma(e) + 0.5 * log(dfr * STATS_PI);
++
++ RETURN_DOUBLE(exp( fac1 - (fac2 + fac3) ));
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_gamma(float x, float shape, float scale)
++ Not documented */
++PHP_FUNCTION(stats_dens_gamma)
++{
++ double shape;
++ double scale;
++ double x;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &shape, &scale) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (scale == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "scale == 0.0");
++ RETURN_FALSE;
++ }
++
++ z = ((shape - 1.0) * log(x)) -
++ (
++ (x / scale) + lgamma(shape) + (shape * log(scale))
++ )
++ ;
++
++ RETURN_DOUBLE(exp(z));
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_exponential(float x, float scale)
++ Not documented */
++PHP_FUNCTION(stats_dens_exponential)
++{
++ double scale;
++ double x;
++ double y;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &scale) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if (scale == 0.0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "scale == 0.0");
++ RETURN_FALSE;
++ }
++
++ if (x < 0) {
++ y = 0;
++ } else {
++ y = exp(-x / scale) / scale;
++ }
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_f(float x, float dfr1, float dfr2)
++ */
++PHP_FUNCTION(stats_dens_f)
++{
++ double dfr1;
++ double dfr2;
++ double efr1;
++ double efr2;
++ double fac1;
++ double fac2;
++ double fac3;
++ double fac4;
++ double x;
++ double z;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &dfr1, &dfr2) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ efr1 = dfr1 / 2.0;
++ efr2 = dfr2 / 2.0;
++ fac1 = (efr1 - 1.0) * log (x);
++ fac2 = (efr1 + efr2) * log (dfr2 + (dfr1 * x));
++ fac3 = (efr1 * log (dfr1)) + (efr2 * log (dfr2));
++ fac4 = lgamma (efr1) + lgamma (efr2) - lgamma (efr1 + efr2);
++
++ z = (fac1 + fac3) - (fac2 + fac4);
++
++ RETURN_DOUBLE(exp(z));
++}
++/* }}} */
++
++static double binom(double x, double n)
++{
++ int i;
++ double di;
++ double s = 1.0;
++
++ for (i = 0; i < x; ++i) {
++ di = (double) i;
++ s = (s * (n - di)) / (di + 1.0);
++ }
++
++ return s;
++}
++
++/* {{{ proto float stats_dens_pmf_binomial(float x, float n, float pi)
++ Not documented */
++PHP_FUNCTION(stats_dens_pmf_binomial)
++{
++ double pi;
++ double y;
++ double n;
++ double x;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
++ "ddd", &x, &n, &pi) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if ((x == 0.0 && n == 0.0) || (pi == 0.0 && x == 0.0)
++ || ( (1.0 - pi) == 0.0 && (n - x) == 0) ) {
++
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Params leading to pow(0, 0). x:%16.6E n:%16.6E pi:%16.6E", x, n, pi);
++ RETURN_FALSE;
++ }
++
++ y = binom(x,n) * pow(pi,x) * pow((1.0 - pi), (n - x));
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_pmf_poisson(float x, float lb)
++ Not documented */
++PHP_FUNCTION(stats_dens_pmf_poisson)
++{
++ double lb;
++ double z;
++ double x;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &lb) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ z = (x * log(lb)) - (lb + lgamma(x + 1.0));
++
++ RETURN_DOUBLE(exp(z));
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_negative_binomial(float x, float n, float pi)
++ Not documented */
++PHP_FUNCTION(stats_dens_pmf_negative_binomial)
++{
++ double pi;
++ double y;
++ double n;
++ double x;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &n, &pi) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if ((pi == 0.0 && n == 0.0) || ((1.0 - pi) == 0.0 && x == 0.0)) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Params leading to pow(0, 0). x:%16.6E n:%16.6E pi:%16.6E", x, n, pi);
++ RETURN_FALSE;
++ }
++
++ y = binom(x, n + x - 1.0) * pow(pi,n) * pow((1.0 - pi), x);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/* {{{ proto float stats_dens_pmf_hypergeometric(float n1, float n2, float N1, float N2)
++ */
++PHP_FUNCTION(stats_dens_pmf_hypergeometric)
++{
++ double y;
++ double N1;
++ double N2;
++ double n1;
++ double n2;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &n1, &n2, &N1, &N2) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ if ((int)(n1 + n2) >= (int)(N1 + N2)) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "possible division by zero - n1+n2 >= N1+N2");
++ /* RETURN_FALSE; */
++ }
++
++ y = binom(n1, N1) * binom (n2, N2)/binom(n1 + n2, N1 + N2);
++
++ RETURN_DOUBLE(y);
++}
++/* }}} */
++
++/************************/
++/* Statistics functions */
++/************************/
++
++/* {{{ proto float stats_stat_powersum(array arr, float power)
++ Not documented */
++PHP_FUNCTION(stats_stat_powersum)
++{
++ zval **arg1, **arg2, **data; /* pointer to array entry */
++ HashPosition pos; /* hash iterator */
++ double power;
++ double sum = 0.0;
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ convert_to_array_ex(arg1);
++ convert_to_double_ex(arg2);
++ power = Z_DVAL_PP(arg2);
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data, &pos) == SUCCESS) {
++ convert_to_double_ex(data);
++ if (Z_DVAL_PP(data) != 0 && power != 0) {
++ sum += pow (Z_DVAL_PP(data), power);
++ } else {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both value and power are zero");
++ }
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos);
++ }
++
++ RETURN_DOUBLE(sum);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_innerproduct(array arr1, array arr2)
++ */
++PHP_FUNCTION(stats_stat_innerproduct)
++{
++ zval **arg1, **arg2;
++ zval **data1, **data2; /* pointers to array entries */
++ HashPosition pos1; /* hash iterator */
++ HashPosition pos2; /* hash iterator */
++ double sum = 0.0;
++
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++ convert_to_array_ex(arg1);
++ convert_to_array_ex(arg2);
++
++ if (zend_hash_num_elements(Z_ARRVAL_PP(arg1)) != zend_hash_num_elements(Z_ARRVAL_PP(arg2))) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
++ RETURN_FALSE;
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
++ && zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
++ convert_to_double_ex(data1);
++ convert_to_double_ex(data2);
++ sum = Z_DVAL_PP(data1) * Z_DVAL_PP(data2);
++
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
++ }
++
++ RETURN_DOUBLE(sum);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_independent_t(array arr1, array arr2)
++ Not documented */
++PHP_FUNCTION(stats_stat_independent_t)
++{
++ zval **arg1, **arg2;
++ zval **data1, **data2; /* pointers to array entries */
++ HashPosition pos1; /* hash iterator */
++ HashPosition pos2; /* hash iterator */
++ int xnum = 0, ynum = 0;
++ double cur;
++ double sx = 0.0;
++ double sxx = 0.0;
++ double sy = 0.0;
++ double syy = 0.0;
++ double mx;
++ double vx;
++ double my;
++ double vy;
++ double sp;
++ double fc;
++ double ts;
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++ convert_to_array_ex(arg1);
++ convert_to_array_ex(arg2);
++
++ xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
++ ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
++ if ( xnum < 2 || ynum < 2) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each argument should have more than 1 element");
++ RETURN_FALSE;
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
++ convert_to_double_ex(data1);
++ cur = Z_DVAL_PP(data1);
++ sx += cur;
++ sxx += cur * cur;
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
++ convert_to_double_ex(data2);
++ cur = Z_DVAL_PP(data2);
++ sy += cur;
++ syy += cur * cur;
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
++ }
++
++ mx = sx / xnum;
++ my = sy / ynum;
++ vx = (sxx - (xnum * mx * mx)) / (xnum - 1.0);
++ vy = (syy - (ynum * my * my)) / (ynum - 1.0);
++ sp = (((xnum - 1.0) * vx) + ((ynum - 1.0) * vy)) / (xnum + ynum - 2.0);
++ fc = (1.0 / xnum) + (1.0 / ynum);
++ ts = (mx - my) / sqrt(sp * fc);
++
++ RETURN_DOUBLE(ts);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_paired_t(array arr1, array arr2)
++ Not documented */
++PHP_FUNCTION(stats_stat_paired_t)
++{
++ zval **arg1, **arg2, **data1, **data2; /* pointers to array entries */
++ HashPosition pos1; /* hash iterator */
++ HashPosition pos2; /* hash iterator */
++ int xnum = 0;
++ int ynum = 0;
++ double sd = 0.0;
++ double sdd = 0.0;
++ double md;
++ double td;
++ double ts;
++ double cur;
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++ convert_to_array_ex(arg1);
++ convert_to_array_ex(arg2);
++
++ xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
++ ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
++
++ if (xnum != ynum) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
++ RETURN_FALSE;
++ }
++ if (xnum < 2) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "arr1 should have atleast 2 elements");
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
++ &&
++ zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
++ convert_to_double_ex(data1);
++ convert_to_double_ex(data2);
++
++ cur = Z_DVAL_PP(data1) - Z_DVAL_PP(data2);
++ sd += cur;
++ sdd += cur * cur;
++
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
++ }
++
++ md = sd / xnum;
++ td = sqrt((sdd - (xnum * md * md)) / (xnum - 1.0));
++ ts = sqrt((double) xnum) * (md / td);
++
++ RETURN_DOUBLE(ts);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_percentile(float df, float xnonc)
++ Not documented */
++PHP_FUNCTION(stats_stat_percentile)
++{
++ zval **arg1, **arg2;
++ zval **data1; /* pointers to array entries */
++ HashPosition pos1; /* hash iterator */
++ long ilow;
++ long iupp;
++ int xnum = 0;
++ int cnt = -1;
++ double perc;
++ double low;
++ double upp;
++ double val = 0.0;
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ convert_to_array_ex(arg1);
++ convert_to_double_ex(arg2);
++ perc = Z_DVAL_PP(arg2);
++
++ xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
++
++ if (zend_hash_sort(Z_ARRVAL_PP(arg1), zend_qsort, stats_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
++
++ low = .01 * perc * (double)xnum;
++ upp = .01 * (100.0 - perc) * (double)xnum;
++ ilow = floor(low);
++ iupp = floor(upp);
++ if ((ilow + iupp) == xnum) {
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
++ if (++cnt == ilow - 1 ) {
++ convert_to_double_ex(data1);
++ val = Z_DVAL_PP(data1);
++
++ zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1);
++ convert_to_double_ex(data1);
++ val += Z_DVAL_PP(data1);
++ val = val / 2.0;
++ break;
++ }
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ }
++ } else {
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
++ if (++cnt == ilow) {
++ convert_to_double_ex(data1);
++ val += Z_DVAL_PP(data1);
++ break;
++ }
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ }
++ }
++
++ RETURN_DOUBLE(val);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_correlation(array arr1, array arr2)
++ Not documented */
++PHP_FUNCTION(stats_stat_correlation)
++{
++ zval **arg1, **arg2;
++ zval **data1, **data2; /* pointers to array entries */
++ HashPosition pos1; /* hash iterator */
++ HashPosition pos2; /* hash iterator */
++ int xnum = 0;
++ int ynum = 0;
++ double sx = 0.0;
++ double sy = 0.0;
++ double sxx = 0.0;
++ double syy = 0.0;
++ double sxy = 0.0;
++ double mx;
++ double my;
++ double vx;
++ double vy;
++ double cc;
++ double rr;
++
++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ convert_to_array_ex(arg1);
++ convert_to_array_ex(arg2);
++
++ xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
++ ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
++
++ if (xnum != ynum) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
++ RETURN_FALSE;
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
++
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
++ && zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
++
++ convert_to_double_ex(data1);
++ convert_to_double_ex(data2);
++
++ sx += Z_DVAL_PP(data1);
++ sxx += Z_DVAL_PP(data1) * Z_DVAL_PP(data1);
++ sy += Z_DVAL_PP(data2);
++ syy += Z_DVAL_PP(data2) * Z_DVAL_PP(data2);
++ sxy += Z_DVAL_PP(data1) * Z_DVAL_PP(data2);
++
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
++ zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
++ }
++
++ mx = sx / xnum;
++ my = sy / ynum;
++ vx = sxx - (xnum * mx * mx);
++ vy = syy - (ynum * my * my);
++ cc = sxy - (xnum * mx * my);
++ rr = cc / sqrt(vx * vy);
++
++ RETURN_DOUBLE(rr);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_binomial_coef(int x, int n)
++ Not documented */
++PHP_FUNCTION(stats_stat_binomial_coef)
++{
++ int i;
++ int n;
++ int x;
++ double bc = 1.0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &x, &n) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ for (i = 0; i < x; ++i) {
++ bc = (bc * (n - i)) / (i + 1);
++ }
++
++ RETURN_DOUBLE(bc);
++}
++/* }}} */
++
++/* {{{ proto float stats_stat_gennch(int n)
++ Not documented */
++PHP_FUNCTION(stats_stat_factorial)
++{
++ int n;
++ int i;
++ double f = 1;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) {
++ RETURN_FALSE;
++ }
++
++ for (i = 1; i <= n; ++i) {
++ f *= i;
++ }
++
++ RETURN_DOUBLE(f);
++}
++/* }}} */
++
++
++/* {{{ php_population_variance
++*/
++static long double php_math_mean(zval *arr)
++{
++ double sum = 0.0;
++ zval **entry;
++ HashPosition pos;
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ convert_to_double_ex(entry);
++ sum += Z_DVAL_PP(entry);
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ }
++ /*
++ we don't check whether the array has 0 elements. this is left to the caller - no need
++ to kill performance by checking on every level.
++ */
++ return sum / zend_hash_num_elements(Z_ARRVAL_P(arr));
++}
++/* }}} */
++
++
++/* {{{ php_population_variance
++*/
++static long double php_population_variance(zval *arr, zend_bool sample)
++{
++ double mean, vr = 0.0;
++ zval **entry;
++ HashPosition pos;
++ int elements_num;
++
++ elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr));
++
++ mean = php_math_mean(arr);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ double d;
++ convert_to_double_ex(entry);
++ d = Z_DVAL_PP(entry) - mean;
++ vr += d*d;
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ }
++ if (sample) {
++ --elements_num;
++ }
++ return (vr / elements_num);
++}
++/* }}} */
++
++
++/* {{{ proto float stats_variance(array a [, bool sample])
++ Returns the population variance */
++PHP_FUNCTION(stats_variance)
++{
++ zval *arr;
++ zend_bool sample = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &arr, &sample) == FAILURE) {
++ return;
++ }
++ if (zend_hash_num_elements(Z_ARRVAL_P(arr)) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++ if (sample && zend_hash_num_elements(Z_ARRVAL_P(arr)) == 1) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has only 1 element");
++ RETURN_FALSE;
++ }
++ RETURN_DOUBLE(php_population_variance(arr, sample));
++}
++/* }}} */
++
++/* {{{ proto float stats_standard_deviation(array a[, bool sample = false])
++ Returns the standard deviation */
++PHP_FUNCTION(stats_standard_deviation)
++{
++ zval *arr;
++ zend_bool sample = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &arr, &sample) == FAILURE) {
++ return;
++ }
++ if (zend_hash_num_elements(Z_ARRVAL_P(arr)) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++ if (sample && zend_hash_num_elements(Z_ARRVAL_P(arr)) == 1) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has only 1 element");
++ RETURN_FALSE;
++ }
++ RETURN_DOUBLE(sqrt(php_population_variance(arr, sample)));
++}
++/* }}} */
++
++
++/* {{{ proto float stats_absolute_deviation(array a)
++ Returns the absolute deviation of an array of values*/
++PHP_FUNCTION(stats_absolute_deviation)
++{
++ zval *arr;
++ double mean = 0.0, abs_dev = 0.0;
++ zval **entry;
++ HashPosition pos;
++ int elements_num;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
++ return;
++ }
++ if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++
++ mean = php_math_mean(arr);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ convert_to_double_ex(entry);
++ abs_dev += fabs(Z_DVAL_PP(entry) - mean);
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ }
++
++ RETURN_DOUBLE(abs_dev / elements_num);
++}
++/* }}} */
++
++/* {{{ proto float stats_harmonic_mean(array a)
++ Returns the harmonic mean of an array of values */
++PHP_FUNCTION(stats_harmonic_mean)
++{
++ zval *arr;
++ double sum = 0.0;
++ zval **entry;
++ HashPosition pos;
++ int elements_num;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
++ return;
++ }
++ if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ convert_to_double_ex(entry);
++ if (Z_DVAL_PP(entry) == 0) {
++ RETURN_LONG(0);
++ }
++ sum += 1 / Z_DVAL_PP(entry);
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ }
++
++ RETURN_DOUBLE(elements_num / sum);
++}
++/* }}} */
++
++/* {{{ proto float stats_skew(array a)
++ Computes the skewness of the data in the array */
++PHP_FUNCTION(stats_skew)
++{
++ zval *arr;
++ double mean, std_dev, skew = 0.0;
++ zval **entry;
++ HashPosition pos;
++ int elements_num, i = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
++ return;
++ }
++ if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++
++ mean = php_math_mean(arr);
++ std_dev = sqrt(php_population_variance(arr, 0));
++
++ /* the calculation of the skewness is protected of value "explosion". a bit more
++ FP operations performed but more accurateness.
++ */
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ double tmp;
++ convert_to_double_ex(entry);
++ tmp = ((Z_DVAL_PP(entry) - mean) / std_dev);
++ skew += (tmp*tmp*tmp - skew) / (i + 1);
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ ++i;
++ }
++
++ RETURN_DOUBLE(skew);
++}
++/* }}} */
++
++/* {{{ proto float stats_kurtosis(array a)
++ Computes the kurtosis of the data in the array */
++PHP_FUNCTION(stats_kurtosis)
++{
++ zval *arr;
++ double mean, std_dev, avg = 0.0;
++ zval **entry;
++ HashPosition pos;
++ int elements_num, i = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
++ return;
++ }
++ if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
++ RETURN_FALSE;
++ }
++
++ mean = php_math_mean(arr);
++ std_dev = sqrt(php_population_variance(arr, 0));
++
++ /* the calculation of the kurtosis is protected of value "explosion". a bit more
++ FP operations performed but more accurateness.
++ */
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
++ double tmp;
++ convert_to_double_ex(entry);
++ tmp = ((Z_DVAL_PP(entry) - mean) / std_dev);
++ avg += (tmp*tmp*tmp*tmp - avg) / (i + 1);
++
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
++ ++i;
++ }
++
++ RETURN_DOUBLE(avg - 3);
++}
++/* }}} */
++
++
++/* {{{ proto float stats_covariance(array a, array b)
++ Computes the covariance of two data sets */
++PHP_FUNCTION(stats_covariance)
++{
++ zval *arr_1, *arr_2;
++ double mean_1, mean_2, covar = 0.0;
++ zval **entry;
++ HashPosition pos_1, pos_2;
++ int elements_num, i = 0;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &arr_1, &arr_2) == FAILURE) {
++ return;
++ }
++ if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr_1))) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first array has zero elements");
++ RETURN_FALSE;
++ }
++ if (zend_hash_num_elements(Z_ARRVAL_P(arr_2)) == 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second array has zero elements");
++ RETURN_FALSE;
++ }
++ if (elements_num != zend_hash_num_elements(Z_ARRVAL_P(arr_2))) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The datasets are not of the same size");
++ RETURN_FALSE;
++ }
++
++ mean_1 = php_math_mean(arr_1);
++ mean_2 = php_math_mean(arr_2);
++ /* the calculation of the covariance is protected of value "explosion". a bit more
++ FP operations performed but more accurateness.
++ */
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr_1), &pos_1);
++ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr_2), &pos_2);
++ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr_1), (void **)&entry, &pos_1) == SUCCESS) {
++ double tmp_1, tmp_2;
++ convert_to_double_ex(entry);
++ tmp_1 = Z_DVAL_PP(entry) - mean_1;
++
++ if (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr_2), (void **)&entry, &pos_2) != SUCCESS) {
++ break;
++ }
++ convert_to_double_ex(entry);
++ tmp_2 = Z_DVAL_PP(entry) - mean_2;
++
++ covar += (tmp_1 * tmp_2 - covar) / (i + 1);
++
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr_1), &pos_1);
++ zend_hash_move_forward_ex(Z_ARRVAL_P(arr_2), &pos_2);
++ ++i;
++ }
++
++ RETURN_DOUBLE(covar);
++}
++/* }}} */
++
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * indent-tabs-mode: t
++ * End:
++ */
+diff -dPNur stats-1.0.2/php_stats.h trunk/php_stats.h
+--- stats-1.0.2/php_stats.h 1970-01-01 01:00:00.000000000 +0100
++++ trunk/php_stats.h 2012-10-29 17:22:36.000000000 +0100
+@@ -0,0 +1,129 @@
++/*
++ +----------------------------------------------------------------------+
++ | PHP Version 5 |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 1997-2004 The PHP Group |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 3.0 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available through the world-wide-web at the following url: |
++ | http://www.php.net/license/3_0.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Andrey Hristov <andrey@php.net> |
++ +----------------------------------------------------------------------+
++*/
++
++/* $Id: php_stats.h 256977 2008-04-08 16:13:17Z sfox $ */
++
++#ifndef PHP_STATS_H
++#define PHP_STATS_H
++
++extern zend_module_entry stats_module_entry;
++#define phpext_stats_ptr &stats_module_entry
++
++#define PHP_STATS_VERSION "1.0.3-dev"
++
++#ifdef PHP_WIN32
++#define PHP_STATS_API __declspec(dllexport)
++#else
++#define PHP_STATS_API
++#endif
++
++
++PHP_MINFO_FUNCTION(stats);
++
++PHP_FUNCTION(stats_bin_counts);
++PHP_FUNCTION(stats_cdf_t);
++PHP_FUNCTION(stats_cdf_normal);
++PHP_FUNCTION(stats_cdf_gamma);
++PHP_FUNCTION(stats_cdf_chisquare);
++PHP_FUNCTION(stats_cdf_beta);
++PHP_FUNCTION(stats_cdf_binomial);
++PHP_FUNCTION(stats_cdf_noncentral_chisquare);
++PHP_FUNCTION(stats_cdf_f);
++PHP_FUNCTION(stats_cdf_noncentral_f);
++PHP_FUNCTION(stats_cdf_noncentral_t);
++PHP_FUNCTION(stats_cdf_negative_binomial);
++PHP_FUNCTION(stats_cdf_poisson);
++PHP_FUNCTION(stats_cdf_laplace);
++PHP_FUNCTION(stats_cdf_cauchy);
++PHP_FUNCTION(stats_cdf_logistic);
++PHP_FUNCTION(stats_cdf_weibull);
++PHP_FUNCTION(stats_cdf_uniform);
++PHP_FUNCTION(stats_cdf_exponential);
++PHP_FUNCTION(stats_rand_setall);
++PHP_FUNCTION(stats_rand_getsd);
++PHP_FUNCTION(stats_rand_gen_iuniform);
++PHP_FUNCTION(stats_rand_gen_funiform);
++PHP_FUNCTION(stats_rand_ignlgi);
++PHP_FUNCTION(stats_rand_ranf);
++PHP_FUNCTION(stats_rand_gen_beta);
++PHP_FUNCTION(stats_rand_gen_chisquare);
++PHP_FUNCTION(stats_rand_gen_exponential);
++PHP_FUNCTION(stats_rand_gen_f);
++PHP_FUNCTION(stats_rand_gen_gamma);
++PHP_FUNCTION(stats_rand_gen_noncentral_chisquare);
++PHP_FUNCTION(stats_rand_gen_noncenral_f);
++PHP_FUNCTION(stats_rand_gen_normal);
++PHP_FUNCTION(stats_rand_phrase_to_seeds);
++PHP_FUNCTION(stats_rand_ibinomial);
++PHP_FUNCTION(stats_rand_ibinomial_negative);
++PHP_FUNCTION(stats_rand_gen_ipoisson);
++PHP_FUNCTION(stats_rand_gen_noncentral_t);
++PHP_FUNCTION(stats_rand_gen_t);
++PHP_FUNCTION(stats_dens_normal);
++PHP_FUNCTION(stats_dens_cauchy);
++PHP_FUNCTION(stats_dens_laplace);
++PHP_FUNCTION(stats_dens_logistic);
++PHP_FUNCTION(stats_dens_beta);
++PHP_FUNCTION(stats_dens_weibull);
++PHP_FUNCTION(stats_dens_uniform);
++PHP_FUNCTION(stats_dens_chisquare);
++PHP_FUNCTION(stats_dens_t);
++PHP_FUNCTION(stats_dens_gamma);
++PHP_FUNCTION(stats_dens_exponential);
++PHP_FUNCTION(stats_dens_f);
++PHP_FUNCTION(stats_dens_pmf_binomial);
++PHP_FUNCTION(stats_dens_pmf_poisson);
++PHP_FUNCTION(stats_dens_pmf_negative_binomial);
++PHP_FUNCTION(stats_dens_pmf_hypergeometric);
++PHP_FUNCTION(stats_stat_powersum);
++PHP_FUNCTION(stats_stat_innerproduct);
++PHP_FUNCTION(stats_stat_independent_t);
++PHP_FUNCTION(stats_stat_paired_t);
++PHP_FUNCTION(stats_stat_percentile);
++PHP_FUNCTION(stats_stat_correlation);
++PHP_FUNCTION(stats_stat_binomial_coef);
++PHP_FUNCTION(stats_stat_factorial);
++PHP_FUNCTION(stats_absolute_deviation);
++PHP_FUNCTION(stats_standard_deviation);
++PHP_FUNCTION(stats_variance);
++PHP_FUNCTION(stats_harmonic_mean);
++PHP_FUNCTION(stats_skew);
++PHP_FUNCTION(stats_kurtosis);
++PHP_FUNCTION(stats_covariance);
++
++
++#ifdef ZTS
++#define STATS_D zend_stats_globals *stats_globals
++#define STATS_G(v) (stats_globals->v)
++#define STATS_FETCH() zend_stats_globals *stats_globals = ts_resource(stats_globals_id)
++#else
++#define STATS_D
++#define STATS_G(v) (stats_globals.v)
++#define STATS_FETCH()
++#endif
++
++#endif /* PHP_STATS_H */
++
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * indent-tabs-mode: t
++ * End:
++ */
+diff -dPNur stats-1.0.2/statistics.c trunk/statistics.c
+--- stats-1.0.2/statistics.c 2006-05-31 19:24:26.000000000 +0200
++++ trunk/statistics.c 1970-01-01 01:00:00.000000000 +0100
+@@ -1,3728 +0,0 @@
+-/*
+- +----------------------------------------------------------------------+
+- | PHP Version 5 |
+- +----------------------------------------------------------------------+
+- | Copyright (c) 1997-2004 The PHP Group |
+- +----------------------------------------------------------------------+
+- | This source file is subject to version 3.0 of the PHP license, |
+- | that is bundled with this package in the file LICENSE, and is |
+- | available through the world-wide-web at the following url: |
+- | http://www.php.net/license/3_0.txt. |
+- | If you did not receive a copy of the PHP license and are unable to |
+- | obtain it through the world-wide-web, please send a note to |
+- | license@php.net so we can mail you a copy immediately. |
+- +----------------------------------------------------------------------+
+- | Author: Andrey Hristov <andrey@php.net> |
+- +----------------------------------------------------------------------+
+-*/
+-
+-/* $Id: statistics.c,v 1.11 2006/05/30 18:02:36 andrey Exp $ */
+-
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include "php.h"
+-#include "php_statistics.h"
+-#include "ext/standard/info.h"
+-#include "ext/standard/head.h"
+-#include <stdlib.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include <math.h>
+-#include "randlib.h"
+-#include "cdflib.h"
+-
+-#define STATS_PI 3.14159265358979323846
+-
+-
+-#ifdef PHP_WIN32
+-extern double fd_lgamma(double x);
+-#define lgamma fd_lgamma
+-#endif
+-
+-static double logistic_quantile(double p);
+-static double logistic_cdf(double x);
+-static double cauchy_quantile(double p);
+-static double cauchy_cdf(double x);
+-static double laplace_quantile(double p);
+-static double laplace_cdf(double x);
+-static double exponential_quantile(double p);
+-static double exponential_cdf(double x);
+-static double binom(double x, double n);
+-
+-zend_function_entry statistics_functions[] = {
+- PHP_FE(stats_cdf_t, NULL)
+- PHP_FE(stats_cdf_normal, NULL)
+- PHP_FE(stats_cdf_gamma, NULL)
+- PHP_FE(stats_cdf_chisquare, NULL)
+- PHP_FE(stats_cdf_beta, NULL)
+- PHP_FE(stats_cdf_binomial, NULL)
+- PHP_FE(stats_cdf_noncentral_chisquare,NULL)
+- PHP_FE(stats_cdf_f, NULL)
+- PHP_FE(stats_cdf_noncentral_f, NULL)
+- PHP_FE(stats_cdf_noncentral_t, NULL)
+- PHP_FE(stats_cdf_negative_binomial, NULL)
+- PHP_FE(stats_cdf_poisson, NULL)
+- PHP_FE(stats_cdf_laplace, NULL)
+- PHP_FE(stats_cdf_cauchy, NULL)
+- PHP_FE(stats_cdf_logistic, NULL)
+- PHP_FE(stats_cdf_weibull, NULL)
+- PHP_FE(stats_cdf_uniform, NULL)
+- PHP_FE(stats_cdf_exponential, NULL)
+- PHP_FE(stats_rand_setall, NULL)
+- PHP_FE(stats_rand_getsd, NULL)
+- PHP_FE(stats_rand_gen_iuniform, NULL)
+- PHP_FE(stats_rand_gen_funiform, NULL)
+- PHP_FE(stats_rand_ignlgi, NULL)
+- PHP_FE(stats_rand_ranf, NULL)
+- PHP_FE(stats_rand_gen_beta, NULL)
+- PHP_FE(stats_rand_gen_chisquare, NULL)
+- PHP_FE(stats_rand_gen_exponential, NULL)
+- PHP_FE(stats_rand_gen_f, NULL)
+- PHP_FE(stats_rand_gen_gamma, NULL)
+- PHP_FE(stats_rand_gen_noncentral_chisquare,NULL)
+- PHP_FE(stats_rand_gen_noncenral_f, NULL)
+- PHP_FE(stats_rand_gen_normal, NULL)
+- PHP_FE(stats_rand_phrase_to_seeds, NULL)
+- PHP_FE(stats_rand_ibinomial, NULL)
+- PHP_FE(stats_rand_ibinomial_negative,NULL)
+- PHP_FE(stats_rand_gen_ipoisson, NULL)
+- PHP_FE(stats_rand_gen_noncentral_t, NULL)
+- PHP_FE(stats_rand_gen_t, NULL)
+- PHP_FE(stats_dens_normal, NULL)
+- PHP_FE(stats_dens_cauchy, NULL)
+- PHP_FE(stats_dens_laplace, NULL)
+- PHP_FE(stats_dens_logistic, NULL)
+- PHP_FE(stats_dens_beta, NULL)
+- PHP_FE(stats_dens_weibull, NULL)
+- PHP_FE(stats_dens_uniform, NULL)
+- PHP_FE(stats_dens_chisquare, NULL)
+- PHP_FE(stats_dens_t, NULL)
+- PHP_FE(stats_dens_gamma, NULL)
+- PHP_FE(stats_dens_exponential, NULL)
+- PHP_FE(stats_dens_f, NULL)
+- PHP_FE(stats_dens_pmf_binomial, NULL)
+- PHP_FE(stats_dens_pmf_poisson, NULL)
+- PHP_FE(stats_dens_pmf_negative_binomial,NULL)
+- PHP_FE(stats_dens_pmf_hypergeometric, NULL)
+- PHP_FE(stats_stat_powersum, NULL)
+- PHP_FE(stats_stat_innerproduct, NULL)
+- PHP_FE(stats_stat_independent_t, NULL)
+- PHP_FE(stats_stat_paired_t, NULL)
+- PHP_FE(stats_stat_percentile, NULL)
+- PHP_FE(stats_stat_correlation, NULL)
+- PHP_FE(stats_stat_binomial_coef, NULL)
+- PHP_FE(stats_stat_factorial, NULL)
+- PHP_FE(stats_standard_deviation, NULL)
+- PHP_FE(stats_absolute_deviation, NULL)
+- PHP_FE(stats_variance, NULL)
+- PHP_FE(stats_harmonic_mean, NULL)
+- PHP_FE(stats_skew, NULL)
+- PHP_FE(stats_kurtosis, NULL)
+- PHP_FE(stats_covariance, NULL)
+- {NULL, NULL, NULL}
+-};
+-
+-zend_module_entry stats_module_entry = {
+- STANDARD_MODULE_HEADER,
+- "stats",
+- statistics_functions,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- PHP_MINFO(stats),
+- "1.1",
+- STANDARD_MODULE_PROPERTIES,
+-};
+-
+-#ifdef COMPILE_DL_STATS
+-ZEND_GET_MODULE(stats)
+-#endif
+-
+-
+-PHP_MINFO_FUNCTION(stats)
+-{
+- php_info_print_table_start();
+- php_info_print_table_row(2, "Statistics Support", "enabled");
+- php_info_print_table_end();
+-}
+-
+-
+-
+-/* Numbers are always smaller than strings int this function as it
+- * anyway doesn't make much sense to compare two different data types.
+- * This keeps it consistant and simple.
+- *
+- * This is not correct any more, depends on what compare_func is set to.
+- */
+-static int stats_array_data_compare(const void *a, const void *b TSRMLS_DC)
+-{
+- Bucket *f;
+- Bucket *s;
+- pval result;
+- pval *first;
+- pval *second;
+-
+- f = *((Bucket **) a);
+- s = *((Bucket **) b);
+-
+- first = *((pval **) f->pData);
+- second = *((pval **) s->pData);
+-
+- if (numeric_compare_function(&result, first, second TSRMLS_CC) == FAILURE) {
+- return 0;
+- }
+-
+- if (Z_TYPE(result) == IS_DOUBLE) {
+- if (Z_DVAL(result) < 0) {
+- return -1;
+- } else if (Z_DVAL(result) > 0) {
+- return 1;
+- } else {
+- return 0;
+- }
+- }
+-
+- convert_to_long(&result);
+-
+- if (Z_LVAL(result) < 0) {
+- return -1;
+- } else if (Z_LVAL(result) > 0) {
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-
+-
+-/**************************************/
+-/* Cumulative Distributions Functions */
+-/**************************************/
+-
+-/******************************************************
+- Cumulative Distribution Function
+- T distribution
+-
+- Function
+-
+-
+- Calculates any one parameter of the t distribution given
+- values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which argument
+- values is to be calculated from the others.
+- Legal range: 1..3
+- iwhich = 1 : Calculate P and Q from T and DF
+- iwhich = 2 : Calculate T from P,Q and DF
+- iwhich = 3 : Calculate DF from P,Q and T
+-
+- P <--> The integral from -infinity to t of the t-density.
+- Input range: (0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- T <--> Upper limit of integration of the t-density.
+- Input range: ( -infinity, +infinity).
+- Search range: [ -1E100, 1E100 ]
+-
+- DF <--> Degrees of freedom of the t-distribution.
+- Input range: (0 , +infinity).
+- Search range: [1e-100, 1E10]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.5.27 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce the computation
+- of the cumulative distribution function to that of an incomplete
+- beta.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-******************************************************/
+-
+-/* {{{ proto float stats_cdf_t(float par1, float par2, int which)
+- Calculates any one parameter of the T distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_t)
+-{
+- double arg1;
+- double arg2;
+- double df;
+- double bound;
+- double p;
+- double q;
+- double t;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddl", &arg1, &arg2, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 3) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 3 ) {
+- df = arg2;
+- } else {
+- t = arg2;
+- }
+- if (which == 1) {
+- t = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdft((int *)&which, &p, &q, &t, &df, &status, &bound);
+-
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(t);
+- case 3: RETURN_DOUBLE(df);
+- }
+- RETURN_FALSE; /* should never be reached */
+-}
+-/* }}} */
+-
+-/*********************************************************************
+- Cumulative Distribution Function NORmal distribution
+-
+- Calculates any one parameter of the normal
+- distribution given values for the others.
+-
+-
+- Arguments
+-
+-
+- WHICH --> Integer indicating which of the next parameter
+- values is to be calculated using values of the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from X,MEAN and SD
+- iwhich = 2 : Calculate X from P,Q,MEAN and SD
+- iwhich = 3 : Calculate MEAN from P,Q,X and SD
+- iwhich = 4 : Calculate SD from P,Q,X and MEAN
+-
+- P <--> The integral from -infinity to X of the normal density.
+- Input range: (0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- X < --> Upper limit of integration of the normal-density.
+- Input range: ( -infinity, +infinity)
+-
+- MEAN <--> The mean of the normal density.
+- Input range: (-infinity, +infinity)
+-
+- SD <--> Standard Deviation of the normal density.
+- Input range: (0, +infinity).
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- A slightly modified version of ANORM from
+-
+- Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN
+- Package of Special Function Routines and Test Drivers"
+- acm Transactions on Mathematical Software. 19, 22-32.
+-
+- is used to calulate the cumulative standard normal distribution.
+-
+- The rational functions from pages 90-95 of Kennedy and Gentle,
+- Statistical Computing, Marcel Dekker, NY, 1980 are used as
+- starting values to Newton's Iterations which compute the inverse
+- standard normal. Therefore no searches are necessary for any
+- parameter.
+-
+- For X < -15, the asymptotic expansion for the normal is used as
+- the starting value in finding the inverse standard normal.
+- This is formula 26.2.12 of Abramowitz and Stegun.
+-
+- Note
+-
+- The normal density is proportional to
+- exp( - 0.5 * (( X - MEAN)/SD)**2)
+-***********************************************************************/
+-
+-/* {{{ proto float stats_stat_gennch(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the normal distribution given values for thee others. */
+-PHP_FUNCTION(stats_cdf_normal)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double sd;
+- double bound;
+- double p;
+- double q;
+- double x;
+- double mean;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- sd = arg3;
+- } else {
+- mean = arg3;
+- }
+-
+- if (which < 3) {
+- mean = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfnor((int *)&which, &p, &q, &x, &mean, &sd, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(mean);
+- case 4: RETURN_DOUBLE(sd);
+- }
+- RETURN_FALSE; /* should never be reached */
+-}
+-/* }}} */
+-
+-
+-/*********************************************************************
+- Cumulative Distribution Function
+- GAMma Distribution
+-
+-
+- Function
+-
+-
+- Calculates any one parameter of the gamma
+- distribution given values for the others.
+-
+-
+- Arguments
+-
+-
+- WHICH --> Integer indicating which of the next four argument
+- values is to be calculated from the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from X,SHAPE and SCALE
+- iwhich = 2 : Calculate X from P,Q,SHAPE and SCALE
+- iwhich = 3 : Calculate SHAPE from P,Q,X and SCALE
+- iwhich = 4 : Calculate SCALE from P,Q,X and SHAPE
+-
+- P <--> The integral from 0 to X of the gamma density.
+- Input range: [0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- X <--> The upper limit of integration of the gamma density.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- SHAPE <--> The shape parameter of the gamma density.
+- Input range: (0, +infinity).
+- Search range: [1E-100,1E100]
+-
+- SCALE <--> The scale parameter of the gamma density.
+- Input range: (0, +infinity).
+- Search range: (1E-100,1E100]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+- 10 if the gamma or inverse gamma routine cannot
+- compute the answer. Usually happens only for
+- X and SHAPE very large (gt 1E10 or more)
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+-
+- Method
+-
+-
+- Cumulative distribution function (P) is calculated directly by
+- the code associated with:
+-
+- DiDinato, A. R. and Morris, A. H. Computation of the incomplete
+- gamma function ratios and their inverse. ACM Trans. Math.
+- Softw. 12 (1986), 377-393.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+-
+- Note
+-
+-
+-
+- The gamma density is proportional to
+- T**(SHAPE - 1) * EXP(- SCALE * T)
+-**************************************************************************/
+-/* {{{ proto float stats_cdf_gamma(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the gamma distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_gamma)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double bound;
+- double p;
+- double q;
+- double x;
+- double shape;
+- double scale;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- scale = arg3;
+- } else {
+- shape = arg3;
+- }
+-
+- if (which < 3) {
+- shape = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfgam((int *)&which, &p, &q, &x, &shape, &scale, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(shape);
+- case 4: RETURN_DOUBLE(scale);
+- }
+- RETURN_FALSE; /* should never be reached */
+-}
+-/* }}} */
+-
+-/*****************************************************************
+- Cumulative Distribution Function
+- CHI-Square distribution
+-
+- Function
+-
+- Calculates any one parameter of the chi-square
+- distribution given values for the others.
+-
+- Arguments
+-
+-
+- WHICH --> Integer indicating which of the next three argument
+- values is to be calculated from the others.
+- Legal range: 1..3
+- iwhich = 1 : Calculate P and Q from X and DF
+- iwhich = 2 : Calculate X from P,Q and DF
+- iwhich = 3 : Calculate DF from P,Q and X
+-
+- P <--> The integral from 0 to X of the chi-square
+- distribution.
+- Input range: [0, 1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- X <--> Upper limit of integration of the non-central
+- chi-square distribution.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- DF <--> Degrees of freedom of the
+- chi-square distribution.
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+- 10 indicates error returned from cumgam. See
+- references in cdfgam
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+-
+- Method
+-
+-
+- Formula 26.4.19 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce the chisqure
+- distribution to the incomplete distribution.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-*****************************************************************/
+-/* {{{ proto float stats_cdf_chisquare(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the chi-square distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_chisquare)
+-{
+- double arg1;
+- double arg2;
+- double bound;
+- double p;
+- double q;
+- double x;
+- double df;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddl", &arg1, &arg2, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 3) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 3 ) {
+- df = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfchi((int *)&which, &p, &q, &x, &df, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(df);
+- }
+- RETURN_FALSE; /* should never be here */
+-}
+-/* }}} */
+-
+-/*******************************************************************
+- Cumulative Distribution Function
+- BETa Distribution
+-
+- Function
+-
+- Calculates any one parameter of the beta distribution given
+- values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next four argument
+- values is to be calculated from the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from X,Y,A and B
+- iwhich = 2 : Calculate X and Y from P,Q,A and B
+- iwhich = 3 : Calculate A from P,Q,X,Y and B
+- iwhich = 4 : Calculate B from P,Q,X,Y and A
+-
+- P <--> The integral from 0 to X of the chi-square
+- distribution.
+- Input range: [0, 1].
+-
+- Q <--> 1-P.
+- Input range: [0, 1].
+- P + Q = 1.0.
+-
+- X <--> Upper limit of integration of beta density.
+- Input range: [0,1].
+- Search range: [0,1]
+-
+- Y <--> 1-X.
+- Input range: [0,1].
+- Search range: [0,1]
+- X + Y = 1.0.
+-
+- A <--> The first parameter of the beta density.
+- Input range: (0, +infinity).
+- Search range: [1D-100,1D100]
+-
+- B <--> The second parameter of the beta density.
+- Input range: (0, +infinity).
+- Search range: [1D-100,1D100]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+- 4 if X + Y .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Cumulative distribution function (P) is calculated directly by
+- code associated with the following reference.
+-
+- DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant
+- Digit Computation of the Incomplete Beta Function Ratios. ACM
+- Trans. Math. Softw. 18 (1993), 360-373.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+- Note
+-
+- The beta density is proportional to
+- t^(A-1) * (1-t)^(B-1)
+-
+-*******************************************************************/
+-
+-/* {{{ proto float stats_cdf_beta(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the beta distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_beta)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double x;
+- double bound;
+- double y;
+- double a;
+- double b;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+-
+- if (which < 4) {
+- b = arg3;
+- } else {
+- a = arg3;
+- }
+-
+- if (which < 3) {
+- a = arg2;
+- } else {
+- x = arg2;
+- y = 1.0 - x;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- y = 1.0 - x;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfbet((int *)&which, &p, &q, &x, &y, &a, &b, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(a);
+- case 4: RETURN_DOUBLE(b);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/*********************************************************************
+- Cumulative Distribution Function
+- BINomial distribution
+-
+- Function
+-
+- Calculates any one parameter of the binomial
+- distribution given values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next four argument
+- values is to be calculated from the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
+- iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
+- iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
+- iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
+-
+- P <--> The cumulation from 0 to S of the binomial distribution.
+- (Probablility of S or fewer successes in XN trials each
+- with probability of success PR.)
+- Input range: [0,1].
+-
+- Q <--> 1-P.
+- Input range: [0, 1].
+- P + Q = 1.0.
+-
+- S <--> The number of successes observed.
+- Input range: [0, XN]
+- Search range: [0, XN]
+-
+- XN <--> The number of binomial trials.
+- Input range: (0, +infinity).
+- Search range: [1E-100, 1E100]
+-
+- PR <--> The probability of success in each binomial trial.
+- Input range: [0,1].
+- Search range: [0,1]
+-
+- OMPR <--> 1-PR
+- Input range: [0,1].
+- Search range: [0,1]
+- PR + OMPR = 1.0
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+- 4 if PR + OMPR .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.5.24 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce the binomial
+- distribution to the cumulative incomplete beta distribution.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+-*********************************************************************/
+-
+-/* {{{ proto float stats_cdf_binomial(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the binomial distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_binomial)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double xn;
+- double bound;
+- double sn;
+- double pr;
+- double ompr;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+-
+- if (which < 4) {
+- pr = arg3;
+- ompr = 1.0 - pr;
+- } else {
+- xn = arg3;
+- }
+-
+- if (which < 3) {
+- xn = arg2;
+- } else {
+- sn = arg2;
+- }
+-
+- if (which == 1) {
+- sn = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfbin((int *)&which, &p, &q, &sn, &xn, &pr, &ompr, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in binomialcdf");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(sn);
+- case 3: RETURN_DOUBLE(xn);
+- case 4: RETURN_DOUBLE(pr);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/*****************************************************************
+- Cumulative Distribution Function
+- Non-central Chi-Square
+-
+- Function
+-
+- Calculates any one parameter of the non-central chi-square
+- distribution given values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next three argument
+- values is to be calculated from the others.
+- Input range: 1..4
+- iwhich = 1 : Calculate P and Q from X and DF
+- iwhich = 2 : Calculate X from P,DF and PNONC
+- iwhich = 3 : Calculate DF from P,X and PNONC
+- iwhich = 3 : Calculate PNONC from P,X and DF
+-
+- P <--> The integral from 0 to X of the non-central chi-square
+- distribution.
+- Input range: [0, 1-1E-16).
+-
+- Q <--> 1-P.
+- Q is not used by this subroutine and is only included
+- for similarity with other cdf* routines.
+-
+- X <--> Upper limit of integration of the non-central
+- chi-square distribution.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- DF <--> Degrees of freedom of the non-central
+- chi-square distribution.
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- PNONC <--> Non-centrality parameter of the non-central
+- chi-square distribution.
+- Input range: [0, +infinity).
+- Search range: [0,1E4]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.4.25 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to compute the cumulative
+- distribution function.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+- WARNING
+-
+- The computation time required for this routine is proportional
+- to the noncentrality parameter (PNONC). Very large values of
+- this parameter can consume immense computer resources. This is
+- why the search range is bounded by 10,000.
+-
+-*****************************************************************/
+-
+-/* {{{ proto float stats_cdf_noncentral_chisquare(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the non-central chi-square distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_noncentral_chisquare)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double bound;
+- double q;
+- double x;
+- double df;
+- double pnonc;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- pnonc = arg3;
+- } else {
+- df = arg3;
+- }
+-
+- if (which < 3) {
+- df = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfchn((int *)&which, &p, &q, &x, &df, &pnonc, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdfchn");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(df);
+- case 4: RETURN_DOUBLE(pnonc);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/**************************************************************
+- Cumulative Distribution Function F distribution
+-
+- Function
+-
+- Calculates any one parameter of the F distribution
+- given values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next four argument
+- values is to be calculated from the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from F,DFN and DFD
+- iwhich = 2 : Calculate F from P,Q,DFN and DFD
+- iwhich = 3 : Calculate DFN from P,Q,F and DFD
+- iwhich = 4 : Calculate DFD from P,Q,F and DFN
+-
+- P <--> The integral from 0 to F of the f-density.
+- Input range: [0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- F <--> Upper limit of integration of the f-density.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- DFN < --> Degrees of freedom of the numerator sum of squares.
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- DFD < --> Degrees of freedom of the denominator sum of squares.
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.6.2 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce the computation
+- of the cumulative distribution function for the F variate to
+- that of an incomplete beta.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+- WARNING
+-
+- The value of the cumulative F distribution is not necessarily
+- monotone in either degrees of freedom. There thus may be two
+- values that provide a given CDF value. This routine assumes
+- monotonicity and will find an arbitrary one of the two values.
+-
+-**********************************************************************/
+-/* {{{ proto float stats_cdf_f(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the F distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_f)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double bound;
+- double dfn;
+- double q;
+- double f;
+- double dfd;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+- if (which < 4) {
+- dfd = arg3;
+- } else {
+- dfn = arg3;
+- }
+- if (which < 3) {
+- dfn = arg2;
+- } else {
+- f = arg2;
+- }
+- if (which == 1) {
+- f = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdff((int *)&which, &p, &q, &f, &dfn, &dfd, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdff");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(f);
+- case 3: RETURN_DOUBLE(dfn);
+- case 4: RETURN_DOUBLE(dfd);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/***********************************************************************
+- Cumulative Distribution Function
+- Non-central F distribution
+-
+- Function
+-
+- Calculates any one parameter of the Non-central F
+- distribution given values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next five argument
+- values is to be calculated from the others.
+- Legal range: 1..5
+- iwhich = 1 : Calculate P and Q from F,DFN,DFD and PNONC
+- iwhich = 2 : Calculate F from P,Q,DFN,DFD and PNONC
+- iwhich = 3 : Calculate DFN from P,Q,F,DFD and PNONC
+- iwhich = 4 : Calculate DFD from P,Q,F,DFN and PNONC
+- iwhich = 5 : Calculate PNONC from P,Q,F,DFN and DFD
+-
+- P <--> The integral from 0 to F of the non-central f-density.
+- Input range: [0,1-1E-16).
+-
+- Q <--> 1-P.
+- Q is not used by this subroutine and is only included
+- for similarity with other cdf* routines.
+-
+- F <--> Upper limit of integration of the non-central f-density.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- DFN < --> Degrees of freedom of the numerator sum of squares.
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- DFD < --> Degrees of freedom of the denominator sum of squares.
+- Must be in range: (0, +infinity).
+- Input range: (0, +infinity).
+- Search range: [ 1E-100, 1E100]
+-
+- PNONC <-> The non-centrality parameter
+- Input range: [0,infinity)
+- Search range: [0,1E4]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.6.20 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to compute the cumulative
+- distribution function.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+- WARNING
+-
+- The computation time required for this routine is proportional
+- to the noncentrality parameter (PNONC). Very large values of
+- this parameter can consume immense computer resources. This is
+- why the search range is bounded by 10,000.
+-
+- WARNING
+-
+- The value of the cumulative noncentral F distribution is not
+- necessarily monotone in either degrees of freedom. There thus
+- may be two values that provide a given CDF value. This routine
+- assumes monotonicity and will find an arbitrary one of the two
+- values.
+-
+-***********************************************************************/
+-
+-/* {{{ proto float stats_cdf_noncentral_f(float par1, float par2, float par3, float par4, int which)
+- Calculates any one parameter of the Non-central F distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_noncentral_f)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double arg4;
+- double p;
+- double q;
+- double f;
+- double dfn;
+- double dfd;
+- double pnonc;
+- double bound;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddddl", &arg1, &arg2, &arg3, &arg4, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 5) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fifth parameter should be in the 1..5 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 5) {
+- pnonc = arg4;
+- } else {
+- dfd = arg4;
+- }
+-
+- if (which < 4) {
+- dfd = arg3;
+- } else {
+- dfn = arg3;
+- }
+-
+- if (which < 3) {
+- dfn = arg2;
+- } else {
+- f = arg2;
+- }
+-
+- if (which == 1) {
+- f = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdffnc((int *)&which, &p, &q, &f, &dfn, &dfd, &pnonc, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdffnc");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(f);
+- case 3: RETURN_DOUBLE(dfn);
+- case 4: RETURN_DOUBLE(dfd);
+- case 5: RETURN_DOUBLE(pnonc);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/************************************************************************
+- Cumulative Distribution Function Non-Central T distribution
+-
+- Function
+-
+- Calculates any one parameter of the noncentral t distribution give
+- values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which argument
+- values is to be calculated from the others.
+- Legal range: 1..3
+- iwhich = 1 : Calculate P and Q from T,DF,PNONC
+- iwhich = 2 : Calculate T from P,Q,DF,PNONC
+- iwhich = 3 : Calculate DF from P,Q,T
+- iwhich = 4 : Calculate PNONC from P,Q,DF,T
+-
+- P <--> The integral from -infinity to t of the noncentral t-den
+- Input range: (0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- T <--> Upper limit of integration of the noncentral t-density.
+- Input range: ( -infinity, +infinity).
+- Search range: [ -1E100, 1E100 ]
+-
+- DF <--> Degrees of freedom of the noncentral t-distribution.
+- Input range: (0 , +infinity).
+- Search range: [1e-100, 1E10]
+-
+- PNONC <--> Noncentrality parameter of the noncentral t-distributio
+- Input range: [-infinity , +infinity).
+- Search range: [-1e4, 1E4]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Upper tail of the cumulative noncentral t is calculated usin
+- formulae from page 532 of Johnson, Kotz, Balakrishnan, Coninuou
+- Univariate Distributions, Vol 2, 2nd Edition. Wiley (1995)
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+-************************************************************************/
+-
+-/* {{{ proto float stats_stat_noncentral_t(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the noncentral t distribution give values for the others. */
+-PHP_FUNCTION(stats_cdf_noncentral_t)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double pnonc;
+- double bound;
+- double p;
+- double q;
+- double t;
+- double df;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- pnonc = arg3;
+- } else {
+- df = arg3;
+- }
+- if (which < 3) {
+- df = arg2;
+- } else {
+- t = arg2;
+- }
+-
+- if (which == 1) {
+- t = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdftnc((int *)&which, &p, &q, &t, &df, &pnonc, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(t);
+- case 3: RETURN_DOUBLE(df);
+- case 4: RETURN_DOUBLE(pnonc);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/************************************************************************
+- Cumulative Distribution Function Negative BiNomial distribution
+-
+- Function
+-
+- Calculates any one parameter of the negative binomial
+- distribution given values for the others.
+-
+- The cumulative negative binomial distribution returns the
+- probability that there will be F or fewer failures before the
+- XNth success in binomial trials each of which has probability of
+- success PR.
+-
+- The individual term of the negative binomial is the probability of
+- S failures before XN successes and is
+- Choose( S, XN+S-1 ) * PR^(XN) * (1-PR)^S
+-
+- Arguments
+-
+- WHICH --> Integer indicating which of the next four argument
+- values is to be calculated from the others.
+- Legal range: 1..4
+- iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
+- iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
+- iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
+- iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
+-
+- P <--> The cumulation from 0 to S of the negative
+- binomial distribution.
+- Input range: [0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- S <--> The upper limit of cumulation of the binomial distribution.
+- There are F or fewer failures before the XNth success.
+- Input range: [0, +infinity).
+- Search range: [0, 1E100]
+-
+- XN <--> The number of successes.
+- Input range: [0, +infinity).
+- Search range: [0, 1E100]
+-
+- PR <--> The probability of success in each binomial trial.
+- Input range: [0,1].
+- Search range: [0,1].
+-
+- OMPR <--> 1-PR
+- Input range: [0,1].
+- Search range: [0,1]
+- PR + OMPR = 1.0
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+- 4 if PR + OMPR .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.5.26 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce calculation of
+- the cumulative distribution function to that of an incomplete
+- beta.
+-
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+-************************************************************************/
+-
+-/* {{{ proto float stats_cdf_negative_binomial(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the negative binomial distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_negative_binomial)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double bound;
+- double sn;
+- double xn;
+- double pr;
+- double ompr;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- pr = arg3;
+- ompr = 1.0 - pr;
+- } else {
+- xn = arg3;
+- }
+-
+- if (which < 3) {
+- xn = arg2;
+- } else {
+- sn = arg2;
+- }
+-
+- if (which == 1) {
+- sn = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfnbn((int *)&which, &p, &q, &sn, &xn, &pr, &ompr, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error in cdfnbn");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(sn);
+- case 3: RETURN_DOUBLE(xn);
+- case 4: RETURN_DOUBLE(pr);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/**********************************************************************
+- Cumulative Distribution Function POIsson distribution
+-
+- Function
+-
+- Calculates any one parameter of the Poisson
+- distribution given values for the others.
+-
+- Arguments
+-
+- WHICH --> Integer indicating which argument
+- value is to be calculated from the others.
+- Legal range: 1..3
+- iwhich = 1 : Calculate P and Q from S and XLAM
+- iwhich = 2 : Calculate A from P,Q and XLAM
+- iwhich = 3 : Calculate XLAM from P,Q and S
+-
+- P <--> The cumulation from 0 to S of the poisson density.
+- Input range: [0,1].
+-
+- Q <--> 1-P.
+- Input range: (0, 1].
+- P + Q = 1.0.
+-
+- S <--> Upper limit of cumulation of the Poisson.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- XLAM <--> Mean of the Poisson distribution.
+- Input range: [0, +infinity).
+- Search range: [0,1E100]
+-
+- STATUS <-- 0 if calculation completed correctly
+- -I if input parameter number I is out of range
+- 1 if answer appears to be lower than lowest
+- search bound
+- 2 if answer appears to be higher than greatest
+- search bound
+- 3 if P + Q .ne. 1
+-
+- BOUND <-- Undefined if STATUS is 0
+-
+- Bound exceeded by parameter number I if STATUS
+- is negative.
+-
+- Lower search bound if STATUS is 1.
+-
+- Upper search bound if STATUS is 2.
+-
+- Method
+-
+- Formula 26.4.21 of Abramowitz and Stegun, Handbook of
+- Mathematical Functions (1966) is used to reduce the computation
+- of the cumulative distribution function to that of computing a
+- chi-square, hence an incomplete gamma function.
+-
+- Cumulative distribution function (P) is calculated directly.
+- Computation of other parameters involve a seach for a value that
+- produces the desired value of P. The search relies on the
+- monotinicity of P with the other parameter.
+-
+-**********************************************************************/
+-
+-/* {{{ proto float stats_cdf_poisson(float par1, float par2, float par3, int which)
+- Calculates any one parameter of the Poisson distribution given values for the others. */
+-PHP_FUNCTION(stats_cdf_poisson)
+-{
+- double arg1;
+- double arg2;
+- double p;
+- double q;
+- double x;
+- double xlam;
+- double bound;
+- long which;
+- int status = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddl", &arg1, &arg2, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 3) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 3 ) {
+- xlam = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- cdfpoi((int *)&which, &p, &q, &x, &xlam, &status, &bound);
+- if (status != 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Computation Error");
+- RETURN_FALSE;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(xlam);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-
+-static double laplace_quantile(double p)
+-{
+- if (p <= 0.5) {
+- return log(2.0*p);
+- } else {
+- return (-log(2.0*(1.0-p)));
+- }
+-}
+-
+-static double laplace_cdf(double x)
+-{
+- if (x <= 0) {
+- return (0.5*exp(x));
+- } else {
+- return (1.0 - 0.5*exp(-x));
+- }
+-}
+-
+-
+-/* {{{ proto float stats_cdf_laplace(float par1, float par2, float par3, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_laplace)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double x;
+- double t;
+- double mean;
+- double sd;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- sd = arg3;
+- } else {
+- mean = arg3;
+- }
+-
+- if (which < 3) {
+- mean = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- if (which == 1) {
+- t = (x - mean) / sd;
+- p = laplace_cdf(t);
+- } else {
+- t = laplace_quantile(p);
+- }
+-
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(mean + (sd * t));
+- case 3: RETURN_DOUBLE(x - (sd * t));
+- case 4: RETURN_DOUBLE((x - mean) / t);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-static double cauchy_quantile(double p)
+-{
+- return (tan(STATS_PI*(p-0.5)));
+-}
+-
+-static double cauchy_cdf (double x)
+-{
+- return (0.5+(atan(x)/STATS_PI));
+-}
+-
+-/* {{{ proto float stats_cdf_cauchy(float par1, float par2, float par3, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_cauchy)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double x;
+- double t;
+- double mean;
+- double sd;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- sd = arg3;
+- } else {
+- mean = arg3;
+- }
+-
+- if (which < 3) {
+- mean = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- if (which == 1) {
+- t = (x - mean) / sd;
+- p = cauchy_cdf(t);
+- } else {
+- t = cauchy_quantile(p);
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(mean + (sd * t));
+- case 3: RETURN_DOUBLE(x - (sd * t));
+- case 4: RETURN_DOUBLE((x - mean) / t);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-static double logistic_cdf(double x)
+-{
+- return (1.0/(1.0+exp(-x)));
+-}
+-
+-static double logistic_quantile (double p)
+-{
+- return (log(p/(1.0-p)));
+-}
+-
+-/* {{{ proto float stats_cdf_logistic(float par1, float par2, float par3, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_logistic)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double sd;
+- double p;
+- double q;
+- double x;
+- double t;
+- double mean;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- sd = arg3;
+- } else {
+- mean = arg3;
+- }
+-
+- if (which < 3) {
+- mean = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- if (which == 1) {
+- t = (x - mean) / sd;
+- p = logistic_cdf(t);
+- } else {
+- t = logistic_quantile(p);
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(mean + (sd * t));
+- case 3: RETURN_DOUBLE(x - (sd * t));
+- case 4: RETURN_DOUBLE((x - mean) / t);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_cdf_weibull(float par1, float par2, float par3, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_weibull)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double x;
+- double a;
+- double b;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- b = arg3;
+- } else {
+- a = arg3;
+- }
+-
+- if (which < 3) {
+- a = arg2;
+- } else {
+- x = arg2;
+- }
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- if (which == 1) {
+- p = 1 - exp(-pow(x / b, a));
+- } else {
+- x = b * pow(-log(1.0 - p), 1.0 / a);
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(p);
+- case 2: RETURN_DOUBLE(x);
+- case 3: RETURN_DOUBLE(log(-log(1.0 - p)) / log(x / b));
+- case 4: RETURN_DOUBLE(x / pow(-log(1.0 - p), 1.0 / a));
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_cdf_uniform(float par1, float par2, float par3, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_uniform)
+-{
+- double arg1;
+- double arg2;
+- double arg3;
+- double p;
+- double q;
+- double x;
+- double a;
+- double b;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dddl", &arg1, &arg2, &arg3, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 4) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Fourth parameter should be in the 1..4 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 4) {
+- b = arg3;
+- } else {
+- a = arg3;
+- }
+-
+- if (which < 3) {
+- a = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- if (which == 1) {
+- p = 1 - exp(-pow(x / b, a));
+- } else {
+- x = b * pow(-log(1.0 - p), 1.0 / a);
+- }
+-
+- switch (which) {
+- case 4: RETURN_DOUBLE((x - (1.0 - p) * a) / p);
+- case 3: RETURN_DOUBLE((x - p * b) / (1.0 - p));
+- case 2: RETURN_DOUBLE(a + p * (b - a));
+- case 1:
+- if (x < a) {
+- p = 0;
+- } else {
+- if (x > b) {
+- p = 1;
+- } else {
+- p = (x - a) / ( b - a);
+- }
+- }
+- RETURN_DOUBLE(p);
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-static double exponential_quantile(double p)
+-{
+- return -log(1.0-p);
+-}
+-
+-static double exponential_cdf(double x)
+-{
+- return (1.0 - exp(-x));
+-}
+-
+-/* {{{ proto float stats_cdf_exponential(float par1, float par2, int which)
+- Not documented */
+-PHP_FUNCTION(stats_cdf_exponential)
+-{
+- double arg1;
+- double arg2;
+- double p;
+- double q;
+- double x;
+- double scale;
+- long which;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddl", &arg1, &arg2, &which) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (which < 1 || which > 3) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Third parameter should be in the 1..3 range");
+- RETURN_FALSE;
+- }
+-
+- if (which < 3) {
+- scale = arg2;
+- } else {
+- x = arg2;
+- }
+-
+- if (which == 1) {
+- x = arg1;
+- } else {
+- p = arg1;
+- q = 1.0 - p;
+- }
+-
+- switch (which) {
+- case 1: RETURN_DOUBLE(exponential_cdf(x / scale));
+- case 2: RETURN_DOUBLE(scale * exponential_quantile(p));
+- case 3: RETURN_DOUBLE(x / exponential_quantile(p));
+- }
+- RETURN_FALSE; /* never here */
+-}
+-/* }}} */
+-
+-
+-/*********************/
+-/* RANDLIB functions */
+-/*********************/
+-
+-/* {{{ proto void stats_rand_setall(int iseed1, int iseed2)
+- Not documented */
+-PHP_FUNCTION(stats_rand_setall)
+-{
+- long iseed_1;
+- long iseed_2;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &iseed_1, &iseed_2) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- setall(iseed_1, iseed_2);
+-}
+-/* }}} */
+-
+-/* {{{ proto array stats_rand_get_seeds(void)
+- Not documented */
+-PHP_FUNCTION(stats_rand_getsd)
+-{
+- long iseed_1;
+- long iseed_2;
+-
+- if (ZEND_NUM_ARGS() != 0) {
+- WRONG_PARAM_COUNT;
+- }
+- getsd(&iseed_1, &iseed_2);
+-
+- array_init(return_value);
+- add_next_index_long(return_value, iseed_1);
+- add_next_index_long(return_value, iseed_2);
+-}
+-/* }}} */
+-
+-/* {{{ proto int stats_rand_gen_iuniform(int low, int high)
+- Generates integer uniformly distributed between LOW (inclusive) and HIGH (inclusive) */
+-PHP_FUNCTION(stats_rand_gen_iuniform)
+-{
+- long low;
+- long high;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &low, &high) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (high - low > 2147483561L) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "high - low too large. low : %16ld high %16ld", low, high);
+- RETURN_FALSE;
+- }
+- if (low > high) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "low greater than high. low : %16ld high %16ld", low, high);
+- RETURN_FALSE;
+- }
+-
+- RETURN_LONG(ignuin(low, high));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_funiform(float low, float high)
+- Generates uniform float between low (exclusive) and high (exclusive) */
+-PHP_FUNCTION(stats_rand_gen_funiform)
+-{
+- double low;
+- double high;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &low, &high) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (low > high) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "low greater than high. low : %16.6E high : %16.6E", low, high);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(genunf(low, high));
+-}
+-/* }}} */
+-
+-/* {{{ proto int stats_rand_gen_int(void)
+- Generates random integer between 1 and 2147483562 */
+-PHP_FUNCTION(stats_rand_ignlgi)
+-{
+- if (ZEND_NUM_ARGS() != 0) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- RETURN_LONG(ignlgi());
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_ranf(void)
+- Returns a random floating point number from a uniform distribution over 0 - 1 (endpoints of this interval are not returned) using the current generator */
+-PHP_FUNCTION(stats_rand_ranf)
+-{
+- if (ZEND_NUM_ARGS() != 0) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- RETURN_DOUBLE(ranf());
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_beta(float a, float b)
+- Generates beta random deviate. Returns a random deviate from the beta distribution with parameters A and B. The density of the beta is x^(a-1) * (1-x)^(b-1) / B(a,b) for 0<x<1. aa - first parameter of the beta distribution. bb - second parameter of the beta distribution. Method R. C. H. Cheng */
+-PHP_FUNCTION(stats_rand_gen_beta)
+-{
+- double a;
+- double b;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &a, &b) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (a < 1.0E-37 || b < 1.0E-37) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "'a' or 'b' lower than 1.0E-37. 'a' value : %16.6E 'b' value : %16.6E", a, b);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(genbet(a, b));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_chisquare(float df)
+- Generates random deviate from the distribution of a chisquare with "df" degrees of freedom random variable. */
+-PHP_FUNCTION(stats_rand_gen_chisquare)
+-{
+- double df;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &df) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (df <= 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0.0. df : %16.6E", df);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(genchi(df));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_exponential(float av)
+- Generates a single random deviate from an exponential distribution with mean "av" */
+-PHP_FUNCTION(stats_rand_gen_exponential)
+-{
+- double av;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &av) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (av < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "av < 0.0");
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(genexp(av));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_f(float dfn, float dfd)
+- Generates a random deviate from the F (variance ratio) distribution with "dfn" degrees of freedom in the numerator and "dfd" degrees of freedom in the denominator. Method : directly generates ratio of chisquare variates*/
+-PHP_FUNCTION(stats_rand_gen_f)
+-{
+- double dfn;
+- double dfd;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &dfn, &dfd) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (dfn < 0.0 || dfd < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Degrees of freedom nonpositive. DFN value:%16.6E DFD value:%16.6E", dfn, dfd);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(genf(dfn, dfd));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_gamma(float a, float r)
+- Generates random deviates from the gamma distribution whose density is (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X). Parameters : a - location parameter of Gamma distribution (a > 0), r - shape parameter of Gamma distribution (r > 0) */
+-PHP_FUNCTION(stats_rand_gen_gamma)
+-{
+- double a;
+- double r;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &a, &r) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (!(a > 0.0 && r > 0.0)) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "A or R nonpositive. A value : %16.6E , R value : %16.6E", a, r);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gengam(a, r));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_noncenral_chisquare(float df, float xnonc)
+- Generates random deviate from the distribution of a noncentral chisquare with "df" degrees of freedom and noncentrality parameter "xnonc". d must be >= 1.0, xnonc must >= 0.0 */
+-PHP_FUNCTION(stats_rand_gen_noncentral_chisquare)
+-{
+- double df;
+- double xnonc;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &df, &xnonc) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (df < 1.0 || xnonc < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "df < 1 or xnonc < 0. df value : %16.6E xnonc value : %16.6E", df, xnonc);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gennch(df, xnonc));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_noncentral_f(float dfn, float dfd, float xnonc)
+- Generates a random deviate from the noncentral F (variance ratio) distribution with "dfn" degrees of freedom in the numerator, and "dfd" degrees of freedom in the denominator, and noncentrality parameter "xnonc". Method : directly generates ratio of noncentral numerator chisquare variate to central denominator chisquare variate. */
+-PHP_FUNCTION(stats_rand_gen_noncenral_f)
+-{
+- double dfn;
+- double dfd;
+- double xnonc;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &dfn, &dfd, &xnonc) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (dfn < 1.0 || dfd <= 0.0 || xnonc < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Either (1) Numerator df < 1.0 or (2) Denominator df <= 0.0 or (3) Noncentrality parameter < 0.0. dfn: %16.6E dfd: %16.6E xnonc: %16.6E", dfn, dfd, xnonc);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gennf(dfn, dfd, xnonc));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_normal(float av, float sd)
+- Generates a single random deviate from a normal distribution with mean, av, and standard deviation, sd (sd >= 0). Method : Renames SNORM from TOMS as slightly modified by BWB to use RANF instead of SUNIF. */
+-PHP_FUNCTION(stats_rand_gen_normal)
+-{
+- double av;
+- double sd;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &av, &sd) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (sd < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "sd < 0.0 . sd : %16.6E", sd);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gennor(av, sd));
+-}
+-/* }}} */
+-
+-/* {{{ proto array stats_rand_phrase_to_seeds(string phrase)
+- Uses a phrase (characted string) to generate two seeds for the RGN random number generator. Trailing blanks are eliminated before the seeds are generated. Generated seed values will fall in the range 1..2^30. */
+-PHP_FUNCTION(stats_rand_phrase_to_seeds)
+-{
+- zval **par1;
+- char *arg1 = NULL;
+- long seed_1;
+- long seed_2;
+-
+- if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &par1) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+- convert_to_string_ex(par1);
+-
+- arg1 = estrndup(Z_STRVAL_PP(par1), Z_STRLEN_PP(par1));
+- phrtsd(arg1, &seed_1, &seed_2);
+- efree(arg1);
+-
+- array_init(return_value);
+- add_next_index_long(return_value, seed_1);
+- add_next_index_long(return_value, seed_2);
+-}
+-/* }}} */
+-
+-/* {{{ proto int stats_rand_gen_ibinomial(int n, float pp)
+- Generates a single random deviate from a binomial distribution whose number of trials is "n" (n >= 0) and whose probability of an event in each trial is "pp" ([0;1]). Method : algorithm BTPE */
+-PHP_FUNCTION(stats_rand_ibinomial)
+-{
+- long n;
+- double pp;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &n, &pp) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if ((n < 0) || (pp < 0.0) || (pp > 1.0)) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad values for the arguments. n : %ld pp : %16.6E", n, pp);
+- RETURN_FALSE;
+- }
+-
+- RETURN_LONG(ignbin(n, pp));
+-}
+-/* }}} */
+-
+-/* {{{ proto int stats_rand_gen_ibinomial_negative(int n, float p)
+- Generates a single random deviate from a negative binomial distribution. Arguments : n - the number of trials in the negative binomial distribution from which a random deviate is to be generated (n > 0), p - the probability of an event (0 < p < 1)). */
+-PHP_FUNCTION(stats_rand_ibinomial_negative)
+-{
+- long n;
+- double p;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &n, &p) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (n <= 0L) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "n < 0. n : %ld", n);
+- RETURN_FALSE;
+- }
+- if (p < 0.0F || p > 1.0F) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "p is out of range. p : %16.E", p);
+- RETURN_FALSE;
+- }
+-
+- RETURN_LONG(ignnbn(n, p));
+-}
+-/* }}} */
+-
+-/* {{{ proto int stats_rand_gen_ipoisson(float mu)
+- Generates a single random deviate from a Poisson distribution with mean "mu" (mu >= 0.0). */
+-PHP_FUNCTION(stats_rand_gen_ipoisson)
+-{
+- double mu;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &mu) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (mu < 0.0F) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "mu < 0.0 . mu : %16.6E", mu);
+- RETURN_FALSE;
+- }
+-
+- RETURN_LONG(ignpoi(mu));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_noncentral_t(float df, float xnonc)
+- Generates a single random deviate from a noncentral T distribution. xnonc - noncentrality parameter. df must be >= 0.0*/
+-PHP_FUNCTION(stats_rand_gen_noncentral_t)
+-{
+- double df;
+- double xnonc;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &df, &xnonc) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (df < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0 . df : %16.6E", df);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gennor(xnonc, 1) / sqrt(genchi(df) / df) );
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_rand_gen_t(float df)
+- Generates a single random deviate from a T distribution. df must be >= 0.0 */
+-PHP_FUNCTION(stats_rand_gen_t)
+-{
+- zval **arg1;
+- double df;
+-
+- if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- convert_to_double_ex(arg1);
+- df = Z_DVAL_PP(arg1);
+-
+- if (df < 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "df <= 0 . df : %16.6E", df);
+- RETURN_FALSE;
+- }
+-
+- RETURN_DOUBLE(gennor(0, 1) / sqrt(genchi(df) / df));
+-}
+-/* }}} */
+-
+-/***************************/
+-/* Start density functions */
+-/***************************/
+-
+-/* {{{ proto float stats_dens_normal(float x, float ave, float stdev)
+- Not documented */
+-PHP_FUNCTION(stats_dens_normal)
+-{
+- double stdev;
+- double ave;
+- double x;
+- double y;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &ave, &stdev) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (stdev == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
+- RETURN_FALSE;
+- }
+-
+- z = (x - ave) / stdev;
+- y = (1.0 / (stdev * sqrt(2.0 * STATS_PI))) * exp (-0.5 * z * z);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_cauchy(float x, float ave, float stdev)
+- Not documented */
+-PHP_FUNCTION(stats_dens_cauchy)
+-{
+- double stdev;
+- double ave;
+- double x;
+- double y;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &ave, &stdev) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (stdev == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
+- RETURN_FALSE;
+- }
+-
+- z = (x - ave) / stdev;
+- y = 1.0 / (stdev*STATS_PI * (1.0 + (z * z)));
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_laplace(float x, float ave, float stdev)
+- Not documented */
+-PHP_FUNCTION(stats_dens_laplace)
+-{
+- double stdev;
+- double ave;
+- double x;
+- double y;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &ave, &stdev) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (stdev == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
+- RETURN_FALSE;
+- }
+-
+- z = fabs((x - ave) / stdev);
+- y = (1.0 / (2.0 * stdev)) * exp(- z);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_logistic(float x, float ave, float stdev)
+- Not documented */
+-PHP_FUNCTION(stats_dens_logistic)
+-{
+- double stdev;
+- double ave;
+- double x;
+- double y;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &ave, &stdev) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (stdev == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "stdev is 0.0");
+- RETURN_FALSE;
+- }
+-
+- z = exp((x - ave) / stdev);
+- y = z / (stdev * pow(1 + z, 2.0));
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_beta(float x, float a, float b)
+- Not documented */
+-PHP_FUNCTION(stats_dens_beta)
+-{
+- double a;
+- double b;
+- double beta;
+- double x;
+- double y;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &a, &b) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- beta = 1.0 / exp(lgamma(a) + lgamma(b) - lgamma(a + b));
+- y = beta * pow(x, a - 1.0) * pow(1.0 - x, b - 1.0);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_weibull(float x, float a, float b)
+- Not documented */
+-PHP_FUNCTION(stats_dens_weibull)
+-{
+- double a;
+- double b;
+- double x;
+- double y;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &a, &b) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (b == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "b is 0.0");
+- RETURN_FALSE;
+- }
+-
+- y = (a / b) * pow(x / b, a - 1.0) * exp(pow(- x / b, a));
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_den_uniform(float x, float a, float b)
+- Not documented */
+-PHP_FUNCTION(stats_dens_uniform)
+-{
+- double a;
+- double b;
+- double x;
+- double y;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &a, &b) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (a == b) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "b == a == %16.6E", a);
+- RETURN_FALSE;
+- }
+-
+- if ((x <= b) && (x >= a)) {
+- y = 1.0 / (b - a);
+- } else {
+- y = 0.0;
+- }
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_chisquare(float x, float dfr)
+- Not documented */
+-PHP_FUNCTION(stats_dens_chisquare)
+-{
+- double dfr;
+- double e;
+- double x;
+- double y;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "dd", &x, &dfr) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- e = dfr / 2.0;
+- z = ((e - 1.0) * log(x)) - ((x / 2.0) +(e * log(2.0)) + lgamma(e));
+- y = exp (z);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_t(float x, float dfr)
+- Not documented */
+-PHP_FUNCTION(stats_dens_t)
+-{
+- double dfr;
+- double e;
+- double f;
+- double fac1;
+- double fac2;
+- double fac3;
+- double x;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &dfr) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (dfr == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "dfr == 0.0");
+- RETURN_FALSE;
+- }
+-
+- e = dfr / 2.0;
+- f = e + 0.5;
+- fac1 = lgamma(f);
+- fac2 = f * log(1.0 + (x * x) / dfr);
+- fac3 = lgamma(e) + 0.5 * log(dfr * STATS_PI);
+-
+- RETURN_DOUBLE(exp( fac1 - (fac2 + fac3) ));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_gamma(float x, float shape, float scale)
+- Not documented */
+-PHP_FUNCTION(stats_dens_gamma)
+-{
+- double shape;
+- double scale;
+- double x;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &shape, &scale) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (scale == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "scale == 0.0");
+- RETURN_FALSE;
+- }
+-
+- z = ((shape - 1.0) * log(x)) -
+- (
+- (x / scale) + lgamma(shape) + (shape * log(scale))
+- )
+- ;
+-
+- RETURN_DOUBLE(exp(z));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_exponential(float x, float scale)
+- Not documented */
+-PHP_FUNCTION(stats_dens_exponential)
+-{
+- double scale;
+- double x;
+- double y;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &scale) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if (scale == 0.0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "scale == 0.0");
+- RETURN_FALSE;
+- }
+-
+- if (x < 0) {
+- y = 0;
+- } else {
+- y = exp(-x / scale) / scale;
+- }
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_f(float x, float dfr1, float dfr2)
+- */
+-PHP_FUNCTION(stats_dens_f)
+-{
+- double dfr1;
+- double dfr2;
+- double efr1;
+- double efr2;
+- double fac1;
+- double fac2;
+- double fac3;
+- double fac4;
+- double x;
+- double z;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &dfr1, &dfr2) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- efr1 = dfr1 / 2.0;
+- efr2 = dfr2 / 2.0;
+- fac1 = (efr1 - 1.0) * log (x);
+- fac2 = (efr1 + efr2) * log (dfr2 + (dfr1 * x));
+- fac3 = (efr1 * log (dfr1)) + (efr2 * log (dfr2));
+- fac4 = lgamma (efr1) + lgamma (efr2) - lgamma (efr1 + efr2);
+-
+- z = (fac1 + fac3) - (fac2 + fac4);
+-
+- RETURN_DOUBLE(exp(z));
+-}
+-/* }}} */
+-
+-static double binom(double x, double n)
+-{
+- int i;
+- double di;
+- double s = 1.0;
+-
+- for (i = 0; i < x; ++i) {
+- di = (double) i;
+- s = (s * (n - di)) / (di + 1.0);
+- }
+-
+- return s;
+-}
+-
+-/* {{{ proto float stats_dens_pmf_binomial(float x, float n, float pi)
+- Not documented */
+-PHP_FUNCTION(stats_dens_pmf_binomial)
+-{
+- double pi;
+- double y;
+- double n;
+- double x;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
+- "ddd", &x, &n, &pi) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if ((x == 0.0 && n == 0.0) || (pi == 0.0 && x == 0.0)
+- || ( (1.0 - pi) == 0.0 && (n - x) == 0) ) {
+-
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Params leading to pow(0, 0). x:%16.6E n:%16.6E pi:%16.6E", x, n, pi);
+- RETURN_FALSE;
+- }
+-
+- y = binom(x,n) * pow(pi,x) * pow((1.0 - pi), (n - x));
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_pmf_poisson(float x, float lb)
+- Not documented */
+-PHP_FUNCTION(stats_dens_pmf_poisson)
+-{
+- double lb;
+- double z;
+- double x;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &lb) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- z = (x * log(lb)) - (lb + lgamma(x + 1.0));
+-
+- RETURN_DOUBLE(exp(z));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_negative_binomial(float x, float n, float pi)
+- Not documented */
+-PHP_FUNCTION(stats_dens_pmf_negative_binomial)
+-{
+- double pi;
+- double y;
+- double n;
+- double x;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &n, &pi) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if ((pi == 0.0 && n == 0.0) || ((1.0 - pi) == 0.0 && x == 0.0)) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Params leading to pow(0, 0). x:%16.6E n:%16.6E pi:%16.6E", x, n, pi);
+- RETURN_FALSE;
+- }
+-
+- y = binom(x, n + x - 1.0) * pow(pi,n) * pow((1.0 - pi), x);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_dens_pmf_hypergeometric(float n1, float n2, float N1, float N2)
+- */
+-PHP_FUNCTION(stats_dens_pmf_hypergeometric)
+-{
+- double y;
+- double N1;
+- double N2;
+- double n1;
+- double n2;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &n1, &n2, &N1, &N2) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- if ((int)(n1 + n2) >= (int)(N1 + N2)) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "possible division by zero - n1+n2 >= N1+N2");
+- /* RETURN_FALSE; */
+- }
+-
+- y = binom(n1, N1) * binom (n2, N2)/binom(n1 + n2, N1 + N2);
+-
+- RETURN_DOUBLE(y);
+-}
+-/* }}} */
+-
+-/************************/
+-/* Statistics functions */
+-/************************/
+-
+-/* {{{ proto float stats_stat_powersum(array arr, float power)
+- Not documented */
+-PHP_FUNCTION(stats_stat_powersum)
+-{
+- zval **arg1, **arg2, **data; /* pointer to array entry */
+- HashPosition pos; /* hash iterator */
+- double power;
+- double sum = 0.0;
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- convert_to_array_ex(arg1);
+- convert_to_double_ex(arg2);
+- power = Z_DVAL_PP(arg2);
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data, &pos) == SUCCESS) {
+- convert_to_double_ex(data);
+- if (Z_DVAL_PP(data) != 0 && power != 0) {
+- sum += pow (Z_DVAL_PP(data), power);
+- } else {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both value and power are zero");
+- }
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos);
+- }
+-
+- RETURN_DOUBLE(sum);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_innerproduct(array arr1, array arr2)
+- */
+-PHP_FUNCTION(stats_stat_innerproduct)
+-{
+- zval **arg1, **arg2;
+- zval **data1, **data2; /* pointers to array entries */
+- HashPosition pos1; /* hash iterator */
+- HashPosition pos2; /* hash iterator */
+- double sum = 0.0;
+-
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+- convert_to_array_ex(arg1);
+- convert_to_array_ex(arg2);
+-
+- if (zend_hash_num_elements(Z_ARRVAL_PP(arg1)) != zend_hash_num_elements(Z_ARRVAL_PP(arg2))) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
+- RETURN_FALSE;
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
+- && zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
+- convert_to_double_ex(data1);
+- convert_to_double_ex(data2);
+- sum = Z_DVAL_PP(data1) * Z_DVAL_PP(data2);
+-
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
+- }
+-
+- RETURN_DOUBLE(sum);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_independent_t(array arr1, array arr2)
+- Not documented */
+-PHP_FUNCTION(stats_stat_independent_t)
+-{
+- zval **arg1, **arg2;
+- zval **data1, **data2; /* pointers to array entries */
+- HashPosition pos1; /* hash iterator */
+- HashPosition pos2; /* hash iterator */
+- int xnum = 0, ynum = 0;
+- double cur;
+- double sx = 0.0;
+- double sxx = 0.0;
+- double sy = 0.0;
+- double syy = 0.0;
+- double mx;
+- double vx;
+- double my;
+- double vy;
+- double sp;
+- double fc;
+- double ts;
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+- convert_to_array_ex(arg1);
+- convert_to_array_ex(arg2);
+-
+- xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
+- ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
+- if ( xnum < 2 || ynum < 2) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each argument should have more than 1 element");
+- RETURN_FALSE;
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
+- convert_to_double_ex(data1);
+- cur = Z_DVAL_PP(data1);
+- sx += cur;
+- sxx += cur * cur;
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
+- convert_to_double_ex(data2);
+- cur = Z_DVAL_PP(data2);
+- sy += cur;
+- syy += cur * cur;
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
+- }
+-
+- mx = sx / xnum;
+- my = sy / ynum;
+- vx = (sxx - (xnum * mx * mx)) / (xnum - 1.0);
+- vy = (syy - (ynum * my * my)) / (ynum - 1.0);
+- sp = (((xnum - 1.0) * vx) + ((ynum - 1.0) * vy)) / (xnum + ynum - 2.0);
+- fc = (1.0 / xnum) + (1.0 / ynum);
+- ts = (mx - my) / sqrt(sp * fc);
+-
+- RETURN_DOUBLE(ts);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_paired_t(array arr1, array arr2)
+- Not documented */
+-PHP_FUNCTION(stats_stat_paired_t)
+-{
+- zval **arg1, **arg2, **data1, **data2; /* pointers to array entries */
+- HashPosition pos1; /* hash iterator */
+- HashPosition pos2; /* hash iterator */
+- int xnum = 0;
+- int ynum = 0;
+- double sd = 0.0;
+- double sdd = 0.0;
+- double md;
+- double td;
+- double ts;
+- double cur;
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+- convert_to_array_ex(arg1);
+- convert_to_array_ex(arg2);
+-
+- xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
+- ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
+-
+- if (xnum != ynum) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
+- RETURN_FALSE;
+- }
+- if (xnum < 2) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "arr1 should have atleast 2 elements");
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
+- &&
+- zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
+- convert_to_double_ex(data1);
+- convert_to_double_ex(data2);
+-
+- cur = Z_DVAL_PP(data1) - Z_DVAL_PP(data2);
+- sd += cur;
+- sdd += cur * cur;
+-
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
+- }
+-
+- md = sd / xnum;
+- td = sqrt((sdd - (xnum * md * md)) / (xnum - 1.0));
+- ts = sqrt((double) xnum) * (md / td);
+-
+- RETURN_DOUBLE(ts);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_percentile(float df, float xnonc)
+- Not documented */
+-PHP_FUNCTION(stats_stat_percentile)
+-{
+- zval **arg1, **arg2;
+- zval **data1; /* pointers to array entries */
+- HashPosition pos1; /* hash iterator */
+- long ilow;
+- long iupp;
+- int xnum = 0;
+- int cnt = -1;
+- double perc;
+- double low;
+- double upp;
+- double val = 0.0;
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- convert_to_array_ex(arg1);
+- convert_to_double_ex(arg2);
+- perc = Z_DVAL_PP(arg2);
+-
+- xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
+-
+- if (zend_hash_sort(Z_ARRVAL_PP(arg1), zend_qsort, stats_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
+-
+- low = .01 * perc * (double)xnum;
+- upp = .01 * (100.0 - perc) * (double)xnum;
+- ilow = floor(low);
+- iupp = floor(upp);
+- if ((ilow + iupp) == xnum) {
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
+- if (++cnt == ilow - 1 ) {
+- convert_to_double_ex(data1);
+- val = Z_DVAL_PP(data1);
+-
+- zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1);
+- convert_to_double_ex(data1);
+- val += Z_DVAL_PP(data1);
+- val = val / 2.0;
+- break;
+- }
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- }
+- } else {
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS) {
+- if (++cnt == ilow) {
+- convert_to_double_ex(data1);
+- val += Z_DVAL_PP(data1);
+- break;
+- }
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- }
+- }
+-
+- RETURN_DOUBLE(val);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_correlation(array arr1, array arr2)
+- Not documented */
+-PHP_FUNCTION(stats_stat_correlation)
+-{
+- zval **arg1, **arg2;
+- zval **data1, **data2; /* pointers to array entries */
+- HashPosition pos1; /* hash iterator */
+- HashPosition pos2; /* hash iterator */
+- int xnum = 0;
+- int ynum = 0;
+- double sx = 0.0;
+- double sy = 0.0;
+- double sxx = 0.0;
+- double syy = 0.0;
+- double sxy = 0.0;
+- double mx;
+- double my;
+- double vx;
+- double vy;
+- double cc;
+- double rr;
+-
+- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+- WRONG_PARAM_COUNT;
+- }
+-
+- convert_to_array_ex(arg1);
+- convert_to_array_ex(arg2);
+-
+- xnum = zend_hash_num_elements(Z_ARRVAL_PP(arg1));
+- ynum = zend_hash_num_elements(Z_ARRVAL_PP(arg2));
+-
+- if (xnum != ynum) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unequal number of X and Y coordinates");
+- RETURN_FALSE;
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arg2), &pos2);
+-
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg1), (void **)&data1, &pos1) == SUCCESS
+- && zend_hash_get_current_data_ex(Z_ARRVAL_PP(arg2), (void **)&data2, &pos2) == SUCCESS) {
+-
+- convert_to_double_ex(data1);
+- convert_to_double_ex(data2);
+-
+- sx += Z_DVAL_PP(data1);
+- sxx += Z_DVAL_PP(data1) * Z_DVAL_PP(data1);
+- sy += Z_DVAL_PP(data2);
+- syy += Z_DVAL_PP(data2) * Z_DVAL_PP(data2);
+- sxy += Z_DVAL_PP(data1) * Z_DVAL_PP(data2);
+-
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg1), &pos1);
+- zend_hash_move_forward_ex(Z_ARRVAL_PP(arg2), &pos2);
+- }
+-
+- mx = sx / xnum;
+- my = sy / ynum;
+- vx = sxx - (xnum * mx * mx);
+- vy = syy - (ynum * my * my);
+- cc = sxy - (xnum * mx * my);
+- rr = cc / sqrt(vx * vy);
+-
+- RETURN_DOUBLE(rr);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_binomial_coef(int x, int n)
+- Not documented */
+-PHP_FUNCTION(stats_stat_binomial_coef)
+-{
+- int i;
+- int n;
+- int x;
+- double bc = 1.0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &x, &n) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- for (i = 0; i < x; ++i) {
+- bc = (bc * (n - i)) / (i + 1);
+- }
+-
+- RETURN_DOUBLE(bc);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_stat_gennch(int n)
+- Not documented */
+-PHP_FUNCTION(stats_stat_factorial)
+-{
+- int n;
+- int i;
+- double f = 1;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) {
+- RETURN_FALSE;
+- }
+-
+- for (i = 1; i <= n; ++i) {
+- f *= i;
+- }
+-
+- RETURN_DOUBLE(f);
+-}
+-/* }}} */
+-
+-
+-/* {{{ php_population_variance
+-*/
+-static long double php_math_mean(zval *arr)
+-{
+- double sum = 0.0;
+- zval **entry;
+- HashPosition pos;
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- convert_to_double_ex(entry);
+- sum += Z_DVAL_PP(entry);
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- }
+- /*
+- we don't check whether the array has 0 elements. this is left to the caller - no need
+- to kill performance by checking on every level.
+- */
+- return sum / zend_hash_num_elements(Z_ARRVAL_P(arr));
+-}
+-/* }}} */
+-
+-
+-/* {{{ php_population_variance
+-*/
+-static long double php_population_variance(zval *arr, zend_bool sample)
+-{
+- double mean, vr = 0.0;
+- zval **entry;
+- HashPosition pos;
+- int elements_num;
+-
+- elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr));
+-
+- mean = php_math_mean(arr);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- double d;
+- convert_to_double_ex(entry);
+- d = Z_DVAL_PP(entry) - mean;
+- vr += d*d;
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- }
+- if (sample) {
+- --elements_num;
+- }
+- return (vr / elements_num);
+-}
+-/* }}} */
+-
+-
+-/* {{{ proto float stats_variance(array a [, bool sample])
+- Returns the population variance */
+-PHP_FUNCTION(stats_variance)
+-{
+- zval *arr;
+- zend_bool sample = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &arr, &sample) == FAILURE) {
+- return;
+- }
+- if (zend_hash_num_elements(Z_ARRVAL_P(arr)) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+- if (sample && zend_hash_num_elements(Z_ARRVAL_P(arr)) == 1) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has only 1 element");
+- RETURN_FALSE;
+- }
+- RETURN_DOUBLE(php_population_variance(arr, sample));
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_standard_deviation(array a[, bool sample = false])
+- Returns the standard deviation */
+-PHP_FUNCTION(stats_standard_deviation)
+-{
+- zval *arr;
+- zend_bool sample = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &arr, &sample) == FAILURE) {
+- return;
+- }
+- if (zend_hash_num_elements(Z_ARRVAL_P(arr)) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+- if (sample && zend_hash_num_elements(Z_ARRVAL_P(arr)) == 1) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has only 1 element");
+- RETURN_FALSE;
+- }
+- RETURN_DOUBLE(sqrt(php_population_variance(arr, sample)));
+-}
+-/* }}} */
+-
+-
+-/* {{{ proto float stats_absolute_deviation(array a)
+- Returns the absolute deviation of an array of values*/
+-PHP_FUNCTION(stats_absolute_deviation)
+-{
+- zval *arr;
+- double mean = 0.0, abs_dev = 0.0;
+- zval **entry;
+- HashPosition pos;
+- int elements_num;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
+- return;
+- }
+- if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+-
+- mean = php_math_mean(arr);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- convert_to_double_ex(entry);
+- abs_dev += fabs(Z_DVAL_PP(entry) - mean);
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- }
+-
+- RETURN_DOUBLE(abs_dev / elements_num);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_harmonic_mean(array a)
+- Returns the harmonic mean of an array of values */
+-PHP_FUNCTION(stats_harmonic_mean)
+-{
+- zval *arr;
+- double sum = 0.0;
+- zval **entry;
+- HashPosition pos;
+- int elements_num;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
+- return;
+- }
+- if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+-
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- convert_to_double_ex(entry);
+- if (Z_DVAL_PP(entry) == 0) {
+- RETURN_LONG(0);
+- }
+- sum += 1 / Z_DVAL_PP(entry);
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- }
+-
+- RETURN_DOUBLE(elements_num / sum);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_skew(array a)
+- Computes the skewness of the data in the array */
+-PHP_FUNCTION(stats_skew)
+-{
+- zval *arr;
+- double mean, std_dev, skew = 0.0;
+- zval **entry;
+- HashPosition pos;
+- int elements_num, i = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
+- return;
+- }
+- if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+-
+- mean = php_math_mean(arr);
+- std_dev = sqrt(php_population_variance(arr, 0));
+-
+- /* the calculation of the skewness is protected of value "explosion". a bit more
+- FP operations performed but more accurateness.
+- */
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- double tmp;
+- convert_to_double_ex(entry);
+- tmp = ((Z_DVAL_PP(entry) - mean) / std_dev);
+- skew += (tmp*tmp*tmp - skew) / (i + 1);
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- ++i;
+- }
+-
+- RETURN_DOUBLE(skew);
+-}
+-/* }}} */
+-
+-/* {{{ proto float stats_kurtosis(array a)
+- Computes the kurtosis of the data in the array */
+-PHP_FUNCTION(stats_kurtosis)
+-{
+- zval *arr;
+- double mean, std_dev, avg = 0.0;
+- zval **entry;
+- HashPosition pos;
+- int elements_num, i = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
+- return;
+- }
+- if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr))) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array has zero elements");
+- RETURN_FALSE;
+- }
+-
+- mean = php_math_mean(arr);
+- std_dev = sqrt(php_population_variance(arr, 0));
+-
+- /* the calculation of the kurtosis is protected of value "explosion". a bit more
+- FP operations performed but more accurateness.
+- */
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+- double tmp;
+- convert_to_double_ex(entry);
+- tmp = ((Z_DVAL_PP(entry) - mean) / std_dev);
+- avg += (tmp*tmp*tmp*tmp - avg) / (i + 1);
+-
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+- ++i;
+- }
+-
+- RETURN_DOUBLE(avg - 3);
+-}
+-/* }}} */
+-
+-
+-/* {{{ proto float stats_covariance(array a, array b)
+- Computes the covariance of two data sets */
+-PHP_FUNCTION(stats_covariance)
+-{
+- zval *arr_1, *arr_2;
+- double mean_1, mean_2, covar = 0.0;
+- zval **entry;
+- HashPosition pos_1, pos_2;
+- int elements_num, i = 0;
+-
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &arr_1, &arr_2) == FAILURE) {
+- return;
+- }
+- if ((elements_num = zend_hash_num_elements(Z_ARRVAL_P(arr_1))) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first array has zero elements");
+- RETURN_FALSE;
+- }
+- if (zend_hash_num_elements(Z_ARRVAL_P(arr_2)) == 0) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second array has zero elements");
+- RETURN_FALSE;
+- }
+- if (elements_num != zend_hash_num_elements(Z_ARRVAL_P(arr_2))) {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The datasets are not of the same size");
+- RETURN_FALSE;
+- }
+-
+- mean_1 = php_math_mean(arr_1);
+- mean_2 = php_math_mean(arr_2);
+- /* the calculation of the covariance is protected of value "explosion". a bit more
+- FP operations performed but more accurateness.
+- */
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr_1), &pos_1);
+- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr_2), &pos_2);
+- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr_1), (void **)&entry, &pos_1) == SUCCESS) {
+- double tmp_1, tmp_2;
+- convert_to_double_ex(entry);
+- tmp_1 = Z_DVAL_PP(entry) - mean_1;
+-
+- if (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr_2), (void **)&entry, &pos_2) != SUCCESS) {
+- break;
+- }
+- convert_to_double_ex(entry);
+- tmp_2 = Z_DVAL_PP(entry) - mean_2;
+-
+- covar += (tmp_1 * tmp_2 - covar) / (i + 1);
+-
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr_1), &pos_1);
+- zend_hash_move_forward_ex(Z_ARRVAL_P(arr_2), &pos_2);
+- ++i;
+- }
+-
+- RETURN_DOUBLE(covar);
+-}
+-/* }}} */
+-
+-
+-/*
+- * Local variables:
+- * tab-width: 4
+- * c-basic-offset: 4
+- * indent-tabs-mode: t
+- * End:
+- */
+diff -dPNur stats-1.0.2/.svn/all-wcprops trunk/.svn/all-wcprops
+diff -dPNur stats-1.0.2/.svn/entries trunk/.svn/entries
+diff -dPNur stats-1.0.2/.svn/prop-base/cdflib.h.svn-base trunk/.svn/prop-base/cdflib.h.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/com.c.svn-base trunk/.svn/prop-base/com.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/config.m4.svn-base trunk/.svn/prop-base/config.m4.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/config.w32.svn-base trunk/.svn/prop-base/config.w32.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/CREDITS.svn-base trunk/.svn/prop-base/CREDITS.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/dcdflib.c.svn-base trunk/.svn/prop-base/dcdflib.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fd_e_lgamma_r.c.svn-base trunk/.svn/prop-base/fd_e_lgamma_r.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fd_e_log.c.svn-base trunk/.svn/prop-base/fd_e_log.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fd_k_cos.c.svn-base trunk/.svn/prop-base/fd_k_cos.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fd_k_sin.c.svn-base trunk/.svn/prop-base/fd_k_sin.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fdlibm.h.svn-base trunk/.svn/prop-base/fdlibm.h.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/fd_w_lgamma.c.svn-base trunk/.svn/prop-base/fd_w_lgamma.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/ipmpar.c.svn-base trunk/.svn/prop-base/ipmpar.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/linpack.c.svn-base trunk/.svn/prop-base/linpack.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/package.xml.svn-base trunk/.svn/prop-base/package.xml.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/php_stats.c.svn-base trunk/.svn/prop-base/php_stats.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/php_stats.h.svn-base trunk/.svn/prop-base/php_stats.h.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/randlib.c.svn-base trunk/.svn/prop-base/randlib.c.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/randlib.h.svn-base trunk/.svn/prop-base/randlib.h.svn-base
+diff -dPNur stats-1.0.2/.svn/prop-base/TODO.svn-base trunk/.svn/prop-base/TODO.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/cdflib.h.svn-base trunk/.svn/text-base/cdflib.h.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/com.c.svn-base trunk/.svn/text-base/com.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/config.m4.svn-base trunk/.svn/text-base/config.m4.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/config.w32.svn-base trunk/.svn/text-base/config.w32.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/CREDITS.svn-base trunk/.svn/text-base/CREDITS.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/.svn/text-base/dcdflib.c.svn-base trunk/.svn/text-base/dcdflib.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fd_e_lgamma_r.c.svn-base trunk/.svn/text-base/fd_e_lgamma_r.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fd_e_log.c.svn-base trunk/.svn/text-base/fd_e_log.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fd_k_cos.c.svn-base trunk/.svn/text-base/fd_k_cos.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fd_k_sin.c.svn-base trunk/.svn/text-base/fd_k_sin.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fdlibm.h.svn-base trunk/.svn/text-base/fdlibm.h.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/fd_w_lgamma.c.svn-base trunk/.svn/text-base/fd_w_lgamma.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/ipmpar.c.svn-base trunk/.svn/text-base/ipmpar.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/linpack.c.svn-base trunk/.svn/text-base/linpack.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/package.xml.svn-base trunk/.svn/text-base/package.xml.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/php_stats.c.svn-base trunk/.svn/text-base/php_stats.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/php_stats.h.svn-base trunk/.svn/text-base/php_stats.h.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/randlib.c.svn-base trunk/.svn/text-base/randlib.c.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/randlib.h.svn-base trunk/.svn/text-base/randlib.h.svn-base
+diff -dPNur stats-1.0.2/.svn/text-base/TODO.svn-base trunk/.svn/text-base/TODO.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/tests/.svn/all-wcprops trunk/tests/.svn/all-wcprops
+diff -dPNur stats-1.0.2/tests/.svn/entries trunk/tests/.svn/entries
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/common.php.svn-base trunk/tests/.svn/prop-base/common.php.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/math_abs_dev.phpt.svn-base trunk/tests/.svn/prop-base/math_abs_dev.phpt.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/math_covariance.phpt.svn-base trunk/tests/.svn/prop-base/math_covariance.phpt.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/math_harmonic_mean.phpt.svn-base trunk/tests/.svn/prop-base/math_harmonic_mean.phpt.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/math_skew_kurtosis.phpt.svn-base trunk/tests/.svn/prop-base/math_skew_kurtosis.phpt.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/prop-base/math_std_dev.phpt.svn-base trunk/tests/.svn/prop-base/math_std_dev.phpt.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/text-base/common.php.svn-base trunk/tests/.svn/text-base/common.php.svn-base
+diff -dPNur stats-1.0.2/tests/.svn/text-base/math_abs_dev.phpt.svn-base trunk/tests/.svn/text-base/math_abs_dev.phpt.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/tests/.svn/text-base/math_covariance.phpt.svn-base trunk/tests/.svn/text-base/math_covariance.phpt.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/tests/.svn/text-base/math_harmonic_mean.phpt.svn-base trunk/tests/.svn/text-base/math_harmonic_mean.phpt.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/tests/.svn/text-base/math_skew_kurtosis.phpt.svn-base trunk/tests/.svn/text-base/math_skew_kurtosis.phpt.svn-base
+\ No newline at end of file
+diff -dPNur stats-1.0.2/tests/.svn/text-base/math_std_dev.phpt.svn-base trunk/tests/.svn/text-base/math_std_dev.phpt.svn-base
+\ No newline at end of file
diff --git a/dev-php/pecl-stats/pecl-stats-1.0.2.ebuild b/dev-php/pecl-stats/pecl-stats-1.0.2.ebuild
new file mode 100644
index 0000000..36a34fe
--- /dev/null
+++ b/dev-php/pecl-stats/pecl-stats-1.0.2.ebuild
@@ -0,0 +1,31 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-php/PECL-sqlite/Attic/PECL-sqlite-1.0.3.ebuild,v 1.7 2006/05/21 01:53:28 chtekk dead $
+
+EAPI=6
+
+PHP_EXT_ZENDEXT="no"
+PHP_EXT_INI="yes"
+PHP_EXT_PECL_PKG="stats"
+PHP_EXT_NAME="stats"
+USE_PHP="php5-6 php5-5 php5-4 php5-3"
+
+inherit php-ext-pecl-r3
+
+IUSE=""
+DESCRIPTION="PHP statistics package"
+HOMEPAGE="http://pecl.php.net/package/stats"
+SLOT="0"
+LICENSE="PHP"
+KEYWORDS="alpha amd64 ~ia64 ppc ~sparc x86"
+
+
+src_prepare() {
+ local slot
+ for slot in $(php_get_slots); do
+ php_init_slot_env ${slot}
+ epatch "${FILESDIR}"/stats-php54.diff
+ done
+
+ php-ext-source-r2_src_prepare
+}