sqlite3: Vendor import of sqlite3 3.37.1

Changes at https://www.sqlite.org/releaselog/3_37_1.html.

Merge commit '7e13a4eb402641ddf307497cc9ac7ce1ab21c2a8' into sqlite3-work2
This commit is contained in:
Cy Schubert 2022-01-05 16:03:14 -08:00
commit 0197ba465f
12 changed files with 13063 additions and 8147 deletions

View File

@ -290,7 +290,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF !ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF !ENDIF
@ -960,7 +959,6 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF !ENDIF

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.35.5. # Generated by GNU Autoconf 2.69 for sqlite 3.37.1.
# #
# Report bugs to <http://www.sqlite.org>. # Report bugs to <http://www.sqlite.org>.
# #
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='sqlite' PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite' PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.35.5' PACKAGE_VERSION='3.37.1'
PACKAGE_STRING='sqlite 3.35.5' PACKAGE_STRING='sqlite 3.37.1'
PACKAGE_BUGREPORT='http://www.sqlite.org' PACKAGE_BUGREPORT='http://www.sqlite.org'
PACKAGE_URL='' PACKAGE_URL=''
@ -1342,7 +1342,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures sqlite 3.35.5 to adapt to many kinds of systems. \`configure' configures sqlite 3.37.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1413,7 +1413,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.35.5:";; short | recursive ) echo "Configuration of sqlite 3.37.1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1539,7 +1539,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
sqlite configure 3.35.5 sqlite configure 3.37.1
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -1954,7 +1954,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.35.5, which was It was created by sqlite $as_me 3.37.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2820,7 +2820,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='sqlite' PACKAGE='sqlite'
VERSION='3.35.5' VERSION='3.37.1'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -14569,7 +14569,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by sqlite $as_me 3.35.5, which was This file was extended by sqlite $as_me 3.37.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -14626,7 +14626,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
sqlite config.status 3.35.5 sqlite config.status 3.37.1
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -10,7 +10,7 @@
# #
AC_PREREQ(2.61) AC_PREREQ(2.61)
AC_INIT(sqlite, 3.35.5, http://www.sqlite.org) AC_INIT(sqlite, 3.37.1, http://www.sqlite.org)
AC_CONFIG_SRCDIR([sqlite3.c]) AC_CONFIG_SRCDIR([sqlite3.c])
AC_CONFIG_AUX_DIR([.]) AC_CONFIG_AUX_DIR([.])

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,30 @@ extern "C" {
/* /*
** Provide the ability to override linkage features of the interface. ** Facilitate override of interface linkage and calling conventions.
** Be aware that these macros may not be used within this particular
** translation of the amalgamation and its associated header file.
**
** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
** compiler that the target identifier should have external linkage.
**
** The SQLITE_CDECL macro is used to set the calling convention for
** public functions that accept a variable number of arguments.
**
** The SQLITE_APICALL macro is used to set the calling convention for
** public functions that accept a fixed number of arguments.
**
** The SQLITE_STDCALL macro is no longer used and is now deprecated.
**
** The SQLITE_CALLBACK macro is used to set the calling convention for
** function pointers.
**
** The SQLITE_SYSAPI macro is used to set the calling convention for
** functions provided by the operating system.
**
** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
** SQLITE_SYSAPI macros are used only when building for environments
** that require non-default calling conventions.
*/ */
#ifndef SQLITE_EXTERN #ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern # define SQLITE_EXTERN extern
@ -123,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()]. ** [sqlite_version()] and [sqlite_source_id()].
*/ */
#define SQLITE_VERSION "3.35.5" #define SQLITE_VERSION "3.37.1"
#define SQLITE_VERSION_NUMBER 3035005 #define SQLITE_VERSION_NUMBER 3037001
#define SQLITE_SOURCE_ID "2021-04-19 18:32:05 1b256d97b553a9611efca188a3d995a2fff712759044ba480f9a0c9e98fae886" #define SQLITE_SOURCE_ID "2021-12-30 15:30:28 378629bf2ea546f73eee84063c5358439a12f7300e433f18c9e1bddd948dea62"
/* /*
** CAPI3REF: Run-Time Library Version Numbers ** CAPI3REF: Run-Time Library Version Numbers
@ -537,6 +560,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8)) #define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
@ -550,6 +574,19 @@ SQLITE_API int sqlite3_exec(
** These bit values are intended for use in the ** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and ** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
**
** Only those flags marked as "Ok for sqlite3_open_v2()" may be
** used as the third argument to the [sqlite3_open_v2()] interface.
** The other flags have historically been ignored by sqlite3_open_v2(),
** though future versions of SQLite might change so that an error is
** raised if any of the disallowed bits are passed into sqlite3_open_v2().
** Applications should not depend on the historical behavior.
**
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
** [sqlite3_open_v2()] does *not* cause the underlying database file
** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
** [sqlite3_open_v2()] has historically be a no-op and might become an
** error in future versions of SQLite.
*/ */
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
@ -572,6 +609,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
/* Reserved: 0x00F00000 */ /* Reserved: 0x00F00000 */
/* Legacy compatibility: */ /* Legacy compatibility: */
@ -1128,6 +1166,23 @@ struct sqlite3_io_methods {
** file to the database file, but before the *-shm file is updated to ** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed. ** record the fact that the pages have been checkpointed.
** </ul> ** </ul>
**
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
** whether or not there is a database client in another process with a wal-mode
** transaction open on the database or not. It is only available on unix.The
** (void*) argument passed with this file-control should be a pointer to a
** value of type (int). The integer value is set to 1 if the database is a wal
** mode database and there exists at least one client in another process that
** currently has an SQL transaction open on the database. It is set to 0 if
** the database is not a wal-mode db, or if there is no such connection in any
** other process. This opcode cannot be used to detect transactions opened
** by clients within the current process, only within other processes.
** </ul>
**
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
** Used by the cksmvfs VFS module only.
** </ul>
*/ */
#define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@ -1167,6 +1222,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37 #define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39 #define SQLITE_FCNTL_CKPT_START 39
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */ /* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@ -2445,11 +2502,14 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** CAPI3REF: Count The Number Of Rows Modified ** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3 ** METHOD: sqlite3
** **
** ^This function returns the number of rows modified, inserted or ** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE ** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter. ** statement on the database connection specified by the only parameter.
** ^Executing any other type of SQL statement does not modify the value ** The two functions are identical except for the type of the return value
** returned by this function. ** and that if the number of rows modified by the most recent INSERT, UPDATE
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
** **
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@ -2498,16 +2558,21 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** </ul> ** </ul>
*/ */
SQLITE_API int sqlite3_changes(sqlite3*); SQLITE_API int sqlite3_changes(sqlite3*);
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
/* /*
** CAPI3REF: Total Number Of Rows Modified ** CAPI3REF: Total Number Of Rows Modified
** METHOD: sqlite3 ** METHOD: sqlite3
** **
** ^This function returns the total number of rows inserted, modified or ** ^These functions return the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
** since the database connection was opened, including those executed as ** since the database connection was opened, including those executed as
** part of trigger programs. ^Executing any other type of SQL statement ** part of trigger programs. The two functions are identical except for the
** does not affect the value returned by sqlite3_total_changes(). ** type of the return value and that if the number of rows modified by the
** connection exceeds the maximum value supported by type "int", then
** the return value of sqlite3_total_changes() is undefined. ^Executing
** any other type of SQL statement does not affect the value returned by
** sqlite3_total_changes().
** **
** ^Changes made as part of [foreign key actions] are included in the ** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are ** count, but those made as part of REPLACE constraint resolution are
@ -2535,6 +2600,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** </ul> ** </ul>
*/ */
SQLITE_API int sqlite3_total_changes(sqlite3*); SQLITE_API int sqlite3_total_changes(sqlite3*);
SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
/* /*
** CAPI3REF: Interrupt A Long-Running Query ** CAPI3REF: Interrupt A Long-Running Query
@ -3364,6 +3430,14 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** the default shared cache setting provided by ** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^ ** [sqlite3_enable_shared_cache()].)^
** **
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
** <dd>The database connection comes up in "extended result code mode".
** In other words, the database behaves has if
** [sqlite3_extended_result_codes(db,1)] where called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.</dd>
**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
** <dd>The database filename is not allowed to be a symbolic link</dd> ** <dd>The database filename is not allowed to be a symbolic link</dd>
** </dl>)^ ** </dl>)^
@ -3371,7 +3445,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** If the 3rd parameter to sqlite3_open_v2() is not one of the ** If the 3rd parameter to sqlite3_open_v2() is not one of the
** required combinations shown above optionally combined with other ** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined. ** then the behavior is undefined. Historic versions of SQLite
** have silently ignored surplus bits in the flags parameter to
** sqlite3_open_v2(), however that behavior might not be carried through
** into future versions of SQLite and so applications should not rely
** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause
** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE
** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not
** by sqlite3_open_v2().
** **
** ^The fourth parameter to sqlite3_open_v2() is the name of the ** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that ** [sqlite3_vfs] object that defines the operating system interface that
@ -4139,12 +4221,17 @@ SQLITE_API int sqlite3_prepare16_v3(
** are managed by SQLite and are automatically freed when the prepared ** are managed by SQLite and are automatically freed when the prepared
** statement is finalized. ** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application ** is obtained from [sqlite3_malloc()] and must be freed by the application
** by passing it to [sqlite3_free()]. ** by passing it to [sqlite3_free()].
**
** ^The sqlite3_normalized_sql() interface is only available if
** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
*/ */
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
#ifdef SQLITE_ENABLE_NORMALIZE
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
#endif
/* /*
** CAPI3REF: Determine If An SQL Statement Writes The Database ** CAPI3REF: Determine If An SQL Statement Writes The Database
@ -4179,6 +4266,15 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands. ** sqlite3_stmt_readonly() returns false for those commands.
**
** ^This routine returns false if there is any possibility that the
** statement might change the database file. ^A false return does
** not guarantee that the statement will change the database file.
** ^For example, an UPDATE statement might have a WHERE clause that
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
** read-only no-op if the table already exists, but
** sqlite3_stmt_readonly() still returns false for such a statement.
*/ */
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@ -4348,18 +4444,22 @@ typedef struct sqlite3_context sqlite3_context;
** contain embedded NULs. The result of expressions involving strings ** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined. ** with embedded NULs is undefined.
** **
** ^The fifth argument to the BLOB and string binding interfaces ** ^The fifth argument to the BLOB and string binding interfaces controls
** is a destructor used to dispose of the BLOB or ** or indicates the lifetime of the object referenced by the third parameter.
** string after SQLite has finished with it. ^The destructor is called ** These three options exist:
** to dispose of the BLOB or string even if the call to the bind API fails, ** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
** except the destructor is not called if the third parameter is a NULL ** with it may be passed. ^It is called to dispose of the BLOB or string even
** pointer or the fourth parameter is negative. ** if the call to the bind API fails, except the destructor is not called if
** ^If the fifth argument is ** the third parameter is a NULL pointer or the fourth parameter is negative.
** the special value [SQLITE_STATIC], then SQLite assumes that the ** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
** information is in static, unmanaged space and does not need to be freed. ** the application remains responsible for disposing of the object. ^In this
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then ** case, the object and the provided pointer to it must remain valid until
** SQLite makes its own private copy of the data immediately, before ** either the prepared statement is finalized or the same SQL parameter is
** the sqlite3_bind_*() routine returns. ** bound to something else, whichever occurs sooner.
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
** object and pointer to it must remain valid until then. ^SQLite will then
** manage the lifetime of its private copy.
** **
** ^The sixth argument to sqlite3_bind_text64() must be one of ** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@ -5101,7 +5201,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
** index expressions, or the WHERE clause of partial indexes. ** index expressions, or the WHERE clause of partial indexes.
** **
** <span style="background-color:#ffff90;">
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be ** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of ** used inside of triggers, view, CHECK constraints, or other elements of
@ -5111,7 +5210,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** a database file to include invocations of the function with parameters ** a database file to include invocations of the function with parameters
** chosen by the attacker, which the application will then execute when ** chosen by the attacker, which the application will then execute when
** the database file is opened and read. ** the database file is opened and read.
** </span>
** **
** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^ ** function can gain access to this pointer using [sqlite3_user_data()].)^
@ -6317,6 +6415,72 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
** function C that is invoked prior to each autovacuum of the database
** file. ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively. The callback should
** return the number of free pages that should be removed by the
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface. If it does, bad
** things may happen, including segmentation faults and corrupt database
** files. The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter. ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection. ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled. The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong. The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages. So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** &nbsp; unsigned int demonstration_autovac_pages_callback(
** &nbsp; void *pClientData,
** &nbsp; const char *zSchema,
** &nbsp; unsigned int nDbPage,
** &nbsp; unsigned int nFreePage,
** &nbsp; unsigned int nBytePerPage
** &nbsp; ){
** &nbsp; return nFreePage;
** &nbsp; }
** </pre></blockquote>
*/
SQLITE_API int sqlite3_autovacuum_pages(
sqlite3 *db,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*,
void(*)(void*)
);
/* /*
** CAPI3REF: Data Change Notification Callbacks ** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3 ** METHOD: sqlite3
@ -7779,7 +7943,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_SEEK_COUNT 30
#define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TRACEFLAGS 31
#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */ #define SQLITE_TESTCTRL_TUNE 32
#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
/* /*
** CAPI3REF: SQL Keyword Checking ** CAPI3REF: SQL Keyword Checking
@ -8979,8 +9144,9 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** **
** A single database handle may have at most a single write-ahead log callback ** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
** previously registered write-ahead log callback. ^Note that the ** previously registered write-ahead log callback. ^The return value is
** [sqlite3_wal_autocheckpoint()] interface and the ** a copy of the third parameter from the previous call, if any, or 0.
** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** overwrite any prior [sqlite3_wal_hook()] settings. ** overwrite any prior [sqlite3_wal_hook()] settings.
*/ */
@ -9531,6 +9697,15 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth. ** triggers; and so forth.
** **
** When the [sqlite3_blob_write()] API is used to update a blob column,
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
** in this case the new values are not available. In this case, when a
** callback made with op==SQLITE_DELETE is actuall a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
** pre-update hook is being invoked for some other reason, including a
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
**
** See also: [sqlite3_update_hook()] ** See also: [sqlite3_update_hook()]
*/ */
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) #if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@ -9551,6 +9726,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *); SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif #endif
/* /*
@ -9789,8 +9965,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs. ** allocation error occurs.
** **
** This interface is only available if SQLite is compiled with the ** This interface is omitted if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option. ** [SQLITE_OMIT_DESERIALIZE] option.
*/ */
SQLITE_API unsigned char *sqlite3_serialize( SQLITE_API unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */ sqlite3 *db, /* The database connection */
@ -9837,12 +10013,16 @@ SQLITE_API unsigned char *sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup ** database is currently in a read transaction or is involved in a backup
** operation. ** operation.
** **
** It is not possible to deserialized into the TEMP database. If the
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
** function returns SQLITE_ERROR.
**
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning. ** [sqlite3_free()] is invoked on argument P prior to returning.
** **
** This interface is only available if SQLite is compiled with the ** This interface is omitted if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option. ** [SQLITE_OMIT_DESERIALIZE] option.
*/ */
SQLITE_API int sqlite3_deserialize( SQLITE_API int sqlite3_deserialize(
sqlite3 *db, /* The database connection */ sqlite3 *db, /* The database connection */
@ -10091,6 +10271,38 @@ SQLITE_API int sqlite3session_create(
*/ */
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPIREF: Conigure a Session Object
** METHOD: sqlite3_session
**
** This method is used to configure a session object after it has been
** created. At present the only valid value for the second parameter is
** [SQLITE_SESSION_OBJCONFIG_SIZE].
**
** Arguments for sqlite3session_object_config()
**
** The following values may passed as the the 4th parameter to
** sqlite3session_object_config().
**
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
** This option is used to set, clear or query the flag that enables
** the [sqlite3session_changeset_size()] API. Because it imposes some
** computational overhead, this API is disabled by default. Argument
** pArg must point to a value of type (int). If the value is initially
** 0, then the sqlite3session_changeset_size() API is disabled. If it
** is greater than 0, then the same API is enabled. Or, if the initial
** value is less than zero, no change is made. In all cases the (int)
** variable is set to 1 if the sqlite3session_changeset_size() API is
** enabled following the current call, or 0 otherwise.
**
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
** the first table has been attached to the session object.
*/
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
/*
*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/* /*
** CAPI3REF: Enable Or Disable A Session Object ** CAPI3REF: Enable Or Disable A Session Object
@ -10335,6 +10547,22 @@ SQLITE_API int sqlite3session_changeset(
void **ppChangeset /* OUT: Buffer containing changeset */ void **ppChangeset /* OUT: Buffer containing changeset */
); );
/*
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
** METHOD: sqlite3_session
**
** By default, this function always returns 0. For it to return
** a useful result, the sqlite3_session object must have been configured
** to enable this API using sqlite3session_object_config() with the
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
**
** When enabled, this function returns an upper limit, in bytes, for the size
** of the changeset that might be produced if sqlite3session_changeset() were
** called. The final changeset size might be equal to or smaller than the
** size in bytes returned by this function.
*/
SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
/* /*
** CAPI3REF: Load The Difference Between Tables Into A Session ** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session ** METHOD: sqlite3_session

View File

@ -337,6 +337,13 @@ struct sqlite3_api_routines {
sqlite3_file *(*database_file_object)(const char*); sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */ /* Version 3.34.0 and later */
int (*txn_state)(sqlite3*,const char*); int (*txn_state)(sqlite3*,const char*);
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
}; };
/* /*
@ -643,6 +650,11 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_database_file_object sqlite3_api->database_file_object #define sqlite3_database_file_object sqlite3_api->database_file_object
/* Version 3.34.0 and later */ /* Version 3.34.0 and later */
#define sqlite3_txn_state sqlite3_api->txn_state #define sqlite3_txn_state sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64 sqlite3_api->changes64
#define sqlite3_total_changes64 sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)

View File

@ -1,3 +1,3 @@
#ifndef SQLITE_RESOURCE_VERSION #ifndef SQLITE_RESOURCE_VERSION
#define SQLITE_RESOURCE_VERSION 3,35,5 #define SQLITE_RESOURCE_VERSION 3,37,1
#endif #endif

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.35.5. # Generated by GNU Autoconf 2.69 for sqlite 3.37.1.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='sqlite' PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite' PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.35.5' PACKAGE_VERSION='3.37.1'
PACKAGE_STRING='sqlite 3.35.5' PACKAGE_STRING='sqlite 3.37.1'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
@ -1303,7 +1303,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures sqlite 3.35.5 to adapt to many kinds of systems. \`configure' configures sqlite 3.37.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1365,7 +1365,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.35.5:";; short | recursive ) echo "Configuration of sqlite 3.37.1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1467,7 +1467,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
sqlite configure 3.35.5 sqlite configure 3.37.1
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -1878,7 +1878,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.35.5, which was It was created by sqlite $as_me 3.37.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -9373,7 +9373,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by sqlite $as_me 3.35.5, which was This file was extended by sqlite $as_me 3.37.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -9426,7 +9426,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
sqlite config.status 3.35.5 sqlite config.status 3.37.1
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
# so you can encode the package version directly into the source files. # so you can encode the package version directly into the source files.
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
AC_INIT([sqlite], [3.35.5]) AC_INIT([sqlite], [3.37.1])
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars. # Call TEA_INIT as the first TEA_ macro to set up initial vars.

View File

@ -186,6 +186,7 @@ struct SqliteDb {
int nVMStep; /* Another statistic for most recent operation */ int nVMStep; /* Another statistic for most recent operation */
int nTransaction; /* Number of nested [transaction] methods */ int nTransaction; /* Number of nested [transaction] methods */
int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */ int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
int nRef; /* Delete object when this reaches 0 */
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int bLegacyPrepare; /* True to use sqlite3_prepare() */ int bLegacyPrepare; /* True to use sqlite3_prepare() */
#endif #endif
@ -522,64 +523,84 @@ static void flushStmtCache(SqliteDb *pDb){
pDb->stmtList = 0; pDb->stmtList = 0;
} }
/*
** Increment the reference counter on the SqliteDb object. The reference
** should be released by calling delDatabaseRef().
*/
static void addDatabaseRef(SqliteDb *pDb){
pDb->nRef++;
}
/*
** Decrement the reference counter associated with the SqliteDb object.
** If it reaches zero, delete the object.
*/
static void delDatabaseRef(SqliteDb *pDb){
assert( pDb->nRef>0 );
pDb->nRef--;
if( pDb->nRef==0 ){
flushStmtCache(pDb);
closeIncrblobChannels(pDb);
sqlite3_close(pDb->db);
while( pDb->pFunc ){
SqlFunc *pFunc = pDb->pFunc;
pDb->pFunc = pFunc->pNext;
assert( pFunc->pDb==pDb );
Tcl_DecrRefCount(pFunc->pScript);
Tcl_Free((char*)pFunc);
}
while( pDb->pCollate ){
SqlCollate *pCollate = pDb->pCollate;
pDb->pCollate = pCollate->pNext;
Tcl_Free((char*)pCollate);
}
if( pDb->zBusy ){
Tcl_Free(pDb->zBusy);
}
if( pDb->zTrace ){
Tcl_Free(pDb->zTrace);
}
if( pDb->zTraceV2 ){
Tcl_Free(pDb->zTraceV2);
}
if( pDb->zProfile ){
Tcl_Free(pDb->zProfile);
}
if( pDb->zBindFallback ){
Tcl_Free(pDb->zBindFallback);
}
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
if( pDb->pUpdateHook ){
Tcl_DecrRefCount(pDb->pUpdateHook);
}
if( pDb->pPreUpdateHook ){
Tcl_DecrRefCount(pDb->pPreUpdateHook);
}
if( pDb->pRollbackHook ){
Tcl_DecrRefCount(pDb->pRollbackHook);
}
if( pDb->pWalHook ){
Tcl_DecrRefCount(pDb->pWalHook);
}
if( pDb->pCollateNeeded ){
Tcl_DecrRefCount(pDb->pCollateNeeded);
}
Tcl_Free((char*)pDb);
}
}
/* /*
** TCL calls this procedure when an sqlite3 database command is ** TCL calls this procedure when an sqlite3 database command is
** deleted. ** deleted.
*/ */
static void SQLITE_TCLAPI DbDeleteCmd(void *db){ static void SQLITE_TCLAPI DbDeleteCmd(void *db){
SqliteDb *pDb = (SqliteDb*)db; SqliteDb *pDb = (SqliteDb*)db;
flushStmtCache(pDb); delDatabaseRef(pDb);
closeIncrblobChannels(pDb);
sqlite3_close(pDb->db);
while( pDb->pFunc ){
SqlFunc *pFunc = pDb->pFunc;
pDb->pFunc = pFunc->pNext;
assert( pFunc->pDb==pDb );
Tcl_DecrRefCount(pFunc->pScript);
Tcl_Free((char*)pFunc);
}
while( pDb->pCollate ){
SqlCollate *pCollate = pDb->pCollate;
pDb->pCollate = pCollate->pNext;
Tcl_Free((char*)pCollate);
}
if( pDb->zBusy ){
Tcl_Free(pDb->zBusy);
}
if( pDb->zTrace ){
Tcl_Free(pDb->zTrace);
}
if( pDb->zTraceV2 ){
Tcl_Free(pDb->zTraceV2);
}
if( pDb->zProfile ){
Tcl_Free(pDb->zProfile);
}
if( pDb->zBindFallback ){
Tcl_Free(pDb->zBindFallback);
}
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
if( pDb->pUpdateHook ){
Tcl_DecrRefCount(pDb->pUpdateHook);
}
if( pDb->pPreUpdateHook ){
Tcl_DecrRefCount(pDb->pPreUpdateHook);
}
if( pDb->pRollbackHook ){
Tcl_DecrRefCount(pDb->pRollbackHook);
}
if( pDb->pWalHook ){
Tcl_DecrRefCount(pDb->pWalHook);
}
if( pDb->pCollateNeeded ){
Tcl_DecrRefCount(pDb->pCollateNeeded);
}
Tcl_Free((char*)pDb);
} }
/* /*
@ -1251,6 +1272,7 @@ static int SQLITE_TCLAPI DbTransPostCmd(
} }
pDb->disableAuth--; pDb->disableAuth--;
delDatabaseRef(pDb);
return rc; return rc;
} }
@ -1584,6 +1606,7 @@ static void dbEvalInit(
Tcl_IncrRefCount(pArray); Tcl_IncrRefCount(pArray);
} }
p->evalFlags = evalFlags; p->evalFlags = evalFlags;
addDatabaseRef(p->pDb);
} }
/* /*
@ -1724,6 +1747,7 @@ static void dbEvalFinalize(DbEvalContext *p){
} }
Tcl_DecrRefCount(p->pSql); Tcl_DecrRefCount(p->pSql);
dbReleaseColumnNames(p); dbReleaseColumnNames(p);
delDatabaseRef(p->pDb);
} }
/* /*
@ -2212,7 +2236,7 @@ static int SQLITE_TCLAPI DbObjCmd(
return TCL_ERROR; return TCL_ERROR;
} }
pResult = Tcl_GetObjResult(interp); pResult = Tcl_GetObjResult(interp);
Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); Tcl_SetWideIntObj(pResult, sqlite3_changes64(pDb->db));
break; break;
} }
@ -2605,7 +2629,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Reopen DATABASE (default "main") using the content in $VALUE ** Reopen DATABASE (default "main") using the content in $VALUE
*/ */
case DB_DESERIALIZE: { case DB_DESERIALIZE: {
#ifndef SQLITE_ENABLE_DESERIALIZE #ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build", Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0); (char*)0);
rc = TCL_ERROR; rc = TCL_ERROR;
@ -2628,8 +2652,10 @@ static int SQLITE_TCLAPI DbObjCmd(
for(i=2; i<objc-1; i++){ for(i=2; i<objc-1; i++){
const char *z = Tcl_GetString(objv[i]); const char *z = Tcl_GetString(objv[i]);
if( strcmp(z,"-maxsize")==0 && i<objc-2 ){ if( strcmp(z,"-maxsize")==0 && i<objc-2 ){
rc = Tcl_GetWideIntFromObj(interp, objv[++i], &mxSize); Tcl_WideInt x;
rc = Tcl_GetWideIntFromObj(interp, objv[++i], &x);
if( rc ) goto deserialize_error; if( rc ) goto deserialize_error;
mxSize = x;
continue; continue;
} }
if( strcmp(z,"-readonly")==0 && i<objc-2 ){ if( strcmp(z,"-readonly")==0 && i<objc-2 ){
@ -3172,7 +3198,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Return a serialization of a database. ** Return a serialization of a database.
*/ */
case DB_SERIALIZE: { case DB_SERIALIZE: {
#ifndef SQLITE_ENABLE_DESERIALIZE #ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build", Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0); (char*)0);
rc = TCL_ERROR; rc = TCL_ERROR;
@ -3260,7 +3286,7 @@ static int SQLITE_TCLAPI DbObjCmd(
return TCL_ERROR; return TCL_ERROR;
} }
pResult = Tcl_GetObjResult(interp); pResult = Tcl_GetObjResult(interp);
Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); Tcl_SetWideIntObj(pResult, sqlite3_total_changes64(pDb->db));
break; break;
} }
@ -3440,6 +3466,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** opened above. If not using NRE, evaluate the script directly, then ** opened above. If not using NRE, evaluate the script directly, then
** call function DbTransPostCmd() to commit (or rollback) the transaction ** call function DbTransPostCmd() to commit (or rollback) the transaction
** or savepoint. */ ** or savepoint. */
addDatabaseRef(pDb); /* DbTransPostCmd() calls delDatabaseRef() */
if( DbUseNre() ){ if( DbUseNre() ){
Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0); Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
(void)Tcl_NREvalObj(interp, pScript, 0); (void)Tcl_NREvalObj(interp, pScript, 0);
@ -3847,6 +3874,7 @@ static int SQLITE_TCLAPI DbMain(
}else{ }else{
Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
} }
p->nRef = 1;
return TCL_OK; return TCL_OK;
} }
@ -3954,7 +3982,9 @@ static const char *tclsh_main_loop(void){
return zMainloop; return zMainloop;
} }
#define TCLSH_MAIN main /* Needed to fake out mktclapp */ #ifndef TCLSH_MAIN
# define TCLSH_MAIN main
#endif
int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){ int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
Tcl_Interp *interp; Tcl_Interp *interp;
int i; int i;

View File

@ -14,13 +14,10 @@
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#include <windows.h> #include <windows.h>
#define NO_SHLWAPI_GDI #ifdef _MSC_VER
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_REG
#include <shlwapi.h>
#pragma comment (lib, "user32.lib") #pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib") #pragma comment (lib, "kernel32.lib")
#pragma comment (lib, "shlwapi.lib") #endif
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
@ -39,15 +36,15 @@
#endif #endif
/* protos */ /* protos */
static int CheckForCompilerFeature(const char *option); static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char *option); static int CheckForLinkerFeature(char **options, int count);
static int IsIn(const char *string, const char *substring); static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename); static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path); static int QualifyPath(const char *path);
static const char *GetVersionFromFile(const char *filename, const char *match); static int LocateDependency(const char *keyfile);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args); static DWORD WINAPI ReadFromPipe(LPVOID args);
/* globals */ /* globals */
@ -59,8 +56,8 @@ typedef struct {
char buffer[STATICBUFFERSIZE]; char buffer[STATICBUFFERSIZE];
} pipeinfo; } pipeinfo;
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; pipeinfo Err = {INVALID_HANDLE_VALUE, ""};
/* /*
* exitcodes: 0 == no, 1 == yes, 2 == error * exitcodes: 0 == no, 1 == yes, 2 == error
@ -74,6 +71,7 @@ main(
char msg[300]; char msg[300];
DWORD dwWritten; DWORD dwWritten;
int chars; int chars;
const char *s;
/* /*
* Make sure children (cl.exe and link.exe) are kept quiet. * Make sure children (cl.exe and link.exe) are kept quiet.
@ -102,16 +100,16 @@ main(
} }
return CheckForCompilerFeature(argv[2]); return CheckForCompilerFeature(argv[2]);
case 'l': case 'l':
if (argc != 3) { if (argc < 3) {
chars = snprintf(msg, sizeof(msg) - 1, chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -l <linker option>\n" "usage: %s -l <linker option> ?<mandatory option> ...?\n"
"Tests for whether link.exe supports an option\n" "Tests for whether link.exe supports an option\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL); &dwWritten, NULL);
return 2; return 2;
} }
return CheckForLinkerFeature(argv[2]); return CheckForLinkerFeature(&argv[2], argc-2);
case 'f': case 'f':
if (argc == 2) { if (argc == 2) {
chars = snprintf(msg, sizeof(msg) - 1, chars = snprintf(msg, sizeof(msg) - 1,
@ -153,8 +151,13 @@ main(
&dwWritten, NULL); &dwWritten, NULL);
return 0; return 0;
} }
printf("%s\n", GetVersionFromFile(argv[2], argv[3])); s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
return 0; if (s && *s) {
printf("%s\n", s);
return 0;
} else
return 1; /* Version not found. Return non-0 exit code */
case 'Q': case 'Q':
if (argc != 3) { if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1, chars = snprintf(msg, sizeof(msg) - 1,
@ -166,6 +169,18 @@ main(
return 2; return 2;
} }
return QualifyPath(argv[2]); return QualifyPath(argv[2]);
case 'L':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -L keypath\n"
"Emit the fully qualified path of directory containing keypath\n"
"exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return LocateDependency(argv[2]);
} }
} }
chars = snprintf(msg, sizeof(msg) - 1, chars = snprintf(msg, sizeof(msg) - 1,
@ -260,7 +275,7 @@ CheckForCompilerFeature(
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
(300-chars), 0); (300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2; return 2;
@ -313,7 +328,8 @@ CheckForCompilerFeature(
static int static int
CheckForLinkerFeature( CheckForLinkerFeature(
const char *option) char **options,
int count)
{ {
STARTUPINFO si; STARTUPINFO si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
@ -322,7 +338,8 @@ CheckForLinkerFeature(
char msg[300]; char msg[300];
BOOL ok; BOOL ok;
HANDLE hProcess, h, pipeThreads[2]; HANDLE hProcess, h, pipeThreads[2];
char cmdline[100]; int i;
char cmdline[255];
hProcess = GetCurrentProcess(); hProcess = GetCurrentProcess();
@ -368,7 +385,11 @@ CheckForLinkerFeature(
* Append our option for testing. * Append our option for testing.
*/ */
lstrcat(cmdline, option); for (i = 0; i < count; i++) {
lstrcat(cmdline, " \"");
lstrcat(cmdline, options[i]);
lstrcat(cmdline, "\"");
}
ok = CreateProcess( ok = CreateProcess(
NULL, /* Module name. */ NULL, /* Module name. */
@ -388,7 +409,7 @@ CheckForLinkerFeature(
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
(300-chars), 0); (300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2; return 2;
@ -433,7 +454,9 @@ CheckForLinkerFeature(
return !(strstr(Out.buffer, "LNK1117") != NULL || return !(strstr(Out.buffer, "LNK1117") != NULL ||
strstr(Err.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL ||
strstr(Out.buffer, "LNK4044") != NULL || strstr(Out.buffer, "LNK4044") != NULL ||
strstr(Err.buffer, "LNK4044") != NULL); strstr(Err.buffer, "LNK4044") != NULL ||
strstr(Out.buffer, "LNK4224") != NULL ||
strstr(Err.buffer, "LNK4224") != NULL);
} }
static DWORD WINAPI static DWORD WINAPI
@ -479,9 +502,9 @@ IsIn(
static const char * static const char *
GetVersionFromFile( GetVersionFromFile(
const char *filename, const char *filename,
const char *match) const char *match,
int numdots)
{ {
size_t cbBuffer = 100;
static char szBuffer[100]; static char szBuffer[100];
char *szResult = NULL; char *szResult = NULL;
FILE *fp = fopen(filename, "rt"); FILE *fp = fopen(filename, "rt");
@ -491,16 +514,17 @@ GetVersionFromFile(
* Read data until we see our match string. * Read data until we see our match string.
*/ */
while (fgets(szBuffer, cbBuffer, fp) != NULL) { while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
LPSTR p, q; LPSTR p, q;
p = strstr(szBuffer, match); p = strstr(szBuffer, match);
if (p != NULL) { if (p != NULL) {
/* /*
* Skip to first digit. * Skip to first digit after the match.
*/ */
while (*p && !isdigit(*p)) { p += strlen(match);
while (*p && !isdigit((unsigned char)*p)) {
++p; ++p;
} }
@ -509,13 +533,13 @@ GetVersionFromFile(
*/ */
q = p; q = p;
while (*q && (isalnum(*q) || *q == '.')) { while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
&& !strchr("ab", q[-1])) || --numdots))) {
++q; ++q;
} }
memcpy(szBuffer, p, q - p); *q = 0;
szBuffer[q-p] = 0; szResult = p;
szResult = szBuffer;
break; break;
} }
} }
@ -538,7 +562,7 @@ typedef struct list_item_t {
static list_item_t * static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value) list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{ {
list_item_t *itemPtr = malloc(sizeof(list_item_t)); list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
if (itemPtr) { if (itemPtr) {
itemPtr->key = strdup(key); itemPtr->key = strdup(key);
itemPtr->value = strdup(value); itemPtr->value = strdup(value);
@ -587,9 +611,7 @@ SubstituteFile(
const char *substitutions, const char *substitutions,
const char *filename) const char *filename)
{ {
size_t cbBuffer = 1024;
static char szBuffer[1024], szCopy[1024]; static char szBuffer[1024], szCopy[1024];
char *szResult = NULL;
list_item_t *substPtr = NULL; list_item_t *substPtr = NULL;
FILE *fp, *sp; FILE *fp, *sp;
@ -602,7 +624,7 @@ SubstituteFile(
sp = fopen(substitutions, "rt"); sp = fopen(substitutions, "rt");
if (sp != NULL) { if (sp != NULL) {
while (fgets(szBuffer, cbBuffer, sp) != NULL) { while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
unsigned char *ks, *ke, *vs, *ve; unsigned char *ks, *ke, *vs, *ve;
ks = (unsigned char*)szBuffer; ks = (unsigned char*)szBuffer;
while (ks && *ks && isspace(*ks)) ++ks; while (ks && *ks && isspace(*ks)) ++ks;
@ -619,7 +641,7 @@ SubstituteFile(
} }
/* debug: dump the list */ /* debug: dump the list */
#ifdef _DEBUG #ifndef NDEBUG
{ {
int n = 0; int n = 0;
list_item_t *p = NULL; list_item_t *p = NULL;
@ -633,7 +655,7 @@ SubstituteFile(
* Run the substitutions over each line of the input * Run the substitutions over each line of the input
*/ */
while (fgets(szBuffer, cbBuffer, fp) != NULL) { while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
list_item_t *p = NULL; list_item_t *p = NULL;
for (p = substPtr; p != NULL; p = p->nextPtr) { for (p = substPtr; p != NULL; p = p->nextPtr) {
char *m = strstr(szBuffer, p->key); char *m = strstr(szBuffer, p->key);
@ -650,7 +672,7 @@ SubstituteFile(
memcpy(szBuffer, szCopy, sizeof(szCopy)); memcpy(szBuffer, szCopy, sizeof(szCopy));
} }
} }
printf(szBuffer); printf("%s", szBuffer);
} }
list_free(&substPtr); list_free(&substPtr);
@ -659,6 +681,17 @@ SubstituteFile(
return 0; return 0;
} }
BOOL FileExists(LPCTSTR szPath)
{
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
DWORD pathAttr = GetFileAttributes(szPath);
return (pathAttr != INVALID_FILE_ATTRIBUTES &&
!(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
}
/* /*
* QualifyPath -- * QualifyPath --
* *
@ -672,17 +705,105 @@ QualifyPath(
const char *szPath) const char *szPath)
{ {
char szCwd[MAX_PATH + 1]; char szCwd[MAX_PATH + 1];
char szTmp[MAX_PATH + 1];
char *p; GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
GetCurrentDirectory(MAX_PATH, szCwd);
while ((p = strchr(szPath, '/')) && *p)
*p = '\\';
PathCombine(szTmp, szCwd, szPath);
PathCanonicalize(szCwd, szTmp);
printf("%s\n", szCwd); printf("%s\n", szCwd);
return 0; return 0;
} }
/*
* Implements LocateDependency for a single directory. See that command
* for an explanation.
* Returns 0 if found after printing the directory.
* Returns 1 if not found but no errors.
* Returns 2 on any kind of error
* Basically, these are used as exit codes for the process.
*/
static int LocateDependencyHelper(const char *dir, const char *keypath)
{
HANDLE hSearch;
char path[MAX_PATH+1];
size_t dirlen;
int keylen, ret;
WIN32_FIND_DATA finfo;
if (dir == NULL || keypath == NULL)
return 2; /* Have no real error reporting mechanism into nmake */
dirlen = strlen(dir);
if ((dirlen + 3) > sizeof(path))
return 2;
strncpy(path, dir, dirlen);
strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
keylen = strlen(keypath);
#if 0 /* This function is not available in Visual C++ 6 */
/*
* Use numerics 0 -> FindExInfoStandard,
* 1 -> FindExSearchLimitToDirectories,
* as these are not defined in Visual C++ 6
*/
hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
hSearch = FindFirstFile(path, &finfo);
#endif
if (hSearch == INVALID_HANDLE_VALUE)
return 1; /* Not found */
/* Loop through all subdirs checking if the keypath is under there */
ret = 1; /* Assume not found */
do {
int sublen;
/*
* We need to check it is a directory despite the
* FindExSearchLimitToDirectories in the above call. See SDK docs
*/
if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
continue;
sublen = strlen(finfo.cFileName);
if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
continue; /* Path does not fit, assume not matched */
strncpy(path+dirlen+1, finfo.cFileName, sublen);
path[dirlen+1+sublen] = '\\';
strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
if (FileExists(path)) {
/* Found a match, print to stdout */
path[dirlen+1+sublen] = '\0';
QualifyPath(path);
ret = 0;
break;
}
} while (FindNextFile(hSearch, &finfo));
FindClose(hSearch);
return ret;
}
/*
* LocateDependency --
*
* Locates a dependency for a package.
* keypath - a relative path within the package directory
* that is used to confirm it is the correct directory.
* The search path for the package directory is currently only
* the parent and grandparent of the current working directory.
* If found, the command prints
* name_DIRPATH=<full path of located directory>
* and returns 0. If not found, does not print anything and returns 1.
*/
static int LocateDependency(const char *keypath)
{
size_t i;
int ret;
static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
ret = LocateDependencyHelper(paths[i], keypath);
if (ret == 0)
return ret;
}
return ret;
}
/* /*
* Local variables: * Local variables:
* mode: c * mode: c