From dd4a3b583a0ebe61b9e87dc42304b36e6e446945 Mon Sep 17 00:00:00 2001 From: Kim Grasman Date: Wed, 13 Jul 2016 15:14:45 +0200 Subject: [PATCH 001/305] Redefine Poco assertions for static analysis Static analyzers typically don't do cross-translation unit analysis, so they don't understand that most of the Poco::Bugcheck methods never return. Unfortunately, some of them also don't understand noreturn annotations (see e.g. http://en.cppreference.com/w/cpp/language/attributes), so decorating Bugcheck doesn't help. Instead redefine all the Poco assertion macros to just call abort() iff we're parsed by a known static analyzer. --- Foundation/include/Poco/Bugcheck.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Foundation/include/Poco/Bugcheck.h b/Foundation/include/Poco/Bugcheck.h index 941676029..12f5ca252 100644 --- a/Foundation/include/Poco/Bugcheck.h +++ b/Foundation/include/Poco/Bugcheck.h @@ -81,6 +81,25 @@ protected: // // useful macros (these automatically supply line number and file name) // +#if defined(__KLOCWORK__) || defined(__clang_analyzer__) + +// Short-circuit these macros when under static analysis. +// Ideally, static analysis tools should understand and reason correctly about +// noreturn methods such as Bugcheck::bugcheck. In practice, they don't. +// Help them by turning these macros into 'abort' as described here: +// https://developer.klocwork.com/documentation/en/insight/10-1/tuning-cc-analysis#Usingthe__KLOCWORK__macro + +#include // for abort +#define poco_assert_dbg(cond) do { if (!(cond)) abort(); } while (0) +#define poco_assert_msg_dbg(cond, text) do { if (!(cond)) abort(); } while (0) +#define poco_assert(cond) do { if (!(cond)) abort(); } while (0) +#define poco_assert_msg(cond, text) do { if (!(cond)) abort(); } while (0) +#define poco_check_ptr(ptr) do { if (!(ptr)) abort(); } while (0) +#define poco_bugcheck() do { abort(); } while (0) +#define poco_bugcheck_msg(msg) do { abort(); } while (0) + +#else // defined(__KLOCWORK__) || defined(__clang_analyzer__) + #if defined(_DEBUG) #define poco_assert_dbg(cond) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 @@ -112,6 +131,7 @@ protected: #define poco_bugcheck_msg(msg) \ Poco::Bugcheck::bugcheck(msg, __FILE__, __LINE__) +#endif // defined(__KLOCWORK__) || defined(__clang_analyzer__) #define poco_unexpected() \ Poco::Bugcheck::unexpected(__FILE__, __LINE__); From de0f4e58b51ed1cdf91ba7550ff8aa20e7d819c3 Mon Sep 17 00:00:00 2001 From: Francis ANDRE Date: Tue, 23 Aug 2016 08:42:16 +0200 Subject: [PATCH 002/305] Added a new 'useenv' parameter ('env' | 'noenv'), defaulted to 'env' To be used with msbuild for specifying to use the environement variables or the %LOCALAPPDATA%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.X.user.props --- buildwin.cmd | 130 ++++++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/buildwin.cmd b/buildwin.cmd index 154b5586d..ef7b6619b 100644 --- a/buildwin.cmd +++ b/buildwin.cmd @@ -1,4 +1,5 @@ @echo off +setlocal enableextensions setlocal enabledelayedexpansion rem @@ -17,7 +18,7 @@ rem Modified by Guenter Obiltschnig. rem rem Usage: rem ------ -rem buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL [VERBOSITY [LOGGER] ] ] +rem buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL] [ENV] [VERBOSITY [LOGGER] ] ] rem VS_VERSION: 90|100|110|120|140 rem ACTION: build|rebuild|clean rem LINKMODE: static_mt|static_md|shared|all @@ -26,18 +27,12 @@ rem PLATFORM: Win32|x64|WinCE|WEC2013 rem SAMPLES: samples|nosamples rem TESTS: tests|notests rem TOOL: devenv|vcexpress|wdexpress|msbuild +rem ENV: env|noenv (active only with msbuild, defaulted to env) rem VERBOSITY quiet|minimal|normal|detailed|diagnostic rem LOGGER see msbuild /? rem rem VS_VERSION is required argument. Default is build all. -rem Change MYSQL_DIR to match your setup -set MYSQL_DIR=C:\PROGRA~1\MySQL\MYSQLS~1.5 -set MYSQL_INCLUDE=%MYSQL_DIR%\include -set MYSQL_LIB=%MYSQL_DIR%\lib -set INCLUDE=%INCLUDE%;%MYSQL_INCLUDE% -set LIB=%LIB%;%MYSQL_LIB% - set POCO_BASE=%CD% set PATH=%POCO_BASE%\bin64;%POCO_BASE%\bin;%PATH% @@ -45,16 +40,52 @@ rem VS_VERSION {90 | 100 | 110 | 120 | 140} if "%1"=="" goto usage set VS_VERSION=vs%1 set VS_64_BIT_ENV=VC\bin\x86_amd64\vcvarsx86_amd64.bat + shift /1 +rem ACTION [build|rebuild|clean] +set ACTION=%1 +if "%ACTION%"=="" (set ACTION=build) +if not "%ACTION%"=="build" ( +if not "%ACTION%"=="rebuild" ( +if not "%ACTION%"=="clean" goto usage)) + +shift /1 +rem LINKMODE [static_mt|static_md|shared|all] +set LINK_MODE=%1 +if "%LINK_MODE%"=="" (set LINK_MODE=all) +if not "%LINK_MODE%"=="static_mt" ( +if not "%LINK_MODE%"=="static_md" ( +if not "%LINK_MODE%"=="shared" ( +if not "%LINK_MODE%"=="all" goto usage))) + +rem CONFIGURATION [release|debug|both] +set CONFIGURATION=%2 +if "%CONFIGURATION%"=="" (set CONFIGURATION=both) +if not "%CONFIGURATION%"=="release" ( +if not "%CONFIGURATION%"=="debug" ( +if not "%CONFIGURATION%"=="both" goto usage)) rem PLATFORM [Win32|x64|WinCE|WEC2013] -set PLATFORM=%4 +set PLATFORM=%3 if "%PLATFORM%"=="" (set PLATFORM=Win32) if not "%PLATFORM%"=="Win32" ( if not "%PLATFORM%"=="x64" ( if not "%PLATFORM%"=="WinCE" ( if not "%PLATFORM%"=="WEC2013" goto usage))) +if "%PLATFORM%"=="Win32" (set PLATFORM_SUFFIX=) else ( +if "%PLATFORM%"=="x64" (set PLATFORM_SUFFIX=_x64) else ( +if "%PLATFORM%"=="WinCE" (set PLATFORM_SUFFIX=_CE) else ( +if "%PLATFORM%"=="WEC2013" (set PLATFORM_SUFFIX=_WEC2013)))) + +rem SAMPLES [samples|nosamples] +set SAMPLES=%4 +if "%SAMPLES%"=="" (set SAMPLES=samples) + +rem TESTS [tests|notests] +set TESTS=%5 +if "%TESTS%"=="" (set TESTS=notests) + if not defined VCINSTALLDIR ( if %VS_VERSION%==vs90 ( if %PLATFORM%==x64 ( @@ -104,6 +135,19 @@ if not defined VSINSTALLDIR ( goto :EOF ) +set VCPROJ_EXT=vcproj +if %VS_VERSION%==vs100 (set VCPROJ_EXT=vcxproj) +if %VS_VERSION%==vs110 (set VCPROJ_EXT=vcxproj) +if %VS_VERSION%==vs120 (set VCPROJ_EXT=vcxproj) +if %VS_VERSION%==vs140 (set VCPROJ_EXT=vcxproj) + + +rem ENV env|noenv +set USEENV=%7 +if "%USEENV%"=="" (set USEENV=env) +if not "%USEENV%"=="env" ( +if not "%USEENV%"=="noenv" goto usage) + rem VERBOSITY quiet|minimal|normal|detailed set VERBOSITY=%8 if "%VERBOSITY%"=="" (set VERBOSITY=minimal) @@ -113,17 +157,8 @@ if not "%VERBOSITY%"=="normal" ( if not "%VERBOSITY%"=="detailed" ( if not "%VERBOSITY%"=="diagnostic" goto usage)))) -rem LOGGER see msbuild /? -set LOGGER=%9 - -set VCPROJ_EXT=vcproj -if %VS_VERSION%==vs100 (set VCPROJ_EXT=vcxproj) -if %VS_VERSION%==vs110 (set VCPROJ_EXT=vcxproj) -if %VS_VERSION%==vs120 (set VCPROJ_EXT=vcxproj) -if %VS_VERSION%==vs140 (set VCPROJ_EXT=vcxproj) - -if "%7"=="" goto use_devenv -set BUILD_TOOL=%7 +if "%6"=="" goto use_devenv +set BUILD_TOOL=%6 goto use_custom :use_devenv set BUILD_TOOL=devenv @@ -132,22 +167,32 @@ if "%VS_VERSION%"=="vs110" (set BUILD_TOOL=msbuild) if "%VS_VERSION%"=="vs120" (set BUILD_TOOL=msbuild) if "%VS_VERSION%"=="vs140" (set BUILD_TOOL=msbuild) :use_custom -if not "%BUILD_TOOL%"=="msbuild" (set USEENV=/useenv) if "%BUILD_TOOL%"=="msbuild" ( set ACTIONSW=/t: set CONFIGSW=/p:Configuration= set EXTRASW=/m set USEENV=/p:UseEnv=true + if "%USEENV%"=="noenv" set USEENV=/p:UseEnv=false set BUILD_TOOL_FLAGS=/clp:NoSummary set BUILD_TOOL_FLAGS=!BUILD_TOOL_FLAGS! /nologo /v:%VERBOSITY% - if not %LOGGER%X==X ( - set BUILD_TOOL_FLAGS=!BUILD_TOOL_FLAGS! /logger:%LOGGER% - ) ) if not "%BUILD_TOOL%"=="msbuild" ( + set USEENV=/useenv set ACTIONSW=/ ) + + +rem LOGGER see msbuild /? +set LOGGER=%9 +if not "%LOGGER%"=="" ( + if "%BUILD_TOOL%"=="msbuild" ( + if not %LOGGER%X==X ( + set BUILD_TOOL_FLAGS=!BUILD_TOOL_FLAGS! /logger:%LOGGER% + ) + ) +) + if "%VS_VERSION%"=="vs100" (goto msbuildok) if "%VS_VERSION%"=="vs110" (goto msbuildok) if "%VS_VERSION%"=="vs120" (goto msbuildok) @@ -158,32 +203,6 @@ if "%BUILD_TOOL%"=="msbuild" ( ) :msbuildok -rem ACTION [build|rebuild|clean] -set ACTION=%1 -if "%ACTION%"=="" (set ACTION=build) -if not "%ACTION%"=="build" ( -if not "%ACTION%"=="rebuild" ( -if not "%ACTION%"=="clean" goto usage)) - -rem LINKMODE [static_mt|static_md|shared|all] -set LINK_MODE=%2 -if "%LINK_MODE%"=="" (set LINK_MODE=all) -if not "%LINK_MODE%"=="static_mt" ( -if not "%LINK_MODE%"=="static_md" ( -if not "%LINK_MODE%"=="shared" ( -if not "%LINK_MODE%"=="all" goto usage))) - -rem CONFIGURATION [release|debug|both] -set CONFIGURATION=%3 -if "%CONFIGURATION%"=="" (set CONFIGURATION=both) -if not "%CONFIGURATION%"=="release" ( -if not "%CONFIGURATION%"=="debug" ( -if not "%CONFIGURATION%"=="both" goto usage)) - -if "%PLATFORM%"=="Win32" (set PLATFORM_SUFFIX=) else ( -if "%PLATFORM%"=="x64" (set PLATFORM_SUFFIX=_x64) else ( -if "%PLATFORM%"=="WinCE" (set PLATFORM_SUFFIX=_CE) else ( -if "%PLATFORM%"=="WEC2013" (set PLATFORM_SUFFIX=_WEC2013)))) if "%PLATFORM%"=="WEC2013" ( if "%WEC2013_PLATFORM%"=="" ( @@ -197,14 +216,6 @@ if %VS_VERSION%==vs120 (set EXTRASW=/m /p:VisualStudioVersion=12.0) if %VS_VERSION%==vs140 (set EXTRASW=/m /p:VisualStudioVersion=14.0) ) -rem SAMPLES [samples|nosamples] -set SAMPLES=%5 -if "%SAMPLES%"=="" (set SAMPLES=samples) - -rem TESTS [tests|notests] -set TESTS=%6 -if "%TESTS%"=="" (set TESTS=notests) - set DEBUG_SHARED=0 set RELEASE_SHARED=0 @@ -569,7 +580,7 @@ exit /b 1 :usage echo Usage: echo ------ -echo buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL [VERBOSITY] ] +echo buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL] {ENV] [VERBOSITY] echo VS_VERSION: "90|100|110|120|140" echo ACTION: "build|rebuild|clean" echo LINKMODE: "static_mt|static_md|shared|all" @@ -578,6 +589,7 @@ echo PLATFORM: "Win32|x64|WinCE|WEC2013" echo SAMPLES: "samples|nosamples" echo TESTS: "tests|notests" echo TOOL: "devenv|vcexpress|wdexpress|msbuild" +echo ENV: "env|noenv" (active only with msbuild, defaulted to env) echo VERBOSITY: "quiet|minimal|normal|detailed|diagnostic" only for msbuild echo. echo Default is build all. From 0268de2aad9a5b90a85f3b75f5a3d514c330b3a1 Mon Sep 17 00:00:00 2001 From: Francis ANDRE Date: Tue, 23 Aug 2016 08:42:53 +0200 Subject: [PATCH 003/305] Set useenv parameters to noenv --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 37627b96a..9f65ccd18 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -388,7 +388,7 @@ build_script: $verbosity='minimal'; $process = Start-Process -PassThru -nnw -Wait -FilePath "$env:poco_base\buildwin.cmd" -RSO cout -RSE cerr ` - -EA Stop -Args "$env:vsver build $env:linkmode $env:configuration $env:platform samples tests msbuild $verbosity $logger"; + -EA Stop -Args "$env:vsver build $env:linkmode $env:configuration $env:platform samples tests msbuild env $verbosity $logger"; gc cout; gc cerr; Write-Host -ForegroundColor Yellow '>>> current directory is ' $(get-location).Path; } From ff2d8b65c7351894114be089eb78caa91ee3adac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 5 Sep 2016 08:37:47 +0200 Subject: [PATCH 004/305] Revert "GH #1050 JSON: fix gcc -Wshadow warnings" --- Foundation/include/Poco/Nullable.h | 20 ++++++++++---------- JSON/include/Poco/JSON/Array.h | 8 ++++---- JSON/include/Poco/JSON/Object.h | 12 ++++++------ JSON/include/Poco/JSON/PrintHandler.h | 4 ++-- JSON/src/Array.cpp | 4 ++-- JSON/src/Object.cpp | 12 ++++++------ JSON/src/ParseHandler.cpp | 6 +++--- JSON/src/PrintHandler.cpp | 12 ++++++------ 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Foundation/include/Poco/Nullable.h b/Foundation/include/Poco/Nullable.h index 7857ffe68..adceafd87 100644 --- a/Foundation/include/Poco/Nullable.h +++ b/Foundation/include/Poco/Nullable.h @@ -74,9 +74,9 @@ public: { } - Nullable(const C& rValue): + Nullable(const C& value): /// Creates a Nullable with the given value. - _value(rValue), + _value(value), _isNull(false) { } @@ -93,10 +93,10 @@ public: { } - Nullable& assign(const C& rValue) + Nullable& assign(const C& value) /// Assigns a value to the Nullable. { - _value = rValue; + _value = value; _isNull = false; return *this; } @@ -116,10 +116,10 @@ public: return *this; } - Nullable& operator = (const C& rValue) + Nullable& operator = (const C& value) /// Assigns a value to the Nullable. { - return assign(rValue); + return assign(value); } Nullable& operator = (const Nullable& other) @@ -148,10 +148,10 @@ public: return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value); } - bool operator == (const C& rValue) const + bool operator == (const C& value) const /// Compares Nullable with value for equality { - return (!_isNull && _value == rValue); + return (!_isNull && _value == value); } bool operator == (const NullType&) const @@ -160,10 +160,10 @@ public: return _isNull; } - bool operator != (const C& rValue) const + bool operator != (const C& value) const /// Compares Nullable with value for non equality { - return !(*this == rValue); + return !(*this == value); } bool operator != (const Nullable& other) const diff --git a/JSON/include/Poco/JSON/Array.h b/JSON/include/Poco/JSON/Array.h index 3fef77237..54769460c 100644 --- a/JSON/include/Poco/JSON/Array.h +++ b/JSON/include/Poco/JSON/Array.h @@ -300,9 +300,9 @@ public: throw BadCastException(); } - void convert(bool& rValue) const + void convert(bool& value) const { - rValue = !_val.isNull() && _val->size() > 0; + value = !_val.isNull() && _val->size() > 0; } void convert(float&) const @@ -439,9 +439,9 @@ public: throw BadCastException(); } - void convert(bool& rValue) const + void convert(bool& value) const { - rValue = _val.size() > 0; + value = _val.size() > 0; } void convert(float&) const diff --git a/JSON/include/Poco/JSON/Object.h b/JSON/include/Poco/JSON/Object.h index ac3c4e455..a14e022d3 100644 --- a/JSON/include/Poco/JSON/Object.h +++ b/JSON/include/Poco/JSON/Object.h @@ -216,8 +216,8 @@ private: if (indent > 0) out << std::endl; typename C::const_iterator it = container.begin(); - typename C::const_iterator itEnd = container.end(); - for (; it != itEnd;) + typename C::const_iterator end = container.end(); + for (; it != end;) { for(unsigned int i = 0; i < indent; i++) out << ' '; @@ -405,9 +405,9 @@ public: throw BadCastException(); } - void convert(bool& rValue) const + void convert(bool& value) const { - rValue = !_val.isNull() && _val->size() > 0; + value = !_val.isNull() && _val->size() > 0; } void convert(float&) const @@ -547,9 +547,9 @@ public: throw BadCastException(); } - void convert(bool& rValue) const + void convert(bool& value) const { - rValue = _val.size() > 0; + value = _val.size() > 0; } void convert(float&) const diff --git a/JSON/include/Poco/JSON/PrintHandler.h b/JSON/include/Poco/JSON/PrintHandler.h index de95539c1..b063565ad 100644 --- a/JSON/include/Poco/JSON/PrintHandler.h +++ b/JSON/include/Poco/JSON/PrintHandler.h @@ -119,9 +119,9 @@ private: }; -inline void PrintHandler::setIndent(unsigned newIndent) +inline void PrintHandler::setIndent(unsigned indent) { - _indent = newIndent; + _indent = indent; } diff --git a/JSON/src/Array.cpp b/JSON/src/Array.cpp index 94a5866ac..d49c01077 100644 --- a/JSON/src/Array.cpp +++ b/JSON/src/Array.cpp @@ -149,10 +149,10 @@ Array::operator const Poco::Dynamic::Array& () const if (!_pArray) { ValueVec::const_iterator it = _values.begin(); - ValueVec::const_iterator itEnd = _values.end(); + ValueVec::const_iterator end = _values.end(); _pArray = new Poco::Dynamic::Array; int index = 0; - for (; it != itEnd; ++it, ++index) + for (; it != end; ++it, ++index) { if (isObject(it)) { diff --git a/JSON/src/Object.cpp b/JSON/src/Object.cpp index d23f52fc6..d81fa3e81 100644 --- a/JSON/src/Object.cpp +++ b/JSON/src/Object.cpp @@ -113,8 +113,8 @@ void Object::stringify(std::ostream& out, unsigned int indent, int step) const const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const { ValueMap::const_iterator it = _values.begin(); - ValueMap::const_iterator itEnd = _values.end(); - for (; it != itEnd; ++it) + ValueMap::const_iterator end = _values.end(); + for (; it != end; ++it) { if (it->first == **iter) return it->first; } @@ -130,8 +130,8 @@ void Object::set(const std::string& key, const Dynamic::Var& value) if (_preserveInsOrder) { KeyPtrList::iterator it = _keys.begin(); - KeyPtrList::iterator itEnd = _keys.end(); - for (; it != itEnd; ++it) + KeyPtrList::iterator end = _keys.end(); + for (; it != end; ++it) { if (key == **it) return; } @@ -173,9 +173,9 @@ Object::operator const Poco::DynamicStruct& () const if (!_pStruct) { ValueMap::const_iterator it = _values.begin(); - ValueMap::const_iterator itEnd = _values.end(); + ValueMap::const_iterator end = _values.end(); _pStruct = new Poco::DynamicStruct; - for (; it != itEnd; ++it) + for (; it != end; ++it) { if (isObject(it)) { diff --git a/JSON/src/ParseHandler.cpp b/JSON/src/ParseHandler.cpp index cb1cb248b..74296493a 100644 --- a/JSON/src/ParseHandler.cpp +++ b/JSON/src/ParseHandler.cpp @@ -122,20 +122,20 @@ void ParseHandler::key(const std::string& k) } -void ParseHandler::setValue(const Var& rValue) +void ParseHandler::setValue(const Var& value) { Var parent = _stack.top(); if ( parent.type() == typeid(Array::Ptr) ) { Array::Ptr arr = parent.extract(); - arr->add(rValue); + arr->add(value); } else if ( parent.type() == typeid(Object::Ptr) ) { poco_assert_dbg(!_key.empty()); Object::Ptr obj = parent.extract(); - obj->set(_key, rValue); + obj->set(_key, value); _key.clear(); } } diff --git a/JSON/src/PrintHandler.cpp b/JSON/src/PrintHandler.cpp index 92bc6d09f..d88ee37ff 100644 --- a/JSON/src/PrintHandler.cpp +++ b/JSON/src/PrintHandler.cpp @@ -23,18 +23,18 @@ namespace Poco { namespace JSON { -PrintHandler::PrintHandler(unsigned newIndent): +PrintHandler::PrintHandler(unsigned indent): _out(std::cout), - _indent(newIndent), + _indent(indent), _array(0), _objStart(true) { } -PrintHandler::PrintHandler(std::ostream& out, unsigned newIndent): +PrintHandler::PrintHandler(std::ostream& out, unsigned indent): _out(out), - _indent(newIndent), + _indent(indent), _array(0), _objStart(true) { @@ -172,10 +172,10 @@ void PrintHandler::value(UInt64 v) #endif -void PrintHandler::value(const std::string& rValue) +void PrintHandler::value(const std::string& value) { arrayValue(); - Stringifier::formatString(rValue, _out); + Stringifier::formatString(value, _out); _objStart = false; } From 60f5d630b38b99e931f75a3189e3a51de53758b9 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Sep 2016 15:25:41 +0200 Subject: [PATCH 005/305] fixed a unused warning --- Foundation/src/Process.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Foundation/src/Process.cpp b/Foundation/src/Process.cpp index 845611166..d3e7a5d5a 100644 --- a/Foundation/src/Process.cpp +++ b/Foundation/src/Process.cpp @@ -47,6 +47,7 @@ namespace return envbuf; } +#if defined(POCO_OS_FAMILY_VMS) void setEnvironmentVariables(const Poco::Process::Env& env) { for (Poco::Process::Env::const_iterator it = env.begin(); it != env.end(); ++it) @@ -54,6 +55,7 @@ namespace Poco::Environment::set(it->first, it->second); } } +#endif } From d074e5e6eab72d2b2728e01a9b30d6d6f29d137f Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Sep 2016 16:30:59 +0200 Subject: [PATCH 006/305] fixed warnings with GCC on Linux --- Net/src/Socket.cpp | 6 ++++-- Net/src/SocketImpl.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index 5f1726418..0d4758c39 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -148,7 +148,8 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce if (epollfd < 0) { char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); + int rc = strerror_r(errno, buf, sizeof(buf)); + poco_assert (rc == 0); SocketImpl::error(std::string("Can't create epoll queue: ") + buf); } @@ -160,8 +161,9 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) { char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); + int rc = strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); + poco_assert (rc == 0); SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf); } } diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 40bda76a2..e74a767b9 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -429,7 +429,8 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (epollfd < 0) { char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); + int rc = strerror_r(errno, buf, sizeof(buf)); + poco_assert (rc == 0); error(std::string("Can't create epoll queue: ") + buf); } @@ -446,8 +447,9 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) { char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); + int rc = strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); + poco_assert (rc == 0); error(std::string("Can't insert socket to epoll queue: ") + buf); } From c0906ab5aa3afd69c921c1e737a68c8a3770a51f Mon Sep 17 00:00:00 2001 From: CREMARENCO Cosmin Date: Tue, 6 Sep 2016 17:18:25 +0200 Subject: [PATCH 007/305] Fix failing testStartsWith: startsWith/endsWith will dereference invalid string iterator when the prefix/suffix is longer than the actual length of the string --- Foundation/include/Poco/String.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Foundation/include/Poco/String.h b/Foundation/include/Poco/String.h index f1d379f6f..da12d1c04 100644 --- a/Foundation/include/Poco/String.h +++ b/Foundation/include/Poco/String.h @@ -627,7 +627,7 @@ template bool startsWith(const S& str, const S& prefix) /// Tests whether the string starts with the given prefix. { - return equal(prefix.begin(), prefix.end(), str.begin()); + return str.size() >= prefix.size() && equal(prefix.begin(), prefix.end(), str.begin()); } @@ -635,7 +635,7 @@ template bool endsWith(const S& str, const S& suffix) /// Tests whether the string ends with the given suffix. { - return equal(suffix.rbegin(), suffix.rend(), str.rbegin()); + return str.size() >= suffix.size() && equal(suffix.rbegin(), suffix.rend(), str.rbegin()); } From f62ee1466d8026b47e76a03e2ff96a7f60fbf511 Mon Sep 17 00:00:00 2001 From: zosrothko Date: Wed, 7 Sep 2016 21:27:19 +0200 Subject: [PATCH 008/305] Issue with gcc strerror_r in Net/Socket.cpp@151 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All Travis jobs fail with ```src/Socket.cpp: In static member function ‘static int Poco::Net::Socket::select(Poco::Net::Socket::SocketList&, Poco::Net::Socket::SocketList&, Poco::Net::Socket::SocketList&, const Poco::Timespan&)’: src/Socket.cpp:151:47: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive] src/Socket.cpp:164:49: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive] ``` From man strerror_r ``` int strerror_r(int errnum, char *buf, size_t buflen); /* XSI-compliant */ char *strerror_r(int errnum, char *buf, size_t bufle); /* GNU-specific */ Feature Test Macro Requirements for glibc (see feature_test_macros(7)): The XSI-compliant version of strerror_r() is provided if: (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE Otherwise, the GNU-specific version is provided. ``` --- build/config/Linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/config/Linux b/build/config/Linux index 39bdc8e81..40ef8f059 100644 --- a/build/config/Linux +++ b/build/config/Linux @@ -69,7 +69,7 @@ RELEASEOPT_LINK = -O2 # # System Specific Flags # -SYSFLAGS = -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DPOCO_HAVE_FD_EPOLL -DPOCO_HAVE_ADDRINFO -DPOCO_HAVE_LIBRESOLV +SYSFLAGS = -D_XOPEN_SOURCE=600 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DPOCO_HAVE_FD_EPOLL -DPOCO_HAVE_ADDRINFO -DPOCO_HAVE_LIBRESOLV # # System Specific Libraries From 28ff1f2530ea9f808b0dbc8bd6eaec70d19de6ae Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 8 Sep 2016 09:36:28 +0200 Subject: [PATCH 009/305] fixed strerror_r issue --- Net/src/Socket.cpp | 6 ++---- Net/src/SocketImpl.cpp | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index 0d4758c39..935308d81 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -148,8 +148,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce if (epollfd < 0) { char buf[1024]; - int rc = strerror_r(errno, buf, sizeof(buf)); - poco_assert (rc == 0); + (void) strerror_r(errno, buf, sizeof(buf)); SocketImpl::error(std::string("Can't create epoll queue: ") + buf); } @@ -161,9 +160,8 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) { char buf[1024]; - int rc = strerror_r(errno, buf, sizeof(buf)); + (void) strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); - poco_assert (rc == 0); SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf); } } diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index e74a767b9..4d0bbe422 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -429,8 +429,7 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (epollfd < 0) { char buf[1024]; - int rc = strerror_r(errno, buf, sizeof(buf)); - poco_assert (rc == 0); + (void) strerror_r(errno, buf, sizeof(buf)); error(std::string("Can't create epoll queue: ") + buf); } @@ -447,9 +446,8 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) { char buf[1024]; - int rc = strerror_r(errno, buf, sizeof(buf)); + (void) strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); - poco_assert (rc == 0); error(std::string("Can't insert socket to epoll queue: ") + buf); } From 20c7392c21d73ad8a167e863782944e313966928 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 8 Sep 2016 10:10:39 +0200 Subject: [PATCH 010/305] giving up on strerror_r --- Net/src/Socket.cpp | 8 ++------ Net/src/SocketImpl.cpp | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index 935308d81..0dd1c8851 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -147,9 +147,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce epollfd = epoll_create(epollSize); if (epollfd < 0) { - char buf[1024]; - (void) strerror_r(errno, buf, sizeof(buf)); - SocketImpl::error(std::string("Can't create epoll queue: ") + buf); + SocketImpl::error("Can't create epoll queue"); } for (struct epoll_event* e = eventsIn; e != eventLast; ++e) @@ -159,10 +157,8 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce { if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) { - char buf[1024]; - (void) strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); - SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf); + SocketImpl::error("Can't insert socket to epoll queue: "); } } } diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 4d0bbe422..1357b3501 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -428,9 +428,7 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) int epollfd = epoll_create(1); if (epollfd < 0) { - char buf[1024]; - (void) strerror_r(errno, buf, sizeof(buf)); - error(std::string("Can't create epoll queue: ") + buf); + error("Can't create epoll queue"); } struct epoll_event evin; @@ -445,10 +443,8 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) { - char buf[1024]; - (void) strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); - error(std::string("Can't insert socket to epoll queue: ") + buf); + error("Can't insert socket to epoll queue"); } Poco::Timespan remainingTime(timeout); From 9cb7979dc98ae9106905a8d609a31749c93fcbdb Mon Sep 17 00:00:00 2001 From: zosrothko Date: Fri, 9 Sep 2016 09:25:39 +0200 Subject: [PATCH 011/305] Fix space issue with the msbuild's logger path With ```LOGGER='"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"';``` ```if (not "%LOGGER%"==""``` evaluate to ```Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll""=="" was unexpected at this time``` --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 9f65ccd18..1a266261b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -384,7 +384,7 @@ build_script: } if ($env:builder -eq "msbuild") { - $logger='"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"'; + $logger='"C:\Progra~1\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"'; $verbosity='minimal'; $process = Start-Process -PassThru -nnw -Wait -FilePath "$env:poco_base\buildwin.cmd" -RSO cout -RSE cerr ` From eb01c3f5396a5639b51df93a7986a9504a4fb463 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 11 Sep 2016 01:40:28 +0200 Subject: [PATCH 012/305] don't include connection string in exception message --- Data/src/SessionPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/src/SessionPool.cpp b/Data/src/SessionPool.cpp index 40b74d2a3..be87fb1c1 100644 --- a/Data/src/SessionPool.cpp +++ b/Data/src/SessionPool.cpp @@ -82,7 +82,7 @@ Session SessionPool::get() _idleSessions.push_front(pHolder); ++_nSessions; } - else throw SessionPoolExhaustedException(_connector, _connectionString); + else throw SessionPoolExhaustedException(_connector); } PooledSessionHolderPtr pHolder(_idleSessions.front()); From 762e1ff899aa816f75d9456af48ee3a6d69c91f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 12 Sep 2016 18:53:26 +0200 Subject: [PATCH 013/305] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d771181e7..1773923fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,8 @@ --- If you think you've found a bug or would like to see a feature in one of the [upcoming releases](https://github.com/pocoproject/poco/milestones), file an [issue](https://github.com/pocoproject/poco/issues). Please make sure that your explanations are clear and coherent; do the homework of understanding the problem and searching for existing solutions before posting. +Possible security issues or vulnerabilities can also be reported via email directly to the core team security pocoproject.org. + If you're in a hurry, the fastest way to have bugs fixed or features added are code contributions. Good code contributions, to be precise; if you want to contribute, read on ... --- From df37d79f8848d96a990b86610e9148b987a9bc64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 12 Sep 2016 18:53:58 +0200 Subject: [PATCH 014/305] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1773923fb..7fc2afa31 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ --- If you think you've found a bug or would like to see a feature in one of the [upcoming releases](https://github.com/pocoproject/poco/milestones), file an [issue](https://github.com/pocoproject/poco/issues). Please make sure that your explanations are clear and coherent; do the homework of understanding the problem and searching for existing solutions before posting. -Possible security issues or vulnerabilities can also be reported via email directly to the core team security pocoproject.org. +Possible security issues or vulnerabilities can also be reported via email directly to the core team security AT pocoproject.org. If you're in a hurry, the fastest way to have bugs fixed or features added are code contributions. Good code contributions, to be precise; if you want to contribute, read on ... From 1fa6f34882ab2799e1c2bf4a777c15ea688b0d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 12 Sep 2016 18:54:25 +0200 Subject: [PATCH 015/305] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7fc2afa31..8c9e1c3b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing --- -## Bug Reports and Feature requests +## Bug Reports and Feature Requests --- If you think you've found a bug or would like to see a feature in one of the [upcoming releases](https://github.com/pocoproject/poco/milestones), file an [issue](https://github.com/pocoproject/poco/issues). Please make sure that your explanations are clear and coherent; do the homework of understanding the problem and searching for existing solutions before posting. From 251cb4aa2c71b8f095fed15ef897c9fa3c0b60fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 12 Sep 2016 19:35:37 +0200 Subject: [PATCH 016/305] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7e67491b7..49a5eb18e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Build Status - Travis: [![Travis Build Status](https://travis-ci.org/pocoproject/poco.png?branch=develop)](https://travis-ci.org/pocoproject/poco) - AppVeyor: [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/7iyrx3f233s3akae)](https://ci.appveyor.com/project/obiltschnig/poco) +- [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/370/badge)](https://bestpractices.coreinfrastructure.org/projects/370) ![alt text][logo] From 75a43b8723d66861ab5457e4a8e737aa80a54f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Tue, 13 Sep 2016 07:15:12 +0200 Subject: [PATCH 017/305] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8c9e1c3b8..239272ffd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ --- If you think you've found a bug or would like to see a feature in one of the [upcoming releases](https://github.com/pocoproject/poco/milestones), file an [issue](https://github.com/pocoproject/poco/issues). Please make sure that your explanations are clear and coherent; do the homework of understanding the problem and searching for existing solutions before posting. -Possible security issues or vulnerabilities can also be reported via email directly to the core team security AT pocoproject.org. +Possible security issues or vulnerabilities can also be reported via email directly to the core team security AT pocoproject.org. The core team will respond to security issues within 24 hours. If you're in a hurry, the fastest way to have bugs fixed or features added are code contributions. Good code contributions, to be precise; if you want to contribute, read on ... From dfb03273c67b617b16d0f678110fb94d08aa6bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Tue, 13 Sep 2016 07:16:40 +0200 Subject: [PATCH 018/305] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 49a5eb18e..ab7a0caaa 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ To start using POCO, see the [Guided Tour](http://pocoproject.org/docs/00100-Gui POCO has an active user and contributing community, please visit our [web site](http://pocoproject.org), [forum](http://pocoproject.org/forum) and [blog](http://pocoproject.org/blog). Answers to POCO-related questions can also be found on [Stack Overflow](http://stackoverflow.com/questions/tagged/poco-libraries). +Please see [CONTRIBUTING](CONTRIBUTING.md) for submitting bugs, feature requests or security issues. + ---- In regards to Boost, in spite of some functional overlapping, POCO is best thought of as a Boost complement (rather than replacement). From 2701c2e0ca1233b5e5f20ea94450c9acdddc6428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Tue, 13 Sep 2016 07:17:16 +0200 Subject: [PATCH 019/305] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab7a0caaa..bc13a2b4d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ To start using POCO, see the [Guided Tour](http://pocoproject.org/docs/00100-Gui POCO has an active user and contributing community, please visit our [web site](http://pocoproject.org), [forum](http://pocoproject.org/forum) and [blog](http://pocoproject.org/blog). Answers to POCO-related questions can also be found on [Stack Overflow](http://stackoverflow.com/questions/tagged/poco-libraries). -Please see [CONTRIBUTING](CONTRIBUTING.md) for submitting bugs, feature requests or security issues. +Please see [CONTRIBUTING](CONTRIBUTING.md) for submitting contributions, bugs reports, feature requests or security issues. ---- In regards to Boost, in spite of some functional overlapping, From fbbf197fd2a779c1f533ba6b71e05ac179b0fcde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Tue, 13 Sep 2016 07:45:35 +0200 Subject: [PATCH 020/305] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc13a2b4d..90f1024d0 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ POrtable COmponents C++ Libraries are: - Open Source, licensed under the [Boost Software License](https://spdx.org/licenses/BSL-1.0). ---- -To start using POCO, see the [Guided Tour](http://pocoproject.org/docs/00100-GuidedTour.html) and [Getting Started](http://pocoproject.org/docs/00200-GettingStarted.html) documents. +To start using POCO, see the [Guided Tour](https://pocoproject.org/docs/00100-GuidedTour.html) and [Getting Started](https://pocoproject.org/docs/00200-GettingStarted.html) documents. ---- -POCO has an active user and contributing community, please visit our [web site](http://pocoproject.org), [forum](http://pocoproject.org/forum) and [blog](http://pocoproject.org/blog). -Answers to POCO-related questions can also be found on [Stack Overflow](http://stackoverflow.com/questions/tagged/poco-libraries). +POCO has an active user and contributing community, please visit our [web site](https://pocoproject.org), [forum](https://pocoproject.org/forum) and [blog](https://pocoproject.org/blog). +Answers to POCO-related questions can also be found on [Stack Overflow](https://stackoverflow.com/questions/tagged/poco-libraries). Please see [CONTRIBUTING](CONTRIBUTING.md) for submitting contributions, bugs reports, feature requests or security issues. From ae3c4a4ba31d6d140d4dc01a4185f6f1fa4173f7 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 13 Sep 2016 11:37:12 +0200 Subject: [PATCH 021/305] fixed some warnings and minor issues detected by clang-analyzer Conflicts: Data/src/RecordSet.cpp --- Data/src/RecordSet.cpp | 6 ++---- Foundation/src/StreamCopier.cpp | 4 ++-- Net/src/HTTPResponse.cpp | 1 + Net/src/MailMessage.cpp | 5 ++++- Net/src/MultipartReader.cpp | 8 ++++---- Net/src/QuotedPrintableDecoder.cpp | 2 +- NetSSL_OpenSSL/src/ConsoleCertificateHandler.cpp | 2 +- PageCompiler/src/PageReader.cpp | 4 ++-- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Data/src/RecordSet.cpp b/Data/src/RecordSet.cpp index b630a3153..555fe2a03 100644 --- a/Data/src/RecordSet.cpp +++ b/Data/src/RecordSet.cpp @@ -256,8 +256,7 @@ bool RecordSet::moveFirst() return true; } - std::size_t currentRow = _currentRow; - currentRow = 0; + std::size_t currentRow = 0; while (!isAllowed(currentRow)) { if (currentRow >= rc - 1) return false; @@ -303,8 +302,7 @@ bool RecordSet::moveLast() { if (storageRowCount() > 0) { - std::size_t currentRow = _currentRow; - currentRow = storageRowCount() - 1; + std::size_t currentRow = subTotalRowCount() - 1; if (!isFiltered()) { _currentRow = currentRow; diff --git a/Foundation/src/StreamCopier.cpp b/Foundation/src/StreamCopier.cpp index f0c4445b1..92f923ec6 100644 --- a/Foundation/src/StreamCopier.cpp +++ b/Foundation/src/StreamCopier.cpp @@ -119,7 +119,7 @@ Poco::UInt64 StreamCopier::copyToString64(std::istream& istr, std::string& str, std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr) { - char c; + char c = 0; std::streamsize len = 0; istr.get(c); while (istr && ostr) @@ -135,7 +135,7 @@ std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostr #if defined(POCO_HAVE_INT64) Poco::UInt64 StreamCopier::copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr) { - char c; + char c = 0; Poco::UInt64 len = 0; istr.get(c); while (istr && ostr) diff --git a/Net/src/HTTPResponse.cpp b/Net/src/HTTPResponse.cpp index cf6a47b4f..8782d3cc8 100644 --- a/Net/src/HTTPResponse.cpp +++ b/Net/src/HTTPResponse.cpp @@ -242,6 +242,7 @@ void HTTPResponse::read(std::istream& istr) while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); } if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP reason string too long"); if (ch == '\r') ch = istr.get(); + if (ch != '\n') throw MessageException("Unterminated HTTP response line"); HTTPMessage::read(istr); ch = istr.get(); diff --git a/Net/src/MailMessage.cpp b/Net/src/MailMessage.cpp index 69a6d88c1..54ee3c104 100644 --- a/Net/src/MailMessage.cpp +++ b/Net/src/MailMessage.cpp @@ -105,18 +105,21 @@ namespace poco_check_ptr (pPS); NameValueCollection::ConstIterator it = header.begin(); NameValueCollection::ConstIterator end = header.end(); + bool added = false; for (; it != end; ++it) { - if (MailMessage::HEADER_CONTENT_DISPOSITION == it->first) + if (!added && MailMessage::HEADER_CONTENT_DISPOSITION == it->first) { if (it->second == "inline") _pMsg->addContent(pPS, cte); else _pMsg->addAttachment("", pPS, cte); + added = true; } pPS->headers().set(it->first, it->second); } + if (!added) delete pPS; } } diff --git a/Net/src/MultipartReader.cpp b/Net/src/MultipartReader.cpp index 1ee9a98e5..d167906d3 100644 --- a/Net/src/MultipartReader.cpp +++ b/Net/src/MultipartReader.cpp @@ -88,13 +88,13 @@ int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length) { if (ch == '\r') { - ch = buf.sbumpc(); // '\n' + buf.sbumpc(); // '\n' } return 0; } else if (ch == '-' && buf.sgetc() == '-') { - ch = buf.sbumpc(); // '-' + buf.sbumpc(); // '-' _lastPart = true; return 0; } @@ -268,7 +268,7 @@ void MultipartReader::guessBoundary() ch = _istr.peek(); } if (ch == '\r' || ch == '\n') - ch = _istr.get(); + _istr.get(); if (_istr.peek() == '\n') _istr.get(); } @@ -281,7 +281,7 @@ void MultipartReader::parseHeader(MessageHeader& messageHeader) messageHeader.clear(); messageHeader.read(_istr); int ch = _istr.get(); - if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get(); + if (ch == '\r' && _istr.peek() == '\n') _istr.get(); } diff --git a/Net/src/QuotedPrintableDecoder.cpp b/Net/src/QuotedPrintableDecoder.cpp index 331d8b148..d664f63ae 100644 --- a/Net/src/QuotedPrintableDecoder.cpp +++ b/Net/src/QuotedPrintableDecoder.cpp @@ -48,7 +48,7 @@ int QuotedPrintableDecoderBuf::readFromDevice() ch = _buf.sbumpc(); if (ch == '\r') { - ch = _buf.sbumpc(); // read \n + _buf.sbumpc(); // read \n } else if (Poco::Ascii::isHexDigit(ch)) { diff --git a/NetSSL_OpenSSL/src/ConsoleCertificateHandler.cpp b/NetSSL_OpenSSL/src/ConsoleCertificateHandler.cpp index 40cf8ce8b..839ea13a9 100644 --- a/NetSSL_OpenSSL/src/ConsoleCertificateHandler.cpp +++ b/NetSSL_OpenSSL/src/ConsoleCertificateHandler.cpp @@ -43,7 +43,7 @@ void ConsoleCertificateHandler::onInvalidCertificate(const void*, VerificationEr std::cout << "The certificate yielded the error: " << errorCert.errorMessage() << "\n\n"; std::cout << "The error occurred in the certificate chain at position " << errorCert.errorDepth() << "\n"; std::cout << "Accept the certificate (y,n)? "; - char c; + char c = 0; std::cin >> c; if (c == 'y' || c == 'Y') errorCert.setIgnoreError(true); diff --git a/PageCompiler/src/PageReader.cpp b/PageCompiler/src/PageReader.cpp index d435ca07f..02a08a110 100644 --- a/PageCompiler/src/PageReader.cpp +++ b/PageCompiler/src/PageReader.cpp @@ -267,7 +267,7 @@ void PageReader::nextToken(std::istream& istr, std::string& token) if (ch == '<' && istr.peek() == '%') { token += "<%"; - ch = istr.get(); + istr.get(); ch = istr.peek(); switch (ch) { @@ -300,7 +300,7 @@ void PageReader::nextToken(std::istream& istr, std::string& token) else if (ch == '%' && istr.peek() == '>') { token += "%>"; - ch = istr.get(); + istr.get(); } else token += (char) ch; } From dcdcee5afab6e8972f1b144ef7e7e884f85e83a3 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 14 Sep 2016 17:06:55 +0200 Subject: [PATCH 022/305] minor fixes for style --- Foundation/include/Poco/Bugcheck.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Foundation/include/Poco/Bugcheck.h b/Foundation/include/Poco/Bugcheck.h index 12f5ca252..06f12c24d 100644 --- a/Foundation/include/Poco/Bugcheck.h +++ b/Foundation/include/Poco/Bugcheck.h @@ -22,6 +22,7 @@ #include "Poco/Foundation.h" #include +#include #if defined(_DEBUG) # include #endif @@ -83,23 +84,26 @@ protected: // #if defined(__KLOCWORK__) || defined(__clang_analyzer__) + // Short-circuit these macros when under static analysis. // Ideally, static analysis tools should understand and reason correctly about -// noreturn methods such as Bugcheck::bugcheck. In practice, they don't. -// Help them by turning these macros into 'abort' as described here: +// noreturn methods such as Bugcheck::bugcheck(). In practice, they don't. +// Help them by turning these macros into std::abort() as described here: // https://developer.klocwork.com/documentation/en/insight/10-1/tuning-cc-analysis#Usingthe__KLOCWORK__macro #include // for abort -#define poco_assert_dbg(cond) do { if (!(cond)) abort(); } while (0) -#define poco_assert_msg_dbg(cond, text) do { if (!(cond)) abort(); } while (0) -#define poco_assert(cond) do { if (!(cond)) abort(); } while (0) -#define poco_assert_msg(cond, text) do { if (!(cond)) abort(); } while (0) -#define poco_check_ptr(ptr) do { if (!(ptr)) abort(); } while (0) -#define poco_bugcheck() do { abort(); } while (0) -#define poco_bugcheck_msg(msg) do { abort(); } while (0) +#define poco_assert_dbg(cond) do { if (!(cond)) std::abort(); } while (0) +#define poco_assert_msg_dbg(cond, text) do { if (!(cond)) std::abort(); } while (0) +#define poco_assert(cond) do { if (!(cond)) std::abort(); } while (0) +#define poco_assert_msg(cond, text) do { if (!(cond)) std::abort(); } while (0) +#define poco_check_ptr(ptr) do { if (!(ptr)) std::abort(); } while (0) +#define poco_bugcheck() do { std::abort(); } while (0) +#define poco_bugcheck_msg(msg) do { std::abort(); } while (0) + #else // defined(__KLOCWORK__) || defined(__clang_analyzer__) + #if defined(_DEBUG) #define poco_assert_dbg(cond) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 @@ -131,8 +135,10 @@ protected: #define poco_bugcheck_msg(msg) \ Poco::Bugcheck::bugcheck(msg, __FILE__, __LINE__) + #endif // defined(__KLOCWORK__) || defined(__clang_analyzer__) + #define poco_unexpected() \ Poco::Bugcheck::unexpected(__FILE__, __LINE__); From e87a8fe962ec3424b73305117343a167afe79b9a Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 15 Sep 2016 12:01:30 +0200 Subject: [PATCH 023/305] handle MySQL connection lost/server gone when starting a transaction --- Data/MySQL/src/SessionHandle.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Data/MySQL/src/SessionHandle.cpp b/Data/MySQL/src/SessionHandle.cpp index 9815e4243..5af93044a 100644 --- a/Data/MySQL/src/SessionHandle.cpp +++ b/Data/MySQL/src/SessionHandle.cpp @@ -150,8 +150,17 @@ void SessionHandle::close() void SessionHandle::startTransaction() { - if (mysql_autocommit(_pHandle, false) != 0) - throw TransactionException("Start transaction failed.", _pHandle); + int rc = mysql_autocommit(_pHandle, false); + if (rc != 0) + { + // retry if connection lost + int err = mysql_errno(_pHandle); + if (err == 2006 /* CR_SERVER_GONE_ERROR */ || err == 2013 /* CR_SERVER_LOST */) + { + rc = mysql_autocommit(_pHandle, false); + } + } + if (rc != 0) throw TransactionException("Start transaction failed.", _pHandle); } From ad1be5fe87a5cc14f602f368b86dd71b080f7f7b Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 20 Sep 2016 20:48:36 +0200 Subject: [PATCH 024/305] fixed GH #1418:Poco::Delegate assignment operator fails to compile for some specializations --- Foundation/include/Poco/Delegate.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Foundation/include/Poco/Delegate.h b/Foundation/include/Poco/Delegate.h index eaed9c3e3..1a6a315e6 100644 --- a/Foundation/include/Poco/Delegate.h +++ b/Foundation/include/Poco/Delegate.h @@ -128,7 +128,6 @@ public: { if (&delegate != this) { - this->_pTarget = delegate._pTarget; this->_receiverObject = delegate._receiverObject; this->_receiverMethod = delegate._receiverMethod; } @@ -341,7 +340,6 @@ public: { if (&delegate != this) { - this->_pTarget = delegate._pTarget; this->_receiverObject = delegate._receiverObject; this->_receiverMethod = delegate._receiverMethod; } From f1b75ec44277a61e12d7b3729bdd54f21af07b1e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 21 Sep 2016 08:31:23 +0200 Subject: [PATCH 025/305] updated .gitattributes linguist settings --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitattributes b/.gitattributes index 8c88af1d7..95c524dd0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -31,3 +31,8 @@ *.png binary *.jpg binary *.gif binary + +# Linguist overrides +.cpp linguist-language=C++ +.h linguist-language=C++ + From 68e3676ddc4e8a868e1e7dba559cba9175cba6e2 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 16:51:13 +0200 Subject: [PATCH 026/305] fixed an unlikely potential memory leak if one of two new fails --- Foundation/include/Poco/ClassLoader.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Foundation/include/Poco/ClassLoader.h b/Foundation/include/Poco/ClassLoader.h index 1dd63a7ac..d8a5682e3 100644 --- a/Foundation/include/Poco/ClassLoader.h +++ b/Foundation/include/Poco/ClassLoader.h @@ -158,11 +158,13 @@ public: if (it == _map.end()) { LibraryInfo li; - li.pLibrary = new SharedLibrary(path); - li.pManifest = new Manif(); + li.pLibrary = 0; + li.pManifest = 0; li.refCount = 1; try { + li.pLibrary = new SharedLibrary(path); + li.pManifest = new Manif(); std::string pocoBuildManifestSymbol("pocoBuildManifest"); pocoBuildManifestSymbol.append(manifest); if (li.pLibrary->hasSymbol("pocoInitializeLibrary")) From 89998df17aa7d7dfe85a7e10d27c17362d311c11 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 16:53:59 +0200 Subject: [PATCH 027/305] bugfix: _null member not initialized in ctor --- Data/include/Poco/Data/Extraction.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Data/include/Poco/Data/Extraction.h b/Data/include/Poco/Data/Extraction.h index 81153c979..9594e5022 100644 --- a/Data/include/Poco/Data/Extraction.h +++ b/Data/include/Poco/Data/Extraction.h @@ -90,7 +90,8 @@ public: AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), _rResult(rResult), _default(), - _extracted(false) + _extracted(false), + _null(false) /// Creates an Extraction object at specified position. /// Uses an empty object T as default value. { @@ -100,7 +101,8 @@ public: AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), _rResult(rResult), _default(def), - _extracted(false) + _extracted(false), + _null(false) /// Creates an Extraction object at specified position. /// Uses the provided def object as default value. { From b0026b6a1c5ffc4f0693d2f6bb66d90284b3e8ec Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:00:20 +0200 Subject: [PATCH 028/305] style fix --- Data/include/Poco/Data/Extraction.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Data/include/Poco/Data/Extraction.h b/Data/include/Poco/Data/Extraction.h index 9594e5022..ddc1f0830 100644 --- a/Data/include/Poco/Data/Extraction.h +++ b/Data/include/Poco/Data/Extraction.h @@ -182,7 +182,6 @@ public: AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), _rResult(rResult), _default() - { _rResult.clear(); } From c9437273543a542a365067d26489be7efe9f4498 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:00:42 +0200 Subject: [PATCH 029/305] style fix --- NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp b/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp index 37c3a47be..67296cd6d 100644 --- a/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp +++ b/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp @@ -132,7 +132,8 @@ std::istream* HTTPSStreamFactory::open(const URI& uri) resolvedURI.setUserInfo(username + ":" + password); authorize = false; } - delete pSession; pSession = 0; + delete pSession; + pSession = 0; ++redirects; retry = true; } From b1004587b265d04de6c6a2986c2ab96b677e4ec3 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:19:55 +0200 Subject: [PATCH 030/305] code cleanup; fixed some issues reported by Klocwork --- Net/include/Poco/Net/ICMPSocket.h | 28 +----------------------- Net/include/Poco/Net/ICMPSocketImpl.h | 31 +++++++++++++++++++++++++++ Net/src/ICMPSocket.cpp | 23 ++++++++++++++++---- Net/src/ICMPSocketImpl.cpp | 19 ++++++---------- 4 files changed, 58 insertions(+), 43 deletions(-) diff --git a/Net/include/Poco/Net/ICMPSocket.h b/Net/include/Poco/Net/ICMPSocket.h index 3b98dd6e8..ebc5d175e 100644 --- a/Net/include/Poco/Net/ICMPSocket.h +++ b/Net/include/Poco/Net/ICMPSocket.h @@ -42,7 +42,7 @@ public: ICMPSocket(const Socket& socket); /// Creates the ICMPSocket with the SocketImpl /// from another socket. The SocketImpl must be - /// a DatagramSocketImpl, otherwise an InvalidArgumentException + /// a ICMPSocketImpl, otherwise an InvalidArgumentException /// will be thrown. ~ICMPSocket(); @@ -84,35 +84,9 @@ protected: /// /// The SocketImpl must be a ICMPSocketImpl, otherwise /// an InvalidArgumentException will be thrown. - -private: - int _dataSize; - int _ttl; - int _timeout; }; -// -// inlines -// -inline int ICMPSocket::dataSize() const -{ - return _dataSize; -} - - -inline int ICMPSocket::ttl() const -{ - return _ttl; -} - - -inline int ICMPSocket::timeout() const -{ - return _timeout; -} - - } } // namespace Poco::Net diff --git a/Net/include/Poco/Net/ICMPSocketImpl.h b/Net/include/Poco/Net/ICMPSocketImpl.h index 771c5a227..b59988e0b 100644 --- a/Net/include/Poco/Net/ICMPSocketImpl.h +++ b/Net/include/Poco/Net/ICMPSocketImpl.h @@ -50,15 +50,46 @@ public: /// /// Returns the time elapsed since the originating request was sent. + int dataSize() const; + /// Returns the data size in bytes. + + int ttl() const; + /// Returns the Time-To-Live value. + + int timeout() const; + /// Returns the socket timeout value. + protected: ~ICMPSocketImpl(); private: ICMPPacket _icmpPacket; + int _ttl; int _timeout; }; +// +// inlines +// +inline int ICMPSocketImpl::dataSize() const +{ + return _icmpPacket.getDataSize(); +} + + +inline int ICMPSocketImpl::ttl() const +{ + return _ttl; +} + + +inline int ICMPSocketImpl::timeout() const +{ + return _timeout; +} + + } } // namespace Poco::Net diff --git a/Net/src/ICMPSocket.cpp b/Net/src/ICMPSocket.cpp index ece9871c3..7e1204fe1 100644 --- a/Net/src/ICMPSocket.cpp +++ b/Net/src/ICMPSocket.cpp @@ -27,10 +27,7 @@ namespace Net { ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout): - Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout)), - _dataSize(dataSize), - _ttl(ttl), - _timeout(timeout) + Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout)) { } @@ -78,4 +75,22 @@ int ICMPSocket::receiveFrom(SocketAddress& address, int flags) } +int ICMPSocket::dataSize() const +{ + return static_cast(impl())->dataSize(); +} + + +int ICMPSocket::ttl() const +{ + return static_cast(impl())->ttl(); +} + + +int ICMPSocket::timeout() const +{ + return static_cast(impl())->timeout(); +} + + } } // namespace Poco::Net diff --git a/Net/src/ICMPSocketImpl.cpp b/Net/src/ICMPSocketImpl.cpp index 2deefbaae..11ebc30d2 100644 --- a/Net/src/ICMPSocketImpl.cpp +++ b/Net/src/ICMPSocketImpl.cpp @@ -19,6 +19,7 @@ #include "Poco/Timespan.h" #include "Poco/Timestamp.h" #include "Poco/Exception.h" +#include "Poco/Buffer.h" using Poco::TimeoutException; @@ -33,6 +34,7 @@ namespace Net { ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout): RawSocketImpl(family, IPPROTO_ICMP), _icmpPacket(family, dataSize), + _ttl(ttl), _timeout(timeout) { setOption(IPPROTO_IP, IP_TTL, ttl); @@ -55,7 +57,7 @@ int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int f int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags) { int maxPacketSize = _icmpPacket.maxPacketSize(); - unsigned char* buffer = new unsigned char[maxPacketSize]; + Poco::Buffer buffer(maxPacketSize); try { @@ -68,31 +70,24 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags) // fake ping responses will cause an endless loop. throw TimeoutException(); } - SocketImpl::receiveFrom(buffer, maxPacketSize, address, flags); + SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags); } - while (!_icmpPacket.validReplyID(buffer, maxPacketSize)); - } - catch (TimeoutException&) - { - delete [] buffer; - throw; + while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)); } catch (Exception&) { - std::string err = _icmpPacket.errorDescription(buffer, maxPacketSize); - delete [] buffer; + std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize); if (!err.empty()) throw ICMPException(err); else throw; } - struct timeval then = _icmpPacket.time(buffer, maxPacketSize); + struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize); struct timeval now = _icmpPacket.time(); int elapsed = (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000; - delete[] buffer; return elapsed; } From 5d750ac8edc4b81a9d186ed5248f8c7df09e9576 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:28:41 +0200 Subject: [PATCH 031/305] fixed issues reported by Klocwork --- Foundation/src/DeflatingStream.cpp | 15 +++++++++++---- Foundation/src/InflatingStream.cpp | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Foundation/src/DeflatingStream.cpp b/Foundation/src/DeflatingStream.cpp index 1adb54fb3..56d7b9146 100644 --- a/Foundation/src/DeflatingStream.cpp +++ b/Foundation/src/DeflatingStream.cpp @@ -27,13 +27,20 @@ DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, StreamType type, int _pOstr(0), _eof(false) { + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.total_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + _zstr.total_out = 0; + _zstr.msg = 0; + _zstr.state = 0; _zstr.zalloc = Z_NULL; _zstr.zfree = Z_NULL; _zstr.opaque = Z_NULL; - _zstr.next_in = 0; - _zstr.avail_in = 0; - _zstr.next_out = 0; - _zstr.avail_out = 0; + _zstr.data_type = 0; + _zstr.adler = 0; + _zstr.reserved = 0; _buffer = new char[DEFLATE_BUFFER_SIZE]; diff --git a/Foundation/src/InflatingStream.cpp b/Foundation/src/InflatingStream.cpp index 77ecb500b..1eac3fa1a 100644 --- a/Foundation/src/InflatingStream.cpp +++ b/Foundation/src/InflatingStream.cpp @@ -16,6 +16,7 @@ #include "Poco/InflatingStream.h" #include "Poco/Exception.h" +#include namespace Poco { @@ -28,13 +29,20 @@ InflatingStreamBuf::InflatingStreamBuf(std::istream& istr, StreamType type): _eof(false), _check(type != STREAM_ZIP) { + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.total_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + _zstr.total_out = 0; + _zstr.msg = 0; + _zstr.state = 0; _zstr.zalloc = Z_NULL; _zstr.zfree = Z_NULL; _zstr.opaque = Z_NULL; - _zstr.next_in = 0; - _zstr.avail_in = 0; - _zstr.next_out = 0; - _zstr.avail_out = 0; + _zstr.data_type = 0; + _zstr.adler = 0; + _zstr.reserved = 0; _buffer = new char[INFLATE_BUFFER_SIZE]; From 34b9b1284ccc54498e56594764e99832a7e1db71 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:31:29 +0200 Subject: [PATCH 032/305] fixed uninitialized _encoding member --- Net/src/MailMessage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Net/src/MailMessage.cpp b/Net/src/MailMessage.cpp index 54ee3c104..3fa4641ba 100644 --- a/Net/src/MailMessage.cpp +++ b/Net/src/MailMessage.cpp @@ -194,6 +194,7 @@ const std::string MailMessage::CTE_BASE64("base64"); MailMessage::MailMessage(PartStoreFactory* pStoreFactory): + _encoding(), _pStoreFactory(pStoreFactory) { Poco::Timestamp now; From 8935e19bbcd357ec2000abf54981caa1f4ff847a Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:39:29 +0200 Subject: [PATCH 033/305] fixed potential memory leak in out-of-memory situations --- Foundation/include/Poco/MemoryPool.h | 2 ++ Foundation/src/MemoryPool.cpp | 29 +++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Foundation/include/Poco/MemoryPool.h b/Foundation/include/Poco/MemoryPool.h index 048c9e199..2ab807031 100644 --- a/Foundation/include/Poco/MemoryPool.h +++ b/Foundation/include/Poco/MemoryPool.h @@ -73,6 +73,8 @@ private: MemoryPool(const MemoryPool&); MemoryPool& operator = (const MemoryPool&); + void clear(); + enum { BLOCK_RESERVE = 128 diff --git a/Foundation/src/MemoryPool.cpp b/Foundation/src/MemoryPool.cpp index ee940fc3f..fb83b7403 100644 --- a/Foundation/src/MemoryPool.cpp +++ b/Foundation/src/MemoryPool.cpp @@ -35,19 +35,35 @@ MemoryPool::MemoryPool(std::size_t blockLength, int preAlloc, int maxAlloc): if (maxAlloc > 0 && maxAlloc < r) r = maxAlloc; _blocks.reserve(r); - for (int i = 0; i < preAlloc; ++i) + + try { - _blocks.push_back(new char[_blockSize]); + for (int i = 0; i < preAlloc; ++i) + { + _blocks.push_back(new char[_blockSize]); + } + } + catch (...) + { + clear(); + throw; } } MemoryPool::~MemoryPool() +{ + clear(); +} + + +void MemoryPool::clear() { for (BlockVec::iterator it = _blocks.begin(); it != _blocks.end(); ++it) { delete [] *it; } + _blocks.clear(); } @@ -77,7 +93,14 @@ void MemoryPool::release(void* ptr) { FastMutex::ScopedLock lock(_mutex); - _blocks.push_back(reinterpret_cast(ptr)); + try + { + _blocks.push_back(reinterpret_cast(ptr)); + } + catch (...) + { + delete [] reinterpret_cast(ptr); + } } From 1bb795e7ede043d3bfcb42ead8dcfe1463b0815f Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:42:01 +0200 Subject: [PATCH 034/305] initialize all members in default ctor --- Data/src/MetaColumn.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Data/src/MetaColumn.cpp b/Data/src/MetaColumn.cpp index c743665a7..a4ecb1ef2 100644 --- a/Data/src/MetaColumn.cpp +++ b/Data/src/MetaColumn.cpp @@ -21,7 +21,12 @@ namespace Poco { namespace Data { -MetaColumn::MetaColumn() +MetaColumn::MetaColumn(): + _length(), + _precision(), + _position(), + _type(), + _nullable() { } From eabae863bbc1fd88cd273cfa6a665c53bdde4a6e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:48:09 +0200 Subject: [PATCH 035/305] fixed uninitialized member in ctor --- Net/src/NetworkInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Net/src/NetworkInterface.cpp b/Net/src/NetworkInterface.cpp index 85ae403f2..359df059b 100644 --- a/Net/src/NetworkInterface.cpp +++ b/Net/src/NetworkInterface.cpp @@ -228,7 +228,8 @@ NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, _pointToPoint(false), _up(false), _running(false), - _mtu(0) + _mtu(0), + _type(NetworkInterface::NI_TYPE_OTHER) { _addressList.push_back(AddressTuple(address, subnetMask, broadcastAddress)); setPhyParams(); From 9bd74daef9b37a27c553a64e3fff21fc7c3ca2fd Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 17:50:28 +0200 Subject: [PATCH 036/305] fixed uninitialized members in ctor --- Data/SQLite/src/Notifier.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Data/SQLite/src/Notifier.cpp b/Data/SQLite/src/Notifier.cpp index 6484b07cd..b279db91c 100644 --- a/Data/SQLite/src/Notifier.cpp +++ b/Data/SQLite/src/Notifier.cpp @@ -25,7 +25,9 @@ namespace SQLite { Notifier::Notifier(const Session& session, EnabledEventType enabled): - _session(session) + _session(session), + _row(), + _enabledEvents() { if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate(); if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit(); @@ -35,7 +37,9 @@ Notifier::Notifier(const Session& session, EnabledEventType enabled): Notifier::Notifier(const Session& session, const Any& value, EnabledEventType enabled): _session(session), - _value(value) + _value(value), + _row(), + _enabledEvents() { if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate(); if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit(); From 9c684af4785a5fdbf2c3e1cbcc07eb3c7d3912e2 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 18:08:36 +0200 Subject: [PATCH 037/305] handle unlikely situation that XML_ParserCreate() fails --- XML/src/ParserEngine.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/XML/src/ParserEngine.cpp b/XML/src/ParserEngine.cpp index 89c2385f1..bd1cdc5dd 100644 --- a/XML/src/ParserEngine.cpp +++ b/XML/src/ParserEngine.cpp @@ -450,19 +450,27 @@ void ParserEngine::init() if (dynamic_cast(_pNamespaceStrategy)) { _parser = XML_ParserCreateNS(_encodingSpecified ? _encoding.c_str() : 0, '\t'); - XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl); + if (_parser) + { + XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl); + } } else if (dynamic_cast(_pNamespaceStrategy)) { _parser = XML_ParserCreateNS(_encodingSpecified ? _encoding.c_str() : 0, '\t'); - XML_SetReturnNSTriplet(_parser, 1); - XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl); + if (_parser) + { + XML_SetReturnNSTriplet(_parser, 1); + XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl); + } } else { _parser = XML_ParserCreate(_encodingSpecified ? _encoding.c_str() : 0); } + if (!_parser) throw XMLException("Cannot create Expat parser"); + XML_SetUserData(_parser, this); XML_SetElementHandler(_parser, handleStartElement, handleEndElement); XML_SetCharacterDataHandler(_parser, handleCharacterData); @@ -720,6 +728,8 @@ int ParserEngine::handleExternalEntityRef(XML_Parser parser, const XML_Char* con if (pInputSource) { XML_Parser extParser = XML_ExternalEntityParserCreate(pThis->_parser, context, 0); + if (!extParser) throw XMLException("Cannot create external entity parser"); + try { pThis->parseExternal(extParser, pInputSource); From 142ad284947f78331c3f9af1240c6876f4e4e857 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 18:10:07 +0200 Subject: [PATCH 038/305] initialize all members in ctor --- Data/src/SQLChannel.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Data/src/SQLChannel.cpp b/Data/src/SQLChannel.cpp index 7c2afaf08..8e7130317 100644 --- a/Data/src/SQLChannel.cpp +++ b/Data/src/SQLChannel.cpp @@ -47,7 +47,10 @@ SQLChannel::SQLChannel(): _table("T_POCO_LOG"), _timeout(1000), _throw(true), - _async(true) + _async(true), + _pid(), + _tid(), + _priority() { } @@ -61,7 +64,10 @@ SQLChannel::SQLChannel(const std::string& connector, _table("T_POCO_LOG"), _timeout(1000), _throw(true), - _async(true) + _async(true), + _pid(), + _tid(), + _priority() { open(); } From b0140637d523defb4b3d019032b38a79035ffd75 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 18:12:56 +0200 Subject: [PATCH 039/305] fix uninitialized member in ctor --- JSON/src/Template.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/JSON/src/Template.cpp b/JSON/src/Template.cpp index 862a7783a..4effd54e2 100644 --- a/JSON/src/Template.cpp +++ b/JSON/src/Template.cpp @@ -350,14 +350,16 @@ private: Template::Template(const Path& templatePath) - : _parts(NULL) + : _parts(0) + , _currentPart(0) , _templatePath(templatePath) { } Template::Template() - : _parts(NULL) + : _parts(0) + , _currentPart(0) { } From 78f954f58ff65a9eb438a44a11ac2ed300e148b2 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 18:15:36 +0200 Subject: [PATCH 040/305] fixed issues reported by Klocwork --- Foundation/include/Poco/Nullable.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Foundation/include/Poco/Nullable.h b/Foundation/include/Poco/Nullable.h index adceafd87..4b23aac6c 100644 --- a/Foundation/include/Poco/Nullable.h +++ b/Foundation/include/Poco/Nullable.h @@ -63,28 +63,32 @@ public: Nullable(): /// Creates an empty Nullable. _value(), - _isNull(true) + _isNull(true), + _null() { } Nullable(const NullType&): /// Creates an empty Nullable. _value(), - _isNull(true) + _isNull(true), + _null() { } Nullable(const C& value): /// Creates a Nullable with the given value. _value(value), - _isNull(false) + _isNull(false), + _null() { } Nullable(const Nullable& other): /// Creates a Nullable by copying another one. _value(other._value), - _isNull(other._isNull) + _isNull(other._isNull), + _null() { } From 18e594e7ffdf552acef90a52869f2cc95342d81e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 18:15:43 +0200 Subject: [PATCH 041/305] fixed issues reported by Klocwork --- Foundation/include/Poco/Thread_POSIX.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Foundation/include/Poco/Thread_POSIX.h b/Foundation/include/Poco/Thread_POSIX.h index 5d43603ed..6963929c5 100644 --- a/Foundation/include/Poco/Thread_POSIX.h +++ b/Foundation/include/Poco/Thread_POSIX.h @@ -132,6 +132,7 @@ private: ThreadData(): thread(0), prio(PRIO_NORMAL_IMPL), + osPrio(), policy(SCHED_OTHER), done(Event::EVENT_MANUALRESET), stackSize(POCO_THREAD_STACK_SIZE), From dd30db6ca9b05c8e5984b35f012ca3ed534913d6 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 26 Sep 2016 19:29:55 +0200 Subject: [PATCH 042/305] fixed Klocwork issues --- Zip/src/ZipFileInfo.cpp | 67 ++++++++++++++++++++++------------ Zip/src/ZipLocalFileHeader.cpp | 67 ++++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 52 deletions(-) diff --git a/Zip/src/ZipFileInfo.cpp b/Zip/src/ZipFileInfo.cpp index c426e247a..e29cd73c8 100644 --- a/Zip/src/ZipFileInfo.cpp +++ b/Zip/src/ZipFileInfo.cpp @@ -101,34 +101,53 @@ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) _localHeaderOffset = getOffsetFromHeader(); parseDateTime(); Poco::UInt16 len = getFileNameLength(); - Poco::Buffer buf(len); - inp.read(buf.begin(), len); - _fileName = std::string(buf.begin(), len); + if (len > 0) + { + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _fileName = std::string(buf.begin(), len); + } if (hasExtraField()) { len = getExtraFieldLength(); - Poco::Buffer xtra(len); - inp.read(xtra.begin(), len); - _extraField = std::string(xtra.begin(), len); - char* ptr = xtra.begin(); - while(ptr <= xtra.begin() + len - 4) { - Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; - Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; - if(id == ZipCommon::ZIP64_EXTRA_ID) { - poco_assert(size >= 8); - if(getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { - setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; - } - if(size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { - setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; - } - if(size >= 8 && getOffsetFromHeader() == ZipCommon::ZIP64_MAGIC) { - setOffset(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; - } - } - else + if (len > 0) + { + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + char* ptr = xtra.begin(); + while (ptr <= xtra.begin() + len - 4) { - ptr += size; + Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); + ptr += 2; + Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); + ptr += 2; + if (id == ZipCommon::ZIP64_EXTRA_ID) + { + poco_assert(size >= 8); + if (getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); + size -= 8; + ptr += 8; + } + if (size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); + size -= 8; + ptr += 8; + } + if (size >= 8 && getOffsetFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setOffset(ZipUtil::get64BitValue(ptr, 0)); + size -= 8; + ptr += 8; + } + } + else + { + ptr += size; + } } } } diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp index a2a7eb7ba..7b7f63a1c 100644 --- a/Zip/src/ZipLocalFileHeader.cpp +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -131,10 +131,13 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) poco_assert (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) < ZipCommon::CM_UNUSED); parseDateTime(); Poco::UInt16 len = getFileNameLength(); - Poco::Buffer buf(len); - inp.read(buf.begin(), len); - _fileName = std::string(buf.begin(), len); - + if (len > 0) + { + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _fileName = std::string(buf.begin(), len); + } + if (!searchCRCAndSizesAfterData()) { _crc32 = getCRCFromHeader(); @@ -145,33 +148,41 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) if (hasExtraField()) { len = getExtraFieldLength(); - Poco::Buffer xtra(len); - inp.read(xtra.begin(), len); - _extraField = std::string(xtra.begin(), len); - char* ptr = xtra.begin(); - while (ptr <= xtra.begin() + len - 4) + if (len > 0) { - Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; - Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; - if (id == ZipCommon::ZIP64_EXTRA_ID) - { - poco_assert(size >= 8); - if (getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) - { - setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; - } - if (size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) - { - setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; - } - } - else - { - ptr += size; - } + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + char* ptr = xtra.begin(); + while (ptr <= xtra.begin() + len - 4) + { + Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); + ptr += 2; + Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); + ptr += 2; + if (id == ZipCommon::ZIP64_EXTRA_ID) + { + poco_assert(size >= 8); + if (getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); + size -= 8; + ptr += 8; + } + if (size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); + size -= 8; + ptr += 8; + } + } + else + { + ptr += size; + } + } } } - } From 61e0561182312bc1c155be6aef96b54e2af6424b Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 28 Sep 2016 12:31:48 +0200 Subject: [PATCH 043/305] fixed GH #1429: exception thrown in MongoDB when using replicaset --- MongoDB/include/Poco/MongoDB/Element.h | 48 ++++++++++++++++++++++++++ MongoDB/src/Document.cpp | 5 ++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/MongoDB/include/Poco/MongoDB/Element.h b/MongoDB/include/Poco/MongoDB/Element.h index 346bef60c..e383adb7c 100644 --- a/MongoDB/include/Poco/MongoDB/Element.h +++ b/MongoDB/include/Poco/MongoDB/Element.h @@ -247,6 +247,54 @@ inline void BSONWriter::write(NullValue& from) } +struct BSONTimestamp +{ + Poco::Timestamp ts; + Poco::Int32 inc; +}; + + +// BSON Timestamp +// spec: int64 +template<> +struct ElementTraits +{ + enum { TypeId = 0x11 }; + + static std::string toString(const BSONTimestamp& value, int indent = 0) + { + std::string result; + result.append(1, '"'); + result.append(DateTimeFormatter::format(value.ts, "%Y-%m-%dT%H:%M:%s%z")); + result.append(1, ' '); + result.append(NumberFormatter::format(value.inc)); + result.append(1, '"'); + return result; + } +}; + + +template<> +inline void BSONReader::read(BSONTimestamp& to) +{ + Poco::Int64 value; + _reader >> value; + to.inc = value & 0xffffffff; + value >>= 32; + to.ts = Timestamp::fromEpochTime(static_cast(value)); +} + + +template<> +inline void BSONWriter::write(BSONTimestamp& from) +{ + Poco::Int64 value = from.ts.epochMicroseconds() / 1000; + value <<= 32; + value += from.inc; + _writer << value; +} + + // BSON 64-bit integer // spec: int64 template<> diff --git a/MongoDB/src/Document.cpp b/MongoDB/src/Document.cpp index 43f652358..a968f1780 100644 --- a/MongoDB/src/Document.cpp +++ b/MongoDB/src/Document.cpp @@ -118,6 +118,9 @@ void Document::read(BinaryReader& reader) case ElementTraits::TypeId: element = new ConcreteElement(name, Poco::Timestamp()); break; + case ElementTraits::TypeId: + element = new ConcreteElement(name, BSONTimestamp()); + break; case ElementTraits::TypeId: element = new ConcreteElement(name, NullValue(0)); break; @@ -133,7 +136,7 @@ void Document::read(BinaryReader& reader) default: { std::stringstream ss; - ss << "Element " << name << " contains an unsupported type " << std::hex << (int) type; + ss << "Element " << name << " contains an unsupported type 0x" << std::hex << (int) type; throw Poco::NotImplementedException(ss.str()); } //TODO: x0F -> JavaScript code with scope From 5d8faa371e82898529b3932c7aa9fff75a0afde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Thu, 29 Sep 2016 17:41:37 +0200 Subject: [PATCH 044/305] added URISyntaxException; better error handling in URIStreamOpener --- Foundation/include/Poco/Exception.h | 2 ++ Foundation/src/Exception.cpp | 3 ++- Foundation/src/URI.cpp | 14 +++++------ Foundation/src/URIStreamOpener.cpp | 37 +++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Foundation/include/Poco/Exception.h b/Foundation/include/Poco/Exception.h index fb76576c3..5e582e045 100644 --- a/Foundation/include/Poco/Exception.h +++ b/Foundation/include/Poco/Exception.h @@ -255,6 +255,8 @@ POCO_DECLARE_EXCEPTION(Foundation_API, OpenFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, WriteFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, ReadFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, UnknownURISchemeException, RuntimeException) +POCO_DECLARE_EXCEPTION(Foundation_API, TooManyURIRedirectsException, RuntimeException) +POCO_DECLARE_EXCEPTION(Foundation_API, URISyntaxException, SyntaxException) POCO_DECLARE_EXCEPTION(Foundation_API, ApplicationException, Exception) POCO_DECLARE_EXCEPTION(Foundation_API, BadCastException, RuntimeException) diff --git a/Foundation/src/Exception.cpp b/Foundation/src/Exception.cpp index fd1eacd66..738d4dfc8 100644 --- a/Foundation/src/Exception.cpp +++ b/Foundation/src/Exception.cpp @@ -179,7 +179,8 @@ POCO_IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file") POCO_IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file") POCO_IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file") POCO_IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme") - +POCO_IMPLEMENT_EXCEPTION(TooManyURIRedirectsException, RuntimeException, "Too many URI redirects") +POCO_IMPLEMENT_EXCEPTION(URISyntaxException, SyntaxException, "Bad URI syntax") POCO_IMPLEMENT_EXCEPTION(ApplicationException, Exception, "Application exception") POCO_IMPLEMENT_EXCEPTION(BadCastException, RuntimeException, "Bad cast exception") diff --git a/Foundation/src/URI.cpp b/Foundation/src/URI.cpp index 0f375bd29..e0cbb241a 100644 --- a/Foundation/src/URI.cpp +++ b/Foundation/src/URI.cpp @@ -660,9 +660,9 @@ void URI::decode(const std::string& str, std::string& decodedStr, bool plusAsSpa if (inQuery && plusAsSpace && c == '+') c = ' '; else if (c == '%') { - if (it == end) throw SyntaxException("URI encoding: no hex digit following percent sign", str); + if (it == end) throw URISyntaxException("URI encoding: no hex digit following percent sign", str); char hi = *it++; - if (it == end) throw SyntaxException("URI encoding: two hex digits must follow percent sign", str); + if (it == end) throw URISyntaxException("URI encoding: two hex digits must follow percent sign", str); char lo = *it++; if (hi >= '0' && hi <= '9') c = hi - '0'; @@ -670,7 +670,7 @@ void URI::decode(const std::string& str, std::string& decodedStr, bool plusAsSpa c = hi - 'A' + 10; else if (hi >= 'a' && hi <= 'f') c = hi - 'a' + 10; - else throw SyntaxException("URI encoding: not a hex digit"); + else throw URISyntaxException("URI encoding: not a hex digit"); c *= 16; if (lo >= '0' && lo <= '9') c += lo - '0'; @@ -678,7 +678,7 @@ void URI::decode(const std::string& str, std::string& decodedStr, bool plusAsSpa c += lo - 'A' + 10; else if (lo >= 'a' && lo <= 'f') c += lo - 'a' + 10; - else throw SyntaxException("URI encoding: not a hex digit"); + else throw URISyntaxException("URI encoding: not a hex digit"); } decodedStr += c; } @@ -732,7 +732,7 @@ void URI::parse(const std::string& uri) if (it != end && *it == ':') { ++it; - if (it == end) throw SyntaxException("URI scheme must be followed by authority or path", uri); + if (it == end) throw URISyntaxException("URI scheme must be followed by authority or path", uri); setScheme(scheme); if (*it == '/') { @@ -786,7 +786,7 @@ void URI::parseHostAndPort(std::string::const_iterator& it, const std::string::c // IPv6 address ++it; while (it != end && *it != ']') host += *it++; - if (it == end) throw SyntaxException("unterminated IPv6 address"); + if (it == end) throw URISyntaxException("unterminated IPv6 address"); ++it; } else @@ -804,7 +804,7 @@ void URI::parseHostAndPort(std::string::const_iterator& it, const std::string::c if (NumberParser::tryParse(port, nport) && nport > 0 && nport < 65536) _port = (unsigned short) nport; else - throw SyntaxException("bad or invalid port number", port); + throw URISyntaxException("bad or invalid port number", port); } else _port = getWellKnownPort(); } diff --git a/Foundation/src/URIStreamOpener.cpp b/Foundation/src/URIStreamOpener.cpp index 825fb1c60..14ffa6d3a 100644 --- a/Foundation/src/URIStreamOpener.cpp +++ b/Foundation/src/URIStreamOpener.cpp @@ -62,13 +62,34 @@ std::istream* URIStreamOpener::open(const std::string& pathOrURI) const std::string scheme(uri.getScheme()); FactoryMap::const_iterator it = _map.find(scheme); if (it != _map.end()) + { return openURI(scheme, uri); + } + else + { + Path path; + if (path.tryParse(pathOrURI, Path::PATH_GUESS)) + return openFile(path); + else + throw UnknownURISchemeException(pathOrURI); + } } - catch (Exception&) + catch (UnknownURISchemeException&) { + throw; + } + catch (TooManyURIRedirectsException&) + { + throw; + } + catch (URISyntaxException&) + { + Path path; + if (path.tryParse(pathOrURI, Path::PATH_GUESS)) + return openFile(path); + else + throw; } - Path path(pathOrURI, Path::PATH_GUESS); - return openFile(path); } @@ -87,6 +108,14 @@ std::istream* URIStreamOpener::open(const std::string& basePathOrURI, const std: return openURI(scheme, uri); } } + catch (UnknownURISchemeException&) + { + throw; + } + catch (TooManyURIRedirectsException&) + { + throw; + } catch (Exception&) { } @@ -176,7 +205,7 @@ std::istream* URIStreamOpener::openURI(const std::string& scheme, const URI& uri ++redirects; } } - throw IOException("Too many redirects while opening URI", uri.toString()); + throw TooManyURIRedirectsException(uri.toString()); } From e87a3a6e45a878d5e8dde82652f97d4ef6b2f481 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 29 Sep 2016 17:44:34 +0200 Subject: [PATCH 045/305] style fix --- Foundation/src/Exception.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Foundation/src/Exception.cpp b/Foundation/src/Exception.cpp index 738d4dfc8..e3cdd7ca7 100644 --- a/Foundation/src/Exception.cpp +++ b/Foundation/src/Exception.cpp @@ -185,4 +185,5 @@ POCO_IMPLEMENT_EXCEPTION(URISyntaxException, SyntaxException, "Bad URI syntax") POCO_IMPLEMENT_EXCEPTION(ApplicationException, Exception, "Application exception") POCO_IMPLEMENT_EXCEPTION(BadCastException, RuntimeException, "Bad cast exception") + } // namespace Poco From a73eef0487398c8756f7a504626d1496f230a868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Thu, 29 Sep 2016 19:06:46 +0200 Subject: [PATCH 046/305] improvement of URIStreamOpener::open() implementation --- Foundation/src/URIStreamOpener.cpp | 49 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Foundation/src/URIStreamOpener.cpp b/Foundation/src/URIStreamOpener.cpp index 14ffa6d3a..b9494c4e2 100644 --- a/Foundation/src/URIStreamOpener.cpp +++ b/Foundation/src/URIStreamOpener.cpp @@ -65,22 +65,15 @@ std::istream* URIStreamOpener::open(const std::string& pathOrURI) const { return openURI(scheme, uri); } - else + else if (scheme.length() <= 1) // could be Windows path { Path path; if (path.tryParse(pathOrURI, Path::PATH_GUESS)) + { return openFile(path); - else - throw UnknownURISchemeException(pathOrURI); + } } - } - catch (UnknownURISchemeException&) - { - throw; - } - catch (TooManyURIRedirectsException&) - { - throw; + throw UnknownURISchemeException(pathOrURI); } catch (URISyntaxException&) { @@ -105,24 +98,32 @@ std::istream* URIStreamOpener::open(const std::string& basePathOrURI, const std: if (it != _map.end()) { uri.resolve(pathOrURI); + scheme = uri.getScheme(); return openURI(scheme, uri); } + else if (scheme.length() <= 1) // could be Windows path + { + Path base; + Path path; + if (base.tryParse(basePathOrURI, Path::PATH_GUESS) && path.tryParse(pathOrURI, Path::PATH_GUESS)) + { + base.resolve(path); + return openFile(base); + } + } + throw UnknownURISchemeException(basePathOrURI); } - catch (UnknownURISchemeException&) - { - throw; - } - catch (TooManyURIRedirectsException&) - { - throw; - } - catch (Exception&) + catch (URISyntaxException&) { + Path base; + Path path; + if (base.tryParse(basePathOrURI, Path::PATH_GUESS) && path.tryParse(pathOrURI, Path::PATH_GUESS)) + { + base.resolve(path); + return openFile(base); + } + else throw; } - Path base(basePathOrURI, Path::PATH_GUESS); - Path path(pathOrURI, Path::PATH_GUESS); - base.resolve(path); - return openFile(base); } From f86dfa82393dfe635ce51c7bb9109115dc896479 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 29 Sep 2016 20:10:10 +0200 Subject: [PATCH 047/305] integrated fixes for #1416 from poco-1.7.6 branch --- Zip/include/Poco/Zip/ZipArchive.h | 1 - Zip/src/AutoDetectStream.cpp | 9 ++++----- Zip/src/Compress.cpp | 15 ++++++++------- Zip/src/Decompress.cpp | 2 +- Zip/src/PartialStream.cpp | 2 +- Zip/src/SkipCallback.cpp | 2 ++ Zip/src/ZipArchiveInfo.cpp | 18 +++++++++++++++--- Zip/src/ZipDataInfo.cpp | 16 ++++++++++------ Zip/src/ZipFileInfo.cpp | 6 +++++- Zip/src/ZipLocalFileHeader.cpp | 8 ++++++-- Zip/src/ZipManipulator.cpp | 2 +- Zip/src/ZipStream.cpp | 12 +++++++----- Zip/src/ZipUtil.cpp | 25 +++++++++---------------- 13 files changed, 69 insertions(+), 49 deletions(-) diff --git a/Zip/include/Poco/Zip/ZipArchive.h b/Zip/include/Poco/Zip/ZipArchive.h index aa5a8498c..150f003e9 100644 --- a/Zip/include/Poco/Zip/ZipArchive.h +++ b/Zip/include/Poco/Zip/ZipArchive.h @@ -24,7 +24,6 @@ #include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipFileInfo.h" #include "Poco/Zip/ZipArchiveInfo.h" - #include #include diff --git a/Zip/src/AutoDetectStream.cpp b/Zip/src/AutoDetectStream.cpp index 1229e3294..3664df9a1 100644 --- a/Zip/src/AutoDetectStream.cpp +++ b/Zip/src/AutoDetectStream.cpp @@ -69,6 +69,7 @@ int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) { _pIstr->seekg(_start, std::ios_base::beg); _reposition = false; + if (!_pIstr->good()) return -1; } if (!_prefix.empty()) @@ -145,11 +146,9 @@ int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) { if (c-1 == byte3) { - // a match, pushback - _pIstr->putback(c); - _pIstr->putback(byte3); - _pIstr->putback(ZipLocalFileHeader::HEADER[1]); - _pIstr->putback(ZipLocalFileHeader::HEADER[0]); + // a match, seek back + _pIstr->seekg(-4, std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); _eofDetected = true; return tempPos; } diff --git a/Zip/src/Compress.cpp b/Zip/src/Compress.cpp index b335a3074..b74333d1a 100644 --- a/Zip/src/Compress.cpp +++ b/Zip/src/Compress.cpp @@ -78,7 +78,7 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, _offset = hdr.getEndPos(); _offset += extraDataSize; _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -89,12 +89,13 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName) { + if (!in.good()) + throw ZipException("Invalid input stream"); + std::string fn = ZipUtil::validZipEntryFileName(fileName); //bypass the header of the input stream and point to the first byte of the data payload in.seekg(h.getDataStartPos(), std::ios_base::beg); - - if (!in.good()) - throw ZipException("Invalid input stream"); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); std::streamoff localHeaderOffset = _offset; ZipLocalFileHeader hdr(h); @@ -161,7 +162,7 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P } _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -229,7 +230,7 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l if (hdr.searchCRCAndSizesAfterData()) _offset += extraDataSize; _files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -314,7 +315,7 @@ ZipArchive Compress::close() centralDirSize64 += entrySize; _offset += entrySize; } - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); Poco::UInt64 numEntries64 = _infos.size(); needZip64 = needZip64 || _offset >= ZipCommon::ZIP64_MAGIC; diff --git a/Zip/src/Decompress.cpp b/Zip/src/Decompress.cpp index 2f94fa949..e01f47e9d 100644 --- a/Zip/src/Decompress.cpp +++ b/Zip/src/Decompress.cpp @@ -39,7 +39,7 @@ Decompress::Decompress(std::istream& in, const Poco::Path& outputDir, bool flatt { _outDir.makeAbsolute(); _outDir.makeDirectory(); - poco_assert (_in.good()); + if (!_in.good()) throw Poco::IOException("Bad input stream"); Poco::File tmp(_outDir); if (!tmp.exists()) { diff --git a/Zip/src/PartialStream.cpp b/Zip/src/PartialStream.cpp index 85587278e..d6d9e302b 100644 --- a/Zip/src/PartialStream.cpp +++ b/Zip/src/PartialStream.cpp @@ -69,7 +69,7 @@ int PartialStreamBuf::readFromDevice(char* buffer, std::streamsize length) _pIstr->clear(); _pIstr->seekg(_start, std::ios_base::beg); if (_pIstr->fail()) - throw Poco::IOException("Failed to reposition in stream"); + throw Poco::IOException("Failed to seek on input stream"); } if (!_prefix.empty()) { diff --git a/Zip/src/SkipCallback.cpp b/Zip/src/SkipCallback.cpp index 20d0ca491..febbd0af6 100644 --- a/Zip/src/SkipCallback.cpp +++ b/Zip/src/SkipCallback.cpp @@ -17,6 +17,7 @@ #include "Poco/Zip/SkipCallback.h" #include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipUtil.h" +#include "Poco/Exception.h" namespace Poco { @@ -39,6 +40,7 @@ bool SkipCallback::handleZipEntry(std::istream& zipStream, const ZipLocalFileHea zipStream.seekg(hdr.getCompressedSize(), std::ios_base::cur); else ZipUtil::sync(zipStream); + if (!zipStream.good()) throw Poco::IOException("Failed to seek on input stream"); return true; } diff --git a/Zip/src/ZipArchiveInfo.cpp b/Zip/src/ZipArchiveInfo.cpp index 9299eb4cb..6985efab3 100644 --- a/Zip/src/ZipArchiveInfo.cpp +++ b/Zip/src/ZipArchiveInfo.cpp @@ -59,12 +59,16 @@ void ZipArchiveInfo::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read archive info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad archive info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); Poco::UInt16 len = getZipCommentSize(); @@ -136,12 +140,16 @@ void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read archive info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad archive info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + std::memset(_rawInfo + ZipCommon::HEADER_SIZE, 0, FULL_HEADER_SIZE - ZipCommon::HEADER_SIZE); // read the rest of the header @@ -164,7 +172,11 @@ void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) ZipUtil::set64BitValue(FULL_HEADER_SIZE + len - offset, _rawInfo, RECORDSIZE_POS); } inp.read(_locInfo, FULL_LOCATOR_SIZE); - poco_assert (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) == 0); + if (inp.gcount() != FULL_LOCATOR_SIZE) + throw Poco::IOException("Failed to read locator"); + if (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad locator header"); + } diff --git a/Zip/src/ZipDataInfo.cpp b/Zip/src/ZipDataInfo.cpp index c2b6bf645..e03b82074 100644 --- a/Zip/src/ZipDataInfo.cpp +++ b/Zip/src/ZipDataInfo.cpp @@ -15,6 +15,7 @@ #include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Exception.h" #include #include @@ -47,10 +48,11 @@ ZipDataInfo::ZipDataInfo(std::istream& in, bool assumeHeaderRead): else { in.read(_rawInfo, ZipCommon::HEADER_SIZE); - if ((!in) || (in.gcount() != ZipCommon::HEADER_SIZE)) - return; + if (in.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read data info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad data info header"); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); // now copy the rest of the header in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _valid = (!in.eof() && in.good()); @@ -87,10 +89,12 @@ ZipDataInfo64::ZipDataInfo64(std::istream& in, bool assumeHeaderRead): else { in.read(_rawInfo, ZipCommon::HEADER_SIZE); - if ((!in) || (in.gcount() != ZipCommon::HEADER_SIZE)) - return; + if (in.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read data info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad data info header"); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // now copy the rest of the header in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _valid = (!in.eof() && in.good()); diff --git a/Zip/src/ZipFileInfo.cpp b/Zip/src/ZipFileInfo.cpp index e29cd73c8..e23d0870e 100644 --- a/Zip/src/ZipFileInfo.cpp +++ b/Zip/src/ZipFileInfo.cpp @@ -87,12 +87,16 @@ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read file info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad file info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _crc32 = getCRCFromHeader(); diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp index 7b7f63a1c..aab16fdf1 100644 --- a/Zip/src/ZipLocalFileHeader.cpp +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -118,13 +118,17 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawHeader, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read local file header"); + if (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad local file header"); } else { std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); - // read the rest of the header + + // read the rest of the header inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED); poco_assert (getMajorVersionNumber() <= 4); // Allow for Zip64 version 4.5 diff --git a/Zip/src/ZipManipulator.cpp b/Zip/src/ZipManipulator.cpp index 5fc00e9ae..73e8e7e1c 100644 --- a/Zip/src/ZipManipulator.cpp +++ b/Zip/src/ZipManipulator.cpp @@ -111,7 +111,7 @@ const ZipLocalFileHeader& ZipManipulator::getForChange(const std::string& zipPat { ZipArchive::FileHeaders::const_iterator it = _in->findHeader(zipPath); if (it == _in->headerEnd()) - throw ZipManipulationException("entry not found: " + zipPath); + throw ZipManipulationException("Entry not found: " + zipPath); if (_changes.find(zipPath) != _changes.end()) throw ZipManipulationException("A change request exists already for entry " + zipPath); diff --git a/Zip/src/ZipStream.cpp b/Zip/src/ZipStream.cpp index fdda20eb2..26514feb5 100644 --- a/Zip/src/ZipStream.cpp +++ b/Zip/src/ZipStream.cpp @@ -177,8 +177,8 @@ int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) Poco::Int32 size = static_cast(nfo.getFullHeaderSize()); _expectedCrc32 = nfo.getCRC32(); const char* rawHeader = nfo.getRawHeader(); - for (Poco::Int32 i = size-1; i >= 0; --i) - _pIstr->putback(rawHeader[i]); + _pIstr->seekg(-size, std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); if (!crcValid()) throw ZipException("CRC failure"); } @@ -215,7 +215,8 @@ void ZipStreamBuf::close(Poco::UInt64& extraDataSize) _ptrOHelper->close(); } _ptrOBuf = 0; - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); + // write an extra datablock if required // or fix the crc entries poco_check_ptr(_pHeader); @@ -248,13 +249,14 @@ void ZipStreamBuf::close(Poco::UInt64& extraDataSize) else { _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); + if (_pHeader->hasExtraField()) // Update sizes in header extension. _pHeader->setZip64Data(); std::string header = _pHeader->createHeader(); _pOstr->write(header.c_str(), static_cast(header.size())); _pOstr->seekp(0, std::ios_base::end); - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); } _pHeader = 0; } diff --git a/Zip/src/ZipUtil.cpp b/Zip/src/ZipUtil.cpp index 069074651..7bdb76dfe 100644 --- a/Zip/src/ZipUtil.cpp +++ b/Zip/src/ZipUtil.cpp @@ -117,31 +117,23 @@ void ZipUtil::sync(std::istream& in) { if (std::memcmp(ZipLocalFileHeader::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipLocalFileHeader::HEADER[3]); - in.putback(ZipLocalFileHeader::HEADER[2]); - in.putback(ZipLocalFileHeader::HEADER[1]); - in.putback(ZipLocalFileHeader::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else if (std::memcmp(ZipArchiveInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipArchiveInfo::HEADER[3]); - in.putback(ZipArchiveInfo::HEADER[2]); - in.putback(ZipArchiveInfo::HEADER[1]); - in.putback(ZipArchiveInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else if (std::memcmp(ZipFileInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipFileInfo::HEADER[3]); - in.putback(ZipFileInfo::HEADER[2]); - in.putback(ZipFileInfo::HEADER[1]); - in.putback(ZipFileInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else { - in.putback(ZipDataInfo::HEADER[3]); - in.putback(ZipDataInfo::HEADER[2]); - in.putback(ZipDataInfo::HEADER[1]); - in.putback(ZipDataInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } return; } @@ -149,6 +141,7 @@ void ZipUtil::sync(std::istream& in) { // we have read 2 bytes, should only be one: putback the last char in.putback(temp[tempPos - 1]); + if (!in.good()) throw Poco::IOException("Failed to putback on input stream"); --tempPos; } } From 48862bf08ef04e640a16f5a557656970a126d802 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Tue, 4 Oct 2016 14:43:01 -0400 Subject: [PATCH 048/305] Use stable_sort to preserve order of IP addresses from DNS --- Net/src/SocketAddress.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Net/src/SocketAddress.cpp b/Net/src/SocketAddress.cpp index 1c2608394..fa5290472 100644 --- a/Net/src/SocketAddress.cpp +++ b/Net/src/SocketAddress.cpp @@ -170,7 +170,7 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress) destruct(); if (socketAddress.family() == IPv4) newIPv4(reinterpret_cast(socketAddress.addr())); -#if defined(POCO_HAVE_IPv6) +#if defined(POCO_HAVE_IPv6) else if (socketAddress.family() == IPv6) newIPv6(reinterpret_cast(socketAddress.addr())); #endif @@ -252,7 +252,7 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber { #if defined(POCO_HAVE_IPv6) // if we get both IPv4 and IPv6 addresses, prefer IPv4 - std::sort(addresses.begin(), addresses.end(), AFLT()); + std::stable_sort(addresses.begin(), addresses.end(), AFLT()); #endif init(addresses[0], portNumber); } @@ -285,7 +285,7 @@ void SocketAddress::init(const std::string& hostAndPort) std::string port; std::string::const_iterator it = hostAndPort.begin(); std::string::const_iterator end = hostAndPort.end(); - + #if defined(POCO_OS_FAMILY_UNIX) if (*it == '/') { From 2817376436f1207a3edc13053e4bcbb12ef8d976 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 10:43:34 +0200 Subject: [PATCH 049/305] increased default XML name pool size, added Document constructor taking name pool size as argument --- XML/include/Poco/DOM/Document.h | 10 +++++++++- XML/include/Poco/XML/NamePool.h | 7 ++++++- XML/src/Document.cpp | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/XML/include/Poco/DOM/Document.h b/XML/include/Poco/DOM/Document.h index 55a353952..070e1e999 100644 --- a/XML/include/Poco/DOM/Document.h +++ b/XML/include/Poco/DOM/Document.h @@ -62,11 +62,15 @@ class XML_API Document: public AbstractContainerNode, public DocumentEvent public: typedef Poco::AutoReleasePool AutoReleasePool; - Document(NamePool* pNamePool = 0); + explicit Document(NamePool* pNamePool = 0); /// Creates a new document. If pNamePool == 0, the document /// creates its own name pool, otherwise it uses the given name pool. /// Sharing a name pool makes sense for documents containing instances /// of the same schema, thus reducing memory usage. + + explicit Document(unsigned long namePoolSize); + /// Creates a new document using a name pool with the given size, which + /// should be a prime number (e.g., 251, 509, 1021, 4093). Document(DocumentType* pDocumentType, NamePool* pNamePool = 0); /// Creates a new document. If pNamePool == 0, the document @@ -74,6 +78,10 @@ public: /// Sharing a name pool makes sense for documents containing instances /// of the same schema, thus reducing memory usage. + Document(DocumentType* pDocumentType, unsigned long namePoolSize); + /// Creates a new document using a name pool with the given size, which + /// should be a prime number (e.g., 251, 509, 1021, 4093). + NamePool& namePool(); /// Returns a pointer to the documents Name Pool. diff --git a/XML/include/Poco/XML/NamePool.h b/XML/include/Poco/XML/NamePool.h index e7c976cfc..7ff81ca5d 100644 --- a/XML/include/Poco/XML/NamePool.h +++ b/XML/include/Poco/XML/NamePool.h @@ -25,6 +25,11 @@ #include "Poco/XML/Name.h" +#ifndef POCO_XML_NAMEPOOL_DEFAULT_SIZE +#define POCO_XML_NAMEPOOL_DEFAULT_SIZE 509 +#endif + + namespace Poco { namespace XML { @@ -37,7 +42,7 @@ class XML_API NamePool /// local name and a qualified name. { public: - NamePool(unsigned long size = 251); + NamePool(unsigned long size = POCO_XML_NAMEPOOL_DEFAULT_SIZE); /// Creates a name pool with room for up to size strings. const Name& insert(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName); diff --git a/XML/src/Document.cpp b/XML/src/Document.cpp index abcac7879..a293f668e 100644 --- a/XML/src/Document.cpp +++ b/XML/src/Document.cpp @@ -57,6 +57,15 @@ Document::Document(NamePool* pNamePool): } +Document::Document(unsigned long namePoolSize): + AbstractContainerNode(0), + _pDocumentType(0), + _pNamePool(new NamePool(namePoolSize)), + _eventSuspendLevel(0) +{ +} + + Document::Document(DocumentType* pDocumentType, NamePool* pNamePool): AbstractContainerNode(0), _pDocumentType(pDocumentType), @@ -79,6 +88,20 @@ Document::Document(DocumentType* pDocumentType, NamePool* pNamePool): } +Document::Document(DocumentType* pDocumentType, unsigned long namePoolSize): + AbstractContainerNode(0), + _pDocumentType(pDocumentType), + _pNamePool(new NamePool(namePoolSize)), + _eventSuspendLevel(0) +{ + if (_pDocumentType) + { + _pDocumentType->duplicate(); + _pDocumentType->setOwnerDocument(this); + } +} + + Document::~Document() { if (_pDocumentType) _pDocumentType->release(); From a53464e784c45d2e38195a2cb2dbbb2d1f8bd397 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 10:53:14 +0200 Subject: [PATCH 050/305] add optional name pool size argument to DOMParser constructor --- XML/include/Poco/DOM/DOMParser.h | 5 ++++- XML/src/DOMParser.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/XML/include/Poco/DOM/DOMParser.h b/XML/include/Poco/DOM/DOMParser.h index 440b60574..1a60c2438 100644 --- a/XML/include/Poco/DOM/DOMParser.h +++ b/XML/include/Poco/DOM/DOMParser.h @@ -40,9 +40,12 @@ class XML_API DOMParser /// support of a WhitespaceFilter. { public: - DOMParser(NamePool* pNamePool = 0); + explicit DOMParser(NamePool* pNamePool = 0); /// Creates a new DOMParser. /// If a NamePool is given, it becomes the Document's NamePool. + + explicit DOMParser(unsigned long namePoolSize); + /// Creates a new DOMParser, using the given name pool size. ~DOMParser(); /// Destroys the DOMParser. diff --git a/XML/src/DOMParser.cpp b/XML/src/DOMParser.cpp index 4360f0f37..5762760ae 100644 --- a/XML/src/DOMParser.cpp +++ b/XML/src/DOMParser.cpp @@ -39,6 +39,15 @@ DOMParser::DOMParser(NamePool* pNamePool): } +DOMParser::DOMParser(unsigned long namePoolSize): + _pNamePool(new NamePool(namePoolSize)), + _filterWhitespace(false) +{ + _saxParser.setFeature(XMLReader::FEATURE_NAMESPACES, true); + _saxParser.setFeature(XMLReader::FEATURE_NAMESPACE_PREFIXES, true); +} + + DOMParser::~DOMParser() { if (_pNamePool) _pNamePool->release(); From bae5b38df0e27e6e639c6cdc3eb60afc016067e7 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 10:59:24 +0200 Subject: [PATCH 051/305] add a load() overload to specify name pool size --- Util/include/Poco/Util/XMLConfiguration.h | 6 ++++++ Util/src/XMLConfiguration.cpp | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Util/include/Poco/Util/XMLConfiguration.h b/Util/include/Poco/Util/XMLConfiguration.h index 539e44df1..43721015d 100644 --- a/Util/include/Poco/Util/XMLConfiguration.h +++ b/Util/include/Poco/Util/XMLConfiguration.h @@ -134,6 +134,12 @@ public: /// Loads the XML document containing the configuration data /// from the given InputSource. + void load(Poco::XML::InputSource* pInputSource, unsigned long namePoolSize); + /// Loads the XML document containing the configuration data + /// from the given InputSource. Uses the give namePoolSize (which + /// should be a suitable prime like 251, 509, 1021, 4093) for the + /// internal DOM Document's name pool. + void load(std::istream& istr); /// Loads the XML document containing the configuration data /// from the given stream. diff --git a/Util/src/XMLConfiguration.cpp b/Util/src/XMLConfiguration.cpp index 9bdbe5a90..e9249f09e 100644 --- a/Util/src/XMLConfiguration.cpp +++ b/Util/src/XMLConfiguration.cpp @@ -123,11 +123,11 @@ XMLConfiguration::~XMLConfiguration() } -void XMLConfiguration::load(Poco::XML::InputSource* pInputSource) +void XMLConfiguration::load(Poco::XML::InputSource* pInputSource, unsigned long namePoolSize) { poco_check_ptr (pInputSource); - Poco::XML::DOMParser parser; + Poco::XML::DOMParser parser(namePoolSize); parser.setFeature(Poco::XML::XMLReader::FEATURE_NAMESPACES, false); parser.setFeature(Poco::XML::DOMParser::FEATURE_FILTER_WHITESPACE, true); Poco::XML::AutoPtr pDoc = parser.parse(pInputSource); @@ -135,6 +135,12 @@ void XMLConfiguration::load(Poco::XML::InputSource* pInputSource) } +void XMLConfiguration::load(Poco::XML::InputSource* pInputSource) +{ + load(pInputSource, POCO_XML_NAMEPOOL_DEFAULT_SIZE); +} + + void XMLConfiguration::load(std::istream& istr) { Poco::XML::InputSource src(istr); From a5d801cc6e6feb7d652e47eea423c3558929b740 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 11:05:36 +0200 Subject: [PATCH 052/305] doc clarifications --- XML/include/Poco/DOM/DOMParser.h | 6 +++++- XML/include/Poco/XML/NamePool.h | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/XML/include/Poco/DOM/DOMParser.h b/XML/include/Poco/DOM/DOMParser.h index 1a60c2438..de24fea3f 100644 --- a/XML/include/Poco/DOM/DOMParser.h +++ b/XML/include/Poco/DOM/DOMParser.h @@ -45,7 +45,11 @@ public: /// If a NamePool is given, it becomes the Document's NamePool. explicit DOMParser(unsigned long namePoolSize); - /// Creates a new DOMParser, using the given name pool size. + /// Creates a new DOMParser, using the given NamePool size. + /// + /// The given namePoolSize should be a suitable prime number, + /// e.g. 251, 509, 1021 or 4093, depending on the expected + /// size of the document. ~DOMParser(); /// Destroys the DOMParser. diff --git a/XML/include/Poco/XML/NamePool.h b/XML/include/Poco/XML/NamePool.h index 7ff81ca5d..426208c4a 100644 --- a/XML/include/Poco/XML/NamePool.h +++ b/XML/include/Poco/XML/NamePool.h @@ -44,6 +44,9 @@ class XML_API NamePool public: NamePool(unsigned long size = POCO_XML_NAMEPOOL_DEFAULT_SIZE); /// Creates a name pool with room for up to size strings. + /// + /// The given size should be a suitable prime number, + /// e.g. 251, 509, 1021 or 4093. const Name& insert(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName); /// Returns a const reference to an Name for the given names. From e350781084a928e2a12b2d1a89ebac48742d60f5 Mon Sep 17 00:00:00 2001 From: Adrian Weiler Date: Fri, 7 Oct 2016 19:16:12 +0200 Subject: [PATCH 053/305] Fixed "integer constant is too large for 'long' type" issue; make constant unsigned instead of typecasting --- XML/src/xmlparse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XML/src/xmlparse.cpp b/XML/src/xmlparse.cpp index 26797bead..8fb98b6cc 100644 --- a/XML/src/xmlparse.cpp +++ b/XML/src/xmlparse.cpp @@ -742,7 +742,7 @@ generate_hash_secret_salt(XML_Parser parser) if (sizeof(unsigned long) == 4) { return entropy * 2147483647; } else { - return entropy * (unsigned long)2305843009213693951; + return entropy * 2305843009213693951ULL; } } From 29010bc6ad984fcf0f01f1ff5aa2aa5ade8149b9 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 21:05:57 +0200 Subject: [PATCH 054/305] fixed GH #1403: Android compile with poco-1.7.5 no 'pthread_condattr_setclock' error --- Foundation/src/Event_POSIX.cpp | 17 +++++++++++++++-- Foundation/src/Semaphore_POSIX.cpp | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Foundation/src/Event_POSIX.cpp b/Foundation/src/Event_POSIX.cpp index 4d7cd2367..d2fc8c0f5 100644 --- a/Foundation/src/Event_POSIX.cpp +++ b/Foundation/src/Event_POSIX.cpp @@ -24,6 +24,19 @@ #endif +// +// Note: pthread_cond_timedwait() with CLOCK_MONOTONIC is supported +// on Linux and QNX, as well as on Android >= 5.0. On Android < 5.0, +// HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC is defined to indicate +// availability of non-standard pthread_cond_timedwait_monotonic(). +// +#ifndef POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT +#if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) +#define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 +#endif +#endif + + namespace Poco { @@ -40,7 +53,7 @@ EventImpl::EventImpl(EventTypeImpl type): _auto(type == EVENT_AUTORESET_IMPL), _ if (pthread_mutex_init(&_mutex, NULL)) throw SystemException("cannot create event (mutex)"); -#if defined(__linux__) || defined(__QNX__) +#if defined(POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT) pthread_condattr_t attr; if (pthread_condattr_init(&attr)) { @@ -105,7 +118,7 @@ bool EventImpl::waitImpl(long milliseconds) delta.tv_sec = milliseconds / 1000; delta.tv_nsec = (milliseconds % 1000)*1000000; pthread_get_expiration_np(&delta, &abstime); -#elif defined(__linux__) || defined(__QNX__) +#elif defined(POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT) clock_gettime(CLOCK_MONOTONIC, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; diff --git a/Foundation/src/Semaphore_POSIX.cpp b/Foundation/src/Semaphore_POSIX.cpp index 88e768ed1..57c5dae15 100644 --- a/Foundation/src/Semaphore_POSIX.cpp +++ b/Foundation/src/Semaphore_POSIX.cpp @@ -24,6 +24,19 @@ #endif +// +// Note: pthread_cond_timedwait() with CLOCK_MONOTONIC is supported +// on Linux and QNX, as well as on Android >= 5.0. On Android < 5.0, +// HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC is defined to indicate +// availability of non-standard pthread_cond_timedwait_monotonic(). +// +#ifndef POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT +#if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) +#define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 +#endif +#endif + + namespace Poco { @@ -41,7 +54,7 @@ SemaphoreImpl::SemaphoreImpl(int n, int max): _n(n), _max(max) if (pthread_mutex_init(&_mutex, NULL)) throw SystemException("cannot create semaphore (mutex)"); -#if defined(__linux__) || defined(__QNX__) +#if defined(POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT) pthread_condattr_t attr; if (pthread_condattr_init(&attr)) { @@ -105,7 +118,7 @@ bool SemaphoreImpl::waitImpl(long milliseconds) delta.tv_sec = milliseconds / 1000; delta.tv_nsec = (milliseconds % 1000)*1000000; pthread_get_expiration_np(&delta, &abstime); -#elif defined(__linux__) || defined(__QNX__) +#elif defined(POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT) clock_gettime(CLOCK_MONOTONIC, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; From b02d8cecdb51a938a317dc94a2b8d2f41888c3fa Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 21:27:07 +0200 Subject: [PATCH 055/305] fixed GH #1431: Poco/FIFOBuffer.h copy issue --- Foundation/include/Poco/FIFOBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/include/Poco/FIFOBuffer.h b/Foundation/include/Poco/FIFOBuffer.h index 045a71290..ea2d0f458 100644 --- a/Foundation/include/Poco/FIFOBuffer.h +++ b/Foundation/include/Poco/FIFOBuffer.h @@ -325,7 +325,7 @@ public: if (!isWritable()) throw Poco::InvalidAccessException("Buffer not writable."); - std::memcpy(&_buffer[_used], ptr, length * sizeof(T)); + std::memcpy(begin() + _used, ptr, length * sizeof(T)); std::size_t usedBefore = _used; _used += length; if (_notify) notify(usedBefore); From 835d0365d972e9670d2a06fbf8b214d2493ee7b3 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 21:54:20 +0200 Subject: [PATCH 056/305] fixed bad disconnect handling in onSocketReadable --- Net/samples/EchoServer/src/EchoServer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Net/samples/EchoServer/src/EchoServer.cpp b/Net/samples/EchoServer/src/EchoServer.cpp index 6bf18109c..03fdfd2c7 100644 --- a/Net/samples/EchoServer/src/EchoServer.cpp +++ b/Net/samples/EchoServer/src/EchoServer.cpp @@ -111,13 +111,15 @@ public: void onSocketReadable(const AutoPtr& pNf) { - // some socket implementations (windows) report available - // bytes on client disconnect, so we double-check here - if (_socket.available()) + int len = _socket.receiveBytes(_fifoIn); + if (len > 0) { - int len = _socket.receiveBytes(_fifoIn); _fifoIn.drain(_fifoOut.write(_fifoIn.buffer(), _fifoIn.used())); } + else + { + delete this; + } } void onSocketWritable(const AutoPtr& pNf) From 92a0f0f0aa7e360469d34c8d800c93fd02bc953a Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 22:02:57 +0200 Subject: [PATCH 057/305] improved EchoServer error handling --- Net/samples/EchoServer/src/EchoServer.cpp | 28 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Net/samples/EchoServer/src/EchoServer.cpp b/Net/samples/EchoServer/src/EchoServer.cpp index 03fdfd2c7..a35d8d4d5 100644 --- a/Net/samples/EchoServer/src/EchoServer.cpp +++ b/Net/samples/EchoServer/src/EchoServer.cpp @@ -111,20 +111,38 @@ public: void onSocketReadable(const AutoPtr& pNf) { - int len = _socket.receiveBytes(_fifoIn); - if (len > 0) + try { - _fifoIn.drain(_fifoOut.write(_fifoIn.buffer(), _fifoIn.used())); + int len = _socket.receiveBytes(_fifoIn); + if (len > 0) + { + _fifoIn.drain(_fifoOut.write(_fifoIn.buffer(), _fifoIn.used())); + } + else + { + delete this; + } } - else + catch (Poco::Exception& exc) { + Application& app = Application::instance(); + app.logger().log(exc); delete this; } } void onSocketWritable(const AutoPtr& pNf) { - _socket.sendBytes(_fifoOut); + try + { + _socket.sendBytes(_fifoOut); + } + catch (Poco::Exception& exc) + { + Application& app = Application::instance(); + app.logger().log(exc); + delete this; + } } void onSocketShutdown(const AutoPtr& pNf) From e2bfe6f2cfbe7adca410ec982631ec48d97baf41 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 7 Oct 2016 22:09:36 +0200 Subject: [PATCH 058/305] added Yocto config; updated ARM-Linux config --- build/config/ARM-Linux | 28 ++++++++-------- build/config/Yocto | 75 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 build/config/Yocto diff --git a/build/config/ARM-Linux b/build/config/ARM-Linux index ea192c9cf..7837691c8 100644 --- a/build/config/ARM-Linux +++ b/build/config/ARM-Linux @@ -1,22 +1,19 @@ # -# $Id: //poco/1.4/build/config/ARM-Linux#2 $ +# $Id $ # -# ARM-Linux +# Yocto +# +# Make settings for Linux/GCC ARM # -# Make settings for ARM Linux/gcc 2.95.3 (cross-compile, using STLport 4.6.2) # # # General Settings # -LINKMODE ?= SHARED -POCO_TARGET_OSNAME = Linux -POCO_TARGET_OSARCH = ARM -STLPORT_INCLUDE = /usr/local/include/stlport -STLPORT_LIB = /usr/local/lib -OPENSSL_INCLUDE = /usr/local/arm/2.95.3/include -OPENSSL_LIB = /usr/local/arm/2.95.3/lib -TOOL = arm-linux +LINKMODE ?= SHARED +TOOL ?= arm-linux +POCO_TARGET_OSNAME = Linux +POCO_TARGET_OSARCH ?= armv7l # # Define Tools @@ -44,10 +41,10 @@ SHAREDLIBLINKEXT = .so # # Compiler and Linker Flags # -CFLAGS = -Isrc +CFLAGS = CFLAGS32 = CFLAGS64 = -CXXFLAGS = +CXXFLAGS = -Wall -Wno-sign-compare CXXFLAGS32 = CXXFLAGS64 = LINKFLAGS = @@ -69,9 +66,10 @@ RELEASEOPT_LINK = -O2 # # System Specific Flags # -SYSFLAGS = -I$(STLPORT_INCLUDE) -I$(OPENSSL_INCLUDE) -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_REENTRANT -D_THREAD_SAFE -DPOCO_NO_FPENVIRONMENT +SYSFLAGS = -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DPOCO_HAVE_FD_EPOLL \ + -DPOCO_HAVE_ADDRINFO -DPOCO_HAVE_LIBRESOLV # # System Specific Libraries # -SYSLIBS = -L$(STLPORT_LIB) -L$(OPENSSL_LIB) -lstlport_arm-linux-gcc -lpthread -ldl -lrt +SYSLIBS = -lpthread -ldl -lrt diff --git a/build/config/Yocto b/build/config/Yocto new file mode 100644 index 000000000..7ffc31355 --- /dev/null +++ b/build/config/Yocto @@ -0,0 +1,75 @@ +# +# $Id $ +# +# Yocto +# +# Make settings for Yocto Linux/GCC ARM +# +# + +# +# General Settings +# +LINKMODE ?= SHARED +TOOL ?= arm-poky-linux-gnueabi +POCO_TARGET_OSNAME = Linux +POCO_TARGET_OSARCH ?= armv7l + +# +# Define Tools +# +CC = $(TOOL)-gcc +CXX = $(TOOL)-g++ +LINK = $(CXX) +LIB = $(TOOL)-ar -cr +RANLIB = $(TOOL)-ranlib +SHLIB = $(CXX) -shared -Wl,-soname,$(notdir $@) -o $@ +SHLIBLN = $(POCO_BASE)/build/script/shlibln +STRIP = $(TOOL)-strip +DEP = $(POCO_BASE)/build/script/makedepend.gcc +SHELL = sh +RM = rm -rf +CP = cp +MKDIR = mkdir -p + +# +# Extension for Shared Libraries +# +SHAREDLIBEXT = .so.$(target_version) +SHAREDLIBLINKEXT = .so + +# +# Compiler and Linker Flags +# +CFLAGS = +CFLAGS32 = +CFLAGS64 = +CXXFLAGS = -Wall -Wno-sign-compare +CXXFLAGS32 = +CXXFLAGS64 = +LINKFLAGS = +LINKFLAGS32 = +LINKFLAGS64 = +STATICOPT_CC = +STATICOPT_CXX = +STATICOPT_LINK = -static +SHAREDOPT_CC = -fPIC +SHAREDOPT_CXX = -fPIC +SHAREDOPT_LINK = -Wl,-rpath,$(LIBPATH) +DEBUGOPT_CC = -g -D_DEBUG +DEBUGOPT_CXX = -g -D_DEBUG +DEBUGOPT_LINK = -g +RELEASEOPT_CC = -O2 -DNDEBUG +RELEASEOPT_CXX = -O2 -DNDEBUG +RELEASEOPT_LINK = -O2 + +# +# System Specific Flags +# +SYSFLAGS = -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DPOCO_HAVE_FD_EPOLL \ + -DPOCO_HAVE_ADDRINFO -DPOCO_HAVE_LIBRESOLV + +# +# System Specific Libraries +# +SYSLIBS = -lpthread -ldl -lrt From 8888d3daae5c971f9419756aa95661f2dc87fb3c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 10 Oct 2016 12:07:58 +0200 Subject: [PATCH 059/305] added POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX configuration macro to disable *d.so, *d.dll suffix in SharedLibrary class --- Foundation/include/Poco/Config.h | 12 +++++++++++- Foundation/src/SharedLibrary_HPUX.cpp | 2 +- Foundation/src/SharedLibrary_UNIX.cpp | 8 ++++---- Foundation/src/SharedLibrary_VMS.cpp | 2 +- Foundation/src/SharedLibrary_WIN32.cpp | 2 +- Foundation/src/SharedLibrary_WIN32U.cpp | 2 +- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index 894562db7..e4111825b 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -9,7 +9,7 @@ // // Feature configuration for the POCO libraries. // -// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH. +// Copyright (c) 2006-2016, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 @@ -93,8 +93,10 @@ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // #ifndef POCO_NO_SOO +#ifndef POCO_ENABLE_SOO #define POCO_NO_SOO #endif +#endif @@ -168,13 +170,21 @@ #define POCO_NO_LOCALE #endif + // Enable the poco_debug_* and poco_trace_* macros // even if the _DEBUG variable is not set. // This allows the use of these macros in a release version. // #define POCO_LOG_DEBUG + // Uncomment to disable the use of bundled OpenSSL binaries // (Windows only) // #define POCO_EXTERNAL_OPENSSL + +// Define to prevent changing the suffix for shared libraries +// to "d.so", "d.dll", etc. for _DEBUG builds in Poco::SharedLibrary. +// #define POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX + + #endif // Foundation_Config_INCLUDED diff --git a/Foundation/src/SharedLibrary_HPUX.cpp b/Foundation/src/SharedLibrary_HPUX.cpp index 375e3e390..a233c04ec 100644 --- a/Foundation/src/SharedLibrary_HPUX.cpp +++ b/Foundation/src/SharedLibrary_HPUX.cpp @@ -91,7 +91,7 @@ std::string SharedLibraryImpl::prefixImpl() std::string SharedLibraryImpl::suffixImpl() { -#if defined(_DEBUG) +#if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.sl"; #else return ".sl"; diff --git a/Foundation/src/SharedLibrary_UNIX.cpp b/Foundation/src/SharedLibrary_UNIX.cpp index e900faf96..e32689069 100644 --- a/Foundation/src/SharedLibrary_UNIX.cpp +++ b/Foundation/src/SharedLibrary_UNIX.cpp @@ -112,25 +112,25 @@ std::string SharedLibraryImpl::prefixImpl() std::string SharedLibraryImpl::suffixImpl() { #if POCO_OS == POCO_OS_MAC_OS_X - #if defined(_DEBUG) + #if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.dylib"; #else return ".dylib"; #endif #elif POCO_OS == POCO_OS_HPUX - #if defined(_DEBUG) + #if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.sl"; #else return ".sl"; #endif #elif POCO_OS == POCO_OS_CYGWIN - #if defined(_DEBUG) + #if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.dll"; #else return ".dll"; #endif #else - #if defined(_DEBUG) + #if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.so"; #else return ".so"; diff --git a/Foundation/src/SharedLibrary_VMS.cpp b/Foundation/src/SharedLibrary_VMS.cpp index 92dac3d5b..bb5ac9918 100644 --- a/Foundation/src/SharedLibrary_VMS.cpp +++ b/Foundation/src/SharedLibrary_VMS.cpp @@ -114,7 +114,7 @@ std::string SharedLibraryImpl::prefixImpl() std::string SharedLibraryImpl::suffixImpl() { -#if defined(_DEBUG) +#if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.exe"; #else return ".exe"; diff --git a/Foundation/src/SharedLibrary_WIN32.cpp b/Foundation/src/SharedLibrary_WIN32.cpp index 42751de1e..7acd0ecc3 100644 --- a/Foundation/src/SharedLibrary_WIN32.cpp +++ b/Foundation/src/SharedLibrary_WIN32.cpp @@ -95,7 +95,7 @@ std::string SharedLibraryImpl::prefixImpl() std::string SharedLibraryImpl::suffixImpl() { -#if defined(_DEBUG) +#if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.dll"; #else return ".dll"; diff --git a/Foundation/src/SharedLibrary_WIN32U.cpp b/Foundation/src/SharedLibrary_WIN32U.cpp index 2b50a0df6..4c2187338 100644 --- a/Foundation/src/SharedLibrary_WIN32U.cpp +++ b/Foundation/src/SharedLibrary_WIN32U.cpp @@ -106,7 +106,7 @@ std::string SharedLibraryImpl::prefixImpl() std::string SharedLibraryImpl::suffixImpl() { -#if defined(_DEBUG) +#if defined(_DEBUG) && !defined(POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX) return "d.dll"; #else return ".dll"; From 547553278c24bd262211f85e15fbfa51516d57ba Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 10 Oct 2016 14:14:50 +0200 Subject: [PATCH 060/305] use #ifdef POCO_LONG_IS_64_BIT instead of if (sizeof(... to avoid warnings --- XML/src/xmlparse.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/XML/src/xmlparse.cpp b/XML/src/xmlparse.cpp index 8fb98b6cc..1de8864b8 100644 --- a/XML/src/xmlparse.cpp +++ b/XML/src/xmlparse.cpp @@ -739,11 +739,11 @@ generate_hash_secret_salt(XML_Parser parser) platform_gather_time_entropy() ^ platform_getpid() ^ (unsigned long)parser; /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ - if (sizeof(unsigned long) == 4) { - return entropy * 2147483647; - } else { - return entropy * 2305843009213693951ULL; - } +#ifdef POCO_LONG_IS_64_BIT + return entropy * 2305843009213693951ULL; +#else + return entropy * 2147483647; +#endif } static XML_Bool /* only valid for root parser */ From 6195c97a868b7f61f5ad993f5a90eccb6a3df339 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 10 Oct 2016 18:44:55 +0200 Subject: [PATCH 061/305] make port constructor explicit; no longer prefer IPv4 addresses over IPv6 addresses --- Net/include/Poco/Net/SocketAddress.h | 2 +- Net/src/SocketAddress.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Net/include/Poco/Net/SocketAddress.h b/Net/include/Poco/Net/SocketAddress.h index d6ebd053a..19a87c337 100644 --- a/Net/include/Poco/Net/SocketAddress.h +++ b/Net/include/Poco/Net/SocketAddress.h @@ -61,7 +61,7 @@ public: SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber); /// Creates a SocketAddress from an IP address and given port number. - SocketAddress(Poco::UInt16 port); + explicit SocketAddress(Poco::UInt16 port); /// Creates a SocketAddress with unspecified (wildcard) IP address /// and given port number. diff --git a/Net/src/SocketAddress.cpp b/Net/src/SocketAddress.cpp index fa5290472..6c3aec0a8 100644 --- a/Net/src/SocketAddress.cpp +++ b/Net/src/SocketAddress.cpp @@ -250,7 +250,7 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber HostEntry::AddressList addresses = he.addresses(); if (addresses.size() > 0) { -#if defined(POCO_HAVE_IPv6) +#if defined(POCO_HAVE_IPv6) && defined(POCO_SOCKETADDRESS_PREFER_IPv4) // if we get both IPv4 and IPv6 addresses, prefer IPv4 std::stable_sort(addresses.begin(), addresses.end(), AFLT()); #endif From 8293f93f7a19c7198c205daab4b1a8b4cee0a52a Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 14 Oct 2016 12:01:25 +0200 Subject: [PATCH 062/305] use std::unique_ptr instead of std::auto_ptr with C++11 or newer compilers to avoid std::auto_ptr deprecation warnings --- CppUnit/include/Poco/CppUnit/TestCaller.h | 4 ++++ Foundation/include/Poco/DynamicFactory.h | 4 ++++ Foundation/src/NumericString.cpp | 4 ++++ Net/src/HTTPServerConnection.cpp | 4 ++++ Net/src/TCPServerDispatcher.cpp | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/CppUnit/include/Poco/CppUnit/TestCaller.h b/CppUnit/include/Poco/CppUnit/TestCaller.h index d859bb7ce..90775c569 100644 --- a/CppUnit/include/Poco/CppUnit/TestCaller.h +++ b/CppUnit/include/Poco/CppUnit/TestCaller.h @@ -89,7 +89,11 @@ protected: private: TestMethod _test; +#if __cplusplus < 201103L std::auto_ptr _fixture; +#else + std::unique_ptr _fixture; +#endif }; diff --git a/Foundation/include/Poco/DynamicFactory.h b/Foundation/include/Poco/DynamicFactory.h index d7bb666d8..b507c01fe 100644 --- a/Foundation/include/Poco/DynamicFactory.h +++ b/Foundation/include/Poco/DynamicFactory.h @@ -89,7 +89,11 @@ public: FastMutex::ScopedLock lock(_mutex); +#if __cplusplus < 201103L std::auto_ptr ptr(pAbstractFactory); +#else + std::unique_ptr ptr(pAbstractFactory); +#endif typename FactoryMap::iterator it = _map.find(className); if (it == _map.end()) _map[className] = ptr.release(); diff --git a/Foundation/src/NumericString.cpp b/Foundation/src/NumericString.cpp index e8cfed369..3604bc7ed 100644 --- a/Foundation/src/NumericString.cpp +++ b/Foundation/src/NumericString.cpp @@ -59,7 +59,11 @@ void pad(std::string& str, int precision, int width, char prefix = ' ', char dec std::string::size_type frac = str.length() - decSepPos - 1; std::string::size_type ePos = str.find_first_of("eE"); +#if __cplusplus < 201103L std::auto_ptr eStr; +#else + std::unique_ptr eStr; +#endif if (ePos != std::string::npos) { eStr.reset(new std::string(str.substr(ePos, std::string::npos))); diff --git a/Net/src/HTTPServerConnection.cpp b/Net/src/HTTPServerConnection.cpp index 4166f26c8..7a686595d 100644 --- a/Net/src/HTTPServerConnection.cpp +++ b/Net/src/HTTPServerConnection.cpp @@ -78,7 +78,11 @@ void HTTPServerConnection::run() response.set("Server", server); try { +#if __cplusplus < 201103L std::auto_ptr pHandler(_pFactory->createRequestHandler(request)); +#else + std::unique_ptr pHandler(_pFactory->createRequestHandler(request)); +#endif if (pHandler.get()) { if (request.getExpectContinue() && response.getStatus() == HTTPResponse::HTTP_OK) diff --git a/Net/src/TCPServerDispatcher.cpp b/Net/src/TCPServerDispatcher.cpp index a5f2de3c6..ce286b26e 100644 --- a/Net/src/TCPServerDispatcher.cpp +++ b/Net/src/TCPServerDispatcher.cpp @@ -110,7 +110,11 @@ void TCPServerDispatcher::run() TCPConnectionNotification* pCNf = dynamic_cast(pNf.get()); if (pCNf) { +#if __cplusplus < 201103L std::auto_ptr pConnection(_pConnectionFactory->createConnection(pCNf->socket())); +#else + std::unique_ptr pConnection(_pConnectionFactory->createConnection(pCNf->socket())); +#endif poco_check_ptr(pConnection.get()); beginConnection(); pConnection->start(); From 066224438411ba99e1d34e54681c4bb9dd95b241 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 14 Oct 2016 12:02:32 +0200 Subject: [PATCH 063/305] fix typo in test suite --- Data/testsuite/src/DataTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/testsuite/src/DataTest.cpp b/Data/testsuite/src/DataTest.cpp index 615616f69..2431d1508 100644 --- a/Data/testsuite/src/DataTest.cpp +++ b/Data/testsuite/src/DataTest.cpp @@ -952,7 +952,7 @@ void DataTest::testRow() row3.append("field4", 4); assert (row3 == row); - assert (!(row < row3 | row3 < row)); + assert (!(row < row3 || row3 < row)); Row row4(row3.names()); try From 20a6f258655646b5c5fab3a438b63ed2806ec00b Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 16 Oct 2016 13:39:17 +0200 Subject: [PATCH 064/305] XMLConfiguration default (and single-argument delimiter) constructor now loads an empty XML document with "config" root element to make the configuration usable without an additional call to load() or loadEmpty(). --- Util/include/Poco/Util/XMLConfiguration.h | 6 ++-- Util/src/XMLConfiguration.cpp | 2 ++ Util/testsuite/src/XMLConfigurationTest.cpp | 33 +++++++++++++++++++++ Util/testsuite/src/XMLConfigurationTest.h | 3 ++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Util/include/Poco/Util/XMLConfiguration.h b/Util/include/Poco/Util/XMLConfiguration.h index 43721015d..99e1ba180 100644 --- a/Util/include/Poco/Util/XMLConfiguration.h +++ b/Util/include/Poco/Util/XMLConfiguration.h @@ -83,11 +83,11 @@ class Util_API XMLConfiguration: public AbstractConfiguration { public: XMLConfiguration(); - /// Creates an empty XMLConfiguration. + /// Creates an empty XMLConfiguration with a "config" root element. XMLConfiguration(char delim); - /// Creates an empty XMLConfiguration, using the given - /// delimiter char instead of the default '.'. + /// Creates an empty XMLConfiguration with a "config" root element, + /// using the given delimiter char instead of the default '.'. XMLConfiguration(Poco::XML::InputSource* pInputSource); /// Creates an XMLConfiguration and loads the XML document from diff --git a/Util/src/XMLConfiguration.cpp b/Util/src/XMLConfiguration.cpp index e9249f09e..8a1de6317 100644 --- a/Util/src/XMLConfiguration.cpp +++ b/Util/src/XMLConfiguration.cpp @@ -39,12 +39,14 @@ namespace Util { XMLConfiguration::XMLConfiguration(): _delim('.') { + loadEmpty("config"); } XMLConfiguration::XMLConfiguration(char delim): _delim(delim) { + loadEmpty("config"); } diff --git a/Util/testsuite/src/XMLConfigurationTest.cpp b/Util/testsuite/src/XMLConfigurationTest.cpp index 3fc69006e..4f9f3c179 100644 --- a/Util/testsuite/src/XMLConfigurationTest.cpp +++ b/Util/testsuite/src/XMLConfigurationTest.cpp @@ -272,6 +272,36 @@ AbstractConfiguration* XMLConfigurationTest::allocConfiguration() const } +void XMLConfigurationTest::testSaveEmpty() +{ + Poco::AutoPtr pConfig = new XMLConfiguration; + std::ostringstream ostr; + pConfig->save(ostr); + assert (ostr.str() == "\n"); +} + + +void XMLConfigurationTest::testFromScratch() +{ + Poco::AutoPtr pConfig = new XMLConfiguration; + pConfig->setString("foo", "bar"); + std::ostringstream ostr; + pConfig->save(ostr); + assert (ostr.str() == "\n\tbar\n\n"); +} + + +void XMLConfigurationTest::testLoadEmpty() +{ + Poco::AutoPtr pConfig = new XMLConfiguration; + pConfig->loadEmpty("AppConfig"); + pConfig->setString("foo", "bar"); + std::ostringstream ostr; + pConfig->save(ostr); + assert (ostr.str() == "\n\tbar\n\n"); +} + + void XMLConfigurationTest::setUp() { } @@ -291,6 +321,9 @@ CppUnit::Test* XMLConfigurationTest::suite() CppUnit_addTest(pSuite, XMLConfigurationTest, testSave); CppUnit_addTest(pSuite, XMLConfigurationTest, testLoadAppendSave); CppUnit_addTest(pSuite, XMLConfigurationTest, testOtherDelimiter); + CppUnit_addTest(pSuite, XMLConfigurationTest, testSaveEmpty); + CppUnit_addTest(pSuite, XMLConfigurationTest, testFromScratch); + CppUnit_addTest(pSuite, XMLConfigurationTest, testLoadEmpty); return pSuite; } diff --git a/Util/testsuite/src/XMLConfigurationTest.h b/Util/testsuite/src/XMLConfigurationTest.h index 799918f9c..c77a4d759 100644 --- a/Util/testsuite/src/XMLConfigurationTest.h +++ b/Util/testsuite/src/XMLConfigurationTest.h @@ -30,6 +30,9 @@ public: void testSave(); void testLoadAppendSave(); void testOtherDelimiter(); + void testSaveEmpty(); + void testFromScratch(); + void testLoadEmpty(); void setUp(); void tearDown(); From 31df37cf22a0aed0a045706c8eb526baf43c0610 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 16 Oct 2016 14:00:10 +0200 Subject: [PATCH 065/305] use std::unique_ptr instead of std::auto_ptr if available --- PageCompiler/src/PageCompiler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PageCompiler/src/PageCompiler.cpp b/PageCompiler/src/PageCompiler.cpp index da59a6e67..774cc09ba 100644 --- a/PageCompiler/src/PageCompiler.cpp +++ b/PageCompiler/src/PageCompiler.cpp @@ -285,7 +285,11 @@ protected: p.setBaseName(clazz); } +#if __cplusplus < 201103L std::auto_ptr pCodeWriter(createCodeWriter(page, clazz)); +#else + std::unique_ptr pCodeWriter(createCodeWriter(page, clazz)); +#endif if (!_outputDir.empty()) { From 6d373825fa4b4ca76c4d46994a4b12b54fadb9b3 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 17 Oct 2016 17:59:09 +0200 Subject: [PATCH 066/305] fixed GH #1458: always pass 1 to epoll_create() --- Net/src/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index 0dd1c8851..b2b1f589b 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -144,7 +144,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce } epollSize = eventLast - eventsIn; - epollfd = epoll_create(epollSize); + epollfd = epoll_create(1); if (epollfd < 0) { SocketImpl::error("Can't create epoll queue"); From b22501f6926f9fbeaa06e31bc65bc7ba599eabfc Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 18 Oct 2016 18:13:52 +0200 Subject: [PATCH 067/305] another fix for GH #1458 - handle case when all sockets are invalid --- Net/src/Socket.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index b2b1f589b..27444a82b 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -144,6 +144,8 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce } epollSize = eventLast - eventsIn; + if (epollSize == 0) return 0; + epollfd = epoll_create(1); if (epollfd < 0) { From a1657d5e1bfca92471f95a215904df63ee63f7f5 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 22 Oct 2016 14:27:49 +0200 Subject: [PATCH 068/305] fixed GH #1465: Assertion violation in DateTime.cpp using ZipArchive --- Zip/src/ZipUtil.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Zip/src/ZipUtil.cpp b/Zip/src/ZipUtil.cpp index 7bdb76dfe..1aa6d3bdc 100644 --- a/Zip/src/ZipUtil.cpp +++ b/Zip/src/ZipUtil.cpp @@ -31,31 +31,33 @@ Poco::DateTime ZipUtil::parseDateTime(const char* pVal, const Poco::UInt32 timeP { Poco::UInt16 time = ZipUtil::get16BitValue(pVal, timePos); Poco::UInt16 date = ZipUtil::get16BitValue(pVal, datePos); - //TIME: second 0-4, minute 5-10, hour 11-15, second resolution is 2! - int sec = 2*(time & 0x001fu); // 0000 0000 0001 1111 - int min = ((time & 0x07e0u) >> 5); // 0000 0111 1110 0000 - int hour= ((time & 0xf800u) >> 11); // 1111 1000 0000 0000 + // TIME: second 0-4, minute 5-10, hour 11-15, second resolution is 2! + int sec = 2*(time & 0x001fu); // 0000 0000 0001 1111 + int min = ((time & 0x07e0u) >> 5); // 0000 0111 1110 0000 + int hour = ((time & 0xf800u) >> 11); // 1111 1000 0000 0000 - //DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 - int day = (date & 0x001fu); // 0000 0000 0001 1111 - int mon = ((date & 0x01e0u) >> 5); // 0000 0001 1110 0000 - int year= 1980+((date & 0xfe00u) >> 9); // 1111 1110 0000 0000 - return Poco::DateTime(year, mon, day, hour, min, sec); + // DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 + int day = (date & 0x001fu); // 0000 0000 0001 1111 + int mon = ((date & 0x01e0u) >> 5); // 0000 0001 1110 0000 + int year = 1980+((date & 0xfe00u) >> 9); // 1111 1110 0000 0000 + + if (Poco::DateTime::isValid(year, mon, day, hour, min, sec)) + return Poco::DateTime(year, mon, day, hour, min, sec); + else + return Poco::DateTime(1970, 01, 01); } void ZipUtil::setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos) { - //TIME: second 0-4, minute 5-10, hour 11-15 + // TIME: second 0-4, minute 5-10, hour 11-15 Poco::UInt16 time = static_cast((dt.second()/2) + (dt.minute()<<5) + (dt.hour()<<11)); - //DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 + // DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 int year = dt.year() - 1980; - if (year<0) - year = 0; + if (year < 0) year = 0; Poco::UInt16 date = static_cast(dt.day() + (dt.month()<<5) + (year<<9)); ZipUtil::set16BitValue(time, pVal, timePos); ZipUtil::set16BitValue(date, pVal, datePos); - } From 1f3b53298c149f5e5403b7b7e9f884953b65b145 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 24 Oct 2016 09:41:49 +0200 Subject: [PATCH 069/305] fixed GH #1462: AbstractConfiguration::getUInt does not parse hex numbers --- Util/include/Poco/Util/AbstractConfiguration.h | 2 +- Util/src/AbstractConfiguration.cpp | 18 +++++++++--------- .../src/AbstractConfigurationTest.cpp | 3 +++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Util/include/Poco/Util/AbstractConfiguration.h b/Util/include/Poco/Util/AbstractConfiguration.h index 6085219cb..c7d2183a3 100644 --- a/Util/include/Poco/Util/AbstractConfiguration.h +++ b/Util/include/Poco/Util/AbstractConfiguration.h @@ -346,7 +346,7 @@ protected: /// implementation throws a Poco::NotImplementedException. static int parseInt(const std::string& value); - static int parseUInt(const std::string& value); + static unsigned parseUInt(const std::string& value); #if defined(POCO_HAVE_INT64) diff --git a/Util/src/AbstractConfiguration.cpp b/Util/src/AbstractConfiguration.cpp index 5f8ab3016..7398f347d 100644 --- a/Util/src/AbstractConfiguration.cpp +++ b/Util/src/AbstractConfiguration.cpp @@ -147,7 +147,7 @@ unsigned AbstractConfiguration::getUInt(const std::string& key) const std::string value; if (getRaw(key, value)) - return NumberParser::parseUnsigned(internalExpand(value)); + return parseUInt(internalExpand(value)); else throw NotFoundException(key); } @@ -159,7 +159,7 @@ unsigned AbstractConfiguration::getUInt(const std::string& key, unsigned default std::string value; if (getRaw(key, value)) - return NumberParser::parseUnsigned(internalExpand(value)); + return parseUInt(internalExpand(value)); else return defaultValue; } @@ -174,7 +174,7 @@ Int64 AbstractConfiguration::getInt64(const std::string& key) const std::string value; if (getRaw(key, value)) - return NumberParser::parse64(internalExpand(value)); + return parseInt64(internalExpand(value)); else throw NotFoundException(key); } @@ -186,7 +186,7 @@ Int64 AbstractConfiguration::getInt64(const std::string& key, Int64 defaultValue std::string value; if (getRaw(key, value)) - return NumberParser::parse64(internalExpand(value)); + return parseInt64(internalExpand(value)); else return defaultValue; } @@ -198,7 +198,7 @@ UInt64 AbstractConfiguration::getUInt64(const std::string& key) const std::string value; if (getRaw(key, value)) - return NumberParser::parseUnsigned64(internalExpand(value)); + return parseUInt64(internalExpand(value)); else throw NotFoundException(key); } @@ -210,7 +210,7 @@ UInt64 AbstractConfiguration::getUInt64(const std::string& key, UInt64 defaultVa std::string value; if (getRaw(key, value)) - return NumberParser::parseUnsigned64(internalExpand(value)); + return parseUInt64(internalExpand(value)); else return defaultValue; } @@ -462,13 +462,13 @@ std::string AbstractConfiguration::uncheckedExpand(const std::string& rValue) co int AbstractConfiguration::parseInt(const std::string& value) { if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) - return NumberParser::parseHex(value); + return static_cast(NumberParser::parseHex(value)); else return NumberParser::parse(value); } -int AbstractConfiguration::parseUInt(const std::string& value) +unsigned AbstractConfiguration::parseUInt(const std::string& value) { if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) return NumberParser::parseHex(value); @@ -480,7 +480,7 @@ int AbstractConfiguration::parseUInt(const std::string& value) Int64 AbstractConfiguration::parseInt64(const std::string& value) { if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0)) - return NumberParser::parseHex64(value); + return static_cast(NumberParser::parseHex64(value)); else return NumberParser::parse64(value); } diff --git a/Util/testsuite/src/AbstractConfigurationTest.cpp b/Util/testsuite/src/AbstractConfigurationTest.cpp index 857e00a2b..dae40567c 100644 --- a/Util/testsuite/src/AbstractConfigurationTest.cpp +++ b/Util/testsuite/src/AbstractConfigurationTest.cpp @@ -89,6 +89,7 @@ void AbstractConfigurationTest::testGetInt() assert (pConf->getInt("prop4.int1") == 42); assert (pConf->getInt("prop4.int2") == -42); assert (pConf->getInt("prop4.hex") == 0x1f); + assert (pConf->getUInt("prop4.hex") == 0x1f); assert (pConf->getInt("ref2") == 42); try @@ -114,6 +115,8 @@ void AbstractConfigurationTest::testGetInt64() assert (pConf->getInt64("prop4.bigint1") == std::numeric_limits::max()); assert (pConf->getInt64("prop4.bigint2") == std::numeric_limits::min()); assert (pConf->getUInt64("prop4.biguint") == std::numeric_limits::max()); + assert (pConf->getInt64("prop4.hex") == 0x1f); + assert (pConf->getUInt64("prop4.hex") == 0x1f); assert (pConf->getInt64("ref2") == 42); try From 5df7f69b08933632721034bd15992e4f0c78bd47 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 26 Oct 2016 12:58:52 +0200 Subject: [PATCH 070/305] fixed GH #1472: HTTP(S)StreamFactory should send a User-Agent header --- Net/src/HTTPStreamFactory.cpp | 8 ++++++++ NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Net/src/HTTPStreamFactory.cpp b/Net/src/HTTPStreamFactory.cpp index c00c4d2ed..c2044e8d3 100644 --- a/Net/src/HTTPStreamFactory.cpp +++ b/Net/src/HTTPStreamFactory.cpp @@ -26,6 +26,8 @@ #include "Poco/UnbufferedStreamBuf.h" #include "Poco/NullStream.h" #include "Poco/StreamCopier.h" +#include "Poco/Format.h" +#include "Poco/Version.h" using Poco::URIStreamFactory; @@ -115,6 +117,12 @@ std::istream* HTTPStreamFactory::open(const URI& uri) cred.authenticate(req, res); } + req.set("User-Agent", Poco::format("poco/%d.%d.%d", + (POCO_VERSION >> 24) & 0xFF, + (POCO_VERSION >> 16) & 0xFF, + (POCO_VERSION >> 8) & 0xFF)); + req.set("Accept", "*/*"); + pSession->sendRequest(req); std::istream& rs = pSession->receiveResponse(res); bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || diff --git a/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp b/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp index 67296cd6d..d0438486d 100644 --- a/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp +++ b/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp @@ -26,6 +26,8 @@ #include "Poco/UnbufferedStreamBuf.h" #include "Poco/NullStream.h" #include "Poco/StreamCopier.h" +#include "Poco/Format.h" +#include "Poco/Version.h" using Poco::URIStreamFactory; @@ -118,6 +120,12 @@ std::istream* HTTPSStreamFactory::open(const URI& uri) cred.authenticate(req, res); } + req.set("User-Agent", Poco::format("poco/%d.%d.%d", + (POCO_VERSION >> 24) & 0xFF, + (POCO_VERSION >> 16) & 0xFF, + (POCO_VERSION >> 8) & 0xFF)); + req.set("Accept", "*/*"); + pSession->sendRequest(req); std::istream& rs = pSession->receiveResponse(res); bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || From 95590d620ec9bf52f2a40ed52a28ebf15bb7e0e4 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 29 Oct 2016 20:27:28 +0300 Subject: [PATCH 071/305] Fixed error with Poco::UTF8Encoding::isLegal (wrong result on illegal sequence "\xED\x20\xA8"). --- Foundation/src/UTF8Encoding.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Foundation/src/UTF8Encoding.cpp b/Foundation/src/UTF8Encoding.cpp index 1ebebdfd5..d4d055701 100644 --- a/Foundation/src/UTF8Encoding.cpp +++ b/Foundation/src/UTF8Encoding.cpp @@ -224,23 +224,23 @@ bool UTF8Encoding::isLegal(const unsigned char *bytes, int length) case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: - if ((a = (*--srcptr)) > 0xBF) return false; - switch (*bytes) + a = (*--srcptr); + switch (*bytes) { case 0xE0: - if (a < 0xA0) return false; + if (a < 0xA0 || a > 0xBF) return false; break; case 0xED: - if (a > 0x9F) return false; + if (a < 0x80 || a > 0x9F) return false; break; case 0xF0: - if (a < 0x90) return false; + if (a < 0x90 || a > 0xBF) return false; break; case 0xF4: - if (a > 0x8F) return false; + if (a < 0x80 || a > 0x8F) return false; break; default: - if (a < 0x80) return false; + if (a < 0x80 || a > 0xBF) return false; } case 1: if (*bytes >= 0x80 && *bytes < 0xC2) return false; From efdeadef2a1e408893424ae08bbb81d98a071311 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 3 Nov 2016 14:48:51 +0100 Subject: [PATCH 072/305] fixed GH #990: Potential race condition in on Windows --- Foundation/include/Poco/Exception.h | 1 + Foundation/src/Exception.cpp | 1 + Foundation/src/File.cpp | 32 ++++++++++++++++++++++++++++- Foundation/src/File_UNIX.cpp | 2 +- Foundation/src/File_VMS.cpp | 2 +- Foundation/src/File_VX.cpp | 2 +- Foundation/src/File_WIN32.cpp | 2 +- Foundation/src/File_WIN32U.cpp | 2 +- Foundation/src/File_WINCE.cpp | 2 +- 9 files changed, 39 insertions(+), 7 deletions(-) diff --git a/Foundation/include/Poco/Exception.h b/Foundation/include/Poco/Exception.h index 5e582e045..80c09e2bb 100644 --- a/Foundation/include/Poco/Exception.h +++ b/Foundation/include/Poco/Exception.h @@ -254,6 +254,7 @@ POCO_DECLARE_EXCEPTION(Foundation_API, CreateFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, OpenFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, WriteFileException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, ReadFileException, FileException) +POCO_DECLARE_EXCEPTION(Foundation_API, DirectoryNotEmptyException, FileException) POCO_DECLARE_EXCEPTION(Foundation_API, UnknownURISchemeException, RuntimeException) POCO_DECLARE_EXCEPTION(Foundation_API, TooManyURIRedirectsException, RuntimeException) POCO_DECLARE_EXCEPTION(Foundation_API, URISyntaxException, SyntaxException) diff --git a/Foundation/src/Exception.cpp b/Foundation/src/Exception.cpp index e3cdd7ca7..c38d6fef9 100644 --- a/Foundation/src/Exception.cpp +++ b/Foundation/src/Exception.cpp @@ -178,6 +178,7 @@ POCO_IMPLEMENT_EXCEPTION(CreateFileException, FileException, "Cannot create file POCO_IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file") POCO_IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file") POCO_IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file") +POCO_IMPLEMENT_EXCEPTION(DirectoryNotEmptyException, FileException, "Directory not empty") POCO_IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme") POCO_IMPLEMENT_EXCEPTION(TooManyURIRedirectsException, RuntimeException, "Too many URI redirects") POCO_IMPLEMENT_EXCEPTION(URISyntaxException, SyntaxException, "Bad URI syntax") diff --git a/Foundation/src/File.cpp b/Foundation/src/File.cpp index 06ba25b6a..0b2b6aa06 100644 --- a/Foundation/src/File.cpp +++ b/Foundation/src/File.cpp @@ -34,6 +34,7 @@ #else #include "File_VMS.cpp" #endif +#include "Poco/Thread.h" namespace Poco { @@ -269,8 +270,37 @@ void File::remove(bool recursive) { it->remove(true); } + + // Note: On Windows, removing a directory may not succeed at first + // try because deleting files is not a synchronous operation. Files + // are merely marked as deleted, and actually removed at a later time. + // + // An alternate strategy would be moving files to a different directory + // first (on the same drive, but outside the deleted tree), and marking + // them as hidden, before deleting them, but this could lead to other issues. + // So we simply retry after some time until we succeed, or give up. + + int retry = 8; + long sleep = 10; + while (retry > 0) + { + try + { + removeImpl(); + retry = 0; + } + catch (DirectoryNotEmptyException&) + { + if (--retry == 0) throw; + Poco::Thread::sleep(sleep); + sleep *= 2; + } + } + } + else + { + removeImpl(); } - removeImpl(); } diff --git a/Foundation/src/File_UNIX.cpp b/Foundation/src/File_UNIX.cpp index f8fc2e338..d01fe8bd6 100644 --- a/Foundation/src/File_UNIX.cpp +++ b/Foundation/src/File_UNIX.cpp @@ -507,7 +507,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) throw FileException("disk quota exceeded", path, errno); #if !defined(_AIX) case ENOTEMPTY: - throw FileException("directory not empty", path, errno); + throw DirectoryNotEmptyException(path, errno); #endif case ENAMETOOLONG: throw PathSyntaxException(path, errno); diff --git a/Foundation/src/File_VMS.cpp b/Foundation/src/File_VMS.cpp index a8b640e47..ebbdc2840 100644 --- a/Foundation/src/File_VMS.cpp +++ b/Foundation/src/File_VMS.cpp @@ -405,7 +405,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) case EDQUOT: throw FileException("disk quota exceeded", path); case ENOTEMPTY: - throw FileException("directory not empty", path); + throw DirectoryNotEmptyException(path, err); case ENAMETOOLONG: throw PathSyntaxException(path); default: diff --git a/Foundation/src/File_VX.cpp b/Foundation/src/File_VX.cpp index 4a59082b9..d36ba9ef9 100644 --- a/Foundation/src/File_VX.cpp +++ b/Foundation/src/File_VX.cpp @@ -389,7 +389,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) case ENOSPC: throw FileException("no space left on device", path); case ENOTEMPTY: - throw FileException("directory not empty", path); + throw DirectoryNotEmptyException(path); case ENAMETOOLONG: throw PathSyntaxException(path); case ENFILE: diff --git a/Foundation/src/File_WIN32.cpp b/Foundation/src/File_WIN32.cpp index 9cb92e3ea..e777b257b 100644 --- a/Foundation/src/File_WIN32.cpp +++ b/Foundation/src/File_WIN32.cpp @@ -409,7 +409,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) case ERROR_CANNOT_MAKE: throw CreateFileException(path, err); case ERROR_DIR_NOT_EMPTY: - throw FileException("directory not empty", path, err); + throw DirectoryNotEmptyException(path, err); case ERROR_WRITE_FAULT: throw WriteFileException(path, err); case ERROR_READ_FAULT: diff --git a/Foundation/src/File_WIN32U.cpp b/Foundation/src/File_WIN32U.cpp index 3bdff0171..370350fda 100644 --- a/Foundation/src/File_WIN32U.cpp +++ b/Foundation/src/File_WIN32U.cpp @@ -417,7 +417,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) case ERROR_CANNOT_MAKE: throw CreateFileException(path, err); case ERROR_DIR_NOT_EMPTY: - throw FileException("directory not empty", path, err); + throw DirectoryNotEmptyException(path, err); case ERROR_WRITE_FAULT: throw WriteFileException(path, err); case ERROR_READ_FAULT: diff --git a/Foundation/src/File_WINCE.cpp b/Foundation/src/File_WINCE.cpp index a11b1c822..5f5ddc0b6 100644 --- a/Foundation/src/File_WINCE.cpp +++ b/Foundation/src/File_WINCE.cpp @@ -407,7 +407,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path) case ERROR_CANNOT_MAKE: throw CreateFileException(path); case ERROR_DIR_NOT_EMPTY: - throw FileException("directory not empty", path); + throw DirectoryNotEmptyException(path); case ERROR_WRITE_FAULT: throw WriteFileException(path); case ERROR_READ_FAULT: From 0ad635c5d4320cfaa926bb666c7ea0ac336e7ba2 Mon Sep 17 00:00:00 2001 From: Xu Yifeng Date: Wed, 9 Nov 2016 17:05:50 +0800 Subject: [PATCH 073/305] Add a new bind() and bind6() interface and make REUSEPORT as an option. SO_REUSEADDR is to reuse a socket in time-wait state, this is often turned on by server applicationis, but if a port is being used, the server could fail, this is expected. But with SO_REUSEPORT option, it even can open a port which is being used, this is a more error prone than SO_REUSEADDR, because we normally don't want to share a port with irrelevant application without notice, the behavior should not be default. --- Net/include/Poco/Net/DatagramSocket.h | 14 ++++++ Net/include/Poco/Net/RawSocket.h | 14 ++++++ Net/include/Poco/Net/ServerSocket.h | 63 +++++++++++++++++++++++++++ Net/include/Poco/Net/SocketImpl.h | 33 ++++++++++++++ Net/include/Poco/Net/WebSocketImpl.h | 2 + Net/src/DatagramSocket.cpp | 6 +++ Net/src/RawSocket.cpp | 6 +++ Net/src/ServerSocket.cpp | 29 ++++++++++++ Net/src/SocketImpl.cpp | 18 ++++++-- Net/src/WebSocketImpl.cpp | 11 +++++ 10 files changed, 192 insertions(+), 4 deletions(-) diff --git a/Net/include/Poco/Net/DatagramSocket.h b/Net/include/Poco/Net/DatagramSocket.h index e25a16b0c..93ba3505a 100644 --- a/Net/include/Poco/Net/DatagramSocket.h +++ b/Net/include/Poco/Net/DatagramSocket.h @@ -89,6 +89,20 @@ public: /// /// Calls to connect cannot() come before calls to bind(). + void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// Calls to connect cannot() come before calls to bind(). + int sendBytes(const void* buffer, int length, int flags = 0); /// Sends the contents of the given buffer through /// the socket. diff --git a/Net/include/Poco/Net/RawSocket.h b/Net/include/Poco/Net/RawSocket.h index 43efd7a95..75b62bfbb 100644 --- a/Net/include/Poco/Net/RawSocket.h +++ b/Net/include/Poco/Net/RawSocket.h @@ -82,6 +82,20 @@ public: /// /// Calls to connect() cannot come before calls to bind(). + void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// Calls to connect() cannot come before calls to bind(). + int sendBytes(const void* buffer, int length, int flags = 0); /// Sends the contents of the given buffer through /// the socket. diff --git a/Net/include/Poco/Net/ServerSocket.h b/Net/include/Poco/Net/ServerSocket.h index 2fb7727a0..aeddcff5a 100644 --- a/Net/include/Poco/Net/ServerSocket.h +++ b/Net/include/Poco/Net/ServerSocket.h @@ -82,6 +82,19 @@ public: /// If reuseAddress is true, sets the SO_REUSEADDR /// socket option. + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Binds a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reuseAddress is true, sets the SO_REUSEPORT + /// socket option. + virtual void bind(Poco::UInt16 port, bool reuseAddress = false); /// Binds a local port to the socket. /// @@ -91,6 +104,18 @@ public: /// If reuseAddress is true, sets the SO_REUSEADDR /// socket option. + virtual void bind(Poco::UInt16 port, bool reuseAddress, bool reusePort); + /// Binds a local port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); /// Binds a local IPv6 address to the socket. /// @@ -108,6 +133,26 @@ public: /// If the library has not been built with IPv6 support, /// a Poco::NotImplementedException will be thrown. + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Binds a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + virtual void bind6(Poco::UInt16 port, bool reuseAddress = false, bool ipV6Only = false); /// Binds a local IPv6 port to the socket. /// @@ -124,6 +169,24 @@ public: /// If the library has not been built with IPv6 support, /// a Poco::NotImplementedException will be thrown. + virtual void bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Binds a local IPv6 port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + virtual void listen(int backlog = 64); /// Puts the socket into listening state. /// diff --git a/Net/include/Poco/Net/SocketImpl.h b/Net/include/Poco/Net/SocketImpl.h index 533332e6c..217da21af 100644 --- a/Net/include/Poco/Net/SocketImpl.h +++ b/Net/include/Poco/Net/SocketImpl.h @@ -86,6 +86,19 @@ public: /// If reuseAddress is true, sets the SO_REUSEADDR /// socket option. + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort ); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); /// Bind a local IPv6 address to the socket. /// @@ -103,6 +116,26 @@ public: /// If the library has not been built with IPv6 support, /// a Poco::NotImplementedException will be thrown. + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Bind a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + virtual void listen(int backlog = 64); /// Puts the socket into listening state. /// diff --git a/Net/include/Poco/Net/WebSocketImpl.h b/Net/include/Poco/Net/WebSocketImpl.h index 060bc8a67..fc1135dcc 100644 --- a/Net/include/Poco/Net/WebSocketImpl.h +++ b/Net/include/Poco/Net/WebSocketImpl.h @@ -52,7 +52,9 @@ public: virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout); virtual void connectNB(const SocketAddress& address); virtual void bind(const SocketAddress& address, bool reuseAddress = false); + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); virtual void listen(int backlog = 64); virtual void close(); virtual void shutdownReceive(); diff --git a/Net/src/DatagramSocket.cpp b/Net/src/DatagramSocket.cpp index ce5d6b7ee..a7acbd480 100644 --- a/Net/src/DatagramSocket.cpp +++ b/Net/src/DatagramSocket.cpp @@ -83,6 +83,12 @@ void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress) } +void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + int DatagramSocket::sendBytes(const void* buffer, int length, int flags) { return impl()->sendBytes(buffer, length, flags); diff --git a/Net/src/RawSocket.cpp b/Net/src/RawSocket.cpp index 2f35c3027..641ad158e 100644 --- a/Net/src/RawSocket.cpp +++ b/Net/src/RawSocket.cpp @@ -86,6 +86,12 @@ void RawSocket::bind(const SocketAddress& address, bool reuseAddress) } +void RawSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + int RawSocket::sendBytes(const void* buffer, int length, int flags) { return impl()->sendBytes(buffer, length, flags); diff --git a/Net/src/ServerSocket.cpp b/Net/src/ServerSocket.cpp index d52e5977a..ca86fce36 100644 --- a/Net/src/ServerSocket.cpp +++ b/Net/src/ServerSocket.cpp @@ -80,6 +80,12 @@ void ServerSocket::bind(const SocketAddress& address, bool reuseAddress) } +void ServerSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress) { IPAddress wildcardAddr; @@ -88,12 +94,24 @@ void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress) } +void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress, bool reusePort) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, reuseAddress, reusePort); +} + void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) { impl()->bind6(address, reuseAddress, ipV6Only); } +void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) +{ + impl()->bind6(address, reuseAddress, reusePort, ipV6Only); +} + void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only) { #if defined(POCO_HAVE_IPv6) @@ -106,6 +124,17 @@ void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only) } +void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only) +{ +#if defined(POCO_HAVE_IPv6) + IPAddress wildcardAddr(IPAddress::IPv6); + SocketAddress address(wildcardAddr, port); + impl()->bind6(address, reuseAddress, reusePort, ipV6Only); +#else + throw Poco::NotImplementedException("No IPv6 support available"); +#endif // POCO_HAVE_IPv6 +} + void ServerSocket::listen(int backlog) { impl()->listen(backlog); diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 1357b3501..02dcdda9c 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -190,16 +190,21 @@ void SocketImpl::connectNB(const SocketAddress& address) void SocketImpl::bind(const SocketAddress& address, bool reuseAddress) +{ + bind(address, reuseAddress, true); +} + + +void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) { if (_sockfd == POCO_INVALID_SOCKET) { init(address.af()); } if (reuseAddress) - { setReuseAddress(true); + if (reusePort) setReusePort(true); - } #if defined(POCO_VXWORKS) int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length()); #else @@ -210,6 +215,12 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress) void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) +{ + bind6(address, reuseAddress, true, ipV6Only); +} + + +void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) { #if defined(POCO_HAVE_IPv6) if (address.family() != SocketAddress::IPv6) @@ -225,10 +236,9 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined."); #endif if (reuseAddress) - { setReuseAddress(true); + if (reusePort) setReusePort(true); - } int rc = ::bind(_sockfd, address.addr(), address.length()); if (rc != 0) error(address.toString()); #else diff --git a/Net/src/WebSocketImpl.cpp b/Net/src/WebSocketImpl.cpp index 760a75061..d1c72d843 100644 --- a/Net/src/WebSocketImpl.cpp +++ b/Net/src/WebSocketImpl.cpp @@ -257,12 +257,23 @@ void WebSocketImpl::bind(const SocketAddress& address, bool reuseAddress) } +void WebSocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl"); +} + + void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) { throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); } +void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) +{ + throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); +} + void WebSocketImpl::listen(int backlog) { throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl"); From 92bdee1e70875c535f05edf0c1ed790d12238cc9 Mon Sep 17 00:00:00 2001 From: Dawid Drozd Date: Sun, 14 Aug 2016 18:04:38 +0200 Subject: [PATCH 074/305] Fix for android include pthread.h from /usr/include --- CMakeLists.txt | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a95ec5db6..33355a907 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,18 +182,20 @@ if(WIN32 AND ENABLE_NETSSL_WIN) list(APPEND Poco_COMPONENTS "NetSSL_Win") endif(WIN32 AND ENABLE_NETSSL_WIN) -find_package(OpenSSL) -if(OPENSSL_FOUND) - include_directories("${OPENSSL_INCLUDE_DIR}") - if(ENABLE_NETSSL) - add_subdirectory(NetSSL_OpenSSL) - list(APPEND Poco_COMPONENTS "NetSSL_OpenSSL") - endif() - if(ENABLE_CRYPTO) - add_subdirectory(Crypto) - list(APPEND Poco_COMPONENTS "Crypto") - endif() -endif(OPENSSL_FOUND) +if(ENABLE_NETSSL OR ENABLE_CRYPTO) + find_package(OpenSSL) + if(OPENSSL_FOUND) + include_directories("${OPENSSL_INCLUDE_DIR}") + if(ENABLE_NETSSL) + add_subdirectory(NetSSL_OpenSSL) + list(APPEND Poco_COMPONENTS "NetSSL_OpenSSL") + endif() + if(ENABLE_CRYPTO) + add_subdirectory(Crypto) + list(APPEND Poco_COMPONENTS "Crypto") + endif() + endif(OPENSSL_FOUND) +endif(ENABLE_NETSSL OR ENABLE_CRYPTO) if(ENABLE_DATA) add_subdirectory(Data) From abb54a4b6789997d61e6c2b192e69b63716e4913 Mon Sep 17 00:00:00 2001 From: Dawid Drozd Date: Wed, 9 Nov 2016 11:07:21 +0100 Subject: [PATCH 075/305] Add required when looking for OpenSSL Fixes accoring to code review: https://github.com/pocoproject/poco/pull/1351/files/5771eccd31c923b28aa690b88ca409bba91db1e8 --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33355a907..8a9d1bda6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,7 +183,7 @@ if(WIN32 AND ENABLE_NETSSL_WIN) endif(WIN32 AND ENABLE_NETSSL_WIN) if(ENABLE_NETSSL OR ENABLE_CRYPTO) - find_package(OpenSSL) + find_package(OpenSSL REQUIRED) if(OPENSSL_FOUND) include_directories("${OPENSSL_INCLUDE_DIR}") if(ENABLE_NETSSL) @@ -316,4 +316,3 @@ message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO:=${CMAKE_CXX_FLAGS_RELWITHDEBINFO foreach(component ${Poco_COMPONENTS}) message(STATUS "Building: ${component}") endforeach() - From 696a9de502a6a78d6565e7c705bba9c496a14062 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 9 Nov 2016 12:22:49 +0100 Subject: [PATCH 076/305] GH #1481, GH #1449: fix broken tests due to changed dns resolution --- Net/include/Poco/Net/NetException.h | 1 + Net/include/Poco/Net/SocketAddress.h | 35 +++++++++ Net/src/NetException.cpp | 3 +- Net/src/ServerSocket.cpp | 3 + Net/src/SocketAddress.cpp | 82 ++++++++++++++++++++- Net/src/WebSocketImpl.cpp | 1 + Net/testsuite/src/DNSTest.cpp | 8 +- Net/testsuite/src/DatagramSocketTest.cpp | 8 +- Net/testsuite/src/DialogSocketTest.cpp | 2 +- Net/testsuite/src/FTPClientSessionTest.cpp | 30 ++++---- Net/testsuite/src/FTPStreamFactoryTest.cpp | 10 +-- Net/testsuite/src/HTTPClientSessionTest.cpp | 30 ++++---- Net/testsuite/src/HTTPServerTest.cpp | 28 +++---- Net/testsuite/src/ICMPClientTest.cpp | 4 +- Net/testsuite/src/POP3ClientSessionTest.cpp | 16 ++-- Net/testsuite/src/RawSocketTest.cpp | 4 +- Net/testsuite/src/SMTPClientSessionTest.cpp | 14 ++-- Net/testsuite/src/SocketAddressTest.cpp | 23 +++++- Net/testsuite/src/SocketReactorTest.cpp | 8 +- Net/testsuite/src/SocketStreamTest.cpp | 6 +- Net/testsuite/src/SocketTest.cpp | 30 ++++---- Net/testsuite/src/TCPServerTest.cpp | 6 +- Net/testsuite/src/WebSocketTest.cpp | 6 +- 23 files changed, 246 insertions(+), 112 deletions(-) diff --git a/Net/include/Poco/Net/NetException.h b/Net/include/Poco/Net/NetException.h index a8e22bf65..40e5a2802 100644 --- a/Net/include/Poco/Net/NetException.h +++ b/Net/include/Poco/Net/NetException.h @@ -53,6 +53,7 @@ POCO_DECLARE_EXCEPTION(Net_API, NTPException, NetException) POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException) POCO_DECLARE_EXCEPTION(Net_API, WebSocketException, NetException) POCO_DECLARE_EXCEPTION(Net_API, UnsupportedFamilyException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, AddressFamilyMismatchException, NetException) } } // namespace Poco::Net diff --git a/Net/include/Poco/Net/SocketAddress.h b/Net/include/Poco/Net/SocketAddress.h index 19a87c337..72f7cf837 100644 --- a/Net/include/Poco/Net/SocketAddress.h +++ b/Net/include/Poco/Net/SocketAddress.h @@ -58,6 +58,10 @@ public: SocketAddress(); /// Creates a wildcard (all zero) IPv4 SocketAddress. + explicit SocketAddress(Family family); + /// Creates a SocketAddress with unspecified (wildcard) IP address + /// of the given family. + SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber); /// Creates a SocketAddress from an IP address and given port number. @@ -65,12 +69,27 @@ public: /// Creates a SocketAddress with unspecified (wildcard) IP address /// and given port number. + SocketAddress(Family family, Poco::UInt16 port); + /// Creates a SocketAddress with unspecified (wildcard) IP address + /// of the given family, and given port number. + SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber); /// Creates a SocketAddress from an IP address and given port number. /// /// The IP address must either be a domain name, or it must /// be in dotted decimal (IPv4) or hex string (IPv6) format. + SocketAddress(Family family, const std::string& hostAddress, Poco::UInt16 portNumber); + /// Creates a SocketAddress from an IP address and given port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + /// + /// If a domain name is given in hostAddress, it is resolved and the address + /// matching the given family is used. If no address matching the given family + /// is found, or the IP address given in hostAddress does not match the given + /// family, an AddressFamilyMismatchException is thrown. + SocketAddress(const std::string& hostAddress, const std::string& portNumber); /// Creates a SocketAddress from an IP address and the /// service name or port number. @@ -81,6 +100,21 @@ public: /// The given port must either be a decimal port number, or /// a service name. + SocketAddress(Family family, const std::string& hostAddress, const std::string& portNumber); + /// Creates a SocketAddress from an IP address and the + /// service name or port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + /// + /// The given port must either be a decimal port number, or + /// a service name. + /// + /// If a domain name is given in hostAddress, it is resolved and the address + /// matching the given family is used. If no address matching the given family + /// is found, or the IP address given in hostAddress does not match the given + /// family, an AddressFamilyMismatchException is thrown. + explicit SocketAddress(const std::string& hostAndPort); /// Creates a SocketAddress from an IP address or host name and the /// port number/service name. Host name/address and port number must @@ -156,6 +190,7 @@ public: protected: void init(const IPAddress& hostAddress, Poco::UInt16 portNumber); void init(const std::string& hostAddress, Poco::UInt16 portNumber); + void init(Family family, const std::string& hostAddress, Poco::UInt16 portNumber); void init(Family family, const std::string& address); void init(const std::string& hostAndPort); Poco::UInt16 resolveService(const std::string& service); diff --git a/Net/src/NetException.cpp b/Net/src/NetException.cpp index 1c76342e1..a57423de6 100644 --- a/Net/src/NetException.cpp +++ b/Net/src/NetException.cpp @@ -49,7 +49,8 @@ POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception") POCO_IMPLEMENT_EXCEPTION(NTPException, NetException, "NTP Exception") POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception") POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception") -POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family.") +POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family") +POCO_IMPLEMENT_EXCEPTION(AddressFamilyMismatchException, NetException, "Address family mismatch") } } // namespace Poco::Net diff --git a/Net/src/ServerSocket.cpp b/Net/src/ServerSocket.cpp index ca86fce36..54ac6ae30 100644 --- a/Net/src/ServerSocket.cpp +++ b/Net/src/ServerSocket.cpp @@ -101,6 +101,7 @@ void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress, bool reusePort) impl()->bind(address, reuseAddress, reusePort); } + void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) { impl()->bind6(address, reuseAddress, ipV6Only); @@ -112,6 +113,7 @@ void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool r impl()->bind6(address, reuseAddress, reusePort, ipV6Only); } + void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only) { #if defined(POCO_HAVE_IPv6) @@ -135,6 +137,7 @@ void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, b #endif // POCO_HAVE_IPv6 } + void ServerSocket::listen(int backlog) { impl()->listen(backlog); diff --git a/Net/src/SocketAddress.cpp b/Net/src/SocketAddress.cpp index 6c3aec0a8..5354ace75 100644 --- a/Net/src/SocketAddress.cpp +++ b/Net/src/SocketAddress.cpp @@ -77,6 +77,12 @@ SocketAddress::SocketAddress() } +SocketAddress::SocketAddress(Family fam) +{ + init(IPAddress(fam), 0); +} + + SocketAddress::SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber) { init(hostAddress, portNumber); @@ -89,21 +95,39 @@ SocketAddress::SocketAddress(Poco::UInt16 portNumber) } +SocketAddress::SocketAddress(Family fam, Poco::UInt16 portNumber) +{ + init(IPAddress(fam), portNumber); +} + + SocketAddress::SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber) { init(hostAddress, portNumber); } +SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) +{ + init(fam, hostAddress, portNumber); +} + + SocketAddress::SocketAddress(const std::string& hostAddress, const std::string& portNumber) { init(hostAddress, resolveService(portNumber)); } -SocketAddress::SocketAddress(Family family, const std::string& addr) +SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, const std::string& portNumber) { - init(family, addr); + init(fam, hostAddress, resolveService(portNumber)); +} + + +SocketAddress::SocketAddress(Family fam, const std::string& addr) +{ + init(fam, addr); } @@ -261,6 +285,35 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber } +void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) +{ + IPAddress ip; + if (IPAddress::tryParse(hostAddress, ip)) + { + if (ip.family() != fam) throw AddressFamilyMismatchException(hostAddress); + init(ip, portNumber); + } + else + { + HostEntry he = DNS::hostByName(hostAddress); + HostEntry::AddressList addresses = he.addresses(); + if (addresses.size() > 0) + { + for (HostEntry::AddressList::const_iterator it = addresses.begin(); it != addresses.end(); ++it) + { + if (it->family() == fam) + { + init(*it, portNumber); + return; + } + } + throw AddressFamilyMismatchException(hostAddress); + } + else throw HostNotFoundException("No address found for host", hostAddress); + } +} + + void SocketAddress::init(Family fam, const std::string& address) { #if defined(POCO_OS_FAMILY_UNIX) @@ -271,8 +324,29 @@ void SocketAddress::init(Family fam, const std::string& address) else #endif { - init(address); - if (fam != family()) throw Poco::InvalidArgumentException("address does not fit family"); + std::string host; + std::string port; + std::string::const_iterator it = address.begin(); + std::string::const_iterator end = address.end(); + + if (*it == '[') + { + ++it; + while (it != end && *it != ']') host += *it++; + if (it == end) throw InvalidArgumentException("Malformed IPv6 address"); + ++it; + } + else + { + while (it != end && *it != ':') host += *it++; + } + if (it != end && *it == ':') + { + ++it; + while (it != end) port += *it++; + } + else throw InvalidArgumentException("Missing port number"); + init(fam, host, resolveService(port)); } } diff --git a/Net/src/WebSocketImpl.cpp b/Net/src/WebSocketImpl.cpp index d1c72d843..0e5ac6075 100644 --- a/Net/src/WebSocketImpl.cpp +++ b/Net/src/WebSocketImpl.cpp @@ -274,6 +274,7 @@ void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); } + void WebSocketImpl::listen(int backlog) { throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl"); diff --git a/Net/testsuite/src/DNSTest.cpp b/Net/testsuite/src/DNSTest.cpp index 559cad4e0..6316fb79e 100644 --- a/Net/testsuite/src/DNSTest.cpp +++ b/Net/testsuite/src/DNSTest.cpp @@ -39,20 +39,20 @@ DNSTest::~DNSTest() void DNSTest::testHostByName() { - HostEntry he1 = DNS::hostByName("aliastest.appinf.com"); + HostEntry he1 = DNS::hostByName("aliastest.pocoproject.org"); // different systems report different canonical names, unfortunately. - assert (he1.name() == "dnstest.appinf.com" || he1.name() == "aliastest.appinf.com"); + assert (he1.name() == "dnstest.pocoproject.org" || he1.name() == "aliastest.pocoproject.org"); #if !defined(POCO_HAVE_ADDRINFO) // getaddrinfo() does not report any aliases assert (!he1.aliases().empty()); - assert (he1.aliases()[0] == "aliastest.appinf.com"); + assert (he1.aliases()[0] == "aliastest.pocoproject.org"); #endif assert (he1.addresses().size() >= 1); assert (he1.addresses()[0].toString() == "1.2.3.4"); try { - HostEntry he1 = DNS::hostByName("nohost.appinf.com"); + HostEntry he1 = DNS::hostByName("nohost.pocoproject.org"); fail("host not found - must throw"); } catch (HostNotFoundException&) diff --git a/Net/testsuite/src/DatagramSocketTest.cpp b/Net/testsuite/src/DatagramSocketTest.cpp index b5d7a54d5..1b3efd9f1 100644 --- a/Net/testsuite/src/DatagramSocketTest.cpp +++ b/Net/testsuite/src/DatagramSocketTest.cpp @@ -51,7 +51,7 @@ void DatagramSocketTest::testEcho() UDPEchoServer echoServer; DatagramSocket ss; char buffer[256]; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); int n = ss.sendBytes("hello", 5); assert (n == 5); n = ss.receiveBytes(buffer, sizeof(buffer)); @@ -63,9 +63,9 @@ void DatagramSocketTest::testEcho() void DatagramSocketTest::testSendToReceiveFrom() { - UDPEchoServer echoServer(SocketAddress("localhost", 0)); + UDPEchoServer echoServer(SocketAddress("127.0.0.1", 0)); DatagramSocket ss(SocketAddress::IPv4); - int n = ss.sendTo("hello", 5, SocketAddress("localhost", echoServer.port())); + int n = ss.sendTo("hello", 5, SocketAddress("127.0.0.1", echoServer.port())); assert (n == 5); char buffer[256]; SocketAddress sa; @@ -83,7 +83,7 @@ void DatagramSocketTest::testUnbound() UDPEchoServer echoServer; DatagramSocket ss; char buffer[256]; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); int n = ss.sendBytes("hello", 5); assert (n == 5); n = ss.receiveBytes(buffer, sizeof(buffer)); diff --git a/Net/testsuite/src/DialogSocketTest.cpp b/Net/testsuite/src/DialogSocketTest.cpp index f9c895d12..fcb4b00d2 100644 --- a/Net/testsuite/src/DialogSocketTest.cpp +++ b/Net/testsuite/src/DialogSocketTest.cpp @@ -37,7 +37,7 @@ void DialogSocketTest::testDialogSocket() { EchoServer echoServer; DialogSocket ds; - ds.connect(SocketAddress("localhost", echoServer.port())); + ds.connect(SocketAddress("127.0.0.1", echoServer.port())); ds.sendMessage("Hello, world!"); std::string str; diff --git a/Net/testsuite/src/FTPClientSessionTest.cpp b/Net/testsuite/src/FTPClientSessionTest.cpp index 062104265..e7e4a340a 100644 --- a/Net/testsuite/src/FTPClientSessionTest.cpp +++ b/Net/testsuite/src/FTPClientSessionTest.cpp @@ -94,7 +94,7 @@ void FTPClientSessionTest::testLogin1() { DialogServer server; server.addResponse("220 localhost FTP ready"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); assert (session.isOpen()); assert (!session.isLoggedIn()); login(server, session); @@ -125,7 +125,7 @@ void FTPClientSessionTest::testLogin2() server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); Poco::UInt16 serverPort = server.port(); - FTPClientSession session("localhost", serverPort, "user", "password"); + FTPClientSession session("127.0.0.1", serverPort, "user", "password"); assert (session.isOpen()); assert (session.isLoggedIn()); server.addResponse("221 Good Bye"); @@ -139,7 +139,7 @@ void FTPClientSessionTest::testLogin2() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - session.open("localhost", serverPort, "user", "password"); + session.open("127.0.0.1", serverPort, "user", "password"); assert (session.isOpen()); assert (session.isLoggedIn()); server.addResponse("221 Good Bye"); @@ -159,7 +159,7 @@ void FTPClientSessionTest::testLogin3() FTPClientSession session; assert (!session.isOpen()); assert (!session.isLoggedIn()); - session.open("localhost", server.port(), "user", "password"); + session.open("127.0.0.1", server.port(), "user", "password"); server.addResponse("221 Good Bye"); session.close(); assert (!session.isOpen()); @@ -172,7 +172,7 @@ void FTPClientSessionTest::testLoginFailed1() { DialogServer server; server.addResponse("421 localhost FTP not ready"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); try { session.login("user", "password"); @@ -192,7 +192,7 @@ void FTPClientSessionTest::testLoginFailed2() server.addResponse("220 localhost FTP ready"); server.addResponse("331 Password required"); server.addResponse("530 Login incorrect"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); try { session.login("user", "password"); @@ -213,7 +213,7 @@ void FTPClientSessionTest::testCommands() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.login("user", "password"); std::string cmd = server.popCommand(); assert (cmd == "USER user"); @@ -342,7 +342,7 @@ void FTPClientSessionTest::testDownloadPORT() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.setPassive(false); session.login("user", "password"); server.clearCommands(); @@ -373,7 +373,7 @@ void FTPClientSessionTest::testDownloadPORT() cmd = server.popCommandWait(); assert (cmd == "RETR test.txt"); - SocketAddress sa("localhost", (Poco::UInt16) port); + SocketAddress sa("127.0.0.1", (Poco::UInt16) port); DialogSocket dataSock; dataSock.connect(sa); @@ -397,7 +397,7 @@ void FTPClientSessionTest::testDownloadEPRT() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.setPassive(false); session.login("user", "password"); server.clearCommands(); @@ -421,7 +421,7 @@ void FTPClientSessionTest::testDownloadEPRT() cmd = server.popCommandWait(); assert (cmd == "RETR test.txt"); - SocketAddress sa("localhost", (Poco::UInt16) port); + SocketAddress sa("127.0.0.1", (Poco::UInt16) port); DialogSocket dataSock; dataSock.connect(sa); @@ -445,7 +445,7 @@ void FTPClientSessionTest::testDownloadPASV() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.login("user", "password"); server.clearCommands(); @@ -478,7 +478,7 @@ void FTPClientSessionTest::testDownloadEPSV() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.login("user", "password"); server.clearCommands(); @@ -513,7 +513,7 @@ void FTPClientSessionTest::testUpload() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.login("user", "password"); server.clearCommands(); @@ -546,7 +546,7 @@ void FTPClientSessionTest::testList() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - FTPClientSession session("localhost", server.port()); + FTPClientSession session("127.0.0.1", server.port()); session.login("user", "password"); server.clearCommands(); diff --git a/Net/testsuite/src/FTPStreamFactoryTest.cpp b/Net/testsuite/src/FTPStreamFactoryTest.cpp index 1a7e78d94..ef1c887a9 100644 --- a/Net/testsuite/src/FTPStreamFactoryTest.cpp +++ b/Net/testsuite/src/FTPStreamFactoryTest.cpp @@ -77,7 +77,7 @@ void FTPStreamFactoryTest::testDownload() URI uri; uri.setScheme("ftp"); - uri.setHost("localhost"); + uri.setHost("127.0.0.1"); uri.setPort(server.port()); uri.setPath("/test.txt;type=a"); FTPStreamFactory sf; @@ -115,7 +115,7 @@ void FTPStreamFactoryTest::testList() URI uri; uri.setScheme("ftp"); - uri.setHost("localhost"); + uri.setHost("127.0.0.1"); uri.setPort(server.port()); uri.setPath("/usr/guest/data;type=d"); FTPStreamFactory sf; @@ -152,7 +152,7 @@ void FTPStreamFactoryTest::testUserInfo() URI uri; uri.setScheme("ftp"); - uri.setHost("localhost"); + uri.setHost("127.0.0.1"); uri.setPort(server.port()); uri.setPath("/test.txt;type=a"); uri.setUserInfo("user:secret"); @@ -191,7 +191,7 @@ void FTPStreamFactoryTest::testPasswordProvider() URI uri; uri.setScheme("ftp"); - uri.setHost("localhost"); + uri.setHost("127.0.0.1"); uri.setPort(server.port()); uri.setPath("/test.txt;type=a"); uri.setUserInfo("user"); @@ -218,7 +218,7 @@ void FTPStreamFactoryTest::testMissingPasswordProvider() URI uri; uri.setScheme("ftp"); - uri.setHost("localhost"); + uri.setHost("127.0.0.1"); uri.setPort(server.port()); uri.setPath("/test.txt;type=a"); uri.setUserInfo("user"); diff --git a/Net/testsuite/src/HTTPClientSessionTest.cpp b/Net/testsuite/src/HTTPClientSessionTest.cpp index 87a31d697..2999c12ce 100644 --- a/Net/testsuite/src/HTTPClientSessionTest.cpp +++ b/Net/testsuite/src/HTTPClientSessionTest.cpp @@ -43,7 +43,7 @@ HTTPClientSessionTest::~HTTPClientSessionTest() void HTTPClientSessionTest::testGetSmall() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/small"); s.sendRequest(request); HTTPResponse response; @@ -59,7 +59,7 @@ void HTTPClientSessionTest::testGetSmall() void HTTPClientSessionTest::testGetLarge() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); s.sendRequest(request); HTTPResponse response; @@ -75,7 +75,7 @@ void HTTPClientSessionTest::testGetLarge() void HTTPClientSessionTest::testHead() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/large"); s.sendRequest(request); HTTPResponse response; @@ -90,7 +90,7 @@ void HTTPClientSessionTest::testHead() void HTTPClientSessionTest::testPostSmallIdentity() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body\r\n0\r\n"); request.setContentLength((int) body.length()); @@ -107,7 +107,7 @@ void HTTPClientSessionTest::testPostSmallIdentity() void HTTPClientSessionTest::testPostLargeIdentity() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(8000, 'x'); body.append("\r\n0\r\n"); @@ -125,7 +125,7 @@ void HTTPClientSessionTest::testPostLargeIdentity() void HTTPClientSessionTest::testPostSmallChunked() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body"); request.setChunkedTransferEncoding(true); @@ -143,7 +143,7 @@ void HTTPClientSessionTest::testPostSmallChunked() void HTTPClientSessionTest::testPostLargeChunked() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(16000, 'x'); request.setChunkedTransferEncoding(true); @@ -163,7 +163,7 @@ void HTTPClientSessionTest::testPostLargeChunked() void HTTPClientSessionTest::testPostSmallClose() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body"); s.sendRequest(request) << body; @@ -180,7 +180,7 @@ void HTTPClientSessionTest::testPostSmallClose() void HTTPClientSessionTest::testPostLargeClose() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(8000, 'x'); s.sendRequest(request) << body; @@ -197,7 +197,7 @@ void HTTPClientSessionTest::testPostLargeClose() void HTTPClientSessionTest::testKeepAlive() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); s.setKeepAlive(true); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/keepAlive", HTTPMessage::HTTP_1_1); s.sendRequest(request); @@ -246,7 +246,7 @@ void HTTPClientSessionTest::testProxy() { HTTPTestServer srv; HTTPClientSession s("www.somehost.com"); - s.setProxy("localhost", srv.port()); + s.setProxy("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); s.sendRequest(request); HTTPResponse response; @@ -263,7 +263,7 @@ void HTTPClientSessionTest::testProxyAuth() { HTTPTestServer srv; HTTPClientSession s("www.somehost.com"); - s.setProxy("localhost", srv.port()); + s.setProxy("127.0.0.1", srv.port()); s.setProxyCredentials("user", "pass"); HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); s.sendRequest(request); @@ -286,7 +286,7 @@ void HTTPClientSessionTest::testBypassProxy() proxyConfig.port = 80; proxyConfig.nonProxyHosts = "localhost|127\\.0\\.0\\.1"; - HTTPClientSession s1("localhost", 80); + HTTPClientSession s1("127.0.0.1", 80); s1.setProxyConfig(proxyConfig); assert (s1.bypassProxy()); @@ -303,7 +303,7 @@ void HTTPClientSessionTest::testBypassProxy() void HTTPClientSessionTest::testExpectContinue() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/expect"); std::string body("this is a random request body\r\n0\r\n"); request.setContentLength((int) body.length()); @@ -324,7 +324,7 @@ void HTTPClientSessionTest::testExpectContinue() void HTTPClientSessionTest::testExpectContinueFail() { HTTPTestServer srv; - HTTPClientSession s("localhost", srv.port()); + HTTPClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/fail"); std::string body("this is a random request body\r\n0\r\n"); request.setContentLength((int) body.length()); diff --git a/Net/testsuite/src/HTTPServerTest.cpp b/Net/testsuite/src/HTTPServerTest.cpp index 7dc31b554..e4900b4e3 100644 --- a/Net/testsuite/src/HTTPServerTest.cpp +++ b/Net/testsuite/src/HTTPServerTest.cpp @@ -146,7 +146,7 @@ void HTTPServerTest::testIdentityRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -169,7 +169,7 @@ void HTTPServerTest::testPutIdentityRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("PUT", "/echoBody"); request.setContentLength((int) body.length()); @@ -192,7 +192,7 @@ void HTTPServerTest::testChunkedRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentType("text/plain"); @@ -216,7 +216,7 @@ void HTTPServerTest::testClosedRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentType("text/plain"); @@ -236,7 +236,7 @@ void HTTPServerTest::testIdentityRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, 8008); srv.start(); - HTTPClientSession cs("localhost", srv.socket().address().port()); + HTTPClientSession cs("127.0.0.1", srv.socket().address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -267,7 +267,7 @@ void HTTPServerTest::testChunkedRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, 8009); srv.start(); - HTTPClientSession cs("localhost", srv.socket().address().port()); + HTTPClientSession cs("127.0.0.1", srv.socket().address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -299,7 +299,7 @@ void HTTPServerTest::testClosedRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, 8010); srv.start(); - HTTPClientSession cs("localhost", srv.socket().address().port()); + HTTPClientSession cs("127.0.0.1", srv.socket().address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentType("text/plain"); @@ -324,7 +324,7 @@ void HTTPServerTest::testMaxKeepAlive() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); request.setContentType("text/plain"); @@ -380,7 +380,7 @@ void HTTPServerTest::testKeepAliveTimeout() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); cs.setKeepAliveTimeout(Poco::Timespan(2, 0)); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -424,7 +424,7 @@ void HTTPServerTest::test100Continue() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -448,7 +448,7 @@ void HTTPServerTest::testRedirect() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/redirect"); cs.sendRequest(request); HTTPResponse response; @@ -468,7 +468,7 @@ void HTTPServerTest::testAuth() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/auth"); cs.sendRequest(request); HTTPResponse response; @@ -488,7 +488,7 @@ void HTTPServerTest::testNotImpl() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/notImpl"); cs.sendRequest(request); HTTPResponse response; @@ -507,7 +507,7 @@ void HTTPServerTest::testBuffer() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPClientSession cs("localhost", svs.address().port()); + HTTPClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/buffer"); cs.sendRequest(request); HTTPResponse response; diff --git a/Net/testsuite/src/ICMPClientTest.cpp b/Net/testsuite/src/ICMPClientTest.cpp index 1ac1923a8..2304b9d84 100644 --- a/Net/testsuite/src/ICMPClientTest.cpp +++ b/Net/testsuite/src/ICMPClientTest.cpp @@ -48,9 +48,9 @@ ICMPClientTest::~ICMPClientTest() void ICMPClientTest::testPing() { - assert(ICMPClient::pingIPv4("localhost") > 0); + assert(ICMPClient::pingIPv4("127.0.0.1") > 0); - assert(_icmpClient.ping("localhost") > 0); + assert(_icmpClient.ping("127.0.0.1") > 0); assert(_icmpClient.ping("www.appinf.com", 4) > 0); // warning: may fail depending on the existence of the addresses at test site diff --git a/Net/testsuite/src/POP3ClientSessionTest.cpp b/Net/testsuite/src/POP3ClientSessionTest.cpp index b9b0b23a3..3e8c6d846 100644 --- a/Net/testsuite/src/POP3ClientSessionTest.cpp +++ b/Net/testsuite/src/POP3ClientSessionTest.cpp @@ -42,7 +42,7 @@ void POP3ClientSessionTest::testLogin() server.addResponse("+OK USER"); server.addResponse("+OK PASS"); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); std::string cmd = server.popCommand(); assert (cmd == "USER user"); @@ -61,7 +61,7 @@ void POP3ClientSessionTest::testLoginFail() server.addResponse("+OK USER"); server.addResponse("-ERR PASS"); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); try { session.login("user", "secret"); @@ -82,7 +82,7 @@ void POP3ClientSessionTest::testMessageCount() server.addResponse("+OK PASS"); server.addResponse("+OK 42 12345"); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); int n = session.messageCount(); @@ -107,7 +107,7 @@ void POP3ClientSessionTest::testList() ".\r\n" ); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); std::vector infos; @@ -146,7 +146,7 @@ void POP3ClientSessionTest::testRetrieveMessage() ".\r\n" ); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); MailMessage message; @@ -182,7 +182,7 @@ void POP3ClientSessionTest::testRetrieveHeader() "." ); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); MessageHeader header; @@ -225,7 +225,7 @@ void POP3ClientSessionTest::testRetrieveMessages() "." ); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); MessageHeader header; @@ -261,7 +261,7 @@ void POP3ClientSessionTest::testDeleteMessage() server.addResponse("+OK PASS"); server.addResponse("+OK DELETED"); server.addResponse("+OK QUIT"); - POP3ClientSession session("localhost", server.port()); + POP3ClientSession session("127.0.0.1", server.port()); session.login("user", "secret"); server.clearCommands(); session.deleteMessage(42); diff --git a/Net/testsuite/src/RawSocketTest.cpp b/Net/testsuite/src/RawSocketTest.cpp index b043066af..973562c32 100644 --- a/Net/testsuite/src/RawSocketTest.cpp +++ b/Net/testsuite/src/RawSocketTest.cpp @@ -45,7 +45,7 @@ RawSocketTest::~RawSocketTest() void RawSocketTest::testEchoIPv4() { - SocketAddress sa("localhost", 0); + SocketAddress sa("127.0.0.1", 0); RawSocket rs(IPAddress::IPv4); rs.connect(sa); @@ -70,7 +70,7 @@ void RawSocketTest::testSendToReceiveFromIPv4() { RawSocket rs(IPAddress::IPv4); - int n = rs.sendTo("hello", 5, SocketAddress("localhost", 0)); + int n = rs.sendTo("hello", 5, SocketAddress("127.0.0.1", 0)); assert (n == 5); char buffer[256] = ""; diff --git a/Net/testsuite/src/SMTPClientSessionTest.cpp b/Net/testsuite/src/SMTPClientSessionTest.cpp index a36f75e91..ab800a55d 100644 --- a/Net/testsuite/src/SMTPClientSessionTest.cpp +++ b/Net/testsuite/src/SMTPClientSessionTest.cpp @@ -42,7 +42,7 @@ void SMTPClientSessionTest::testLoginEHLO() server.addResponse("220 localhost SMTP ready"); server.addResponse("250 Hello localhost"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); std::string cmd = server.popCommand(); assert (cmd == "EHLO localhost"); @@ -59,7 +59,7 @@ void SMTPClientSessionTest::testLoginHELO() server.addResponse("500 EHLO not understood"); server.addResponse("250 Hello localhost"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); std::string cmd = server.popCommand(); assert (cmd == "EHLO localhost"); @@ -76,7 +76,7 @@ void SMTPClientSessionTest::testLoginFailed() DialogServer server; server.addResponse("500 No SMTP service here"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); try { session.login("localhost"); @@ -99,7 +99,7 @@ void SMTPClientSessionTest::testSend() server.addResponse("354 Send data"); server.addResponse("250 OK"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); MailMessage message; @@ -153,7 +153,7 @@ void SMTPClientSessionTest::testSendMultiRecipient() server.addResponse("250 OK"); server.addResponse("250 OK"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); MailMessage message; @@ -218,7 +218,7 @@ void SMTPClientSessionTest::testMultiSeparateRecipient() server.addResponse("250 OK"); server.addResponse("250 OK"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); MailMessage message; @@ -285,7 +285,7 @@ void SMTPClientSessionTest::testSendFailed() server.addResponse("354 Send data"); server.addResponse("500 Error"); server.addResponse("221 Bye"); - SMTPClientSession session("localhost", server.port()); + SMTPClientSession session("127.0.0.1", server.port()); session.login("localhost"); MailMessage message; diff --git a/Net/testsuite/src/SocketAddressTest.cpp b/Net/testsuite/src/SocketAddressTest.cpp index fabf0b251..df51a909a 100644 --- a/Net/testsuite/src/SocketAddressTest.cpp +++ b/Net/testsuite/src/SocketAddressTest.cpp @@ -23,6 +23,7 @@ using Poco::Net::InvalidAddressException; using Poco::Net::HostNotFoundException; using Poco::Net::ServiceNotFoundException; using Poco::Net::NoAddressFoundException; +using Poco::Net::AddressFamilyMismatchException; using Poco::InvalidArgumentException; @@ -68,10 +69,10 @@ void SocketAddressTest::testSocketAddress() { } - SocketAddress sa4("www.appinf.com", 80); + SocketAddress sa4("pocoproject.org", 80); assert (sa4.host().toString() == "162.209.7.4"); assert (sa4.port() == 80); - + try { SocketAddress sa5("192.168.2.260", 80); @@ -118,6 +119,24 @@ void SocketAddressTest::testSocketAddress() catch (InvalidArgumentException&) { } + + SocketAddress sa10("www6.pocoproject.org", 80); + assert (sa10.host().toString() == "162.209.7.4" || sa10.host().toString() == "[2001:4801:7819:74:be76:4eff:fe10:6b73]"); + + SocketAddress sa11(SocketAddress::IPv4, "www6.pocoproject.org", 80); + assert (sa11.host().toString() == "162.209.7.4"); + +#ifdef POCO_HAVE_IPv6 + try + { + SocketAddress sa12(SocketAddress::IPv6, "www6.pocoproject.org", 80); + assert (sa12.host().toString() == "[2001:4801:7819:74:be76:4eff:fe10:6b73]"); + } + catch (AddressFamilyMismatchException&) + { + // may happen if no IPv6 address is configured on the system + } +#endif } diff --git a/Net/testsuite/src/SocketReactorTest.cpp b/Net/testsuite/src/SocketReactorTest.cpp index 938d900b1..79fb0e1c6 100644 --- a/Net/testsuite/src/SocketReactorTest.cpp +++ b/Net/testsuite/src/SocketReactorTest.cpp @@ -314,7 +314,7 @@ void SocketReactorTest::testSocketReactor() ServerSocket ss(ssa); SocketReactor reactor; SocketAcceptor acceptor(ss, reactor); - SocketAddress sa("localhost", ss.address().port()); + SocketAddress sa("127.0.0.1", ss.address().port()); SocketConnector connector(sa, reactor); ClientServiceHandler::setOnce(true); ClientServiceHandler::resetData(); @@ -334,7 +334,7 @@ void SocketReactorTest::testSetSocketReactor() SocketReactor reactor; SocketAcceptor acceptor(ss); acceptor.setReactor(reactor); - SocketAddress sa("localhost", ss.address().port()); + SocketAddress sa("127.0.0.1", ss.address().port()); SocketConnector connector(sa, reactor); ClientServiceHandler::setOnce(true); ClientServiceHandler::resetData(); @@ -353,7 +353,7 @@ void SocketReactorTest::testParallelSocketReactor() ServerSocket ss(ssa); SocketReactor reactor; ParallelSocketAcceptor acceptor(ss, reactor); - SocketAddress sa("localhost", ss.address().port()); + SocketAddress sa("127.0.0.1", ss.address().port()); SocketConnector connector1(sa, reactor); SocketConnector connector2(sa, reactor); SocketConnector connector3(sa, reactor); @@ -390,7 +390,7 @@ void SocketReactorTest::testSocketConnectorTimeout() SocketAddress ssa; ServerSocket ss(ssa); SocketReactor reactor; - SocketAddress sa("localhost", ss.address().port()); + SocketAddress sa("127.0.0.1", ss.address().port()); SocketConnector connector(sa, reactor); reactor.run(); assert (ClientServiceHandler::timeout()); diff --git a/Net/testsuite/src/SocketStreamTest.cpp b/Net/testsuite/src/SocketStreamTest.cpp index 8c9d15338..b2b5c95be 100644 --- a/Net/testsuite/src/SocketStreamTest.cpp +++ b/Net/testsuite/src/SocketStreamTest.cpp @@ -49,7 +49,7 @@ void SocketStreamTest::testStreamEcho() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); SocketStream str(ss); str << "hello"; assert (str.good()); @@ -72,7 +72,7 @@ void SocketStreamTest::testLargeStreamEcho() const int msgSize = 64000; EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); SocketStream str(ss); ss.setSendBufferSize(msgSize); ss.setReceiveBufferSize(msgSize); @@ -100,7 +100,7 @@ void SocketStreamTest::testEOF() { EchoServer echoServer; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); str << "hello"; assert (str.good()); str.flush(); diff --git a/Net/testsuite/src/SocketTest.cpp b/Net/testsuite/src/SocketTest.cpp index c0030e9c2..a52c01f88 100644 --- a/Net/testsuite/src/SocketTest.cpp +++ b/Net/testsuite/src/SocketTest.cpp @@ -55,7 +55,7 @@ void SocketTest::testEcho() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); int n = ss.sendBytes("hello", 5); assert (n == 5); char buffer[256]; @@ -70,7 +70,7 @@ void SocketTest::testPoll() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); Stopwatch sw; sw.start(); Timespan timeout(1000000); @@ -95,7 +95,7 @@ void SocketTest::testAvailable() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); Timespan timeout(1000000); ss.sendBytes("hello", 5); char buffer[256]; @@ -135,7 +135,7 @@ void SocketTest::testFIFOBuffer() EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); int n = ss.sendBytes(f); assert (n == 5); assert(1 == _notToReadable); @@ -172,7 +172,7 @@ void SocketTest::testConnect() serv.listen(); StreamSocket ss; Timespan timeout(250000); - ss.connect(SocketAddress("localhost", serv.address().port()), timeout); + ss.connect(SocketAddress("127.0.0.1", serv.address().port()), timeout); } @@ -187,7 +187,7 @@ void SocketTest::testConnectRefused() Timespan timeout(250000); try { - ss.connect(SocketAddress("localhost", port)); + ss.connect(SocketAddress("127.0.0.1", port)); fail("connection refused - must throw"); } catch (ConnectionRefusedException&) @@ -207,7 +207,7 @@ void SocketTest::testConnectRefusedNB() Timespan timeout(2, 0); try { - ss.connect(SocketAddress("localhost", port), timeout); + ss.connect(SocketAddress("127.0.0.1", port), timeout); fail("connection refused - must throw"); } catch (TimeoutException&) @@ -223,7 +223,7 @@ void SocketTest::testNonBlocking() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); ss.setBlocking(false); Timespan timeout(1000000); @@ -247,7 +247,7 @@ void SocketTest::testAddress() serv.bind(SocketAddress()); serv.listen(); StreamSocket ss; - ss.connect(SocketAddress("localhost", serv.address().port())); + ss.connect(SocketAddress("127.0.0.1", serv.address().port())); StreamSocket css = serv.acceptConnection(); assert (css.peerAddress().host() == ss.address().host()); assert (css.peerAddress().port() == ss.address().port()); @@ -309,7 +309,7 @@ void SocketTest::testTimeout() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); Timespan timeout0 = ss.getReceiveTimeout(); Timespan timeout(250000); @@ -347,7 +347,7 @@ void SocketTest::testTimeout() void SocketTest::testBufferSize() { EchoServer echoServer; - SocketAddress sa("localhost", 1234); + SocketAddress sa("127.0.0.1", 1234); StreamSocket ss(sa.family()); int osz = ss.getSendBufferSize(); @@ -371,7 +371,7 @@ void SocketTest::testOptions() { EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); ss.setLinger(true, 20); bool f; @@ -405,7 +405,7 @@ void SocketTest::testSelect() EchoServer echoServer; StreamSocket ss; - ss.connect(SocketAddress("localhost", echoServer.port())); + ss.connect(SocketAddress("127.0.0.1", echoServer.port())); Socket::SocketList readList; Socket::SocketList writeList; @@ -442,8 +442,8 @@ void SocketTest::testSelect2() EchoServer echoServer1; EchoServer echoServer2; - StreamSocket ss1(SocketAddress("localhost", echoServer1.port())); - StreamSocket ss2(SocketAddress("localhost", echoServer2.port())); + StreamSocket ss1(SocketAddress("127.0.0.1", echoServer1.port())); + StreamSocket ss2(SocketAddress("127.0.0.1", echoServer2.port())); Socket::SocketList readList; Socket::SocketList writeList; diff --git a/Net/testsuite/src/TCPServerTest.cpp b/Net/testsuite/src/TCPServerTest.cpp index 9f11d461e..86375779e 100644 --- a/Net/testsuite/src/TCPServerTest.cpp +++ b/Net/testsuite/src/TCPServerTest.cpp @@ -84,7 +84,7 @@ void TCPServerTest::testOneConnection() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", srv.socket().address().port()); + SocketAddress sa("127.0.0.1", srv.socket().address().port()); StreamSocket ss1(sa); std::string data("hello, world"); ss1.sendBytes(data.data(), (int) data.size()); @@ -111,7 +111,7 @@ void TCPServerTest::testTwoConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", srv.socket().address().port()); + SocketAddress sa("127.0.0.1", srv.socket().address().port()); StreamSocket ss1(sa); StreamSocket ss2(sa); std::string data("hello, world"); @@ -159,7 +159,7 @@ void TCPServerTest::testMultiConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); StreamSocket ss1(sa); StreamSocket ss2(sa); StreamSocket ss3(sa); diff --git a/Net/testsuite/src/WebSocketTest.cpp b/Net/testsuite/src/WebSocketTest.cpp index 72f6dcaf3..501cf9897 100644 --- a/Net/testsuite/src/WebSocketTest.cpp +++ b/Net/testsuite/src/WebSocketTest.cpp @@ -119,7 +119,7 @@ void WebSocketTest::testWebSocket() Poco::Thread::sleep(200); - HTTPClientSession cs("localhost", ss.address().port()); + HTTPClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1); HTTPResponse response; WebSocket ws(cs, request, response); @@ -200,7 +200,7 @@ void WebSocketTest::testWebSocketLarge() Poco::Thread::sleep(200); - HTTPClientSession cs("localhost", ss.address().port()); + HTTPClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1); HTTPResponse response; WebSocket ws(cs, request, response); @@ -232,7 +232,7 @@ void WebSocketTest::testOneLargeFrame(int msgSize) Poco::Thread::sleep(200); - HTTPClientSession cs("localhost", ss.address().port()); + HTTPClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1); HTTPResponse response; WebSocket ws(cs, request, response); From f38a1a38de4cf2b2477faf83de58b84849386da8 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 9 Nov 2016 13:04:40 +0100 Subject: [PATCH 077/305] more Net testsuite fixes --- Net/testsuite/src/HTTPStreamFactoryTest.cpp | 10 +++++----- Net/testsuite/src/SocketAddressTest.cpp | 2 +- Net/testsuite/src/SyslogTest.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Net/testsuite/src/HTTPStreamFactoryTest.cpp b/Net/testsuite/src/HTTPStreamFactoryTest.cpp index 9c513e87f..4ef7cec5c 100644 --- a/Net/testsuite/src/HTTPStreamFactoryTest.cpp +++ b/Net/testsuite/src/HTTPStreamFactoryTest.cpp @@ -44,7 +44,7 @@ void HTTPStreamFactoryTest::testNoRedirect() { HTTPTestServer server; HTTPStreamFactory factory; - URI uri("http://localhost/large"); + URI uri("http://127.0.0.1/large"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -57,7 +57,7 @@ void HTTPStreamFactoryTest::testEmptyPath() { HTTPTestServer server; HTTPStreamFactory factory; - URI uri("http://localhost"); + URI uri("http://127.0.0.1"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -71,7 +71,7 @@ void HTTPStreamFactoryTest::testRedirect() HTTPTestServer server; Poco::URIStreamOpener opener; opener.registerStreamFactory("http", new HTTPStreamFactory); - URI uri("http://localhost/redirect"); + URI uri("http://127.0.0.1/redirect"); uri.setPort(server.port()); std::auto_ptr pStr(opener.open(uri)); std::ostringstream ostr; @@ -83,7 +83,7 @@ void HTTPStreamFactoryTest::testRedirect() void HTTPStreamFactoryTest::testProxy() { HTTPTestServer server; - HTTPStreamFactory factory("localhost", server.port()); + HTTPStreamFactory factory("127.0.0.1", server.port()); URI uri("http://www.somehost.com/large"); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -96,7 +96,7 @@ void HTTPStreamFactoryTest::testError() { HTTPTestServer server; HTTPStreamFactory factory; - URI uri("http://localhost/notfound"); + URI uri("http://127.0.0.1/notfound"); uri.setPort(server.port()); try { diff --git a/Net/testsuite/src/SocketAddressTest.cpp b/Net/testsuite/src/SocketAddressTest.cpp index df51a909a..5d52d6aa9 100644 --- a/Net/testsuite/src/SocketAddressTest.cpp +++ b/Net/testsuite/src/SocketAddressTest.cpp @@ -130,7 +130,7 @@ void SocketAddressTest::testSocketAddress() try { SocketAddress sa12(SocketAddress::IPv6, "www6.pocoproject.org", 80); - assert (sa12.host().toString() == "[2001:4801:7819:74:be76:4eff:fe10:6b73]"); + assert (sa12.host().toString() == "2001:4801:7819:74:be76:4eff:fe10:6b73"); } catch (AddressFamilyMismatchException&) { diff --git a/Net/testsuite/src/SyslogTest.cpp b/Net/testsuite/src/SyslogTest.cpp index 51e7b05d7..7edf023d3 100644 --- a/Net/testsuite/src/SyslogTest.cpp +++ b/Net/testsuite/src/SyslogTest.cpp @@ -125,7 +125,7 @@ SyslogTest::~SyslogTest() void SyslogTest::testListener() { Poco::AutoPtr channel = new RemoteSyslogChannel(); - channel->setProperty("loghost", "localhost:51400"); + channel->setProperty("loghost", "127.0.0.1:51400"); channel->open(); Poco::AutoPtr listener = new RemoteSyslogListener(51400); listener->open(); @@ -150,7 +150,7 @@ void SyslogTest::testListener() void SyslogTest::testChannelOpenClose() { Poco::AutoPtr channel = new RemoteSyslogChannel(); - channel->setProperty("loghost", "localhost:51400"); + channel->setProperty("loghost", "127.0.0.1:51400"); channel->open(); Poco::AutoPtr listener = new RemoteSyslogListener(51400); listener->open(); @@ -189,7 +189,7 @@ void SyslogTest::testChannelOpenClose() void SyslogTest::testOldBSD() { Poco::AutoPtr channel = new RemoteSyslogChannel(); - channel->setProperty("loghost", "localhost:51400"); + channel->setProperty("loghost", "127.0.0.1:51400"); channel->setProperty("format", "bsd"); channel->open(); Poco::AutoPtr listener = new RemoteSyslogListener(51400); From 199a82cff99deae427432426f8f4ec61ccd5fb01 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 9 Nov 2016 15:09:46 +0100 Subject: [PATCH 078/305] NetSSL fixes for GH #1481, GH #1449 --- .../testsuite/src/HTTPSClientSessionTest.cpp | 26 +++++++++---------- .../testsuite/src/HTTPSServerTest.cpp | 16 ++++++------ .../testsuite/src/HTTPSStreamFactoryTest.cpp | 8 +++--- .../testsuite/src/TCPServerTest.cpp | 10 +++---- .../testsuite/src/WebSocketTest.cpp | 4 +-- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp b/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp index c1a420636..9f60bd3de 100644 --- a/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp @@ -93,7 +93,7 @@ HTTPSClientSessionTest::~HTTPSClientSessionTest() void HTTPSClientSessionTest::testGetSmall() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/small"); s.sendRequest(request); HTTPResponse response; @@ -109,7 +109,7 @@ void HTTPSClientSessionTest::testGetSmall() void HTTPSClientSessionTest::testGetLarge() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); s.sendRequest(request); HTTPResponse response; @@ -125,7 +125,7 @@ void HTTPSClientSessionTest::testGetLarge() void HTTPSClientSessionTest::testHead() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/large"); s.sendRequest(request); HTTPResponse response; @@ -140,7 +140,7 @@ void HTTPSClientSessionTest::testHead() void HTTPSClientSessionTest::testPostSmallIdentity() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body\r\n0\r\n"); request.setContentLength((int) body.length()); @@ -157,7 +157,7 @@ void HTTPSClientSessionTest::testPostSmallIdentity() void HTTPSClientSessionTest::testPostLargeIdentity() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(8000, 'x'); body.append("\r\n0\r\n"); @@ -175,7 +175,7 @@ void HTTPSClientSessionTest::testPostLargeIdentity() void HTTPSClientSessionTest::testPostSmallChunked() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body"); request.setChunkedTransferEncoding(true); @@ -193,7 +193,7 @@ void HTTPSClientSessionTest::testPostSmallChunked() void HTTPSClientSessionTest::testPostLargeChunked() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(16000, 'x'); request.setChunkedTransferEncoding(true); @@ -215,7 +215,7 @@ void HTTPSClientSessionTest::testPostLargeChunkedKeepAlive() srv.start(); try { - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); s.setKeepAlive(true); for (int i = 0; i < 10; ++i) { @@ -244,7 +244,7 @@ void HTTPSClientSessionTest::testPostLargeChunkedKeepAlive() void HTTPSClientSessionTest::testKeepAlive() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); s.setKeepAlive(true); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/keepAlive", HTTPMessage::HTTP_1_1); s.sendRequest(request); @@ -359,7 +359,7 @@ void HTTPSClientSessionTest::testCachedSession() "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pClientContext->enableSessionCache(true); - HTTPSClientSession s1("localhost", srv.port(), pClientContext); + HTTPSClientSession s1("127.0.0.1", srv.port(), pClientContext); HTTPRequest request1(HTTPRequest::HTTP_GET, "/small"); s1.sendRequest(request1); Session::Ptr pSession1 = s1.sslSession(); @@ -371,7 +371,7 @@ void HTTPSClientSessionTest::testCachedSession() StreamCopier::copyStream(rs1, ostr1); assert (ostr1.str() == HTTPSTestServer::SMALL_BODY); - HTTPSClientSession s2("localhost", srv.port(), pClientContext, pSession1); + HTTPSClientSession s2("127.0.0.1", srv.port(), pClientContext, pSession1); HTTPRequest request2(HTTPRequest::HTTP_GET, "/small"); s2.sendRequest(request2); Session::Ptr pSession2 = s2.sslSession(); @@ -419,7 +419,7 @@ void HTTPSClientSessionTest::testCachedSession() void HTTPSClientSessionTest::testUnknownContentLength() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/nolength"); s.sendRequest(request); HTTPResponse response; @@ -435,7 +435,7 @@ void HTTPSClientSessionTest::testUnknownContentLength() void HTTPSClientSessionTest::testServerAbort() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/nolength/connection/abort"); s.sendRequest(request); HTTPResponse response; diff --git a/NetSSL_OpenSSL/testsuite/src/HTTPSServerTest.cpp b/NetSSL_OpenSSL/testsuite/src/HTTPSServerTest.cpp index c48855ab2..3c2e4dba8 100644 --- a/NetSSL_OpenSSL/testsuite/src/HTTPSServerTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/HTTPSServerTest.cpp @@ -133,7 +133,7 @@ void HTTPSServerTest::testIdentityRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -156,7 +156,7 @@ void HTTPSServerTest::testChunkedRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentType("text/plain"); @@ -180,7 +180,7 @@ void HTTPSServerTest::testIdentityRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -214,7 +214,7 @@ void HTTPSServerTest::testChunkedRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -249,7 +249,7 @@ void HTTPSServerTest::test100Continue() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -273,7 +273,7 @@ void HTTPSServerTest::testRedirect() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/redirect"); cs.sendRequest(request); HTTPResponse response; @@ -293,7 +293,7 @@ void HTTPSServerTest::testAuth() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/auth"); cs.sendRequest(request); HTTPResponse response; @@ -313,7 +313,7 @@ void HTTPSServerTest::testNotImpl() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/notImpl"); cs.sendRequest(request); HTTPResponse response; diff --git a/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp b/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp index d83cefce8..6f6bd7edd 100644 --- a/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp @@ -48,7 +48,7 @@ void HTTPSStreamFactoryTest::testNoRedirect() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/large"); + URI uri("https://127.0.0.1/large"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -61,7 +61,7 @@ void HTTPSStreamFactoryTest::testEmptyPath() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost"); + URI uri("https://127.0.0.1"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -74,7 +74,7 @@ void HTTPSStreamFactoryTest::testRedirect() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/redirect"); + URI uri("https://127.0.0.1/redirect"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -103,7 +103,7 @@ void HTTPSStreamFactoryTest::testError() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/notfound"); + URI uri("https://127.0.0.1/notfound"); uri.setPort(server.port()); try { diff --git a/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp b/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp index d5b9edd52..6ff66f918 100644 --- a/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp @@ -95,7 +95,7 @@ void TCPServerTest::testOneConnection() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); std::string data("hello, world"); ss1.sendBytes(data.data(), (int) data.size()); @@ -123,7 +123,7 @@ void TCPServerTest::testTwoConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); SecureStreamSocket ss2(sa); std::string data("hello, world"); @@ -170,7 +170,7 @@ void TCPServerTest::testMultiConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); SecureStreamSocket ss2(sa); SecureStreamSocket ss3(sa); @@ -259,7 +259,7 @@ void TCPServerTest::testReuseSocket() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); std::string data("hello, world"); ss1.sendBytes(data.data(), (int) data.size()); @@ -328,7 +328,7 @@ void TCPServerTest::testReuseSession() "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pClientContext->enableSessionCache(true); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa, pClientContext); assert (!ss1.sessionWasReused()); std::string data("hello, world"); diff --git a/NetSSL_OpenSSL/testsuite/src/WebSocketTest.cpp b/NetSSL_OpenSSL/testsuite/src/WebSocketTest.cpp index cb84c562f..ef06a169e 100644 --- a/NetSSL_OpenSSL/testsuite/src/WebSocketTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/WebSocketTest.cpp @@ -119,7 +119,7 @@ void WebSocketTest::testWebSocket() Poco::Thread::sleep(200); - HTTPSClientSession cs("localhost", ss.address().port()); + HTTPSClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws"); HTTPResponse response; WebSocket ws(cs, request, response); @@ -186,7 +186,7 @@ void WebSocketTest::testWebSocketLarge() Poco::Thread::sleep(200); - HTTPSClientSession cs("localhost", ss.address().port()); + HTTPSClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws"); HTTPResponse response; WebSocket ws(cs, request, response); From 0cac5dbf73f171a435d26d7551ef0074de6782eb Mon Sep 17 00:00:00 2001 From: Jan Viktorin Date: Thu, 10 Nov 2016 17:34:05 +0100 Subject: [PATCH 079/305] ODBC: fix uninitialized variable This prevents valgrind reports like: ==18426== Conditional jump or move depends on uninitialised value(s) ==18426== at 0x6423EB5: Poco::Data::StatementImpl::execute(bool const&) (in /usr/lib/libPocoDatad.so.46) ==18426== by 0x641DB5F: Poco::Data::Statement::execute(bool) (in /usr/lib/libPocoDatad.so.46) ==18426== by 0x632A0C: Poco::Data::Keywords::now(Poco::Data::Statement&) (Statement.h:443) ==18426== by 0x641C8E5: Poco::Data::Statement::operator,(void (*)(Poco::Data::Statement&)) (in /usr/lib/libPocoDatad.so.46) ... ==18426== Uninitialised value was created by a stack allocation ==18426== at 0x6A1A170: Poco::Data::ODBC::ODBCStatementImpl::affectedRowCount() const (in /usr/lib/libPocoDataODBCd.so.46) Signed-off-by: Jan Viktorin --- Data/ODBC/src/ODBCStatementImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/ODBC/src/ODBCStatementImpl.cpp b/Data/ODBC/src/ODBCStatementImpl.cpp index 5a37892ab..b3dc4df3c 100644 --- a/Data/ODBC/src/ODBCStatementImpl.cpp +++ b/Data/ODBC/src/ODBCStatementImpl.cpp @@ -499,7 +499,7 @@ int ODBCStatementImpl::affectedRowCount() const { if (0 == _affectedRowCount) { - SQLLEN rows; + SQLLEN rows = 0; if (!Utility::isError(SQLRowCount(_stmt, &rows))) _affectedRowCount = static_cast(rows); } From 1164c4b03b7d48430e917dbf60182f1ebb9b2c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Fri, 11 Nov 2016 10:33:41 +0100 Subject: [PATCH 080/305] #1481: fix NetSSL_Win tests --- .../testsuite/src/HTTPSClientSessionTest.cpp | 22 +++++++++---------- NetSSL_Win/testsuite/src/HTTPSServerTest.cpp | 16 +++++++------- .../testsuite/src/HTTPSStreamFactoryTest.cpp | 8 +++---- NetSSL_Win/testsuite/src/TCPServerTest.cpp | 10 ++++----- NetSSL_Win/testsuite/src/WebSocketTest.cpp | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/NetSSL_Win/testsuite/src/HTTPSClientSessionTest.cpp b/NetSSL_Win/testsuite/src/HTTPSClientSessionTest.cpp index f01050459..c1df2ba0d 100644 --- a/NetSSL_Win/testsuite/src/HTTPSClientSessionTest.cpp +++ b/NetSSL_Win/testsuite/src/HTTPSClientSessionTest.cpp @@ -92,7 +92,7 @@ HTTPSClientSessionTest::~HTTPSClientSessionTest() void HTTPSClientSessionTest::testGetSmall() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/small"); s.sendRequest(request); HTTPResponse response; @@ -108,7 +108,7 @@ void HTTPSClientSessionTest::testGetSmall() void HTTPSClientSessionTest::testGetLarge() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); s.sendRequest(request); HTTPResponse response; @@ -124,7 +124,7 @@ void HTTPSClientSessionTest::testGetLarge() void HTTPSClientSessionTest::testHead() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/large"); s.sendRequest(request); HTTPResponse response; @@ -139,7 +139,7 @@ void HTTPSClientSessionTest::testHead() void HTTPSClientSessionTest::testPostSmallIdentity() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body\r\n0\r\n"); request.setContentLength((int) body.length()); @@ -156,7 +156,7 @@ void HTTPSClientSessionTest::testPostSmallIdentity() void HTTPSClientSessionTest::testPostLargeIdentity() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(8000, 'x'); body.append("\r\n0\r\n"); @@ -174,7 +174,7 @@ void HTTPSClientSessionTest::testPostLargeIdentity() void HTTPSClientSessionTest::testPostSmallChunked() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body("this is a random request body"); request.setChunkedTransferEncoding(true); @@ -192,7 +192,7 @@ void HTTPSClientSessionTest::testPostSmallChunked() void HTTPSClientSessionTest::testPostLargeChunked() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); std::string body(16000, 'x'); request.setChunkedTransferEncoding(true); @@ -214,7 +214,7 @@ void HTTPSClientSessionTest::testPostLargeChunkedKeepAlive() srv.start(); try { - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); s.setKeepAlive(true); for (int i = 0; i < 10; ++i) { @@ -243,7 +243,7 @@ void HTTPSClientSessionTest::testPostLargeChunkedKeepAlive() void HTTPSClientSessionTest::testKeepAlive() { HTTPSTestServer srv; - HTTPSClientSession s("localhost", srv.port()); + HTTPSClientSession s("127.0.0.1", srv.port()); s.setKeepAlive(true); HTTPRequest request(HTTPRequest::HTTP_HEAD, "/keepAlive", HTTPMessage::HTTP_1_1); s.sendRequest(request); @@ -359,7 +359,7 @@ void HTTPSClientSessionTest::testCachedSession() ""); //pClientContext->enableSessionCache(true); - HTTPSClientSession s1("localhost", srv.port(), pClientContext); + HTTPSClientSession s1("127.0.0.1", srv.port(), pClientContext); HTTPRequest request1(HTTPRequest::HTTP_GET, "/small"); s1.sendRequest(request1); Session::Ptr pSession1 = s1.sslSession(); @@ -371,7 +371,7 @@ void HTTPSClientSessionTest::testCachedSession() StreamCopier::copyStream(rs1, ostr1); assert (ostr1.str() == HTTPSTestServer::SMALL_BODY); - HTTPSClientSession s2("localhost", srv.port(), pClientContext, pSession1); + HTTPSClientSession s2("127.0.0.1", srv.port(), pClientContext, pSession1); HTTPRequest request2(HTTPRequest::HTTP_GET, "/small"); s2.sendRequest(request2); Session::Ptr pSession2 = s2.sslSession(); diff --git a/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp b/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp index 40af0fbc4..605771d97 100644 --- a/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp +++ b/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp @@ -134,7 +134,7 @@ void HTTPSServerTest::testIdentityRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -157,7 +157,7 @@ void HTTPSServerTest::testChunkedRequest() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentType("text/plain"); @@ -181,7 +181,7 @@ void HTTPSServerTest::testIdentityRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -216,7 +216,7 @@ void HTTPSServerTest::testChunkedRequestKeepAlive() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); cs.setKeepAlive(true); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1); @@ -251,7 +251,7 @@ void HTTPSServerTest::test100Continue() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); std::string body(5000, 'x'); HTTPRequest request("POST", "/echoBody"); request.setContentLength((int) body.length()); @@ -275,7 +275,7 @@ void HTTPSServerTest::testRedirect() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/redirect"); cs.sendRequest(request); HTTPResponse response; @@ -295,7 +295,7 @@ void HTTPSServerTest::testAuth() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/auth"); cs.sendRequest(request); HTTPResponse response; @@ -315,7 +315,7 @@ void HTTPSServerTest::testNotImpl() HTTPServer srv(new RequestHandlerFactory, svs, pParams); srv.start(); - HTTPSClientSession cs("localhost", svs.address().port()); + HTTPSClientSession cs("127.0.0.1", svs.address().port()); HTTPRequest request("GET", "/notImpl"); cs.sendRequest(request); HTTPResponse response; diff --git a/NetSSL_Win/testsuite/src/HTTPSStreamFactoryTest.cpp b/NetSSL_Win/testsuite/src/HTTPSStreamFactoryTest.cpp index 0d011e309..e292b1609 100644 --- a/NetSSL_Win/testsuite/src/HTTPSStreamFactoryTest.cpp +++ b/NetSSL_Win/testsuite/src/HTTPSStreamFactoryTest.cpp @@ -48,7 +48,7 @@ void HTTPSStreamFactoryTest::testNoRedirect() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/large"); + URI uri("https://127.0.0.1/large"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -61,7 +61,7 @@ void HTTPSStreamFactoryTest::testEmptyPath() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost"); + URI uri("https://127.0.0.1"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -74,7 +74,7 @@ void HTTPSStreamFactoryTest::testRedirect() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/redirect"); + URI uri("https://127.0.0.1/redirect"); uri.setPort(server.port()); std::auto_ptr pStr(factory.open(uri)); std::ostringstream ostr; @@ -107,7 +107,7 @@ void HTTPSStreamFactoryTest::testError() { HTTPSTestServer server; HTTPSStreamFactory factory; - URI uri("https://localhost/notfound"); + URI uri("https://127.0.0.1/notfound"); uri.setPort(server.port()); try { diff --git a/NetSSL_Win/testsuite/src/TCPServerTest.cpp b/NetSSL_Win/testsuite/src/TCPServerTest.cpp index cd3c59cb2..a2f4e35f4 100644 --- a/NetSSL_Win/testsuite/src/TCPServerTest.cpp +++ b/NetSSL_Win/testsuite/src/TCPServerTest.cpp @@ -95,7 +95,7 @@ void TCPServerTest::testOneConnection() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); std::string data("hello, world"); ss1.sendBytes(data.data(), (int) data.size()); @@ -123,7 +123,7 @@ void TCPServerTest::testTwoConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); SecureStreamSocket ss2(sa); std::string data("hello, world"); @@ -170,7 +170,7 @@ void TCPServerTest::testMultiConnections() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); SecureStreamSocket ss2(sa); SecureStreamSocket ss3(sa); @@ -259,7 +259,7 @@ void TCPServerTest::testReuseSocket() assert (srv.queuedConnections() == 0); assert (srv.totalConnections() == 0); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa); std::string data("hello, world"); ss1.sendBytes(data.data(), (int) data.size()); @@ -316,7 +316,7 @@ void TCPServerTest::testReuseSession() ""); //pClientContext->enableSessionCache(true); - SocketAddress sa("localhost", svs.address().port()); + SocketAddress sa("127.0.0.1", svs.address().port()); SecureStreamSocket ss1(sa, pClientContext); assert (!ss1.sessionWasReused()); std::string data("hello, world"); diff --git a/NetSSL_Win/testsuite/src/WebSocketTest.cpp b/NetSSL_Win/testsuite/src/WebSocketTest.cpp index fd0a874d5..dd82ce6bb 100644 --- a/NetSSL_Win/testsuite/src/WebSocketTest.cpp +++ b/NetSSL_Win/testsuite/src/WebSocketTest.cpp @@ -121,7 +121,7 @@ void WebSocketTest::testWebSocket() Poco::Thread::sleep(200); - HTTPSClientSession cs("localhost", ss.address().port()); + HTTPSClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws"); HTTPResponse response; WebSocket ws(cs, request, response); @@ -188,7 +188,7 @@ void WebSocketTest::testWebSocketLarge() Poco::Thread::sleep(200); - HTTPSClientSession cs("localhost", ss.address().port()); + HTTPSClientSession cs("127.0.0.1", ss.address().port()); HTTPRequest request(HTTPRequest::HTTP_GET, "/ws"); HTTPResponse response; WebSocket ws(cs, request, response); From fe59f959ef920fb09c29701b4fa65044a16dd14c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 11 Nov 2016 14:13:04 +0100 Subject: [PATCH 081/305] GH #1485: add TCPConnectionFilter --- Net/include/Poco/Net/TCPServer.h | 53 ++++++++++++++++++++++++++--- Net/src/TCPServer.cpp | 40 ++++++++++++++++++---- Net/testsuite/src/TCPServerTest.cpp | 38 ++++++++++++++++++++- Net/testsuite/src/TCPServerTest.h | 1 + 4 files changed, 121 insertions(+), 11 deletions(-) diff --git a/Net/include/Poco/Net/TCPServer.h b/Net/include/Poco/Net/TCPServer.h index 45ce8edd2..9c2ab525b 100644 --- a/Net/include/Poco/Net/TCPServer.h +++ b/Net/include/Poco/Net/TCPServer.h @@ -24,6 +24,8 @@ #include "Poco/Net/ServerSocket.h" #include "Poco/Net/TCPServerConnectionFactory.h" #include "Poco/Net/TCPServerParams.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" #include "Poco/Runnable.h" #include "Poco/Thread.h" #include "Poco/ThreadPool.h" @@ -36,6 +38,26 @@ namespace Net { class TCPServerDispatcher; +class Net_API TCPConnectionFilter: public Poco::RefCountedObject + /// A TCPConnectionFilter can be used to reject incoming connections + /// before a thread is started to handle them. + /// + /// An example use case is white-list or black-list IP address filtering. + /// + /// Subclasses must override the accept() method. +{ +public: + typedef Poco::AutoPtr Ptr; + + virtual bool accept(const Poco::Net::SocketAddress& clientAddress) = 0; + /// Returns true if a connection from the given clientAddress should + /// be accepted, otherwise false. + +protected: + virtual ~TCPConnectionFilter(); +}; + + class Net_API TCPServer: public Poco::Runnable /// This class implements a multithreaded TCP server. /// @@ -165,6 +187,19 @@ public: Poco::UInt16 port() const; /// Returns the port the server socket listens on. + + void setConnectionFilter(const TCPConnectionFilter::Ptr& pFilter); + /// Sets a TCPConnectionFilter. Can also be used to remove + /// a filter by passing a null pointer. + /// + /// To avoid a potential race condition, the filter must + /// be set before the TCPServer is started. Trying to set + /// the filter after start() has been called will trigger + /// an assertion. + + TCPConnectionFilter::Ptr getConnectionFilter() const; + /// Returns the TCPConnectionFilter set with setConnectionFilter(), + /// or null pointer if no filter has been set. protected: void run(); @@ -181,13 +216,17 @@ private: TCPServer(const TCPServer&); TCPServer& operator = (const TCPServer&); - ServerSocket _socket; - TCPServerDispatcher* _pDispatcher; - Poco::Thread _thread; - bool _stopped; + ServerSocket _socket; + TCPServerDispatcher* _pDispatcher; + TCPConnectionFilter::Ptr _pConnectionFilter; + Poco::Thread _thread; + bool _stopped; }; +// +// inlines +// inline const ServerSocket& TCPServer::socket() const { return _socket; @@ -200,6 +239,12 @@ inline Poco::UInt16 TCPServer::port() const } +inline TCPConnectionFilter::Ptr TCPServer::getConnectionFilter() const +{ + return _pConnectionFilter; +} + + } } // namespace Poco::Net diff --git a/Net/src/TCPServer.cpp b/Net/src/TCPServer.cpp index 7b06d694c..34236c71d 100644 --- a/Net/src/TCPServer.cpp +++ b/Net/src/TCPServer.cpp @@ -30,6 +30,21 @@ namespace Poco { namespace Net { +// +// TCPConnectionFilter +// + + +TCPConnectionFilter::~TCPConnectionFilter() +{ +} + + +// +// TCPServer +// + + TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber, TCPServerParams::Ptr pParams): _socket(ServerSocket(portNumber)), _thread(threadName(_socket)), @@ -122,14 +137,18 @@ void TCPServer::run() try { StreamSocket ss = _socket.acceptConnection(); - // enable nodelay per default: OSX really needs that -#if defined(POCO_OS_FAMILY_UNIX) - if (ss.address().family() != AddressFamily::UNIX_LOCAL) -#endif + + if (!_pConnectionFilter || _pConnectionFilter->accept(ss.peerAddress())) { - ss.setNoDelay(true); + // enable nodelay per default: OSX really needs that +#if defined(POCO_OS_FAMILY_UNIX) + if (ss.address().family() != AddressFamily::UNIX_LOCAL) +#endif + { + ss.setNoDelay(true); + } + _pDispatcher->enqueue(ss); } - _pDispatcher->enqueue(ss); } catch (Poco::Exception& exc) { @@ -161,6 +180,7 @@ int TCPServer::currentThreads() const return _pDispatcher->currentThreads(); } + int TCPServer::maxThreads() const { return _pDispatcher->maxThreads(); @@ -197,6 +217,14 @@ int TCPServer::refusedConnections() const } +void TCPServer::setConnectionFilter(const TCPConnectionFilter::Ptr& pConnectionFilter) +{ + poco_assert (_stopped); + + _pConnectionFilter = pConnectionFilter; +} + + std::string TCPServer::threadName(const ServerSocket& socket) { #if _WIN32_WCE == 0x0800 diff --git a/Net/testsuite/src/TCPServerTest.cpp b/Net/testsuite/src/TCPServerTest.cpp index 86375779e..11240244c 100644 --- a/Net/testsuite/src/TCPServerTest.cpp +++ b/Net/testsuite/src/TCPServerTest.cpp @@ -24,6 +24,7 @@ using Poco::Net::TCPServer; +using Poco::Net::TCPConnectionFilter; using Poco::Net::TCPServerConnection; using Poco::Net::TCPServerConnectionFactory; using Poco::Net::TCPServerConnectionFactoryImpl; @@ -62,6 +63,15 @@ namespace } } }; + + class RejectFilter: public TCPConnectionFilter + { + public: + bool accept(const SocketAddress&) + { + return false; + } + }; } @@ -233,7 +243,9 @@ void TCPServerTest::testMultiConnections() assert (srv.currentConnections() == 0); } -void TCPServerTest::testThreadCapacity(){ + +void TCPServerTest::testThreadCapacity() +{ ServerSocket svs(0); TCPServerParams* pParams = new TCPServerParams; pParams->setMaxThreads(64); @@ -243,6 +255,29 @@ void TCPServerTest::testThreadCapacity(){ } +void TCPServerTest::testFilter() +{ + TCPServer srv(new TCPServerConnectionFactoryImpl()); + srv.setConnectionFilter(new RejectFilter); + srv.start(); + assert (srv.currentConnections() == 0); + assert (srv.currentThreads() == 0); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 0); + + SocketAddress sa("127.0.0.1", srv.socket().address().port()); + StreamSocket ss(sa); + + char buffer[256]; + int n = ss.receiveBytes(buffer, sizeof(buffer)); + + assert (n == 0); + assert (srv.currentConnections() == 0); + assert (srv.currentThreads() == 0); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 0); +} + void TCPServerTest::setUp() { @@ -262,6 +297,7 @@ CppUnit::Test* TCPServerTest::suite() CppUnit_addTest(pSuite, TCPServerTest, testTwoConnections); CppUnit_addTest(pSuite, TCPServerTest, testMultiConnections); CppUnit_addTest(pSuite, TCPServerTest, testThreadCapacity); + CppUnit_addTest(pSuite, TCPServerTest, testFilter); return pSuite; } diff --git a/Net/testsuite/src/TCPServerTest.h b/Net/testsuite/src/TCPServerTest.h index 138a970ff..c39c87cf0 100644 --- a/Net/testsuite/src/TCPServerTest.h +++ b/Net/testsuite/src/TCPServerTest.h @@ -30,6 +30,7 @@ public: void testTwoConnections(); void testMultiConnections(); void testThreadCapacity(); + void testFilter(); void setUp(); void tearDown(); From 0b0c80840862ce2db1e3c16585663573bb3fa09c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 11 Nov 2016 14:30:37 +0100 Subject: [PATCH 082/305] rename TCPConnectionFilter to TCPServerConnectionFilter; pass a StreamSocket to accept() --- Net/include/Poco/Net/TCPServer.h | 45 +++++++++++++++++------------ Net/src/TCPServer.cpp | 8 ++--- Net/testsuite/src/TCPServerTest.cpp | 6 ++-- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Net/include/Poco/Net/TCPServer.h b/Net/include/Poco/Net/TCPServer.h index 9c2ab525b..4cf02d791 100644 --- a/Net/include/Poco/Net/TCPServer.h +++ b/Net/include/Poco/Net/TCPServer.h @@ -36,25 +36,34 @@ namespace Net { class TCPServerDispatcher; +class StreamSocket; -class Net_API TCPConnectionFilter: public Poco::RefCountedObject - /// A TCPConnectionFilter can be used to reject incoming connections - /// before a thread is started to handle them. +class Net_API TCPServerConnectionFilter: public Poco::RefCountedObject + /// A TCPServerConnectionFilter can be used to reject incoming connections + /// before passing them on to the TCPServerDispatcher and + /// starting a thread to handle them. /// /// An example use case is white-list or black-list IP address filtering. /// /// Subclasses must override the accept() method. { public: - typedef Poco::AutoPtr Ptr; + typedef Poco::AutoPtr Ptr; - virtual bool accept(const Poco::Net::SocketAddress& clientAddress) = 0; - /// Returns true if a connection from the given clientAddress should - /// be accepted, otherwise false. + virtual bool accept(const StreamSocket& socket) = 0; + /// Returns true if the given StreamSocket connection should + /// be handled, and passed on to the TCPServerDispatcher. + /// + /// Returns false if the socket should be closed immediately. + /// + /// The socket can be prevented from being closed immediately + /// if false is returned by creating a copy of the socket. + /// This can be used to handle certain socket connections in + /// a special way, outside the TCPServer framework. protected: - virtual ~TCPConnectionFilter(); + virtual ~TCPServerConnectionFilter(); }; @@ -188,8 +197,8 @@ public: Poco::UInt16 port() const; /// Returns the port the server socket listens on. - void setConnectionFilter(const TCPConnectionFilter::Ptr& pFilter); - /// Sets a TCPConnectionFilter. Can also be used to remove + void setConnectionFilter(const TCPServerConnectionFilter::Ptr& pFilter); + /// Sets a TCPServerConnectionFilter. Can also be used to remove /// a filter by passing a null pointer. /// /// To avoid a potential race condition, the filter must @@ -197,8 +206,8 @@ public: /// the filter after start() has been called will trigger /// an assertion. - TCPConnectionFilter::Ptr getConnectionFilter() const; - /// Returns the TCPConnectionFilter set with setConnectionFilter(), + TCPServerConnectionFilter::Ptr getConnectionFilter() const; + /// Returns the TCPServerConnectionFilter set with setConnectionFilter(), /// or null pointer if no filter has been set. protected: @@ -216,11 +225,11 @@ private: TCPServer(const TCPServer&); TCPServer& operator = (const TCPServer&); - ServerSocket _socket; - TCPServerDispatcher* _pDispatcher; - TCPConnectionFilter::Ptr _pConnectionFilter; - Poco::Thread _thread; - bool _stopped; + ServerSocket _socket; + TCPServerDispatcher* _pDispatcher; + TCPServerConnectionFilter::Ptr _pConnectionFilter; + Poco::Thread _thread; + bool _stopped; }; @@ -239,7 +248,7 @@ inline Poco::UInt16 TCPServer::port() const } -inline TCPConnectionFilter::Ptr TCPServer::getConnectionFilter() const +inline TCPServerConnectionFilter::Ptr TCPServer::getConnectionFilter() const { return _pConnectionFilter; } diff --git a/Net/src/TCPServer.cpp b/Net/src/TCPServer.cpp index 34236c71d..b05e08054 100644 --- a/Net/src/TCPServer.cpp +++ b/Net/src/TCPServer.cpp @@ -31,11 +31,11 @@ namespace Net { // -// TCPConnectionFilter +// TCPServerConnectionFilter // -TCPConnectionFilter::~TCPConnectionFilter() +TCPServerConnectionFilter::~TCPServerConnectionFilter() { } @@ -138,7 +138,7 @@ void TCPServer::run() { StreamSocket ss = _socket.acceptConnection(); - if (!_pConnectionFilter || _pConnectionFilter->accept(ss.peerAddress())) + if (!_pConnectionFilter || _pConnectionFilter->accept(ss)) { // enable nodelay per default: OSX really needs that #if defined(POCO_OS_FAMILY_UNIX) @@ -217,7 +217,7 @@ int TCPServer::refusedConnections() const } -void TCPServer::setConnectionFilter(const TCPConnectionFilter::Ptr& pConnectionFilter) +void TCPServer::setConnectionFilter(const TCPServerConnectionFilter::Ptr& pConnectionFilter) { poco_assert (_stopped); diff --git a/Net/testsuite/src/TCPServerTest.cpp b/Net/testsuite/src/TCPServerTest.cpp index 11240244c..bb3b863b1 100644 --- a/Net/testsuite/src/TCPServerTest.cpp +++ b/Net/testsuite/src/TCPServerTest.cpp @@ -24,7 +24,7 @@ using Poco::Net::TCPServer; -using Poco::Net::TCPConnectionFilter; +using Poco::Net::TCPServerConnectionFilter; using Poco::Net::TCPServerConnection; using Poco::Net::TCPServerConnectionFactory; using Poco::Net::TCPServerConnectionFactoryImpl; @@ -64,10 +64,10 @@ namespace } }; - class RejectFilter: public TCPConnectionFilter + class RejectFilter: public TCPServerConnectionFilter { public: - bool accept(const SocketAddress&) + bool accept(const StreamSocket&) { return false; } From be59c5b8fd78e8db5fd7d734dfb2259633a93ffc Mon Sep 17 00:00:00 2001 From: Jan Viktorin Date: Wed, 9 Nov 2016 11:55:42 +0100 Subject: [PATCH 083/305] Support ODBC GUID data type as string The ODBC defines SQL_GUID datatype in sqlext.h. It is used e.g. for transfer of UUID datatype from PostgreSQL. Signed-off-by: Jan Viktorin --- Data/ODBC/src/ODBCMetaColumn.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Data/ODBC/src/ODBCMetaColumn.cpp b/Data/ODBC/src/ODBCMetaColumn.cpp index 871a33655..2eb2b4470 100644 --- a/Data/ODBC/src/ODBCMetaColumn.cpp +++ b/Data/ODBC/src/ODBCMetaColumn.cpp @@ -88,6 +88,9 @@ void ODBCMetaColumn::init() case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: +#ifdef SQL_GUID + case SQL_GUID: +#endif setType(MetaColumn::FDT_STRING); break; case SQL_WCHAR: From c12047b060455619a718cb473dc97b458ee93dc2 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 12 Nov 2016 21:29:55 +0100 Subject: [PATCH 084/305] change localhost to 127.0.0.1 to ensure IPv4 when connecting to Redis and MongoDB for testing --- MongoDB/testsuite/src/MongoDBTest.cpp | 6 +++--- Redis/testsuite/src/RedisTest.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MongoDB/testsuite/src/MongoDBTest.cpp b/MongoDB/testsuite/src/MongoDBTest.cpp index c3a095fab..7b1ae7d6b 100644 --- a/MongoDB/testsuite/src/MongoDBTest.cpp +++ b/MongoDB/testsuite/src/MongoDBTest.cpp @@ -287,7 +287,7 @@ void MongoDBTest::testBuildInfo() void MongoDBTest::testConnectionPool() { - Poco::Net::SocketAddress sa("localhost", 27017); + Poco::Net::SocketAddress sa("127.0.0.1", 27017); Poco::PoolableObjectFactory factory(sa); Poco::ObjectPool pool(factory, 10, 15); @@ -394,8 +394,8 @@ CppUnit::Test* MongoDBTest::suite() { try { - _mongo = new Poco::MongoDB::Connection("localhost", 27017); - std::cout << "Connected to [localhost:27017]" << std::endl; + _mongo = new Poco::MongoDB::Connection("127.0.0.1", 27017); + std::cout << "Connected to [127.0.0.1:27017]" << std::endl; } catch (Poco::Net::ConnectionRefusedException& e) { diff --git a/Redis/testsuite/src/RedisTest.cpp b/Redis/testsuite/src/RedisTest.cpp index dc428ad7c..4a4f58d11 100644 --- a/Redis/testsuite/src/RedisTest.cpp +++ b/Redis/testsuite/src/RedisTest.cpp @@ -31,7 +31,7 @@ Poco::Redis::Client RedisTest::_redis; RedisTest::RedisTest(const std::string& name): CppUnit::TestCase("Redis"), - _host("localhost"), + _host("127.0.0.1"), _port(6379) { if (!_connected) From 8265d1b28eacf435ea907336ceff300d524e7178 Mon Sep 17 00:00:00 2001 From: Tomaz Beltram Date: Wed, 16 Nov 2016 14:17:17 +0100 Subject: [PATCH 085/305] GH #1488: fixed ObjectPool size handling --- Foundation/include/Poco/ObjectPool.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Foundation/include/Poco/ObjectPool.h b/Foundation/include/Poco/ObjectPool.h index 7c9729a8c..9b732cf4b 100644 --- a/Foundation/include/Poco/ObjectPool.h +++ b/Foundation/include/Poco/ObjectPool.h @@ -260,18 +260,12 @@ public: if (_pool.size() < _capacity) { _pool.push_back(pObject); - } - else - { - _factory.destroyObject(pObject); - _size--; - _availableCondition.signal(); + return; } } - else - { - _factory.destroyObject(pObject); - } + _factory.destroyObject(pObject); + _size--; + _availableCondition.signal(); } std::size_t capacity() const From 3621d49b23f3bebc024498cf3e7c9817ec834571 Mon Sep 17 00:00:00 2001 From: Ubiquite Date: Fri, 18 Nov 2016 17:17:19 +0100 Subject: [PATCH 086/305] enable CppUnit with ENABLE_CPPUNIT I wasted some time because ENABLE_CPPUNIT seems not to enable anything, --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a9d1bda6..1ae6eaeaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,7 +143,7 @@ set(Poco_COMPONENTS "") # Pthreads/threads support find_package(Threads REQUIRED) -if (ENABLE_TESTS) +if (ENABLE_TESTS OR ENABLE_CPPUNIT) add_subdirectory(CppUnit) list(APPEND Poco_COMPONENTS "CppUnit") endif () From 9141f38035f1fcf0baa7714131028a9fe460fbce Mon Sep 17 00:00:00 2001 From: vm2mv Date: Mon, 21 Nov 2016 11:49:49 +0300 Subject: [PATCH 087/305] * Net: fixed adding content part to mail message with empty content-disposition --- Net/src/MailMessage.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Net/src/MailMessage.cpp b/Net/src/MailMessage.cpp index 3fa4641ba..db7c54f69 100644 --- a/Net/src/MailMessage.cpp +++ b/Net/src/MailMessage.cpp @@ -119,6 +119,10 @@ namespace pPS->headers().set(it->first, it->second); } + + if (contentDisp.empty()) + _pMsg->addContent(pPS, cte); + if (!added) delete pPS; } } From 780430487bc1a0f670742a3dada9ac7668fa7abb Mon Sep 17 00:00:00 2001 From: vm2mv Date: Mon, 21 Nov 2016 16:43:27 +0300 Subject: [PATCH 088/305] Foundation: fixed exceptions handling in zlib-output-streams constructors --- Foundation/include/Poco/DeflatingStream.h | 2 +- Foundation/include/Poco/InflatingStream.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Foundation/include/Poco/DeflatingStream.h b/Foundation/include/Poco/DeflatingStream.h index 2def954d3..b656163c0 100644 --- a/Foundation/include/Poco/DeflatingStream.h +++ b/Foundation/include/Poco/DeflatingStream.h @@ -139,7 +139,7 @@ protected: }; -class Foundation_API DeflatingOutputStream: public DeflatingIOS, public std::ostream +class Foundation_API DeflatingOutputStream: public std::ostream, public DeflatingIOS /// This stream compresses all data passing through it /// using zlib's deflate algorithm. /// After all data has been written to the stream, close() diff --git a/Foundation/include/Poco/InflatingStream.h b/Foundation/include/Poco/InflatingStream.h index ca20cb07e..66a42b1bc 100644 --- a/Foundation/include/Poco/InflatingStream.h +++ b/Foundation/include/Poco/InflatingStream.h @@ -143,7 +143,7 @@ protected: }; -class Foundation_API InflatingOutputStream: public InflatingIOS, public std::ostream +class Foundation_API InflatingOutputStream: public std::ostream, public InflatingIOS /// This stream decompresses all data passing through it /// using zlib's inflate algorithm. /// From bfaa161c61cca06526eaf238bfdddd190381616b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Sun, 27 Nov 2016 23:58:39 +0100 Subject: [PATCH 089/305] Crypto and NetSSL fixes for OpenSSL 1.1 --- Crypto/include/Poco/Crypto/DigestEngine.h | 2 +- Crypto/src/CipherImpl.cpp | 54 +++++++++++++++++++---- Crypto/src/DigestEngine.cpp | 27 +++++++----- Crypto/src/RSAKeyImpl.cpp | 24 ++++++++++ Crypto/src/X509Certificate.cpp | 4 ++ NetSSL_OpenSSL/src/Context.cpp | 12 +++++ 6 files changed, 103 insertions(+), 20 deletions(-) diff --git a/Crypto/include/Poco/Crypto/DigestEngine.h b/Crypto/include/Poco/Crypto/DigestEngine.h index 5de75392a..e2121c414 100644 --- a/Crypto/include/Poco/Crypto/DigestEngine.h +++ b/Crypto/include/Poco/Crypto/DigestEngine.h @@ -61,7 +61,7 @@ protected: private: std::string _name; - EVP_MD_CTX* _ctx; + EVP_MD_CTX* _pContext; Poco::DigestEngine::Digest _digest; OpenSSLInitializer _openSSLInitializer; }; diff --git a/Crypto/src/CipherImpl.cpp b/Crypto/src/CipherImpl.cpp index b115ede8f..b8708a78c 100644 --- a/Crypto/src/CipherImpl.cpp +++ b/Crypto/src/CipherImpl.cpp @@ -77,7 +77,11 @@ namespace private: const EVP_CIPHER* _pCipher; - EVP_CIPHER_CTX _ctx; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + EVP_CIPHER_CTX* _pContext; +#else + EVP_CIPHER_CTX _context; +#endif ByteVec _key; ByteVec _iv; }; @@ -92,30 +96,52 @@ namespace _key(key), _iv(iv) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + _pContext = EVP_CIPHER_CTX_new(); EVP_CipherInit( - &_ctx, + _pContext, _pCipher, &_key[0], _iv.empty() ? 0 : &_iv[0], (dir == DIR_ENCRYPT) ? 1 : 0); +#else + EVP_CipherInit( + &_context, + _pCipher, + &_key[0], + _iv.empty() ? 0 : &_iv[0], + (dir == DIR_ENCRYPT) ? 1 : 0); +#endif } CryptoTransformImpl::~CryptoTransformImpl() { - EVP_CIPHER_CTX_cleanup(&_ctx); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + EVP_CIPHER_CTX_cleanup(_pContext); +#else + EVP_CIPHER_CTX_cleanup(&_context); +#endif } std::size_t CryptoTransformImpl::blockSize() const { - return EVP_CIPHER_CTX_block_size(&_ctx); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return EVP_CIPHER_CTX_block_size(_pContext); +#else + return EVP_CIPHER_CTX_block_size(&_context); +#endif } int CryptoTransformImpl::setPadding(int padding) { - return EVP_CIPHER_CTX_set_padding(&_ctx, padding); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return EVP_CIPHER_CTX_block_size(_pContext); +#else + return EVP_CIPHER_CTX_set_padding(&_context, padding); +#endif } @@ -128,13 +154,21 @@ namespace poco_assert (outputLength >= (inputLength + blockSize() - 1)); int outLen = static_cast(outputLength); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L int rc = EVP_CipherUpdate( - &_ctx, + _pContext, output, &outLen, input, static_cast(inputLength)); - +#else + int rc = EVP_CipherUpdate( + &_context, + output, + &outLen, + input, + static_cast(inputLength)); +#endif if (rc == 0) throwError(); @@ -153,7 +187,11 @@ namespace // Use the '_ex' version that does not perform implicit cleanup since we // will call EVP_CIPHER_CTX_cleanup() from the dtor as there is no // guarantee that finalize() will be called if an error occurred. - int rc = EVP_CipherFinal_ex(&_ctx, output, &len); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + int rc = EVP_CipherFinal_ex(_pContext, output, &len); +#else + int rc = EVP_CipherFinal_ex(&_context, output, &len); +#endif if (rc == 0) throwError(); diff --git a/Crypto/src/DigestEngine.cpp b/Crypto/src/DigestEngine.cpp index 6e574ab42..64042589f 100644 --- a/Crypto/src/DigestEngine.cpp +++ b/Crypto/src/DigestEngine.cpp @@ -23,46 +23,51 @@ namespace Crypto { DigestEngine::DigestEngine(const std::string& name): - _name(name) + _name(name), + _pContext(EVP_MD_CTX_create()) { const EVP_MD* md = EVP_get_digestbyname(_name.c_str()); if (!md) throw Poco::NotFoundException(_name); - _ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(_ctx, md, NULL); + EVP_DigestInit_ex(_pContext, md, NULL); } DigestEngine::~DigestEngine() { - EVP_MD_CTX_destroy(_ctx); + EVP_MD_CTX_destroy(_pContext); } int DigestEngine::nid() const { - return EVP_MD_nid(_ctx->digest); + return EVP_MD_nid(EVP_MD_CTX_md(_pContext)); } std::size_t DigestEngine::digestLength() const { - return EVP_MD_CTX_size(_ctx); + return EVP_MD_CTX_size(_pContext); } void DigestEngine::reset() { - EVP_MD_CTX_cleanup(_ctx); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + EVP_MD_CTX_free(_pContext); + _pContext = EVP_MD_CTX_create(); +#else + EVP_MD_CTX_cleanup(_pContext); +#endif const EVP_MD* md = EVP_get_digestbyname(_name.c_str()); if (!md) throw Poco::NotFoundException(_name); - EVP_DigestInit_ex(_ctx, md, NULL); + EVP_DigestInit_ex(_pContext, md, NULL); } const Poco::DigestEngine::Digest& DigestEngine::digest() { _digest.clear(); - unsigned len = EVP_MD_CTX_size(_ctx); + unsigned len = EVP_MD_CTX_size(_pContext); _digest.resize(len); - EVP_DigestFinal_ex(_ctx, &_digest[0], &len); + EVP_DigestFinal_ex(_pContext, &_digest[0], &len); reset(); return _digest; } @@ -70,7 +75,7 @@ const Poco::DigestEngine::Digest& DigestEngine::digest() void DigestEngine::updateImpl(const void* data, std::size_t length) { - EVP_DigestUpdate(_ctx, data, length); + EVP_DigestUpdate(_pContext, data, length); } diff --git a/Crypto/src/RSAKeyImpl.cpp b/Crypto/src/RSAKeyImpl.cpp index 8333453ce..3a1580f69 100644 --- a/Crypto/src/RSAKeyImpl.cpp +++ b/Crypto/src/RSAKeyImpl.cpp @@ -207,19 +207,43 @@ int RSAKeyImpl::size() const RSAKeyImpl::ByteVec RSAKeyImpl::modulus() const { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const BIGNUM* n = 0; + const BIGNUM* e = 0; + const BIGNUM* d = 0; + RSA_get0_key(_pRSA, &n, &e, &d); + return convertToByteVec(n); +#else return convertToByteVec(_pRSA->n); +#endif } RSAKeyImpl::ByteVec RSAKeyImpl::encryptionExponent() const { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const BIGNUM* n = 0; + const BIGNUM* e = 0; + const BIGNUM* d = 0; + RSA_get0_key(_pRSA, &n, &e, &d); + return convertToByteVec(e); +#else return convertToByteVec(_pRSA->e); +#endif } RSAKeyImpl::ByteVec RSAKeyImpl::decryptionExponent() const { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const BIGNUM* n = 0; + const BIGNUM* e = 0; + const BIGNUM* d = 0; + RSA_get0_key(_pRSA, &n, &e, &d); + return convertToByteVec(d); +#else return convertToByteVec(_pRSA->d); +#endif } diff --git a/Crypto/src/X509Certificate.cpp b/Crypto/src/X509Certificate.cpp index 0137c6bfc..211e84b13 100644 --- a/Crypto/src/X509Certificate.cpp +++ b/Crypto/src/X509Certificate.cpp @@ -63,7 +63,11 @@ X509Certificate::X509Certificate(X509* pCert, bool shared): if (shared) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + X509_up_ref(_pCert); +#else _pCert->references++; +#endif } init(); diff --git a/NetSSL_OpenSSL/src/Context.cpp b/NetSSL_OpenSSL/src/Context.cpp index aa5e314ab..c386c4047 100644 --- a/NetSSL_OpenSSL/src/Context.cpp +++ b/NetSSL_OpenSSL/src/Context.cpp @@ -494,6 +494,17 @@ void Context::initDH(const std::string& dhParamsFile) std::string msg = Utility::getLastError(); throw SSLContextException("Error creating Diffie-Hellman parameters", msg); } +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); + BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); + DH_set0_pqg(dh, p, 0, g); + DH_set_length(dh, 160); + if (!p || !g) + { + DH_free(dh); + throw SSLContextException("Error creating Diffie-Hellman parameters"); + } +#else dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); dh->length = 160; @@ -502,6 +513,7 @@ void Context::initDH(const std::string& dhParamsFile) DH_free(dh); throw SSLContextException("Error creating Diffie-Hellman parameters"); } +#endif } SSL_CTX_set_tmp_dh(_pSSLContext, dh); SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE); From 9c436860b3ad2a9366fdf96c8401283a48ea4964 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Dec 2016 00:03:39 +0100 Subject: [PATCH 090/305] ObjectPool: gracefully handle case if push_back() throws --- Foundation/include/Poco/ObjectPool.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Foundation/include/Poco/ObjectPool.h b/Foundation/include/Poco/ObjectPool.h index 9b732cf4b..8d234d969 100644 --- a/Foundation/include/Poco/ObjectPool.h +++ b/Foundation/include/Poco/ObjectPool.h @@ -259,8 +259,14 @@ public: _factory.deactivateObject(pObject); if (_pool.size() < _capacity) { - _pool.push_back(pObject); - return; + try + { + _pool.push_back(pObject); + return; + } + catch (...) + { + } } } _factory.destroyObject(pObject); From 710845f0230934b483d59708cfd527085ea608f7 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Dec 2016 18:21:37 +0100 Subject: [PATCH 091/305] fixed GH #1453: _clock_gettime Symbol not found on Mac 10.11 [do not use clock_gettime() on Apple platforms, even if _POSIX_TIMERS indicates it's available] --- Foundation/src/Timestamp.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Foundation/src/Timestamp.cpp b/Foundation/src/Timestamp.cpp index 3511d7d95..62c4c8187 100644 --- a/Foundation/src/Timestamp.cpp +++ b/Foundation/src/Timestamp.cpp @@ -39,6 +39,15 @@ #endif +#ifndef POCO_HAVE_CLOCK_GETTIME +#if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) +#ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 +#define POCO_HAVE_CLOCK_GETTIME +#endif +#endif +#endif + + #if defined(_WIN32_WCE) && defined(POCO_WINCE_TIMESTAMP_HACK) @@ -227,7 +236,7 @@ void Timestamp::update() ts.QuadPart -= epoch.QuadPart; _ts = ts.QuadPart/10; -#elif (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) +#elif defined(POCO_HAVE_CLOCK_GETTIME) struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts)) From feedbbbea5aafdec05b614a45c0e5e9cdb3a3e6d Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Dec 2016 21:47:39 +0100 Subject: [PATCH 092/305] more fixes related to GH #1453 Conflicts: Foundation/include/Poco/AtomicCounter.h --- Foundation/include/Poco/AtomicCounter.h | 10 ++++++++++ Foundation/src/Clock.cpp | 11 ++++++++++- Foundation/src/Event_POSIX.cpp | 15 ++++++++++++--- Foundation/src/Mutex_POSIX.cpp | 15 ++++++++++++--- Foundation/src/Semaphore_POSIX.cpp | 15 ++++++++++++--- Foundation/src/Timestamp.cpp | 10 +++++----- 6 files changed, 61 insertions(+), 15 deletions(-) diff --git a/Foundation/include/Poco/AtomicCounter.h b/Foundation/include/Poco/AtomicCounter.h index 0554558bb..fd3eb34d9 100644 --- a/Foundation/include/Poco/AtomicCounter.h +++ b/Foundation/include/Poco/AtomicCounter.h @@ -24,7 +24,17 @@ #if POCO_OS == POCO_OS_WINDOWS_NT #include "Poco/UnWindows.h" #elif POCO_OS == POCO_OS_MAC_OS_X +<<<<<<< HEAD #include +======= + #if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0 || __WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0 + #ifndef POCO_HAVE_STD_ATOMICS + #define POCO_HAVE_STD_ATOMICS + #endif + #else + #include + #endif +>>>>>>> c8aa273... more fixes related to GH #1453 #elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2) || __GNUC__ > 4) && (defined(__x86_64__) || defined(__i386__)) #if !defined(POCO_HAVE_GCC_ATOMICS) && !defined(POCO_NO_GCC_ATOMICS) #define POCO_HAVE_GCC_ATOMICS diff --git a/Foundation/src/Clock.cpp b/Foundation/src/Clock.cpp index ac95bfc80..abef10a9a 100644 --- a/Foundation/src/Clock.cpp +++ b/Foundation/src/Clock.cpp @@ -34,6 +34,15 @@ #include +#ifndef POCO_HAVE_CLOCK_GETTIME + #if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) + #ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 + #define POCO_HAVE_CLOCK_GETTIME + #endif + #endif +#endif + + namespace Poco { @@ -120,7 +129,7 @@ void Clock::update() #endif _clock = ClockVal(ts.tv_sec)*resolution() + ts.tv_nsec/1000; -#elif (defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)) || defined(__QNX__) +#elif defined(POCO_HAVE_CLOCK_GETTIME) struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) diff --git a/Foundation/src/Event_POSIX.cpp b/Foundation/src/Event_POSIX.cpp index d2fc8c0f5..450f114bf 100644 --- a/Foundation/src/Event_POSIX.cpp +++ b/Foundation/src/Event_POSIX.cpp @@ -31,9 +31,18 @@ // availability of non-standard pthread_cond_timedwait_monotonic(). // #ifndef POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT -#if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) -#define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 + #if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) + #define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 + #endif #endif + + +#ifndef POCO_HAVE_CLOCK_GETTIME + #if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) + #ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 + #define POCO_HAVE_CLOCK_GETTIME + #endif + #endif #endif @@ -127,7 +136,7 @@ bool EventImpl::waitImpl(long milliseconds) abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } -#elif (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) +#elif defined(POCO_HAVE_CLOCK_GETTIME) clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; diff --git a/Foundation/src/Mutex_POSIX.cpp b/Foundation/src/Mutex_POSIX.cpp index 26c220383..213375cc1 100644 --- a/Foundation/src/Mutex_POSIX.cpp +++ b/Foundation/src/Mutex_POSIX.cpp @@ -29,9 +29,18 @@ #if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L -#if defined(_POSIX_THREADS) && (_POSIX_THREADS - 200112L) >= 0L -#define POCO_HAVE_MUTEX_TIMEOUT + #if defined(_POSIX_THREADS) && (_POSIX_THREADS - 200112L) >= 0L + #define POCO_HAVE_MUTEX_TIMEOUT + #endif #endif + + +#ifndef POCO_HAVE_CLOCK_GETTIME + #if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) + #ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 + #define POCO_HAVE_CLOCK_GETTIME + #endif + #endif #endif @@ -73,7 +82,7 @@ bool MutexImpl::tryLockImpl(long milliseconds) { #if defined(POCO_HAVE_MUTEX_TIMEOUT) struct timespec abstime; -#if defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME) +#if defined(POCO_HAVE_CLOCK_GETTIME) clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; diff --git a/Foundation/src/Semaphore_POSIX.cpp b/Foundation/src/Semaphore_POSIX.cpp index 57c5dae15..e602410db 100644 --- a/Foundation/src/Semaphore_POSIX.cpp +++ b/Foundation/src/Semaphore_POSIX.cpp @@ -31,9 +31,18 @@ // availability of non-standard pthread_cond_timedwait_monotonic(). // #ifndef POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT -#if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) -#define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 + #if (defined(__linux__) || defined(__QNX__)) && !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) + #define POCO_HAVE_MONOTONIC_PTHREAD_COND_TIMEDWAIT 1 + #endif #endif + + +#ifndef POCO_HAVE_CLOCK_GETTIME + #if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) + #ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 + #define POCO_HAVE_CLOCK_GETTIME + #endif + #endif #endif @@ -127,7 +136,7 @@ bool SemaphoreImpl::waitImpl(long milliseconds) abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } -#elif (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) +#elif defined(POCO_HAVE_CLOCK_GETTIME) clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; diff --git a/Foundation/src/Timestamp.cpp b/Foundation/src/Timestamp.cpp index 62c4c8187..64cce810a 100644 --- a/Foundation/src/Timestamp.cpp +++ b/Foundation/src/Timestamp.cpp @@ -40,11 +40,11 @@ #ifndef POCO_HAVE_CLOCK_GETTIME -#if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) -#ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 -#define POCO_HAVE_CLOCK_GETTIME -#endif -#endif + #if (defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)) || defined(POCO_VXWORKS) || defined(__QNX__) + #ifndef __APPLE__ // See GitHub issue #1453 - not available before Mac OS 10.12/iOS 10 + #define POCO_HAVE_CLOCK_GETTIME + #endif + #endif #endif From 955f4091774edd8dda644fd15b7d2b70f3c9dc7f Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 5 Dec 2016 22:19:45 +0100 Subject: [PATCH 093/305] On Apple platforms, use std::atomic with MacOS 10.12 or iOS 10 SDK. Conflicts: Foundation/include/Poco/AtomicCounter.h --- Foundation/include/Poco/AtomicCounter.h | 59 ++++++++++++++++++++++--- Foundation/src/AtomicCounter.cpp | 43 +++++++++++++++++- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/Foundation/include/Poco/AtomicCounter.h b/Foundation/include/Poco/AtomicCounter.h index fd3eb34d9..f8cdb731a 100644 --- a/Foundation/include/Poco/AtomicCounter.h +++ b/Foundation/include/Poco/AtomicCounter.h @@ -24,9 +24,6 @@ #if POCO_OS == POCO_OS_WINDOWS_NT #include "Poco/UnWindows.h" #elif POCO_OS == POCO_OS_MAC_OS_X -<<<<<<< HEAD - #include -======= #if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0 || __WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0 #ifndef POCO_HAVE_STD_ATOMICS #define POCO_HAVE_STD_ATOMICS @@ -34,7 +31,6 @@ #else #include #endif ->>>>>>> c8aa273... more fixes related to GH #1453 #elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2) || __GNUC__ > 4) && (defined(__x86_64__) || defined(__i386__)) #if !defined(POCO_HAVE_GCC_ATOMICS) && !defined(POCO_NO_GCC_ATOMICS) #define POCO_HAVE_GCC_ATOMICS @@ -45,6 +41,9 @@ #endif #endif // POCO_OS #include "Poco/Mutex.h" +#ifdef POCO_HAVE_STD_ATOMICS +#include +#endif namespace Poco { @@ -114,7 +113,9 @@ public: /// Returns true if the counter is zero, false otherwise. private: -#if POCO_OS == POCO_OS_WINDOWS_NT +#if defined(POCO_HAVE_STD_ATOMICS) + typedef std::atomic ImplType; +#elif POCO_OS == POCO_OS_WINDOWS_NT typedef volatile LONG ImplType; #elif POCO_OS == POCO_OS_MAC_OS_X typedef int32_t ImplType; @@ -137,7 +138,53 @@ private: // -#if POCO_OS == POCO_OS_WINDOWS_NT +#if defined(POCO_HAVE_STD_ATOMICS) +// +// C++11 atomics +// +inline AtomicCounter::operator AtomicCounter::ValueType () const +{ + return _counter.load(); +} + + +inline AtomicCounter::ValueType AtomicCounter::value() const +{ + return _counter.load(); +} + + +inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix +{ + return ++_counter; +} + + +inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix +{ + return _counter++; +} + + +inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix +{ + return --_counter; +} + + +inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix +{ + return _counter--; +} + + +inline bool AtomicCounter::operator ! () const +{ + return _counter.load() == 0; +} + + +#elif POCO_OS == POCO_OS_WINDOWS_NT // // Windows // diff --git a/Foundation/src/AtomicCounter.cpp b/Foundation/src/AtomicCounter.cpp index dc45065bd..c0d6e2b7f 100644 --- a/Foundation/src/AtomicCounter.cpp +++ b/Foundation/src/AtomicCounter.cpp @@ -20,7 +20,48 @@ namespace Poco { -#if POCO_OS == POCO_OS_WINDOWS_NT +#if defined(POCO_HAVE_STD_ATOMICS) +// +// C++11 atomics +// +AtomicCounter::AtomicCounter(): + _counter(0) +{ +} + + +AtomicCounter::AtomicCounter(AtomicCounter::ValueType initialValue): + _counter(initialValue) +{ +} + + +AtomicCounter::AtomicCounter(const AtomicCounter& counter): + _counter(counter.value()) +{ +} + + +AtomicCounter::~AtomicCounter() +{ +} + + +AtomicCounter& AtomicCounter::operator = (const AtomicCounter& counter) +{ + _counter.store(counter._counter.load()); + return *this; +} + + +AtomicCounter& AtomicCounter::operator = (AtomicCounter::ValueType value) +{ + _counter.store(value); + return *this; +} + + +#elif POCO_OS == POCO_OS_WINDOWS_NT // // Windows // From 13b062c7869e4cb2d1044dc117f6fd8a64d92a19 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 6 Dec 2016 22:11:54 +0100 Subject: [PATCH 094/305] fixed warnings and inconsistencies --- Foundation/include/Poco/DeflatingStream.h | 2 +- Foundation/include/Poco/InflatingStream.h | 2 +- Foundation/src/DeflatingStream.cpp | 16 ++++++++-------- Foundation/src/InflatingStream.cpp | 16 ++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Foundation/include/Poco/DeflatingStream.h b/Foundation/include/Poco/DeflatingStream.h index b656163c0..4502652fd 100644 --- a/Foundation/include/Poco/DeflatingStream.h +++ b/Foundation/include/Poco/DeflatingStream.h @@ -176,7 +176,7 @@ protected: }; -class Foundation_API DeflatingInputStream: public DeflatingIOS, public std::istream +class Foundation_API DeflatingInputStream: public std::istream, public DeflatingIOS /// This stream compresses all data passing through it /// using zlib's deflate algorithm. { diff --git a/Foundation/include/Poco/InflatingStream.h b/Foundation/include/Poco/InflatingStream.h index 66a42b1bc..7f34650cc 100644 --- a/Foundation/include/Poco/InflatingStream.h +++ b/Foundation/include/Poco/InflatingStream.h @@ -173,7 +173,7 @@ public: }; -class Foundation_API InflatingInputStream: public InflatingIOS, public std::istream +class Foundation_API InflatingInputStream: public std::istream, public InflatingIOS /// This stream decompresses all data passing through it /// using zlib's inflate algorithm. /// Example: diff --git a/Foundation/src/DeflatingStream.cpp b/Foundation/src/DeflatingStream.cpp index 56d7b9146..e68b7ea1e 100644 --- a/Foundation/src/DeflatingStream.cpp +++ b/Foundation/src/DeflatingStream.cpp @@ -334,15 +334,15 @@ DeflatingStreamBuf* DeflatingIOS::rdbuf() DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level): - DeflatingIOS(ostr, type, level), - std::ostream(&_buf) + std::ostream(&_buf), + DeflatingIOS(ostr, type, level) { } DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, int windowBits, int level): - DeflatingIOS(ostr, windowBits, level), - std::ostream(&_buf) + std::ostream(&_buf), + DeflatingIOS(ostr, windowBits, level) { } @@ -365,15 +365,15 @@ int DeflatingOutputStream::sync() DeflatingInputStream::DeflatingInputStream(std::istream& istr, DeflatingStreamBuf::StreamType type, int level): - DeflatingIOS(istr, type, level), - std::istream(&_buf) + std::istream(&_buf), + DeflatingIOS(istr, type, level) { } DeflatingInputStream::DeflatingInputStream(std::istream& istr, int windowBits, int level): - DeflatingIOS(istr, windowBits, level), - std::istream(&_buf) + std::istream(&_buf), + DeflatingIOS(istr, windowBits, level) { } diff --git a/Foundation/src/InflatingStream.cpp b/Foundation/src/InflatingStream.cpp index 1eac3fa1a..274c3b79c 100644 --- a/Foundation/src/InflatingStream.cpp +++ b/Foundation/src/InflatingStream.cpp @@ -309,15 +309,15 @@ InflatingStreamBuf* InflatingIOS::rdbuf() InflatingOutputStream::InflatingOutputStream(std::ostream& ostr, InflatingStreamBuf::StreamType type): - InflatingIOS(ostr, type), - std::ostream(&_buf) + std::ostream(&_buf), + InflatingIOS(ostr, type) { } InflatingOutputStream::InflatingOutputStream(std::ostream& ostr, int windowBits): - InflatingIOS(ostr, windowBits), - std::ostream(&_buf) + std::ostream(&_buf), + InflatingIOS(ostr, windowBits) { } @@ -334,15 +334,15 @@ int InflatingOutputStream::close() InflatingInputStream::InflatingInputStream(std::istream& istr, InflatingStreamBuf::StreamType type): - InflatingIOS(istr, type), - std::istream(&_buf) + std::istream(&_buf), + InflatingIOS(istr, type) { } InflatingInputStream::InflatingInputStream(std::istream& istr, int windowBits): - InflatingIOS(istr, windowBits), - std::istream(&_buf) + std::istream(&_buf), + InflatingIOS(istr, windowBits) { } From 22e746d1ced0efeb60eb84df5378e04376dac94b Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 7 Dec 2016 12:57:19 +0100 Subject: [PATCH 095/305] fixed GH #1436: ODBC Bug: Unicode text(NVARCHAT) read from DB is truncated to half. --- Data/ODBC/include/Poco/Data/ODBC/Preparator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Data/ODBC/include/Poco/Data/ODBC/Preparator.h b/Data/ODBC/include/Poco/Data/ODBC/Preparator.h index 586c14498..a9246cd15 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Preparator.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Preparator.h @@ -633,7 +633,7 @@ private: (SQLUSMALLINT) pos + 1, valueType, (SQLPOINTER) pCache, - (SQLINTEGER) size, + (SQLINTEGER) size*sizeof(T), &_lengths[pos]))) { throw StatementException(_rStmt, "SQLBindCol()"); @@ -1040,7 +1040,7 @@ inline void Preparator::prepare(std::size_t pos, const std::list& v inline void Preparator::prepare(std::size_t pos, const UTF16String&) { - prepareVariableLen(pos, SQL_C_WCHAR, maxDataSize(pos), DT_CHAR); + prepareVariableLen(pos, SQL_C_WCHAR, maxDataSize(pos), DT_WCHAR); } From 2a7568c737b03e2b2e639c7bfd71c187c9fae960 Mon Sep 17 00:00:00 2001 From: theAirC Date: Thu, 8 Dec 2016 22:04:15 +0200 Subject: [PATCH 096/305] Detection of closed websocket connection When the websocket connection is closed, a non-empty frame (n>0) may be received with FRAME_OP_CLOSE flag bit set. Tested with chrome 54.0.2840.99 ; after establishing the websocket connection, if the connection is not closed by javascript and the tab is closed, a frame of length n=2 is received with FRAME_OP_CLOSE flag set. --- Net/samples/WebSocketServer/src/WebSocketServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Net/samples/WebSocketServer/src/WebSocketServer.cpp b/Net/samples/WebSocketServer/src/WebSocketServer.cpp index 440ab7d5d..8e067129e 100644 --- a/Net/samples/WebSocketServer/src/WebSocketServer.cpp +++ b/Net/samples/WebSocketServer/src/WebSocketServer.cpp @@ -119,7 +119,7 @@ public: app.logger().information(Poco::format("Frame received (length=%d, flags=0x%x).", n, unsigned(flags))); ws.sendFrame(buffer, n, flags); } - while (n > 0 || (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE); + while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE); app.logger().information("WebSocket connection closed."); } catch (WebSocketException& exc) From 7d29037ab53a254788c232b3bab85ce9718ba763 Mon Sep 17 00:00:00 2001 From: zosrothko Date: Sun, 11 Dec 2016 18:56:22 +0100 Subject: [PATCH 097/305] Update to mysql-5.7.16-win32 Switch to http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.16-win32.zip as http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.13-win32.zip is no more available. --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1a266261b..1d980ed37 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ version: build {branch}-{build} cache: - - C:\mysql-5.7.13-win32 + - C:\mysql-5.7.16-win32 - C:\ProgramData\chocolatey - C:\OpenSSL-Win32 - C:\OpenSSL-Win64 @@ -51,7 +51,7 @@ configuration: environment: bundling: bundled - MYSQL32: C:\mysql-5.7.13-win32 + MYSQL32: C:\mysql-5.7.16-win32 MYSQL64: C:\Program Files\MySql\MySQL Server 5.6 POSTGRES32: C:\Program Files (x86)\PostgreSQL\9.4 POSTGRES64: C:\Program Files\PostgreSQL\9.4 @@ -192,9 +192,9 @@ install: else { echo "downloading $env:MYSQL32" - Invoke-WebRequest "http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.13-win32.zip" -OutFile mysql-5.7.13-win32.zip + Invoke-WebRequest "http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.16-win32.zip" -OutFile mysql-5.7.16-win32.zip echo "installing $env:MYSQL32" - 7z x -y mysql-5.7.13-win32.zip -oc:\ + 7z x -y mysql-5.7.16-win32.zip -oc:\ } } # ------------------------------------------------------------------------------------------- From ad37bc3516df23c655b5fb7be89c7ab45d120903 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 29 Dec 2016 11:22:16 +0100 Subject: [PATCH 098/305] fixed GH #1521: bug in JSON ParseHandler.cpp (empty keys should be valid) --- JSON/src/ParseHandler.cpp | 1 - JSON/testsuite/src/JSONTest.cpp | 32 ++++++++++++++++++++++++++++++++ JSON/testsuite/src/JSONTest.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/JSON/src/ParseHandler.cpp b/JSON/src/ParseHandler.cpp index 74296493a..30c8ece07 100644 --- a/JSON/src/ParseHandler.cpp +++ b/JSON/src/ParseHandler.cpp @@ -133,7 +133,6 @@ void ParseHandler::setValue(const Var& value) } else if ( parent.type() == typeid(Object::Ptr) ) { - poco_assert_dbg(!_key.empty()); Object::Ptr obj = parent.extract(); obj->set(_key, value); _key.clear(); diff --git a/JSON/testsuite/src/JSONTest.cpp b/JSON/testsuite/src/JSONTest.cpp index d248bdc1e..99dfe9d25 100644 --- a/JSON/testsuite/src/JSONTest.cpp +++ b/JSON/testsuite/src/JSONTest.cpp @@ -377,6 +377,37 @@ void JSONTest::testEmptyObject() } +void JSONTest::testEmptyPropertyName() +{ + std::string json = "{\"\": 42}"; + Parser parser; + Var result; + + try + { + result = parser.parse(json); + } + catch(JSONException& jsone) + { + std::cout << jsone.message() << std::endl; + assert(false); + } + + assert(result.type() == typeid(Object::Ptr)); + + Object::Ptr object = result.extract(); + assert(object->size() == 1); + + DynamicStruct ds = *object; + assert (ds.size() == 1); + + const DynamicStruct& rds = *object; + assert (rds.size() == 1); + + assert (ds[""] == 42); +} + + void JSONTest::testComplexObject() { std::string json = @@ -1889,6 +1920,7 @@ CppUnit::Test* JSONTest::suite() #endif CppUnit_addTest(pSuite, JSONTest, testStringProperty); CppUnit_addTest(pSuite, JSONTest, testEmptyObject); + CppUnit_addTest(pSuite, JSONTest, testEmptyPropertyName); CppUnit_addTest(pSuite, JSONTest, testComplexObject); CppUnit_addTest(pSuite, JSONTest, testDoubleProperty); CppUnit_addTest(pSuite, JSONTest, testDouble2Property); diff --git a/JSON/testsuite/src/JSONTest.h b/JSON/testsuite/src/JSONTest.h index 637de2e50..be9e25538 100644 --- a/JSON/testsuite/src/JSONTest.h +++ b/JSON/testsuite/src/JSONTest.h @@ -46,6 +46,7 @@ public: #endif void testStringProperty(); void testEmptyObject(); + void testEmptyPropertyName(); void testComplexObject(); void testDoubleProperty(); void testDouble2Property(); From 2914d077c487926652572f877fc8c94d295351d0 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 29 Dec 2016 14:19:42 +0100 Subject: [PATCH 099/305] GH #865: FileChannel compress fails leaving empty .gz files --- Foundation/src/ArchiveStrategy.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Foundation/src/ArchiveStrategy.cpp b/Foundation/src/ArchiveStrategy.cpp index 7491da61f..70327034a 100644 --- a/Foundation/src/ArchiveStrategy.cpp +++ b/Foundation/src/ArchiveStrategy.cpp @@ -25,7 +25,7 @@ #include "Poco/ActiveMethod.h" #include "Poco/Void.h" #include "Poco/FileStream.h" - +#include namespace Poco { @@ -47,28 +47,36 @@ public: { } - ActiveMethod > compress; + ActiveMethod > compress; protected: - Void compressImpl(const std::string& path) + void compressImpl(const std::string& path) { std::string gzPath(path); gzPath.append(".gz"); - FileInputStream istr(path, std::ios::binary | std::ios::in); - if (!istr.good()) throw OpenFileException(path); - FileOutputStream ostr(gzPath, std::ios::binary | std::ios::out); - if (ostr.good()) + FileInputStream istr(path); + FileOutputStream ostr(gzPath); + try { DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP); StreamCopier::copyStream(istr, deflater); + if (!deflater.good() || !ostr.good()) throw WriteFileException(gzPath); deflater.close(); ostr.close(); istr.close(); - File f(path); - f.remove(); } - else throw CreateFileException(gzPath); - return Void(); + catch (Poco::Exception& exc) + { + std::cerr << "***************** Error: " << exc.displayText() << std::endl; + // deflating failed - remove gz file and leave uncompressed log file + ostr.close(); + Poco::File gzf(gzPath); + gzf.remove(); + return; + } + File f(path); + f.remove(); + return; } }; From 760286f86fc1ed379a9aff6da143092d8b40ea9c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 29 Dec 2016 15:00:45 +0100 Subject: [PATCH 100/305] remove debug output --- Foundation/src/ArchiveStrategy.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Foundation/src/ArchiveStrategy.cpp b/Foundation/src/ArchiveStrategy.cpp index 70327034a..cc235119a 100644 --- a/Foundation/src/ArchiveStrategy.cpp +++ b/Foundation/src/ArchiveStrategy.cpp @@ -25,7 +25,7 @@ #include "Poco/ActiveMethod.h" #include "Poco/Void.h" #include "Poco/FileStream.h" -#include + namespace Poco { @@ -65,9 +65,8 @@ protected: ostr.close(); istr.close(); } - catch (Poco::Exception& exc) + catch (Poco::Exception&) { - std::cerr << "***************** Error: " << exc.displayText() << std::endl; // deflating failed - remove gz file and leave uncompressed log file ostr.close(); Poco::File gzf(gzPath); From e46e610b84e69b9d7d3ffc5427a8b0bc1386286c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 30 Dec 2016 10:06:06 +0100 Subject: [PATCH 101/305] fixed GH #1532: RecordSet and RowFilter: bad use of reference counter --- Data/include/Poco/Data/RecordSet.h | 11 ++++++----- Data/include/Poco/Data/RowFilter.h | 8 ++++++-- Data/src/RecordSet.cpp | 8 +------- Data/src/RowFilter.cpp | 11 ++++++++--- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Data/include/Poco/Data/RecordSet.h b/Data/include/Poco/Data/RecordSet.h index ae7fb2719..bba7ac653 100644 --- a/Data/include/Poco/Data/RecordSet.h +++ b/Data/include/Poco/Data/RecordSet.h @@ -26,10 +26,12 @@ #include "Poco/Data/BulkExtraction.h" #include "Poco/Data/Statement.h" #include "Poco/Data/RowIterator.h" +#include "Poco/Data/RowFilter.h" #include "Poco/Data/LOB.h" #include "Poco/String.h" #include "Poco/Dynamic/Var.h" #include "Poco/Exception.h" +#include "Poco/AutoPtr.h" #include #include @@ -98,7 +100,6 @@ public: _currentRow(0), _pBegin(new RowIterator(this, 0 == rowsExtracted())), _pEnd(new RowIterator(this, true)), - _pFilter(0), _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) /// Creates the RecordSet. { @@ -480,17 +481,17 @@ private: /// Returns true if the specified row is allowed by the /// currently active filter. - void filter(RowFilter* pFilter); + void filter(const Poco::AutoPtr& pFilter); /// Sets the filter for the RecordSet. - const RowFilter* getFilter() const; + const Poco::AutoPtr& getFilter() const; /// Returns the filter associated with the RecordSet. std::size_t _currentRow; RowIterator* _pBegin; RowIterator* _pEnd; RowMap _rowMap; - RowFilter* _pFilter; + Poco::AutoPtr _pFilter; std::size_t _totalRowCount; friend class RowIterator; @@ -656,7 +657,7 @@ inline RecordSet::Iterator RecordSet::end() } -inline const RowFilter* RecordSet::getFilter() const +inline const Poco::AutoPtr& RecordSet::getFilter() const { return _pFilter; } diff --git a/Data/include/Poco/Data/RowFilter.h b/Data/include/Poco/Data/RowFilter.h index d427fe821..be89607b6 100644 --- a/Data/include/Poco/Data/RowFilter.h +++ b/Data/include/Poco/Data/RowFilter.h @@ -21,7 +21,6 @@ #include "Poco/Data/Data.h" -#include "Poco/Data/RecordSet.h" #include "Poco/Dynamic/Var.h" #include "Poco/Tuple.h" #include "Poco/String.h" @@ -36,6 +35,9 @@ namespace Poco { namespace Data { +class RecordSet; + + class Data_API RowFilter: public RefCountedObject /// RowFilter class provides row filtering functionality. /// A filter contains a set of criteria (field name, value and @@ -93,7 +95,7 @@ public: void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR) /// Adds value to the filter. { - if (_pRecordSet) _pRecordSet->moveFirst(); + rewindRecordSet(); _comparisonMap.insert(ComparisonMap::value_type(toUpper(name), ComparisonEntry(value, comparison, op))); } @@ -164,6 +166,8 @@ private: RecordSet& recordSet() const; Comparison getComparison(const std::string& comp) const; + + void rewindRecordSet(); Comparisons _comparisons; ComparisonMap _comparisonMap; diff --git a/Data/src/RecordSet.cpp b/Data/src/RecordSet.cpp index 555fe2a03..37600719f 100644 --- a/Data/src/RecordSet.cpp +++ b/Data/src/RecordSet.cpp @@ -41,7 +41,6 @@ RecordSet::RecordSet(const Statement& rStatement, _currentRow(0), _pBegin(new RowIterator(this, 0 == rowsExtracted())), _pEnd(new RowIterator(this, true)), - _pFilter(0), _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) { if (pRowFormatter) setRowFormatter(pRowFormatter); @@ -55,7 +54,6 @@ RecordSet::RecordSet(Session& rSession, _currentRow(0), _pBegin(new RowIterator(this, 0 == rowsExtracted())), _pEnd(new RowIterator(this, true)), - _pFilter(0), _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) { if (pRowFormatter) setRowFormatter(pRowFormatter); @@ -70,7 +68,6 @@ RecordSet::RecordSet(const RecordSet& other): _pFilter(other._pFilter), _totalRowCount(other._totalRowCount) { - if (_pFilter) _pFilter->duplicate(); } @@ -80,7 +77,6 @@ RecordSet::~RecordSet() { delete _pBegin; delete _pEnd; - if (_pFilter) _pFilter->release(); RowMap::iterator it = _rowMap.begin(); RowMap::iterator itEnd = _rowMap.end(); @@ -395,11 +391,9 @@ std::ostream& RecordSet::copy(std::ostream& os, std::size_t offset, std::size_t } -void RecordSet::filter(RowFilter* pFilter) +void RecordSet::filter(const Poco::AutoPtr& pFilter) { - if (_pFilter) _pFilter->release(); _pFilter = pFilter; - if (_pFilter) _pFilter->duplicate(); } diff --git a/Data/src/RowFilter.cpp b/Data/src/RowFilter.cpp index b5e3ff4fb..3d3de5f47 100644 --- a/Data/src/RowFilter.cpp +++ b/Data/src/RowFilter.cpp @@ -20,6 +20,7 @@ #include "Poco/Exception.h" #include + namespace Poco { namespace Data { @@ -53,8 +54,6 @@ void RowFilter::init() _comparisons.insert(Comparisons::value_type("<>", VALUE_NOT_EQUAL)); _comparisons.insert(Comparisons::value_type("!=", VALUE_NOT_EQUAL)); _comparisons.insert(Comparisons::value_type("IS NULL", VALUE_IS_NULL)); - - duplicate(); } @@ -62,7 +61,6 @@ RowFilter::~RowFilter() { try { - release(); if (_pRecordSet) _pRecordSet->filter(0); if (_pParent.get()) _pParent->removeFilter(this); } @@ -201,6 +199,7 @@ void RowFilter::doCompare(Poco::Dynamic::Var& ret, } } + RecordSet& RowFilter::recordSet() const { if (!_pRecordSet) @@ -214,4 +213,10 @@ RecordSet& RowFilter::recordSet() const } +void RowFilter::rewindRecordSet() +{ + if (_pRecordSet) _pRecordSet->moveFirst(); +} + + } } // namespace Poco::Data From f55e88c3f27007e3764ecf6c35831bf27e05d0f8 Mon Sep 17 00:00:00 2001 From: Marian Krivos Date: Tue, 3 Jan 2017 13:55:07 +0100 Subject: [PATCH 102/305] Update to zlib 1.2.10 --- Foundation/include/Poco/zconf.h | 42 +- Foundation/include/Poco/zlib.h | 438 ++++++++++------ Foundation/src/adler32.c | 21 +- Foundation/src/compress.c | 42 +- Foundation/src/crc32.c | 41 +- Foundation/src/deflate.c | 853 +++++++++++++++++++------------- Foundation/src/deflate.h | 31 +- Foundation/src/gzguts.h | 23 +- Foundation/src/infback.c | 4 +- Foundation/src/inffast.c | 85 ++-- Foundation/src/inflate.c | 123 +++-- Foundation/src/inflate.h | 11 +- Foundation/src/inftrees.c | 26 +- Foundation/src/trees.c | 77 +-- Foundation/src/zconf.h | 45 +- Foundation/src/zlib.h | 443 +++++++++++------ Foundation/src/zutil.c | 49 +- Foundation/src/zutil.h | 54 +- 18 files changed, 1503 insertions(+), 905 deletions(-) diff --git a/Foundation/include/Poco/zconf.h b/Foundation/include/Poco/zconf.h index 4dde6868e..eee48179b 100644 --- a/Foundation/include/Poco/zconf.h +++ b/Foundation/include/Poco/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -17,7 +17,7 @@ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align @@ -29,6 +29,7 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 @@ -37,10 +38,14 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams @@ -67,6 +72,8 @@ # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets @@ -78,7 +85,6 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -89,32 +95,39 @@ # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress +# define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO @@ -224,6 +237,21 @@ # define z_const #endif +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL @@ -256,7 +284,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -416,13 +444,11 @@ typedef uLong FAR uLongf; # define Z_HAVE_STDARG_H #endif -#ifndef _WIN32_WCE #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif -#endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO diff --git a/Foundation/include/Poco/zlib.h b/Foundation/include/Poco/zlib.h index 3e0c7672a..3cd6cb852 100644 --- a/Foundation/include/Poco/zlib.h +++ b/Foundation/include/Poco/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 + version 1.2.10, January 2nd, 2017 - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 +#define ZLIB_VERSION "1.2.10" +#define ZLIB_VERNUM 0x12a0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 +#define ZLIB_VER_REVISION 10 #define ZLIB_VER_SUBREVISION 0 /* @@ -65,7 +65,8 @@ extern "C" { with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. + This library can optionally read and write gzip and raw deflate streams in + memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- @@ -74,7 +75,7 @@ extern "C" { The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash - even in case of corrupted input. + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -87,7 +88,7 @@ typedef struct z_stream_s { uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ @@ -98,8 +99,9 @@ typedef struct z_stream_s { free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; @@ -142,7 +144,9 @@ typedef gz_header FAR *gz_headerp; zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if @@ -155,7 +159,7 @@ typedef gz_header FAR *gz_headerp; The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly + uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ @@ -200,7 +204,7 @@ typedef gz_header FAR *gz_headerp; #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ @@ -258,11 +262,11 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more @@ -271,7 +275,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to @@ -292,8 +298,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. + in order for the decompressor to finish the block before the empty fixed + codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to @@ -319,34 +325,38 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ @@ -369,23 +379,21 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ @@ -401,17 +409,20 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be @@ -428,7 +439,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the + To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or @@ -454,7 +465,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not + saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the @@ -476,32 +487,33 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 + below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing + header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. + recovery of the data is to be attempted. */ @@ -511,9 +523,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); This function discards any unprocessed input and does not flush any pending output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ @@ -544,16 +555,29 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. + with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is @@ -614,12 +638,12 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -628,6 +652,28 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* @@ -648,10 +694,10 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). @@ -662,20 +708,35 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). + If the compression approach (which is a function of the level) or the + strategy is changed, then the input available so far is compressed with the + old level and strategy using deflate(strm, Z_BLOCK). There are three + approaches for the compression levels 0, 1..3, and 4..9 respectively. The + new level and strategy will take effect at the next call of deflate(). - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, @@ -793,7 +854,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to + recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. @@ -802,7 +863,10 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -823,7 +887,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. + can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the @@ -834,7 +898,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ @@ -892,7 +956,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The + but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source @@ -904,7 +968,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if @@ -956,7 +1022,7 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. - inflateMark returns the value noted above or -1 << 16 if the provided + inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ @@ -1048,9 +1114,9 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those @@ -1059,12 +1125,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). @@ -1092,7 +1158,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() + assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ @@ -1114,7 +1180,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 7.6: size of z_off_t Compiler, assembler, and debug options: - 8: DEBUG + 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) @@ -1164,7 +1230,8 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1180,7 +1247,7 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, @@ -1203,7 +1270,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1212,6 +1279,14 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + /* gzip file access functions */ /* @@ -1290,10 +1365,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). @@ -1304,10 +1378,12 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); @@ -1335,7 +1411,35 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); case. gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, @@ -1346,19 +1450,33 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); @@ -1418,7 +1536,7 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. + concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. @@ -1572,7 +1690,7 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: @@ -1585,6 +1703,12 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); @@ -1614,6 +1738,12 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); @@ -1644,19 +1774,35 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif #ifndef Z_SOLO @@ -1676,10 +1822,10 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or @@ -1747,9 +1893,11 @@ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif diff --git a/Foundation/src/adler32.c b/Foundation/src/adler32.c index a868f073d..d0be4380a 100644 --- a/Foundation/src/adler32.c +++ b/Foundation/src/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,11 +7,9 @@ #include "zutil.h" -#define local static - local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521 /* largest prime smaller than 65536 */ +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -62,10 +60,10 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #endif /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) +uLong ZEXPORT adler32_z(adler, buf, len) uLong adler; const Bytef *buf; - uInt len; + z_size_t len; { unsigned long sum2; unsigned n; @@ -132,6 +130,15 @@ uLong ZEXPORT adler32(adler, buf, len) return adler | (sum2 << 16); } +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; @@ -156,7 +163,7 @@ local uLong adler32_combine_(adler1, adler2, len2) sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } diff --git a/Foundation/src/compress.c b/Foundation/src/compress.c index 6e9762676..e2db404ab 100644 --- a/Foundation/src/compress.c +++ b/Foundation/src/compress.c @@ -1,5 +1,5 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -28,16 +28,11 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) { z_stream stream; int err; + const uInt max = (uInt)-1; + uLong left; - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + left = *destLen; + *destLen = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; @@ -46,15 +41,26 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) err = deflateInit(&stream, level); if (err != Z_OK) return err; - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; - err = deflateEnd(&stream); - return err; + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== diff --git a/Foundation/src/crc32.c b/Foundation/src/crc32.c index 979a7190a..9580440c0 100644 --- a/Foundation/src/crc32.c +++ b/Foundation/src/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -30,17 +30,15 @@ #include "zutil.h" /* for STDC and FAR definitions */ -#define local static - /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR #endif #ifdef BYFOUR local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); # define TBLS 8 #else # define TBLS 1 @@ -201,10 +199,10 @@ const z_crc_t FAR * ZEXPORT get_crc_table() #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) +unsigned long ZEXPORT crc32_z(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - uInt len; + z_size_t len; { if (buf == Z_NULL) return 0UL; @@ -235,8 +233,29 @@ unsigned long ZEXPORT crc32(crc, buf, len) return crc ^ 0xffffffffUL; } +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + #ifdef BYFOUR +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ @@ -247,7 +266,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; @@ -278,7 +297,7 @@ local unsigned long crc32_little(crc, buf, len) } /* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ +#define DOBIG4 c ^= *buf4++; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 @@ -287,7 +306,7 @@ local unsigned long crc32_little(crc, buf, len) local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; @@ -300,7 +319,6 @@ local unsigned long crc32_big(crc, buf, len) } buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; while (len >= 32) { DOBIG32; len -= 32; @@ -309,7 +327,6 @@ local unsigned long crc32_big(crc, buf, len) DOBIG4; len -= 4; } - buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { diff --git a/Foundation/src/deflate.c b/Foundation/src/deflate.c index abb57bbf1..2ad890e35 100644 --- a/Foundation/src/deflate.c +++ b/Foundation/src/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.10 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -73,6 +73,8 @@ typedef enum { typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); @@ -84,8 +86,9 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else @@ -148,21 +151,14 @@ local const config configuration_table[10] = { * meaning. */ -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) @@ -173,9 +169,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ @@ -197,6 +193,37 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; @@ -270,7 +297,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ @@ -278,14 +305,15 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; - s->w_bits = windowBits; + s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; + s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); @@ -319,6 +347,31 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; @@ -331,7 +384,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) unsigned avail; z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; @@ -388,14 +441,35 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -410,7 +484,11 @@ int ZEXPORT deflateResetKeep (strm) if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : @@ -440,8 +518,8 @@ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } @@ -452,7 +530,7 @@ int ZEXPORT deflatePending (strm, pending, bits) int *bits; z_streamp strm; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) @@ -469,7 +547,7 @@ int ZEXPORT deflatePrime (strm, bits, value) deflate_state *s; int put; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; @@ -494,9 +572,8 @@ int ZEXPORT deflateParams(strm, level, strategy) { deflate_state *s; compress_func func; - int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST @@ -509,14 +586,22 @@ int ZEXPORT deflateParams(strm, level, strategy) } func = configuration_table[s->level].func; - if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { + if ((strategy != s->strategy || func != configuration_table[level].func)) { /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_out == 0) + return Z_BUF_ERROR; } if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; @@ -524,7 +609,7 @@ int ZEXPORT deflateParams(strm, level, strategy) s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; - return err; + return Z_OK; } /* ========================================================================= */ @@ -537,12 +622,12 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; - s->max_chain_length = max_chain; + s->max_chain_length = (uInt)max_chain; return Z_OK; } @@ -569,14 +654,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) { deflate_state *s; uLong complen, wraplen; - Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) + if (deflateStateCheck(strm)) return complen + 6; /* compute wrapper length */ @@ -588,9 +672,11 @@ uLong ZEXPORT deflateBound(strm, sourceLen) case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; +#ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; @@ -607,6 +693,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen += 2; } break; +#endif default: /* for compiler happiness */ wraplen = 6; } @@ -634,10 +721,10 @@ local void putShortMSB (s, b) } /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; @@ -654,13 +741,23 @@ local void flush_pending(strm) strm->next_out += len; s->pending_out += len; strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; + strm->avail_out -= len; + s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; @@ -669,203 +766,21 @@ int ZEXPORT deflate (strm, flush) int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); @@ -894,15 +809,197 @@ int ZEXPORT deflate (strm, flush) ERR_RETURN(strm, Z_BUF_ERROR); } + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -944,7 +1041,6 @@ int ZEXPORT deflate (strm, flush) } } } - Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; @@ -981,18 +1077,9 @@ int ZEXPORT deflateEnd (strm) { int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -1023,7 +1110,7 @@ int ZEXPORT deflateCopy (dest, source) ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -1073,7 +1160,7 @@ int ZEXPORT deflateCopy (dest, source) * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -local int read_buf(strm, buf, size) +local unsigned read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; @@ -1097,7 +1184,7 @@ local int read_buf(strm, buf, size) strm->next_in += len; strm->total_in += len; - return (int)len; + return len; } /* =========================================================================== @@ -1151,9 +1238,9 @@ local uInt longest_match(s, cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ + register Bytef *match; /* matched string */ register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ + int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; @@ -1188,7 +1275,7 @@ local uInt longest_match(s, cur_match) /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); @@ -1350,6 +1437,10 @@ local uInt longest_match(s, cur_match) #endif /* FASTEST */ #ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + /* =========================================================================== * Check that the match at match_start is indeed a match. */ @@ -1375,7 +1466,7 @@ local void check_match(s, start, match, length) } #else # define check_match(s, start, match, length) -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. @@ -1390,8 +1481,7 @@ local void check_match(s, start, match, length) local void fill_window(s) deflate_state *s; { - register unsigned n, m; - register Posf *p; + unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; @@ -1418,35 +1508,11 @@ local void fill_window(s) */ if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif + slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; @@ -1552,70 +1618,195 @@ local void fill_window(s) if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. */ - ulg max_block_size = 0xffff; - ulg max_start; + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + if (left > len) + left = len; /* limit window pull to len */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len - left != s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len - left == s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + + /* Update debugging counts for the data about to be copied. */ +#ifdef ZLIB_DEBUG + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + } + s->block_start = s->strstart; + s->insert += MIN(used, s->w_size - s->insert); } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); + + /* If the last block was written to next_out, then done. */ + if (last) return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart - 1; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + } + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; } /* =========================================================================== @@ -1892,7 +2083,7 @@ local block_state deflate_rle(s, flush) prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); + s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } diff --git a/Foundation/src/deflate.h b/Foundation/src/deflate.h index 844079019..23ecdd312 100644 --- a/Foundation/src/deflate.h +++ b/Foundation/src/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2016 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -51,13 +51,16 @@ #define Buf_size 16 /* size of bit buffer in bi_buf */ -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ @@ -83,7 +86,7 @@ typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; @@ -100,10 +103,10 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ + ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ + ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ @@ -275,7 +278,7 @@ typedef struct internal_state { /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) @@ -328,8 +331,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ diff --git a/Foundation/src/gzguts.h b/Foundation/src/gzguts.h index 545d5b40e..990a4d251 100644 --- a/Foundation/src/gzguts.h +++ b/Foundation/src/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -25,16 +25,22 @@ # include # include #endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include #ifdef _WIN32 # include #endif -#ifndef _WIN32_WCE #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif + +#if defined(_WIN32) || defined(__CYGWIN__) +# define WIDECHAR #endif #ifdef WINAPI_FAMILY @@ -97,18 +103,19 @@ # endif #endif -/* unlike snprintf (which is required in C99, yet still not supported by - Microsoft more than a decade later!), _snprintf does not guarantee null - termination of the result -- however this is only used in gzlib.c where +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC @@ -172,7 +179,7 @@ typedef struct { char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ + unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ diff --git a/Foundation/src/infback.c b/Foundation/src/infback.c index f3833c2e4..59679ecbf 100644 --- a/Foundation/src/infback.c +++ b/Foundation/src/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -61,7 +61,7 @@ int stream_size; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; - state->wbits = windowBits; + state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; diff --git a/Foundation/src/inffast.c b/Foundation/src/inffast.c index bda59ceb6..29eb7d824 100644 --- a/Foundation/src/inffast.c +++ b/Foundation/src/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013 Mark Adler + * Copyright (C) 1995-2008, 2010, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,26 +8,9 @@ #include "inflate.h" #include "inffast.h" -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") #else -# define OFF 1 -# define PUP(a) *++(a) -#endif /* Decode literal, length, and distance codes and write out the resulting @@ -96,9 +79,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -119,9 +102,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode[hold & lmask]; @@ -134,14 +117,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); + *out++ = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -150,9 +133,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode[hold & dmask]; @@ -165,10 +148,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } @@ -196,30 +179,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { - PUP(out) = 0; + *out++ = 0; } while (--len); continue; } len -= op - whave; do { - PUP(out) = 0; + *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--len); continue; } #endif } - from = window - OFF; + from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -230,14 +213,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; + from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -248,35 +231,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } while (len > 2); if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } } @@ -313,8 +296,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); diff --git a/Foundation/src/inflate.c b/Foundation/src/inflate.c index 870f89bb4..ac333e8c2 100644 --- a/Foundation/src/inflate.c +++ b/Foundation/src/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2012 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -92,6 +92,7 @@ #endif /* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, unsigned copy)); @@ -101,12 +102,26 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; @@ -131,7 +146,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; @@ -147,7 +162,7 @@ int windowBits; struct inflate_state FAR *state; /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ @@ -156,7 +171,7 @@ int windowBits; windowBits = -windowBits; } else { - wrap = (windowBits >> 4) + 1; + wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; @@ -210,7 +225,9 @@ int stream_size; if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; + state->strm = strm; state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -234,17 +251,17 @@ int value; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; return Z_OK; } @@ -625,7 +642,7 @@ int flush; static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -645,6 +662,8 @@ int flush; NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); @@ -672,7 +691,7 @@ int flush; len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - else if (len > state->wbits) { + if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; @@ -699,14 +718,16 @@ int flush; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: @@ -715,7 +736,8 @@ int flush; state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: @@ -724,7 +746,8 @@ int flush; state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) @@ -742,7 +765,7 @@ int flush; len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -761,9 +784,9 @@ int flush; if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) - state->head->name[state->length++] = len; + state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -782,9 +805,9 @@ int flush; if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) - state->head->comment[state->length++] = len; + state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -796,7 +819,7 @@ int flush; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); - if (hold != (state->check & 0xffff)) { + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; @@ -1177,11 +1200,11 @@ int flush; out -= left; strm->total_out += out; state->total += out; - if (out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; - if (( + if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif @@ -1240,10 +1263,10 @@ int flush; strm->total_in += in; strm->total_out += out; state->total += out; - if (state->wrap && out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1255,7 +1278,7 @@ int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); @@ -1273,7 +1296,7 @@ uInt *dictLength; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ @@ -1298,7 +1321,7 @@ uInt dictLength; int ret; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; @@ -1330,7 +1353,7 @@ gz_headerp head; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; @@ -1383,7 +1406,7 @@ z_streamp strm; struct inflate_state FAR *state; /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; @@ -1430,7 +1453,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } @@ -1445,8 +1468,7 @@ z_streamp source; unsigned wsize; /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; @@ -1467,6 +1489,7 @@ z_streamp source; /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); @@ -1488,25 +1511,51 @@ int subvert; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; return Z_OK; #else + (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + if (inflateStateCheck(strm)) + return -(1L << 16); state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + + return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/Foundation/src/inflate.h b/Foundation/src/inflate.h index 95f4986d4..a46cce6b6 100644 --- a/Foundation/src/inflate.h +++ b/Foundation/src/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,7 +18,7 @@ /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -77,11 +77,14 @@ typedef enum { CHECK -> LENGTH -> DONE */ -/* state maintained between inflate() calls. Approximately 10K bytes. */ +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ diff --git a/Foundation/src/inftrees.c b/Foundation/src/inftrees.c index 44d89cf24..8a904ddbc 100644 --- a/Foundation/src/inftrees.c +++ b/Foundation/src/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2013 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; + " inflate 1.2.10 Copyright 1995-2017 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -54,7 +54,7 @@ unsigned short FAR *work; code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 192, 202}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -181,19 +181,17 @@ unsigned short FAR *work; switch (type) { case CODES: base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; - default: /* DISTS */ + default: /* DISTS */ base = dbase; extra = dext; - end = -1; + match = 0; } /* initialize state for loop */ @@ -216,13 +214,13 @@ unsigned short FAR *work; for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ diff --git a/Foundation/src/trees.c b/Foundation/src/trees.c index 480303d9f..357f31392 100644 --- a/Foundation/src/trees.c +++ b/Foundation/src/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2016 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -122,13 +122,13 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local static_tree_desc static_l_desc = +local const static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local static_tree_desc static_d_desc = +local const static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local static_tree_desc static_bl_desc = +local const static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== @@ -152,8 +152,6 @@ local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); @@ -163,7 +161,7 @@ local void gen_trees_header OF((void)); # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ -#else /* DEBUG */ +#else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } @@ -208,12 +206,12 @@ local void send_bits(s, value, length) s->bi_valid += length; } } -#else /* !DEBUG */ +#else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ + int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ @@ -223,7 +221,7 @@ local void send_bits(s, value, length) s->bi_valid += len;\ }\ } -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ @@ -317,7 +315,7 @@ local void tr_static_init() * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H -# ifndef DEBUG +# ifndef ZLIB_DEBUG # include # endif @@ -522,12 +520,12 @@ local void gen_bitlen(s, desc) xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; - Trace((stderr,"\nbit length overflow\n")); + Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ @@ -554,9 +552,8 @@ local void gen_bitlen(s, desc) m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; @@ -578,7 +575,7 @@ local void gen_codes (tree, max_code, bl_count) ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ + unsigned code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ @@ -586,7 +583,8 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. @@ -599,7 +597,7 @@ local void gen_codes (tree, max_code, bl_count) int len = tree[n].Len; if (len == 0) continue; /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); @@ -821,7 +819,7 @@ local int build_bl_tree(s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); @@ -869,11 +867,17 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) int last; /* one if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; #ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len<<3; #endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== @@ -1090,7 +1094,7 @@ local void compress_block(s, ltree, dtree) send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { - dist -= base_dist[code]; + dist -= (unsigned)base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ @@ -1197,30 +1201,3 @@ local void bi_windup(s) s->bits_sent = (s->bits_sent+7) & ~7; #endif } - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef ZLIB_DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef ZLIB_DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/Foundation/src/zconf.h b/Foundation/src/zconf.h index c88108b6e..5e1d68a00 100644 --- a/Foundation/src/zconf.h +++ b/Foundation/src/zconf.h @@ -1,9 +1,9 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id: //poco/1.4/Foundation/src/zconf.h#6 $ */ +/* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H @@ -17,7 +17,7 @@ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align @@ -29,6 +29,7 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 @@ -37,10 +38,14 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams @@ -67,6 +72,8 @@ # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets @@ -78,7 +85,6 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -89,32 +95,39 @@ # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress +# define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO @@ -224,9 +237,19 @@ # define z_const #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -256,7 +279,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -416,13 +439,11 @@ typedef uLong FAR uLongf; # define Z_HAVE_STDARG_H #endif -#ifndef _WIN32_WCE #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif -#endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO diff --git a/Foundation/src/zlib.h b/Foundation/src/zlib.h index 3e0c7672a..dc90dc8d2 100644 --- a/Foundation/src/zlib.h +++ b/Foundation/src/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 + version 1.2.10, January 2nd, 2017 - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 +#define ZLIB_VERSION "1.2.10" +#define ZLIB_VERNUM 0x12a0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 +#define ZLIB_VER_REVISION 10 #define ZLIB_VER_SUBREVISION 0 /* @@ -65,7 +65,8 @@ extern "C" { with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. + This library can optionally read and write gzip and raw deflate streams in + memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- @@ -74,7 +75,7 @@ extern "C" { The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash - even in case of corrupted input. + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -87,7 +88,7 @@ typedef struct z_stream_s { uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ @@ -98,8 +99,9 @@ typedef struct z_stream_s { free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; @@ -142,7 +144,9 @@ typedef gz_header FAR *gz_headerp; zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if @@ -155,7 +159,7 @@ typedef gz_header FAR *gz_headerp; The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly + uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ @@ -200,7 +204,7 @@ typedef gz_header FAR *gz_headerp; #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ @@ -258,11 +262,11 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more @@ -271,7 +275,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to @@ -292,8 +298,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. + in order for the decompressor to finish the block before the empty fixed + codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to @@ -319,34 +325,38 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ @@ -369,23 +379,21 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ @@ -401,17 +409,20 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be @@ -428,7 +439,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the + To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or @@ -454,7 +465,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not + saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the @@ -476,32 +487,33 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 + below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing + header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. + recovery of the data is to be attempted. */ @@ -511,9 +523,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); This function discards any unprocessed input and does not flush any pending output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ @@ -544,16 +555,29 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. + with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is @@ -614,12 +638,12 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -628,6 +652,28 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* @@ -648,10 +694,10 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). @@ -662,20 +708,35 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). + If the compression approach (which is a function of the level) or the + strategy is changed, then the input available so far is compressed with the + old level and strategy using deflate(strm, Z_BLOCK). There are three + approaches for the compression levels 0, 1..3, and 4..9 respectively. The + new level and strategy will take effect at the next call of deflate(). - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, @@ -793,7 +854,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to + recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. @@ -802,7 +863,10 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -823,7 +887,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. + can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the @@ -834,7 +898,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ @@ -892,7 +956,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The + but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source @@ -904,7 +968,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if @@ -956,7 +1022,7 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. - inflateMark returns the value noted above or -1 << 16 if the provided + inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ @@ -1048,9 +1114,9 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those @@ -1059,12 +1125,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). @@ -1092,7 +1158,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() + assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ @@ -1114,7 +1180,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 7.6: size of z_off_t Compiler, assembler, and debug options: - 8: DEBUG + 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) @@ -1164,7 +1230,8 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1180,7 +1247,7 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, @@ -1203,7 +1270,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1212,6 +1279,14 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + /* gzip file access functions */ /* @@ -1290,10 +1365,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). @@ -1304,10 +1378,12 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); @@ -1335,7 +1411,35 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); case. gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, @@ -1346,19 +1450,33 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); @@ -1418,7 +1536,7 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. + concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. @@ -1572,7 +1690,7 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: @@ -1585,6 +1703,12 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); @@ -1614,6 +1738,12 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); @@ -1644,19 +1774,35 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif #ifndef Z_SOLO @@ -1676,10 +1822,10 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or @@ -1737,19 +1883,16 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #endif /* !Z_SOLO */ -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif diff --git a/Foundation/src/zutil.c b/Foundation/src/zutil.c index 083c9f58c..56534fba0 100644 --- a/Foundation/src/zutil.c +++ b/Foundation/src/zutil.c @@ -1,30 +1,27 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2010, 2011, 2012, 2016 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id: //poco/1.4/Foundation/src/zutil.c#3 $ */ +/* @(#) $Id$ */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - z_const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; const char * ZEXPORT zlibVersion() @@ -116,7 +113,7 @@ uLong ZEXPORT zlibCompileFlags() } #ifdef ZLIB_DEBUG - +#include # ifndef verbose # define verbose 0 # endif @@ -139,7 +136,7 @@ const char * ZEXPORT zError(err) return ERR_MSG(err); } -#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 +#if defined(_WIN32_WCE) /* The Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. @@ -219,9 +216,11 @@ local ptr_table table[MAX_PTR]; voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -244,6 +243,9 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -259,7 +261,6 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } @@ -278,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; _hfree(ptr); } @@ -306,7 +307,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) unsigned items; unsigned size; { - if (opaque) items += size - size; /* make compiler happy */ + (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } @@ -315,8 +316,8 @@ void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { + (void)opaque; free(ptr); - if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ diff --git a/Foundation/src/zutil.h b/Foundation/src/zutil.h index dd28aa337..b079ea6a8 100644 --- a/Foundation/src/zutil.h +++ b/Foundation/src/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,7 +8,7 @@ subject to change. Applications should only use zlib.h. */ -/* @(#) $Id: //poco/1.4/Foundation/src/zutil.h#3 $ */ +/* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H @@ -36,7 +36,9 @@ #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; @@ -98,28 +100,38 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifdef AMIGA -# define OS_CODE 0x01 +# define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 +# define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 #endif #ifdef OS2 -# define OS_CODE 0x06 +# define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 +# define OS_CODE 7 # ifndef Z_SOLO # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ @@ -131,18 +143,24 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#ifdef __acorn +# define OS_CODE 13 #endif -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) @@ -150,7 +168,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 +# if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # ifndef _PTRDIFF_T_DEFINED typedef int ptrdiff_t; @@ -177,7 +195,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN From 1915e2b7495cb31f25a688165f46bb0e2d17d912 Mon Sep 17 00:00:00 2001 From: Marian Krivos Date: Tue, 3 Jan 2017 14:02:09 +0100 Subject: [PATCH 103/305] Update to sqlite 3.16.0 --- Data/SQLite/src/sqlite3.c | 12241 ++++++++++++++++++++++-------------- Data/SQLite/src/sqlite3.h | 632 +- 2 files changed, 7866 insertions(+), 5007 deletions(-) diff --git a/Data/SQLite/src/sqlite3.c b/Data/SQLite/src/sqlite3.c index ccddfe69b..40bcbefe6 100644 --- a/Data/SQLite/src/sqlite3.c +++ b/Data/SQLite/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.14.1. By combining all the individual C code files into this +** version 3.16.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -9,7 +9,7 @@ ** ** This file is all you need to compile SQLite. To use SQLite in other ** programs, you need this file and the "sqlite3.h" header file that defines -** the programming interface to the SQLite library. (If you do not have +** the programming interface to the SQLite library. (If you do not have ** the "sqlite3.h" header file at hand, you will find a copy embedded within ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed @@ -368,7 +368,8 @@ extern "C" { ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since version 3.6.18, SQLite source code has been stored in the +** Since [version 3.6.18] ([dateof:3.6.18]), +** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite @@ -380,13 +381,13 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.14.1" -#define SQLITE_VERSION_NUMBER 3014001 -#define SQLITE_SOURCE_ID "2016-08-11 18:53:32 a12d8059770df4bca59e321c266410344242bf7b" +#define SQLITE_VERSION "3.16.0" +#define SQLITE_VERSION_NUMBER 3016000 +#define SQLITE_SOURCE_ID "2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf" /* ** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version, sqlite3_sourceid +** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros @@ -415,9 +416,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -442,8 +443,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* @@ -482,7 +483,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); +SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -579,8 +580,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -651,7 +652,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -712,7 +713,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( ** [result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include +** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] +** and later) include ** support for additional result codes that provide more detailed information ** about errors. These [extended result codes] are enabled or disabled ** on a per database connection basis using the @@ -1236,6 +1238,12 @@ struct sqlite3_io_methods { ** on whether or not the file has been renamed, moved, or deleted since it ** was first opened. ** +**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the +** underlying native file handle associated with a file handle. This file +** control interprets its argument as a pointer to a native file handle and +** writes the resulting value there. +** **
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one @@ -1286,6 +1294,8 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 +#define SQLITE_FCNTL_PDB 30 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1650,10 +1660,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1686,7 +1696,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); +SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections @@ -1705,7 +1715,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -2229,13 +2239,36 @@ struct sqlite3_mem_methods { ** be a NULL pointer, in which case the new setting is not reported back. ** ** +**
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    ^This option is used to change the name of the "main" database +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged +** until after the database connection closes. +**
    +** +**
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    +**
    Usually, when a database in wal mode is closed or detached from a +** database handle, SQLite checks if this will mean that there are now no +** connections at all to the database. If so, it performs a checkpoint +** operation before closing the connection. This option may be used to +** override this behaviour. The first parameter passed to this operation +** is an integer - non-zero to disable checkpoints-on-close, or zero (the +** default) to enable them. The second parameter is a pointer to an integer +** into which is written 0 or 1 to indicate whether checkpoints-on-close +** have been disabled - 0 if they are not disabled, 1 if they are. +**
    +** ** */ +#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ /* @@ -2246,7 +2279,7 @@ struct sqlite3_mem_methods { ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid @@ -2298,7 +2331,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff) ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified @@ -2351,7 +2384,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified @@ -2375,7 +2408,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query @@ -2415,7 +2448,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2450,8 +2483,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors @@ -2512,7 +2545,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); /* ** CAPI3REF: Set A Busy Timeout @@ -2535,7 +2568,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*,int(*)(void*,int),vo ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries @@ -2610,7 +2643,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2618,7 +2651,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions @@ -2724,10 +2757,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2817,12 +2850,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void sqlite3_free(void*); +SQLITE_API sqlite3_uint64 sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2847,8 +2880,8 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2871,7 +2904,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks @@ -2954,7 +2987,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -3062,9 +3095,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_trace(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_profile(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* @@ -3153,7 +3186,7 @@ SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_profile(sqlite3*, ** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which ** are deprecated. */ -SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( +SQLITE_API int sqlite3_trace_v2( sqlite3*, unsigned uMask, int(*xCallback)(unsigned,void*,void*,void*), @@ -3192,7 +3225,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection @@ -3421,15 +3454,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3475,9 +3508,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* @@ -3521,11 +3554,11 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); /* ** CAPI3REF: Prepared Statement Object @@ -3593,7 +3626,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3745,28 +3778,28 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); **
  • ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3805,8 +3838,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); -SQLITE_API char *SQLITE_STDCALL sqlite3_expanded_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -3837,8 +3870,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_expanded_sql(sqlite3_stmt *pStmt); ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. +** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since +** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and +** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so +** sqlite3_stmt_readonly() returns false for those commands. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -3859,7 +3896,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -4023,20 +4060,20 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -4057,7 +4094,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter @@ -4085,7 +4122,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name @@ -4102,7 +4139,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_name()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement @@ -4112,7 +4149,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set @@ -4124,7 +4161,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set @@ -4153,8 +4190,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result @@ -4202,12 +4239,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result @@ -4239,8 +4276,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt* ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement @@ -4301,7 +4338,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** other than [SQLITE_ROW] before any subsequent invocation of ** sqlite3_step(). Failure to reset the prepared statement using ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from -** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], +** sqlite3_step() began ** calling [sqlite3_reset()] automatically in this circumstance rather ** than returning [SQLITE_MISUSE]. This is not considered a compatibility ** break because any application that ever receives an SQLITE_MISUSE error @@ -4320,7 +4358,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set @@ -4341,7 +4379,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -4531,16 +4569,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4568,7 +4606,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object @@ -4595,7 +4633,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions @@ -4695,7 +4733,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4705,7 +4743,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4715,7 +4753,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4761,12 +4799,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif @@ -4816,18 +4854,18 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -4843,7 +4881,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); ** from the result of one [application-defined SQL function] into the ** input of another. */ -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -4859,8 +4897,8 @@ SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); +SQLITE_API void sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context @@ -4905,7 +4943,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions @@ -4920,7 +4958,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions @@ -4932,7 +4970,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data @@ -4986,8 +5024,8 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -5123,27 +5161,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* @@ -5158,7 +5196,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int); +SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -5240,14 +5278,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -5255,7 +5293,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -5290,12 +5328,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -5309,11 +5347,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( +SQLITE_API int sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -5327,11 +5365,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( +SQLITE_API int sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -5341,7 +5379,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( +SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5351,7 +5389,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( +SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5373,7 +5411,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5492,7 +5530,7 @@ SQLITE_API char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement @@ -5505,7 +5543,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection @@ -5522,7 +5560,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only @@ -5532,7 +5570,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement @@ -5548,7 +5586,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks @@ -5597,8 +5635,8 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks @@ -5649,7 +5687,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], ** and [sqlite3_preupdate_hook()] interfaces. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5664,7 +5702,8 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** and disabled if the argument is false.)^ ** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent @@ -5689,7 +5728,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5705,7 +5744,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection @@ -5719,7 +5758,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); +SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5758,7 +5797,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** from the heap. ** )^ ** -** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without @@ -5771,7 +5811,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5782,7 +5822,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* @@ -5852,7 +5892,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5908,7 +5948,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( ** ** See also the [load_extension() SQL function]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5940,7 +5980,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5978,7 +6018,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void(*xEntryPoint)(void)); +SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading @@ -5990,7 +6030,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void(*xEntryPoint)(void)); ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); +SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading @@ -5998,7 +6038,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void(*xEntryPoint)(v ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); +SQLITE_API void sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered @@ -6152,13 +6192,15 @@ struct sqlite3_module { ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -** structure for SQLite version 3.8.2. If a virtual table extension is +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). +** If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for version 3.9.0. It may therefore only be used if +** was added for [version 3.9.0] ([dateof:3.9.0]). +** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ @@ -6243,13 +6285,13 @@ struct sqlite3_index_info { ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -6312,7 +6354,7 @@ struct sqlite3_vtab_cursor { ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table @@ -6331,7 +6373,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -6430,7 +6472,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -6463,7 +6505,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( ** ** ^This function sets the database handle error code and message. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle @@ -6486,7 +6528,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64) ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB @@ -6502,7 +6544,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally @@ -6531,7 +6573,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); ** ** See also: [sqlite3_blob_write()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally @@ -6573,7 +6615,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, ** ** See also: [sqlite3_blob_read()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects @@ -6604,9 +6646,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes @@ -6722,11 +6764,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object @@ -6836,8 +6878,8 @@ struct sqlite3_mutex_methods { ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* @@ -6856,7 +6898,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ @@ -6877,7 +6919,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files @@ -6912,7 +6954,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -6931,7 +6973,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); +SQLITE_API int sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes @@ -6960,6 +7002,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ +#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 @@ -6994,8 +7037,8 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); ** ** See also: [sqlite3_db_status()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); -SQLITE_API int SQLITE_STDCALL sqlite3_status64( +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int sqlite3_status64( int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, @@ -7120,7 +7163,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections @@ -7263,7 +7306,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7732,16 +7775,16 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification @@ -7858,7 +7901,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7873,8 +7916,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7891,7 +7934,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); ** ** See also: [sqlite3_strlike()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: String LIKE Matching @@ -7914,7 +7957,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zSt ** ** See also: [sqlite3_strglob()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); +SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); /* ** CAPI3REF: Error Logging Interface @@ -7937,7 +7980,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zSt ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook @@ -7973,7 +8016,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -8008,7 +8051,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database @@ -8030,7 +8073,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database @@ -8124,7 +8167,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zD ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -8160,7 +8203,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -8213,7 +8256,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -8318,7 +8361,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -8334,7 +8377,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction @@ -8366,7 +8409,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); ** ^This function does not set the database handle error code or message ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); +SQLITE_API int sqlite3_db_cacheflush(sqlite3*); /* ** CAPI3REF: The pre-update hook. @@ -8446,7 +8489,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); ** ** See also: [sqlite3_update_hook()] */ -SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_preupdate_hook( +#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) +SQLITE_API void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ @@ -8459,10 +8503,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_preupdate_hook( ), void* ); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_count(sqlite3 *); +SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); +SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +#endif /* ** CAPI3REF: Low-level system error code @@ -8474,11 +8519,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 ** called to get back the underlying "errno" that caused the problem, such ** as ENOSPC, EAUTH, EISDIR, and so forth. */ -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); +SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} +** KEYWORDS: {snapshot} {sqlite3_snapshot} ** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] @@ -8502,7 +8547,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ -typedef struct sqlite3_snapshot sqlite3_snapshot; +typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +} sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot @@ -8513,9 +8560,32 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** schema S in database connection D. ^On success, the ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** ^If schema S of [database connection] D is not a [WAL mode] database -** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)] -** leaves the *P value unchanged and returns an appropriate [error code]. +** If there is not already a read-transaction open on schema S when +** this function is called, one is opened automatically. +** +** The following must be true for this function to succeed. If any of +** the following statements are false when sqlite3_snapshot_get() is +** called, SQLITE_ERROR is returned. The final value of *P is undefined +** in this case. +** +**
      +**
    • The database handle must be in [autocommit mode]. +** +**
    • Schema S of [database connection] D must be a [WAL mode] database. +** +**
    • There must not be a write transaction open on schema S of database +** connection D. +** +**
    • One or more transactions must have been written to the current wal +** file since it was created on disk (by any connection). This means +** that a snapshot cannot be taken on a wal mode database with no wal +** file immediately after it is first opened. At least one transaction +** must be written to it first. +**
    +** +** This function may also return SQLITE_NOMEM. If it is called with the +** database handle in autocommit mode but fails for some other reason, +** whether or not a read transaction is opened on schema S is undefined. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] @@ -8524,7 +8594,7 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -8562,7 +8632,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -8579,7 +8649,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. @@ -8603,11 +8673,33 @@ SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3 ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_cmp( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); +/* +** CAPI3REF: Recover snapshots from a wal file +** EXPERIMENTAL +** +** If all connections disconnect from a database file but do not perform +** a checkpoint, the existing wal file is opened along with the database +** file the next time the database is opened. At this point it is only +** possible to successfully call sqlite3_snapshot_open() to open the most +** recent snapshot of the database (the one at the head of the wal file), +** even though the wal file may contain other valid snapshots for which +** clients have sqlite3_snapshot handles. +** +** This function attempts to scan the wal file associated with database zDb +** of database handle db and make all valid snapshots available to +** sqlite3_snapshot_open(). It is an error if there is already a read +** transaction open on the database, or if the database is not a wal mode +** database. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -8661,7 +8753,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -8687,7 +8779,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -8899,7 +8991,7 @@ int sqlite3session_attach( ** CAPI3REF: Set a table filter on a Session Object. ** ** The second argument (xFilter) is the "filter callback". For changes to rows -** in tables that are not attached to the Session oject, the filter is called +** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. @@ -9165,7 +9257,7 @@ int sqlite3session_isempty(sqlite3_session *pSession); ** [sqlite3changeset_invert()] functions, all changes within the changeset ** that apply to a single table are grouped together. This means that when ** an application iterates through a changeset using an iterator created by -** this function, all changes that relate to a single table are visted +** this function, all changes that relate to a single table are visited ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. @@ -9252,7 +9344,7 @@ int sqlite3changeset_op( ** 0x01 if the corresponding column is part of the tables primary key, or ** 0x00 if it is not. ** -** If argumet pnCol is not NULL, then *pnCol is set to the number of columns +** If argument pnCol is not NULL, then *pnCol is set to the number of columns ** in the table. ** ** If this function is called when the iterator does not point to a valid @@ -9469,12 +9561,12 @@ int sqlite3changeset_concat( /* -** Changegroup handle. +** CAPI3REF: Changegroup Handle */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* -** CAPI3REF: Combine two or more changesets into a single changeset. +** CAPI3REF: Create A New Changegroup Object ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -9511,6 +9603,8 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; int sqlite3changegroup_new(sqlite3_changegroup **pp); /* +** CAPI3REF: Add A Changeset To A Changegroup +** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. ** @@ -9525,7 +9619,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp); ** apply to the same row as a change already present in the changegroup if ** the two rows have the same primary key. ** -** Changes to rows that that do not already appear in the changegroup are +** Changes to rows that do not already appear in the changegroup are ** simply copied into it. Or, if both the new changeset and the changegroup ** contain changes that apply to a single row, the final contents of the ** changegroup depends on the type of each change, as follows: @@ -9586,6 +9680,8 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp); int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); /* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup ** were themselves changesets, the output is a changeset. Or, if the @@ -9614,7 +9710,7 @@ int sqlite3changegroup_output( ); /* -** Delete a changegroup object. +** CAPI3REF: Delete A Changegroup Object */ void sqlite3changegroup_delete(sqlite3_changegroup*); @@ -11391,9 +11487,9 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_LIMIT 129 #define TK_WHERE 130 #define TK_INTO 131 -#define TK_INTEGER 132 -#define TK_FLOAT 133 -#define TK_BLOB 134 +#define TK_FLOAT 132 +#define TK_BLOB 133 +#define TK_INTEGER 134 #define TK_VARIABLE 135 #define TK_CASE 136 #define TK_WHEN 137 @@ -11417,10 +11513,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_UMINUS 155 #define TK_UPLUS 156 #define TK_REGISTER 157 -#define TK_ASTERISK 158 -#define TK_SPAN 159 -#define TK_SPACE 160 -#define TK_ILLEGAL 161 +#define TK_VECTOR 158 +#define TK_SELECT_COLUMN 159 +#define TK_ASTERISK 160 +#define TK_SPAN 161 +#define TK_SPACE 162 +#define TK_ILLEGAL 163 /* The token codes above must all fit in 8 bits */ #define TKFLG_MASK 0xff @@ -11902,8 +12000,8 @@ struct BusyHandler { #define SQLITE_WSD const #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) -SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J); -SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L); +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); #else #define SQLITE_WSD #define GLOBAL(t,v) v @@ -11980,6 +12078,14 @@ typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; typedef struct With With; +/* A VList object records a mapping between parameters/variables/wildcards +** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer +** variable number associated with that parameter. See the format description +** on the sqlite3VListAdd() routine for more information. A VList is really +** just an array of integers. +*/ +typedef int VList; + /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque @@ -12079,7 +12185,9 @@ SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +#ifndef SQLITE_OMIT_SHARED_CACHE SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); +#endif SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); @@ -12262,6 +12370,8 @@ struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ const void *pData; /* Data for tables. NULL for indexes */ + struct Mem *aMem; /* First of nMem value in the unpacked pKey */ + u16 nMem; /* Number of aMem[] value. Might be zero */ int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; @@ -12274,16 +12384,18 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); +#ifndef SQLITE_OMIT_INCRBLOB +SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); +#endif SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); @@ -12293,6 +12405,7 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); #endif +SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*); #ifndef SQLITE_OMIT_BTREECOUNT SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); @@ -12444,7 +12557,6 @@ struct SubProgram { int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ - int nOnce; /* Number of OP_Once instructions */ void *token; /* id that may be used to recursive triggers */ SubProgram *pNext; /* Next sub-program already visited */ }; @@ -12467,22 +12579,21 @@ typedef struct VdbeOpList VdbeOpList; #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ -#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ -#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */ -#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_COLLSEQ (-3) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-4) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-5) /* P4 is a pointer to a KeyInfo structure */ +#define P4_EXPR (-6) /* P4 is a pointer to an Expr tree */ +#define P4_MEM (-7) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ -#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ -#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ -#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ -#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ -#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ -#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ -#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ -#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_TABLE (-20) /* P4 is a pointer to a Table structure */ -#define P4_FUNCCTX (-21) /* P4 is a pointer to an sqlite3_context object */ +#define P4_VTAB (-8) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_REAL (-9) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-10) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-11) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-12) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-13) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-14) /* P4 is a pointer to BtreeNext() or BtreePrev() */ +#define P4_TABLE (-15) /* P4 is a pointer to a Table structure */ +#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -12561,13 +12672,13 @@ typedef struct VdbeOpList VdbeOpList; #define OP_NotExists 33 /* synopsis: intkey=r[P3] */ #define OP_IsNull 34 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ #define OP_NotNull 35 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 36 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ -#define OP_Eq 37 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ -#define OP_Gt 38 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ -#define OP_Le 39 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ -#define OP_Lt 40 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ -#define OP_Last 42 +#define OP_Ne 36 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +#define OP_Eq 37 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */ +#define OP_Gt 38 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */ +#define OP_Le 39 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */ +#define OP_Lt 40 /* same as TK_LT, synopsis: IF r[P3]=r[P1] */ +#define OP_ElseNotEq 42 /* same as TK_ESCAPE */ #define OP_BitAnd 43 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ #define OP_BitOr 44 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ #define OP_ShiftLeft 45 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<0 then r[P1]-=P3, goto P2 */ -#define OP_IfNotZero 66 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ -#define OP_DecrJumpZero 67 /* synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 68 -#define OP_VNext 69 -#define OP_Init 70 /* synopsis: Start at P2 */ -#define OP_Return 71 -#define OP_EndCoroutine 72 -#define OP_HaltIfNull 73 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 74 -#define OP_Integer 75 /* synopsis: r[P2]=P1 */ -#define OP_Int64 76 /* synopsis: r[P2]=P4 */ -#define OP_String 77 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 78 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 79 /* synopsis: r[P1]=NULL */ -#define OP_Blob 80 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 81 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 82 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 83 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 84 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 85 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 86 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 87 -#define OP_Function0 88 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Function 89 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_AddImm 90 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 91 -#define OP_Cast 92 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 93 -#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_Column 95 /* synopsis: r[P3]=PX */ -#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */ +#define OP_SorterSort 55 +#define OP_Sort 56 +#define OP_Rewind 57 +#define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */ +#define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */ +#define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 64 +#define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +#define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +#define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */ +#define OP_IncrVacuum 69 +#define OP_VNext 70 +#define OP_Init 71 /* synopsis: Start at P2 */ +#define OP_Return 72 +#define OP_EndCoroutine 73 +#define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 75 +#define OP_Integer 76 /* synopsis: r[P2]=P1 */ +#define OP_Int64 77 /* synopsis: r[P2]=P4 */ +#define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 79 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 80 /* synopsis: r[P1]=NULL */ +#define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 88 +#define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 92 +#define OP_Cast 93 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 94 +#define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_Column 96 /* synopsis: r[P3]=PX */ #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_MakeRecord 98 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 99 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 100 -#define OP_SetCookie 101 -#define OP_ReopenIdx 102 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 103 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 104 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenAutoindex 105 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 106 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 107 -#define OP_SequenceTest 108 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 109 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 110 -#define OP_ColumnsUsed 111 -#define OP_Sequence 112 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 113 /* synopsis: r[P2]=rowid */ -#define OP_Insert 114 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_InsertInt 115 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 116 -#define OP_ResetCount 117 -#define OP_SorterCompare 118 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 119 /* synopsis: r[P2]=data */ -#define OP_RowKey 120 /* synopsis: r[P2]=key */ +#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 100 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 101 +#define OP_SetCookie 102 +#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 108 +#define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 111 +#define OP_ColumnsUsed 112 +#define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 114 /* synopsis: r[P2]=rowid */ +#define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 117 +#define OP_ResetCount 118 +#define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 120 /* synopsis: r[P2]=data */ #define OP_RowData 121 /* synopsis: r[P2]=data */ #define OP_Rowid 122 /* synopsis: r[P2]=rowid */ #define OP_NullRow 123 -#define OP_SorterInsert 124 +#define OP_SorterInsert 124 /* synopsis: key=r[P2] */ #define OP_IdxInsert 125 /* synopsis: key=r[P2] */ #define OP_IdxDelete 126 /* synopsis: key=r[P2@P3] */ #define OP_Seek 127 /* synopsis: Move P3 to P1.rowid */ @@ -12657,8 +12768,8 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Destroy 129 #define OP_Clear 130 #define OP_ResetSorter 131 -#define OP_CreateIndex 132 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_CreateIndex 133 /* synopsis: r[P2]=root iDb=P1 */ #define OP_CreateTable 134 /* synopsis: r[P2]=root iDb=P1 */ #define OP_ParseSchema 135 #define OP_LoadAnalysis 136 @@ -12706,14 +12817,14 @@ typedef struct VdbeOpList VdbeOpList; /* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\ /* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\ -/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b, 0x01,\ -/* 64 */ 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x02,\ -/* 72 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\ -/* 80 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ -/* 88 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\ -/* 96 */ 0x00, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\ +/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\ +/* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\ +/* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\ +/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\ +/* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ +/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 120 */ 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00,\ /* 128 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\ @@ -12727,7 +12838,7 @@ typedef struct VdbeOpList VdbeOpList; ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 70 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -12764,6 +12875,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type); SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); @@ -12799,7 +12911,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); -SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); @@ -13004,7 +13116,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int, void(*)(DbPage*) ); -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ @@ -13055,15 +13167,19 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); #ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); # ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); +SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); # endif +#else +# define sqlite3PagerUseWal(x) 0 #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -13696,7 +13812,7 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *); ** databases may be attached. */ struct Db { - char *zName; /* Name of this database */ + char *zDbSName; /* Name of this database. (schema name, not filename) */ Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ @@ -14034,6 +14150,7 @@ struct sqlite3 { #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ +#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ /* @@ -14059,13 +14176,8 @@ struct sqlite3 { /* ** Macros for testing whether or not optimizations are enabled or disabled. */ -#ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) -#else -#define OptimizationDisabled(db, mask) 0 -#define OptimizationEnabled(db, mask) 1 -#endif /* ** Return true if it OK to factor constant expressions into the initialization @@ -14332,6 +14444,7 @@ struct CollSeq { ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ +#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */ #define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ @@ -14403,9 +14516,9 @@ struct Table { ExprList *pCheck; /* All CHECK constraints */ /* ... also used as column name list in a VIEW */ int tnum; /* Root BTree page for this table */ + u32 nTabRef; /* Number of pointers to this Table */ i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 nCol; /* Number of columns in this table */ - u16 nRef; /* Number of pointers to this Table */ LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT @@ -14896,9 +15009,11 @@ struct Expr { int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old - ** EP_Unlikely: 134217728 times likelihood */ + ** EP_Unlikely: 134217728 times likelihood + ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. - ** TK_VARIABLE: variable number (always >= 1). */ + ** TK_VARIABLE: variable number (always >= 1). + ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op @@ -14934,6 +15049,7 @@ struct Expr { #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ +#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ /* ** Combinations of two or more EP_* flags @@ -15379,7 +15495,7 @@ struct Select { */ struct SelectDest { u8 eDest; /* How to dispose of the results. On of SRT_* above. */ - char affSdst; /* Affinity used when eDest==SRT_Set */ + char *zAffSdst; /* Affinity used when eDest==SRT_Set */ int iSDParm; /* A parameter used by the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ @@ -15485,36 +15601,23 @@ struct Parse { u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 nColCache; /* Number of entries in aColCache[] */ - int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ - int nSet; /* Number of sets used so far */ - int nOnce; /* Number of OP_Once instructions so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ int ckBase; /* Base register of data during check constraints */ int iSelfTab; /* Table of an index whose exprs are being coded */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ - struct yColCache { - int iTable; /* Table cursor number */ - i16 iColumn; /* Table column number */ - u8 tempReg; /* iReg is a temp register that needs to be freed */ - int iLevel; /* Nesting level */ - int iReg; /* Reg with value of this column. 0 means none. */ - int lru; /* Least recently used entry has the smallest value */ - } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ ExprList *pConstExpr;/* Constant expressions */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ - int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ @@ -15527,8 +15630,6 @@ struct Parse { TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ - - /* Information used while coding trigger programs. */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ @@ -15539,35 +15640,50 @@ struct Parse { u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ + /************************************************************************** + ** Fields above must be initialized to zero. The fields that follow, + ** down to the beginning of the recursive section, do not need to be + ** initialized as they will be set before being used. The boundary is + ** determined by offsetof(Parse,aColCache). + **************************************************************************/ + + struct yColCache { + int iTable; /* Table cursor number */ + i16 iColumn; /* Table column number */ + u8 tempReg; /* iReg is a temp register that needs to be freed */ + int iLevel; /* Nesting level */ + int iReg; /* Reg with value of this column. 0 means none. */ + int lru; /* Least recently used entry has the smallest value */ + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ + int aTempReg[8]; /* Holding area for temporary registers */ + Token sNameToken; /* Token with unqualified schema object name */ + /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined - ** using offsetof(Parse,nVar) so the nVar field must be the first field - ** in the recursive region. + ** using offsetof(Parse,sLastToken) so the sLastToken field must be the + ** first field in the recursive region. ************************************************************************/ + Token sLastToken; /* The last token parsed */ ynVar nVar; /* Number of '?' variables seen in the SQL so far */ - int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ #endif - int nAlias; /* Number of aliased result set columns */ int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN int iSelectId; /* ID of current select for EXPLAIN output */ int iNextSelectId; /* Next available select ID for EXPLAIN output */ #endif - char **azVar; /* Pointers to names of parameters */ + VList *pVList; /* Mapping between variable names and numbers */ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ - Token sNameToken; /* Token with unqualified schema object name */ - Token sLastToken; /* The last token parsed */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ @@ -15578,6 +15694,14 @@ struct Parse { With *pWithToFree; /* Free this WITH object at the end of the parse */ }; +/* +** Sizes and pointers of various parts of the Parse object. +*/ +#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ +#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ +#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ +#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ + /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ @@ -15822,10 +15946,11 @@ struct Sqlite3Config { void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ void *pVdbeBranchArg; /* 1st argument */ #endif -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int iOnceResetThreshold; /* When to reset OP_Once counters */ }; /* @@ -16025,7 +16150,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void*); SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); #endif SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); @@ -16111,6 +16236,7 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); +SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); @@ -16135,13 +16261,14 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); -SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); +SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); @@ -16150,6 +16277,9 @@ SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); +#ifndef SQLITE_OMIT_VIRTUALTABLE +SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); +#endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); @@ -16177,9 +16307,8 @@ SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); -SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); -#ifdef SQLITE_OMIT_BUILTIN_TEST +#ifdef SQLITE_UNTESTABLE # define sqlite3FaultSim(X) SQLITE_OK #else SQLITE_PRIVATE int sqlite3FaultSim(int); @@ -16192,7 +16321,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); #endif @@ -16289,6 +16418,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ +#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); @@ -16300,8 +16430,8 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_ite SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3Vacuum(Parse*); -SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*); +SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); +SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); @@ -16311,7 +16441,7 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); #endif @@ -16448,6 +16578,9 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); #endif +SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); +SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); +SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); /* ** Routines to read and write variable-length integers. These used to @@ -16477,6 +16610,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*); SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table*,int); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); @@ -16542,7 +16676,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); +SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); @@ -16597,12 +16731,20 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); +#ifndef SQLITE_OMIT_SUBQUERY +SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*); +#else +# define sqlite3ExprCheckIN(x,y) SQLITE_OK +#endif + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void); -SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*); +SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( + Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*); SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); +SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); #endif /* @@ -16655,6 +16797,13 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int); SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); +SQLITE_PRIVATE Module *sqlite3VtabCreateModule( + sqlite3*, + const char*, + const sqlite3_module*, + void*, + void(*)(void*) + ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); @@ -16730,10 +16879,10 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); /* ** The interface to the code in fault.c used for identifying "benign" -** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST +** malloc failures. This is only present if SQLITE_UNTESTABLE ** is not defined. */ -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void); SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); #else @@ -16755,7 +16904,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); #define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ #define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ #define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*); +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*); SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); @@ -16860,6 +17009,12 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); #endif +SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr); +SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr); +SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); +SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int); +SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); + #endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ @@ -16945,16 +17100,13 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { ** ** (x & ~(map[x]&0x20)) ** -** Standard function tolower() is implemented using the sqlite3UpperToLower[] +** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] ** array. tolower() is used more often than toupper() by SQLite. ** -** Bit 0x40 is set if the character non-alphanumeric and can be used in an +** Bit 0x40 is set if the character is non-alphanumeric and can be used in an ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any ** non-ASCII UTF character. Hence the test for whether or not a character is ** part of an identifier is 0x46. -** -** SQLite's versions are identical to the standard versions assuming a -** locale of "C". They are implemented as macros in sqliteInt.h. */ #ifdef SQLITE_ASCII SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { @@ -17027,7 +17179,7 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { #endif /* Statement journals spill to disk when their size exceeds the following -** threashold (in bytes). 0 means that statement journals are created and +** threshold (in bytes). 0 means that statement journals are created and ** written to disk immediately (the default behavior for SQLite versions ** before 3.12.0). -1 means always keep the entire statement journal in ** memory. (The statement journal is also always held entirely in memory @@ -17050,8 +17202,8 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ - 128, /* szLookaside */ - 500, /* nLookaside */ + 512, /* szLookaside */ + 125, /* nLookaside */ SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ @@ -17088,10 +17240,11 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif - 0 /* bLocaltimeFault */ + 0, /* bLocaltimeFault */ + 0x7ffffffe /* iOnceResetThreshold */ }; /* @@ -17114,7 +17267,7 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = { ** The value of the "pending" byte must be 0x40000000 (1 byte past the ** 1-gibabyte boundary) in a compatible database. SQLite never uses ** the database page that contains the pending byte. It never attempts -** to read or write that page. The pending byte page is set assign +** to read or write that page. The pending byte page is set aside ** for use by the VFS layers as space for managing file locks. ** ** During testing, it is often desirable to move the pending byte to @@ -17216,6 +17369,9 @@ static const char * const azCompileOpt[] = { #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif +#if SQLITE_DIRECT_OVERFLOW_READ + "DIRECT_OVERFLOW_READ", +#endif #if SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif @@ -17302,6 +17458,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", #endif +#if defined(SQLITE_ENABLE_URI_00_ERROR) + "ENABLE_URI_00_ERROR", +#endif #if SQLITE_HAS_CODEC "HAS_CODEC", #endif @@ -17377,9 +17536,6 @@ static const char * const azCompileOpt[] = { #if SQLITE_OMIT_BTREECOUNT "OMIT_BTREECOUNT", #endif -#if SQLITE_OMIT_BUILTIN_TEST - "OMIT_BUILTIN_TEST", -#endif #if SQLITE_OMIT_CAST "OMIT_CAST", #endif @@ -17542,6 +17698,9 @@ static const char * const azCompileOpt[] = { #if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #endif +#if SQLITE_UNTESTABLE + "UNTESTABLE" +#endif #if SQLITE_USE_ALLOCA "USE_ALLOCA", #endif @@ -17563,7 +17722,7 @@ static const char * const azCompileOpt[] = { ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix ** is not required for a match. */ -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int i, n; #if SQLITE_ENABLE_API_ARMOR @@ -17591,7 +17750,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ ** Return the N-th compile-time option string. If N is out of range, ** return a NULL pointer. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N){ +SQLITE_API const char *sqlite3_compileoption_get(int N){ if( N>=0 && NaDb[] (or -1) */ - u8 nullRow; /* True if pointing to a row with no data */ - u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ - u8 isTable; /* True for rowid tables. False for indexes */ + u8 eCurType; /* One of the CURTYPE_* values above */ + i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ + u8 nullRow; /* True if pointing to a row with no data */ + u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ + u8 isTable; /* True for rowid tables. False for indexes */ #ifdef SQLITE_DEBUG - u8 seekOp; /* Most recent seek operation on this cursor */ - u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ + u8 seekOp; /* Most recent seek operation on this cursor */ + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif - Bool isEphemeral:1; /* True for an ephemeral table */ - Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ - Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ - Pgno pgnoRoot; /* Root page of the open btree cursor */ - i16 nField; /* Number of fields in the header */ - u16 nHdrParsed; /* Number of header fields parsed so far */ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ + Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ + Btree *pBtx; /* Separate file holding temporary table */ + i64 seqCount; /* Sequence counter */ + int *aAltMap; /* Mapping from table to index column numbers */ + + /* Cached OP_Column parse information is only valid if cacheStatus matches + ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of + ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that + ** the cache is out of date. */ + u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 + ** if there have been no prior seeks on the cursor. */ + /* NB: seekResult does not distinguish between "no seeks have ever occurred + ** on this cursor" and "the most recent seek was an exact match". */ + + /* When a new VdbeCursor is allocated, only the fields above are zeroed. + ** The fields that follow are uninitialized, and must be individually + ** initialized prior to first use. */ + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ union { BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ } uc; - Btree *pBt; /* Separate file holding temporary table */ - KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ - int seekResult; /* Result of previous sqlite3BtreeMoveto() */ - i64 seqCount; /* Sequence counter */ - i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ - VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ - int *aAltMap; /* Mapping from table to index column numbers */ + KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ + u32 iHdrOffset; /* Offset to next unparsed byte of the header */ + Pgno pgnoRoot; /* Root page of the open btree cursor */ + i16 nField; /* Number of fields in the header */ + u16 nHdrParsed; /* Number of header fields parsed so far */ + i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + u32 *aOffset; /* Pointer to aType[nField] */ + const u8 *aRow; /* Data for the current row, if all on one page */ + u32 payloadSize; /* Total number of bytes in the record */ + u32 szRow; /* Byte available in aRow */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK - u64 maskUsed; /* Mask of columns used by this cursor */ + u64 maskUsed; /* Mask of columns used by this cursor */ #endif - /* Cached information about the header for the data record that the - ** cursor is currently pointing to. Only valid if cacheStatus matches - ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of - ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that - ** the cache is out of date. - ** - ** aRow might point to (ephemeral) data for the current row, or it might - ** be NULL. - */ - u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ - u32 payloadSize; /* Total number of bytes in the record */ - u32 szRow; /* Byte available in aRow */ - u32 iHdrOffset; /* Offset to next unparsed byte of the header */ - const u8 *aRow; /* Data for the current row, if all on one page */ - u32 *aOffset; /* Pointer to aType[nField] */ - u32 aType[1]; /* Type values for all entries in the record */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ + u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; + +/* +** A value for VdbeCursor.cacheStatus that means the cache is always invalid. +*/ +#define CACHE_STALE 0 + /* ** When a sub-program is executed (OP_Program), a structure of this type ** is allocated to store the current value of the program counter, as @@ -17779,7 +17944,6 @@ struct VdbeFrame { Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ - u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ @@ -17788,7 +17952,6 @@ struct VdbeFrame { int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ - int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ int nChange; /* Statement changes (Vdbe.nChange) */ @@ -17797,11 +17960,6 @@ struct VdbeFrame { #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) -/* -** A value for VdbeCursor.cacheValid that means the cache is always invalid. -*/ -#define CACHE_STALE 0 - /* ** Internally, the vdbe manipulates nearly all SQL values as Mem ** structures. Each Mem struct may cache multiple representations (string, @@ -17942,18 +18100,6 @@ struct sqlite3_context { sqlite3_value *argv[1]; /* Argument set */ }; -/* -** An Explain object accumulates indented output which is helpful -** in describing recursive data structures. -*/ -struct Explain { - Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ - StrAccum str; /* The string being accumulated */ - int nIndent; /* Number of elements in aIndent */ - u16 aIndent[100]; /* Levels of indentation */ - char zBase[100]; /* Initial space */ -}; - /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ @@ -17978,34 +18124,46 @@ struct ScanStatus { */ struct Vdbe { sqlite3 *db; /* The database connection that owns this statement */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ + Parse *pParse; /* Parsing context used to create this Vdbe */ + ynVar nVar; /* Number of entries in aVar[] */ + u32 magic; /* Magic number for sanity checking */ + int nMem; /* Number of memory locations currently allocated */ + int nCursor; /* Number of slots in apCsr[] */ + u32 cacheCtr; /* VdbeCursor row cache generation counter */ + int pc; /* The program counter */ + int rc; /* Value to return */ + int nChange; /* Number of db changes made since last reset */ + int iStatement; /* Statement number (or 0 if has not opened stmt) */ + i64 iCurrentTime; /* Value of julianday('now') for this statement */ + i64 nFkConstraint; /* Number of imm. FK constraints this VM */ + i64 nStmtDefCons; /* Number of def. constraints when stmt started */ + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ + + /* When allocating a new Vdbe object, all of the fields below should be + ** initialized to zero or NULL */ + Op *aOp; /* Space to hold the virtual machine's program */ Mem *aMem; /* The memory locations */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ Mem *pResultSet; /* Pointer to an array of results */ - Parse *pParse; /* Parsing context used to create this Vdbe */ - int nMem; /* Number of memory locations currently allocated */ - int nOp; /* Number of instructions in the program */ - int nCursor; /* Number of slots in apCsr[] */ - u32 magic; /* Magic number for sanity checking */ char *zErrMsg; /* Error message written here */ - Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ VdbeCursor **apCsr; /* One element of this array for each open cursor */ Mem *aVar; /* Values for the OP_Variable opcode. */ - char **azVar; /* Name of variables */ - ynVar nVar; /* Number of entries in aVar[] */ - ynVar nzVar; /* Number of entries in azVar[] */ - u32 cacheCtr; /* VdbeCursor row cache generation counter */ - int pc; /* The program counter */ - int rc; /* Value to return */ + VList *pVList; /* Name of variables */ +#ifndef SQLITE_OMIT_TRACE + i64 startTime; /* Time when query started - used for profiling */ +#endif + int nOp; /* Number of instructions in the program */ #ifdef SQLITE_DEBUG int rcApp; /* errcode set by sqlite3_result_error_code() */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft expired:1; /* True if the VM needs to be recompiled */ bft doingRerun:1; /* True if rerunning after an auto-reprepare */ - u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ @@ -18013,18 +18171,9 @@ struct Vdbe { bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ bft isPrepareV2:1; /* True if prepared with prepare_v2() */ - int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - int iStatement; /* Statement number (or 0 if has not opened stmt) */ u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ -#ifndef SQLITE_OMIT_TRACE - i64 startTime; /* Time when query started - used for profiling */ -#endif - i64 iCurrentTime; /* Value of julianday('now') for this statement */ - i64 nFkConstraint; /* Number of imm. FK constraints this VM */ - i64 nStmtDefCons; /* Number of def. constraints when stmt started */ - i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ @@ -18032,8 +18181,6 @@ struct Vdbe { int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ - int nOnceFlag; /* Size of array aOnceFlag[] */ - u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS i64 *anExec; /* Number of times each op has been executed */ @@ -18045,10 +18192,11 @@ struct Vdbe { /* ** The following are allowed values for Vdbe.magic */ -#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ -#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ -#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ -#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ +#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ +#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ +#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ +#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ /* ** Structure used to store the context required by the @@ -18065,8 +18213,8 @@ struct PreUpdate { int iNewReg; /* Register for new.* values */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ - int iPKey; /* If not negative index of IPK column */ Mem *aNew; /* Array of new.* values */ + Table *pTab; /* Schema object being upated */ }; /* @@ -18119,7 +18267,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); @@ -18301,7 +18449,7 @@ SQLITE_PRIVATE void sqlite3StatusHighwater(int op, int X){ /* ** Query status information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_status64( +SQLITE_API int sqlite3_status64( int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, @@ -18326,7 +18474,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ sqlite3_int64 iCur = 0, iHwtr = 0; int rc; #ifdef SQLITE_ENABLE_API_ARMOR @@ -18343,7 +18491,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwa /* ** Query status information for a single database connection */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status( +SQLITE_API int sqlite3_db_status( sqlite3 *db, /* The database connection whose status is desired */ int op, /* Status verb */ int *pCurrent, /* Write current value here */ @@ -18588,16 +18736,18 @@ struct tm *__cdecl localtime(const time_t *); */ typedef struct DateTime DateTime; struct DateTime { - sqlite3_int64 iJD; /* The julian day number times 86400000 */ - int Y, M, D; /* Year, month, and day */ - int h, m; /* Hour and minutes */ - int tz; /* Timezone offset in minutes */ - double s; /* Seconds */ - char validYMD; /* True (1) if Y,M,D are valid */ - char validHMS; /* True (1) if h,m,s are valid */ - char validJD; /* True (1) if iJD is valid */ - char validTZ; /* True (1) if tz is valid */ - char tzSet; /* Timezone was set explicitly */ + sqlite3_int64 iJD; /* The julian day number times 86400000 */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validJD; /* True (1) if iJD is valid */ + char rawS; /* Raw numeric value stored in s */ + char validYMD; /* True (1) if Y,M,D are valid */ + char validHMS; /* True (1) if h,m,s are valid */ + char validTZ; /* True (1) if tz is valid */ + char tzSet; /* Timezone was set explicitly */ + char isError; /* An overflow has occurred */ }; @@ -18745,6 +18895,7 @@ static int parseHhMmSs(const char *zDate, DateTime *p){ s = 0; } p->validJD = 0; + p->rawS = 0; p->validHMS = 1; p->h = h; p->m = m; @@ -18754,6 +18905,14 @@ static int parseHhMmSs(const char *zDate, DateTime *p){ return 0; } +/* +** Put the DateTime object into its error state. +*/ +static void datetimeError(DateTime *p){ + memset(p, 0, sizeof(*p)); + p->isError = 1; +} + /* ** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume ** that the YYYY-MM-DD is according to the Gregorian calendar. @@ -18773,6 +18932,10 @@ static void computeJD(DateTime *p){ M = 1; D = 1; } + if( Y<-4713 || Y>9999 || p->rawS ){ + datetimeError(p); + return; + } if( M<=2 ){ Y--; M += 12; @@ -18853,6 +19016,21 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ } } +/* +** Input "r" is a numeric quantity which might be a julian day number, +** or the number of seconds since 1970. If the value if r is within +** range of a julian day number, install it as such and set validJD. +** If the value is a valid unix timestamp, put it in p->s and set p->rawS. +*/ +static void setRawDateNumber(DateTime *p, double r){ + p->s = r; + p->rawS = 1; + if( r>=0.0 && r<5373484.5 ){ + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; + } +} + /* ** Attempt to parse the given string into a julian day number. Return ** the number of errors. @@ -18882,13 +19060,30 @@ static int parseDateOrTime( }else if( sqlite3StrICmp(zDate,"now")==0){ return setDateTimeToCurrent(context, p); }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ - p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); - p->validJD = 1; + setRawDateNumber(p, r); return 0; } return 1; } +/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999. +** Multiplying this by 86400000 gives 464269060799999 as the maximum value +** for DateTime.iJD. +** +** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with +** such a large integer literal, so we have to encode it. +*/ +#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff) + +/* +** Return TRUE if the given julian day number is within range. +** +** The input is the JulianDay times 86400000. +*/ +static int validJulianDay(sqlite3_int64 iJD){ + return iJD>=0 && iJD<=INT_464269060799999; +} + /* ** Compute the Year, Month, and Day from the julian day number. */ @@ -18900,6 +19095,7 @@ static void computeYMD(DateTime *p){ p->M = 1; p->D = 1; }else{ + assert( validJulianDay(p->iJD) ); Z = (int)((p->iJD + 43200000)/86400000); A = (int)((Z - 1867216.25)/36524.25); A = Z + 1 + A - (A/4); @@ -18930,6 +19126,7 @@ static void computeHMS(DateTime *p){ s -= p->h*3600; p->m = s/60; p->s += s - p->m*60; + p->rawS = 0; p->validHMS = 1; } @@ -18991,14 +19188,14 @@ static int osLocaltime(time_t *t, struct tm *pTm){ #endif sqlite3_mutex_enter(mutex); pX = localtime(t); -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; sqlite3_mutex_leave(mutex); rc = pX==0; #else -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif #if HAVE_LOCALTIME_R @@ -19069,13 +19266,38 @@ static sqlite3_int64 localtimeOffset( y.validYMD = 1; y.validHMS = 1; y.validJD = 0; + y.rawS = 0; y.validTZ = 0; + y.isError = 0; computeJD(&y); *pRc = SQLITE_OK; return y.iJD - x.iJD; } #endif /* SQLITE_OMIT_LOCALTIME */ +/* +** The following table defines various date transformations of the form +** +** 'NNN days' +** +** Where NNN is an arbitrary floating-point number and "days" can be one +** of several units of time. +*/ +static const struct { + u8 eType; /* Transformation type code */ + u8 nName; /* Length of th name */ + char *zName; /* Name of the transformation */ + double rLimit; /* Maximum NNN value for this transform */ + double rXform; /* Constant used for this transform */ +} aXformType[] = { + { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) }, + { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) }, + { 0, 4, "hour", 128963628.0, 86400000.0/24.0 }, + { 0, 3, "day", 5373485.0, 86400000.0 }, + { 1, 5, "month", 176546.0, 30.0*86400000.0 }, + { 2, 4, "year", 14713.0, 365.0*86400000.0 }, +}; + /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: @@ -19100,17 +19322,15 @@ static sqlite3_int64 localtimeOffset( ** to context pCtx. If the error is an unrecognized modifier, no error is ** written to pCtx. */ -static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ +static int parseModifier( + sqlite3_context *pCtx, /* Function context */ + const char *z, /* The text of the modifier */ + int n, /* Length of zMod in bytes */ + DateTime *p /* The date/time value to be modified */ +){ int rc = 1; - int n; double r; - char *z, zBuf[30]; - z = zBuf; - for(n=0; niJD += localtimeOffset(p, pCtx, &rc); clearYMD_HMS_TZ(p); @@ -19130,16 +19350,21 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ /* ** unixepoch ** - ** Treat the current value of p->iJD as the number of + ** Treat the current value of p->s as the number of ** seconds since 1970. Convert to a real julian day number. */ - if( strcmp(z, "unixepoch")==0 && p->validJD ){ - p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000; - clearYMD_HMS_TZ(p); - rc = 0; + if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ + r = p->s*1000.0 + 210866760000000.0; + if( r>=0.0 && r<464269060800000.0 ){ + clearYMD_HMS_TZ(p); + p->iJD = (sqlite3_int64)r; + p->validJD = 1; + p->rawS = 0; + rc = 0; + } } #ifndef SQLITE_OMIT_LOCALTIME - else if( strcmp(z, "utc")==0 ){ + else if( sqlite3_stricmp(z, "utc")==0 ){ if( p->tzSet==0 ){ sqlite3_int64 c1; computeJD(p); @@ -19165,7 +19390,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ ** weekday N where 0==Sunday, 1==Monday, and so forth. If the ** date is already on the appropriate weekday, this is a no-op. */ - if( strncmp(z, "weekday ", 8)==0 + if( sqlite3_strnicmp(z, "weekday ", 8)==0 && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) && (n=(int)r)==r && n>=0 && r<7 ){ sqlite3_int64 Z; @@ -19188,7 +19413,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ ** Move the date backwards to the beginning of the current day, ** or month or year. */ - if( strncmp(z, "start of ", 9)!=0 ) break; + if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; z += 9; computeYMD(p); p->validHMS = 1; @@ -19196,15 +19421,15 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ p->s = 0.0; p->validTZ = 0; p->validJD = 0; - if( strcmp(z,"month")==0 ){ + if( sqlite3_stricmp(z,"month")==0 ){ p->D = 1; rc = 0; - }else if( strcmp(z,"year")==0 ){ + }else if( sqlite3_stricmp(z,"year")==0 ){ computeYMD(p); p->M = 1; p->D = 1; rc = 0; - }else if( strcmp(z,"day")==0 ){ + }else if( sqlite3_stricmp(z,"day")==0 ){ rc = 0; } break; @@ -19222,6 +19447,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ case '8': case '9': { double rRounder; + int i; for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ rc = 1; @@ -19250,46 +19476,48 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ rc = 0; break; } + + /* If control reaches this point, it means the transformation is + ** one of the forms like "+NNN days". */ z += n; while( sqlite3Isspace(*z) ) z++; n = sqlite3Strlen30(z); if( n>10 || n<3 ) break; - if( z[n-1]=='s' ){ z[n-1] = 0; n--; } + if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; computeJD(p); - rc = 0; + rc = 1; rRounder = r<0 ? -0.5 : +0.5; - if( n==3 && strcmp(z,"day")==0 ){ - p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder); - }else if( n==4 && strcmp(z,"hour")==0 ){ - p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder); - }else if( n==6 && strcmp(z,"minute")==0 ){ - p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder); - }else if( n==6 && strcmp(z,"second")==0 ){ - p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder); - }else if( n==5 && strcmp(z,"month")==0 ){ - int x, y; - computeYMD_HMS(p); - p->M += (int)r; - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - p->validJD = 0; - computeJD(p); - y = (int)r; - if( y!=r ){ - p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder); + for(i=0; i-aXformType[i].rLimit && rM += (int)r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + r -= (int)r; + break; + } + case 2: { /* Special processing to add years */ + int y = (int)r; + computeYMD_HMS(p); + p->Y += y; + p->validJD = 0; + r -= (int)r; + break; + } + } + computeJD(p); + p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder); + rc = 0; + break; } - }else if( n==4 && strcmp(z,"year")==0 ){ - int y = (int)r; - computeYMD_HMS(p); - p->Y += y; - p->validJD = 0; - computeJD(p); - if( y!=r ){ - p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder); - } - }else{ - rc = 1; } clearYMD_HMS_TZ(p); break; @@ -19316,7 +19544,7 @@ static int isDate( sqlite3_value **argv, DateTime *p ){ - int i; + int i, n; const unsigned char *z; int eType; memset(p, 0, sizeof(*p)); @@ -19325,8 +19553,7 @@ static int isDate( } if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT || eType==SQLITE_INTEGER ){ - p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5); - p->validJD = 1; + setRawDateNumber(p, sqlite3_value_double(argv[0])); }else{ z = sqlite3_value_text(argv[0]); if( !z || parseDateOrTime(context, (char*)z, p) ){ @@ -19335,8 +19562,11 @@ static int isDate( } for(i=1; iisError || !validJulianDay(p->iJD) ) return 1; return 0; } @@ -20020,7 +20250,7 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0; ** Locate a VFS by name. If no name is given, simply return the ** first VFS on the list. */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ sqlite3_vfs *pVfs = 0; #if SQLITE_THREADSAFE sqlite3_mutex *mutex; @@ -20066,7 +20296,7 @@ static void vfsUnlink(sqlite3_vfs *pVfs){ ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ MUTEX_LOGIC(sqlite3_mutex *mutex;) #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -20094,7 +20324,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDf /* ** Unregister a VFS so that it is no longer accessible. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -20134,7 +20364,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ /* #include "sqliteInt.h" */ -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE /* ** Global variables. @@ -20192,7 +20422,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ } } -#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */ +#endif /* #ifndef SQLITE_UNTESTABLE */ /************** End of fault.c ***********************************************/ /************** Begin file mem0.c ********************************************/ @@ -22445,7 +22675,7 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){ /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ #ifndef SQLITE_OMIT_AUTOINIT if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; @@ -22466,7 +22696,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ /* ** Free a dynamic mutex. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexFree ); sqlite3GlobalConfig.mutex.xMutexFree(p); @@ -22477,7 +22707,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ ** Obtain the mutex p. If some other thread already has the mutex, block ** until it can be obtained. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexEnter ); sqlite3GlobalConfig.mutex.xMutexEnter(p); @@ -22488,7 +22718,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ int rc = SQLITE_OK; if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexTry ); @@ -22503,7 +22733,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexLeave ); sqlite3GlobalConfig.mutex.xMutexLeave(p); @@ -22515,11 +22745,11 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); } -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); } @@ -23551,8 +23781,8 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */ */ static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ +SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ @@ -23852,7 +24082,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){ +SQLITE_API int sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT return sqlite3PcacheReleaseMemory(n); #else @@ -23911,7 +24141,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ ** that was invoked when memory usage grew too large. Now it is a ** no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( +SQLITE_API int sqlite3_memory_alarm( void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, sqlite3_int64 iThreshold @@ -23927,7 +24157,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( ** Set the soft heap-size limit for the library. Passing a zero or ** negative value indicates no limit. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ sqlite3_int64 priorLimit; sqlite3_int64 excess; sqlite3_int64 nUsed; @@ -23949,7 +24179,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); return priorLimit; } -SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ +SQLITE_API void sqlite3_soft_heap_limit(int n){ if( n<0 ) n = 0; sqlite3_soft_heap_limit64(n); } @@ -24018,7 +24248,7 @@ SQLITE_PRIVATE void sqlite3MallocEnd(void){ /* ** Return the amount of memory currently checked out. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void){ sqlite3_int64 res, mx; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0); return res; @@ -24029,7 +24259,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){ +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 res, mx; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag); return mx; @@ -24109,13 +24339,13 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ ** First make sure the memory subsystem is initialized, then do the ** allocation. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){ +SQLITE_API void *sqlite3_malloc(int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif return n<=0 ? 0 : sqlite3Malloc(n); } -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){ +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -24258,7 +24488,7 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ return db->lookaside.sz; } } -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ +SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return p ? sqlite3GlobalConfig.m.xSize(p) : 0; @@ -24267,7 +24497,7 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ /* ** Free memory previously obtained from sqlite3Malloc(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ +SQLITE_API void sqlite3_free(void *p){ if( p==0 ) return; /* IMP: R-49053-54554 */ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); @@ -24351,7 +24581,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ sqlite3_mutex_enter(mem0.mutex); sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); nDiff = nNew - nOld; - if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= + if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= mem0.alarmThreshold-nDiff ){ sqlite3MallocAlarm(nDiff); } @@ -24376,14 +24606,14 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ ** The public interface to sqlite3Realloc. Make sure that the memory ** subsystem is initialized prior to invoking sqliteRealloc. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){ +SQLITE_API void *sqlite3_realloc(void *pOld, int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif if( n<0 ) n = 0; /* IMP: R-26507-47431 */ return sqlite3Realloc(pOld, n); } -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ +SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -24558,9 +24788,8 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){ if( z==0 ){ return 0; } - n = sqlite3Strlen30(z) + 1; - assert( (n&0x7fffffff)==n ); - zNew = sqlite3DbMallocRaw(db, (int)n); + n = strlen(z) + 1; + zNew = sqlite3DbMallocRaw(db, n); if( zNew ){ memcpy(zNew, z, n); } @@ -25500,7 +25729,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); - }else{ + }else if( N ){ assert( p->zText ); p->nChar += N; memcpy(&p->zText[p->nChar-N], z, N); @@ -25520,18 +25749,23 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ ** Return a pointer to the resulting string. Return a NULL ** pointer if any kind of error was encountered. */ +static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ + assert( p->mxAlloc>0 && !isMalloced(p) ); + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ + setStrAccumError(p, STRACCUM_NOMEM); + } + return p->zText; +} SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; if( p->mxAlloc>0 && !isMalloced(p) ){ - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); - if( p->zText ){ - memcpy(p->zText, p->zBase, p->nChar+1); - p->printfFlags |= SQLITE_PRINTF_MALLOCED; - }else{ - setStrAccumError(p, STRACCUM_NOMEM); - } + return strAccumFinishRealloc(p); } } return p->zText; @@ -25610,7 +25844,7 @@ SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ ** Print into memory obtained from sqlite3_malloc(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; @@ -25634,7 +25868,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap ** Print into memory obtained from sqlite3_malloc()(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ +SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; #ifndef SQLITE_OMIT_AUTOINIT @@ -25659,7 +25893,7 @@ SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ ** ** sqlite3_vsnprintf() is the varargs version. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ StrAccum acc; if( n<=0 ) return zBuf; #ifdef SQLITE_ENABLE_API_ARMOR @@ -25671,9 +25905,10 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, zFormat, ap); - return sqlite3StrAccumFinish(&acc); + zBuf[acc.nChar] = 0; + return zBuf; } -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ +SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); @@ -25709,7 +25944,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ /* ** Format and write a message to the log if logging is enabled. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ va_list ap; /* Vararg list */ if( sqlite3GlobalConfig.xLog ){ va_start(ap, zFormat); @@ -25819,6 +26054,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ va_start(ap, zFormat); sqlite3VXPrintf(&acc, zFormat, ap); va_end(ap); + assert( acc.nChar>0 ); if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); @@ -25874,7 +26110,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m /* -** Generate a human-readable description of a the Select object. +** Generate a human-readable description of a Select object. */ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; @@ -26205,6 +26441,15 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewExpr(pView, pExpr->pRight, 0); break; } + case TK_VECTOR: { + sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR"); + break; + } + case TK_SELECT_COLUMN: { + sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn); + sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); + break; + } default: { sqlite3TreeViewLine(pView, "op=%d", pExpr->op); break; @@ -26221,21 +26466,20 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewPop(pView); } + /* ** Generate a human-readable explanation of an expression list. */ -SQLITE_PRIVATE void sqlite3TreeViewExprList( +SQLITE_PRIVATE void sqlite3TreeViewBareExprList( TreeView *pView, const ExprList *pList, - u8 moreToFollow, const char *zLabel ){ - int i; - pView = sqlite3TreeViewPush(pView, moreToFollow); if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; if( pList==0 ){ sqlite3TreeViewLine(pView, "%s (empty)", zLabel); }else{ + int i; sqlite3TreeViewLine(pView, "%s", zLabel); for(i=0; inExpr; i++){ int j = pList->a[i].u.x.iOrderByCol; @@ -26247,6 +26491,15 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList( if( j ) sqlite3TreeViewPop(pView); } } +} +SQLITE_PRIVATE void sqlite3TreeViewExprList( + TreeView *pView, + const ExprList *pList, + u8 moreToFollow, + const char *zLabel +){ + pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewBareExprList(pView, pList, zLabel); sqlite3TreeViewPop(pView); } @@ -26286,7 +26539,7 @@ static SQLITE_WSD struct sqlite3PrngType { /* ** Return N random bytes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ +SQLITE_API void sqlite3_randomness(int N, void *pBuf){ unsigned char t; unsigned char *zBuf = pBuf; @@ -26362,7 +26615,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ sqlite3_mutex_leave(mutex); } -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE /* ** For testing purposes, we sometimes want to preserve the state of ** PRNG and restore the PRNG to its saved state at a later time, or @@ -26387,7 +26640,7 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ sizeof(sqlite3Prng) ); } -#endif /* SQLITE_OMIT_BUILTIN_TEST */ +#endif /* SQLITE_UNTESTABLE */ /************** End of random.c **********************************************/ /************** Begin file threads.c *****************************************/ @@ -27245,7 +27498,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){ ** Return whatever integer value the test callback returns, or return ** SQLITE_OK if no test callback is installed. */ -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; return xCallback ? xCallback(iTest) : SQLITE_OK; @@ -27489,7 +27742,7 @@ SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ ** case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){ +SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ if( zLeft==0 ){ return zRight ? -1 : 0; }else if( zRight==0 ){ @@ -27510,7 +27763,7 @@ SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ } return c; } -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ +SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; if( zLeft==0 ){ return zRight ? -1 : 0; @@ -28508,36 +28761,21 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ return sqlite3AddInt64(pA, -iB); } } -#define TWOPOWER32 (((i64)1)<<32) -#define TWOPOWER31 (((i64)1)<<31) SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ i64 iA = *pA; - i64 iA1, iA0, iB1, iB0, r; - - iA1 = iA/TWOPOWER32; - iA0 = iA % TWOPOWER32; - iB1 = iB/TWOPOWER32; - iB0 = iB % TWOPOWER32; - if( iA1==0 ){ - if( iB1==0 ){ - *pA *= iB; - return 0; + if( iB>0 ){ + if( iA>LARGEST_INT64/iB ) return 1; + if( iA0 ){ + if( iBLARGEST_INT64/-iB ) return 1; } - r = iA0*iB1; - }else if( iB1==0 ){ - r = iA1*iB0; - }else{ - /* If both iA1 and iB1 are non-zero, overflow will result */ - return 1; } - testcase( r==(-TWOPOWER31)-1 ); - testcase( r==(-TWOPOWER31) ); - testcase( r==TWOPOWER31 ); - testcase( r==TWOPOWER31-1 ); - if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1; - r *= TWOPOWER32; - if( sqlite3AddInt64(&r, iA0*iB0) ) return 1; - *pA = r; + *pA = iA*iB; return 0; } @@ -28672,6 +28910,109 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ } #endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ +/* +** Add a new name/number pair to a VList. This might require that the +** VList object be reallocated, so return the new VList. If an OOM +** error occurs, the original VList returned and the +** db->mallocFailed flag is set. +** +** A VList is really just an array of integers. To destroy a VList, +** simply pass it to sqlite3DbFree(). +** +** The first integer is the number of integers allocated for the whole +** VList. The second integer is the number of integers actually used. +** Each name/number pair is encoded by subsequent groups of 3 or more +** integers. +** +** Each name/number pair starts with two integers which are the numeric +** value for the pair and the size of the name/number pair, respectively. +** The text name overlays one or more following integers. The text name +** is always zero-terminated. +** +** Conceptually: +** +** struct VList { +** int nAlloc; // Number of allocated slots +** int nUsed; // Number of used slots +** struct VListEntry { +** int iValue; // Value for this entry +** int nSlot; // Slots used by this entry +** // ... variable name goes here +** } a[0]; +** } +** +** During code generation, pointers to the variable names within the +** VList are taken. When that happens, nAlloc is set to zero as an +** indication that the VList may never again be enlarged, since the +** accompanying realloc() would invalidate the pointers. +*/ +SQLITE_PRIVATE VList *sqlite3VListAdd( + sqlite3 *db, /* The database connection used for malloc() */ + VList *pIn, /* The input VList. Might be NULL */ + const char *zName, /* Name of symbol to add */ + int nName, /* Bytes of text in zName */ + int iVal /* Value to associate with zName */ +){ + int nInt; /* number of sizeof(int) objects needed for zName */ + char *z; /* Pointer to where zName will be stored */ + int i; /* Index in pIn[] where zName is stored */ + + nInt = nName/4 + 3; + assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ + if( pIn==0 || pIn[1]+nInt > pIn[0] ){ + /* Enlarge the allocation */ + int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt; + VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); + if( pOut==0 ) return pIn; + if( pIn==0 ) pOut[1] = 2; + pIn = pOut; + pIn[0] = nAlloc; + } + i = pIn[1]; + pIn[i] = iVal; + pIn[i+1] = nInt; + z = (char*)&pIn[i+2]; + pIn[1] = i+nInt; + assert( pIn[1]<=pIn[0] ); + memcpy(z, zName, nName); + z[nName] = 0; + return pIn; +} + +/* +** Return a pointer to the name of a variable in the given VList that +** has the value iVal. Or return a NULL if there is no such variable in +** the list +*/ +SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){ + int i, mx; + if( pIn==0 ) return 0; + mx = pIn[1]; + i = 2; + do{ + if( pIn[i]==iVal ) return (char*)&pIn[i+2]; + i += pIn[i+1]; + }while( ir[P3] goto P2"), - /* 39 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), - /* 40 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), - /* 42 */ "Last" OpHelp(""), + /* 36 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), + /* 37 */ "Eq" OpHelp("IF r[P3]==r[P1]"), + /* 38 */ "Gt" OpHelp("IF r[P3]>r[P1]"), + /* 39 */ "Le" OpHelp("IF r[P3]<=r[P1]"), + /* 40 */ "Lt" OpHelp("IF r[P3]=r[P1]"), + /* 42 */ "ElseNotEq" OpHelp(""), /* 43 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), /* 44 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), /* 45 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<0 then r[P1]-=P3, goto P2"), - /* 66 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), - /* 67 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 68 */ "IncrVacuum" OpHelp(""), - /* 69 */ "VNext" OpHelp(""), - /* 70 */ "Init" OpHelp("Start at P2"), - /* 71 */ "Return" OpHelp(""), - /* 72 */ "EndCoroutine" OpHelp(""), - /* 73 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 74 */ "Halt" OpHelp(""), - /* 75 */ "Integer" OpHelp("r[P2]=P1"), - /* 76 */ "Int64" OpHelp("r[P2]=P4"), - /* 77 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 78 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 79 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 80 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 81 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 82 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 83 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 84 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 85 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 86 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 87 */ "CollSeq" OpHelp(""), - /* 88 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 89 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 90 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 91 */ "RealAffinity" OpHelp(""), - /* 92 */ "Cast" OpHelp("affinity(r[P1])"), - /* 93 */ "Permutation" OpHelp(""), - /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 95 */ "Column" OpHelp("r[P3]=PX"), - /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 55 */ "SorterSort" OpHelp(""), + /* 56 */ "Sort" OpHelp(""), + /* 57 */ "Rewind" OpHelp(""), + /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"), + /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 64 */ "Program" OpHelp(""), + /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), + /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), + /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 69 */ "IncrVacuum" OpHelp(""), + /* 70 */ "VNext" OpHelp(""), + /* 71 */ "Init" OpHelp("Start at P2"), + /* 72 */ "Return" OpHelp(""), + /* 73 */ "EndCoroutine" OpHelp(""), + /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 75 */ "Halt" OpHelp(""), + /* 76 */ "Integer" OpHelp("r[P2]=P1"), + /* 77 */ "Int64" OpHelp("r[P2]=P4"), + /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 88 */ "CollSeq" OpHelp(""), + /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 92 */ "RealAffinity" OpHelp(""), + /* 93 */ "Cast" OpHelp("affinity(r[P1])"), + /* 94 */ "Permutation" OpHelp(""), + /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 96 */ "Column" OpHelp("r[P3]=PX"), /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 99 */ "Count" OpHelp("r[P2]=count()"), - /* 100 */ "ReadCookie" OpHelp(""), - /* 101 */ "SetCookie" OpHelp(""), - /* 102 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 103 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 104 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 105 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 106 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 107 */ "SorterOpen" OpHelp(""), - /* 108 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 109 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 110 */ "Close" OpHelp(""), - /* 111 */ "ColumnsUsed" OpHelp(""), - /* 112 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 113 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 114 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 115 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 116 */ "Delete" OpHelp(""), - /* 117 */ "ResetCount" OpHelp(""), - /* 118 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 119 */ "SorterData" OpHelp("r[P2]=data"), - /* 120 */ "RowKey" OpHelp("r[P2]=key"), + /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 100 */ "Count" OpHelp("r[P2]=count()"), + /* 101 */ "ReadCookie" OpHelp(""), + /* 102 */ "SetCookie" OpHelp(""), + /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 108 */ "SorterOpen" OpHelp(""), + /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 111 */ "Close" OpHelp(""), + /* 112 */ "ColumnsUsed" OpHelp(""), + /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 117 */ "Delete" OpHelp(""), + /* 118 */ "ResetCount" OpHelp(""), + /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 120 */ "SorterData" OpHelp("r[P2]=data"), /* 121 */ "RowData" OpHelp("r[P2]=data"), /* 122 */ "Rowid" OpHelp("r[P2]=rowid"), /* 123 */ "NullRow" OpHelp(""), - /* 124 */ "SorterInsert" OpHelp(""), + /* 124 */ "SorterInsert" OpHelp("key=r[P2]"), /* 125 */ "IdxInsert" OpHelp("key=r[P2]"), /* 126 */ "IdxDelete" OpHelp("key=r[P2@P3]"), /* 127 */ "Seek" OpHelp("Move P3 to P1.rowid"), @@ -29088,8 +29433,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 129 */ "Destroy" OpHelp(""), /* 130 */ "Clear" OpHelp(""), /* 131 */ "ResetSorter" OpHelp(""), - /* 132 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), - /* 133 */ "Real" OpHelp("r[P2]=P4"), + /* 132 */ "Real" OpHelp("r[P2]=P4"), + /* 133 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), /* 134 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), /* 135 */ "ParseSchema" OpHelp(""), /* 136 */ "LoadAnalysis" OpHelp(""), @@ -30386,7 +30731,14 @@ struct unixFileId { #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID for vxworks. */ #else - ino_t ino; /* Inode number */ + /* We are told that some versions of Android contain a bug that + ** sizes ino_t at only 32-bits instead of 64-bits. (See + ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c) + ** To work around this, always allocate 64-bits for the inode number. + ** On small machines that only have 32-bit inodes, this wastes 4 bytes, + ** but that should not be a big deal. */ + /* WAS: ino_t ino; */ + u64 ino; /* Inode number */ #endif }; @@ -30631,7 +30983,7 @@ static int findInodeInfo( #if OS_VXWORKS fileId.pId = pFile->pId; #else - fileId.ino = statbuf.st_ino; + fileId.ino = (u64)statbuf.st_ino; #endif pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ @@ -30665,7 +31017,8 @@ static int fileHasMoved(unixFile *pFile){ #else struct stat buf; return pFile->pInode!=0 && - (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); + (osStat(pFile->zPath, &buf)!=0 + || (u64)buf.st_ino!=pFile->pInode->fileId.ino); #endif } @@ -34837,7 +35190,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev - || pInode->fileId.ino!=sStat.st_ino) ){ + || pInode->fileId.ino!=(u64)sStat.st_ino) ){ pInode = pInode->pNext; } if( pInode ){ @@ -34854,6 +35207,27 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ return pUnused; } +/* +** Find the mode, uid and gid of file zFile. +*/ +static int getFileMode( + const char *zFile, /* File name */ + mode_t *pMode, /* OUT: Permissions of zFile */ + uid_t *pUid, /* OUT: uid of zFile. */ + gid_t *pGid /* OUT: gid of zFile. */ +){ + struct stat sStat; /* Output of stat() on database file */ + int rc = SQLITE_OK; + if( 0==osStat(zFile, &sStat) ){ + *pMode = sStat.st_mode & 0777; + *pUid = sStat.st_uid; + *pGid = sStat.st_gid; + }else{ + rc = SQLITE_IOERR_FSTAT; + } + return rc; +} + /* ** This function is called by unixOpen() to determine the unix permissions ** to create new files with. If no error occurs, then SQLITE_OK is returned @@ -34889,7 +35263,6 @@ static int findCreateFileMode( if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ char zDb[MAX_PATHNAME+1]; /* Database file path */ int nDb; /* Number of valid bytes in zDb */ - struct stat sStat; /* Output of stat() on database file */ /* zPath is a path to a WAL or journal file. The following block derives ** the path to the associated database file from zPath. This block handles @@ -34920,15 +35293,18 @@ static int findCreateFileMode( memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; - if( 0==osStat(zDb, &sStat) ){ - *pMode = sStat.st_mode & 0777; - *pUid = sStat.st_uid; - *pGid = sStat.st_gid; - }else{ - rc = SQLITE_IOERR_FSTAT; - } + rc = getFileMode(zDb, pMode, pUid, pGid); }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; + }else if( flags & SQLITE_OPEN_URI ){ + /* If this is a main database file and the file was opened using a URI + ** filename, check for the "modeof" parameter. If present, interpret + ** its value as a filename and try to copy the mode, uid and gid from + ** that file. */ + const char *z = sqlite3_uri_parameter(zPath, "modeof"); + if( z ){ + rc = getFileMode(z, pMode, pUid, pGid); + } } return rc; } @@ -36809,7 +37185,7 @@ static int proxyClose(sqlite3_file *id) { ** necessarily been initialized when this routine is called, and so they ** should not be used. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a pointer @@ -36908,7 +37284,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ return SQLITE_OK; } @@ -38343,7 +38719,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ ** "pnLargest" argument, if non-zero, will be used to return the size of the ** largest committed free block in the heap, in bytes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ +SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ int rc = SQLITE_OK; UINT nLargest = 0; HANDLE hHeap; @@ -38383,7 +38759,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will ** be returned and no changes will be made to the Win32 native heap. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ +SQLITE_API int sqlite3_win32_reset_heap(){ int rc; MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ @@ -38428,7 +38804,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ ** (if available). */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){ +SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ @@ -38474,7 +38850,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int n static HANDLE sleepObj = NULL; #endif -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ #if SQLITE_OS_WINRT if ( sleepObj==NULL ){ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, @@ -38523,7 +38899,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ ** This function determines if the machine is running a version of Windows ** based on the NT kernel. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){ +SQLITE_API int sqlite3_win32_is_nt(void){ #if SQLITE_OS_WINRT /* ** NOTE: The WinRT sub-platform is always assumed to be based on the NT @@ -38911,7 +39287,7 @@ static char *winUtf8ToMbcs(const char *zText, int useAnsi){ /* ** This is a public wrapper for the winUtf8ToUnicode() function. */ -SQLITE_API LPWSTR SQLITE_STDCALL sqlite3_win32_utf8_to_unicode(const char *zText){ +SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zText ){ (void)SQLITE_MISUSE_BKPT; @@ -38927,7 +39303,7 @@ SQLITE_API LPWSTR SQLITE_STDCALL sqlite3_win32_utf8_to_unicode(const char *zText /* ** This is a public wrapper for the winUnicodeToUtf8() function. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ +SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zWideText ){ (void)SQLITE_MISUSE_BKPT; @@ -38943,7 +39319,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText) /* ** This is a public wrapper for the winMbcsToUtf8() function. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zText){ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zText ){ (void)SQLITE_MISUSE_BKPT; @@ -38959,7 +39335,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zText){ /* ** This is a public wrapper for the winMbcsToUtf8() function. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zText ){ (void)SQLITE_MISUSE_BKPT; @@ -38975,7 +39351,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8_v2(const char *zText, /* ** This is a public wrapper for the winUtf8ToMbcs() function. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zText){ +SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zText){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zText ){ (void)SQLITE_MISUSE_BKPT; @@ -38991,7 +39367,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zText){ /* ** This is a public wrapper for the winUtf8ToMbcs() function. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ +SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ #ifdef SQLITE_ENABLE_API_ARMOR if( !zText ){ (void)SQLITE_MISUSE_BKPT; @@ -39011,7 +39387,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs_v2(const char *zText, ** argument is the name of the directory to use. The return value will be ** SQLITE_OK if successful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -40604,6 +40980,12 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } + case SQLITE_FCNTL_WIN32_GET_HANDLE: { + LPHANDLE phFile = (LPHANDLE)pArg; + *phFile = pFile->h; + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } #ifdef SQLITE_TEST case SQLITE_FCNTL_WIN32_SET_HANDLE: { LPHANDLE phFile = (LPHANDLE)pArg; @@ -42929,7 +43311,7 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ /* ** Initialize and deinitialize the operating system interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ static sqlite3_vfs winVfs = { 3, /* iVersion */ sizeof(winFile), /* szOsFile */ @@ -43060,7 +43442,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ #if SQLITE_OS_WINRT if( sleepObj!=NULL ){ osCloseHandle(sleepObj); @@ -43369,7 +43751,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ return p->iSize; } -#ifndef SQLITE_OMIT_BUILTIN_TEST +#ifndef SQLITE_UNTESTABLE /* ** Let V[] be an array of unsigned characters sufficient to hold ** up to N bits. Let I be an integer between 0 and N. 0<=Ipgno>0 ); /* Page number is 1 or more */ + assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ pCache = pPg->pCache; assert( pCache!=0 ); /* Every page has an associated PCache */ if( pPg->flags & PGHDR_CLEAN ){ @@ -43774,6 +44156,12 @@ SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } ** has already been allocated and is passed in as the p pointer. ** The caller discovers how much space needs to be allocated by ** calling sqlite3PcacheSize(). +** +** szExtra is some extra space allocated for each page. The first +** 8 bytes of the extra space will be zeroed as the page is allocated, +** but remaining content will be uninitialized. Though it is opaque +** to this module, the extra space really ends up being the MemPage +** structure in the pager. */ SQLITE_PRIVATE int sqlite3PcacheOpen( int szPage, /* Size of every page */ @@ -43786,6 +44174,7 @@ SQLITE_PRIVATE int sqlite3PcacheOpen( memset(p, 0, sizeof(PCache)); p->szPage = 1; p->szExtra = szExtra; + assert( szExtra>=8 ); /* First 8 bytes will be zeroed */ p->bPurgeable = bPurgeable; p->eCreate = 2; p->xStress = xStress; @@ -43855,7 +44244,6 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( assert( pCache!=0 ); assert( pCache->pCache!=0 ); assert( createFlag==3 || createFlag==0 ); - assert( pgno>0 ); assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) ); /* eCreate defines what to do if the page does not exist. @@ -43951,11 +44339,11 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( assert( pPage!=0 ); pPgHdr = (PgHdr*)pPage->pExtra; assert( pPgHdr->pPage==0 ); - memset(pPgHdr, 0, sizeof(PgHdr)); + memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); pPgHdr->pPage = pPage; pPgHdr->pData = pPage->pBuf; pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, pCache->szExtra); + memset(pPgHdr->pExtra, 0, 8); pPgHdr->pCache = pCache; pPgHdr->pgno = pgno; pPgHdr->flags = PGHDR_CLEAN; @@ -44645,7 +45033,7 @@ static int pcache1InitBulk(PCache1 *pCache){ szBulk = -1024 * (i64)pcache1.nInitPage; } if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ - szBulk = pCache->szAlloc*pCache->nMax; + szBulk = pCache->szAlloc*(i64)pCache->nMax; } zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); sqlite3EndBenignMalloc(); @@ -46179,7 +46567,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalLimit(x,y) -# define sqlite3WalClose(w,x,y,z) 0 +# define sqlite3WalClose(v,w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalDbsize(y) 0 @@ -46189,7 +46577,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 -# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 +# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 @@ -46207,7 +46595,7 @@ typedef struct Wal Wal; /* Open and close a connection to a write-ahead log. */ SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); +SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); /* Set the limiting size of a WAL file. */ SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); @@ -46250,6 +46638,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); /* Copy pages from the log to the database file */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Write-ahead log connection */ + sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* One of PASSIVE, FULL and RESTART */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ @@ -46281,6 +46670,7 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); +SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal); #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -46970,6 +47360,7 @@ struct Pager { int nRead; /* Database pages read */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ + int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ @@ -47094,9 +47485,10 @@ static const unsigned char aJournalMagic[] = { ** rollback journal. Otherwise false. */ #ifndef SQLITE_OMIT_WAL -static int pagerUseWal(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ return (pPager->pWal!=0); } +# define pagerUseWal(x) sqlite3PagerUseWal(x) #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 @@ -47295,6 +47687,33 @@ static char *print_pager_state(Pager *p){ } #endif +/* Forward references to the various page getters */ +static int getPageNormal(Pager*,Pgno,DbPage**,int); +static int getPageError(Pager*,Pgno,DbPage**,int); +#if SQLITE_MAX_MMAP_SIZE>0 +static int getPageMMap(Pager*,Pgno,DbPage**,int); +#endif + +/* +** Set the Pager.xGet method for the appropriate routine used to fetch +** content from the pager. +*/ +static void setGetterMethod(Pager *pPager){ + if( pPager->errCode ){ + pPager->xGet = getPageError; +#if SQLITE_MAX_MMAP_SIZE>0 + }else if( USEFETCH(pPager) +#ifdef SQLITE_HAS_CODEC + && pPager->xCodec==0 +#endif + ){ + pPager->xGet = getPageMMap; +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + }else{ + pPager->xGet = getPageNormal; + } +} + /* ** Return true if it is necessary to write page *pPg into the sub-journal. ** A page needs to be written into the sub-journal if there exists one @@ -48109,6 +48528,7 @@ static void pager_unlock(Pager *pPager){ } if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); pPager->errCode = SQLITE_OK; + setGetterMethod(pPager); } pPager->journalOff = 0; @@ -48146,6 +48566,7 @@ static int pager_error(Pager *pPager, int rc){ if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; + setGetterMethod(pPager); } return rc; } @@ -48314,7 +48735,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ pPager->pInJournal = 0; pPager->nRec = 0; if( rc==SQLITE_OK ){ - if( pagerFlushOnCommit(pPager, bCommit) ){ + if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){ sqlite3PcacheCleanAll(pPager->pPCache); }else{ sqlite3PcacheClearWritable(pPager->pPCache); @@ -49713,6 +50134,7 @@ static void pagerFixMaplimit(Pager *pPager){ sqlite3_int64 sz; sz = pPager->szMmap; pPager->bUseFetch = (sz>0); + setGetterMethod(pPager); sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); } #endif @@ -50209,6 +50631,7 @@ static int pagerSyncHotJournal(Pager *pPager){ return rc; } +#if SQLITE_MAX_MMAP_SIZE>0 /* ** Obtain a reference to a memory mapped page object for page number pgno. ** The new object will use the pointer pData, obtained from xFetch(). @@ -50231,7 +50654,8 @@ static int pagerAcquireMapPage( *ppPage = p = pPager->pMmapFreelist; pPager->pMmapFreelist = p->pDirty; p->pDirty = 0; - memset(p->pExtra, 0, pPager->nExtra); + assert( pPager->nExtra>=8 ); + memset(p->pExtra, 0, 8); }else{ *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); if( p==0 ){ @@ -50256,6 +50680,7 @@ static int pagerAcquireMapPage( return SQLITE_OK; } +#endif /* ** Release a reference to page pPg. pPg must have been returned by an @@ -50298,9 +50723,10 @@ static void pagerFreeMapHdrs(Pager *pPager){ ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ u8 *pTmp = (u8 *)pPager->pTmpSpace; + assert( db || pagerUseWal(pPager)==0 ); assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); @@ -50308,7 +50734,10 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL - sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); + assert( db || pPager->pWal==0 ); + sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, + (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) + ); pPager->pWal = 0; #endif pager_reset(pPager); @@ -50827,7 +51256,9 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){ ** ** The nExtra parameter specifies the number of bytes of space allocated ** along with each page reference. This space is available to the user -** via the sqlite3PagerGetExtra() API. +** via the sqlite3PagerGetExtra() API. When a new page is allocated, the +** first 8 bytes of this space are zeroed but the remainder is uninitialized. +** (The extra space is used by btree as the MemPage object.) ** ** The flags argument is used to specify properties that affect the ** operation of the pager. It should be passed some bitwise combination @@ -51057,8 +51488,8 @@ act_like_temp_file: /* Initialize the PCache object. */ if( rc==SQLITE_OK ){ - assert( nExtra<1000 ); nExtra = ROUND8(nExtra); + assert( nExtra>=8 && nExtra<1000 ); rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); } @@ -51123,6 +51554,7 @@ act_like_temp_file: /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; + setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ @@ -51536,10 +51968,17 @@ static void pagerUnlockIfUnused(Pager *pPager){ } /* -** Acquire a reference to page number pgno in pager pPager (a page -** reference has type DbPage*). If the requested reference is +** The page getter methods each try to acquire a reference to a +** page with page number pgno. If the requested reference is ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. ** +** There are different implementations of the getter method depending +** on the current state of the pager. +** +** getPageNormal() -- The normal getter +** getPageError() -- Used if the pager is in an error state +** getPageMmap() -- Used if memory-mapped I/O is enabled +** ** If the requested page is already in the cache, it is returned. ** Otherwise, a new page object is allocated and populated with data ** read from the database file. In some cases, the pcache module may @@ -51551,14 +51990,14 @@ static void pagerUnlockIfUnused(Pager *pPager){ ** already in the cache when this function is called, then the extra ** data is left as it was when the page object was last used. ** -** If the database image is smaller than the requested page or if a -** non-zero value is passed as the noContent parameter and the +** If the database image is smaller than the requested page or if +** the flags parameter contains the PAGER_GET_NOCONTENT bit and the ** requested page is not already stored in the cache, then no ** actual disk read occurs. In this case the memory image of the ** page is initialized to all zeros. ** -** If noContent is true, it means that we do not care about the contents -** of the page. This occurs in two scenarios: +** If PAGER_GET_NOCONTENT is true, it means that we do not care about +** the contents of the page. This occurs in two scenarios: ** ** a) When reading a free-list leaf page from the database, and ** @@ -51566,8 +52005,8 @@ static void pagerUnlockIfUnused(Pager *pPager){ ** a new page into the cache to be filled with the data read ** from the savepoint journal. ** -** If noContent is true, then the data returned is zeroed instead of -** being read from the database. Additionally, the bits corresponding +** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead +** of being read from the database. Additionally, the bits corresponding ** to pgno in Pager.pInJournal (bitvec of pages already written to the ** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open ** savepoints are set. This means if the page is made writable at any @@ -51585,106 +52024,39 @@ static void pagerUnlockIfUnused(Pager *pPager){ ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ -SQLITE_PRIVATE int sqlite3PagerGet( +static int getPageNormal( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ int rc = SQLITE_OK; - PgHdr *pPg = 0; - u32 iFrame = 0; /* Frame to read from WAL file */ - const int noContent = (flags & PAGER_GET_NOCONTENT); + PgHdr *pPg; + u8 noContent; /* True if PAGER_GET_NOCONTENT is set */ + sqlite3_pcache_page *pBase; - /* It is acceptable to use a read-only (mmap) page for any page except - ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY - ** flag was specified by the caller. And so long as the db is not a - ** temporary or in-memory database. */ - const int bMmapOk = (pgno>1 && USEFETCH(pPager) - && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) -#ifdef SQLITE_HAS_CODEC - && pPager->xCodec==0 -#endif - ); - - /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here - ** allows the compiler optimizer to reuse the results of the "pgno>1" - ** test in the previous statement, and avoid testing pgno==0 in the - ** common case where pgno is large. */ - if( pgno<=1 && pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } + assert( pPager->errCode==SQLITE_OK ); assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); - assert( noContent==0 || bMmapOk==0 ); - assert( pPager->hasHeldSharedLock==1 ); - /* If the pager is in the error state, return an error immediately. - ** Otherwise, request the page from the PCache layer. */ - if( pPager->errCode!=SQLITE_OK ){ - rc = pPager->errCode; - }else{ - if( bMmapOk && pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - } - - if( bMmapOk && iFrame==0 ){ - void *pData = 0; - - rc = sqlite3OsFetch(pPager->fd, - (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData - ); - - if( rc==SQLITE_OK && pData ){ - if( pPager->eState>PAGER_READER || pPager->tempFile ){ - pPg = sqlite3PagerLookup(pPager, pgno); - } - if( pPg==0 ){ - rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); - } - if( pPg ){ - assert( rc==SQLITE_OK ); - *ppPage = pPg; - return SQLITE_OK; - } - } - if( rc!=SQLITE_OK ){ - goto pager_acquire_err; - } - } - - { - sqlite3_pcache_page *pBase; - pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); - if( pBase==0 ){ - rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - if( pBase==0 ){ - pPg = *ppPage = 0; - rc = SQLITE_NOMEM_BKPT; - goto pager_acquire_err; - } - } - pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); - assert( pPg!=0 ); - } - } - - if( rc!=SQLITE_OK ){ - /* Either the call to sqlite3PcacheFetch() returned an error or the - ** pager was already in the error-state when this function was called. - ** Set pPg to 0 and jump to the exception handler. */ + if( pgno==0 ) return SQLITE_CORRUPT_BKPT; + pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); + if( pBase==0 ){ pPg = 0; - goto pager_acquire_err; + rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + if( pBase==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto pager_acquire_err; + } } + pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); assert( pPg==(*ppPage) ); assert( pPg->pgno==pgno ); assert( pPg->pPager==pPager || pPg->pPager==0 ); + noContent = (flags & PAGER_GET_NOCONTENT)!=0; if( pPg->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ @@ -51694,17 +52066,18 @@ SQLITE_PRIVATE int sqlite3PagerGet( }else{ /* The pager cache has created a new page. Its content needs to - ** be initialized. */ - - pPg->pPager = pPager; - - /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page - ** number greater than this, or the unused locking-page, is requested. */ + ** be initialized. But first some error checks: + ** + ** (1) The maximum page number is 2^31 + ** (2) Never try to fetch the locking page + */ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } + pPg->pPager = pPager; + assert( !isOpen(pPager->fd) || !MEMDB ); if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ @@ -51730,7 +52103,8 @@ SQLITE_PRIVATE int sqlite3PagerGet( memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ - if( pagerUseWal(pPager) && bMmapOk==0 ){ + u32 iFrame = 0; /* Frame to read from WAL file */ + if( pagerUseWal(pPager) ){ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); if( rc!=SQLITE_OK ) goto pager_acquire_err; } @@ -51743,7 +52117,6 @@ SQLITE_PRIVATE int sqlite3PagerGet( } pager_set_pagehash(pPg); } - return SQLITE_OK; pager_acquire_err: @@ -51752,11 +52125,109 @@ pager_acquire_err: sqlite3PcacheDrop(pPg); } pagerUnlockIfUnused(pPager); - *ppPage = 0; return rc; } +#if SQLITE_MAX_MMAP_SIZE>0 +/* The page getter for when memory-mapped I/O is enabled */ +static int getPageMMap( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int flags /* PAGER_GET_XXX flags */ +){ + int rc = SQLITE_OK; + PgHdr *pPg = 0; + u32 iFrame = 0; /* Frame to read from WAL file */ + + /* It is acceptable to use a read-only (mmap) page for any page except + ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY + ** flag was specified by the caller. And so long as the db is not a + ** temporary or in-memory database. */ + const int bMmapOk = (pgno>1 + && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) + ); + + assert( USEFETCH(pPager) ); +#ifdef SQLITE_HAS_CODEC + assert( pPager->xCodec==0 ); +#endif + + /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here + ** allows the compiler optimizer to reuse the results of the "pgno>1" + ** test in the previous statement, and avoid testing pgno==0 in the + ** common case where pgno is large. */ + if( pgno<=1 && pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pPager->eState>=PAGER_READER ); + assert( assert_pager_state(pPager) ); + assert( pPager->hasHeldSharedLock==1 ); + assert( pPager->errCode==SQLITE_OK ); + + if( bMmapOk && pagerUseWal(pPager) ){ + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); + if( rc!=SQLITE_OK ){ + *ppPage = 0; + return rc; + } + } + if( bMmapOk && iFrame==0 ){ + void *pData = 0; + rc = sqlite3OsFetch(pPager->fd, + (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData + ); + if( rc==SQLITE_OK && pData ){ + if( pPager->eState>PAGER_READER || pPager->tempFile ){ + pPg = sqlite3PagerLookup(pPager, pgno); + } + if( pPg==0 ){ + rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); + }else{ + sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); + } + if( pPg ){ + assert( rc==SQLITE_OK ); + *ppPage = pPg; + return SQLITE_OK; + } + } + if( rc!=SQLITE_OK ){ + *ppPage = 0; + return rc; + } + } + return getPageNormal(pPager, pgno, ppPage, flags); +} +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + +/* The page getter method for when the pager is an error state */ +static int getPageError( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int flags /* PAGER_GET_XXX flags */ +){ + UNUSED_PARAMETER(pgno); + UNUSED_PARAMETER(flags); + assert( pPager->errCode!=SQLITE_OK ); + *ppPage = 0; + return pPager->errCode; +} + + +/* Dispatch all page fetch requests to the appropriate getter method. +*/ +SQLITE_PRIVATE int sqlite3PagerGet( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int flags /* PAGER_GET_XXX flags */ +){ + return pPager->xGet(pPager, pgno, ppPage, flags); +} + /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, @@ -52230,11 +52701,11 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); - if( pPager->errCode ){ - return pPager->errCode; - }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ + if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); return SQLITE_OK; + }else if( pPager->errCode ){ + return pPager->errCode; }else if( pPager->sectorSize > (u32)pPager->pageSize ){ assert( pPager->tempFile==0 ); return pagerWriteLargeSector(pPg); @@ -52729,6 +53200,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ */ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; + setGetterMethod(pPager); return rc; } }else{ @@ -52933,7 +53405,11 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ ** savepoint. If no errors occur, SQLITE_OK is returned. */ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ - int rc = pPager->errCode; /* Return code */ + int rc = pPager->errCode; + +#ifdef SQLITE_ENABLE_ZIPVFS + if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK; +#endif assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); @@ -52974,6 +53450,21 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ rc = pagerPlaybackSavepoint(pPager, pSavepoint); assert(rc!=SQLITE_DONE); } + +#ifdef SQLITE_ENABLE_ZIPVFS + /* If the cache has been modified but the savepoint cannot be rolled + ** back journal_mode=off, put the pager in the error state. This way, + ** if the VFS used by this pager includes ZipVFS, the entire transaction + ** can be rolled back at the ZipVFS level. */ + else if( + pPager->journalMode==PAGER_JOURNALMODE_OFF + && pPager->eState>=PAGER_WRITER_CACHEMOD + ){ + pPager->errCode = SQLITE_ABORT; + pPager->eState = PAGER_ERROR; + setGetterMethod(pPager); + } +#endif } return rc; @@ -53044,6 +53535,7 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec( pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; pPager->pCodec = pCodec; + setGetterMethod(pPager); pagerReportSize(pPager); } SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ @@ -53453,10 +53945,16 @@ SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){ ** ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. */ -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ +SQLITE_PRIVATE int sqlite3PagerCheckpoint( + Pager *pPager, /* Checkpoint on this pager */ + sqlite3 *db, /* Db handle used to check for interrupts */ + int eMode, /* Type of checkpoint */ + int *pnLog, /* OUT: Final number of frames in log */ + int *pnCkpt /* OUT: Final number of checkpointed frames */ +){ int rc = SQLITE_OK; if( pPager->pWal ){ - rc = sqlite3WalCheckpoint(pPager->pWal, eMode, + rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, @@ -53588,7 +54086,7 @@ SQLITE_PRIVATE int sqlite3PagerOpenWal( ** error (SQLITE_BUSY) is returned and the log connection is not closed. ** If successful, the EXCLUSIVE lock is not released before returning. */ -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ int rc = SQLITE_OK; assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); @@ -53616,7 +54114,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, + rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); @@ -53653,6 +54151,20 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSn } return rc; } + +/* +** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this +** is not a WAL database, return an error. +*/ +SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ + int rc; + if( pPager->pWal ){ + rc = sqlite3WalSnapshotRecover(pPager->pWal); + }else{ + rc = SQLITE_ERROR; + } + return rc; +} #endif /* SQLITE_ENABLE_SNAPSHOT */ #endif /* !SQLITE_OMIT_WAL */ @@ -55399,6 +55911,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ */ static int walCheckpoint( Wal *pWal, /* Wal connection */ + sqlite3 *db, /* Check for interrupts on this handle */ int eMode, /* One of PASSIVE, FULL or RESTART */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ @@ -55493,6 +56006,10 @@ static int walCheckpoint( while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); + if( db->u1.isInterrupted ){ + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; + break; + } if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ continue; } @@ -55597,6 +56114,7 @@ static void walLimitSize(Wal *pWal, i64 nMax){ */ SQLITE_PRIVATE int sqlite3WalClose( Wal *pWal, /* Wal to close */ + sqlite3 *db, /* For interrupt flag */ int sync_flags, /* Flags to pass to OsSync() (or 0) */ int nBuf, u8 *zBuf /* Buffer of at least nBuf bytes */ @@ -55613,13 +56131,14 @@ SQLITE_PRIVATE int sqlite3WalClose( ** ** The EXCLUSIVE lock is not released before returning. */ - rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); - if( rc==SQLITE_OK ){ + if( zBuf!=0 + && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) + ){ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } - rc = sqlite3WalCheckpoint( - pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 + rc = sqlite3WalCheckpoint(pWal, db, + SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 ); if( rc==SQLITE_OK ){ int bPersist = -1; @@ -56048,6 +56567,84 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc; } +#ifdef SQLITE_ENABLE_SNAPSHOT +/* +** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted +** variable so that older snapshots can be accessed. To do this, loop +** through all wal frames from nBackfillAttempted to (nBackfill+1), +** comparing their content to the corresponding page with the database +** file, if any. Set nBackfillAttempted to the frame number of the +** first frame for which the wal file content matches the db file. +** +** This is only really safe if the file-system is such that any page +** writes made by earlier checkpointers were atomic operations, which +** is not always true. It is also possible that nBackfillAttempted +** may be left set to a value larger than expected, if a wal frame +** contains content that duplicate of an earlier version of the same +** page. +** +** SQLITE_OK is returned if successful, or an SQLite error code if an +** error occurs. It is not an error if nBackfillAttempted cannot be +** decreased at all. +*/ +SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ + int rc; + + assert( pWal->readLock>=0 ); + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + if( rc==SQLITE_OK ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + int szPage = (int)pWal->szPage; + i64 szDb; /* Size of db file in bytes */ + + rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); + if( rc==SQLITE_OK ){ + void *pBuf1 = sqlite3_malloc(szPage); + void *pBuf2 = sqlite3_malloc(szPage); + if( pBuf1==0 || pBuf2==0 ){ + rc = SQLITE_NOMEM; + }else{ + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){ + volatile ht_slot *dummy; + volatile u32 *aPgno; /* Array of page numbers */ + u32 iZero; /* Frame corresponding to aPgno[0] */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + + rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero); + if( rc!=SQLITE_OK ) break; + pgno = aPgno[i-iZero]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ + iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; + rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); + + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); + } + + if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ + break; + } + } + + pInfo->nBackfillAttempted = i-1; + } + } + + sqlite3_free(pBuf1); + sqlite3_free(pBuf2); + } + walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); + } + + return rc; +} +#endif /* SQLITE_ENABLE_SNAPSHOT */ + /* ** Begin a read transaction on the database. ** @@ -56110,7 +56707,11 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** has not yet set the pInfo->nBackfillAttempted variable to indicate ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. */ + ** before checking pInfo->nBackfillAttempted. + ** + ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing + ** this already? + */ rc = walLockShared(pWal, WAL_CKPT_LOCK); if( rc==SQLITE_OK ){ @@ -56867,6 +57468,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Wal connection */ + sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ @@ -56941,7 +57543,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); } /* If no error occurred, set the output variables. */ @@ -57061,9 +57663,14 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ int rc = SQLITE_OK; WalIndexHdr *pRet; + static const u32 aZero[4] = { 0, 0, 0, 0 }; assert( pWal->readLock>=0 && pWal->writeLock==0 ); + if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){ + *ppSnapshot = 0; + return SQLITE_ERROR; + } pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); if( pRet==0 ){ rc = SQLITE_NOMEM_BKPT; @@ -57085,7 +57692,7 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapsho ** Return a +ve value if snapshot p1 is newer than p2. A -ve value if ** p1 is older than p2 and zero if p1 and p2 are the same snapshot. */ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ +SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ WalIndexHdr *pHdr1 = (WalIndexHdr*)p1; WalIndexHdr *pHdr2 = (WalIndexHdr*)p2; @@ -57401,37 +58008,39 @@ typedef struct CellInfo CellInfo; #define PTF_LEAF 0x08 /* -** As each page of the file is loaded into memory, an instance of the following -** structure is appended and initialized to zero. This structure stores -** information about the page that is decoded from the raw file page. +** An instance of this object stores information about each a single database +** page that has been loaded into memory. The information in this object +** is derived from the raw on-disk page content. ** -** The pParent field points back to the parent page. This allows us to -** walk up the BTree from any leaf to the root. Care must be taken to -** unref() the parent page pointer when this page is no longer referenced. -** The pageDestructor() routine handles that chore. +** As each database page is loaded into memory, the pager allocats an +** instance of this object and zeros the first 8 bytes. (This is the +** "extra" information associated with each page of the pager.) ** ** Access to all fields of this structure is controlled by the mutex ** stored in MemPage.pBt->mutex. */ struct MemPage { u8 isInit; /* True if previously initialized. MUST BE FIRST! */ - u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ u8 intKey; /* True if table b-trees. False for index b-trees */ u8 intKeyLeaf; /* True if the leaf of an intKey table */ + Pgno pgno; /* Page number for this page */ + /* Only the first 8 bytes (above) are zeroed by pager.c when a new page + ** is allocated. All fields that follow must be initialized before use */ u8 leaf; /* True if a leaf page */ u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ - u8 bBusy; /* Prevent endless loops on corrupt database files */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ u16 maskPage; /* Mask for page offset */ - u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th + u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th ** non-overflow cell */ - u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ + u8 *apOvfl[4]; /* Pointers to the body of overflow cells */ BtShared *pBt; /* Pointer to BtShared that this page is part of */ u8 *aData; /* Pointer to disk image of the page data */ u8 *aDataEnd; /* One byte past the end of usable data */ @@ -57440,16 +58049,8 @@ struct MemPage { DbPage *pDbPage; /* Pager page handle */ u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ - Pgno pgno; /* Page number for this page */ }; -/* -** The in-memory image of a disk page has the auxiliary information appended -** to the end. EXTRA_SIZE is the number of bytes of space needed to hold -** that extra information. -*/ -#define EXTRA_SIZE sizeof(MemPage) - /* ** A linked list of the following structures is stored at BtShared.pLock. ** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor @@ -58222,7 +58823,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){ +SQLITE_API int sqlite3_enable_shared_cache(int enable){ sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; } @@ -58768,7 +59369,7 @@ static int saveCursorKey(BtCursor *pCur){ pCur->nKey = sqlite3BtreePayloadSize(pCur); pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ - rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); + rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ pCur->pKey = pKey; }else{ @@ -58899,26 +59500,23 @@ static int btreeMoveto( ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ - char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */ - char *pFree = 0; if( pKey ){ assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeAllocUnpackedRecord( - pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree - ); + pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 ){ - sqlite3DbFree(pCur->pKeyInfo->db, pFree); - return SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_BKPT; + goto moveto_done; } }else{ pIdxKey = 0; } rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); - if( pFree ){ - sqlite3DbFree(pCur->pKeyInfo->db, pFree); +moveto_done: + if( pIdxKey ){ + sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); } return rc; } @@ -59741,8 +60339,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( data[iPtr+1]==0 && data[iPtr]==0 ){ iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ }else{ - while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkiLast ) return SQLITE_CORRUPT_BKPT; @@ -59876,7 +60477,7 @@ static int btreeInitPage(MemPage *pPage){ assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); if( !pPage->isInit ){ - u16 pc; /* Address of a freeblock within pPage->aData[] */ + int pc; /* Address of a freeblock within pPage->aData[] */ u8 hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ BtShared *pBt; /* The main btree structure */ @@ -59956,25 +60557,30 @@ static int btreeInitPage(MemPage *pPage){ ** freeblocks. */ pc = get2byte(&data[hdr+1]); nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ - while( pc>0 ){ - u16 next, size; - if( pciCellLast ){ + if( pc>0 ){ + u32 next, size; + if( pc0 && next<=pc+size+3) || pc+size>usableSize ){ - /* Free blocks must be in ascending order. And the last byte of - ** the free-block must lie on the database page. */ - return SQLITE_CORRUPT_BKPT; + while( 1 ){ + if( pc>iCellLast ){ + return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */ + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + nFree = nFree + size; + if( next<=pc+size+3 ) break; + pc = next; + } + if( next>0 ){ + return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */ + } + if( pc+size>(unsigned int)usableSize ){ + return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */ } - nFree = nFree + size; - pc = next; } /* At this point, nFree contains the sum of the offset to the start @@ -60415,7 +61021,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - EXTRA_SIZE, flags, vfsFlags, pageReinit); + sizeof(MemPage), flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); @@ -60528,12 +61134,14 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( btree_open_out: if( rc!=SQLITE_OK ){ if( pBt && pBt->pPager ){ - sqlite3PagerClose(pBt->pPager); + sqlite3PagerClose(pBt->pPager, 0); } sqlite3_free(pBt); sqlite3_free(p); *ppBtree = 0; }else{ + sqlite3_file *pFile; + /* If the B-Tree was successfully opened, set the pager-cache size to the ** default value. Except, when opening on an existing shared pager-cache, ** do not change the pager-cache size. @@ -60541,6 +61149,11 @@ btree_open_out: if( sqlite3BtreeSchema(p, 0, 0)==0 ){ sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); } + + pFile = sqlite3PagerFile(pBt->pPager); + if( pFile->pMethods ){ + sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); + } } if( mutexOpen ){ assert( sqlite3_mutex_held(mutexOpen) ); @@ -60670,7 +61283,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ ** Clean out and delete the BtShared object. */ assert( !pBt->pCursor ); - sqlite3PagerClose(pBt->pPager); + sqlite3PagerClose(pBt->pPager, p->db); if( pBt->xFreeSchema && pBt->pSchema ){ pBt->xFreeSchema(pBt->pSchema); } @@ -61417,14 +62030,11 @@ static int setChildPtrmaps(MemPage *pPage){ int nCell; /* Number of cells in page pPage */ int rc; /* Return code */ BtShared *pBt = pPage->pBt; - u8 isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); rc = btreeInitPage(pPage); - if( rc!=SQLITE_OK ){ - goto set_child_ptrmaps_out; - } + if( rc!=SQLITE_OK ) return rc; nCell = pPage->nCell; for(i=0; iisInit = isInitOrig; return rc; } @@ -61472,7 +62080,6 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ } put4byte(pPage->aData, iTo); }else{ - u8 isInitOrig = pPage->isInit; int i; int nCell; int rc; @@ -61508,8 +62115,6 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } - - pPage->isInit = isInitOrig; } return SQLITE_OK; } @@ -62404,6 +63009,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ return pCur && pCur->eState==CURSOR_VALID; } #endif /* NDEBUG */ +SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){ + assert( pCur!=0 ); + return pCur->eState==CURSOR_VALID; +} /* ** Return the value of the integer key or "rowid" for a table btree. @@ -62734,7 +63343,7 @@ static int accessPayload( && (bEnd || a==ovflSize) /* (6) */ && pBt->inTransaction==TRANS_READ /* (4) */ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ - && pBt->pPage1->aData[19]==0x01 /* (5) */ + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ && &pBuf[-4]>=pBufStart /* (7) */ ){ u8 aSave[4]; @@ -62773,43 +63382,35 @@ static int accessPayload( } /* -** Read part of the key associated with cursor pCur. Exactly -** "amt" bytes will be transferred into pBuf[]. The transfer +** Read part of the payload for the row at which that cursor pCur is currently +** pointing. "amt" bytes will be transferred into pBuf[]. The transfer ** begins at "offset". ** -** The caller must ensure that pCur is pointing to a valid row -** in the table. +** pCur can be pointing to either a table or an index b-tree. +** If pointing to a table btree, then the content section is read. If +** pCur is pointing to an index b-tree then the key section is read. +** +** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing +** to a valid row in the table. For sqlite3BtreePayloadChecked(), the +** cursor might be invalid or might need to be restored before being read. ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ -SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ +SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } - -/* -** Read part of the data associated with cursor pCur. Exactly -** "amt" bytes will be transfered into pBuf[]. The transfer -** begins at "offset". -** -** Return SQLITE_OK on success or an error code if anything goes -** wrong. An error is returned if "offset+amt" is larger than -** the available payload. -*/ -SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc; - #ifndef SQLITE_OMIT_INCRBLOB +SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; if ( pCur->eState==CURSOR_INVALID ){ return SQLITE_ABORT; } -#endif - assert( cursorOwnsBtShared(pCur) ); rc = restoreCursorPosition(pCur); if( rc==SQLITE_OK ){ @@ -62820,6 +63421,7 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p } return rc; } +#endif /* SQLITE_OMIT_INCRBLOB */ /* ** Return a pointer to payload information from the entry that the @@ -62990,9 +63592,12 @@ static int moveToRoot(BtCursor *pCur){ } if( pCur->iPage>=0 ){ - while( pCur->iPage ){ - assert( pCur->apPage[pCur->iPage]!=0 ); - releasePageNotNull(pCur->apPage[pCur->iPage--]); + if( pCur->iPage ){ + do{ + assert( pCur->apPage[pCur->iPage]!=0 ); + releasePageNotNull(pCur->apPage[pCur->iPage--]); + }while( pCur->iPage); + goto skip_init; } }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; @@ -63003,7 +63608,7 @@ static int moveToRoot(BtCursor *pCur){ 0, pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; - return rc; + return rc; } pCur->iPage = 0; pCur->curIntKey = pCur->apPage[0]->intKey; @@ -63026,10 +63631,12 @@ static int moveToRoot(BtCursor *pCur){ return SQLITE_CORRUPT_BKPT; } +skip_init: pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); + pRoot = pCur->apPage[0]; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ @@ -63286,16 +63893,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( lwr>upr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); - pCur->curFlags |= BTCF_ValidNKey; - pCur->info.nKey = nCellKey; pCur->aiIdx[pCur->iPage] = (u16)idx; if( !pPage->leaf ){ lwr = idx; goto moveto_next_layer; }else{ + pCur->curFlags |= BTCF_ValidNKey; + pCur->info.nKey = nCellKey; + pCur->info.nSize = 0; *pRes = 0; - rc = SQLITE_OK; - goto moveto_finish; + return SQLITE_OK; } } assert( lwr+upr>=0 ); @@ -63406,7 +64013,7 @@ moveto_next_layer: } moveto_finish: pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } @@ -63604,7 +64211,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ moveToParent(pCur); } assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 ); + assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); pCur->aiIdx[pCur->iPage]--; pPage = pCur->apPage[pCur->iPage]; @@ -64120,30 +64727,28 @@ static void freePage(MemPage *pPage, int *pRC){ static int clearCell( MemPage *pPage, /* The page that contains the Cell */ unsigned char *pCell, /* First byte of the Cell */ - u16 *pnSize /* Write the size of the Cell here */ + CellInfo *pInfo /* Size information about the cell */ ){ BtShared *pBt = pPage->pBt; - CellInfo info; Pgno ovflPgno; int rc; int nOvfl; u32 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->xParseCell(pPage, pCell, &info); - *pnSize = info.nSize; - if( info.nLocal==info.nPayload ){ + pPage->xParseCell(pPage, pCell, pInfo); + if( pInfo->nLocal==pInfo->nPayload ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } - if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){ + if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ } - ovflPgno = get4byte(pCell + info.nSize - 4); + ovflPgno = get4byte(pCell + pInfo->nSize - 4); assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; - nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; assert( nOvfl>0 || - (CORRUPT_DB && (info.nPayload + ovflPageSize)nPayload + ovflPageSize)nKey); }else{ - assert( pX->nData==0 ); - assert( pX->nZero==0 ); assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); nSrc = nPayload = (int)pX->nKey; pSrc = pX->pKey; @@ -64385,7 +64988,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; - assert( idx>=0 && idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -64469,7 +65071,10 @@ static void insertCell( put4byte(pCell, iChild); } j = pPage->nOverflow++; - assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); + /* Comparison against ArraySize-1 since we hold back one extra slot + ** as a contingency. In other words, never need more than 3 overflow + ** slots but 4 are allocated, just to be safe. */ + assert( j < ArraySize(pPage->apOvfl)-1 ); pPage->apOvfl[j] = pCell; pPage->aiOvfl[j] = (u16)i; @@ -65209,7 +65814,7 @@ static int balance_nonroot( nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; if( (i--)==0 ) break; - if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ + if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]); @@ -66063,17 +66668,19 @@ static int balance(BtCursor *pCur){ ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to -** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already -** been performed. seekResult is the search result returned (a negative -** number if pCur points at an entry that is smaller than (pKey, nKey), or -** a positive value if pCur points at an entry that is larger than -** (pKey, nKey)). +** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already +** been performed. In other words, if seekResult!=0 then the cursor +** is currently pointing to a cell that will be adjacent to the cell +** to be inserted. If seekResult<0 then pCur points to a cell that is +** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell +** that is larger than (pKey,nKey). ** -** If the seekResult parameter is non-zero, then the caller guarantees that -** cursor pCur is pointing at the existing copy of a row that is to be -** overwritten. If the seekResult parameter is 0, then cursor pCur may -** point to any entry or to no entry at all and so this function has to seek -** the cursor before the new key can be inserted. +** If seekResult==0, that means pCur is pointing at some unknown location. +** In that case, this routine must seek the cursor to the correct insertion +** point for (pKey,nKey) before doing the insertion. For index btrees, +** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked +** key values and pX->aMem can be used instead of pX->pKey to avoid having +** to decode the key. */ SQLITE_PRIVATE int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ @@ -66134,15 +66741,30 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( /* If the cursor is currently on the last row and we are appending a ** new row onto the end, set the "loc" to avoid an unnecessary ** btreeMoveto() call */ - if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 - && pCur->info.nKey==pX->nKey-1 ){ - loc = -1; + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ + loc = 0; + }else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 + && pCur->info.nKey==pX->nKey-1 ){ + loc = -1; }else if( loc==0 ){ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc); if( rc ) return rc; } }else if( loc==0 ){ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc); + if( pX->nMem ){ + UnpackedRecord r; + r.pKeyInfo = pCur->pKeyInfo; + r.aMem = pX->aMem; + r.nField = pX->nMem; + r.default_rc = 0; + r.errCode = 0; + r.r1 = 0; + r.r2 = 0; + r.eqSeen = 0; + rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, appendBias, &loc); + }else{ + rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc); + } if( rc ) return rc; } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); @@ -66163,7 +66785,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( assert( szNew <= MX_CELL_SIZE(pBt) ); idx = pCur->aiIdx[pCur->iPage]; if( loc==0 ){ - u16 szOld; + CellInfo info; assert( idxnCell ); rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ @@ -66173,8 +66795,19 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } - rc = clearCell(pPage, oldCell, &szOld); - dropCell(pPage, idx, szOld, &rc); + rc = clearCell(pPage, oldCell, &info); + if( info.nSize==szNew && info.nLocal==info.nPayload ){ + /* Overwrite the old cell with the new if they are the same size. + ** We could also try to do this if the old cell is smaller, then add + ** the leftover space to the free list. But experiments show that + ** doing that is no faster then skipping this optimization and just + ** calling dropCell() and insertCell(). */ + assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ + if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; + memcpy(oldCell, newCell, szNew); + return SQLITE_OK; + } + dropCell(pPage, idx, info.nSize, &rc); if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); @@ -66250,7 +66883,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ unsigned char *pCell; /* Pointer to cell to delete */ int iCellIdx; /* Index of cell to delete */ int iCellDepth; /* Depth of node containing pCell */ - u16 szCell; /* Size of the cell being deleted */ + CellInfo info; /* Size of the cell being deleted */ int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ @@ -66322,8 +66955,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ ** itself from within the page. */ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; - rc = clearCell(pPage, pCell, &szCell); - dropCell(pPage, iCellIdx, szCell, &rc); + rc = clearCell(pPage, pCell, &info); + dropCell(pPage, iCellIdx, info.nSize, &rc); if( rc ) return rc; /* If the cell deleted was not located on a leaf page, then the cursor @@ -66573,7 +67206,7 @@ static int clearDatabasePage( unsigned char *pCell; int i; int hdr; - u16 szCell; + CellInfo info; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ @@ -66593,7 +67226,7 @@ static int clearDatabasePage( rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } - rc = clearCell(pPage, pCell, &szCell); + rc = clearCell(pPage, pCell, &info); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ @@ -66684,27 +67317,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); - - /* It is illegal to drop a table if any cursors are open on the - ** database. This is because in auto-vacuum mode the backend may - ** need to move another root-page to fill a gap left by the deleted - ** root page. If an open cursor was using this page a problem would - ** occur. - ** - ** This error is caught long before control reaches this point. - */ - if( NEVER(pBt->pCursor) ){ - sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); - return SQLITE_LOCKED_SHAREDCACHE; - } - - /* - ** It is illegal to drop the sqlite_master table on page 1. But again, - ** this error is caught long before reaching this point. - */ - if( NEVER(iTable<2) ){ - return SQLITE_CORRUPT_BKPT; - } + assert( iTable>=2 ); rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; @@ -67612,7 +68225,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int * if( pBt->inTransaction!=TRANS_NONE ){ rc = SQLITE_LOCKED; }else{ - rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); + rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); } sqlite3BtreeLeave(p); } @@ -67934,22 +68547,16 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ - Parse *pParse; + Parse sParse; int rc = 0; - pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); - if( pParse==0 ){ - sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); - rc = SQLITE_NOMEM_BKPT; - }else{ - pParse->db = pDb; - if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); - rc = SQLITE_ERROR; - } - sqlite3DbFree(pErrorDb, pParse->zErrMsg); - sqlite3ParserReset(pParse); - sqlite3StackFree(pErrorDb, pParse); + memset(&sParse, 0, sizeof(sParse)); + sParse.db = pDb; + if( sqlite3OpenTempDatabase(&sParse) ){ + sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); + rc = SQLITE_ERROR; } + sqlite3DbFree(pErrorDb, sParse.zErrMsg); + sqlite3ParserReset(&sParse); if( rc ){ return 0; } @@ -67995,7 +68602,7 @@ static int checkReadTransaction(sqlite3 *db, Btree *p){ ** If an error occurs, NULL is returned and an error code and error message ** stored in database handle pDestDb. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3* pDestDb, /* Database to write to */ const char *zDestDb, /* Name of database within pDestDb */ sqlite3* pSrcDb, /* Database connection to read from */ @@ -68047,7 +68654,6 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( p->isAttached = 0; if( 0==p->pSrc || 0==p->pDest - || setDestPgsz(p)==SQLITE_NOMEM || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK ){ /* One (or both) of the named databases did not exist or an OOM @@ -68203,7 +68809,7 @@ static void attachBackupObject(sqlite3_backup *p){ /* ** Copy nPage pages from the source b-tree to the destination. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ int rc; int destMode; /* Destination journal mode */ int pgszSrc = 0; /* Source page size */ @@ -68235,14 +68841,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ rc = SQLITE_OK; } - /* Lock the destination database, if it is not locked already. */ - if( SQLITE_OK==rc && p->bDestLocked==0 - && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) - ){ - p->bDestLocked = 1; - sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); - } - /* If there is no open read-transaction on the source database, open ** one now. If a transaction is opened here, then it will be closed ** before this function exits. @@ -68252,6 +68850,24 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ bCloseTrans = 1; } + /* If the destination database has not yet been locked (i.e. if this + ** is the first call to backup_step() for the current backup operation), + ** try to set its page size to the same as the source database. This + ** is especially important on ZipVFS systems, as in that case it is + ** not possible to create a database file that uses one page size by + ** writing to it with another. */ + if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){ + rc = SQLITE_NOMEM; + } + + /* Lock the destination database, if it is not locked already. */ + if( SQLITE_OK==rc && p->bDestLocked==0 + && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) + ){ + p->bDestLocked = 1; + sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); + } + /* Do not allow backup if the destination database is in WAL mode ** and the page sizes are different between source and destination */ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); @@ -68447,7 +69063,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ /* ** Release all resources associated with an sqlite3_backup* handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3 *pSrcDb; /* Source database connection */ int rc; /* Value to return */ @@ -68499,7 +69115,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ ** Return the number of pages still to be backed up as of the most recent ** call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -68513,7 +69129,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ ** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -68840,18 +69456,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ - int f; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( (pMem->flags&MEM_RowSet)==0 ); - ExpandBlob(pMem); - f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ - if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ - return SQLITE_NOMEM_BKPT; + if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ + if( ExpandBlob(pMem) ) return SQLITE_NOMEM; + if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ + return SQLITE_NOMEM_BKPT; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; } pMem->flags &= ~MEM_Ephem; #ifdef SQLITE_DEBUG @@ -68867,25 +69483,24 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ */ #ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ - if( pMem->flags & MEM_Zero ){ - int nByte; - assert( pMem->flags&MEM_Blob ); - assert( (pMem->flags&MEM_RowSet)==0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + int nByte; + assert( pMem->flags & MEM_Zero ); + assert( pMem->flags&MEM_Blob ); + assert( (pMem->flags&MEM_RowSet)==0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - /* Set nByte to the number of bytes required to store the expanded blob. */ - nByte = pMem->n + pMem->u.nZero; - if( nByte<=0 ){ - nByte = 1; - } - if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ - return SQLITE_NOMEM_BKPT; - } - - memset(&pMem->z[pMem->n], 0, pMem->u.nZero); - pMem->n += pMem->u.nZero; - pMem->flags &= ~(MEM_Zero|MEM_Term); + /* Set nByte to the number of bytes required to store the expanded blob. */ + nByte = pMem->n + pMem->u.nZero; + if( nByte<=0 ){ + nByte = 1; } + if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ + return SQLITE_NOMEM_BKPT; + } + + memset(&pMem->z[pMem->n], 0, pMem->u.nZero); + pMem->n += pMem->u.nZero; + pMem->flags &= ~(MEM_Zero|MEM_Term); return SQLITE_OK; } #endif @@ -68945,6 +69560,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + pMem->enc = 0; return SQLITE_NOMEM_BKPT; } @@ -69226,7 +69842,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ } } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); - pMem->flags &= ~(MEM_Str|MEM_Blob); + pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero); return SQLITE_OK; } @@ -69244,7 +69860,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ if( (pMem->flags & MEM_Blob)==0 ){ sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - MemSetTypeFlag(pMem, MEM_Blob); + if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); }else{ pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); } @@ -69585,10 +70201,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( /* ** Move data out of a btree key or data field and into a Mem structure. -** The data or key is taken from the entry that pCur is currently pointing +** The data is payload from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. -** key is true to get the key or false to get data. The result is written -** into the pMem element. +** The result is written into the pMem element. ** ** The pMem object must have been initialized. This routine will use ** pMem->zMalloc to hold the content from the btree, if possible. New @@ -69603,17 +70218,12 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ - int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ int rc; pMem->flags = MEM_Null; if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ - if( key ){ - rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); - }else{ - rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); - } + rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); if( rc==SQLITE_OK ){ pMem->z[amt] = 0; pMem->z[amt+1] = 0; @@ -69629,7 +70239,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ - int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ @@ -69650,7 +70259,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; }else{ - rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem); + rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem); } return rc; @@ -69669,9 +70278,6 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert( (pVal->flags & (MEM_Null))==0 ); if( pVal->flags & (MEM_Blob|MEM_Str) ){ pVal->flags |= MEM_Str; - if( pVal->flags & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pVal); - } if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); } @@ -69924,10 +70530,7 @@ static int valueFromExpr( const char *zNeg = ""; int rc = SQLITE_OK; - if( !pExpr ){ - *ppVal = 0; - return SQLITE_OK; - } + assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; @@ -69997,6 +70600,7 @@ static int valueFromExpr( }else if( op==TK_NULL ){ pVal = valueNew(db, pCtx); if( pVal==0 ) goto no_mem; + sqlite3VdbeMemNumerify(pVal); } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ @@ -70051,7 +70655,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr( u8 affinity, /* Affinity to use */ sqlite3_value **ppVal /* Write the new value here */ ){ - return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0); + return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; } #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 @@ -70171,9 +70775,9 @@ static int stat4ValueFromExpr( ** structures intended to be compared against sample index keys stored ** in the sqlite_stat4 table. ** -** A single call to this function attempts to populates field iVal (leftmost -** is 0 etc.) of the unpacked record with a value extracted from expression -** pExpr. Extraction of values is possible if: +** A single call to this function populates zero or more fields of the +** record starting with field iVal (fields are numbered from left to +** right starting with 0). A single field is populated if: ** ** * (pExpr==0). In this case the value is assumed to be an SQL NULL, ** @@ -70182,10 +70786,14 @@ static int stat4ValueFromExpr( ** * The sqlite3ValueFromExpr() function is able to extract a value ** from the expression (i.e. the expression is a literal value). ** -** If a value can be extracted, the affinity passed as the 5th argument -** is applied to it before it is copied into the UnpackedRecord. Output -** parameter *pbOk is set to true if a value is extracted, or false -** otherwise. +** Or, if pExpr is a TK_VECTOR, one field is populated for each of the +** vector components that match either of the two latter criteria listed +** above. +** +** Before any value is appended to the record, the affinity of the +** corresponding column within index pIdx is applied to it. Before +** this function returns, output parameter *pnExtract is set to the +** number of values appended to the record. ** ** When this function is called, *ppRec must either point to an object ** allocated by an earlier call to this function, or must be NULL. If it @@ -70201,22 +70809,33 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( Index *pIdx, /* Index being probed */ UnpackedRecord **ppRec, /* IN/OUT: Probe record */ Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ + int nElem, /* Maximum number of values to append */ int iVal, /* Array element to populate */ - int *pbOk /* OUT: True if value was extracted */ + int *pnExtract /* OUT: Values appended to the record */ ){ - int rc; - sqlite3_value *pVal = 0; - struct ValueNewStat4Ctx alloc; + int rc = SQLITE_OK; + int nExtract = 0; - alloc.pParse = pParse; - alloc.pIdx = pIdx; - alloc.ppRec = ppRec; - alloc.iVal = iVal; + if( pExpr==0 || pExpr->op!=TK_SELECT ){ + int i; + struct ValueNewStat4Ctx alloc; - rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal); - assert( pVal==0 || pVal->db==pParse->db ); - *pbOk = (pVal!=0); + alloc.pParse = pParse; + alloc.pIdx = pIdx; + alloc.ppRec = ppRec; + + for(i=0; idb, pIdx, iVal+i); + alloc.iVal = iVal+i; + rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal); + if( !pVal ) break; + nExtract++; + } + } + + *pnExtract = nExtract; return rc; } @@ -70379,8 +70998,9 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ sqlite3 *db = pParse->db; Vdbe *p; - p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); + p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); if( p==0 ) return 0; + memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); p->db = db; if( db->pVdbe ){ db->pVdbe->pPrev = p; @@ -70542,9 +71162,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ if( p->db->flags & SQLITE_VdbeAddopTrace ){ int jj, kk; Parse *pParse = p->pParse; - for(jj=kk=0; jjnColCache; jj++){ struct yColCache *x = pParse->aColCache + jj; - if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); kk++; } @@ -70671,7 +71290,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( int p4 /* The P4 operand as an integer */ ){ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); + if( p->db->mallocFailed==0 ){ + VdbeOp *pOp = &p->aOp[addr]; + pOp->p4type = P4_INT32; + pOp->p4.i = p4; + } return addr; } @@ -70732,7 +71355,6 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ if( p->aLabel ){ p->aLabel[j] = v->nOp; } - p->iFixedOp = v->nOp - 1; } /* @@ -71123,7 +71745,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ - if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5; + assert( p->nOp>0 || p->db->mallocFailed ); + if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } /* @@ -71131,7 +71754,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ ** the address of the next instruction to be coded. */ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - p->pParse->iFixedOp = p->nOp - 1; sqlite3VdbeChangeP2(p, addr, p->nOp); } @@ -71183,10 +71805,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ break; } #endif - case P4_MPRINTF: { - if( db->pnBytesFreed==0 ) sqlite3_free(p4); - break; - } case P4_FUNCDEF: { freeEphemeralFunction(db, (FuncDef*)p4); break; @@ -71254,7 +71872,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ ** then remove it. Return true if and only if an opcode was removed. */ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ - if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ + if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){ return sqlite3VdbeChangeToNoop(p, p->nOp-1); }else{ return 0; @@ -71331,16 +71949,42 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int } } +/* +** Change the P4 operand of the most recently coded instruction +** to the value defined by the arguments. This is a high-speed +** version of sqlite3VdbeChangeP4(). +** +** The P4 operand must not have been previously defined. And the new +** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of +** those cases. +*/ +SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){ + VdbeOp *pOp; + assert( n!=P4_INT32 && n!=P4_VTAB ); + assert( n<=0 ); + if( p->db->mallocFailed ){ + freeP4(p->db, n, pP4); + }else{ + assert( pP4!=0 ); + assert( p->nOp>0 ); + pOp = &p->aOp[p->nOp-1]; + assert( pOp->p4type==P4_NOTUSED ); + pOp->p4type = n; + pOp->p4.p = pP4; + } +} + /* ** Set the P4 on the most recently added opcode to the KeyInfo for the ** index given. */ SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){ Vdbe *v = pParse->pVdbe; + KeyInfo *pKeyInfo; assert( v!=0 ); assert( pIdx!=0 ); - sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx), - P4_KEYINFO); + pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx); + if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); } #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS @@ -71452,12 +72096,21 @@ static int displayComment( const char *zSynopsis; int nOpName; int ii, jj; + char zAlt[50]; zOpName = sqlite3OpcodeName(pOp->opcode); nOpName = sqlite3Strlen30(zOpName); if( zOpName[nOpName+1] ){ int seenCom = 0; char c; zSynopsis = zOpName += nOpName + 1; + if( strncmp(zSynopsis,"IF ",3)==0 ){ + if( pOp->p5 & SQLITE_STOREP2 ){ + sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3); + }else{ + sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3); + } + zSynopsis = zAlt; + } for(ii=jj=0; jjzName, pDef->nArg); break; } -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); @@ -71808,6 +72461,21 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ } #endif +/* +** Initialize an array of N Mem element. +*/ +static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ + while( (N--)>0 ){ + p->db = db; + p->flags = flags; + p->szMalloc = 0; +#ifdef SQLITE_DEBUG + p->pScopyFrom = 0; +#endif + p++; + } +} + /* ** Release an array of N Mem elements */ @@ -72019,6 +72687,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->flags = MEM_Str|MEM_Term; zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); if( zP4!=pMem->z ){ + pMem->n = 0; sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); }else{ assert( pMem->z!=0 ); @@ -72161,7 +72830,7 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ int i; #endif assert( p!=0 ); - assert( p->magic==VDBE_MAGIC_INIT ); + assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET ); /* There should be at least one opcode. */ @@ -72218,7 +72887,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( int nMem; /* Number of VM memory registers */ int nCursor; /* Number of cursors required */ int nArg; /* Number of arguments in subprograms */ - int nOnce; /* Number of OP_Once instructions */ int n; /* Loop counter */ struct ReusableSpace x; /* Reusable bulk memory */ @@ -72233,8 +72901,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( nMem = pParse->nMem; nCursor = pParse->nTab; nArg = pParse->nMaxArg; - nOnce = pParse->nOnce; - if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ /* Each cursor uses a memory cell. The first cursor (cursor 0) can ** use aMem[0] which is not otherwise used by the VDBE program. Allocate @@ -72253,10 +72919,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); - if( x.nFree>0 ){ - memset(x.pSpace, 0, x.nFree); - assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); - } + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); @@ -72281,36 +72944,32 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); - p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); #endif if( x.nNeeded==0 ) break; - x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); + x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); x.nFree = x.nNeeded; }while( !db->mallocFailed ); - p->nCursor = nCursor; - p->nOnceFlag = nOnce; - if( p->aVar ){ - p->nVar = (ynVar)nVar; - for(n=0; naVar[n].flags = MEM_Null; - p->aVar[n].db = db; - } - } - p->nzVar = pParse->nzVar; - p->azVar = pParse->azVar; - pParse->nzVar = 0; - pParse->azVar = 0; - if( p->aMem ){ - p->nMem = nMem; - for(n=0; naMem[n].flags = MEM_Undefined; - p->aMem[n].db = db; - } - } + p->pVList = pParse->pVList; + pParse->pVList = 0; p->explain = pParse->explain; + if( db->mallocFailed ){ + p->nVar = 0; + p->nCursor = 0; + p->nMem = 0; + }else{ + p->nCursor = nCursor; + p->nVar = (ynVar)nVar; + initMemArray(p->aVar, nVar, db, MEM_Null); + p->nMem = nMem; + initMemArray(p->aMem, nMem, db, MEM_Undefined); + memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + memset(p->anExec, 0, p->nOp*sizeof(i64)); +#endif + } sqlite3VdbeRewind(p); } @@ -72322,15 +72981,15 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } - assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE ); + assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE ); switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); break; } case CURTYPE_BTREE: { - if( pCx->pBt ){ - sqlite3BtreeClose(pCx->pBt); + if( pCx->pBtx ){ + sqlite3BtreeClose(pCx->pBtx); /* The pCx->pCursor will be close automatically, if it exists, by ** the call above. */ }else{ @@ -72379,8 +73038,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS v->anExec = pFrame->anExec; #endif - v->aOnceFlag = pFrame->aOnceFlag; - v->nOnceFlag = pFrame->nOnceFlag; v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; @@ -72464,13 +73121,9 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ sqlite3DbFree(db, p->aColName); n = nResColumn*COLNAME_N; p->nResColumn = (u16)nResColumn; - p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); + p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; - while( n-- > 0 ){ - pColName->flags = MEM_Null; - pColName->db = p->db; - pColName++; - } + initMemArray(p->aColName, n, p->db, MEM_Null); } /* @@ -72921,7 +73574,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } - if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK; @@ -73233,7 +73885,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ } #endif p->iCurrentTime = 0; - p->magic = VDBE_MAGIC_INIT; + p->magic = VDBE_MAGIC_RESET; return p->rc & db->errMask; } @@ -73295,26 +73947,29 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, */ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; - int i; assert( p->db==0 || p->db==db ); - releaseMemArray(p->aVar, p->nVar); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } - for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); - sqlite3DbFree(db, p->azVar); + if( p->magic!=VDBE_MAGIC_INIT ){ + releaseMemArray(p->aVar, p->nVar); + sqlite3DbFree(db, p->pVList); + sqlite3DbFree(db, p->pFree); + } vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); - sqlite3DbFree(db, p->pFree); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - for(i=0; inScan; i++){ - sqlite3DbFree(db, p->aScan[i].zName); + { + int i; + for(i=0; inScan; i++){ + sqlite3DbFree(db, p->aScan[i].zName); + } + sqlite3DbFree(db, p->aScan); } - sqlite3DbFree(db, p->aScan); #endif } @@ -73815,30 +74470,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( ** If an OOM error occurs, NULL is returned. */ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( - KeyInfo *pKeyInfo, /* Description of the record */ - char *pSpace, /* Unaligned space available */ - int szSpace, /* Size of pSpace[] in bytes */ - char **ppFree /* OUT: Caller should free this pointer */ + KeyInfo *pKeyInfo /* Description of the record */ ){ UnpackedRecord *p; /* Unpacked record to return */ - int nOff; /* Increment pSpace by nOff to align it */ int nByte; /* Number of bytes required for *p */ - - /* We want to shift the pointer pSpace up such that it is 8-byte aligned. - ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift - ** it by. If pSpace is already 8-byte aligned, nOff should be zero. - */ - nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7; nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); - if( nByte>szSpace+nOff ){ - p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); - *ppFree = (char *)p; - if( !p ) return 0; - }else{ - p = (UnpackedRecord*)&pSpace[nOff]; - *ppFree = 0; - } - + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); + if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( pKeyInfo->aSortOrder!=0 ); p->pKeyInfo = pKeyInfo; @@ -74065,15 +74703,49 @@ static int vdbeCompareMemString( } } +/* +** The input pBlob is guaranteed to be a Blob that is not marked +** with MEM_Zero. Return true if it could be a zero-blob. +*/ +static int isAllZero(const char *z, int n){ + int i; + for(i=0; iz, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n); + int c; + int n1 = pB1->n; + int n2 = pB2->n; + + /* It is possible to have a Blob value that has some non-zero content + ** followed by zero content. But that only comes up for Blobs formed + ** by the OP_MakeRecord opcode, and such Blobs never get passed into + ** sqlite3MemCompare(). */ + assert( (pB1->flags & MEM_Zero)==0 || n1==0 ); + assert( (pB2->flags & MEM_Zero)==0 || n2==0 ); + + if( (pB1->flags|pB2->flags) & MEM_Zero ){ + if( pB1->flags & pB2->flags & MEM_Zero ){ + return pB1->u.nZero - pB2->u.nZero; + }else if( pB1->flags & MEM_Zero ){ + if( !isAllZero(pB2->z, pB2->n) ) return -1; + return pB1->u.nZero - n2; + }else{ + if( !isAllZero(pB1->z, pB1->n) ) return +1; + return n1 - pB2->u.nZero; + } + } + c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1); if( c ) return c; - return pB1->n - pB2->n; + return n1 - n2; } /* @@ -74379,6 +75051,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* RHS is a blob */ else if( pRhs->flags & MEM_Blob ){ + assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 ); getVarint32(&aKey1[idx1], serial_type); testcase( serial_type==12 ); if( serial_type<12 || (serial_type & 0x01) ){ @@ -74390,6 +75063,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( if( (d1+nStr) > (unsigned)nKey1 ){ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ + }else if( pRhs->flags & MEM_Zero ){ + if( !isAllZero((const char*)&aKey1[d1],nStr) ){ + rc = 1; + }else{ + rc = nStr - pRhs->u.nZero; + } }else{ int nCmp = MIN(nStr, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); @@ -74460,7 +75139,7 @@ static int vdbeRecordCompareInt( int res; u32 y; u64 x; - i64 v = pPKey2->aMem[0].u.i; + i64 v; i64 lhs; vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); @@ -74519,6 +75198,7 @@ static int vdbeRecordCompareInt( return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); } + v = pPKey2->aMem[0].u.i; if( v>lhs ){ res = pPKey2->r1; }else if( viPKey; + preupdate.pTab = pTab; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); @@ -74969,7 +75649,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( ** collating sequences are registered or if an authorizer function is ** added or changed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p==0 || p->expired; } @@ -75038,7 +75718,7 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL @@ -75065,7 +75745,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; @@ -75086,7 +75766,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ /* ** Set all the parameters in the compiled SQL statement to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; @@ -75110,10 +75790,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ ** The following routines extract information from a Mem or sqlite3_value ** structure. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ + if( ExpandBlob(p)!=SQLITE_OK ){ assert( p->flags==MEM_Null && p->z==0 ); return 0; } @@ -75123,36 +75803,36 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ return sqlite3_value_text(pVal); } } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){ +SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ return sqlite3VdbeRealValue((Mem*)pVal); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ +SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); } -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){ +SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16BE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -75160,7 +75840,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal ** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating ** point number string BLOB NULL */ -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ +SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { SQLITE_BLOB, /* 0x00 */ SQLITE_NULL, /* 0x01 */ @@ -75200,7 +75880,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ /* Make a copy of an sqlite3_value object */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value *pOrig){ +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ sqlite3_value *pNew; if( pOrig==0 ) return 0; pNew = sqlite3_malloc( sizeof(*pNew) ); @@ -75223,7 +75903,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value * /* Destroy an sqlite3_value object previously obtained from ** sqlite3_value_dup(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value *pOld){ +SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ sqlite3ValueFree(pOld); } @@ -75266,7 +75946,7 @@ static int invokeValueDestructor( if( pCtx ) sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( +SQLITE_API void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, @@ -75276,7 +75956,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( +SQLITE_API void sqlite3_result_blob64( sqlite3_context *pCtx, const void *z, sqlite3_uint64 n, @@ -75290,43 +75970,43 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( setResultStrOrError(pCtx, z, (int)n, 0, xDel); } } -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){ +SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ +SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ +SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){ +SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ +SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ +SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text( +SQLITE_API void sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, @@ -75335,7 +76015,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( +SQLITE_API void sqlite3_result_text64( sqlite3_context *pCtx, const char *z, sqlite3_uint64 n, @@ -75352,7 +76032,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( +SQLITE_API void sqlite3_result_text16( sqlite3_context *pCtx, const void *z, int n, @@ -75361,7 +76041,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( +SQLITE_API void sqlite3_result_text16be( sqlite3_context *pCtx, const void *z, int n, @@ -75370,7 +76050,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( +SQLITE_API void sqlite3_result_text16le( sqlite3_context *pCtx, const void *z, int n, @@ -75380,15 +76060,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ +SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pCtx->pOut, pValue); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ @@ -75397,7 +76077,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); return SQLITE_OK; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; #ifdef SQLITE_DEBUG @@ -75410,7 +76090,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, } /* Force an SQLITE_TOOBIG error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; pCtx->fErrorOrAux = 1; @@ -75419,7 +76099,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx } /* An SQLITE_NOMEM error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; @@ -75443,7 +76123,7 @@ static int doWalCallbacks(sqlite3 *db){ nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); sqlite3BtreeLeave(pBt); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); } } } @@ -75591,7 +76271,7 @@ end_of_step: ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ @@ -75642,7 +76322,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ +SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData; } @@ -75657,7 +76337,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ ** sqlite3_create_function16() routines that originally registered the ** application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ assert( p && p->pOut ); return p->pOut->db; } @@ -75733,7 +76413,7 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ assert( p && p->pFunc && p->pFunc->xFinalize ); assert( sqlite3_mutex_held(p->pOut->db->mutex) ); testcase( nByte<0 ); @@ -75748,7 +76428,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, in ** Return the auxiliary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); @@ -75769,7 +76449,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int i ** argument to the user-function defined by pCtx. Any previous value is ** deleted by calling the delete function specified when it was set. */ -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( +SQLITE_API void sqlite3_set_auxdata( sqlite3_context *pCtx, int iArg, void *pAux, @@ -75824,7 +76504,7 @@ failed: ** implementations should keep their own counts within their aggregate ** context. */ -SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ +SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize ); return p->pMem->n; } @@ -75833,7 +76513,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ /* ** Return the number of columns in the result set for the statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; return pVm ? pVm->nResColumn : 0; } @@ -75842,7 +76522,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ ** Return the number of values available from the current row of the ** currently executing statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; @@ -75896,14 +76576,13 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ Mem *pOut; pVm = (Vdbe *)pStmt; - if( pVm && pVm->pResultSet!=0 && inResColumn && i>=0 ){ - sqlite3_mutex_enter(pVm->db->mutex); + if( pVm==0 ) return (Mem*)columnNullValue(); + assert( pVm->db ); + sqlite3_mutex_enter(pVm->db->mutex); + if( pVm->pResultSet!=0 && inResColumn && i>=0 ){ pOut = &pVm->pResultSet[i]; }else{ - if( pVm && ALWAYS(pVm->db) ){ - sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE); - } + sqlite3Error(pVm->db, SQLITE_RANGE); pOut = (Mem*)columnNullValue(); } return pOut; @@ -75936,6 +76615,8 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) */ Vdbe *p = (Vdbe *)pStmt; if( p ){ + assert( p->db!=0 ); + assert( sqlite3_mutex_held(p->db->mutex) ); p->rc = sqlite3ApiExit(p->db, p->rc); sqlite3_mutex_leave(p->db->mutex); } @@ -75945,7 +76626,7 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** The following routines are used to access elements of the current row ** in the result set. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might @@ -75955,37 +76636,37 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, i columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){ +SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){ +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ Mem *pOut = columnMem(pStmt, i); if( pOut->flags&MEM_Static ){ pOut->flags &= ~MEM_Static; @@ -75995,13 +76676,13 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStm return (sqlite3_value *)pOut; } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType; @@ -76065,12 +76746,12 @@ static const void *columnName( ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } @@ -76090,12 +76771,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } @@ -76108,12 +76789,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pS ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } @@ -76124,12 +76805,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stm ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } @@ -76140,12 +76821,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt * ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } @@ -76246,7 +76927,7 @@ static int bindText( /* ** Bind a blob value to an SQL statement variable. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( +SQLITE_API int sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, @@ -76258,7 +76939,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( #endif return bindText(pStmt, i, zData, nData, xDel, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( +SQLITE_API int sqlite3_bind_blob64( sqlite3_stmt *pStmt, int i, const void *zData, @@ -76272,7 +76953,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( return bindText(pStmt, i, zData, (int)nData, xDel, 0); } } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ +SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -76282,10 +76963,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, do } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ +SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -76295,7 +76976,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sql } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); @@ -76304,7 +76985,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( +SQLITE_API int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, @@ -76313,7 +76994,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( +SQLITE_API int sqlite3_bind_text64( sqlite3_stmt *pStmt, int i, const char *zData, @@ -76330,7 +77011,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( +SQLITE_API int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, @@ -76340,7 +77021,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ +SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { @@ -76371,7 +77052,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, con } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -76381,7 +77062,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ int rc; Vdbe *p = (Vdbe *)pStmt; sqlite3_mutex_enter(p->db->mutex); @@ -76400,7 +77081,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p ? p->nVar : 0; } @@ -76411,12 +77092,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ ** ** The result is always UTF-8. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ Vdbe *p = (Vdbe*)pStmt; - if( p==0 || i<1 || i>p->nzVar ){ - return 0; - } - return p->azVar[i-1]; + if( p==0 ) return 0; + return sqlite3VListNumToName(p->pVList, i); } /* @@ -76425,21 +77104,10 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt * ** return 0. */ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ - int i; - if( p==0 ){ - return 0; - } - if( zName ){ - for(i=0; inzVar; i++){ - const char *z = p->azVar[i]; - if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){ - return i+1; - } - } - } - return 0; + if( p==0 || zName==0 ) return 0; + return sqlite3VListNameToNum(p->pVList, zName, nName); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); } @@ -76473,7 +77141,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt ** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise ** SQLITE_OK is returned. */ -SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ +SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ @@ -76495,7 +77163,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, ** the first argument to the sqlite3_prepare() that was used to create ** the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->db : 0; } @@ -76503,16 +77171,16 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ ** Return true if the prepared statement is guaranteed to not modify the ** database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement is in need of being reset. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; + return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; } /* @@ -76521,7 +77189,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ ** prepared statement for the database connection. Return NULL if there ** are no more. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ sqlite3_stmt *pNext; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(pDb) ){ @@ -76542,7 +77210,7 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ /* ** Return the value of a status counter for a prepared statement */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR @@ -76559,7 +77227,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, i /* ** Return the SQL associated with a prepared statement */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe *)pStmt; return p ? p->zSql : 0; } @@ -76573,7 +77241,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ ** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of ** expanded bound parameters. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_expanded_sql(sqlite3_stmt *pStmt){ +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){ #ifdef SQLITE_OMIT_TRACE return 0; #else @@ -76600,10 +77268,9 @@ static UnpackedRecord *vdbeUnpackRecord( int nKey, const void *pKey ){ - char *dummy; /* Dummy argument for AllocUnpackedRecord() */ UnpackedRecord *pRet; /* Return value */ - pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); @@ -76615,7 +77282,7 @@ static UnpackedRecord *vdbeUnpackRecord( ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or deleted. */ -SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ +SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p = db->pPreUpdate; int rc = SQLITE_OK; @@ -76638,7 +77305,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlit nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; - rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec); + rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); if( rc==SQLITE_OK ){ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); if( !p->pUnpacked ) rc = SQLITE_NOMEM; @@ -76653,9 +77320,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlit if( iIdx>=p->pUnpacked->nField ){ *ppValue = (sqlite3_value *)columnNullValue(); }else{ + Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; *ppValue = &p->pUnpacked->aMem[iIdx]; - if( iIdx==p->iPKey ){ - sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); + if( iIdx==p->pTab->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey1); + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ + if( pMem->flags & MEM_Int ){ + sqlite3VdbeMemRealify(pMem); + } } } @@ -76670,7 +77342,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlit ** This function is called from within a pre-update callback to retrieve ** the number of columns in the row being updated, deleted or inserted. */ -SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *db){ +SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; return (p ? p->keyinfo.nField : 0); } @@ -76688,7 +77360,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *db){ ** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL ** or SET DEFAULT action is considered a trigger. */ -SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *db){ +SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; return (p ? p->v->nFrame : 0); } @@ -76699,7 +77371,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *db){ ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or inserted. */ -SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ +SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p = db->pPreUpdate; int rc = SQLITE_OK; Mem *pMem; @@ -76719,7 +77391,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlit UnpackedRecord *pUnpack = p->pNewUnpacked; if( !pUnpack ){ Mem *pData = &p->v->aMem[p->iNewReg]; - rc = sqlite3VdbeMemExpandBlob(pData); + rc = ExpandBlob(pData); if( rc!=SQLITE_OK ) goto preupdate_new_out; pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z); if( !pUnpack ){ @@ -76732,7 +77404,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlit pMem = (sqlite3_value *)columnNullValue(); }else{ pMem = &pUnpack->aMem[iIdx]; - if( iIdx==p->iPKey ){ + if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); } } @@ -76753,7 +77425,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlit assert( iIdx>=0 && iIdxpCsr->nField ); pMem = &p->aNew[iIdx]; if( pMem->flags==0 ){ - if( iIdx==p->iPKey ){ + if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); }else{ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); @@ -76773,7 +77445,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlit /* ** Return status data for a single loop within query pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement being queried */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ @@ -76832,7 +77504,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( /* ** Zero all counters associated with the sqlite3_stmt_scanstatus() data. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; memset(p->anExec, 0, p->nOp * sizeof(i64)); } @@ -77150,7 +77822,7 @@ SQLITE_API int sqlite3_found_count = 0; ** Test a register to see if it exceeds the current maximum blob size. ** If it does, record the new maximum blob size. */ -#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) +#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE) # define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) #else # define UPDATE_MAX_BLOBSIZE(P) @@ -77260,7 +77932,7 @@ static VdbeCursor *allocateCursor( } if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; - memset(pCx, 0, sizeof(VdbeCursor)); + memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); pCx->eCurType = eCurType; pCx->iDb = iDb; pCx->nField = nField; @@ -77359,7 +78031,7 @@ static void applyAffinity( ** is appropriate. But only do the conversion if it is possible without ** loss of information and return the revised type of the argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; @@ -77701,7 +78373,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ - int iCompare = 0; /* Result of last OP_Compare operation */ + int iCompare = 0; /* Result of last comparison */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */ @@ -78033,7 +78705,7 @@ case OP_Yield: { /* in1, jump */ } /* Opcode: HaltIfNull P1 P2 P3 P4 P5 -** Synopsis: if r[P3]=null halt +** Synopsis: if r[P3]=null halt ** ** Check the value in register P3. If it is NULL then Halt using ** parameter P1, P2, and P4 as if this were a Halt instruction. If the @@ -78105,7 +78777,7 @@ case OP_Halt: { p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pcx; - assert( pOp->p5>=0 && pOp->p5<=4 ); + assert( pOp->p5<=4 ); if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", @@ -78246,7 +78918,7 @@ case OP_String: { /* out2 */ } /* Opcode: Null P1 P2 P3 * * -** Synopsis: r[P2..P3]=NULL +** Synopsis: r[P2..P3]=NULL ** ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 @@ -78264,18 +78936,20 @@ case OP_Null: { /* out2 */ cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + pOut->n = 0; while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); sqlite3VdbeMemSetNull(pOut); pOut->flags = nullFlag; + pOut->n = 0; cnt--; } break; } /* Opcode: SoftNull P1 * * * * -** Synopsis: r[P1]=NULL +** Synopsis: r[P1]=NULL ** ** Set register P1 to have the value NULL as seen by the OP_MakeRecord ** instruction, but do not free any string or blob memory associated with @@ -78316,7 +78990,7 @@ case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); - assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] ); + assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) ); pVar = &p->aVar[pOp->p1 - 1]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; @@ -78328,7 +79002,7 @@ case OP_Variable: { /* out2 */ } /* Opcode: Move P1 P2 P3 * * -** Synopsis: r[P2@P3]=r[P1@P3] +** Synopsis: r[P2@P3]=r[P1@P3] ** ** Move the P3 values in register P1..P1+P3-1 over into ** registers P2..P2+P3-1. Registers P1..P1+P3-1 are @@ -78438,7 +79112,7 @@ case OP_IntCopy: { /* out2 */ } /* Opcode: ResultRow P1 P2 * * * -** Synopsis: output=r[P1@P2] +** Synopsis: output=r[P1@P2] ** ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate @@ -78571,14 +79245,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ } /* Opcode: Add P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]+r[P2] +** Synopsis: r[P3]=r[P1]+r[P2] ** ** Add the value in register P1 to the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Multiply P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]*r[P2] +** Synopsis: r[P3]=r[P1]*r[P2] ** ** ** Multiply the value in register P1 by the value in register P2 @@ -78586,14 +79260,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** If either input is NULL, the result is NULL. */ /* Opcode: Subtract P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]-r[P1] +** Synopsis: r[P3]=r[P2]-r[P1] ** ** Subtract the value in register P1 from the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Divide P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]/r[P1] +** Synopsis: r[P3]=r[P2]/r[P1] ** ** Divide the value in register P1 by the value in register P2 ** and store the result in register P3 (P3=P2/P1). If the value in @@ -78601,7 +79275,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]%r[P1] +** Synopsis: r[P3]=r[P2]%r[P1] ** ** Compute the remainder after integer register P2 is divided by ** register P1 and store the result in register P3. @@ -78834,21 +79508,21 @@ case OP_Function: { } /* Opcode: BitAnd P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]&r[P2] +** Synopsis: r[P3]=r[P1]&r[P2] ** ** Take the bit-wise AND of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: BitOr P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]|r[P2] +** Synopsis: r[P3]=r[P1]|r[P2] ** ** Take the bit-wise OR of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: ShiftLeft P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]<>r[P1] +** Synopsis: r[P3]=r[P2]>>r[P1] ** ** Shift the integer value in register P2 to the right by the ** number of bits specified by the integer in register P1. @@ -78916,7 +79590,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ } /* Opcode: AddImm P1 P2 * * * -** Synopsis: r[P1]=r[P1]+P2 +** Synopsis: r[P1]=r[P1]+P2 ** ** Add the constant P2 to the value in register P1. ** The result is always an integer. @@ -79008,14 +79682,61 @@ case OP_Cast: { /* in1 */ } #endif /* SQLITE_OMIT_CAST */ +/* Opcode: Eq P1 P2 P3 P4 P5 +** Synopsis: IF r[P3]==r[P1] +** +** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then +** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then +** store the result of comparison in register P2. +** +** The SQLITE_AFF_MASK portion of P5 must be an affinity character - +** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made +** to coerce both inputs according to this affinity before the +** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric +** affinity is used. Note that the affinity conversions are stored +** back into the input registers P1 and P3. So this opcode can cause +** persistent changes to registers P1 and P3. +** +** Once any conversions have taken place, and neither value is NULL, +** the values are compared. If both values are blobs then memcmp() is +** used to determine the results of the comparison. If both values +** are text, then the appropriate collating function specified in +** P4 is used to do the comparison. If P4 is not specified then +** memcmp() is used to compare text string. If both values are +** numeric, then a numeric comparison is used. If the two values +** are of different types, then numbers are considered less than +** strings and strings are considered less than blobs. +** +** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either +** true or false and is never NULL. If both operands are NULL then the result +** of comparison is true. If either operand is NULL then the result is false. +** If neither operand is NULL the result is the same as it would be if +** the SQLITE_NULLEQ flag were omitted from P5. +** +** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the +** content of r[P2] is only changed if the new value is NULL or 0 (false). +** In other words, a prior r[P2] value will not be overwritten by 1 (true). +*/ +/* Opcode: Ne P1 P2 P3 P4 P5 +** Synopsis: IF r[P3]!=r[P1] +** +** This works just like the Eq opcode except that the jump is taken if +** the operands in registers P1 and P3 are not equal. See the Eq opcode for +** additional information. +** +** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the +** content of r[P2] is only changed if the new value is NULL or 1 (true). +** In other words, a prior r[P2] value will not be overwritten by 0 (false). +*/ /* Opcode: Lt P1 P2 P3 P4 P5 -** Synopsis: if r[P1]r[P3] goto P2 +** Synopsis: IF r[P3]>r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than the content of ** register P1. See the Lt opcode for additional information. */ /* Opcode: Ge P1 P2 P3 P4 P5 -** Synopsis: if r[P1]>=r[P3] goto P2 +** Synopsis: IF r[P3]>=r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than or equal to the content of @@ -79096,7 +79784,7 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ - int res; /* Result of the comparison of pIn1 against pIn3 */ + int res, res2; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ @@ -79115,13 +79803,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); - if( (flags1&MEM_Null)!=0 - && (flags3&MEM_Null)!=0 + if( (flags1&flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ - res = 0; /* Results are equal */ + res = 0; /* Operands are equal */ }else{ - res = 1; /* Results are not equal */ + res = 1; /* Operands are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, @@ -79130,6 +79817,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; + iCompare = 1; /* Operands are not equal */ memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); @@ -79148,12 +79836,21 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ if( (flags1 | flags3)&MEM_Str ){ if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); + testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ flags3 = pIn3->flags; } if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3,0); } } + /* Handle the common case of integer comparison here, as an + ** optimization, to avoid a call to sqlite3MemCompare() */ + if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){ + if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; } + if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; } + res = 0; + goto compare_op; + } }else if( affinity==SQLITE_AFF_TEXT ){ if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn1->flags & MEM_Int ); @@ -79161,7 +79858,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); - flags3 = pIn3->flags; + assert( pIn1!=pIn3 ); } if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn3->flags & MEM_Int ); @@ -79172,23 +79869,16 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ } } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - if( flags1 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn1); - flags1 &= ~MEM_Zero; - } - if( flags3 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn3); - flags3 &= ~MEM_Zero; - } res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } +compare_op: switch( pOp->opcode ){ - case OP_Eq: res = res==0; break; - case OP_Ne: res = res!=0; break; - case OP_Lt: res = res<0; break; - case OP_Le: res = res<=0; break; - case OP_Gt: res = res>0; break; - default: res = res>=0; break; + case OP_Eq: res2 = res==0; break; + case OP_Ne: res2 = res; break; + case OP_Lt: res2 = res<0; break; + case OP_Le: res2 = res<=0; break; + case OP_Gt: res2 = res>0; break; + default: res2 = res>=0; break; } /* Undo any changes made by applyAffinity() to the input registers. */ @@ -79199,19 +79889,55 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; + iCompare = res; + res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */ + if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){ + /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1 + ** and prevents OP_Ne from overwriting NULL with 0. This flag + ** is only used in contexts where either: + ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0) + ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1) + ** Therefore it is not necessary to check the content of r[P2] for + ** NULL. */ + assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq ); + assert( res2==0 || res2==1 ); + testcase( res2==0 && pOp->opcode==OP_Eq ); + testcase( res2==1 && pOp->opcode==OP_Eq ); + testcase( res2==0 && pOp->opcode==OP_Ne ); + testcase( res2==1 && pOp->opcode==OP_Ne ); + if( (pOp->opcode==OP_Eq)==res2 ) break; + } memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = res; + pOut->u.i = res2; REGISTER_TRACE(pOp->p2, pOut); }else{ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); - if( res ){ + if( res2 ){ goto jump_to_p2; } } break; } +/* Opcode: ElseNotEq * P2 * * * +** +** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator. +** If result of an OP_Eq comparison on the same two operands +** would have be NULL or false (0), then then jump to P2. +** If the result of an OP_Eq comparison on the two previous operands +** would have been true (1), then fall through. +*/ +case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */ + assert( pOp>aOp ); + assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt ); + assert( pOp[-1].p5 & SQLITE_STOREP2 ); + VdbeBranchTaken(iCompare!=0, 2); + if( iCompare!=0 ) goto jump_to_p2; + break; +} + + /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array @@ -79407,22 +80133,18 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ /* Opcode: Once P1 P2 * * * ** -** Check the "once" flag number P1. If it is set, jump to instruction P2. -** Otherwise, set the flag and fall through to the next instruction. -** In other words, this opcode causes all following opcodes up through P2 -** (but not including P2) to run just once and to be skipped on subsequent -** times through the loop. -** -** All "once" flags are initially cleared whenever a prepared statement -** first begins to run. +** If the P1 value is equal to the P1 value on the OP_Init opcode at +** instruction 0, then jump to P2. If the two P1 values differ, then +** set the P1 value on this opcode to equal the P1 value on the OP_Init +** and fall through. */ case OP_Once: { /* jump */ - assert( pOp->p1nOnceFlag ); - VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); - if( p->aOnceFlag[pOp->p1] ){ + assert( p->aOp[0].opcode==OP_Init ); + VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2); + if( p->aOp[0].p1==pOp->p1 ){ goto jump_to_p2; }else{ - p->aOnceFlag[pOp->p1] = 1; + pOp->p1 = p->aOp[0].p1; } break; } @@ -79461,7 +80183,7 @@ case OP_IfNot: { /* jump, in1 */ } /* Opcode: IsNull P1 P2 * * * -** Synopsis: if r[P1]==NULL goto P2 +** Synopsis: if r[P1]==NULL goto P2 ** ** Jump to P2 if the value in register P1 is NULL. */ @@ -79489,7 +80211,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ } /* Opcode: Column P1 P2 P3 P4 P5 -** Synopsis: r[P3]=PX +** Synopsis: r[P3]=PX ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional @@ -79548,7 +80270,6 @@ case OP_Column: { assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); - pCrsr = pC->uc.pCursor; if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ @@ -79564,6 +80285,7 @@ case OP_Column: { goto op_column_out; } }else{ + pCrsr = pC->uc.pCursor; assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); @@ -79627,7 +80349,7 @@ case OP_Column: { /* Make sure zData points to enough of the record to cover the header. */ if( pC->aRow==0 ){ memset(&sMem, 0, sizeof(sMem)); - rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem); + rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem); if( rc!=SQLITE_OK ) goto abort_due_to_error; zData = (u8*)sMem.z; }else{ @@ -79740,8 +80462,7 @@ case OP_Column: { static u8 aZero[8]; /* This is the bogus content */ sqlite3VdbeSerialGet(aZero, t, pDest); }else{ - rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, - pDest); + rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); if( rc!=SQLITE_OK ) goto abort_due_to_error; sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); pDest->flags &= ~MEM_Ephem; @@ -80255,12 +80976,12 @@ case OP_Transaction: { rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); testcase( rc==SQLITE_BUSY_SNAPSHOT ); testcase( rc==SQLITE_BUSY_RECOVERY ); - if( (rc&0xff)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - p->rc = rc; - goto vdbe_return; - } if( rc!=SQLITE_OK ){ + if( (rc&0xff)==SQLITE_BUSY ){ + p->pc = (int)(pOp - aOp); + p->rc = rc; + goto vdbe_return; + } goto abort_due_to_error; } @@ -80287,10 +81008,9 @@ case OP_Transaction: { } /* Gather the schema version number for checking: - ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite - ** each time a query is executed to ensure that the internal cache of the - ** schema used when compiling the SQL query matches the schema of the - ** database against which the compiled query is actually executed. + ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema + ** version is checked to ensure that the schema has not changed since the + ** SQL statement was prepared. */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; @@ -80607,10 +81327,10 @@ case OP_OpenEphemeral: { if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); + rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling @@ -80618,21 +81338,20 @@ case OP_OpenEphemeral: { ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ - if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ + if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); + rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); - pCx->pKeyInfo = pKeyInfo; - rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR, pKeyInfo, pCx->uc.pCursor); } pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR, 0, pCx->uc.pCursor); pCx->isTable = 1; } @@ -80864,7 +81583,8 @@ case OP_SeekGT: { /* jump, in3 */ if( pC->isTable ){ /* The BTREE_SEEK_EQ flag is only set on index cursors */ - assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 ); + assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 + || CORRUPT_DB ); /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do @@ -80951,7 +81671,6 @@ case OP_SeekGT: { /* jump, in3 */ #ifdef SQLITE_DEBUG { int i; for(i=0; iuc.pCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ @@ -80999,7 +81718,6 @@ seek_not_found: } break; } - /* Opcode: Found P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] @@ -81068,10 +81786,9 @@ case OP_Found: { /* jump, in3 */ int ii; VdbeCursor *pC; int res; - char *pFree; + UnpackedRecord *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; @@ -81088,26 +81805,24 @@ case OP_Found: { /* jump, in3 */ assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 ); - pFree = 0; if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; r.aMem = pIn3; +#ifdef SQLITE_DEBUG for(ii=0; iip3+ii, &r.aMem[ii]); -#endif } +#endif pIdxKey = &r; + pFree = 0; }else{ - pIdxKey = sqlite3VdbeAllocUnpackedRecord( - pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree - ); + pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); - ExpandBlob(pIn3); + (void)ExpandBlob(pIn3); sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; @@ -81124,7 +81839,7 @@ case OP_Found: { /* jump, in3 */ } } rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res); - sqlite3DbFree(db, pFree); + if( pFree ) sqlite3DbFree(db, pFree); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -81351,7 +82066,7 @@ case OP_NewRowid: { /* out2 */ sqlite3VdbeMemIntegerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ + rc = SQLITE_FULL; /* IMP: R-17817-00630 */ goto abort_due_to_error; } if( vu.i+1 ){ @@ -81403,15 +82118,10 @@ case OP_NewRowid: { /* out2 */ ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). ** -** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of -** the last seek operation (OP_NotExists or OP_SeekRowid) was a success, -** then this -** operation will not attempt to find the appropriate row before doing -** the insert but will instead overwrite the row that the cursor is -** currently pointing to. Presumably, the prior OP_NotExists or -** OP_SeekRowid opcode -** has already positioned the cursor correctly. This is an optimization -** that boosts performance by avoiding redundant seeks. +** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might +** run faster by avoiding an unnecessary seek on cursor P1. However, +** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior +** seeks on the cursor or if the most recent seek used a key equal to P3. ** ** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an ** UPDATE operation. Otherwise (if the flag is clear) then this opcode @@ -81432,7 +82142,7 @@ case OP_NewRowid: { /* out2 */ ** for indices is OP_IdxInsert. */ /* Opcode: InsertInt P1 P2 P3 P4 P5 -** Synopsis: intkey=P3 data=r[P2] +** Synopsis: intkey=P3 data=r[P2] ** ** This works exactly like OP_Insert except that the key is the ** integer value P3, not the value of the integer stored in register P3. @@ -81474,7 +82184,7 @@ case OP_InsertInt: { if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->isTable ); assert( pC->iDb>=0 ); - zDb = db->aDb[pC->iDb].zName; + zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; assert( HasRowid(pTab) ); op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); @@ -81548,7 +82258,7 @@ case OP_InsertInt: { ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL then it points to a Table struture. In this case either +** If P4 is not NULL then it points to a Table object. In this case either ** the update or pre-update hook, or both, may be invoked. The P1 cursor must ** have been positioned using OP_NotFound prior to invoking this opcode in ** this case. Specifically, if one is configured, the pre-update hook is @@ -81591,7 +82301,7 @@ case OP_Delete: { if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); assert( pOp->p4.pTab!=0 ); - zDb = db->aDb[pC->iDb].zName; + zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); @@ -81635,6 +82345,7 @@ case OP_Delete: { rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; + pC->seekResult = 0; if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ @@ -81663,7 +82374,7 @@ case OP_ResetCount: { } /* Opcode: SorterCompare P1 P2 P3 P4 -** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 +** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 ** ** P1 is a sorter cursor. This instruction compares a prefix of the ** record blob in register P3 against a prefix of the entry that @@ -81724,26 +82435,18 @@ case OP_SorterData: { /* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** -** Write into register P2 the complete row data for cursor P1. +** Write into register P2 the complete row content for the row at +** which cursor P1 is currently pointing. ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as ** it is found in the database file. ** -** If the P1 cursor must be pointing to a valid row (not a NULL row) -** of a real table, not a pseudo-table. -*/ -/* Opcode: RowKey P1 P2 * * * -** Synopsis: r[P2]=key -** -** Write into register P2 the complete row key for cursor P1. -** There is no interpretation of the data. -** The key is copied onto the P2 register exactly as -** it is found in the database file. +** If cursor P1 is an index, then the content is the key of the row. +** If cursor P2 is a table, then the content extracted is the data. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ -case OP_RowKey: case OP_RowData: { VdbeCursor *pC; BtCursor *pCrsr; @@ -81752,19 +82455,16 @@ case OP_RowData: { pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); - /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( isSorter(pC)==0 ); - assert( pC->isTable || pOp->opcode!=OP_RowData ); - assert( pC->isTable==0 || pOp->opcode==OP_RowData ); assert( pC->nullRow==0 ); assert( pC->uc.pCursor!=0 ); pCrsr = pC->uc.pCursor; - /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or + /* The OP_RowData opcodes always follow OP_NotExists or ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions ** that might invalidate the cursor. ** If this where not the case, on of the following assert()s @@ -81789,11 +82489,7 @@ case OP_RowData: { } pOut->n = n; MemSetTypeFlag(pOut, MEM_Blob); - if( pC->isTable==0 ){ - rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); - }else{ - rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); - } + rc = sqlite3BtreePayload(pCrsr, 0, n, pOut->z); if( rc ) goto abort_due_to_error; pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); @@ -81884,6 +82580,13 @@ case OP_NullRow: { ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. +** +** If P3 is -1, then the cursor is positioned at the end of the btree +** for the purpose of appending a new entry onto the btree. In that +** case P2 must be 0. It is assumed that the cursor is used only for +** appending and so if the cursor is valid, then the cursor must already +** be pointing at the end of the btree and so no changes are made to +** the cursor. */ case OP_Last: { /* jump */ VdbeCursor *pC; @@ -81897,23 +82600,36 @@ case OP_Last: { /* jump */ pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; + if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( rc ) goto abort_due_to_error; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + } + }else{ + assert( pOp->p2==0 ); } break; } +/* Opcode: SorterSort P1 P2 * * * +** +** After all records have been inserted into the Sorter object +** identified by P1, invoke this opcode to actually do the sorting. +** Jump to P2 if there are no records to be sorted. +** +** This opcode is an alias for OP_Sort and OP_Rewind that is used +** for Sorter objects. +*/ /* Opcode: Sort P1 P2 * * * ** ** This opcode does exactly the same thing as OP_Rewind except that @@ -82041,6 +82757,13 @@ case OP_Rewind: { /* jump */ ** This opcode works just like Prev except that if cursor P1 is not ** open it behaves a no-op. */ +/* Opcode: SorterNext P1 P2 * * P5 +** +** This opcode works just like OP_Next except that P1 must be a +** sorter object for which the OP_SorterSort opcode has been +** invoked. This opcode advances the cursor to the next sorted +** record, or jumps to P2 if there are no more sorted records. +*/ case OP_SorterNext: { /* jump */ VdbeCursor *pC; int res; @@ -82097,27 +82820,41 @@ next_tail: goto check_for_interrupt; } -/* Opcode: IdxInsert P1 P2 P3 * P5 +/* Opcode: IdxInsert P1 P2 P3 P4 P5 ** Synopsis: key=r[P2] ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** -** P3 is a flag that provides a hint to the b-tree layer that this -** insert is likely to be an append. +** If P4 is not zero, then it is the number of values in the unpacked +** key of reg(P2). In that case, P3 is the index of the first register +** for the unpacked key. The availability of the unpacked key can sometimes +** be an optimization. +** +** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer +** that this insert is likely to be an append. ** ** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is ** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, ** then the change counter is unchanged. ** -** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have -** just done a seek to the spot where the new entry is to be inserted. -** This flag avoids doing an extra seek. +** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might +** run faster by avoiding an unnecessary seek on cursor P1. However, +** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior +** seeks on the cursor or if the most recent seek used a key equivalent +** to P2. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ +/* Opcode: SorterInsert P1 P2 * * * +** Synopsis: key=r[P2] +** +** Register P2 holds an SQL index key made using the +** MakeRecord instructions. This opcode writes that key +** into the sorter P1. Data for the entry is nil. +*/ case OP_SorterInsert: /* in2 */ case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; @@ -82139,10 +82876,10 @@ case OP_IdxInsert: { /* in2 */ }else{ x.nKey = pIn2->n; x.pKey = pIn2->z; - x.nData = 0; - x.nZero = 0; - x.pData = 0; - rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, + x.aMem = aMem + pOp->p3; + x.nMem = (u16)pOp->p4.i; + rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, + (pOp->p5 & OPFLAG_APPEND)!=0, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); @@ -82186,11 +82923,12 @@ case OP_IdxDelete: { } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; + pC->seekResult = 0; break; } /* Opcode: Seek P1 * P3 P4 * -** Synopsis: Move P3 to P1.rowid +** Synopsis: Move P3 to P1.rowid ** ** P1 is an open index cursor and P3 is a cursor on the corresponding ** table. This opcode does a deferred seek of the P3 table cursor @@ -82555,13 +83293,13 @@ case OP_ParseSchema: { assert( iDb>=0 && iDbnDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); /* Used to be a conditional */ { - zMaster = SCHEMA_TABLE(iDb); + zMaster = MASTER_NAME; initData.db = db; initData.iDb = pOp->p1; initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zName, zMaster, pOp->p4.z); + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ @@ -82697,7 +83435,7 @@ case OP_IntegrityCk: { #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: RowSetAdd P1 P2 * * * -** Synopsis: rowset(P1)=r[P2] +** Synopsis: rowset(P1)=r[P2] ** ** Insert the integer value held by register P2 into a boolean index ** held in register P1. @@ -82717,7 +83455,7 @@ case OP_RowSetAdd: { /* in1, in2 */ } /* Opcode: RowSetRead P1 P2 P3 * * -** Synopsis: r[P3]=rowset(P1) +** Synopsis: r[P3]=rowset(P1) ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 @@ -82866,8 +83604,7 @@ case OP_Program: { /* jump */ if( pProgram->nCsr==0 ) nMem++; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) - + pProgram->nCsr * sizeof(VdbeCursor *) - + pProgram->nOnce * sizeof(u8); + + pProgram->nCsr * sizeof(VdbeCursor *); pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; @@ -82887,8 +83624,6 @@ case OP_Program: { /* jump */ pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; - pFrame->aOnceFlag = p->aOnceFlag; - pFrame->nOnceFlag = p->nOnceFlag; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pFrame->anExec = p->anExec; #endif @@ -82922,13 +83657,10 @@ case OP_Program: { /* jump */ p->apCsr = (VdbeCursor **)&aMem[p->nMem]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; - p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; - p->nOnceFlag = pProgram->nOnce; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif pOp = &aOp[-1]; - memset(p->aOnceFlag, 0, p->nOnceFlag); break; } @@ -83072,29 +83804,42 @@ case OP_IfPos: { /* jump, in1 */ ** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. */ case OP_OffsetLimit: { /* in1, out2, in3 */ + i64 x; pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; pOut = out2Prerelease(p, pOp); assert( pIn1->flags & MEM_Int ); assert( pIn3->flags & MEM_Int ); - pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); + x = pIn1->u.i; + if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){ + /* If the LIMIT is less than or equal to zero, loop forever. This + ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then + ** also loop forever. This is undocumented. In fact, one could argue + ** that the loop should terminate. But assuming 1 billion iterations + ** per second (far exceeding the capabilities of any current hardware) + ** it would take nearly 300 years to actually reach the limit. So + ** looping forever is a reasonable approximation. */ + pOut->u.i = -1; + }else{ + pOut->u.i = x; + } break; } -/* Opcode: IfNotZero P1 P2 P3 * * -** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 +/* Opcode: IfNotZero P1 P2 * * * +** Synopsis: if r[P1]!=0 then r[P1]--, goto P2 ** ** Register P1 must contain an integer. If the content of register P1 is -** initially nonzero, then subtract P3 from the value in register P1 and -** jump to P2. If register P1 is initially zero, leave it unchanged -** and fall through. +** initially greater than zero, then decrement the value in register P1. +** If it is non-zero (negative or positive) and then also jump to P2. +** If register P1 is initially zero, leave it unchanged and fall through. */ case OP_IfNotZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken(pIn1->u.i<0, 2); if( pIn1->u.i ){ - pIn1->u.i -= pOp->p3; + if( pIn1->u.i>0 ) pIn1->u.i--; goto jump_to_p2; } break; @@ -83103,13 +83848,13 @@ case OP_IfNotZero: { /* jump, in1 */ /* Opcode: DecrJumpZero P1 P2 * * * ** Synopsis: if (--r[P1])==0 goto P2 ** -** Register P1 must hold an integer. Decrement the value in register P1 -** then jump to P2 if the new value is exactly zero. +** Register P1 must hold an integer. Decrement the value in P1 +** and jump to P2 if the new value is exactly zero. */ case OP_DecrJumpZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); - pIn1->u.i--; + if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ) goto jump_to_p2; break; @@ -83355,7 +84100,7 @@ case OP_JournalMode: { /* out2 */ ** file. An EXCLUSIVE lock may still be held on the database file ** after a successful return. */ - rc = sqlite3PagerCloseWal(pPager); + rc = sqlite3PagerCloseWal(pPager, db); if( rc==SQLITE_OK ){ sqlite3PagerSetJournalMode(pPager, eNew); } @@ -83390,15 +84135,14 @@ case OP_JournalMode: { /* out2 */ #endif /* SQLITE_OMIT_PRAGMA */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* Opcode: Vacuum * * * * * +/* Opcode: Vacuum P1 * * * * ** -** Vacuum the entire database. This opcode will cause other virtual -** machines to be created and run. It may not be called from within -** a transaction. +** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more +** for an attached database. The "temp" database may not be vacuumed. */ case OP_Vacuum: { assert( p->readOnly==0 ); - rc = sqlite3RunVacuum(&p->zErrMsg, db); + rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1); if( rc ) goto abort_due_to_error; break; } @@ -83896,8 +84640,8 @@ case OP_MaxPgcnt: { /* out2 */ #endif -/* Opcode: Init * P2 * P4 * -** Synopsis: Start at P2 +/* Opcode: Init P1 P2 * P4 * +** Synopsis: Start at P2 ** ** Programs contain a single instance of this opcode as the very first ** opcode. @@ -83907,9 +84651,13 @@ case OP_MaxPgcnt: { /* out2 */ ** Or if P4 is blank, use the string returned by sqlite3_sql(). ** ** If P2 is not zero, jump to instruction P2. +** +** Increment the value of P1 so that OP_Once opcodes will jump the +** first time they are evaluated for this run. */ case OP_Init: { /* jump */ char *zTrace; + int i; /* If the P4 argument is not NULL, then it must be an SQL comment string. ** The "--" string is broken up to prevent false-positives with srcck1.c. @@ -83921,6 +84669,7 @@ case OP_Init: { /* jump */ ** sqlite3_expanded_sql(P) otherwise. */ assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); + assert( pOp==p->aOp ); /* Always instruction 0 */ #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 @@ -83942,10 +84691,10 @@ case OP_Init: { /* jump */ #ifdef SQLITE_USE_FCNTL_TRACE zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ - int i; - for(i=0; inDb; i++){ - if( DbMaskTest(p->btreeMask, i)==0 ) continue; - sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + int j; + for(j=0; jnDb; j++){ + if( DbMaskTest(p->btreeMask, j)==0 ) continue; + sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace); } } #endif /* SQLITE_USE_FCNTL_TRACE */ @@ -83957,8 +84706,15 @@ case OP_Init: { /* jump */ } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ - if( pOp->p2 ) goto jump_to_p2; - break; + assert( pOp->p2>0 ); + if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ + for(i=1; inOp; i++){ + if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; + } + pOp->p1 = 0; + } + pOp->p1++; + goto jump_to_p2; } #ifdef SQLITE_ENABLE_CURSOR_HINTS @@ -84211,7 +84967,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* ** Open a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3* db, /* The database connection */ const char *zDb, /* The attached database containing the blob */ const char *zTable, /* The table containing the blob */ @@ -84281,7 +85037,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( goto blob_open_out; } pBlob->pTab = pTab; - pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zName; + pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iColnCol; iCol++) { @@ -84367,8 +85123,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( {OP_Column, 0, 0, 1}, /* 4 */ {OP_ResultRow, 1, 0, 0}, /* 5 */ {OP_Goto, 0, 2, 0}, /* 6 */ - {OP_Close, 0, 0, 0}, /* 7 */ - {OP_Halt, 0, 0, 0}, /* 8 */ + {OP_Halt, 0, 0, 0}, /* 7 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -84452,7 +85207,7 @@ blob_open_out: ** Close a blob handle that was previously created using ** sqlite3_blob_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; @@ -84545,14 +85300,14 @@ static int blobReadWrite( /* ** Read data from a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ - return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); +SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ + return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked); } /* ** Write data to a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); } @@ -84562,7 +85317,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob ** so no mutex is required for access. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; return (p && p->pStmt) ? p->nByte : 0; } @@ -84577,7 +85332,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) ** immediately return SQLITE_ABORT. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ int rc; Incrblob *p = (Incrblob *)pBlob; sqlite3 *db; @@ -85572,7 +86327,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( } #endif - assert( pCsr->pKeyInfo && pCsr->pBt==0 ); + assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); assert( pCsr->eCurType==CURTYPE_SORTER ); szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); @@ -85940,12 +86695,8 @@ static int vdbeSorterOpenTempFile( */ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pTask->pUnpacked==0 ){ - char *pFree; - pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord( - pTask->pSorter->pKeyInfo, 0, 0, &pFree - ); - assert( pTask->pUnpacked==(UnpackedRecord*)pFree ); - if( pFree==0 ) return SQLITE_NOMEM_BKPT; + pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); + if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; } @@ -87346,9 +88097,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare( r2 = pSorter->pUnpacked; pKeyInfo = pCsr->pKeyInfo; if( r2==0 ){ - char *p; - r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p); - assert( pSorter->pUnpacked==(UnpackedRecord*)p ); + r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( r2==0 ) return SQLITE_NOMEM_BKPT; r2->nField = nKeyCol; } @@ -87833,17 +88582,17 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); rc = pWalker->xExprCallback(pWalker, pExpr); - if( rc==WRC_Continue - && !ExprHasProperty(pExpr,EP_TokenOnly) ){ - if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else{ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } + if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ + return rc & WRC_Abort; } - return rc & WRC_Abort; + if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; + if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; + }else if( pExpr->x.pList ){ + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + } + return WRC_Continue; } SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; @@ -88177,8 +88926,8 @@ static int lookupName( zDb = 0; }else{ for(i=0; inDb; i++){ - assert( db->aDb[i].zName ); - if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ + assert( db->aDb[i].zDbSName ); + if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } @@ -88356,6 +89105,10 @@ static int lookupName( sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } + if( sqlite3ExprVectorSize(pOrig)!=1 ){ + sqlite3ErrorMsg(pParse, "row value misused"); + return WRC_Abort; + } resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; @@ -88579,7 +89332,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* if( pSrcList==0 ) break; */ notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); - /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; @@ -88602,14 +89354,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ - int auth; /* Authorization to use the function */ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - notValid(pParse, pNC, "functions", NC_PartIdx); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); @@ -88646,15 +89396,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } } #ifndef SQLITE_OMIT_AUTHORIZATION - auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); - if( auth!=SQLITE_OK ){ - if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", - pDef->zName); - pNC->nErr++; + { + int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return WRC_Prune; } - pExpr->op = TK_NULL; - return WRC_Prune; } #endif if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){ @@ -88667,7 +89419,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index. */ - notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr); + notValid(pParse, pNC, "non-deterministic functions", + NC_IdxExpr|NC_PartIdx); } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ @@ -88732,6 +89485,42 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + case TK_BETWEEN: + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_IS: + case TK_ISNOT: { + int nLeft, nRight; + if( pParse->db->mallocFailed ) break; + assert( pExpr->pLeft!=0 ); + nLeft = sqlite3ExprVectorSize(pExpr->pLeft); + if( pExpr->op==TK_BETWEEN ){ + nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); + if( nRight==nLeft ){ + nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); + } + }else{ + assert( pExpr->pRight!=0 ); + nRight = sqlite3ExprVectorSize(pExpr->pRight); + } + if( nLeft!=nRight ){ + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + testcase( pExpr->op==TK_BETWEEN ); + sqlite3ErrorMsg(pParse, "row value misused"); + } + break; + } } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } @@ -89474,6 +90263,18 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( */ /* #include "sqliteInt.h" */ +/* Forward declarations */ +static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int); +static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree); + +/* +** Return the affinity character for a single column of a table. +*/ +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table *pTab, int iCol){ + assert( iColnCol ); + return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER; +} + /* ** Return the 'affinity' of the expression pExpr if any. ** @@ -89499,21 +90300,21 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } + if( op==TK_REGISTER ) op = pExpr->op2; #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) - && pExpr->pTab!=0 - ){ - /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally - ** a TK_COLUMN but was previously evaluated and cached in a register */ - int j = pExpr->iColumn; - if( j<0 ) return SQLITE_AFF_INTEGER; - assert( pExpr->pTab && jpTab->nCol ); - return pExpr->pTab->aCol[j].affinity; + if( op==TK_AGG_COLUMN || op==TK_COLUMN ){ + return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + } + if( op==TK_SELECT_COLUMN ){ + assert( pExpr->pLeft->flags&EP_xIsSelect ); + return sqlite3ExprAffinity( + pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr + ); } return pExpr->affinity; } @@ -89679,7 +90480,7 @@ static char comparisonAffinity(Expr *pExpr){ aff = sqlite3CompareAffinity(pExpr->pRight, aff); }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); - }else if( !aff ){ + }else if( NEVER(aff==0) ){ aff = SQLITE_AFF_BLOB; } return aff; @@ -89769,6 +90570,273 @@ static int codeCompare( return addr; } +/* +** Return true if expression pExpr is a vector, or false otherwise. +** +** A vector is defined as any expression that results in two or more +** columns of result. Every TK_VECTOR node is an vector because the +** parser will not generate a TK_VECTOR with fewer than two entries. +** But a TK_SELECT might be either a vector or a scalar. It is only +** considered a vector if it has two or more result columns. +*/ +SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr){ + return sqlite3ExprVectorSize(pExpr)>1; +} + +/* +** If the expression passed as the only argument is of type TK_VECTOR +** return the number of expressions in the vector. Or, if the expression +** is a sub-select, return the number of columns in the sub-select. For +** any other type of expression, return 1. +*/ +SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr){ + u8 op = pExpr->op; + if( op==TK_REGISTER ) op = pExpr->op2; + if( op==TK_VECTOR ){ + return pExpr->x.pList->nExpr; + }else if( op==TK_SELECT ){ + return pExpr->x.pSelect->pEList->nExpr; + }else{ + return 1; + } +} + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Return a pointer to a subexpression of pVector that is the i-th +** column of the vector (numbered starting with 0). The caller must +** ensure that i is within range. +** +** If pVector is really a scalar (and "scalar" here includes subqueries +** that return a single column!) then return pVector unmodified. +** +** pVector retains ownership of the returned subexpression. +** +** If the vector is a (SELECT ...) then the expression returned is +** just the expression for the i-th term of the result set, and may +** not be ready for evaluation because the table cursor has not yet +** been positioned. +*/ +SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ + assert( iop2==0 || pVector->op==TK_REGISTER ); + if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){ + return pVector->x.pSelect->pEList->a[i].pExpr; + }else{ + return pVector->x.pList->a[i].pExpr; + } + } + return pVector; +} +#endif /* !defined(SQLITE_OMIT_SUBQUERY) */ + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Compute and return a new Expr object which when passed to +** sqlite3ExprCode() will generate all necessary code to compute +** the iField-th column of the vector expression pVector. +** +** It is ok for pVector to be a scalar (as long as iField==0). +** In that case, this routine works like sqlite3ExprDup(). +** +** The caller owns the returned Expr object and is responsible for +** ensuring that the returned value eventually gets freed. +** +** The caller retains ownership of pVector. If pVector is a TK_SELECT, +** then the returned object will reference pVector and so pVector must remain +** valid for the life of the returned object. If pVector is a TK_VECTOR +** or a scalar expression, then it can be deleted as soon as this routine +** returns. +** +** A trick to cause a TK_SELECT pVector to be deleted together with +** the returned Expr object is to attach the pVector to the pRight field +** of the returned TK_SELECT_COLUMN Expr object. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( + Parse *pParse, /* Parsing context */ + Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ + int iField /* Which column of the vector to return */ +){ + Expr *pRet; + if( pVector->op==TK_SELECT ){ + assert( pVector->flags & EP_xIsSelect ); + /* The TK_SELECT_COLUMN Expr node: + ** + ** pLeft: pVector containing TK_SELECT + ** pRight: not used. But recursively deleted. + ** iColumn: Index of a column in pVector + ** pLeft->iTable: First in an array of register holding result, or 0 + ** if the result is not yet computed. + ** + ** sqlite3ExprDelete() specifically skips the recursive delete of + ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector + ** can be attached to pRight to cause this node to take ownership of + ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes + ** with the same pLeft pointer to the pVector, but only one of them + ** will own the pVector. + */ + pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); + if( pRet ){ + pRet->iColumn = iField; + pRet->pLeft = pVector; + } + assert( pRet==0 || pRet->iTable==0 ); + }else{ + if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr; + pRet = sqlite3ExprDup(pParse->db, pVector, 0); + } + return pRet; +} +#endif /* !define(SQLITE_OMIT_SUBQUERY) */ + +/* +** If expression pExpr is of type TK_SELECT, generate code to evaluate +** it. Return the register in which the result is stored (or, if the +** sub-select returns more than one column, the first in an array +** of registers in which the result is stored). +** +** If pExpr is not a TK_SELECT expression, return 0. +*/ +static int exprCodeSubselect(Parse *pParse, Expr *pExpr){ + int reg = 0; +#ifndef SQLITE_OMIT_SUBQUERY + if( pExpr->op==TK_SELECT ){ + reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); + } +#endif + return reg; +} + +/* +** Argument pVector points to a vector expression - either a TK_VECTOR +** or TK_SELECT that returns more than one column. This function returns +** the register number of a register that contains the value of +** element iField of the vector. +** +** If pVector is a TK_SELECT expression, then code for it must have +** already been generated using the exprCodeSubselect() routine. In this +** case parameter regSelect should be the first in an array of registers +** containing the results of the sub-select. +** +** If pVector is of type TK_VECTOR, then code for the requested field +** is generated. In this case (*pRegFree) may be set to the number of +** a temporary register to be freed by the caller before returning. +** +** Before returning, output parameter (*ppExpr) is set to point to the +** Expr object corresponding to element iElem of the vector. +*/ +static int exprVectorRegister( + Parse *pParse, /* Parse context */ + Expr *pVector, /* Vector to extract element from */ + int iField, /* Field to extract from pVector */ + int regSelect, /* First in array of registers */ + Expr **ppExpr, /* OUT: Expression element */ + int *pRegFree /* OUT: Temp register to free */ +){ + u8 op = pVector->op; + assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT ); + if( op==TK_REGISTER ){ + *ppExpr = sqlite3VectorFieldSubexpr(pVector, iField); + return pVector->iTable+iField; + } + if( op==TK_SELECT ){ + *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr; + return regSelect+iField; + } + *ppExpr = pVector->x.pList->a[iField].pExpr; + return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); +} + +/* +** Expression pExpr is a comparison between two vector values. Compute +** the result of the comparison (1, 0, or NULL) and write that +** result into register dest. +** +** The caller must satisfy the following preconditions: +** +** if pExpr->op==TK_IS: op==TK_EQ and p5==SQLITE_NULLEQ +** if pExpr->op==TK_ISNOT: op==TK_NE and p5==SQLITE_NULLEQ +** otherwise: op==pExpr->op and p5==0 +*/ +static void codeVectorCompare( + Parse *pParse, /* Code generator context */ + Expr *pExpr, /* The comparison operation */ + int dest, /* Write results into this register */ + u8 op, /* Comparison operator */ + u8 p5 /* SQLITE_NULLEQ or zero */ +){ + Vdbe *v = pParse->pVdbe; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; + int nLeft = sqlite3ExprVectorSize(pLeft); + int i; + int regLeft = 0; + int regRight = 0; + u8 opx = op; + int addrDone = sqlite3VdbeMakeLabel(v); + + if( nLeft!=sqlite3ExprVectorSize(pRight) ){ + sqlite3ErrorMsg(pParse, "row value misused"); + return; + } + assert( pExpr->op==TK_EQ || pExpr->op==TK_NE + || pExpr->op==TK_IS || pExpr->op==TK_ISNOT + || pExpr->op==TK_LT || pExpr->op==TK_GT + || pExpr->op==TK_LE || pExpr->op==TK_GE + ); + assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) + || (pExpr->op==TK_ISNOT && op==TK_NE) ); + assert( p5==0 || pExpr->op!=op ); + assert( p5==SQLITE_NULLEQ || pExpr->op==op ); + + p5 |= SQLITE_STOREP2; + if( opx==TK_LE ) opx = TK_LT; + if( opx==TK_GE ) opx = TK_GT; + + regLeft = exprCodeSubselect(pParse, pLeft); + regRight = exprCodeSubselect(pParse, pRight); + + for(i=0; 1 /*Loop exits by "break"*/; i++){ + int regFree1 = 0, regFree2 = 0; + Expr *pL, *pR; + int r1, r2; + assert( i>=0 && i0 ) sqlite3ExprCachePush(pParse); + r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); + r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); + testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + if( i>0 ) sqlite3ExprCachePop(pParse); + if( i==nLeft-1 ){ + break; + } + if( opx==TK_EQ ){ + sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else if( opx==TK_NE ){ + sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else{ + assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); + sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); + VdbeCoverageIf(v, op==TK_LT); + VdbeCoverageIf(v, op==TK_GT); + VdbeCoverageIf(v, op==TK_LE); + VdbeCoverageIf(v, op==TK_GE); + if( i==nLeft-2 ) opx = op; + } + } + sqlite3VdbeResolveLabel(v, addrDone); +} + #if SQLITE_MAX_EXPR_DEPTH>0 /* ** Check that argument nHeight is less than or equal to the maximum @@ -89904,7 +90972,7 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ ** is allocated to hold the integer text and the dequote flag is ignored. */ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ int op, /* Expression opcode */ const Token *pToken, /* Token argument. Might be NULL */ int dequote /* True to dequote */ @@ -90003,15 +91071,19 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( Parse *pParse, /* Parsing context */ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ - Expr *pRight, /* Right operand */ - const Token *pToken /* Argument token */ + Expr *pRight /* Right operand */ ){ Expr *p; if( op==TK_AND && pParse->nErr==0 ){ /* Take advantage of short-circuit false optimization for AND */ p = sqlite3ExprAnd(pParse->db, pLeft, pRight); }else{ - p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1); + p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); + if( p ){ + memset(p, 0, sizeof(Expr)); + p->op = op & TKFLG_MASK; + p->iAgg = -1; + } sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); } if( p ) { @@ -90114,7 +91186,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * ** variable number. ** ** Wildcards of the form "?nnn" are assigned the number "nnn". We make -** sure "nnn" is not too be to avoid a denial of service attack when +** sure "nnn" is not too big to avoid a denial of service attack when ** the SQL statement comes from an external source. ** ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number @@ -90122,28 +91194,29 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * ** instance of the wildcard, the next sequential variable number is ** assigned. */ -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ sqlite3 *db = pParse->db; const char *z; + ynVar x; if( pExpr==0 ) return; assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); z = pExpr->u.zToken; assert( z!=0 ); assert( z[0]!=0 ); + assert( n==sqlite3Strlen30(z) ); if( z[1]==0 ){ /* Wildcard of the form "?". Assign the next variable number */ assert( z[0]=='?' ); - pExpr->iColumn = (ynVar)(++pParse->nVar); + x = (ynVar)(++pParse->nVar); }else{ - ynVar x = 0; - u32 n = sqlite3Strlen30(z); + int doAdd = 0; if( z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ i64 i; int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); - pExpr->iColumn = x = (ynVar)i; + x = (ynVar)i; testcase( i==0 ); testcase( i==1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); @@ -90151,44 +91224,31 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); - x = 0; + return; } - if( i>pParse->nVar ){ - pParse->nVar = (int)i; + if( x>pParse->nVar ){ + pParse->nVar = (int)x; + doAdd = 1; + }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){ + doAdd = 1; } }else{ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ - ynVar i; - for(i=0; inzVar; i++){ - if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ - pExpr->iColumn = x = (ynVar)i+1; - break; - } - } - if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); - } - if( x>0 ){ - if( x>pParse->nzVar ){ - char **a; - a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); - if( a==0 ){ - assert( db->mallocFailed ); /* Error reported through mallocFailed */ - return; - } - pParse->azVar = a; - memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); - pParse->nzVar = x; - } - if( z[0]!='?' || pParse->azVar[x-1]==0 ){ - sqlite3DbFree(db, pParse->azVar[x-1]); - pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); + x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n); + if( x==0 ){ + x = (ynVar)(++pParse->nVar); + doAdd = 1; } } - } - if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + if( doAdd ){ + pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x); + } + } + pExpr->iColumn = x; + if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); } } @@ -90200,18 +91260,25 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); - if( !ExprHasProperty(p, EP_TokenOnly) ){ +#ifdef SQLITE_DEBUG + if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ + assert( p->pLeft==0 ); + assert( p->pRight==0 ); + assert( p->x.pSelect==0 ); + } +#endif + if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ /* The Expr.x union is never used at the same time as Expr.pRight */ assert( p->x.pList==0 || p->pRight==0 ); - sqlite3ExprDelete(db, p->pLeft); + if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); sqlite3ExprDelete(db, p->pRight); - if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbFree(db, p); } @@ -90388,7 +91455,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ memcpy(zToken, p->u.zToken, nToken); } - if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ + if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); @@ -90400,7 +91467,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ /* Fill in pNew->pLeft and pNew->pRight. */ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, dupFlags); - if( ExprHasProperty(pNew, EP_Reduced) ){ + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; pNew->pRight = p->pRight ? @@ -90410,8 +91477,12 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ *pzBuffer = zAlloc; } }else{ - if( !ExprHasProperty(p, EP_TokenOnly) ){ - pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); + if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ + if( pNew->op==TK_SELECT_COLUMN ){ + pNew->pLeft = p->pLeft; + }else{ + pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); + } pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } @@ -90536,7 +91607,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ } pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ - pTab->nRef++; + pTab->nTabRef++; } pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); @@ -90652,6 +91723,60 @@ no_mem: return 0; } +/* +** pColumns and pExpr form a vector assignment which is part of the SET +** clause of an UPDATE statement. Like this: +** +** (a,b,c) = (expr1,expr2,expr3) +** Or: (a,b,c) = (SELECT x,y,z FROM ....) +** +** For each term of the vector assignment, append new entries to the +** expression list pList. In the case of a subquery on the LHS, append +** TK_SELECT_COLUMN expressions. +*/ +SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to append. Might be NULL */ + IdList *pColumns, /* List of names of LHS of the assignment */ + Expr *pExpr /* Vector expression to be appended. Might be NULL */ +){ + sqlite3 *db = pParse->db; + int n; + int i; + int iFirst = pList ? pList->nExpr : 0; + /* pColumns can only be NULL due to an OOM but an OOM will cause an + ** exit prior to this routine being invoked */ + if( NEVER(pColumns==0) ) goto vector_append_error; + if( pExpr==0 ) goto vector_append_error; + n = sqlite3ExprVectorSize(pExpr); + if( pColumns->nId!=n ){ + sqlite3ErrorMsg(pParse, "%d columns assigned %d values", + pColumns->nId, n); + goto vector_append_error; + } + for(i=0; inExpr==iFirst+i+1 ); + pList->a[pList->nExpr-1].zName = pColumns->a[i].zName; + pColumns->a[i].zName = 0; + } + } + if( pExpr->op==TK_SELECT ){ + if( pList && pList->a[iFirst].pExpr ){ + assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN ); + pList->a[iFirst].pExpr->pRight = pExpr; + pExpr = 0; + } + } + +vector_append_error: + sqlite3ExprDelete(db, pExpr); + sqlite3IdListDelete(db, pColumns); + return pList; +} + /* ** Set the sort order for the last element on the given ExprList. */ @@ -91059,8 +92184,8 @@ static Select *isCandidateForInOpt(Expr *pX){ Select *p; SrcList *pSrc; ExprList *pEList; - Expr *pRes; Table *pTab; + int i; if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ p = pX->x.pSelect; @@ -91083,23 +92208,18 @@ static Select *isCandidateForInOpt(Expr *pX){ assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; - if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ - pRes = pEList->a[0].pExpr; - if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */ - assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + assert( pEList!=0 ); + /* All SELECT results must be columns. */ + for(i=0; inExpr; i++){ + Expr *pRes = pEList->a[i].pExpr; + if( pRes->op!=TK_COLUMN ) return 0; + assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + } return p; } #endif /* SQLITE_OMIT_SUBQUERY */ -/* -** Code an OP_Once instruction and allocate space for its flag. Return the -** address of the new instruction. -*/ -SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); -} - +#ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code that checks the left-most column of index table iCur to see if ** it contains any NULL entries. Cause the register at regHasNull to be set @@ -91115,6 +92235,7 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ VdbeComment((v, "first_entry_in(%d)", iCur)); sqlite3VdbeJumpHere(v, addr1); } +#endif #ifndef SQLITE_OMIT_SUBQUERY @@ -91159,7 +92280,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** -** SELECT FROM +** SELECT , ... FROM
    ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then @@ -91175,14 +92296,14 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate ** through the set members) then the b-tree must not contain duplicates. -** An epheremal table must be used unless the selected is guaranteed -** to be unique - either because it is an INTEGER PRIMARY KEY or it -** has a UNIQUE constraint or UNIQUE index. +** An epheremal table must be used unless the selected columns are guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or due to +** a UNIQUE constraint or index. ** ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used ** for fast set membership tests) then an epheremal table must -** be used unless is an INTEGER PRIMARY KEY or an index can -** be found with as its left-most column. +** be used unless is a single INTEGER PRIMARY KEY column or an +** index can be found with the specified as its left-most. ** ** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and ** if the RHS of the IN operator is a list (not a subquery) then this @@ -91203,9 +92324,26 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** the value in that register will be NULL if the b-tree contains one or more ** NULL values, and it will be some non-NULL value if the b-tree contains no ** NULL values. +** +** If the aiMap parameter is not NULL, it must point to an array containing +** one element for each column returned by the SELECT statement on the RHS +** of the IN(...) operator. The i'th entry of the array is populated with the +** offset of the index column that matches the i'th column returned by the +** SELECT. For example, if the expression and selected index are: +** +** (?,?,?) IN (SELECT a, b, c FROM t1) +** CREATE INDEX i1 ON t1(b, c, a); +** +** then aiMap[] is populated with {2, 0, 1}. */ #ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ +SQLITE_PRIVATE int sqlite3FindInIndex( + Parse *pParse, /* Parsing context */ + Expr *pX, /* The right-hand side (RHS) of the IN operator */ + u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ + int *prRhsHasNull, /* Register holding NULL status. See notes */ + int *aiMap /* Mapping from Index fields to RHS fields */ +){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ @@ -91215,36 +92353,46 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; + /* If the RHS of this IN(...) operator is a SELECT, and if it matters + ** whether or not the SELECT result contains NULL values, check whether + ** or not NULL is actually possible (it may not be, for example, due + ** to NOT NULL constraints in the schema). If no NULL values are possible, + ** set prRhsHasNull to 0 before continuing. */ + if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){ + int i; + ExprList *pEList = pX->x.pSelect->pEList; + for(i=0; inExpr; i++){ + if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; + } + if( i==pEList->nExpr ){ + prRhsHasNull = 0; + } + } + /* Check to see if an existing table or index can be used to ** satisfy the query. This is preferable to generating a new - ** ephemeral table. - */ + ** ephemeral table. */ if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table
    . */ - Expr *pExpr; /* Expression */ - i16 iCol; /* Index of column */ i16 iDb; /* Database idx for pTab */ + ExprList *pEList = p->pEList; + int nExpr = pEList->nExpr; assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - iCol = (i16)pExpr->iColumn; - + /* Code an OP_Transaction and OP_TableLock for
    . */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - /* This function is only called from two places. In both cases the vdbe - ** has already been allocated. So assume sqlite3GetVdbe() is always - ** successful here. - */ - assert(v); - if( iCol<0 ){ - int iAddr = sqlite3CodeOnce(pParse); + assert(v); /* sqlite3GetVdbe() has always been previously called */ + if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ + /* The "x IN (SELECT rowid FROM table)" case */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); @@ -91253,44 +92401,109 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int sqlite3VdbeJumpHere(v, iAddr); }else{ Index *pIdx; /* Iterator variable */ + int affinity_ok = 1; + int i; - /* The collation sequence used by the comparison. If an index is to - ** be used in place of a temp-table, it must be ordered according - ** to this collation sequence. */ - CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); - - /* Check that the affinity that will be used to perform the - ** comparison is the same as the affinity of the column. If - ** it is not, it is not possible to use any index. - */ - int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); - - for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ - if( (pIdx->aiColumn[0]==iCol) - && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq - && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx))) - ){ - int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); - eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - - if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - const i64 sOne = 1; - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, - iTab, 0, 0, (u8*)&sOne, P4_INT64); -#endif - *prRhsHasNull = ++pParse->nMem; - sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); - } - sqlite3VdbeJumpHere(v, iAddr); + /* Check that the affinity that will be used to perform each + ** comparison is the same as the affinity of each column in table + ** on the RHS of the IN operator. If it not, it is not possible to + ** use any index of the RHS table. */ + for(i=0; ipLeft, i); + int iCol = pEList->a[i].pExpr->iColumn; + char idxaff = sqlite3TableColumnAffinity(pTab,iCol); /* RHS table */ + char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); + testcase( cmpaff==SQLITE_AFF_BLOB ); + testcase( cmpaff==SQLITE_AFF_TEXT ); + switch( cmpaff ){ + case SQLITE_AFF_BLOB: + break; + case SQLITE_AFF_TEXT: + /* sqlite3CompareAffinity() only returns TEXT if one side or the + ** other has no affinity and the other side is TEXT. Hence, + ** the only way for cmpaff to be TEXT is for idxaff to be TEXT + ** and for the term on the LHS of the IN to have no affinity. */ + assert( idxaff==SQLITE_AFF_TEXT ); + break; + default: + affinity_ok = sqlite3IsNumericAffinity(idxaff); } } - } - } + + if( affinity_ok ){ + /* Search for an existing index that will work for this IN operator */ + for(pIdx=pTab->pIndex; pIdx && eType==0; pIdx=pIdx->pNext){ + Bitmask colUsed; /* Columns of the index used */ + Bitmask mCol; /* Mask for the current column */ + if( pIdx->nColumnnColumn==BMS-2 ); + testcase( pIdx->nColumn==BMS-1 ); + if( pIdx->nColumn>=BMS-1 ) continue; + if( mustBeUnique ){ + if( pIdx->nKeyCol>nExpr + ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx)) + ){ + continue; /* This index is not unique over the IN RHS columns */ + } + } + + colUsed = 0; /* Columns of index used so far */ + for(i=0; ipLeft, i); + Expr *pRhs = pEList->a[i].pExpr; + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + int j; + + assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); + for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; + assert( pIdx->azColl[j] ); + if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ + continue; + } + break; + } + if( j==nExpr ) break; + mCol = MASKBIT(j); + if( mCol & colUsed ) break; /* Each column used only once */ + colUsed |= mCol; + if( aiMap ) aiMap[i] = j; + } + + assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) ); + if( colUsed==(MASKBIT(nExpr)-1) ){ + /* If we reach this point, that means the index pIdx is usable */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); +#ifndef SQLITE_OMIT_EXPLAIN + sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, + sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), + P4_DYNAMIC); +#endif + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); + assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); + eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; + + if( prRhsHasNull ){ +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK + i64 mask = (1<nMem; + if( nExpr==1 ){ + sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); + } + } + sqlite3VdbeJumpHere(v, iAddr); + } + } /* End loop over indexes */ + } /* End if( affinity_ok ) */ + } /* End if not an rowid index */ + } /* End attempt to optimize using an index */ /* If no preexisting index is available for the IN clause ** and IN_INDEX_NOOP is an allowed reply @@ -91306,7 +92519,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ){ eType = IN_INDEX_NOOP; } - if( eType==0 ){ /* Could not find an existing table or index to use as the RHS b-tree. @@ -91328,10 +92540,85 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int }else{ pX->iTable = iTab; } + + if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){ + int i, n; + n = sqlite3ExprVectorSize(pX->pLeft); + for(i=0; ipLeft; + int nVal = sqlite3ExprVectorSize(pLeft); + Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; + char *zRet; + + assert( pExpr->op==TK_IN ); + zRet = sqlite3DbMallocZero(pParse->db, nVal+1); + if( zRet ){ + int i; + for(i=0; ipEList->a[i].pExpr, a); + }else{ + zRet[i] = a; + } + } + zRet[nVal] = '\0'; + } + return zRet; +} +#endif + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Load the Parse object passed as the first argument with an error +** message of the form: +** +** "sub-select returns N columns - expected M" +*/ +SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){ + const char *zFmt = "sub-select returns %d columns - expected %d"; + sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect); +} +#endif + +/* +** Expression pExpr is a vector that has been used in a context where +** it is not permitted. If pExpr is a sub-select vector, this routine +** loads the Parse object with a message of the form: +** +** "sub-select returns N columns - expected 1" +** +** Or, if it is a regular scalar vector: +** +** "row value misused" +*/ +SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ +#ifndef SQLITE_OMIT_SUBQUERY + if( pExpr->flags & EP_xIsSelect ){ + sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); + }else +#endif + { + sqlite3ErrorMsg(pParse, "row value misused"); + } +} + /* ** Generate code for scalar subqueries used as a subquery expression, EXISTS, ** or IN operators. Examples: @@ -91357,7 +92644,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ** value to non-NULL if the RHS is NULL-free. ** ** For a SELECT or EXISTS operator, return the register that holds the -** result. For IN operators or if an error occurs, the return value is 0. +** result. For a multi-column SELECT, the result is stored in a contiguous +** array of registers and the return value is the register of the left-most +** result column. Return 0 for IN operators or if an error occurs. */ #ifndef SQLITE_OMIT_SUBQUERY SQLITE_PRIVATE int sqlite3CodeSubselect( @@ -91372,8 +92661,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( if( NEVER(v==0) ) return 0; sqlite3ExprCachePush(pParse); - /* This code must be run in its entirety every time it is encountered - ** if any of the following is true: + /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it + ** is encountered if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables @@ -91383,7 +92672,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v); + jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } #ifndef SQLITE_OMIT_EXPLAIN @@ -91399,17 +92688,18 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( switch( pExpr->op ){ case TK_IN: { - char affinity; /* Affinity of the LHS of the IN */ int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ KeyInfo *pKeyInfo = 0; /* Key information */ - - affinity = sqlite3ExprAffinity(pLeft); + int nVal; /* Size of vector pLeft */ + + nVal = sqlite3ExprVectorSize(pLeft); + assert( !isRowid || nVal==1 ); /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' ** expression it is handled the same way. An ephemeral table is - ** filled with single-field index keys representing the results - ** from the SELECT or the . + ** filled with index keys representing the results from the + ** SELECT or the . ** ** If the 'x' expression is a column value, or the SELECT... ** statement returns a column value, then the affinity of that @@ -91420,8 +92710,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); - pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, + pExpr->iTable, (isRowid?0:nVal)); + pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) @@ -91430,27 +92721,37 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** table allocated and opened above. */ Select *pSelect = pExpr->x.pSelect; - SelectDest dest; - ExprList *pEList; + ExprList *pEList = pSelect->pEList; assert( !isRowid ); - sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); - dest.affSdst = (u8)affinity; - assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); - pSelect->iLimit = 0; - testcase( pSelect->selFlags & SF_Distinct ); - testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ - if( sqlite3Select(pParse, pSelect, &dest) ){ - sqlite3KeyInfoUnref(pKeyInfo); - return 0; + /* If the LHS and RHS of the IN operator do not match, that + ** error will have been caught long before we reach this point. */ + if( ALWAYS(pEList->nExpr==nVal) ){ + SelectDest dest; + int i; + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); + dest.zAffSdst = exprINAffinity(pParse, pExpr); + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + pSelect->iLimit = 0; + testcase( pSelect->selFlags & SF_Distinct ); + testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ + if( sqlite3Select(pParse, pSelect, &dest) ){ + sqlite3DbFree(pParse->db, dest.zAffSdst); + sqlite3KeyInfoUnref(pKeyInfo); + return 0; + } + sqlite3DbFree(pParse->db, dest.zAffSdst); + assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ + assert( pEList!=0 ); + assert( pEList->nExpr>0 ); + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( + pParse, p, pEList->a[i].pExpr + ); + } } - pEList = pSelect->pEList; - assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ - assert( pEList!=0 ); - assert( pEList->nExpr>0 ); - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, - pEList->a[0].pExpr); }else if( ALWAYS(pExpr->x.pList!=0) ){ /* Case 2: expr IN (exprlist) ** @@ -91459,11 +92760,13 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** that columns affinity when building index keys. If is not ** a column, use numeric affinity. */ + char affinity; /* Affinity of the LHS of the IN */ int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; + affinity = sqlite3ExprAffinity(pLeft); if( !affinity ){ affinity = SQLITE_AFF_BLOB; } @@ -91503,7 +92806,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); } } } @@ -91519,26 +92822,37 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( case TK_EXISTS: case TK_SELECT: default: { - /* If this has to be a scalar SELECT. Generate code to put the - ** value of this select in a memory cell and record the number - ** of the memory cell in iColumn. If this is an EXISTS, write - ** an integer 0 (not exists) or 1 (exists) into a memory cell - ** and record that memory cell in iColumn. + /* Case 3: (SELECT ... FROM ...) + ** or: EXISTS(SELECT ... FROM ...) + ** + ** For a SELECT, generate code to put the values for all columns of + ** the first row into an array of registers and return the index of + ** the first register. + ** + ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists) + ** into a register and return that register number. + ** + ** In both cases, the query is augmented with "LIMIT 1". Any + ** preexisting limit is discarded in place of the new LIMIT 1. */ Select *pSel; /* SELECT statement to encode */ - SelectDest dest; /* How to deal with SELECt result */ + SelectDest dest; /* How to deal with SELECT result */ + int nReg; /* Registers to allocate */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + pSel = pExpr->x.pSelect; - sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); + nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; + sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); + pParse->nMem += nReg; if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; dest.iSdst = dest.iSDParm; - sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); + dest.nSdst = nReg; + sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1); VdbeComment((v, "Init subquery result")); }else{ dest.eDest = SRT_Exists; @@ -91546,8 +92860,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pParse->db, pSel->pLimit); - pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, - &sqlite3IntTokens[1]); + pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, + &sqlite3IntTokens[1], 0); pSel->iLimit = 0; pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ @@ -91572,6 +92886,28 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( } #endif /* SQLITE_OMIT_SUBQUERY */ +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Expr pIn is an IN(...) expression. This function checks that the +** sub-select on the RHS of the IN() operator has the same number of +** columns as the vector on the LHS. Or, if the RHS of the IN() is not +** a sub-query, that the LHS is a vector of size 1. +*/ +SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ + int nVector = sqlite3ExprVectorSize(pIn->pLeft); + if( (pIn->flags & EP_xIsSelect) ){ + if( nVector!=pIn->x.pSelect->pEList->nExpr ){ + sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); + return 1; + } + }else if( nVector!=1 ){ + sqlite3VectorErrorMsg(pParse, pIn->pLeft); + return 1; + } + return 0; +} +#endif + #ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code for an IN expression. @@ -91579,16 +92915,24 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** x IN (SELECT ...) ** x IN (value, value, ...) ** -** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS) -** is an array of zero or more values. The expression is true if the LHS is -** contained within the RHS. The value of the expression is unknown (NULL) -** if the LHS is NULL or if the LHS is not contained within the RHS and the -** RHS contains one or more NULL values. +** The left-hand side (LHS) is a scalar or vector expression. The +** right-hand side (RHS) is an array of zero or more scalar values, or a +** subquery. If the RHS is a subquery, the number of result columns must +** match the number of columns in the vector on the LHS. If the RHS is +** a list of values, the LHS must be a scalar. +** +** The IN operator is true if the LHS value is contained within the RHS. +** The result is false if the LHS is definitely not in the RHS. The +** result is NULL if the presence of the LHS in the RHS cannot be +** determined due to NULLs. ** ** This routine generates code that jumps to destIfFalse if the LHS is not ** contained within the RHS. If due to NULLs we cannot determine if the LHS ** is contained in the RHS then jump to destIfNull. If the LHS is contained ** within the RHS then fall through. +** +** See the separate in-operator.md documentation file in the canonical +** SQLite source tree for additional information. */ static void sqlite3ExprCodeIN( Parse *pParse, /* Parsing and code generating context */ @@ -91597,36 +92941,83 @@ static void sqlite3ExprCodeIN( int destIfNull /* Jump here if the results are unknown due to NULLs */ ){ int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ - char affinity; /* Comparison affinity to use */ int eType; /* Type of the RHS */ - int r1; /* Temporary use register */ + int rLhs; /* Register(s) holding the LHS values */ + int rLhsOrig; /* LHS values prior to reordering by aiMap[] */ Vdbe *v; /* Statement under construction */ + int *aiMap = 0; /* Map from vector field to index column */ + char *zAff = 0; /* Affinity string for comparisons */ + int nVector; /* Size of vectors for this IN operator */ + int iDummy; /* Dummy parameter to exprCodeVector() */ + Expr *pLeft; /* The LHS of the IN operator */ + int i; /* loop counter */ + int destStep2; /* Where to jump when NULLs seen in step 2 */ + int destStep6 = 0; /* Start of code for Step 6 */ + int addrTruthOp; /* Address of opcode that determines the IN is true */ + int destNotNull; /* Jump here if a comparison is not true in step 6 */ + int addrTop; /* Top of the step-6 loop */ - /* Compute the RHS. After this step, the table with cursor - ** pExpr->iTable will contains the values that make up the RHS. - */ + pLeft = pExpr->pLeft; + if( sqlite3ExprCheckIN(pParse, pExpr) ) return; + zAff = exprINAffinity(pParse, pExpr); + nVector = sqlite3ExprVectorSize(pExpr->pLeft); + aiMap = (int*)sqlite3DbMallocZero( + pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1 + ); + if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error; + + /* Attempt to compute the RHS. After this step, if anything other than + ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable + ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, + ** the RHS has not yet been coded. */ v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); eType = sqlite3FindInIndex(pParse, pExpr, IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, - destIfFalse==destIfNull ? 0 : &rRhsHasNull); + destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap); - /* Figure out the affinity to use to create a key from the results - ** of the expression. affinityStr stores a static string suitable for - ** P4 of OP_MakeRecord. - */ - affinity = comparisonAffinity(pExpr); + assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH + || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC + ); +#ifdef SQLITE_DEBUG + /* Confirm that aiMap[] contains nVector integer values between 0 and + ** nVector-1. */ + for(i=0; i from " IN (...)". + /* Code the LHS, the from " IN (...)". If the LHS is a + ** vector, then it is stored in an array of nVector registers starting + ** at r1. + ** + ** sqlite3FindInIndex() might have reordered the fields of the LHS vector + ** so that the fields are in the same order as an existing index. The + ** aiMap[] array contains a mapping from the original LHS field order to + ** the field order that matches the RHS index. */ sqlite3ExprCachePush(pParse); - r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCode(pParse, pExpr->pLeft, r1); + rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); + for(i=0; ix.pList; @@ -91638,7 +93029,7 @@ static void sqlite3ExprCodeIN( assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull); + sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } for(ii=0; iinExpr; ii++){ r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); @@ -91646,16 +93037,16 @@ static void sqlite3ExprCodeIN( sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); } if( iinExpr-1 || destIfNull!=destIfFalse ){ - sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2, + sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2, (void*)pColl, P4_COLLSEQ); VdbeCoverageIf(v, iinExpr-1); VdbeCoverageIf(v, ii==pList->nExpr-1); - sqlite3VdbeChangeP5(v, affinity); + sqlite3VdbeChangeP5(v, zAff[0]); }else{ assert( destIfNull==destIfFalse ); - sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2, + sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2, (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL); + sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL); } sqlite3ReleaseTempReg(pParse, regToFree); } @@ -91665,77 +93056,113 @@ static void sqlite3ExprCodeIN( } sqlite3VdbeResolveLabel(v, labelOk); sqlite3ReleaseTempReg(pParse, regCkNull); + goto sqlite3ExprCodeIN_finished; + } + + /* Step 2: Check to see if the LHS contains any NULL columns. If the + ** LHS does contain NULLs then the result must be either FALSE or NULL. + ** We will then skip the binary search of the RHS. + */ + if( destIfNull==destIfFalse ){ + destStep2 = destIfFalse; }else{ - - /* If the LHS is NULL, then the result is either false or NULL depending - ** on whether the RHS is empty or not, respectively. - */ - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ - if( destIfNull==destIfFalse ){ - /* Shortcut for the common case where the false and NULL outcomes are - ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); - }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfNull); - sqlite3VdbeJumpHere(v, addr1); - } - } - - if( eType==IN_INDEX_ROWID ){ - /* In this case, the RHS is the ROWID of table b-tree - */ - sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, r1); + destStep2 = destStep6 = sqlite3VdbeMakeLabel(v); + } + for(i=0; ipLeft, i); + if( sqlite3ExprCanBeNull(p) ){ + sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); VdbeCoverage(v); - }else{ - /* In this case, the RHS is an index b-tree. - */ - sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); - - /* If the set membership test fails, then the result of the - ** "x IN (...)" expression must be either 0 or NULL. If the set - ** contains no NULL values, then the result is 0. If the set - ** contains one or more NULL values, then the result of the - ** expression is also NULL. - */ - assert( destIfFalse!=destIfNull || rRhsHasNull==0 ); - if( rRhsHasNull==0 ){ - /* This branch runs if it is known at compile time that the RHS - ** cannot contain NULL values. This happens as the result - ** of a "NOT NULL" constraint in the database schema. - ** - ** Also run this branch if NULL is equivalent to FALSE - ** for this particular IN operator. - */ - sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - VdbeCoverage(v); - }else{ - /* In this branch, the RHS of the IN might contain a NULL and - ** the presence of a NULL on the RHS makes a difference in the - ** outcome. - */ - int addr1; - - /* First check to see if the LHS is contained in the RHS. If so, - ** then the answer is TRUE the presence of NULLs in the RHS does - ** not matter. If the LHS is not contained in the RHS, then the - ** answer is NULL if the RHS contains NULLs and the answer is - ** FALSE if the RHS is NULL-free. - */ - addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfFalse); - sqlite3VdbeJumpHere(v, addr1); - } } } - sqlite3ReleaseTempReg(pParse, r1); + + /* Step 3. The LHS is now known to be non-NULL. Do the binary search + ** of the RHS using the LHS as a probe. If found, the result is + ** true. + */ + if( eType==IN_INDEX_ROWID ){ + /* In this case, the RHS is the ROWID of table b-tree and so we also + ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 + ** into a single opcode. */ + sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs); + VdbeCoverage(v); + addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ + }else{ + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); + if( destIfFalse==destIfNull ){ + /* Combine Step 3 and Step 5 into a single opcode */ + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, + rLhs, nVector); VdbeCoverage(v); + goto sqlite3ExprCodeIN_finished; + } + /* Ordinary Step 3, for the case where FALSE and NULL are distinct */ + addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, + rLhs, nVector); VdbeCoverage(v); + } + + /* Step 4. If the RHS is known to be non-NULL and we did not find + ** an match on the search above, then the result must be FALSE. + */ + if( rRhsHasNull && nVector==1 ){ + sqlite3VdbeAddOp2(v, OP_NotNull, rRhsHasNull, destIfFalse); + VdbeCoverage(v); + } + + /* Step 5. If we do not care about the difference between NULL and + ** FALSE, then just return false. + */ + if( destIfFalse==destIfNull ) sqlite3VdbeGoto(v, destIfFalse); + + /* Step 6: Loop through rows of the RHS. Compare each row to the LHS. + ** If any comparison is NULL, then the result is NULL. If all + ** comparisons are FALSE then the final result is FALSE. + ** + ** For a scalar LHS, it is sufficient to check just the first row + ** of the RHS. + */ + if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6); + addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); + if( nVector>1 ){ + destNotNull = sqlite3VdbeMakeLabel(v); + }else{ + /* For nVector==1, combine steps 6 and 7 by immediately returning + ** FALSE if the first comparison is not NULL */ + destNotNull = destIfFalse; + } + for(i=0; iiTable, i, r3); + sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3, + (void*)pColl, P4_COLLSEQ); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r3); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); + if( nVector>1 ){ + sqlite3VdbeResolveLabel(v, destNotNull); + sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1); + VdbeCoverage(v); + + /* Step 7: If we reach this point, we know that the result must + ** be false. */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + } + + /* Jumps here in order to return true. */ + sqlite3VdbeJumpHere(v, addrTruthOp); + +sqlite3ExprCodeIN_finished: + if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); sqlite3ExprCachePop(pParse); VdbeComment((v, "end IN expr")); +sqlite3ExprCodeIN_oom_error: + sqlite3DbFree(pParse->db, aiMap); + sqlite3DbFree(pParse->db, zAff); } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -91779,52 +93206,39 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3DecOrHexToI64(z, &value); - if( c==0 || (c==2 && negFlag) ){ - if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } - sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); - }else{ + if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){ #ifdef SQLITE_OMIT_FLOATING_POINT sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); #else #ifndef SQLITE_OMIT_HEX_INTEGER if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s", z); + sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z); }else #endif { codeReal(v, z, negFlag, iMem); } #endif + }else{ + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } + sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } } -#if defined(SQLITE_DEBUG) /* -** Verify the consistency of the column cache +** Erase column-cache entry number i */ -static int cacheIsValid(Parse *pParse){ - int i, n; - for(i=n=0; iaColCache[i].iReg>0 ) n++; - } - return n==pParse->nColCache; -} -#endif - -/* -** Clear a cache entry. -*/ -static void cacheEntryClear(Parse *pParse, struct yColCache *p){ - if( p->tempReg ){ +static void cacheEntryClear(Parse *pParse, int i){ + if( pParse->aColCache[i].tempReg ){ if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = p->iReg; + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } - p->tempReg = 0; } - p->iReg = 0; pParse->nColCache--; - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); + if( inColCache ){ + pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; + } } @@ -91854,46 +93268,33 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG - for(i=0, p=pParse->aColCache; iiReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + assert( p->iTable!=iTab || p->iColumn!=iCol ); } #endif - /* Find an empty slot and replace it */ - for(i=0, p=pParse->aColCache; iiReg==0 ){ - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - pParse->nColCache++; - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); - return; + /* If the cache is already full, delete the least recently used entry */ + if( pParse->nColCache>=SQLITE_N_COLCACHE ){ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; ilrulru; + } } + p = &pParse->aColCache[idxLru]; + }else{ + p = &pParse->aColCache[pParse->nColCache++]; } - /* Replace the last recently used */ - minLru = 0x7fffffff; - idxLru = -1; - for(i=0, p=pParse->aColCache; ilrulru; - } - } - if( ALWAYS(idxLru>=0) ){ - p = &pParse->aColCache[idxLru]; - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - assert( cacheIsValid(pParse) ); - return; - } + /* Add the new entry to the end of the cache */ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; } /* @@ -91901,13 +93302,14 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int ** Purge the range of registers from the column cache. */ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ - struct yColCache *p; - if( iReg<=0 || pParse->nColCache==0 ) return; - p = &pParse->aColCache[SQLITE_N_COLCACHE-1]; - while(1){ - if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p); - if( p==pParse->aColCache ) break; - p--; + int i = 0; + while( inColCache ){ + struct yColCache *p = &pParse->aColCache[i]; + if( p->iReg >= iReg && p->iReg < iReg+nReg ){ + cacheEntryClear(pParse, i); + }else{ + i++; + } } } @@ -91931,8 +93333,7 @@ SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ ** the cache to the state it was in prior the most recent Push. */ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ - int i; - struct yColCache *p; + int i = 0; assert( pParse->iCacheLevel>=1 ); pParse->iCacheLevel--; #ifdef SQLITE_DEBUG @@ -91940,9 +93341,11 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ printf("POP to %d\n", pParse->iCacheLevel); } #endif - for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ - cacheEntryClear(pParse, p); + while( inColCache ){ + if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, i); + }else{ + i++; } } } @@ -91956,7 +93359,7 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 0; } @@ -92034,8 +93437,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iTable==iTable && p->iColumn==iColumn ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; @@ -92067,18 +93470,20 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( */ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ int i; - struct yColCache *p; #if SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("CLEAR\n"); } #endif - for(i=0, p=pParse->aColCache; iiReg ){ - cacheEntryClear(pParse, p); + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].tempReg + && pParse->nTempRegaTempReg) + ){ + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } } + pParse->nColCache = 0; } /* @@ -92110,7 +93515,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ int r = p->iReg; if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ } @@ -92120,7 +93525,9 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ /* -** Convert an expression node to a TK_REGISTER +** Convert a scalar expression node to a TK_REGISTER referencing +** register iReg. The caller must ensure that iReg already contains +** the correct value for the expression. */ static void exprToRegister(Expr *p, int iReg){ p->op2 = p->op; @@ -92129,6 +93536,38 @@ static void exprToRegister(Expr *p, int iReg){ ExprClearProperty(p, EP_Skip); } +/* +** Evaluate an expression (either a vector or a scalar expression) and store +** the result in continguous temporary registers. Return the index of +** the first register used to store the result. +** +** If the returned result register is a temporary scalar, then also write +** that register number into *piFreeable. If the returned result register +** is not a temporary or if the expression is a vector set *piFreeable +** to 0. +*/ +static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ + int iResult; + int nResult = sqlite3ExprVectorSize(p); + if( nResult==1 ){ + iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable); + }else{ + *piFreeable = 0; + if( p->op==TK_SELECT ){ + iResult = sqlite3CodeSubselect(pParse, p, 0, 0); + }else{ + int i; + iResult = pParse->nMem+1; + pParse->nMem += nResult; + for(i=0; ix.pList->a[i].pExpr, i+iResult); + } + } + } + return iResult; +} + + /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". @@ -92146,9 +93585,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ - int r1, r2, r3, r4; /* Various register numbers */ - sqlite3 *db = pParse->db; /* The database connection */ + int r1, r2; /* Various register numbers */ Expr tempX; /* Temporary expression node */ + int p5 = 0; assert( target>0 && target<=pParse->nMem ); if( v==0 ){ @@ -92167,12 +93606,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ assert( pCol->iMem>0 ); - inReg = pCol->iMem; - break; + return pCol->iMem; }else if( pAggInfo->useSortingIdx ){ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); - break; + return target; } /* Otherwise, fall thru into the TK_COLUMN case */ } @@ -92181,38 +93619,36 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( iTab<0 ){ if( pParse->ckBase>0 ){ /* Generating CHECK constraints or inserting into partial index */ - inReg = pExpr->iColumn + pParse->ckBase; - break; + return pExpr->iColumn + pParse->ckBase; }else{ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ iTab = pParse->iSelfTab; } } - inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, iTab, target, pExpr->op2); - break; } case TK_INTEGER: { codeInteger(pParse, pExpr, 0, target); - break; + return target; } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pExpr->u.zToken, 0, target); - break; + return target; } #endif case TK_STRING: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeLoadString(v, target, pExpr->u.zToken); - break; + return target; } case TK_NULL: { sqlite3VdbeAddOp2(v, OP_Null, 0, target); - break; + return target; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { @@ -92227,7 +93663,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); - break; + return target; } #endif case TK_VARIABLE: { @@ -92236,15 +93672,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); if( pExpr->u.zToken[1]!=0 ){ - assert( pExpr->u.zToken[0]=='?' - || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 ); - sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC); + const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn); + assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 ); + pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */ + sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC); } - break; + return target; } case TK_REGISTER: { - inReg = pExpr->iTable; - break; + return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { @@ -92258,42 +93694,37 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3AffinityType(pExpr->u.zToken, 0)); testcase( usedAsColumnCache(pParse, inReg, inReg) ); sqlite3ExprCacheAffinityChange(pParse, inReg, 1); - break; + return inReg; } #endif /* SQLITE_OMIT_CAST */ + case TK_IS: + case TK_ISNOT: + op = (op==TK_IS) ? TK_EQ : TK_NE; + p5 = SQLITE_NULLEQ; + /* fall-through */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2); - assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); - assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); - assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); - testcase( regFree1==0 ); - testcase( regFree2==0 ); + Expr *pLeft = pExpr->pLeft; + if( sqlite3ExprIsVector(pLeft) ){ + codeVectorCompare(pParse, pExpr, target, op, p5); + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2 | p5); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + } break; } case TK_AND: @@ -92331,10 +93762,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( pLeft ); if( pLeft->op==TK_INTEGER ){ codeInteger(pParse, pLeft, 1, target); + return target; #ifndef SQLITE_OMIT_FLOATING_POINT }else if( pLeft->op==TK_FLOAT ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pLeft->u.zToken, 1, target); + return target; #endif }else{ tempX.op = TK_INTEGER; @@ -92345,7 +93778,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); testcase( regFree2==0 ); } - inReg = target; break; } case TK_BITNOT: @@ -92354,7 +93786,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); - inReg = target; sqlite3VdbeAddOp2(v, op, r1, inReg); break; } @@ -92379,7 +93810,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ - inReg = pInfo->aFunc[pExpr->iAgg].iMem; + return pInfo->aFunc[pExpr->iAgg].iMem; } break; } @@ -92390,6 +93821,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) const char *zId; /* The function name */ u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ + sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ @@ -92438,8 +93870,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) */ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); - inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); - break; + return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); } for(i=0; ix.pSelect->pEList->nExpr)!=1 ){ + sqlite3SubselectError(pParse, nCol, 1); + }else{ + return sqlite3CodeSubselect(pParse, pExpr, 0, 0); + } break; } + case TK_SELECT_COLUMN: { + if( pExpr->pLeft->iTable==0 ){ + pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0); + } + return pExpr->pLeft->iTable + pExpr->iColumn; + } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = sqlite3VdbeMakeLabel(v); @@ -92533,7 +93975,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeResolveLabel(v, destIfFalse); sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); sqlite3VdbeResolveLabel(v, destIfNull); - break; + return target; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -92550,35 +93992,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { - Expr *pLeft = pExpr->pLeft; - struct ExprList_item *pLItem = pExpr->x.pList->a; - Expr *pRight = pLItem->pExpr; - - r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - r3 = sqlite3GetTempReg(pParse); - r4 = sqlite3GetTempReg(pParse); - codeCompare(pParse, pLeft, pRight, OP_Ge, - r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v); - pLItem++; - pRight = pLItem->pExpr; - sqlite3ReleaseTempReg(pParse, regFree2); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree2==0 ); - codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); - sqlite3ReleaseTempReg(pParse, r3); - sqlite3ReleaseTempReg(pParse, r4); - break; + exprCodeBetween(pParse, pExpr, target, 0, 0); + return target; } case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - break; + return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); } case TK_TRIGGER: { @@ -92637,6 +94057,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) break; } + case TK_VECTOR: { + sqlite3ErrorMsg(pParse, "row value misused"); + break; + } /* ** Form A: @@ -92680,8 +94104,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( (pX = pExpr->pLeft)!=0 ){ tempX = *pX; testcase( pX->op==TK_COLUMN ); - exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, ®Free1)); + exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1)); testcase( regFree1==0 ); + memset(&opCompare, 0, sizeof(opCompare)); opCompare.op = TK_EQ; opCompare.pLeft = &tempX; pTest = &opCompare; @@ -92715,7 +94140,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - assert( db->mallocFailed || pParse->nErr>0 + assert( pParse->db->mallocFailed || pParse->nErr>0 || pParse->iCacheLevel==iCacheLevel ); sqlite3VdbeResolveLabel(v, endLabel); break; @@ -92926,8 +94351,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; - if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){ - sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ + if( flags & SQLITE_ECEL_OMITREF ){ + i--; + n--; + }else{ + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); }else{ @@ -92960,20 +94390,33 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( ** ** Code it as such, taking care to do the common subexpression ** elimination of x. +** +** The xJumpIf parameter determines details: +** +** NULL: Store the boolean result in reg[dest] +** sqlite3ExprIfTrue: Jump to dest if true +** sqlite3ExprIfFalse: Jump to dest if false +** +** The jumpIfNull parameter is ignored if xJumpIf is NULL. */ static void exprCodeBetween( Parse *pParse, /* Parsing and code generating context */ Expr *pExpr, /* The BETWEEN expression */ - int dest, /* Jump here if the jump is taken */ - int jumpIfTrue, /* Take the jump if the BETWEEN is true */ + int dest, /* Jump destination or storage location */ + void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ int jumpIfNull /* Take the jump if the BETWEEN is NULL */ ){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ Expr compLeft; /* The x>=y term */ Expr compRight; /* The x<=z term */ Expr exprX; /* The x subexpression */ int regFree1 = 0; /* Temporary use register */ + + memset(&compLeft, 0, sizeof(Expr)); + memset(&compRight, 0, sizeof(Expr)); + memset(&exprAnd, 0, sizeof(Expr)); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); exprX = *pExpr->pLeft; exprAnd.op = TK_AND; @@ -92985,23 +94428,30 @@ static void exprCodeBetween( compRight.op = TK_LE; compRight.pLeft = &exprX; compRight.pRight = pExpr->x.pList->a[1].pExpr; - exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1)); - if( jumpIfTrue ){ - sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); + exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); + if( xJump ){ + xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ - sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); + /* Mark the expression is being from the ON or USING clause of a join + ** so that the sqlite3ExprCodeTarget() routine will not attempt to move + ** it into the Parse.pConstExpr list. We should use a new bit for this, + ** for clarity, but we are out of bits in the Expr.flags field so we + ** have to reuse the EP_FromJoin bit. Bummer. */ + exprX.flags |= EP_FromJoin; + sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); /* Ensure adequate test coverage */ - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==0 ); } /* @@ -93066,6 +94516,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { + if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); @@ -93098,7 +94549,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int } case TK_BETWEEN: { testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull); + exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull); break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -93112,6 +94563,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { + default_expr: if( exprAlwaysTrue(pExpr) ){ sqlite3VdbeGoto(v, dest); }else if( exprAlwaysFalse(pExpr) ){ @@ -93218,6 +94670,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { + if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); @@ -93248,7 +94701,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int } case TK_BETWEEN: { testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull); + exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull); break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -93264,6 +94717,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { + default_expr: if( exprAlwaysFalse(pExpr) ){ sqlite3VdbeGoto(v, dest); }else if( exprAlwaysTrue(pExpr) ){ @@ -93421,11 +94875,10 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){ ){ return 1; } - if( pE2->op==TK_NOTNULL - && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 - && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) - ){ - return 1; + if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ + Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); + testcase( pX!=pE1->pLeft ); + if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; } return 0; } @@ -93768,7 +95221,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempRegaTempReg) ){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 1; return; @@ -93779,10 +95232,11 @@ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ } /* -** Allocate or deallocate a block of nReg consecutive registers +** Allocate or deallocate a block of nReg consecutive registers. */ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ int i, n; + if( nReg==1 ) return sqlite3GetTempReg(pParse); i = pParse->iRangeReg; n = pParse->nRangeReg; if( nReg<=n ){ @@ -93796,6 +95250,10 @@ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ return i; } SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ + if( nReg==1 ){ + sqlite3ReleaseTempReg(pParse, iReg); + return; + } sqlite3ExprCacheRemove(pParse, iReg, nReg); if( nReg>pParse->nRangeReg ){ pParse->nRangeReg = nReg; @@ -94251,7 +95709,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ @@ -94342,7 +95800,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_parent(sql, %Q, %Q) " - "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); + "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); sqlite3DbFree(db, zWhere); } } @@ -94366,7 +95824,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( "ELSE name END " "WHERE tbl_name=%Q COLLATE nocase AND " "(type='table' OR type='index' OR type='trigger');", - zDb, SCHEMA_TABLE(iDb), zName, zName, zName, + zDb, MASTER_NAME, zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER zName, #endif @@ -94449,7 +95907,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; @@ -94527,7 +95985,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " "WHERE type = 'table' AND name = %Q", - zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, + zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqlite3DbFree(db, zCol); @@ -94611,7 +96069,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); if( !pNew ) goto exit_begin_add_column; pParse->pNewTable = pNew; - pNew->nRef = 1; + pNew->nTabRef = 1; pNew->nCol = pTab->nCol; assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; @@ -94631,7 +96089,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; - pNew->nRef = 1; + pNew->nTabRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); @@ -94859,14 +96317,14 @@ static void openStatTable( for(i=0; izName))==0 ){ + if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){ if( aTable[i].zCols ){ /* The sqlite_statN table does not exist. Create it. Note that a ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, - "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols + "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = OPFLAG_P2ISREG; @@ -94881,7 +96339,7 @@ static void openStatTable( if( zWhere ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE %s=%Q", - pDb->zName, zTab, zWhereType, zWhere + pDb->zDbSName, zTab, zWhereType, zWhere ); }else{ /* The sqlite_stat[134] table already exists. Delete all rows. */ @@ -95643,7 +97101,7 @@ static void analyzeOneTable( assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -96033,7 +97491,7 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ /* Form 3: Analyze the fully qualified table name */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ @@ -96415,7 +97873,9 @@ static int loadStatTbl( sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; } - memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); + if( pSample->n ){ + memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); + } pIdx->nSample++; } rc = sqlite3_finalize(pStmt); @@ -96493,7 +97953,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load new statistics out of the sqlite_stat1 table */ sInfo.db = db; - sInfo.zDatabase = db->aDb[iDb].zName; + sInfo.zDatabase = db->aDb[iDb].zDbSName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ zSql = sqlite3MPrintf(db, "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); @@ -96636,7 +98096,7 @@ static void attachFunc( goto attach_error; } for(i=0; inDb; i++){ - char *z = db->aDb[i].zName; + char *z = db->aDb[i].zDbSName; assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); @@ -96701,8 +98161,8 @@ static void attachFunc( sqlite3BtreeLeave(aNew->pBt); } aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - aNew->zName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zName==0 ){ + aNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && aNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -96731,7 +98191,7 @@ static void attachFunc( case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ + if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; @@ -96814,7 +98274,7 @@ static void detachFunc( for(i=0; inDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 ) continue; - if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break; } if( i>=db->nDb ){ @@ -96864,6 +98324,7 @@ static void codeAttach( sqlite3* db = pParse->db; int regArgs; + if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; @@ -96972,7 +98433,7 @@ SQLITE_PRIVATE void sqlite3FixInit( db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zName; + pFix->zDb = db->aDb[iDb].zDbSName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; @@ -97069,7 +98530,7 @@ SQLITE_PRIVATE int sqlite3FixExpr( return 1; } } - if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; + if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ @@ -97190,7 +98651,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** Setting the auth function to NULL disables this hook. The default ** setting of the auth function is NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3 *db, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pArg @@ -97230,9 +98691,9 @@ SQLITE_PRIVATE int sqlite3AuthReadCol( const char *zCol, /* Column name */ int iDb /* Index of containing database. */ ){ - sqlite3 *db = pParse->db; /* Database handle */ - char *zDb = db->aDb[iDb].zName; /* Name of attached database */ - int rc; /* Auth callback return code */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */ + int rc; /* Auth callback return code */ if( db->init.busy ) return SQLITE_OK; rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext @@ -97417,10 +98878,10 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ ** codeTableLocks() functions. */ struct TableLock { - int iDb; /* The database containing the table to be locked */ - int iTab; /* The root page of the table to be locked */ - u8 isWriteLock; /* True for write lock. False for a read lock */ - const char *zName; /* Name of the table */ + int iDb; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zLockName; /* Name of the table */ }; /* @@ -97446,6 +98907,8 @@ SQLITE_PRIVATE void sqlite3TableLock( TableLock *p; assert( iDb>=0 ); + if( iDb==1 ) return; + if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return; for(i=0; inTableLock; i++){ p = &pToplevel->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ @@ -97462,7 +98925,7 @@ SQLITE_PRIVATE void sqlite3TableLock( p->iDb = iDb; p->iTab = iTab; p->isWriteLock = isWriteLock; - p->zName = zName; + p->zLockName = zName; }else{ pToplevel->nTableLock = 0; sqlite3OomFault(pToplevel->db); @@ -97484,7 +98947,7 @@ static void codeTableLocks(Parse *pParse){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, - p->zName, P4_STATIC); + p->zLockName, P4_STATIC); } } #else @@ -97533,15 +98996,14 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( !pParse->isMultiWrite || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ - while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); if( db->auth.authLevelrc = SQLITE_AUTH_USER; sqlite3ErrorMsg(pParse, "user not authenticated"); + pParse->rc = SQLITE_AUTH_USER; return; } } @@ -97560,14 +99022,16 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); sqlite3VdbeJumpHere(v, 0); for(iDb=0; iDbnDb; iDb++){ + Schema *pSchema; if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); + pSchema = db->aDb[iDb].pSchema; sqlite3VdbeAddOp4Int(v, OP_Transaction, /* Opcode */ iDb, /* P1 */ DbMaskTest(pParse->writeMask,iDb), /* P2 */ - pParse->cookieValue[iDb], /* P3 */ - db->aDb[iDb].pSchema->iGeneration /* P4 */ + pSchema->schema_cookie, /* P3 */ + pSchema->iGeneration /* P4 */ ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); VdbeComment((v, @@ -97618,16 +99082,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ }else{ pParse->rc = SQLITE_ERROR; } - - /* We are done with this Parse object. There is no need to de-initialize it */ -#if 0 - pParse->colNamesSet = 0; - pParse->nTab = 0; - pParse->nMem = 0; - pParse->nSet = 0; - pParse->nVar = 0; - DbMaskZero(pParse->cookieMask); -#endif } /* @@ -97647,8 +99101,7 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ char *zSql; char *zErrMsg = 0; sqlite3 *db = pParse->db; -# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) - char saveBuf[SAVE_SZ]; + char saveBuf[PARSE_TAIL_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ @@ -97659,12 +99112,12 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ return; /* A malloc must have failed */ } pParse->nested++; - memcpy(saveBuf, &pParse->nVar, SAVE_SZ); - memset(&pParse->nVar, 0, SAVE_SZ); + memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); + memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); sqlite3RunParser(pParse, zSql, &zErrMsg); sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); - memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; } @@ -97703,14 +99156,22 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha return 0; } #endif - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); - if( p ) break; + while(1){ + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){ + assert( sqlite3SchemaMutexHeld(db, j, 0) ); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); + if( p ) return p; + } + } + /* Not found. If the name we were looking for was temp.sqlite_master + ** then change the name to sqlite_temp_master and try again. */ + if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break; + if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break; + zName = TEMP_MASTER_NAME; } - return p; + return 0; } /* @@ -97746,6 +99207,9 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); + if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ + pMod = sqlite3PragmaVtabRegister(pParse->db, zName); + } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ return pMod->pEpoTab; } @@ -97782,7 +99246,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem( assert( p->pSchema==0 || p->zDatabase==0 ); if( p->pSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); - zDb = pParse->db->aDb[iDb].zName; + zDb = pParse->db->aDb[iDb].zDbSName; }else{ zDb = p->zDatabase; } @@ -97810,7 +99274,7 @@ SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const cha int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); - if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; @@ -97879,8 +99343,8 @@ SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ - sqlite3DbFree(db, pDb->zName); - pDb->zName = 0; + sqlite3DbFree(db, pDb->zDbSName); + pDb->zDbSName = 0; continue; } if( jpnBytesFreed==0) && (--pTable->nRef)>0) ) return; + if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return; deleteTable(db, pTable); } @@ -98082,7 +99546,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ */ SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); - sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME); sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5); if( p->nTab==0 ){ p->nTab = 1; @@ -98100,7 +99564,10 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){ if( zName ){ Db *pDb; for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( 0==sqlite3StrICmp(pDb->zName, zName) ) break; + if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break; + /* "main" is always an acceptable alias for the primary database + ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */ + if( i==0 && 0==sqlite3_stricmp("main", zName) ) break; } } return i; @@ -98159,7 +99626,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName( return -1; } }else{ - assert( db->init.iDb==0 || db->init.busy ); + assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0); iDb = db->init.iDb; *pUnqual = pName1; } @@ -98270,7 +99737,7 @@ SQLITE_PRIVATE void sqlite3StartTable( SQLITE_CREATE_VIEW, SQLITE_CREATE_TEMP_VIEW }; - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto begin_table_error; } @@ -98289,7 +99756,7 @@ SQLITE_PRIVATE void sqlite3StartTable( ** collisions. */ if( !IN_DECLARE_VTAB ){ - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto begin_table_error; } @@ -98319,7 +99786,7 @@ SQLITE_PRIVATE void sqlite3StartTable( pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; - pTable->nRef = 1; + pTable->nTabRef = 1; pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; @@ -98844,6 +100311,9 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. +** +** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments +** the schema-version whenever the schema changes. */ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ sqlite3 *db = pParse->db; @@ -99382,7 +100852,7 @@ SQLITE_PRIVATE void sqlite3EndTable( "UPDATE %Q.%s " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, MASTER_NAME, zType, p->zName, p->zName, @@ -99397,13 +100867,13 @@ SQLITE_PRIVATE void sqlite3EndTable( /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ - if( p->tabFlags & TF_Autoincrement ){ + if( (p->tabFlags & TF_Autoincrement)!=0 ){ Db *pDb = &db->aDb[iDb]; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", - pDb->zName + pDb->zDbSName ); } } @@ -99527,7 +100997,9 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ +#ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; /* Saved xAuth pointer */ +#endif assert( pTable ); @@ -99717,7 +101189,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ */ sqlite3NestedParse(pParse, "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); + pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1); #endif sqlite3ReleaseTempReg(pParse, r1); } @@ -99793,7 +101265,7 @@ static void sqlite3ClearStatTables( const char *zName /* Name of index or table */ ){ int i; - const char *zDbName = pParse->db->aDb[iDb].zName; + const char *zDbName = pParse->db->aDb[iDb].zDbSName; for(i=1; i<=4; i++){ char zTab[24]; sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i); @@ -99846,7 +101318,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in if( pTab->tabFlags & TF_Autoincrement ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.sqlite_sequence WHERE name=%Q", - pDb->zName, pTab->zName + pDb->zDbSName, pTab->zName ); } #endif @@ -99860,7 +101332,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in */ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", - pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + pDb->zDbSName, MASTER_NAME, pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } @@ -99914,7 +101386,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, { int code; const char *zTab = SCHEMA_TABLE(iDb); - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zArg2 = 0; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; @@ -100155,7 +101627,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -100207,7 +101679,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); @@ -100407,7 +101879,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( goto exit_create_index; } } - if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ if( !ifNotExist ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); }else{ @@ -100437,7 +101909,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = pDb->zName; + const char *zDb = pDb->zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -100752,7 +102224,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( */ sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName, pTab->zName, iMem, @@ -100886,7 +102358,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; @@ -100904,7 +102376,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName + db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); @@ -101047,7 +102519,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( /* Allocate additional space if needed */ if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; - int nAlloc = pSrc->nSrc+nExtra; + int nAlloc = pSrc->nSrc*2+nExtra; int nGot; pNew = sqlite3DbRealloc(db, pSrc, sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) ); @@ -101125,9 +102597,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; - pList->nSrc = 0; + pList->nSrc = 1; + memset(&pList->a[0], 0, sizeof(pList->a[0])); + pList->a[0].iCursor = -1; + }else{ + pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); } - pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); if( db->mallocFailed ){ sqlite3SrcListDelete(db, pList); return 0; @@ -101425,15 +102900,13 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3 *db = pToplevel->db; - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDb>=0 && iDbdb->nDb ); + assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbdb, iDb, 0) ); if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ DbMaskSet(pToplevel->cookieMask, iDb); - pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pToplevel); } @@ -101449,7 +102922,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb) int i; for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; - if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){ + if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){ sqlite3CodeVerifySchema(pParse, i); } } @@ -101696,7 +103169,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); @@ -102344,7 +103817,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; if( pTab ){ - pTab->nRef++; + pTab->nTabRef++; } if( sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; @@ -102410,7 +103883,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView( if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } @@ -102472,7 +103945,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( ** ); */ - pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); + pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); if( pSelectRowid == 0 ) goto limit_where_cleanup; pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); if( pEList == 0 ) goto limit_where_cleanup; @@ -102491,8 +103964,8 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( if( pSelect == 0 ) return 0; /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); - pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0; + pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); + pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; @@ -102520,7 +103993,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ - const char *zDb; /* Name of database holding pTab */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ @@ -102597,8 +104069,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - zDb = db->aDb[iDb].zName; - rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); + rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, + db->aDb[iDb].zDbSName); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; @@ -102758,7 +104230,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, sqlite3IndexAffinityStr(pParse->db, pPk), nPk); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); }else{ /* Add the rowid of the row to be deleted to the RowSet */ nKey = 1; /* OP_Seek always uses a single rowid */ @@ -102782,7 +104254,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( !isView ){ int iAddrOnce = 0; if( eOnePass==ONEPASS_MULTI ){ - iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); + iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, @@ -102804,7 +104276,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); + sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); @@ -102847,14 +104319,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( sqlite3VdbeGoto(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); } - - /* Close the cursors open on the table and its indexes. */ - if( !isView && !IsVirtual(pTab) ){ - if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur); - for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i); - } - } } /* End non-truncate path */ /* Update the sqlite_sequence table by storing the content of the @@ -103029,7 +104493,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); + sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); if( eMode!=ONEPASS_OFF ){ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } @@ -103408,23 +104872,28 @@ static void instrFunc( if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; nHaystack = sqlite3_value_bytes(argv[0]); nNeedle = sqlite3_value_bytes(argv[1]); - if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ - zHaystack = sqlite3_value_blob(argv[0]); - zNeedle = sqlite3_value_blob(argv[1]); - isText = 0; - }else{ - zHaystack = sqlite3_value_text(argv[0]); - zNeedle = sqlite3_value_text(argv[1]); - isText = 1; + if( nNeedle>0 ){ + if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ + zHaystack = sqlite3_value_blob(argv[0]); + zNeedle = sqlite3_value_blob(argv[1]); + assert( zNeedle!=0 ); + assert( zHaystack!=0 || nHaystack==0 ); + isText = 0; + }else{ + zHaystack = sqlite3_value_text(argv[0]); + zNeedle = sqlite3_value_text(argv[1]); + isText = 1; + if( zHaystack==0 || zNeedle==0 ) return; + } + while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ + N++; + do{ + nHaystack--; + zHaystack++; + }while( isText && (zHaystack[0]&0xc0)==0x80 ); + } + if( nNeedle>nHaystack ) N = 0; } - while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ - N++; - do{ - nHaystack--; - zHaystack++; - }while( isText && (zHaystack[0]&0xc0)==0x80 ); - } - if( nNeedle>nHaystack ) N = 0; sqlite3_result_int(context, N); } @@ -103804,9 +105273,19 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 }; static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; /* -** Compare two UTF-8 strings for equality where the first string can -** potentially be a "glob" or "like" expression. Return true (1) if they -** are the same and false (0) if they are different. +** Possible error returns from patternMatch() +*/ +#define SQLITE_MATCH 0 +#define SQLITE_NOMATCH 1 +#define SQLITE_NOWILDCARDMATCH 2 + +/* +** Compare two UTF-8 strings for equality where the first string is +** a GLOB or LIKE expression. Return values: +** +** SQLITE_MATCH: Match +** SQLITE_NOMATCH: No match +** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards. ** ** Globbing rules: ** @@ -103857,30 +105336,31 @@ static int patternCompare( ** single character of the input string for each "?" skipped */ while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ - return 0; + return SQLITE_NOWILDCARDMATCH; } } if( c==0 ){ - return 1; /* "*" at the end of the pattern matches */ + return SQLITE_MATCH; /* "*" at the end of the pattern matches */ }else if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOWILDCARDMATCH; }else{ /* "[...]" immediately follows the "*". We have to do a slow ** recursive search in this case, but it is an unusual case. */ assert( matchOther<0x80 ); /* '[' is a single-byte character */ - while( *zString - && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){ + while( *zString ){ + int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; SQLITE_SKIP_UTF8(zString); } - return *zString!=0; + return SQLITE_NOWILDCARDMATCH; } } /* At this point variable c contains the first character of the ** pattern string past the "*". Search in the input string for the - ** first matching character and recursively contine the match from + ** first matching character and recursively continue the match from ** that point. ** ** For a case-insensitive search, set variable cx to be the same as @@ -103889,6 +105369,7 @@ static int patternCompare( */ if( c<=0x80 ){ u32 cx; + int bMatch; if( noCase ){ cx = sqlite3Toupper(c); c = sqlite3Tolower(c); @@ -103897,27 +105378,30 @@ static int patternCompare( } while( (c2 = *(zString++))!=0 ){ if( c2!=c && c2!=cx ) continue; - if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; + bMatch = patternCompare(zPattern,zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; } }else{ + int bMatch; while( (c2 = Utf8Read(zString))!=0 ){ if( c2!=c ) continue; - if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; + bMatch = patternCompare(zPattern,zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; } } - return 0; + return SQLITE_NOWILDCARDMATCH; } if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOMATCH; zEscaped = zPattern; }else{ u32 prior_c = 0; int seen = 0; int invert = 0; c = sqlite3Utf8Read(&zString); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOMATCH; c2 = sqlite3Utf8Read(&zPattern); if( c2=='^' ){ invert = 1; @@ -103941,7 +105425,7 @@ static int patternCompare( c2 = sqlite3Utf8Read(&zPattern); } if( c2==0 || (seen ^ invert)==0 ){ - return 0; + return SQLITE_NOMATCH; } continue; } @@ -103952,23 +105436,25 @@ static int patternCompare( continue; } if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; - return 0; + return SQLITE_NOMATCH; } - return *zString==0; + return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH; } /* -** The sqlite3_strglob() interface. +** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and +** non-zero if there is no match. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){ - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0; +SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ + return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); } /* -** The sqlite3_strlike() interface. +** The sqlite3_strlike() interface. Return 0 on a match and non-zero for +** a miss - like strcmp(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0; +SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ + return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); } /* @@ -104049,7 +105535,7 @@ static void likeFunc( #ifdef SQLITE_TEST sqlite3_like_count++; #endif - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); } } @@ -104820,7 +106306,7 @@ static void groupConcatStep( zSep = ","; nSep = 1; } - if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); + if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); @@ -105283,7 +106769,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex( } for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ + if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number ** of columns. If each indexed column corresponds to a foreign key ** column of pFKey, then this index is a winner. */ @@ -105642,7 +107128,7 @@ static void fkScanChildren( assert( iCol>=0 ); zCol = pFKey->pFrom->aCol[iCol].zName; pRight = sqlite3Expr(db, TK_ID, zCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); + pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); pWhere = sqlite3ExprAnd(db, pWhere, pEq); } @@ -105664,7 +107150,7 @@ static void fkScanChildren( if( HasRowid(pTab) ){ pLeft = exprTableRegister(pParse, pTab, regData, -1); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); - pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); + pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight); }else{ Expr *pEq, *pAll = 0; Index *pPk = sqlite3PrimaryKeyIndex(pTab); @@ -105674,10 +107160,10 @@ static void fkScanChildren( assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); + pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); pAll = sqlite3ExprAnd(db, pAll, pEq); } - pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0); + pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); } pWhere = sqlite3ExprAnd(db, pWhere, pNe); } @@ -105929,7 +107415,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ @@ -106065,7 +107551,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( struct SrcList_item *pItem = pSrc->a; pItem->pTab = pFKey->pFrom; pItem->zName = pFKey->pFrom->zName; - pItem->pTab->nRef++; + pItem->pTab->nTabRef++; pItem->iCursor = pParse->nTab++; if( regNew!=0 ){ @@ -106263,10 +107749,9 @@ static Trigger *fkActionTrigger( pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) - , 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) - , 0); + ); pWhere = sqlite3ExprAnd(db, pWhere, pEq); /* For ON UPDATE, construct the next term of the WHEN clause. @@ -106278,13 +107763,11 @@ static Trigger *fkActionTrigger( pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), - 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), - 0), - 0); + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) + ); pWhen = sqlite3ExprAnd(db, pWhen, pEq); } @@ -106293,17 +107776,16 @@ static Trigger *fkActionTrigger( if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) - , 0); + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; if( pDflt ){ pNew = sqlite3ExprDup(db, pDflt, 0); }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } pList = sqlite3ExprListAppend(pParse, pList, pNew); sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); @@ -106350,7 +107832,7 @@ static Trigger *fkActionTrigger( pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); if( pWhen ){ - pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); + pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0); pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); } } @@ -106669,7 +108151,9 @@ static int readsTable(Parse *p, int iDb, Table *pTab){ /* ** Locate or create an AutoincInfo structure associated with table pTab ** which is in database iDb. Return the register number for the register -** that holds the maximum rowid. +** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT +** table. (Also return zero when doing a VACUUM since we do not want to +** update the AUTOINCREMENT counters during a VACUUM.) ** ** There is at most one AutoincInfo structure per table even if the ** same table is autoincremented multiple times due to inserts within @@ -106692,7 +108176,9 @@ static int autoIncBegin( Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ - if( pTab->tabFlags & TF_Autoincrement ){ + if( (pTab->tabFlags & TF_Autoincrement)!=0 + && (pParse->db->flags & SQLITE_Vacuum)==0 + ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; @@ -106950,8 +108436,7 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ - const char *zDb; /* Name of the database holding this table */ - int i, j, idx; /* Loop counters */ + int i, j; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ @@ -106965,7 +108450,6 @@ SQLITE_PRIVATE void sqlite3Insert( int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ - Db *pDb; /* The database containing table being inserted into */ u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ @@ -107015,9 +108499,8 @@ SQLITE_PRIVATE void sqlite3Insert( } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - pDb = &db->aDb[iDb]; - zDb = pDb->zName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, + db->aDb[iDb].zDbSName) ){ goto insert_cleanup; } withoutRowid = !HasRowid(pTab); @@ -107260,8 +108743,10 @@ SQLITE_PRIVATE void sqlite3Insert( if( aRegIdx==0 ){ goto insert_cleanup; } - for(i=0; ipIndex; ipNext, i++){ + assert( pIdx ); aRegIdx[i] = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; } } @@ -107463,12 +108948,26 @@ SQLITE_PRIVATE void sqlite3Insert( #endif { int isReplace; /* Set to true if constraints may cause a replace */ + int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); + + /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE + ** constraints or (b) there are no triggers and this table is not a + ** parent table in a foreign key constraint. It is safe to set the + ** flag in the second case as if any REPLACE constraint is hit, an + ** OP_Delete or OP_IdxDelete instruction will be executed on each + ** cursor that is disturbed. And these instructions both clear the + ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT + ** functionality. */ + bUseSeek = (isReplace==0 || (pTrigger==0 && + ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0) + )); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, - regIns, aRegIdx, 0, appendFlag, isReplace==0); + regIns, aRegIdx, 0, appendFlag, bUseSeek + ); } } @@ -107497,14 +108996,6 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3VdbeJumpHere(v, addrInsTop); } - if( !IsVirtual(pTab) && !isView ){ - /* Close all tables opened */ - if( iDataCurpIndex; pIdx; pIdx=pIdx->pNext, idx++){ - sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur); - } - } - insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into @@ -107711,7 +109202,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ - int regRowid = -1; /* Register holding ROWID value */ isUpdate = regOldData!=0; db = pParse->db; @@ -107766,8 +109256,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( case OE_Fail: { char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, pTab->aCol[i].zName); - sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, - regNewData+1+i, zMsg, P4_DYNAMIC); + sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, + regNewData+1+i); + sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); VdbeCoverage(v); break; @@ -107831,7 +109322,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } if( isUpdate ){ - /* pkChng!=0 does not mean that the rowid has change, only that + /* pkChng!=0 does not mean that the rowid has changed, only that ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); @@ -107909,7 +109400,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( ** OP_Insert replace the existing entry than it is to delete the ** existing entry and then insert a new one. */ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); - sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ @@ -107966,7 +109457,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Create a record for this index entry as it should appear after ** the insert or update. Store that record in the aRegIdx[ix] register */ - regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn); + regIdx = aRegIdx[ix]+1; for(i=0; inColumn; i++){ int iField = pIdx->aiColumn[i]; int x; @@ -107977,9 +109468,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( VdbeComment((v, "%s column %d", pIdx->zName, i)); }else{ if( iField==XN_ROWID || iField==pTab->iPKey ){ - if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ x = regNewData; - regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; }else{ x = iField + regNewData + 1; } @@ -107989,7 +109478,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); - sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn); /* In an UPDATE operation, if this index is the PRIMARY KEY index ** of a WITHOUT ROWID table and there has been no change the @@ -108003,7 +109491,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Find out what action to take in case there is a uniqueness conflict */ onError = pIdx->onError; if( onError==OE_None ){ - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; /* pIdx is not a UNIQUE index */ } @@ -108012,6 +109499,12 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( }else if( onError==OE_Default ){ onError = OE_Abort; } + + if( ix==0 && pPk==pIdx && onError==OE_Replace && pPk->pNext==0 ){ + sqlite3VdbeResolveLabel(v, addrUniqueOk); + continue; + } + /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, @@ -108102,7 +109595,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } } sqlite3VdbeResolveLabel(v, addrUniqueOk); - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ @@ -108152,7 +109644,9 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); } - sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], + aRegIdx[i]+1, + pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); pik_flags = 0; if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT; if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ @@ -108165,8 +109659,10 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0); - sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); + if( !bAffinityDone ){ + sqlite3TableAffinity(v, pTab, 0); + sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); + } if( pParse->nested ){ pik_flags = 0; }else{ @@ -108181,7 +109677,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( } sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } sqlite3VdbeChangeP5(v, pik_flags); } @@ -108246,15 +109742,15 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ + if( piDataCur ) *piDataCur = iIdxCur; + p5 = 0; + } if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - } - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - if( piDataCur ) *piDataCur = iIdxCur; - }else{ sqlite3VdbeChangeP5(v, p5); + VdbeComment((v, "%s", pIdx->zName)); } } if( iBase>pParse->nTab ) pParse->nTab = iBase; @@ -108564,6 +110060,7 @@ static int xferOptimization( sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ + u8 insFlags; sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ @@ -108580,9 +110077,16 @@ static int xferOptimization( assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); + if( db->flags & SQLITE_Vacuum ){ + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| + OPFLAG_APPEND|OPFLAG_USESEEKRESULT; + }else{ + insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND; + } sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, (char*)pDest, P4_TABLE); - sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); + sqlite3VdbeChangeP5(v, insFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); @@ -108604,7 +110108,7 @@ static int xferOptimization( sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); if( db->flags & SQLITE_Vacuum ){ /* This INSERT command is part of a VACUUM operation, which guarantees ** that the destination table is empty. If all indexed columns use @@ -108634,8 +110138,8 @@ static int xferOptimization( if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ idxInsFlags |= OPFLAG_NCHANGE; } - sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); - sqlite3VdbeChangeP5(v, idxInsFlags); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); + sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); @@ -108645,6 +110149,7 @@ static int xferOptimization( sqlite3ReleaseTempReg(pParse, regRowid); sqlite3ReleaseTempReg(pParse, regData); if( emptyDestTest ){ + sqlite3AutoincrementEnd(pParse); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); sqlite3VdbeJumpHere(v, emptyDestTest); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); @@ -108686,7 +110191,7 @@ static int xferOptimization( ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ @@ -109948,7 +111453,7 @@ static int sqlite3LoadExtension( db->aExtension[db->nExtension++] = handle; return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -109979,7 +111484,7 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ ** Enable or disable extension loading. Extension loading is disabled by ** default so as not to open security holes in older applications. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff){ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; @@ -109990,18 +111495,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono return SQLITE_OK; } -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - -/* -** The auto-extension code added regardless of whether or not extension -** loading is supported. We need a dummy sqlite3Apis pointer for that -** code if regular extension loading is not available. This is that -** dummy pointer. -*/ -#ifdef SQLITE_OMIT_LOAD_EXTENSION -static const sqlite3_api_routines sqlite3Apis = { 0 }; -#endif - +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ /* ** The following object holds the list of automatically loaded @@ -110036,7 +111530,7 @@ static SQLITE_WSD struct sqlite3AutoExtList { ** Register a statically linked extension that is automatically ** loaded by every new database connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension( +SQLITE_API int sqlite3_auto_extension( void (*xInit)(void) ){ int rc = SQLITE_OK; @@ -110083,7 +111577,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension( ** Return 1 if xInit was found on the list and removed. Return 0 if xInit ** was not on the list. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension( +SQLITE_API int sqlite3_cancel_auto_extension( void (*xInit)(void) ){ #if SQLITE_THREADSAFE @@ -110108,7 +111602,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension( /* ** Reset the automatic extension loading mechanism. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){ +SQLITE_API void sqlite3_reset_auto_extension(void){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize()==SQLITE_OK ) #endif @@ -110145,6 +111639,11 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ char *zErrmsg; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif +#ifdef SQLITE_OMIT_LOAD_EXTENSION + const sqlite3_api_routines *pThunk = 0; +#else + const sqlite3_api_routines *pThunk = &sqlite3Apis; #endif sqlite3_mutex_enter(mutex); if( i>=wsdAutoext.nExt ){ @@ -110155,7 +111654,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ } sqlite3_mutex_leave(mutex); zErrmsg = 0; - if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ + if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){ sqlite3ErrorWithMsg(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; @@ -110203,6 +111702,8 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ ** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit ** that script and rerun it. */ + +/* The various pragma types */ #define PragTyp_HEADER_VALUE 0 #define PragTyp_AUTO_VACUUM 1 #define PragTyp_FLAG 2 @@ -110246,419 +111747,559 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ #define PragTyp_REKEY 40 #define PragTyp_LOCK_STATUS 41 #define PragTyp_PARSER_TRACE 42 -#define PragFlag_NeedSchema 0x01 -#define PragFlag_ReadOnly 0x02 -static const struct sPragmaNames { - const char *const zName; /* Name of pragma */ - u8 ePragTyp; /* PragTyp_XXX value */ - u8 mPragFlag; /* Zero or more PragFlag_XXX values */ - u32 iArg; /* Extra argument */ -} aPragmaNames[] = { + +/* Property flags associated with various pragma. */ +#define PragFlg_NeedSchema 0x01 /* Force schema load before running */ +#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ +#define PragFlg_ReadOnly 0x04 /* Read-only HEADER_VALUE */ +#define PragFlg_Result0 0x08 /* Acts as query when no argument */ +#define PragFlg_Result1 0x10 /* Acts as query when has one argument */ +#define PragFlg_SchemaOpt 0x20 /* Schema restricts name search if present */ +#define PragFlg_SchemaReq 0x40 /* Schema required - "main" is default */ + +/* Names of columns for pragmas that return multi-column result +** or that return single-column results where the name of the +** result column is different from the name of the pragma +*/ +static const char *const pragCName[] = { + /* 0 */ "cache_size", /* Used by: default_cache_size */ + /* 1 */ "cid", /* Used by: table_info */ + /* 2 */ "name", + /* 3 */ "type", + /* 4 */ "notnull", + /* 5 */ "dflt_value", + /* 6 */ "pk", + /* 7 */ "table", /* Used by: stats */ + /* 8 */ "index", + /* 9 */ "width", + /* 10 */ "height", + /* 11 */ "seqno", /* Used by: index_info */ + /* 12 */ "cid", + /* 13 */ "name", + /* 14 */ "seqno", /* Used by: index_xinfo */ + /* 15 */ "cid", + /* 16 */ "name", + /* 17 */ "desc", + /* 18 */ "coll", + /* 19 */ "key", + /* 20 */ "seq", /* Used by: index_list */ + /* 21 */ "name", + /* 22 */ "unique", + /* 23 */ "origin", + /* 24 */ "partial", + /* 25 */ "seq", /* Used by: database_list */ + /* 26 */ "name", + /* 27 */ "file", + /* 28 */ "seq", /* Used by: collation_list */ + /* 29 */ "name", + /* 30 */ "id", /* Used by: foreign_key_list */ + /* 31 */ "seq", + /* 32 */ "table", + /* 33 */ "from", + /* 34 */ "to", + /* 35 */ "on_update", + /* 36 */ "on_delete", + /* 37 */ "match", + /* 38 */ "table", /* Used by: foreign_key_check */ + /* 39 */ "rowid", + /* 40 */ "parent", + /* 41 */ "fkid", + /* 42 */ "busy", /* Used by: wal_checkpoint */ + /* 43 */ "log", + /* 44 */ "checkpointed", + /* 45 */ "timeout", /* Used by: busy_timeout */ + /* 46 */ "database", /* Used by: lock_status */ + /* 47 */ "status", +}; + +/* Definitions of all built-in pragmas */ +typedef struct PragmaName { + const char *const zName; /* Name of pragma */ + u8 ePragTyp; /* PragTyp_XXX value */ + u8 mPragFlg; /* Zero or more PragFlg_XXX values */ + u8 iPragCName; /* Start of column names in pragCName[] */ + u8 nPragCName; /* Num of col names. 0 means use pragma name */ + u32 iArg; /* Extra argument */ +} PragmaName; +static const PragmaName aPragmaName[] = { #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) - { /* zName: */ "activate_extensions", - /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "activate_extensions", + /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "application_id", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_APPLICATION_ID }, + {/* zName: */ "application_id", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ BTREE_APPLICATION_ID }, #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) - { /* zName: */ "auto_vacuum", - /* ePragTyp: */ PragTyp_AUTO_VACUUM, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "auto_vacuum", + /* ePragTyp: */ PragTyp_AUTO_VACUUM, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) - { /* zName: */ "automatic_index", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_AutoIndex }, + {/* zName: */ "automatic_index", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_AutoIndex }, #endif #endif - { /* zName: */ "busy_timeout", - /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "busy_timeout", + /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 45, 1, + /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "cache_size", - /* ePragTyp: */ PragTyp_CACHE_SIZE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "cache_size", + /* ePragTyp: */ PragTyp_CACHE_SIZE, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_CACHE_SPILL, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "cache_spill", + /* ePragTyp: */ PragTyp_CACHE_SPILL, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif - { /* zName: */ "case_sensitive_like", - /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "cell_size_check", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CellSizeCk }, + {/* zName: */ "case_sensitive_like", + /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "cell_size_check", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_CellSizeCk }, #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "checkpoint_fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CkptFullFSync }, + {/* zName: */ "checkpoint_fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_CkptFullFSync }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "collation_list", - /* ePragTyp: */ PragTyp_COLLATION_LIST, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "collation_list", + /* ePragTyp: */ PragTyp_COLLATION_LIST, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 28, 2, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) - { /* zName: */ "compile_options", - /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "compile_options", + /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "count_changes", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CountRows }, + {/* zName: */ "count_changes", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_CountRows }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN - { /* zName: */ "data_store_directory", - /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "data_store_directory", + /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "data_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_DATA_VERSION }, + {/* zName: */ "data_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly, + /* ColNames: */ 0, 0, + /* iArg: */ BTREE_DATA_VERSION }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "database_list", - /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "database_list", + /* ePragTyp: */ PragTyp_DATABASE_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, + /* ColNames: */ 25, 3, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) - { /* zName: */ "default_cache_size", - /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "default_cache_size", + /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 1, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "defer_foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_DeferFKs }, + {/* zName: */ "defer_foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_DeferFKs }, #endif #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "empty_result_callbacks", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_NullCallback }, + {/* zName: */ "empty_result_callbacks", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_NullCallback }, #endif #if !defined(SQLITE_OMIT_UTF16) - { /* zName: */ "encoding", - /* ePragTyp: */ PragTyp_ENCODING, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "encoding", + /* ePragTyp: */ PragTyp_ENCODING, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "foreign_key_check", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "foreign_key_check", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, + /* ePragFlg: */ PragFlg_NeedSchema, + /* ColNames: */ 38, 4, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) - { /* zName: */ "foreign_key_list", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "foreign_key_list", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 30, 8, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ForeignKeys }, + {/* zName: */ "foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_ForeignKeys }, #endif #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "freelist_count", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_FREE_PAGE_COUNT }, + {/* zName: */ "freelist_count", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly, + /* ColNames: */ 0, 0, + /* iArg: */ BTREE_FREE_PAGE_COUNT }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "full_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_FullColNames }, - { /* zName: */ "fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_FullFSync }, + {/* zName: */ "full_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_FullColNames }, + {/* zName: */ "fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_FullFSync }, #endif #if defined(SQLITE_HAS_CODEC) - { /* zName: */ "hexkey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "hexrekey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "hexkey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_CHECK) - { /* zName: */ "ignore_check_constraints", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_IgnoreChecks }, + {/* zName: */ "ignore_check_constraints", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_IgnoreChecks }, #endif #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) - { /* zName: */ "incremental_vacuum", - /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "incremental_vacuum", + /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "index_info", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "index_list", - /* ePragTyp: */ PragTyp_INDEX_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "index_xinfo", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 1 }, + {/* zName: */ "index_info", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 11, 3, + /* iArg: */ 0 }, + {/* zName: */ "index_list", + /* ePragTyp: */ PragTyp_INDEX_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 20, 5, + /* iArg: */ 0 }, + {/* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 14, 6, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - { /* zName: */ "integrity_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "integrity_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlg: */ PragFlg_NeedSchema, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "journal_mode", - /* ePragTyp: */ PragTyp_JOURNAL_MODE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "journal_size_limit", - /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "journal_mode", + /* ePragTyp: */ PragTyp_JOURNAL_MODE, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "journal_size_limit", + /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if defined(SQLITE_HAS_CODEC) - { /* zName: */ "key", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "key", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "legacy_file_format", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_LegacyFileFmt }, + {/* zName: */ "legacy_file_format", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_LegacyFileFmt }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE - { /* zName: */ "lock_proxy_file", - /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "lock_proxy_file", + /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - { /* zName: */ "lock_status", - /* ePragTyp: */ PragTyp_LOCK_STATUS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "lock_status", + /* ePragTyp: */ PragTyp_LOCK_STATUS, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 46, 2, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "locking_mode", - /* ePragTyp: */ PragTyp_LOCKING_MODE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "max_page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "mmap_size", - /* ePragTyp: */ PragTyp_MMAP_SIZE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "page_size", - /* ePragTyp: */ PragTyp_PAGE_SIZE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "locking_mode", + /* ePragTyp: */ PragTyp_LOCKING_MODE, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "max_page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "mmap_size", + /* ePragTyp: */ PragTyp_MMAP_SIZE, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "page_size", + /* ePragTyp: */ PragTyp_PAGE_SIZE, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) - { /* zName: */ "parser_trace", - /* ePragTyp: */ PragTyp_PARSER_TRACE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "parser_trace", + /* ePragTyp: */ PragTyp_PARSER_TRACE, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "query_only", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_QueryOnly }, + {/* zName: */ "query_only", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_QueryOnly }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - { /* zName: */ "quick_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "quick_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlg: */ PragFlg_NeedSchema, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "read_uncommitted", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ReadUncommitted }, - { /* zName: */ "recursive_triggers", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_RecTriggers }, + {/* zName: */ "read_uncommitted", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_ReadUncommitted }, + {/* zName: */ "recursive_triggers", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_RecTriggers }, #endif #if defined(SQLITE_HAS_CODEC) - { /* zName: */ "rekey", - /* ePragTyp: */ PragTyp_REKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "rekey", + /* ePragTyp: */ PragTyp_REKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "reverse_unordered_selects", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ReverseOrder }, + {/* zName: */ "reverse_unordered_selects", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_ReverseOrder }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "schema_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_SCHEMA_VERSION }, + {/* zName: */ "schema_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ BTREE_SCHEMA_VERSION }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "secure_delete", - /* ePragTyp: */ PragTyp_SECURE_DELETE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "secure_delete", + /* ePragTyp: */ PragTyp_SECURE_DELETE, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "short_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ShortColNames }, + {/* zName: */ "short_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_ShortColNames }, #endif - { /* zName: */ "shrink_memory", - /* ePragTyp: */ PragTyp_SHRINK_MEMORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "soft_heap_limit", - /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "shrink_memory", + /* ePragTyp: */ PragTyp_SHRINK_MEMORY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "soft_heap_limit", + /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if defined(SQLITE_DEBUG) - { /* zName: */ "sql_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_SqlTrace }, + {/* zName: */ "sql_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_SqlTrace }, #endif #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "stats", - /* ePragTyp: */ PragTyp_STATS, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "stats", + /* ePragTyp: */ PragTyp_STATS, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 7, 4, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "synchronous", - /* ePragTyp: */ PragTyp_SYNCHRONOUS, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "synchronous", + /* ePragTyp: */ PragTyp_SYNCHRONOUS, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "table_info", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "table_info", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 1, 6, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "temp_store", - /* ePragTyp: */ PragTyp_TEMP_STORE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "temp_store_directory", - /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "temp_store", + /* ePragTyp: */ PragTyp_TEMP_STORE, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "temp_store_directory", + /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif - { /* zName: */ "threads", - /* ePragTyp: */ PragTyp_THREADS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, + {/* zName: */ "threads", + /* ePragTyp: */ PragTyp_THREADS, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "user_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_USER_VERSION }, + {/* zName: */ "user_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 0, 0, + /* iArg: */ BTREE_USER_VERSION }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if defined(SQLITE_DEBUG) - { /* zName: */ "vdbe_addoptrace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeAddopTrace }, - { /* zName: */ "vdbe_debug", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, - { /* zName: */ "vdbe_eqp", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeEQP }, - { /* zName: */ "vdbe_listing", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeListing }, - { /* zName: */ "vdbe_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeTrace }, + {/* zName: */ "vdbe_addoptrace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_VdbeAddopTrace }, + {/* zName: */ "vdbe_debug", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, + {/* zName: */ "vdbe_eqp", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_VdbeEQP }, + {/* zName: */ "vdbe_listing", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_VdbeListing }, + {/* zName: */ "vdbe_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_VdbeTrace }, #endif #endif #if !defined(SQLITE_OMIT_WAL) - { /* zName: */ "wal_autocheckpoint", - /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "wal_checkpoint", - /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, + {/* zName: */ "wal_autocheckpoint", + /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + {/* zName: */ "wal_checkpoint", + /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, + /* ePragFlg: */ PragFlg_NeedSchema, + /* ColNames: */ 42, 3, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "writable_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, + {/* zName: */ "writable_schema", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; /* Number of pragmas: 60 on by default, 73 total. */ @@ -110799,29 +112440,29 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ #endif /* SQLITE_PAGER_PRAGMAS */ /* -** Set the names of the first N columns to the values in azCol[] +** Set result column names for a pragma. */ -static void setAllColumnNames( - Vdbe *v, /* The query under construction */ - int N, /* Number of columns */ - const char **azCol /* Names of columns */ +static void setPragmaResultColumnNames( + Vdbe *v, /* The query under construction */ + const PragmaName *pPragma /* The pragma */ ){ - int i; - sqlite3VdbeSetNumCols(v, N); - for(i=0; inPragCName; + sqlite3VdbeSetNumCols(v, n==0 ? 1 : n); + if( n==0 ){ + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC); + }else{ + int i, j; + for(i=0, j=pPragma->iPragCName; iupr ? 0 : &aPragmaName[mid]; +} + /* ** Process a pragma statement. ** @@ -110941,12 +112600,11 @@ SQLITE_PRIVATE void sqlite3Pragma( Token *pId; /* Pointer to token */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ int iDb; /* Database index for */ - int lwr, upr, mid = 0; /* Binary search bounds */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ - const struct sPragmaNames *pPragma; + const PragmaName *pPragma; /* The pragma */ if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); @@ -110974,7 +112632,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } assert( pId2 ); - zDb = pId2->n>0 ? pDb->zName : 0; + zDb = pId2->n>0 ? pDb->zDbSName : 0; if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } @@ -111001,7 +112659,9 @@ SQLITE_PRIVATE void sqlite3Pragma( db->busyHandler.nBusy = 0; rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); if( rc==SQLITE_OK ){ - returnSingleText(v, "result", aFcntl[0]); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); + returnSingleText(v, aFcntl[0]); sqlite3_free(aFcntl[0]); goto pragma_out; } @@ -111016,26 +112676,19 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* Locate the pragma in the lookup table */ - lwr = 0; - upr = ArraySize(aPragmaNames)-1; - while( lwr<=upr ){ - mid = (lwr+upr)/2; - rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName); - if( rc==0 ) break; - if( rc<0 ){ - upr = mid - 1; - }else{ - lwr = mid + 1; - } - } - if( lwr>upr ) goto pragma_out; - pPragma = &aPragmaNames[mid]; + pPragma = pragmaLocate(zLeft); + if( pPragma==0 ) goto pragma_out; /* Make sure the database schema is loaded if the pragma requires that */ - if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){ + if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } + /* Register the result column names for pragmas that return results */ + if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 ){ + setPragmaResultColumnNames(v, pPragma); + } + /* Jump to the appropriate pragma handler */ switch( pPragma->ePragTyp ){ @@ -111072,7 +112725,6 @@ SQLITE_PRIVATE void sqlite3Pragma( VdbeOp *aOp; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ - setOneColumnName(v, "cache_size"); pParse->nMem += 2; sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize)); aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn); @@ -111107,7 +112759,7 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( pBt!=0 ); if( !zRight ){ int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; - returnSingleInt(v, "page_size", size); + returnSingleInt(v, size); }else{ /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). @@ -111142,7 +112794,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } } b = sqlite3BtreeSecureDelete(pBt, b); - returnSingleInt(v, "secure_delete", b); + returnSingleInt(v, b); break; } @@ -111174,8 +112826,6 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3AbsInt32(sqlite3Atoi(zRight))); } sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); break; } @@ -111221,7 +112871,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ zRet = "exclusive"; } - returnSingleText(v, "locking_mode", zRet); + returnSingleText(v, zRet); break; } @@ -111234,7 +112884,6 @@ SQLITE_PRIVATE void sqlite3Pragma( int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ int ii; /* Loop counter */ - setOneColumnName(v, "journal_mode"); if( zRight==0 ){ /* If there is no "=MODE" part of the pragma, do a query for the ** current mode */ @@ -111280,7 +112929,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( iLimit<-1 ) iLimit = -1; } iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); - returnSingleInt(v, "journal_size_limit", iLimit); + returnSingleInt(v, iLimit); break; } @@ -111298,7 +112947,7 @@ SQLITE_PRIVATE void sqlite3Pragma( Btree *pBt = pDb->pBt; assert( pBt!=0 ); if( !zRight ){ - returnSingleInt(v, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); + returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt)); }else{ int eAuto = getAutoVacuum(zRight); assert( eAuto>=0 && eAuto<=2 ); @@ -111377,7 +113026,7 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ - returnSingleInt(v, "cache_size", pDb->pSchema->cache_size); + returnSingleInt(v, pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; @@ -111411,7 +113060,7 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_CACHE_SPILL: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ - returnSingleInt(v, "cache_spill", + returnSingleInt(v, (db->flags & SQLITE_CacheSpill)==0 ? 0 : sqlite3BtreeSetSpillSize(pDb->pBt,0)); }else{ @@ -111465,7 +113114,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = SQLITE_OK; #endif if( rc==SQLITE_OK ){ - returnSingleInt(v, "mmap_size", sz); + returnSingleInt(v, sz); }else if( rc!=SQLITE_NOTFOUND ){ pParse->nErr++; pParse->rc = rc; @@ -111486,7 +113135,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_TEMP_STORE: { if( !zRight ){ - returnSingleInt(v, "temp_store", db->temp_store); + returnSingleInt(v, db->temp_store); }else{ changeTempStorage(pParse, zRight); } @@ -111505,7 +113154,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_TEMP_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, "temp_store_directory", sqlite3_temp_directory); + returnSingleText(v, sqlite3_temp_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ @@ -111549,7 +113198,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_DATA_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, "data_store_directory", sqlite3_data_directory); + returnSingleText(v, sqlite3_data_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ @@ -111588,7 +113237,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3_file *pFile = sqlite3PagerFile(pPager); sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, &proxy_file_path); - returnSingleText(v, "lock_proxy_file", proxy_file_path); + returnSingleText(v, proxy_file_path); }else{ Pager *pPager = sqlite3BtreePager(pDb->pBt); sqlite3_file *pFile = sqlite3PagerFile(pPager); @@ -111620,7 +113269,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_SYNCHRONOUS: { if( !zRight ){ - returnSingleInt(v, "synchronous", pDb->safety_level-1); + returnSingleInt(v, pDb->safety_level-1); }else{ if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, @@ -111640,7 +113289,8 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_FLAG_PRAGMAS case PragTyp_FLAG: { if( zRight==0 ){ - returnSingleInt(v, pPragma->zName, (db->flags & pPragma->iArg)!=0 ); + setPragmaResultColumnNames(v, pPragma); + returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); }else{ int mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ @@ -111690,16 +113340,12 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ - static const char *azCol[] = { - "cid", "name", "type", "notnull", "dflt_value", "pk" - }; int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ if( IsHiddenColumn(pCol) ){ @@ -111728,13 +113374,10 @@ SQLITE_PRIVATE void sqlite3Pragma( break; case PragTyp_STATS: { - static const char *azCol[] = { "table", "index", "width", "height" }; Index *pIdx; HashElem *i; - v = sqlite3GetVdbe(pParse); pParse->nMem = 4; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); sqlite3VdbeMultiLoad(v, 1, "ssii", @@ -111759,9 +113402,6 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ - static const char *azCol[] = { - "seqno", "cid", "name", "desc", "coll", "key" - }; int i; int mx; if( pPragma->iArg ){ @@ -111775,8 +113415,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } pTab = pIdx->pTable; sqlite3CodeVerifySchema(pParse, iDb); - assert( pParse->nMem<=ArraySize(azCol) ); - setAllColumnNames(v, pParse->nMem, azCol); + assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; iaiColumn[i]; sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum, @@ -111799,13 +113438,8 @@ SQLITE_PRIVATE void sqlite3Pragma( int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ - static const char *azCol[] = { - "seq", "name", "unique", "origin", "partial" - }; - v = sqlite3GetVdbe(pParse); pParse->nMem = 5; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 5, azCol); assert( 5==ArraySize(azCol) ); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeMultiLoad(v, 1, "isisi", @@ -111821,16 +113455,14 @@ SQLITE_PRIVATE void sqlite3Pragma( break; case PragTyp_DATABASE_LIST: { - static const char *azCol[] = { "seq", "name", "file" }; int i; pParse->nMem = 3; - setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zName!=0 ); + assert( db->aDb[i].zDbSName!=0 ); sqlite3VdbeMultiLoad(v, 1, "iss", i, - db->aDb[i].zName, + db->aDb[i].zDbSName, sqlite3BtreeGetFilename(db->aDb[i].pBt)); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } @@ -111838,11 +113470,9 @@ SQLITE_PRIVATE void sqlite3Pragma( break; case PragTyp_COLLATION_LIST: { - static const char *azCol[] = { "seq", "name" }; int i = 0; HashElem *p; pParse->nMem = 2; - setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); @@ -111858,17 +113488,11 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ - v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ - static const char *azCol[] = { - "id", "seq", "table", "from", "to", "on_update", "on_delete", - "match" - }; int i = 0; pParse->nMem = 8; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 8, azCol); assert( 8==ArraySize(azCol) ); while(pFK){ int j; for(j=0; jnCol; j++){ @@ -111909,14 +113533,11 @@ SQLITE_PRIVATE void sqlite3Pragma( int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ - static const char *azCol[] = { "table", "rowid", "parent", "fkid" }; regResult = pParse->nMem+1; pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ @@ -112055,7 +113676,6 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Initialize the VDBE program */ pParse->nMem = 6; - setOneColumnName(v, "integrity_check"); /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; @@ -112119,7 +113739,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); @@ -112307,7 +113927,7 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); - returnSingleText(v, "encoding", encnames[ENC(pParse->db)].zName); + returnSingleText(v, encnames[ENC(pParse->db)].zName); }else{ /* "PRAGMA encoding = XXX" */ /* Only change the value of sqlite.enc if the database handle is not ** initialized. If the main database exists, the new sqlite.enc value @@ -112370,7 +113990,7 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_HEADER_VALUE: { int iCookie = pPragma->iArg; /* Which cookie to read or write */ sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ + if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ @@ -112398,8 +114018,6 @@ SQLITE_PRIVATE void sqlite3Pragma( aOp[0].p1 = iDb; aOp[1].p1 = iDb; aOp[1].p3 = iCookie; - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); sqlite3VdbeReusable(v); } } @@ -112417,7 +114035,6 @@ SQLITE_PRIVATE void sqlite3Pragma( int i = 0; const char *zOpt; pParse->nMem = 1; - setOneColumnName(v, "compile_option"); while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ sqlite3VdbeLoadString(v, 1, zOpt); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); @@ -112434,7 +114051,6 @@ SQLITE_PRIVATE void sqlite3Pragma( ** Checkpoint the database. */ case PragTyp_WAL_CHECKPOINT: { - static const char *azCol[] = { "busy", "log", "checkpointed" }; int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); int eMode = SQLITE_CHECKPOINT_PASSIVE; if( zRight ){ @@ -112446,7 +114062,6 @@ SQLITE_PRIVATE void sqlite3Pragma( eMode = SQLITE_CHECKPOINT_TRUNCATE; } } - setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); pParse->nMem = 3; sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); @@ -112465,7 +114080,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( zRight ){ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, "wal_autocheckpoint", + returnSingleInt(v, db->xWalCallback==sqlite3WalDefaultHook ? SQLITE_PTR_TO_INT(db->pWalArg) : 0); } @@ -112498,7 +114113,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, "timeout", db->busyTimeout); + returnSingleInt(v, db->busyTimeout); break; } @@ -112518,7 +114133,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ sqlite3_soft_heap_limit64(N); } - returnSingleInt(v, "soft_heap_limit", sqlite3_soft_heap_limit64(-1)); + returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); break; } @@ -112537,8 +114152,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ){ sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); } - returnSingleInt(v, "threads", - sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); + returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); break; } @@ -112550,23 +114164,21 @@ SQLITE_PRIVATE void sqlite3Pragma( static const char *const azLockName[] = { "unlocked", "shared", "reserved", "pending", "exclusive" }; - static const char *azCol[] = { "database", "status" }; int i; - setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); pParse->nMem = 2; for(i=0; inDb; i++){ Btree *pBt; const char *zState = "unknown"; int j; - if( db->aDb[i].zName==0 ) continue; + if( db->aDb[i].zDbSName==0 ) continue; pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, + }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } - sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zName, zState); + sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } break; @@ -112622,6 +114234,312 @@ pragma_out: sqlite3DbFree(db, zLeft); sqlite3DbFree(db, zRight); } +#ifndef SQLITE_OMIT_VIRTUALTABLE +/***************************************************************************** +** Implementation of an eponymous virtual table that runs a pragma. +** +*/ +typedef struct PragmaVtab PragmaVtab; +typedef struct PragmaVtabCursor PragmaVtabCursor; +struct PragmaVtab { + sqlite3_vtab base; /* Base class. Must be first */ + sqlite3 *db; /* The database connection to which it belongs */ + const PragmaName *pName; /* Name of the pragma */ + u8 nHidden; /* Number of hidden columns */ + u8 iHidden; /* Index of the first hidden column */ +}; +struct PragmaVtabCursor { + sqlite3_vtab_cursor base; /* Base class. Must be first */ + sqlite3_stmt *pPragma; /* The pragma statement to run */ + sqlite_int64 iRowid; /* Current rowid */ + char *azArg[2]; /* Value of the argument and schema */ +}; + +/* +** Pragma virtual table module xConnect method. +*/ +static int pragmaVtabConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + const PragmaName *pPragma = (const PragmaName*)pAux; + PragmaVtab *pTab = 0; + int rc; + int i, j; + char cSep = '('; + StrAccum acc; + char zBuf[200]; + + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); + for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){ + sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); + cSep = ','; + } + if( i==0 ){ + sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); + cSep = ','; + i++; + } + j = 0; + if( pPragma->mPragFlg & PragFlg_Result1 ){ + sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); + j++; + } + if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ + sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); + j++; + } + sqlite3StrAccumAppend(&acc, ")", 1); + sqlite3StrAccumFinish(&acc); + assert( strlen(zBuf) < sizeof(zBuf)-1 ); + rc = sqlite3_declare_vtab(db, zBuf); + if( rc==SQLITE_OK ){ + pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab)); + if( pTab==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pTab, 0, sizeof(PragmaVtab)); + pTab->pName = pPragma; + pTab->db = db; + pTab->iHidden = i; + pTab->nHidden = j; + } + }else{ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + } + + *ppVtab = (sqlite3_vtab*)pTab; + return rc; +} + +/* +** Pragma virtual table module xDisconnect method. +*/ +static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){ + PragmaVtab *pTab = (PragmaVtab*)pVtab; + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* Figure out the best index to use to search a pragma virtual table. +** +** There are not really any index choices. But we want to encourage the +** query planner to give == constraints on as many hidden parameters as +** possible, and especially on the first hidden parameter. So return a +** high cost if hidden parameters are unconstrained. +*/ +static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + PragmaVtab *pTab = (PragmaVtab*)tab; + const struct sqlite3_index_constraint *pConstraint; + int i, j; + int seen[2]; + + pIdxInfo->estimatedCost = (double)1; + if( pTab->nHidden==0 ){ return SQLITE_OK; } + pConstraint = pIdxInfo->aConstraint; + seen[0] = 0; + seen[1] = 0; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + if( pConstraint->iColumn < pTab->iHidden ) continue; + j = pConstraint->iColumn - pTab->iHidden; + assert( j < 2 ); + seen[j] = i+1; + } + if( seen[0]==0 ){ + pIdxInfo->estimatedCost = (double)2147483647; + pIdxInfo->estimatedRows = 2147483647; + return SQLITE_OK; + } + j = seen[0]-1; + pIdxInfo->aConstraintUsage[j].argvIndex = 1; + pIdxInfo->aConstraintUsage[j].omit = 1; + if( seen[1]==0 ) return SQLITE_OK; + pIdxInfo->estimatedCost = (double)20; + pIdxInfo->estimatedRows = 20; + j = seen[1]-1; + pIdxInfo->aConstraintUsage[j].argvIndex = 2; + pIdxInfo->aConstraintUsage[j].omit = 1; + return SQLITE_OK; +} + +/* Create a new cursor for the pragma virtual table */ +static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ + PragmaVtabCursor *pCsr; + pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr)); + if( pCsr==0 ) return SQLITE_NOMEM; + memset(pCsr, 0, sizeof(PragmaVtabCursor)); + pCsr->base.pVtab = pVtab; + *ppCursor = &pCsr->base; + return SQLITE_OK; +} + +/* Clear all content from pragma virtual table cursor. */ +static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ + int i; + sqlite3_finalize(pCsr->pPragma); + pCsr->pPragma = 0; + for(i=0; iazArg); i++){ + sqlite3_free(pCsr->azArg[i]); + pCsr->azArg[i] = 0; + } +} + +/* Close a pragma virtual table cursor */ +static int pragmaVtabClose(sqlite3_vtab_cursor *cur){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur; + pragmaVtabCursorClear(pCsr); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* Advance the pragma virtual table cursor to the next row */ +static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; + int rc = SQLITE_OK; + + /* Increment the xRowid value */ + pCsr->iRowid++; + assert( pCsr->pPragma ); + if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){ + rc = sqlite3_finalize(pCsr->pPragma); + pCsr->pPragma = 0; + pragmaVtabCursorClear(pCsr); + } + return rc; +} + +/* +** Pragma virtual table module xFilter method. +*/ +static int pragmaVtabFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; + PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); + int rc; + int i, j; + StrAccum acc; + char *zSql; + + UNUSED_PARAMETER(idxNum); + UNUSED_PARAMETER(idxStr); + pragmaVtabCursorClear(pCsr); + j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1; + for(i=0; iazArg) ); + pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i])); + if( pCsr->azArg[j]==0 ){ + return SQLITE_NOMEM; + } + } + sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); + sqlite3StrAccumAppendAll(&acc, "PRAGMA "); + if( pCsr->azArg[1] ){ + sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); + } + sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); + if( pCsr->azArg[0] ){ + sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); + } + zSql = sqlite3StrAccumFinish(&acc); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ){ + pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); + return rc; + } + return pragmaVtabNext(pVtabCursor); +} + +/* +** Pragma virtual table module xEof method. +*/ +static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; + return (pCsr->pPragma==0); +} + +/* The xColumn method simply returns the corresponding column from +** the PRAGMA. +*/ +static int pragmaVtabColumn( + sqlite3_vtab_cursor *pVtabCursor, + sqlite3_context *ctx, + int i +){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; + PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); + if( iiHidden ){ + sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i)); + }else{ + sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT); + } + return SQLITE_OK; +} + +/* +** Pragma virtual table module xRowid method. +*/ +static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){ + PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; + *p = pCsr->iRowid; + return SQLITE_OK; +} + +/* The pragma virtual table object */ +static const sqlite3_module pragmaVtabModule = { + 0, /* iVersion */ + 0, /* xCreate - create a table */ + pragmaVtabConnect, /* xConnect - connect to an existing table */ + pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */ + pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */ + 0, /* xDestroy - Drop a table */ + pragmaVtabOpen, /* xOpen - open a cursor */ + pragmaVtabClose, /* xClose - close a cursor */ + pragmaVtabFilter, /* xFilter - configure scan constraints */ + pragmaVtabNext, /* xNext - advance a cursor */ + pragmaVtabEof, /* xEof */ + pragmaVtabColumn, /* xColumn - read data */ + pragmaVtabRowid, /* xRowid - read data */ + 0, /* xUpdate - write data */ + 0, /* xBegin - begin transaction */ + 0, /* xSync - sync transaction */ + 0, /* xCommit - commit transaction */ + 0, /* xRollback - rollback transaction */ + 0, /* xFindFunction - function overloading */ + 0, /* xRename - rename the table */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ +}; + +/* +** Check to see if zTabName is really the name of a pragma. If it is, +** then register an eponymous virtual table for that pragma and return +** a pointer to the Module object for the new virtual table. +*/ +SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){ + const PragmaName *pName; + assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 ); + pName = pragmaLocate(zName+7); + if( pName==0 ) return 0; + if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0; + assert( sqlite3HashFind(&db->aModule, zName)==0 ); + return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0); +} + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_PRAGMA */ @@ -112702,6 +114620,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char ** structures that describe the table, index, or view. */ int rc; + u8 saved_iDb = db->init.iDb; sqlite3_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ @@ -112712,7 +114631,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); - db->init.iDb = 0; + db->init.iDb = saved_iDb; + assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); @@ -112736,7 +114656,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char ** to do here is record the root page number for that index. */ Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName); if( pIndex==0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since @@ -112915,7 +114835,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ char *zSql; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", - db->aDb[iDb].zName, zMasterName); + db->aDb[iDb].zDbSName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { sqlite3_xauth xAuth; @@ -113145,18 +115065,14 @@ static int sqlite3Prepare( sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - Parse *pParse; /* Parsing context */ char *zErrMsg = 0; /* Error message */ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ + Parse sParse; /* Parsing context */ - /* Allocate the parsing context */ - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); - if( pParse==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto end_prepare; - } - pParse->pReprepare = pReprepare; + memset(&sParse, 0, PARSE_HDR_SZ); + memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); + sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ assert( sqlite3_mutex_held(db->mutex) ); @@ -113190,7 +115106,7 @@ static int sqlite3Prepare( assert( sqlite3BtreeHoldsMutex(pBt) ); rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ - const char *zDb = db->aDb[i].zName; + const char *zDb = db->aDb[i].zDbSName; sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; @@ -113200,8 +115116,7 @@ static int sqlite3Prepare( sqlite3VtabUnlockList(db); - pParse->db = db; - pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */ + sParse.db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; @@ -113214,61 +115129,61 @@ static int sqlite3Prepare( } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); - pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; sqlite3DbFree(db, zSqlCopy); }else{ - pParse->zTail = &zSql[nBytes]; + sParse.zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3RunParser(&sParse, zSql, &zErrMsg); } - assert( 0==pParse->nQueryLoop ); + assert( 0==sParse.nQueryLoop ); - if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; - if( pParse->checkSchema ){ - schemaIsValid(pParse); + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; + if( sParse.checkSchema ){ + schemaIsValid(&sParse); } if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM_BKPT; + sParse.rc = SQLITE_NOMEM_BKPT; } if( pzTail ){ - *pzTail = pParse->zTail; + *pzTail = sParse.zTail; } - rc = pParse->rc; + rc = sParse.rc; #ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ static const char * const azColName[] = { "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", "selectid", "order", "from", "detail" }; int iFirst, mx; - if( pParse->explain==2 ){ - sqlite3VdbeSetNumCols(pParse->pVdbe, 4); + if( sParse.explain==2 ){ + sqlite3VdbeSetNumCols(sParse.pVdbe, 4); iFirst = 8; mx = 12; }else{ - sqlite3VdbeSetNumCols(pParse->pVdbe, 8); + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); iFirst = 0; mx = 8; } for(i=iFirst; ipVdbe, i-iFirst, COLNAME_NAME, + sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME, azColName[i], SQLITE_STATIC); } } #endif if( db->init.busy==0 ){ - Vdbe *pVdbe = pParse->pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); + Vdbe *pVdbe = sParse.pVdbe; + sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); } - if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(pParse->pVdbe); + if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ + sqlite3VdbeFinalize(sParse.pVdbe); assert(!(*ppStmt)); }else{ - *ppStmt = (sqlite3_stmt*)pParse->pVdbe; + *ppStmt = (sqlite3_stmt*)sParse.pVdbe; } if( zErrMsg ){ @@ -113279,16 +115194,15 @@ static int sqlite3Prepare( } /* Delete any TriggerPrg structures allocated while parsing this statement. */ - while( pParse->pTriggerPrg ){ - TriggerPrg *pT = pParse->pTriggerPrg; - pParse->pTriggerPrg = pT->pNext; + while( sParse.pTriggerPrg ){ + TriggerPrg *pT = sParse.pTriggerPrg; + sParse.pTriggerPrg = pT->pNext; sqlite3DbFree(db, pT); } end_prepare: - sqlite3ParserReset(pParse); - sqlite3StackFree(db, pParse); + sqlite3ParserReset(&sParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; @@ -113369,7 +115283,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -113381,7 +115295,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -113457,7 +115371,7 @@ static int sqlite3Prepare16( ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -113469,7 +115383,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -113576,7 +115490,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; pDest->iSDParm = iParm; - pDest->affSdst = 0; + pDest->zAffSdst = 0; pDest->iSdst = 0; pDest->nSdst = 0; } @@ -113822,7 +115736,7 @@ static void addWhereTerm( pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); - pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0); + pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); if( pEq && isOuterJoin ){ ExprSetProperty(pEq, EP_FromJoin); assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); @@ -114009,7 +115923,7 @@ static void pushOntoSorter( int iLimit; /* LIMIT counter */ assert( bSeq==0 || bSeq==1 ); - assert( nData==1 || regData==regOrigData ); + assert( nData==1 || regData==regOrigData || regOrigData==0 ); if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); regBase = regData - nExpr - bSeq; @@ -114021,11 +115935,11 @@ static void pushOntoSorter( iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; pSort->labelDone = sqlite3VdbeMakeLabel(v); sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, - SQLITE_ECEL_DUP|SQLITE_ECEL_REF); + SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); if( bSeq ){ sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); } - if( nPrefixReg==0 ){ + if( nPrefixReg==0 && nData>0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); @@ -114075,7 +115989,8 @@ static void pushOntoSorter( }else{ op = OP_IdxInsert; } - sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); + sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, + regBase+nOBSat, nBase-nOBSat); if( iLimit ){ int addr; int r1 = 0; @@ -114083,7 +115998,7 @@ static void pushOntoSorter( ** register is initialized with value of LIMIT+OFFSET.) After the sorter ** fills up, delete the least entry in the sorter after each insert. ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ - addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); if( pSort->bOrderedInnerLoop ){ r1 = ++pParse->nMem; @@ -114143,34 +116058,10 @@ static void codeDistinct( r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); sqlite3ReleaseTempReg(pParse, r1); } -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate an error message when a SELECT is used within a subexpression -** (example: "a IN (SELECT * FROM table)") but it has more than 1 result -** column. We do this in a subroutine because the error used to occur -** in multiple places. (The error only occurs in one place now, but we -** retain the subroutine to minimize code disruption.) -*/ -static int checkForMultiColumnSelectError( - Parse *pParse, /* Parse context. */ - SelectDest *pDest, /* Destination of SELECT results */ - int nExpr /* Number of result columns returned by SELECT */ -){ - int eDest = pDest->eDest; - if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ - sqlite3ErrorMsg(pParse, "only a single result allowed for " - "a SELECT that is part of an expression"); - return 1; - }else{ - return 0; - } -} -#endif - /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. @@ -114178,7 +116069,7 @@ static int checkForMultiColumnSelectError( ** If srcTab is negative, then the pEList expressions ** are evaluated in order to get the data for this row. If srcTab is ** zero or more, then data is pulled from srcTab and pEList is used only -** to get number columns and the datatype for each column. +** to get the number of columns and the collation sequence for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ @@ -114193,13 +116084,20 @@ static void selectInnerLoop( ){ Vdbe *v = pParse->pVdbe; int i; - int hasDistinct; /* True if the DISTINCT keyword is present */ - int regResult; /* Start of memory holding result set */ + int hasDistinct; /* True if the DISTINCT keyword is present */ int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nPrefixReg = 0; /* Number of extra registers before regResult */ + /* Usually, regResult is the first cell in an array of memory cells + ** containing the current result row. In this case regOrig is set to the + ** same value. However, if the results are being sent to the sorter, the + ** values for any expressions that are also part of the sort-key are omitted + ** from this array. In this case regOrig is set to zero. */ + int regResult; /* Start of memory holding current results */ + int regOrig; /* Start of memory holding full result (or 0) */ + assert( v ); assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; @@ -114230,7 +116128,7 @@ static void selectInnerLoop( pParse->nMem += nResultCol; } pDest->nSdst = nResultCol; - regResult = pDest->iSdst; + regOrig = regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; ipOrderBy), set the associated + ** iOrderByCol value to one more than the index of the ORDER BY + ** expression within the sort-key that pushOntoSorter() will generate. + ** This allows the pEList field to be omitted from the sorted record, + ** saving space and CPU cycles. */ + ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); + for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){ + int j; + if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ + pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; + } + } + regOrig = 0; + assert( eDest==SRT_Set || eDest==SRT_Mem + || eDest==SRT_Coroutine || eDest==SRT_Output ); + } + nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement @@ -114320,7 +116237,7 @@ static void selectInnerLoop( int r1; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3ReleaseTempReg(pParse, r1); break; } @@ -114357,7 +116274,7 @@ static void selectInnerLoop( int addr = sqlite3VdbeCurrentAddr(v) + 4; sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); assert( pSort==0 ); } #endif @@ -114380,20 +116297,20 @@ static void selectInnerLoop( ** item into the set table with bogus data. */ case SRT_Set: { - assert( nResultCol==1 ); - pDest->affSdst = - sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst); if( pSort ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + pushOntoSorter( + pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regResult, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, + r1, pDest->zAffSdst, nResultCol); + sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3ReleaseTempReg(pParse, r1); } break; @@ -114408,14 +116325,16 @@ static void selectInnerLoop( } /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. + ** store the results in the appropriate memory cell or array of + ** memory cells and break out of the scan loop. */ case SRT_Mem: { - assert( nResultCol==1 ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + assert( nResultCol<=pDest->nSdst ); + pushOntoSorter( + pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ + assert( nResultCol==pDest->nSdst ); assert( regResult==iParm ); /* The LIMIT clause will jump out of the loop for us */ } @@ -114428,7 +116347,7 @@ static void selectInnerLoop( testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol, + pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); @@ -114478,7 +116397,7 @@ static void selectInnerLoop( } sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempRange(pParse, r2, nKey+2); @@ -114516,7 +116435,7 @@ static void selectInnerLoop( */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1); - KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra); + KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ p->aSortOrder = (u8*)&p->aColl[N+X]; p->nField = (u16)N; @@ -114713,14 +116632,13 @@ static void generateSortTail( int iParm = pDest->iSDParm; int regRow; int regRowid; + int iCol; int nKey; int iSortTab; /* Sorter cursor to read from */ int nSortData; /* Trailing values to read from sorter */ int i; int bSeq; /* True if sorter record includes seq. no. */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS struct ExprList_item *aOutEx = p->pEList->a; -#endif assert( addrBreak<0 ); if( pSort->labelBkOut ){ @@ -114729,21 +116647,21 @@ static void generateSortTail( sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } iTab = pSort->iECursor; - if( eDest==SRT_Output || eDest==SRT_Coroutine ){ + if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ regRowid = 0; regRow = pDest->iSdst; nSortData = nColumn; }else{ regRowid = sqlite3GetTempReg(pParse); - regRow = sqlite3GetTempReg(pParse); - nSortData = 1; + regRow = sqlite3GetTempRange(pParse, nColumn); + nSortData = nColumn; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; iSortTab = pParse->nTab++; if( pSort->labelBkOut ){ - addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); @@ -114758,8 +116676,14 @@ static void generateSortTail( iSortTab = iTab; bSeq = 1; } - for(i=0; iaffSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regRow, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); + assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, + pDest->zAffSdst, nColumn); + sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); break; } case SRT_Mem: { - assert( nColumn==1 ); - sqlite3ExprCodeMove(pParse, regRow, iParm, 1); /* The LIMIT clause will terminate the loop for us */ break; } @@ -114799,7 +116721,11 @@ static void generateSortTail( } } if( regRowid ){ - sqlite3ReleaseTempReg(pParse, regRow); + if( eDest==SRT_Set ){ + sqlite3ReleaseTempRange(pParse, regRow, nColumn); + }else{ + sqlite3ReleaseTempReg(pParse, regRow); + } sqlite3ReleaseTempReg(pParse, regRowid); } /* The bottom of the loop @@ -114946,7 +116872,7 @@ static const char *columnTypeImpl( zOrigTab = pTab->zName; if( pNC->pParse ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); - zOrigDb = pNC->pParse->db->aDb[iDb].zName; + zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; } #else if( iCol<0 ){ @@ -115282,7 +117208,7 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ assert( db->lookaside.bDisable ); - pTab->nRef = 1; + pTab->nTabRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); @@ -115301,7 +117227,7 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ */ static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); - if( v ) sqlite3VdbeAddOp0(v, OP_Init); + if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); if( pParse->pToplevel==0 && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) ){ @@ -115513,6 +117439,7 @@ static void generateWithRecursiveQuery( /* Process the LIMIT and OFFSET clauses, if they exist */ addrBreak = sqlite3VdbeMakeLabel(v); + p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, addrBreak); pLimit = p->pLimit; pOffset = p->pOffset; @@ -115982,7 +117909,7 @@ static int multiSelect( computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, @@ -116140,19 +118067,17 @@ static int generateOutputSubroutine( } #ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. + /* If we are creating a set for an "expr IN (SELECT ...)". */ case SRT_Set: { int r1; - assert( pIn->nSdst==1 || pParse->nErr>0 ); - pDest->affSdst = - sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); + testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); - sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); + sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, + r1, pDest->zAffSdst, pIn->nSdst); + sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, + pIn->iSdst, pIn->nSdst); sqlite3ReleaseTempReg(pParse, r1); break; } @@ -116611,8 +118536,8 @@ static int multiSelectOrderBy( #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Forward Declarations */ -static void substExprList(sqlite3*, ExprList*, int, ExprList*); -static void substSelect(sqlite3*, Select *, int, ExprList*, int); +static void substExprList(Parse*, ExprList*, int, ExprList*); +static void substSelect(Parse*, Select *, int, ExprList*, int); /* ** Scan through the expression pExpr. Replace every reference to @@ -116628,36 +118553,46 @@ static void substSelect(sqlite3*, Select *, int, ExprList*, int); ** of the subquery rather the result set of the subquery. */ static Expr *substExpr( - sqlite3 *db, /* Report malloc errors to this connection */ + Parse *pParse, /* Report errors here */ Expr *pExpr, /* Expr in which substitution occurs */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute expressions */ ){ + sqlite3 *db = pParse->db; if( pExpr==0 ) return 0; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; + Expr *pCopy = pEList->a[pExpr->iColumn].pExpr; assert( pEList!=0 && pExpr->iColumnnExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); - sqlite3ExprDelete(db, pExpr); - pExpr = pNew; + if( sqlite3ExprIsVector(pCopy) ){ + sqlite3VectorErrorMsg(pParse, pCopy); + }else{ + pNew = sqlite3ExprDup(db, pCopy, 0); + if( pNew && (pExpr->flags & EP_FromJoin) ){ + pNew->iRightJoinTable = pExpr->iRightJoinTable; + pNew->flags |= EP_FromJoin; + } + sqlite3ExprDelete(db, pExpr); + pExpr = pNew; + } } }else{ - pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); - pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); + pExpr->pLeft = substExpr(pParse, pExpr->pLeft, iTable, pEList); + pExpr->pRight = substExpr(pParse, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); + substSelect(pParse, pExpr->x.pSelect, iTable, pEList, 1); }else{ - substExprList(db, pExpr->x.pList, iTable, pEList); + substExprList(pParse, pExpr->x.pList, iTable, pEList); } } return pExpr; } static void substExprList( - sqlite3 *db, /* Report malloc errors here */ + Parse *pParse, /* Report errors here */ ExprList *pList, /* List to scan and in which to make substitutes */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute values */ @@ -116665,11 +118600,11 @@ static void substExprList( int i; if( pList==0 ) return; for(i=0; inExpr; i++){ - pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList); + pList->a[i].pExpr = substExpr(pParse, pList->a[i].pExpr, iTable, pEList); } } static void substSelect( - sqlite3 *db, /* Report malloc errors here */ + Parse *pParse, /* Report errors here */ Select *p, /* SELECT statement in which to make substitutions */ int iTable, /* Table to be replaced */ ExprList *pEList, /* Substitute values */ @@ -116680,17 +118615,17 @@ static void substSelect( int i; if( !p ) return; do{ - substExprList(db, p->pEList, iTable, pEList); - substExprList(db, p->pGroupBy, iTable, pEList); - substExprList(db, p->pOrderBy, iTable, pEList); - p->pHaving = substExpr(db, p->pHaving, iTable, pEList); - p->pWhere = substExpr(db, p->pWhere, iTable, pEList); + substExprList(pParse, p->pEList, iTable, pEList); + substExprList(pParse, p->pGroupBy, iTable, pEList); + substExprList(pParse, p->pOrderBy, iTable, pEList); + p->pHaving = substExpr(pParse, p->pHaving, iTable, pEList); + p->pWhere = substExpr(pParse, p->pWhere, iTable, pEList); pSrc = p->pSrc; assert( pSrc!=0 ); for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - substSelect(db, pItem->pSelect, iTable, pEList, 1); + substSelect(pParse, pItem->pSelect, iTable, pEList, 1); if( pItem->fg.isTabFunc ){ - substExprList(db, pItem->u1.pFuncArg, iTable, pEList); + substExprList(pParse, pItem->u1.pFuncArg, iTable, pEList); } } }while( doPrior && (p = p->pPrior)!=0 ); @@ -117087,12 +119022,12 @@ static int flattenSubquery( */ if( ALWAYS(pSubitem->pTab!=0) ){ Table *pTabToDel = pSubitem->pTab; - if( pTabToDel->nRef==1 ){ + if( pTabToDel->nTabRef==1 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); pTabToDel->pNextZombie = pToplevel->pZombieTab; pToplevel->pZombieTab = pTabToDel; }else{ - pTabToDel->nRef--; + pTabToDel->nTabRef--; } pSubitem->pTab = 0; } @@ -117207,14 +119142,15 @@ static int flattenSubquery( assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; pParent->pWhere = pWhere; - pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, - sqlite3ExprDup(db, pSub->pHaving, 0)); + pParent->pHaving = sqlite3ExprAnd(db, + sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving + ); assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ - pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); + pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); } - substSelect(db, pParent, iParent, pSub->pEList, 0); + substSelect(pParse, pParent, iParent, pSub->pEList, 0); /* The flattened query is distinct if either the inner or the ** outer query is distinct. @@ -117288,7 +119224,7 @@ static int flattenSubquery( ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( - sqlite3 *db, /* The database connection (for malloc()) */ + Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ int iCursor /* Cursor number of the subquery */ @@ -117309,16 +119245,16 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); pWhere = pWhere->pLeft; } if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; while( pSubq ){ - pNew = sqlite3ExprDup(db, pWhere, 0); - pNew = substExpr(db, pNew, iCursor, pSubq->pEList); - pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew); + pNew = sqlite3ExprDup(pParse->db, pWhere, 0); + pNew = substExpr(pParse, pNew, iCursor, pSubq->pEList); + pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); pSubq = pSubq->pPrior; } } @@ -117610,7 +119546,7 @@ static int withExpand( assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; - pTab->nRef = 1; + pTab->nTabRef = 1; pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); @@ -117633,20 +119569,20 @@ static int withExpand( ){ pItem->pTab = pTab; pItem->fg.isRecursive = 1; - pTab->nRef++; + pTab->nTabRef++; pSel->selFlags |= SF_Recursive; } } } /* Only one recursive reference is permitted. */ - if( pTab->nRef>2 ){ + if( pTab->nTabRef>2 ){ sqlite3ErrorMsg( pParse, "multiple references to recursive table: %s", pCte->zName ); return SQLITE_ERROR; } - assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); + assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); pCte->zCteErr = "circular reference: %s"; pSavedWith = pParse->pWith; @@ -117779,7 +119715,7 @@ static int selectExpander(Walker *pWalker, Select *p){ if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; - pTab->nRef = 1; + pTab->nTabRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); @@ -117792,13 +119728,13 @@ static int selectExpander(Walker *pWalker, Select *p){ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; - if( pTab->nRef==0xffff ){ + if( pTab->nTabRef>=0xffff ){ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", pTab->zName); pFrom->pTab = 0; return WRC_Abort; } - pTab->nRef++; + pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } @@ -117902,7 +119838,7 @@ static int selectExpander(Walker *pWalker, Select *p){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; + zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; jnCol; j++){ char *zName = pTab->aCol[j].zName; @@ -117948,10 +119884,10 @@ static int selectExpander(Walker *pWalker, Select *p){ if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); if( zSchemaName ){ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); } if( longNames ){ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); @@ -118188,8 +120124,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ ExprList *pList = pF->pExpr->x.pList; assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); - sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, - (void*)pF->pFunc, P4_FUNCDEF); + sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } } @@ -118240,8 +120176,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem, - (void*)pF->pFunc, P4_FUNCDEF); + sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); @@ -118385,16 +120321,6 @@ SQLITE_PRIVATE int sqlite3Select( } #endif - - /* If writing to memory or generating a set - ** only a single column may be output. - */ -#ifndef SQLITE_OMIT_SUBQUERY - if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){ - goto select_end; - } -#endif - /* Try to flatten subqueries in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -118485,7 +120411,7 @@ SQLITE_PRIVATE int sqlite3Select( ** inside the subquery. This can help the subquery to run more efficiently. */ if( (pItem->fg.jointype & JT_OUTER)==0 - && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) ){ #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ @@ -118549,7 +120475,7 @@ SQLITE_PRIVATE int sqlite3Select( /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ - onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); + onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); }else{ VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); @@ -118647,7 +120573,9 @@ SQLITE_PRIVATE int sqlite3Select( /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); - p->nSelectRow = 320; /* 4 billion rows */ + if( (p->selFlags & SF_FixedLimit)==0 ){ + p->nSelectRow = 320; /* 4 billion rows */ + } computeLimitRegisters(pParse, p, iEnd); if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); @@ -119312,7 +121240,7 @@ malloc_failed: ** Instead, the entire table should be passed to sqlite3_free_table() when ** the calling procedure is finished using it. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ @@ -119381,7 +121309,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( /* ** This routine frees the space the sqlite3_get_table() malloced. */ -SQLITE_API void SQLITE_STDCALL sqlite3_free_table( +SQLITE_API void sqlite3_free_table( char **azResult /* Result returned from sqlite3_get_table() */ ){ if( azResult ){ @@ -119496,7 +121424,6 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; /* State vector for the DB fixer */ - int iTabDb; /* Index of the database holding pTab */ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ assert( pName2!=0 ); @@ -119609,13 +121536,13 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } - iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int code = SQLITE_CREATE_TRIGGER; - const char *zDb = db->aDb[iTabDb].zName; - const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; + const char *zDb = db->aDb[iTabDb].zDbSName; + const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; @@ -119709,7 +121636,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, + db->aDb[iDb].zDbSName, MASTER_NAME, zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); @@ -119898,7 +121825,7 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; + if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; @@ -119944,7 +121871,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || @@ -119960,7 +121887,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName + db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName ); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); @@ -120063,8 +121990,10 @@ static SrcList *targetSrcList( pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ + const char *zDb; assert( iDbnDb ); - pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + zDb = db->aDb[iDb].zDbSName; + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); } } return pSrc; @@ -120278,7 +122207,6 @@ static TriggerPrg *codeRowTrigger( } pProgram->nMem = pSubParse->nMem; pProgram->nCsr = pSubParse->nTab; - pProgram->nOnce = pSubParse->nOnce; pProgram->token = (void *)pTrigger; pPrg->aColmask[0] = pSubParse->oldmask; pPrg->aColmask[1] = pSubParse->newmask; @@ -120571,7 +122499,7 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue); if( pValue ){ - sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); + sqlite3VdbeAppendP4(v, pValue, P4_MEM); } #ifndef SQLITE_OMIT_FLOATING_POINT if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ @@ -120751,7 +122679,7 @@ SQLITE_PRIVATE void sqlite3Update( int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, j<0 ? "ROWID" : pTab->aCol[j].zName, - db->aDb[iDb].zName); + db->aDb[iDb].zDbSName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ @@ -120784,12 +122712,14 @@ SQLITE_PRIVATE void sqlite3Update( int reg; if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; inKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; break; } } @@ -120900,7 +122830,7 @@ SQLITE_PRIVATE void sqlite3Update( }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3IndexAffinityStr(db, pPk), nPk); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); } sqlite3WhereEnd(pWInfo); } @@ -120952,7 +122882,7 @@ SQLITE_PRIVATE void sqlite3Update( }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); - addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); + addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); VdbeCoverage(v); }else{ @@ -121110,7 +123040,7 @@ SQLITE_PRIVATE void sqlite3Update( regNewRowid ); if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } #else if( hasFK || chngKey || pPk!=0 ){ @@ -121159,15 +123089,6 @@ SQLITE_PRIVATE void sqlite3Update( } sqlite3VdbeResolveLabel(v, labelBreak); - /* Close all tables */ - for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - assert( aRegIdx ); - if( aToOpen[i+1] ){ - sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0); - } - } - if( iDataCurflags&SQLITE_CountRows) ); - return vacuumFinalize(db, pStmt, pzErrMsg); -} - -/* -** Execute zSql on database db. The statement returns exactly -** one column. Execute this as SQL on the same database. -*/ -static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ sqlite3_stmt *pStmt; int rc; - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + /* printf("SQL: [%s]\n", zSql); fflush(stdout); */ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; - - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); - if( rc!=SQLITE_OK ){ - vacuumFinalize(db, pStmt, pzErrMsg); - return rc; + while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ + const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); + assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); + if( zSubSql ){ + assert( zSubSql[0]!='S' ); + rc = execSql(db, pzErrMsg, zSubSql); + if( rc!=SQLITE_OK ) break; } } - - return vacuumFinalize(db, pStmt, pzErrMsg); + assert( rc!=SQLITE_ROW ); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + if( rc ){ + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); + } + (void)sqlite3_finalize(pStmt); + return rc; +} +static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){ + char *z; + va_list ap; + int rc; + va_start(ap, zSql); + z = sqlite3VMPrintf(db, zSql, ap); + va_end(ap); + if( z==0 ) return SQLITE_NOMEM; + rc = execSql(db, pzErrMsg, z); + sqlite3DbFree(db, z); + return rc; } /* @@ -121436,11 +123352,12 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ ** transient would cause the database file to appear to be deleted ** following reboot. */ -SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ +SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); - sqlite3VdbeUsesBtree(v, 0); + int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; + if( v && (iDb>=2 || iDb==0) ){ + sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); + sqlite3VdbeUsesBtree(v, iDb); } return; } @@ -121448,11 +123365,10 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ -SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ +SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ - char *zSql = 0; /* SQL statements */ int saved_flags; /* Saved value of the db->flags */ int saved_nChange; /* Saved value of db->nChange */ int saved_nTotalChange; /* Saved value of db->nTotalChange */ @@ -121461,6 +123377,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ int isMemDb; /* True if vacuuming a :memory: database */ int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ + const char *zDbMain; /* Schema name of database to vacuum */ if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); @@ -121478,11 +123395,13 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); + db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks + | SQLITE_PreferBuiltin | SQLITE_Vacuum); + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); db->mTrace = 0; - pMain = db->aDb[0].pBt; + zDbMain = db->aDb[iDb].zDbSName; + pMain = db->aDb[iDb].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma @@ -121500,18 +123419,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** to write the journal header file. */ nDb = db->nDb; - if( sqlite3TempInMemory(db) ){ - zSql = "ATTACH ':memory:' AS vacuum_db;"; - }else{ - zSql = "ATTACH '' AS vacuum_db;"; - } - rc = execSql(db, pzErrMsg, zSql); - if( db->nDb>nDb ){ - pDb = &db->aDb[db->nDb-1]; - assert( strcmp(pDb->zName,"vacuum_db")==0 ); - } + rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db"); if( rc!=SQLITE_OK ) goto end_of_vacuum; - pTemp = db->aDb[db->nDb-1].pBt; + assert( (db->nDb-1)==nDb ); + pDb = &db->aDb[nDb]; + assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); + pTemp = pDb->pBt; /* The call to execSql() to attach the temp database has left the file ** locked (as there was more than one active statement when the transaction @@ -121532,16 +123445,15 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ } #endif - sqlite3BtreeSetCacheSize(pTemp, db->aDb[0].pSchema->cache_size); + sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); - rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); /* Begin a transaction and take an exclusive lock on the main database ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, ** to ensure that we do not try to change the page-size on a WAL database. */ - rc = execSql(db, pzErrMsg, "BEGIN;"); + rc = execSql(db, pzErrMsg, "BEGIN"); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeBeginTrans(pMain, 2); if( rc!=SQLITE_OK ) goto end_of_vacuum; @@ -121568,64 +123480,48 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " - " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" - " AND coalesce(rootpage,1)>0" + db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" + " WHERE type='table'AND name<>'sqlite_sequence'" + " AND coalesce(rootpage,1)>0", + zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" - " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " - " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" + " WHERE type='index' AND length(sql)>10", + zDbMain + ); if( rc!=SQLITE_OK ) goto end_of_vacuum; + db->init.iDb = 0; /* Loop through the tables in the main database. For each, do ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ - assert( (db->flags & SQLITE_Vacuum)==0 ); - db->flags |= SQLITE_Vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';'" - "FROM main.sqlite_master " - "WHERE type = 'table' AND name!='sqlite_sequence' " - " AND coalesce(rootpage,1)>0" + rc = execSqlF(db, pzErrMsg, + "SELECT'INSERT INTO vacuum_db.'||quote(name)" + "||' SELECT*FROM\"%w\".'||quote(name)" + "FROM vacuum_db.sqlite_master " + "WHERE type='table'AND coalesce(rootpage,1)>0", + zDbMain ); assert( (db->flags & SQLITE_Vacuum)!=0 ); db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; - /* Copy over the sequence table - */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Copy the triggers, views, and virtual tables from the main database ** over to the temporary database. None of these objects has any ** associated storage, so all we have to do is copy their entries ** from the SQLITE_MASTER table. */ - rc = execSql(db, pzErrMsg, - "INSERT INTO vacuum_db.sqlite_master " - " SELECT type, name, tbl_name, rootpage, sql" - " FROM main.sqlite_master" - " WHERE type='view' OR type='trigger'" - " OR (type='table' AND rootpage=0)" + rc = execSqlF(db, pzErrMsg, + "INSERT INTO vacuum_db.sqlite_master" + " SELECT*FROM \"%w\".sqlite_master" + " WHERE type IN('view','trigger')" + " OR(type='table'AND rootpage=0)", + zDbMain ); if( rc ) goto end_of_vacuum; @@ -121679,6 +123575,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ end_of_vacuum: /* Restore the original value of db->flags */ + db->init.iDb = 0; db->flags = saved_flags; db->nChange = saved_nChange; db->nTotalChange = saved_nTotalChange; @@ -121741,6 +123638,41 @@ struct VtabCtx { int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; +/* +** Construct and install a Module object for a virtual table. When this +** routine is called, it is guaranteed that all appropriate locks are held +** and the module is not already part of the connection. +*/ +SQLITE_PRIVATE Module *sqlite3VtabCreateModule( + sqlite3 *db, /* Database in which module is registered */ + const char *zName, /* Name assigned to this module */ + const sqlite3_module *pModule, /* The definition of the module */ + void *pAux, /* Context pointer for xCreate/xConnect */ + void (*xDestroy)(void *) /* Module destructor function */ +){ + Module *pMod; + int nName = sqlite3Strlen30(zName); + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); + if( pMod ){ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); + memcpy(zCopy, zName, nName+1); + pMod->zName = zCopy; + pMod->pModule = pModule; + pMod->pAux = pAux; + pMod->xDestroy = xDestroy; + pMod->pEpoTab = 0; + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + assert( pDel==0 || pDel==pMod ); + if( pDel ){ + sqlite3OomFault(db); + sqlite3DbFree(db, pDel); + pMod = 0; + } + } + return pMod; +} + /* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and @@ -121754,35 +123686,15 @@ static int createModule( void (*xDestroy)(void *) /* Module destructor function */ ){ int rc = SQLITE_OK; - int nName; sqlite3_mutex_enter(db->mutex); - nName = sqlite3Strlen30(zName); if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ - Module *pMod; - pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); - if( pMod ){ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); - memcpy(zCopy, zName, nName+1); - pMod->zName = zCopy; - pMod->pModule = pModule; - pMod->pAux = pAux; - pMod->xDestroy = xDestroy; - pMod->pEpoTab = 0; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - assert( pDel==0 || pDel==pMod ); - if( pDel ){ - sqlite3OomFault(db); - sqlite3DbFree(db, pDel); - } - } + (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); } rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); - sqlite3_mutex_leave(db->mutex); return rc; } @@ -121791,7 +123703,7 @@ static int createModule( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ @@ -121806,7 +123718,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_module( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ @@ -122057,7 +123969,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( */ if( pTable->azModuleArg ){ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } @@ -122121,7 +124033,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, MASTER_NAME, pTab->zName, pTab->zName, zStmt, @@ -122231,7 +124143,7 @@ static int vtabCallConstructor( pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->azModuleArg[1] = db->aDb[iDb].zName; + pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); @@ -122385,7 +124297,7 @@ static void addToVTrans(sqlite3 *db, VTable *pVTab){ ** This function is invoked by the vdbe to call the xCreate method ** of the virtual table named zTab in database iDb. ** -** If an error occurs, *pzErr is set to point an an English language +** If an error occurs, *pzErr is set to point to an English language ** description of the error and an SQLITE_XXX error code is returned. ** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. */ @@ -122395,7 +124307,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, Module *pMod; const char *zMod; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); /* Locate the required virtual table module */ @@ -122430,7 +124342,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ +SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; Parse *pParse; int rc = SQLITE_OK; @@ -122519,7 +124431,7 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab int rc = SQLITE_OK; Table *pTab; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ VTable *p; int (*xDestroy)(sqlite3_vtab *); @@ -122846,7 +124758,7 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ return 0; } pMod->pEpoTab = pTab; - pTab->nRef = 1; + pTab->nTabRef = 1; pTab->pSchema = db->aDb[0].pSchema; pTab->tabFlags |= TF_Virtual; pTab->nModuleArg = 0; @@ -122887,7 +124799,7 @@ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ ** The results of this routine are undefined unless it is called from ** within an xUpdate method. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ static const unsigned char aMap[] = { SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE }; @@ -122905,7 +124817,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ ** the SQLite core with additional information about the behavior ** of the virtual table being implemented. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -123086,6 +124998,8 @@ struct WhereLoop { union { struct { /* Information for internal btree tables */ u16 nEq; /* Number of equality constraints */ + u16 nBtm; /* Size of BTM vector */ + u16 nTop; /* Size of TOP vector */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ @@ -123208,19 +125122,20 @@ struct WherePath { */ struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ + WhereClause *pWC; /* The clause this term is part of */ + LogEst truthProb; /* Probability of truth for this expression */ + u16 wtFlags; /* TERM_xxx bit flags. See below */ + u16 eOperator; /* A WO_xx value describing */ + u8 nChild; /* Number of children that must disable us */ + u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X " */ + int iField; /* Field in (?,?,?) IN (SELECT...) vector */ union { int leftColumn; /* Column number of X in "X " */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; - LogEst truthProb; /* Probability of truth for this expression */ - u16 eOperator; /* A WO_xx value describing */ - u16 wtFlags; /* TERM_xxx bit flags. See below */ - u8 nChild; /* Number of children that must disable us */ - u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ - WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ }; @@ -123373,25 +125288,25 @@ struct WhereInfo { SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pDistinctSet; /* DISTINCT over all these values */ - WhereLoop *pLoops; /* List of all WhereLoop objects */ - Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ - LogEst nRowOut; /* Estimated number of output rows */ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ + int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ + int iContinue; /* Jump here to continue with next record */ + int iBreak; /* Jump here to break out of the loop */ + int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ + u8 nLevel; /* Number of nested loop */ i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ u8 sorted; /* True if really sorted (not just grouped) */ u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ - u8 nLevel; /* Number of nested loop */ u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ int iTop; /* The very beginning of the WHERE loop */ - int iContinue; /* Jump here to continue with next record */ - int iBreak; /* Jump here to break out of the loop */ - int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ - int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ - WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ + WhereLoop *pLoops; /* List of all WhereLoop objects */ + Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ + LogEst nRowOut; /* Estimated number of output rows */ WhereClause sWC; /* Decomposition of the WHERE clause */ + WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; @@ -123515,6 +125430,17 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN + +/* +** Return the name of the i-th column of the pIdx index. +*/ +static const char *explainIndexColumnName(Index *pIdx, int i){ + i = pIdx->aiColumn[i]; + if( i==XN_EXPR ) return ""; + if( i==XN_ROWID ) return "rowid"; + return pIdx->pTable->aCol[i].zName; +} + /* ** This routine is a helper for explainIndexRange() below ** @@ -123525,24 +125451,32 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC */ static void explainAppendTerm( StrAccum *pStr, /* The text expression being built */ - int iTerm, /* Index of this term. First is zero */ - const char *zColumn, /* Name of the column */ + Index *pIdx, /* Index to read column names from */ + int nTerm, /* Number of terms */ + int iTerm, /* Zero-based index of first term. */ + int bAnd, /* Non-zero to append " AND " */ const char *zOp /* Name of the operator */ ){ - if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppendAll(pStr, zColumn); - sqlite3StrAccumAppend(pStr, zOp, 1); - sqlite3StrAccumAppend(pStr, "?", 1); -} + int i; -/* -** Return the name of the i-th column of the pIdx index. -*/ -static const char *explainIndexColumnName(Index *pIdx, int i){ - i = pIdx->aiColumn[i]; - if( i==XN_EXPR ) return ""; - if( i==XN_ROWID ) return "rowid"; - return pIdx->pTable->aCol[i].zName; + assert( nTerm>=1 ); + if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); + + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); + + sqlite3StrAccumAppend(pStr, zOp, 1); + + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); } /* @@ -123575,12 +125509,11 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ j = i; if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, i); - explainAppendTerm(pStr, i++, z, ">"); + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">"); + i = 1; } if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, j); - explainAppendTerm(pStr, i, z, "<"); + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } @@ -123770,7 +125703,7 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ int nLoop = 0; - while( pTerm + while( ALWAYS(pTerm!=0) && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 @@ -123826,16 +125759,45 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ } } +/* +** Expression pRight, which is the RHS of a comparison operation, is +** either a vector of n elements or, if n==1, a scalar expression. +** Before the comparison operation, affinity zAff is to be applied +** to the pRight values. This function modifies characters within the +** affinity string to SQLITE_AFF_BLOB if either: +** +** * the comparison will be performed with no affinity, or +** * the affinity change in zAff is guaranteed not to change the value. +*/ +static void updateRangeAffinityStr( + Expr *pRight, /* RHS of comparison */ + int n, /* Number of vector elements in comparison */ + char *zAff /* Affinity string to modify */ +){ + int i; + for(i=0; ipVdbe; int iReg; /* Register holding results */ + assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); assert( iTarget>0 ); if( pX->op==TK_EQ || pX->op==TK_IS ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); @@ -123858,10 +125821,13 @@ static int codeEqualityTerm( sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE_OMIT_SUBQUERY }else{ - int eType; + int eType = IN_INDEX_NOOP; int iTab; struct InLoop *pIn; WhereLoop *pLoop = pLevel->pWLoop; + int i; + int nEq = 0; + int *aiMap = 0; if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 @@ -123873,7 +125839,78 @@ static int codeEqualityTerm( } assert( pX->op==TK_IN ); iReg = iTarget; - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0); + + for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){ + disableTerm(pLevel, pTerm); + return iTarget; + } + } + for(i=iEq;inLTerm; i++){ + if( ALWAYS(pLoop->aLTerm[i]) && pLoop->aLTerm[i]->pExpr==pX ) nEq++; + } + + if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); + }else{ + Select *pSelect = pX->x.pSelect; + sqlite3 *db = pParse->db; + u16 savedDbOptFlags = db->dbOptFlags; + ExprList *pOrigRhs = pSelect->pEList; + ExprList *pOrigLhs = pX->pLeft->x.pList; + ExprList *pRhs = 0; /* New Select.pEList for RHS */ + ExprList *pLhs = 0; /* New pX->pLeft vector */ + + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iField = pLoop->aLTerm[i]->iField - 1; + Expr *pNewRhs = sqlite3ExprDup(db, pOrigRhs->a[iField].pExpr, 0); + Expr *pNewLhs = sqlite3ExprDup(db, pOrigLhs->a[iField].pExpr, 0); + + pRhs = sqlite3ExprListAppend(pParse, pRhs, pNewRhs); + pLhs = sqlite3ExprListAppend(pParse, pLhs, pNewLhs); + } + } + if( !db->mallocFailed ){ + Expr *pLeft = pX->pLeft; + + if( pSelect->pOrderBy ){ + /* If the SELECT statement has an ORDER BY clause, zero the + ** iOrderByCol variables. These are set to non-zero when an + ** ORDER BY term exactly matches one of the terms of the + ** result-set. Since the result-set of the SELECT statement may + ** have been modified or reordered, these variables are no longer + ** set correctly. Since setting them is just an optimization, + ** it's easiest just to zero them here. */ + ExprList *pOrderBy = pSelect->pOrderBy; + for(i=0; inExpr; i++){ + pOrderBy->a[i].u.x.iOrderByCol = 0; + } + } + + /* Take care here not to generate a TK_VECTOR containing only a + ** single value. Since the parser never creates such a vector, some + ** of the subroutines do not handle this case. */ + if( pLhs->nExpr==1 ){ + pX->pLeft = pLhs->a[0].pExpr; + }else{ + pLeft->x.pList = pLhs; + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); + testcase( aiMap==0 ); + } + pSelect->pEList = pRhs; + db->dbOptFlags |= SQLITE_QueryFlattener; + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); + db->dbOptFlags = savedDbOptFlags; + testcase( aiMap!=0 && aiMap[0]!=0 ); + pSelect->pEList = pOrigRhs; + pLeft->x.pList = pOrigLhs; + pX->pLeft = pLeft; + } + sqlite3ExprListDelete(pParse->db, pLhs); + sqlite3ExprListDelete(pParse->db, pRhs); + } + if( eType==IN_INDEX_INDEX_DESC ){ testcase( bRev ); bRev = !bRev; @@ -123883,28 +125920,45 @@ static int codeEqualityTerm( VdbeCoverageIf(v, bRev); VdbeCoverageIf(v, !bRev); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); + pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); } - pLevel->u.in.nIn++; + + i = pLevel->u.in.nIn; + pLevel->u.in.nIn += nEq; pLevel->u.in.aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ - pIn += pLevel->u.in.nIn - 1; - pIn->iCur = iTab; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); - }else{ - pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); + int iMap = 0; /* Index in aiMap[] */ + pIn += i; + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iOut = iReg + i - iEq; + if( eType==IN_INDEX_ROWID ){ + testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */ + pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); + }else{ + int iCol = aiMap ? aiMap[iMap++] : 0; + pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); + } + sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); + if( i==iEq ){ + pIn->iCur = iTab; + pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; + }else{ + pIn->eEndLoopOp = OP_Noop; + } + pIn++; + } } - pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; - sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v); }else{ pLevel->u.in.nIn = 0; } + sqlite3DbFree(pParse->db, aiMap); #endif } disableTerm(pLevel, pTerm); @@ -124030,9 +126084,15 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } } - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IN ); - if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ + if( pTerm->eOperator & WO_IN ){ + if( pTerm->pExpr->flags & EP_xIsSelect ){ + /* No affinity ever needs to be (or should be) applied to a value + ** from the RHS of an "? IN (SELECT ...)" expression. The + ** sqlite3FindInIndex() routine has already ensured that the + ** affinity of the comparison has been applied to the value. */ + if( zAff ) zAff[j] = SQLITE_AFF_BLOB; + } + }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ Expr *pRight = pTerm->pExpr->pRight; if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); @@ -124355,6 +126415,39 @@ static void codeDeferredSeek( } } +/* +** If the expression passed as the second argument is a vector, generate +** code to write the first nReg elements of the vector into an array +** of registers starting with iReg. +** +** If the expression is not a vector, then nReg must be passed 1. In +** this case, generate code to evaluate the expression and leave the +** result in register iReg. +*/ +static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ + assert( nReg>0 ); + if( sqlite3ExprIsVector(p) ){ +#ifndef SQLITE_OMIT_SUBQUERY + if( (p->flags & EP_xIsSelect) ){ + Vdbe *v = pParse->pVdbe; + int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0); + sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); + }else +#endif + { + int i; + ExprList *pList = p->x.pList; + assert( nReg<=pList->nExpr ); + for(i=0; ia[i].pExpr, iReg+i); + } + } + }else{ + assert( nReg==1 ); + sqlite3ExprCode(pParse, p, iReg); + } +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -124450,14 +126543,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; }else{ - sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); + Expr *pRight = pTerm->pExpr->pRight; + codeExprOrVector(pParse, pRight, iTarget, 1); } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, - pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); + pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; pLevel->p1 = iCur; @@ -124490,7 +126584,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Generate code that will continue to the next row if ** the IN constraint is not satisfied */ - pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0); + pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); assert( pCompare!=0 || db->mallocFailed ); if( pCompare ){ pCompare->pLeft = pTerm->pExpr->pLeft; @@ -124564,6 +126658,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ + int op; /* Cursor seek operation */ /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx @@ -124583,8 +126678,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); - sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); + if( sqlite3ExprIsVector(pX->pRight) ){ + r1 = rTemp = sqlite3GetTempReg(pParse); + codeExprOrVector(pParse, pX->pRight, r1, 1); + op = aMoveOp[(pX->op - TK_GT) | 0x0001]; + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); + disableTerm(pLevel, pStart); + op = aMoveOp[(pX->op - TK_GT)]; + } + sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); @@ -124592,7 +126695,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); - disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); VdbeCoverageIf(v, bRev==0); @@ -124606,13 +126708,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); memEndValue = ++pParse->nMem; - sqlite3ExprCode(pParse, pX->pRight, memEndValue); - if( pX->op==TK_LT || pX->op==TK_GT ){ + codeExprOrVector(pParse, pX->pRight, memEndValue, 1); + if( 0==sqlite3ExprIsVector(pX->pRight) + && (pX->op==TK_LT || pX->op==TK_GT) + ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } - disableTerm(pLevel, pEnd); + if( 0==sqlite3ExprIsVector(pX->pRight) ){ + disableTerm(pLevel, pEnd); + } } start = sqlite3VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; @@ -124679,6 +126785,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ }; u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ + u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */ + u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */ int regBase; /* Base register holding constraint values */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ @@ -124691,7 +126799,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ - char cEndAff = 0; /* Affinity for end of range constraint */ + char *zEndAff = 0; /* Affinity for end of range constraint */ u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ @@ -124725,14 +126833,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( j = nEq; if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; - nExtraReg = 1; + nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm); /* Like optimization range constraints always occur in pairs */ assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; - nExtraReg = 1; + nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop); #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ assert( pRangeStart!=0 ); /* LIKE opt constraints */ @@ -124750,11 +126858,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); } #endif - if( pRangeStart==0 - && (j = pIdx->aiColumn[nEq])>=0 - && pIdx->pTable->aCol[j].notNull==0 - ){ - bSeekPastNull = 1; + if( pRangeStart==0 ){ + j = pIdx->aiColumn[nEq]; + if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ + bSeekPastNull = 1; + } } } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); @@ -124768,6 +126876,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); SWAP(u8, bSeekPastNull, bStopAtNull); + SWAP(u8, nBtm, nTop); } /* Generate code to evaluate all constraint terms using == or IN @@ -124777,7 +126886,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); - if( zStartAff ) cEndAff = zStartAff[nEq]; + if( zStartAff && nTop ){ + zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); + } addrNxt = pLevel->addrNxt; testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); @@ -124792,7 +126903,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( nConstraint = nEq; if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; - sqlite3ExprCode(pParse, pRight, regBase+nEq); + codeExprOrVector(pParse, pRight, regBase+nEq, nBtm); whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) @@ -124801,18 +126912,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverage(v); } if( zStartAff ){ - if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_BLOB){ - /* Since the comparison is to be performed with no conversions - ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE_AFF_BLOB. */ - zStartAff[nEq] = SQLITE_AFF_BLOB; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){ - zStartAff[nEq] = SQLITE_AFF_BLOB; - } + updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); } - nConstraint++; + nConstraint += nBtm; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); + if( sqlite3ExprIsVector(pRight)==0 ){ + disableTerm(pLevel, pRangeStart); + }else{ + startEq = 1; + } bSeekPastNull = 0; }else if( bSeekPastNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); @@ -124845,7 +126953,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); - sqlite3ExprCode(pParse, pRight, regBase+nEq); + codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) @@ -124853,19 +126961,27 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } - if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_BLOB - && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff) - ){ - codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff); + if( zEndAff ){ + updateRangeAffinityStr(pRight, nTop, zEndAff); + codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); + }else{ + assert( pParse->db->mallocFailed ); } - nConstraint++; + nConstraint += nTop; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); + + if( sqlite3ExprIsVector(pRight)==0 ){ + disableTerm(pLevel, pRangeEnd); + }else{ + endEq = 1; + } }else if( bStopAtNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); endEq = 0; nConstraint++; } sqlite3DbFree(db, zStartAff); + sqlite3DbFree(db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); @@ -124881,8 +126997,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } /* Seek the table cursor, if required */ - disableTerm(pLevel, pRangeStart); - disableTerm(pLevel, pRangeEnd); if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ @@ -124906,9 +127020,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } - /* Record the instruction used to terminate the loop. Disable - ** WHERE clause terms made redundant by the index range scan. - */ + /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; }else if( bRev ){ @@ -124985,7 +127097,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( u16 wctrlFlags; /* Flags for sub-WHERE clause */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ Table *pTab = pTabItem->pTab; - + pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->eOperator & WO_OR ); @@ -125071,7 +127183,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ - pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0); + pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr); } } @@ -125144,7 +127256,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } if( iSet>=0 ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); - sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid, + r, nPk); if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } @@ -125286,7 +127399,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** the implied "t1.a=123" constraint. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE, *pEAlt; + Expr *pE, sEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; @@ -125304,13 +127417,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); VdbeModuleComment((v, "begin transitive constraint")); - pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); - if( pEAlt ){ - *pEAlt = *pAlt->pExpr; - pEAlt->pLeft = pE->pLeft; - sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL); - sqlite3StackFree(db, pEAlt); - } + sEAlt = *pAlt->pExpr; + sEAlt.pLeft = pE->pLeft; + sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); } /* For a LEFT OUTER JOIN, generate code that will record the fact that @@ -125419,7 +127528,6 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); - memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); } pTerm = &pWC->a[idx = pWC->nTerm++]; if( p && ExprHasProperty(p, EP_Unlikely) ){ @@ -125431,13 +127539,15 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; + memset(&pTerm->eOperator, 0, + sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); return idx; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" +** "=", "<", ">", "<=", ">=", "IN", "IS", and "IS NULL" */ static int allowedOp(int op){ assert( TK_GT>TK_EQ && TK_GT, <, >= or <=), perform the processing + ** on the first element of the vector. */ + assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); + assert( TK_ISop==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ + pExpr = pExpr->x.pList->a[0].pExpr; + } + if( pExpr->op==TK_COLUMN ){ *piCur = pExpr->iTable; *piColumn = pExpr->iColumn; @@ -126193,10 +128316,10 @@ static int exprMightBeIndexed( for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->aColExpr==0 ) continue; for(i=0; inKeyCol; i++){ - if( pIdx->aiColumn[i]!=(-2) ) continue; + if( pIdx->aiColumn[i]!=XN_EXPR ) continue; if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ *piCur = iCur; - *piColumn = -2; + *piColumn = XN_EXPR; return 1; } } @@ -126253,6 +128376,7 @@ static void exprAnalyze( op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); + if( sqlite3ExprCheckIN(pParse, pExpr) ) return; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); }else{ @@ -126279,18 +128403,26 @@ static void exprAnalyze( Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - if( exprMightBeIndexed(pSrc, prereqLeft, pLeft, &iCur, &iColumn) ){ + + if( pTerm->iField>0 ){ + assert( op==TK_IN ); + assert( pLeft->op==TK_VECTOR ); + pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; + } + + if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){ pTerm->leftCursor = iCur; pTerm->u.leftColumn = iColumn; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight - && exprMightBeIndexed(pSrc, pTerm->prereqRight, pRight, &iCur, &iColumn) + && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn) ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ + assert( pTerm->iField==0 ); if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite3ExprDup(db, pExpr, 0); @@ -126351,7 +128483,7 @@ static void exprAnalyze( int idxNew; pNewExpr = sqlite3PExpr(pParse, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0), - sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); + sqlite3ExprDup(db, pList->a[i].pExpr, 0)); transferJoinMarkings(pNewExpr, pExpr); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -126436,7 +128568,7 @@ static void exprAnalyze( pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), - pStr1, 0); + pStr1); transferJoinMarkings(pNewExpr1, pExpr); idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); @@ -126444,7 +128576,7 @@ static void exprAnalyze( pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), - pStr2, 0); + pStr2); transferJoinMarkings(pNewExpr2, pExpr); idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); @@ -126477,7 +128609,7 @@ static void exprAnalyze( if( (prereqExpr & prereqColumn)==0 ){ Expr *pNewExpr; pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0), 0); + 0, sqlite3ExprDup(db, pRight, 0)); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; @@ -126494,6 +128626,60 @@ static void exprAnalyze( } #endif /* SQLITE_OMIT_VIRTUALTABLE */ + /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create + ** new terms for each component comparison - "a = ?" and "b = ?". The + ** new terms completely replace the original vector comparison, which is + ** no longer used. + ** + ** This is only required if at least one side of the comparison operation + ** is not a sub-select. */ + if( pWC->op==TK_AND + && (pExpr->op==TK_EQ || pExpr->op==TK_IS) + && sqlite3ExprIsVector(pExpr->pLeft) + && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 + || (pExpr->pRight->flags & EP_xIsSelect)==0 + )){ + int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); + int i; + assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ); + for(i=0; ipLeft, i); + Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); + + pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); + transferJoinMarkings(pNew, pExpr); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); + } + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->eOperator = 0; + } + + /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create + ** a virtual term for each vector component. The expression object + ** used by each such virtual term is pExpr (the full vector IN(...) + ** expression). The WhereTerm.iField variable identifies the index within + ** the vector on the LHS that the virtual term represents. + ** + ** This only works if the RHS is a simple SELECT, not a compound + */ + if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0 + && pExpr->pLeft->op==TK_VECTOR + && pExpr->x.pSelect->pPrior==0 + ){ + int i; + for(i=0; ipLeft); i++){ + int idxNew; + idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); + pWC->a[idxNew].iField = i+1; + exprAnalyze(pSrc, pWC, idxNew); + markTermAsChild(pWC, idxNew, idxTerm); + } + } + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* When sqlite_stat3 histogram data is available an operator of the ** form "x IS NOT NULL" can sometimes be evaluated more efficiently @@ -126514,7 +128700,7 @@ static void exprAnalyze( pNewExpr = sqlite3PExpr(pParse, TK_GT, sqlite3ExprDup(db, pLeft, 0), - sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); + sqlite3ExprAlloc(db, TK_NULL, 0, 0)); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); @@ -126535,6 +128721,8 @@ static void exprAnalyze( /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ + testcase( pTerm!=&pWC->a[idxTerm] ); + pTerm = &pWC->a[idxTerm]; pTerm->prereqRight |= extraRight; } @@ -126617,13 +128805,14 @@ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ ** tree. */ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ - Bitmask mask = 0; + Bitmask mask; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = sqlite3WhereGetMask(pMaskSet, p->iTable); return mask; } - mask = sqlite3WhereExprUsage(pMaskSet, p->pRight); + assert( !ExprHasProperty(p, EP_TokenOnly) ); + mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0; if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); if( ExprHasProperty(p, EP_xIsSelect) ){ mask |= exprSelectUsage(pMaskSet, p->x.pSelect); @@ -126691,13 +128880,13 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( pTab->zName, j); return; } - pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; pColRef->pTab = pTab; pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } @@ -126904,11 +129093,13 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ - while( pScan->iEquiv<=pScan->nEquiv ){ - iCur = pScan->aiCur[pScan->iEquiv-1]; + assert( pScan->iEquiv<=pScan->nEquiv ); + pWC = pScan->pWC; + while(1){ iColumn = pScan->aiColumn[pScan->iEquiv-1]; - if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; - while( (pWC = pScan->pWC)!=0 ){ + iCur = pScan->aiCur[pScan->iEquiv-1]; + assert( pWC!=0 ); + do{ for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn @@ -126958,15 +129149,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ testcase( pTerm->eOperator & WO_IS ); continue; } + pScan->pWC = pWC; pScan->k = k+1; return pTerm; } } } - pScan->pWC = pScan->pWC->pOuter; + pWC = pWC->pOuter; k = 0; - } - pScan->pWC = pScan->pOrigWC; + }while( pWC!=0 ); + if( pScan->iEquiv>=pScan->nEquiv ) break; + pWC = pScan->pOrigWC; k = 0; pScan->iEquiv++; } @@ -127000,24 +129193,24 @@ static WhereTerm *whereScanInit( u32 opMask, /* Operator(s) to scan for */ Index *pIdx /* Must be compatible with this index */ ){ - int j = 0; - - /* memset(pScan, 0, sizeof(*pScan)); */ pScan->pOrigWC = pWC; pScan->pWC = pWC; pScan->pIdxExpr = 0; + pScan->idxaff = 0; + pScan->zCollName = 0; if( pIdx ){ - j = iColumn; + int j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; - } - if( pIdx && iColumn>=0 ){ - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; - pScan->zCollName = pIdx->azColl[j]; - }else{ - pScan->idxaff = 0; - pScan->zCollName = 0; + if( iColumn==XN_EXPR ){ + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + }else if( iColumn==pIdx->pTable->iPKey ){ + iColumn = XN_ROWID; + }else if( iColumn>=0 ){ + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; + pScan->zCollName = pIdx->azColl[j]; + } + }else if( iColumn==XN_EXPR ){ + return 0; } pScan->opMask = opMask; pScan->k = 0; @@ -127357,7 +129550,7 @@ static void constructAutomaticIndex( ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); + addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ @@ -127532,7 +129725,8 @@ static sqlite3_index_info *allocateIndexInfo( WhereClause *pWC, Bitmask mUnusable, /* Ignore terms with these prereqs */ struct SrcList_item *pSrc, - ExprList *pOrderBy + ExprList *pOrderBy, + u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; int nTerm; @@ -127542,6 +129736,7 @@ static sqlite3_index_info *allocateIndexInfo( WhereTerm *pTerm; int nOrderBy; sqlite3_index_info *pIdxInfo; + u16 mNoOmit = 0; /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ @@ -127630,6 +129825,15 @@ static sqlite3_index_info *allocateIndexInfo( assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + + if( op & (WO_LT|WO_LE|WO_GT|WO_GE) + && sqlite3ExprIsVector(pTerm->pExpr->pRight) + ){ + if( i<16 ) mNoOmit |= (1 << i); + if( op==WO_LT ) pIdxCons[j].op = WO_LE; + if( op==WO_GT ) pIdxCons[j].op = WO_GE; + } + j++; } for(i=0; ia[i].sortOrder; } + *pmNoOmit = mNoOmit; return pIdxInfo; } @@ -127913,7 +130118,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ /* ** Return the affinity for a single column of an index. */ -static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ +SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ assert( iCol>=0 && iColnColumn ); if( !pIdx->zColAff ){ if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; @@ -128090,7 +130295,8 @@ static int whereRangeScanEst( if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; - u8 aff; + int nBtm = pLoop->u.btree.nBtm; + int nTop = pLoop->u.btree.nTop; /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The @@ -128120,8 +130326,6 @@ static int whereRangeScanEst( testcase( pRec->nField!=pBuilder->nRecValid ); pRec->nField = pBuilder->nRecValid; } - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq); - assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER ); /* Determine iLower and iUpper using ($P) only. */ if( nEq==0 ){ iLower = 0; @@ -128140,17 +130344,20 @@ static int whereRangeScanEst( if( p->aSortOrder[nEq] ){ /* The roles of pLower and pUpper are swapped for a DESC index */ SWAP(WhereTerm*, pLower, pUpper); + SWAP(int, nBtm, nTop); } /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ - int bOk; /* True if value is extracted from pExpr */ + int n; /* Values extracted from pExpr */ Expr *pExpr = pLower->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n); + if( rc==SQLITE_OK && n ){ tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); + iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; nOut--; pLower = 0; @@ -128159,13 +130366,15 @@ static int whereRangeScanEst( /* If possible, improve on the iUpper estimate using ($P:$U). */ if( pUpper ){ - int bOk; /* True if value is extracted from pExpr */ + int n; /* Values extracted from pExpr */ Expr *pExpr = pUpper->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n); + if( rc==SQLITE_OK && n ){ tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); + iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0); if( iNewpNew->u.btree.pIndex; int nEq = pBuilder->pNew->u.btree.nEq; UnpackedRecord *pRec = pBuilder->pRec; - u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ tRowcnt a[2]; /* Statistics */ int bOk; @@ -128279,8 +130487,7 @@ static int whereEqualScanEst( return SQLITE_OK; } - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1); - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk); pBuilder->pRec = pRec; if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; @@ -128369,9 +130576,14 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){ sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); } sqlite3DebugPrintf( - "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x\n", + "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x", iTerm, pTerm, zType, zLeft, pTerm->truthProb, pTerm->eOperator, pTerm->wtFlags); + if( pTerm->iField ){ + sqlite3DebugPrintf(" iField=%d\n", pTerm->iField); + }else{ + sqlite3DebugPrintf("\n"); + } sqlite3TreeViewExpr(0, pTerm->pExpr, 0); } } @@ -128893,6 +131105,72 @@ static void whereLoopOutputAdjust( if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; } +/* +** Term pTerm is a vector range comparison operation. The first comparison +** in the vector can be optimized using column nEq of the index. This +** function returns the total number of vector elements that can be used +** as part of the range comparison. +** +** For example, if the query is: +** +** WHERE a = ? AND (b, c, d) > (?, ?, ?) +** +** and the index: +** +** CREATE INDEX ... ON (a, b, c, d, e) +** +** then this function would be invoked with nEq=1. The value returned in +** this case is 3. +*/ +static int whereRangeVectorLen( + Parse *pParse, /* Parsing context */ + int iCur, /* Cursor open on pIdx */ + Index *pIdx, /* The index to be used for a inequality constraint */ + int nEq, /* Number of prior equality constraints on same index */ + WhereTerm *pTerm /* The vector inequality constraint */ +){ + int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); + int i; + + nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); + for(i=1; ipExpr->pLeft->x.pList->a[i].pExpr; + Expr *pRhs = pTerm->pExpr->pRight; + if( pRhs->flags & EP_xIsSelect ){ + pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; + }else{ + pRhs = pRhs->x.pList->a[i].pExpr; + } + + /* Check that the LHS of the comparison is a column reference to + ** the right column of the right source table. And that the sort + ** order of the index column is the same as the sort order of the + ** leftmost index column. */ + if( pLhs->op!=TK_COLUMN + || pLhs->iTable!=iCur + || pLhs->iColumn!=pIdx->aiColumn[i+nEq] + || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] + ){ + break; + } + + testcase( pLhs->iColumn==XN_ROWID ); + aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); + idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); + if( aff!=idxaff ) break; + + pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + if( pColl==0 ) break; + if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; + } + return i; +} + /* ** Adjust the cost C by the costMult facter T. This only occurs if ** compiled with -DSQLITE_ENABLE_COSTMULT @@ -128931,6 +131209,8 @@ static int whereLoopAddBtreeIndex( Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ + u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */ + u16 saved_nTop; /* Original value of pNew->u.btree.nTop */ u16 saved_nSkip; /* Original value of pNew->nSkip */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ LogEst saved_nOut; /* Original value of pNew->nOut */ @@ -128941,12 +131221,15 @@ static int whereLoopAddBtreeIndex( pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; + WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", + pProbe->zName, pNew->u.btree.nEq)); assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ + assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); @@ -128954,6 +131237,8 @@ static int whereLoopAddBtreeIndex( assert( pNew->u.btree.nEqnColumn ); saved_nEq = pNew->u.btree.nEq; + saved_nBtm = pNew->u.btree.nBtm; + saved_nTop = pNew->u.btree.nTop; saved_nSkip = pNew->nSkip; saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; @@ -128997,6 +131282,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nBtm = saved_nBtm; + pNew->u.btree.nTop = saved_nTop; pNew->nLTerm = saved_nLTerm; if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; @@ -129013,14 +131300,23 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; nIn = 46; assert( 46==sqlite3LogEst(25) ); + + /* The expression may actually be of the form (x, y) IN (SELECT...). + ** In this case there is a separate term for each of (x) and (y). + ** However, the nIn multiplier should only be applied once, not once + ** for each such term. The following loop checks that pTerm is the + ** first such term in use, and sets nIn back to 0 if it is not. */ + for(i=0; inLTerm-1; i++){ + if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; + } }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ } - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ - }else if( eOp & (WO_EQ|WO_IS) ){ int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; @@ -129040,6 +131336,9 @@ static int whereLoopAddBtreeIndex( testcase( eOp & WO_GT ); testcase( eOp & WO_GE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; + pNew->u.btree.nBtm = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); pBtm = pTerm; pTop = 0; if( pTerm->wtFlags & TERM_LIKEOPT ){ @@ -129052,12 +131351,16 @@ static int whereLoopAddBtreeIndex( if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTop; pNew->wsFlags |= WHERE_TOP_LIMIT; + pNew->u.btree.nTop = 1; } }else{ assert( eOp & (WO_LT|WO_LE) ); testcase( eOp & WO_LT ); testcase( eOp & WO_LE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; + pNew->u.btree.nTop = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); pTop = pTerm; pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? pNew->aLTerm[pNew->nLTerm-2] : 0; @@ -129157,6 +131460,8 @@ static int whereLoopAddBtreeIndex( } pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nBtm = saved_nBtm; + pNew->u.btree.nTop = saved_nTop; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; pNew->nOut = saved_nOut; @@ -129196,6 +131501,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; } + WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->zName, saved_nEq, rc)); return rc; } @@ -129278,7 +131585,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ /* ** Add all WhereLoop objects for a single table of the join where the table -** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be +** is identified by pBuilder->pNew->iTab. That table is guaranteed to be ** a b-tree table, not a virtual table. ** ** The costs (WhereLoop.rRun) of the b-tree loops added by this function @@ -129432,6 +131739,8 @@ static int whereLoopAddBtree( } rSize = pProbe->aiRowLogEst[0]; pNew->u.btree.nEq = 0; + pNew->u.btree.nBtm = 0; + pNew->u.btree.nTop = 0; pNew->nSkip = 0; pNew->nLTerm = 0; pNew->iSortIdx = 0; @@ -129560,6 +131869,7 @@ static int whereLoopAddVirtualOne( Bitmask mUsable, /* Mask of usable tables */ u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ + u16 mNoOmit, /* Do not omit these constraints */ int *pbIn /* OUT: True if plan uses an IN(...) op */ ){ WhereClause *pWC = pBuilder->pWC; @@ -129648,6 +131958,7 @@ static int whereLoopAddVirtualOne( } } } + pNew->u.vtab.omitMask &= ~mNoOmit; pNew->nLTerm = mxTerm+1; assert( pNew->nLTerm<=pNew->nLSlot ); @@ -129721,6 +132032,7 @@ static int whereLoopAddVirtual( int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ + u16 mNoOmit; assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; @@ -129729,7 +132041,8 @@ static int whereLoopAddVirtual( pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); - p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, + &mNoOmit); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; @@ -129743,7 +132056,7 @@ static int whereLoopAddVirtual( /* First call xBestIndex() with all constraints usable. */ WHERETRACE(0x40, (" VirtualOne: all usable\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0), @@ -129760,7 +132073,8 @@ static int whereLoopAddVirtual( ** xBestIndex again, this time with IN(...) terms disabled. */ if( bIn ){ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ @@ -129786,7 +132100,8 @@ static int whereLoopAddVirtual( if( mNext==mBest || mNext==mBestNoIn ) continue; WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn); if( pNew->prereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; @@ -129798,7 +132113,8 @@ static int whereLoopAddVirtual( ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); if( bIn==0 ) seenZeroNoIN = 1; } @@ -129807,7 +132123,8 @@ static int whereLoopAddVirtual( ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); } } @@ -130107,6 +132424,14 @@ static i8 wherePathSatisfiesOrderBy( pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, ~ready, eqOpMask, 0); if( pTerm==0 ) continue; + if( pTerm->eOperator==WO_IN ){ + /* IN terms are only valid for sorting in the ORDER BY LIMIT + ** optimization, and then only if they are actually used + ** by the query plan */ + assert( wctrlFlags & WHERE_ORDERBY_LIMIT ); + for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){} + if( j>=pLoop->nLTerm ) continue; + } if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ const char *z1, *z2; pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); @@ -130143,20 +132468,42 @@ static i8 wherePathSatisfiesOrderBy( rev = revSet = 0; distinctColumns = 0; for(j=0; ju.btree.nEq - && pLoop->nSkip==0 - && ((i = pLoop->aLTerm[j]->eOperator) & eqOpMask)!=0 - ){ - if( i & WO_ISNULL ){ - testcase( isOrderDistinct ); - isOrderDistinct = 0; + assert( j>=pLoop->u.btree.nEq + || (pLoop->aLTerm[j]==0)==(jnSkip) + ); + if( ju.btree.nEq && j>=pLoop->nSkip ){ + u16 eOp = pLoop->aLTerm[j]->eOperator; + + /* Skip over == and IS and ISNULL terms. (Also skip IN terms when + ** doing WHERE_ORDERBY_LIMIT processing). + ** + ** If the current term is a column of an ((?,?) IN (SELECT...)) + ** expression for which the SELECT returns more than one column, + ** check that it is the only column used by this loop. Otherwise, + ** if it is one of two or more, none of the columns can be + ** considered to match an ORDER BY term. */ + if( (eOp & eqOpMask)!=0 ){ + if( eOp & WO_ISNULL ){ + testcase( isOrderDistinct ); + isOrderDistinct = 0; + } + continue; + }else if( ALWAYS(eOp & WO_IN) ){ + /* ALWAYS() justification: eOp is an equality operator due to the + ** ju.btree.nEq constraint above. Any equality other + ** than WO_IN is captured by the previous "if". So this one + ** always has to be WO_IN. */ + Expr *pX = pLoop->aLTerm[j]->pExpr; + for(i=j+1; iu.btree.nEq; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + assert( (pLoop->aLTerm[i]->eOperator & WO_IN) ); + bOnce = 0; + break; + } + } } - continue; } /* Get the column number in the table (iColumn) and sort order @@ -130185,7 +132532,6 @@ static i8 wherePathSatisfiesOrderBy( /* Find the ORDER BY term that corresponds to the j-th column ** of the index and mark that ORDER BY term off */ - bOnce = 1; isMatch = 0; for(i=0; bOnce && irevMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ pWInfo->nOBSat = 0; - if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){ - Bitmask m = 0; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, + if( nLoop>0 ){ + u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; + if( (wsFlags & WHERE_ONEROW)==0 + && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) + ){ + Bitmask m = 0; + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); - if( rc==pWInfo->pOrderBy->nExpr ){ - pWInfo->bOrderedInnerLoop = 1; - pWInfo->revMask = m; + testcase( wsFlags & WHERE_IPK ); + testcase( wsFlags & WHERE_COLUMN_IN ); + if( rc==pWInfo->pOrderBy->nExpr ){ + pWInfo->bOrderedInnerLoop = 1; + pWInfo->revMask = m; + } } } } @@ -130960,22 +133313,25 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** some architectures. Hence the ROUND8() below. */ nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); - pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); + pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } - pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; - pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; pWInfo->pDistinctSet = pDistinctSet; + pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; + pWInfo->nLevel = nTabList; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; + memset(&pWInfo->nOBSat, 0, + offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); + memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; @@ -131379,10 +133735,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); - VdbeCoverage(v); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); + if( pIn->eEndLoopOp!=OP_Noop ){ + sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); + } sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } } @@ -131401,13 +133759,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #endif if( pLevel->iLeftJoin ){ + int ws = pLoop->wsFlags; addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ + assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); + if( (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); } - if( pLoop->wsFlags & WHERE_INDEXED ){ + if( (ws & WHERE_INDEXED) + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) + ){ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ @@ -131446,27 +133806,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ continue; } - /* Close all of the cursors that were opened by sqlite3WhereBegin. - ** Except, do not close cursors that will be reused by the OR optimization - ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors - ** created for the ONEPASS optimization. - */ - if( (pTab->tabFlags & TF_Ephemeral)==0 - && pTab->pSelect==0 - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - ){ - int ws = pLoop->wsFlags; - if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); - } - if( (ws & WHERE_INDEXED)!=0 - && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 - && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1] - ){ - sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); - } - } - /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can @@ -131584,15 +133923,6 @@ struct LimitVal { Expr *pOffset; /* The OFFSET expression. NULL if there is none */ }; -/* -** An instance of this structure is used to store the LIKE, -** GLOB, NOT LIKE, and NOT GLOB operators. -*/ -struct LikeOp { - Token eOperator; /* "like" or "glob" or "regexp" */ - int bNot; /* True if the NOT keyword is present */ -}; - /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, @@ -131604,11 +133934,6 @@ struct LikeOp { */ struct TrigEvent { int a; IdList * b; }; -/* -** An instance of this structure holds the ATTACH key and the key type. -*/ -struct AttachKey { int type; Token key; }; - /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. @@ -131655,7 +133980,24 @@ static void disableLookaside(Parse *pParse){ ** that created the expression. */ static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ - pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t); + Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); + if( p ){ + memset(p, 0, sizeof(Expr)); + p->op = (u8)op; + p->flags = EP_Leaf; + p->iAgg = -1; + p->u.zToken = (char*)&p[1]; + memcpy(p->u.zToken, t.z, t.n); + p->u.zToken[t.n] = 0; + if( sqlite3Isquote(p->u.zToken[0]) ){ + if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; + sqlite3Dequote(p->u.zToken); + } +#if SQLITE_MAX_EXPR_DEPTH>0 + p->nHeight = 1; +#endif + } + pOut->pExpr = p; pOut->zStart = t.z; pOut->zEnd = &t.z[t.n]; } @@ -131669,7 +134011,7 @@ static void disableLookaside(Parse *pParse){ ExprSpan *pLeft, /* The left operand, and output */ ExprSpan *pRight /* The right operand */ ){ - pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); + pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); pLeft->zEnd = pRight->zEnd; } @@ -131678,7 +134020,7 @@ static void disableLookaside(Parse *pParse){ */ static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ if( doNot ){ - pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0, 0); + pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); } } @@ -131690,7 +134032,7 @@ static void disableLookaside(Parse *pParse){ ExprSpan *pOperand, /* The operand, and output */ Token *pPostOp /* The operand token for setting the span */ ){ - pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); pOperand->zEnd = &pPostOp->z[pPostOp->n]; } @@ -131715,7 +134057,7 @@ static void disableLookaside(Parse *pParse){ Token *pPreOp /* The operand token for setting the span */ ){ pOut->zStart = pPreOp->z; - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); pOut->zEnd = pOperand->zEnd; } @@ -131818,7 +134160,6 @@ typedef union { With* yy285; struct TrigEvent yy332; struct LimitVal yy354; - struct LikeOp yy392; struct {int value; int mask;} yy497; } YYMINORTYPE; #ifndef YYSTACKDEPTH @@ -131829,16 +134170,16 @@ typedef union { #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYFALLBACK 1 -#define YYNSTATE 443 -#define YYNRULE 328 -#define YY_MAX_SHIFT 442 -#define YY_MIN_SHIFTREDUCE 653 -#define YY_MAX_SHIFTREDUCE 980 -#define YY_MIN_REDUCE 981 -#define YY_MAX_REDUCE 1308 -#define YY_ERROR_ACTION 1309 -#define YY_ACCEPT_ACTION 1310 -#define YY_NO_ACTION 1311 +#define YYNSTATE 456 +#define YYNRULE 332 +#define YY_MAX_SHIFT 455 +#define YY_MIN_SHIFTREDUCE 668 +#define YY_MAX_SHIFTREDUCE 999 +#define YY_MIN_REDUCE 1000 +#define YY_MAX_REDUCE 1331 +#define YY_ERROR_ACTION 1332 +#define YY_ACCEPT_ACTION 1333 +#define YY_NO_ACTION 1334 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -131870,7 +134211,7 @@ typedef union { ** ** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE ** and YY_MAX_REDUCE - +** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. @@ -131879,16 +134220,20 @@ typedef union { ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as +** Given state S and lookahead X, the action is computed as either: ** -** yy_action[ yy_shift_ofst[S] + X ] +** (A) N = yy_action[ yy_shift_ofst[S] + X ] +** (B) N = yy_default[S] ** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** -** The formula above is for computing the action when the lookahead is +** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of @@ -131906,159 +134251,165 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (1507) +#define YY_ACTTAB_COUNT (1567) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 317, 814, 341, 808, 5, 195, 195, 802, 93, 94, - /* 10 */ 84, 823, 823, 835, 838, 827, 827, 91, 91, 92, - /* 20 */ 92, 92, 92, 293, 90, 90, 90, 90, 89, 89, - /* 30 */ 88, 88, 88, 87, 341, 317, 958, 958, 807, 807, - /* 40 */ 807, 928, 344, 93, 94, 84, 823, 823, 835, 838, - /* 50 */ 827, 827, 91, 91, 92, 92, 92, 92, 328, 90, - /* 60 */ 90, 90, 90, 89, 89, 88, 88, 88, 87, 341, - /* 70 */ 89, 89, 88, 88, 88, 87, 341, 776, 958, 958, - /* 80 */ 317, 88, 88, 88, 87, 341, 777, 69, 93, 94, - /* 90 */ 84, 823, 823, 835, 838, 827, 827, 91, 91, 92, - /* 100 */ 92, 92, 92, 437, 90, 90, 90, 90, 89, 89, - /* 110 */ 88, 88, 88, 87, 341, 1310, 147, 147, 2, 317, - /* 120 */ 76, 25, 74, 49, 49, 87, 341, 93, 94, 84, - /* 130 */ 823, 823, 835, 838, 827, 827, 91, 91, 92, 92, - /* 140 */ 92, 92, 95, 90, 90, 90, 90, 89, 89, 88, - /* 150 */ 88, 88, 87, 341, 939, 939, 317, 260, 415, 400, - /* 160 */ 398, 58, 737, 737, 93, 94, 84, 823, 823, 835, - /* 170 */ 838, 827, 827, 91, 91, 92, 92, 92, 92, 57, - /* 180 */ 90, 90, 90, 90, 89, 89, 88, 88, 88, 87, - /* 190 */ 341, 317, 1253, 928, 344, 269, 940, 941, 242, 93, - /* 200 */ 94, 84, 823, 823, 835, 838, 827, 827, 91, 91, - /* 210 */ 92, 92, 92, 92, 293, 90, 90, 90, 90, 89, - /* 220 */ 89, 88, 88, 88, 87, 341, 317, 919, 1303, 793, - /* 230 */ 691, 1303, 724, 724, 93, 94, 84, 823, 823, 835, - /* 240 */ 838, 827, 827, 91, 91, 92, 92, 92, 92, 337, - /* 250 */ 90, 90, 90, 90, 89, 89, 88, 88, 88, 87, - /* 260 */ 341, 317, 114, 919, 1304, 684, 395, 1304, 124, 93, - /* 270 */ 94, 84, 823, 823, 835, 838, 827, 827, 91, 91, - /* 280 */ 92, 92, 92, 92, 683, 90, 90, 90, 90, 89, - /* 290 */ 89, 88, 88, 88, 87, 341, 317, 86, 83, 169, - /* 300 */ 801, 917, 234, 399, 93, 94, 84, 823, 823, 835, - /* 310 */ 838, 827, 827, 91, 91, 92, 92, 92, 92, 686, - /* 320 */ 90, 90, 90, 90, 89, 89, 88, 88, 88, 87, - /* 330 */ 341, 317, 436, 742, 86, 83, 169, 917, 741, 93, - /* 340 */ 94, 84, 823, 823, 835, 838, 827, 827, 91, 91, - /* 350 */ 92, 92, 92, 92, 902, 90, 90, 90, 90, 89, - /* 360 */ 89, 88, 88, 88, 87, 341, 317, 321, 434, 434, - /* 370 */ 434, 1, 722, 722, 93, 94, 84, 823, 823, 835, - /* 380 */ 838, 827, 827, 91, 91, 92, 92, 92, 92, 190, - /* 390 */ 90, 90, 90, 90, 89, 89, 88, 88, 88, 87, - /* 400 */ 341, 317, 685, 292, 939, 939, 150, 977, 310, 93, - /* 410 */ 94, 84, 823, 823, 835, 838, 827, 827, 91, 91, - /* 420 */ 92, 92, 92, 92, 437, 90, 90, 90, 90, 89, - /* 430 */ 89, 88, 88, 88, 87, 341, 926, 2, 372, 719, - /* 440 */ 698, 369, 950, 317, 49, 49, 940, 941, 719, 177, - /* 450 */ 72, 93, 94, 84, 823, 823, 835, 838, 827, 827, - /* 460 */ 91, 91, 92, 92, 92, 92, 322, 90, 90, 90, - /* 470 */ 90, 89, 89, 88, 88, 88, 87, 341, 317, 415, - /* 480 */ 405, 824, 824, 836, 839, 75, 93, 82, 84, 823, - /* 490 */ 823, 835, 838, 827, 827, 91, 91, 92, 92, 92, - /* 500 */ 92, 430, 90, 90, 90, 90, 89, 89, 88, 88, - /* 510 */ 88, 87, 341, 317, 340, 340, 340, 658, 659, 660, - /* 520 */ 333, 288, 94, 84, 823, 823, 835, 838, 827, 827, - /* 530 */ 91, 91, 92, 92, 92, 92, 437, 90, 90, 90, - /* 540 */ 90, 89, 89, 88, 88, 88, 87, 341, 317, 882, - /* 550 */ 882, 375, 828, 66, 330, 409, 49, 49, 84, 823, - /* 560 */ 823, 835, 838, 827, 827, 91, 91, 92, 92, 92, - /* 570 */ 92, 351, 90, 90, 90, 90, 89, 89, 88, 88, - /* 580 */ 88, 87, 341, 80, 432, 742, 3, 1180, 351, 350, - /* 590 */ 741, 334, 796, 939, 939, 761, 80, 432, 278, 3, - /* 600 */ 204, 161, 279, 393, 274, 392, 191, 362, 437, 277, - /* 610 */ 745, 77, 78, 272, 800, 254, 355, 243, 79, 342, - /* 620 */ 342, 86, 83, 169, 77, 78, 234, 399, 49, 49, - /* 630 */ 435, 79, 342, 342, 437, 940, 941, 186, 442, 655, - /* 640 */ 390, 387, 386, 435, 235, 213, 108, 421, 761, 351, - /* 650 */ 437, 385, 167, 732, 10, 10, 124, 124, 671, 814, - /* 660 */ 421, 439, 438, 415, 414, 802, 362, 168, 327, 124, - /* 670 */ 49, 49, 814, 219, 439, 438, 800, 186, 802, 326, - /* 680 */ 390, 387, 386, 437, 1248, 1248, 23, 939, 939, 80, - /* 690 */ 432, 385, 3, 761, 416, 876, 807, 807, 807, 809, - /* 700 */ 19, 290, 149, 49, 49, 415, 396, 260, 910, 807, - /* 710 */ 807, 807, 809, 19, 312, 237, 145, 77, 78, 746, - /* 720 */ 168, 702, 437, 149, 79, 342, 342, 114, 358, 940, - /* 730 */ 941, 302, 223, 397, 345, 313, 435, 260, 415, 417, - /* 740 */ 858, 374, 31, 31, 80, 432, 761, 3, 348, 92, - /* 750 */ 92, 92, 92, 421, 90, 90, 90, 90, 89, 89, - /* 760 */ 88, 88, 88, 87, 341, 814, 114, 439, 438, 796, - /* 770 */ 367, 802, 77, 78, 701, 796, 124, 1187, 220, 79, - /* 780 */ 342, 342, 124, 747, 734, 939, 939, 775, 404, 939, - /* 790 */ 939, 435, 254, 360, 253, 402, 895, 346, 254, 360, - /* 800 */ 253, 774, 807, 807, 807, 809, 19, 800, 421, 90, - /* 810 */ 90, 90, 90, 89, 89, 88, 88, 88, 87, 341, - /* 820 */ 814, 114, 439, 438, 939, 939, 802, 940, 941, 114, - /* 830 */ 437, 940, 941, 86, 83, 169, 192, 166, 309, 979, - /* 840 */ 70, 432, 700, 3, 382, 870, 238, 86, 83, 169, - /* 850 */ 10, 10, 361, 406, 763, 190, 222, 807, 807, 807, - /* 860 */ 809, 19, 870, 872, 329, 24, 940, 941, 77, 78, - /* 870 */ 359, 437, 335, 260, 218, 79, 342, 342, 437, 307, - /* 880 */ 306, 305, 207, 303, 339, 338, 668, 435, 339, 338, - /* 890 */ 407, 10, 10, 762, 216, 216, 939, 939, 49, 49, - /* 900 */ 437, 260, 97, 241, 421, 225, 402, 189, 188, 187, - /* 910 */ 309, 918, 980, 149, 221, 898, 814, 868, 439, 438, - /* 920 */ 10, 10, 802, 870, 915, 316, 898, 163, 162, 171, - /* 930 */ 249, 240, 322, 410, 412, 687, 687, 272, 940, 941, - /* 940 */ 239, 965, 901, 437, 226, 403, 226, 437, 963, 367, - /* 950 */ 964, 173, 248, 807, 807, 807, 809, 19, 174, 367, - /* 960 */ 899, 124, 172, 48, 48, 9, 9, 35, 35, 966, - /* 970 */ 966, 899, 363, 966, 966, 814, 900, 808, 725, 939, - /* 980 */ 939, 802, 895, 318, 980, 324, 125, 900, 726, 420, - /* 990 */ 92, 92, 92, 92, 85, 90, 90, 90, 90, 89, - /* 1000 */ 89, 88, 88, 88, 87, 341, 216, 216, 437, 946, - /* 1010 */ 349, 292, 807, 807, 807, 114, 291, 693, 402, 705, - /* 1020 */ 890, 940, 941, 437, 245, 889, 247, 437, 36, 36, - /* 1030 */ 437, 353, 391, 437, 260, 252, 260, 437, 361, 437, - /* 1040 */ 706, 437, 370, 12, 12, 224, 437, 27, 27, 437, - /* 1050 */ 37, 37, 437, 38, 38, 752, 368, 39, 39, 28, - /* 1060 */ 28, 29, 29, 215, 166, 331, 40, 40, 437, 41, - /* 1070 */ 41, 437, 42, 42, 437, 866, 246, 731, 437, 879, - /* 1080 */ 437, 256, 437, 878, 437, 267, 437, 261, 11, 11, - /* 1090 */ 437, 43, 43, 437, 99, 99, 437, 373, 44, 44, - /* 1100 */ 45, 45, 32, 32, 46, 46, 47, 47, 437, 426, - /* 1110 */ 33, 33, 776, 116, 116, 437, 117, 117, 437, 124, - /* 1120 */ 437, 777, 437, 260, 437, 957, 437, 352, 118, 118, - /* 1130 */ 437, 195, 437, 111, 437, 53, 53, 264, 34, 34, - /* 1140 */ 100, 100, 50, 50, 101, 101, 102, 102, 437, 260, - /* 1150 */ 98, 98, 115, 115, 113, 113, 437, 262, 437, 265, - /* 1160 */ 437, 943, 958, 437, 727, 437, 681, 437, 106, 106, - /* 1170 */ 68, 437, 893, 730, 437, 365, 105, 105, 103, 103, - /* 1180 */ 104, 104, 217, 52, 52, 54, 54, 51, 51, 694, - /* 1190 */ 259, 26, 26, 266, 30, 30, 677, 323, 433, 323, - /* 1200 */ 674, 423, 427, 943, 958, 114, 114, 431, 681, 865, - /* 1210 */ 1277, 233, 366, 714, 112, 20, 154, 704, 703, 810, - /* 1220 */ 914, 55, 159, 311, 798, 255, 383, 194, 68, 200, - /* 1230 */ 21, 694, 268, 114, 114, 114, 270, 711, 712, 68, - /* 1240 */ 114, 739, 770, 715, 71, 194, 861, 875, 875, 200, - /* 1250 */ 696, 865, 874, 874, 679, 699, 273, 110, 229, 419, - /* 1260 */ 768, 810, 799, 378, 748, 759, 418, 210, 294, 281, - /* 1270 */ 295, 806, 283, 682, 676, 665, 664, 666, 933, 151, - /* 1280 */ 285, 7, 1267, 308, 251, 790, 354, 244, 892, 364, - /* 1290 */ 287, 422, 300, 164, 160, 936, 974, 127, 197, 137, - /* 1300 */ 909, 907, 971, 388, 276, 863, 862, 56, 698, 325, - /* 1310 */ 148, 59, 122, 66, 356, 381, 357, 176, 152, 62, - /* 1320 */ 371, 130, 877, 181, 377, 760, 211, 182, 132, 133, - /* 1330 */ 134, 135, 258, 146, 140, 795, 787, 263, 183, 379, - /* 1340 */ 667, 394, 184, 332, 894, 314, 718, 717, 857, 716, - /* 1350 */ 696, 315, 709, 690, 65, 196, 6, 408, 289, 708, - /* 1360 */ 275, 689, 688, 948, 756, 757, 280, 282, 425, 755, - /* 1370 */ 284, 336, 73, 67, 754, 429, 411, 96, 286, 413, - /* 1380 */ 205, 934, 673, 22, 209, 440, 119, 120, 109, 206, - /* 1390 */ 208, 441, 662, 661, 656, 843, 654, 343, 158, 236, - /* 1400 */ 170, 347, 107, 227, 121, 738, 873, 298, 296, 297, - /* 1410 */ 299, 871, 794, 128, 129, 728, 230, 131, 175, 250, - /* 1420 */ 888, 136, 138, 231, 232, 139, 60, 61, 891, 178, - /* 1430 */ 179, 887, 8, 13, 180, 257, 880, 968, 194, 141, - /* 1440 */ 142, 376, 153, 670, 380, 185, 143, 277, 63, 384, - /* 1450 */ 14, 707, 271, 15, 389, 64, 319, 320, 126, 228, - /* 1460 */ 813, 812, 841, 736, 123, 16, 401, 740, 4, 769, - /* 1470 */ 165, 212, 214, 193, 144, 764, 71, 68, 17, 18, - /* 1480 */ 856, 842, 840, 897, 845, 896, 199, 198, 923, 155, - /* 1490 */ 424, 929, 924, 156, 201, 202, 428, 844, 157, 203, - /* 1500 */ 811, 680, 81, 1269, 1268, 301, 304, + /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, + /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, + /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, + /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, + /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, + /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, + /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, + /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, + /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, + /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, + /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, + /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, + /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, + /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, + /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, + /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, + /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, + /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, + /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, + /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, + /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, + /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, + /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, + /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, + /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, + /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, + /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, + /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, + /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, + /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, + /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, + /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, + /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, + /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, + /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, + /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, + /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, + /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, + /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, + /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, + /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, + /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, + /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, + /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, + /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, + /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, + /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, + /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, + /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, + /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, + /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, + /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, + /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, + /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, + /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, + /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, + /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, + /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, + /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, + /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, + /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, + /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, + /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, + /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, + /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, + /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, + /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, + /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, + /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, + /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, + /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, + /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, + /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, + /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, + /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, + /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, + /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, + /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, + /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, + /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, + /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, + /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, + /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, + /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, + /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, + /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, + /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, + /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, + /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, + /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, + /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, + /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, + /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, + /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, + /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, + /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, + /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, + /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, + /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, + /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, + /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, + /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, + /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, + /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, + /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, + /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, + /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, + /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, + /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, + /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, + /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, + /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, + /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, + /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, + /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, + /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, + /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, + /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, + /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, + /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, + /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, + /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, + /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, + /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, + /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, + /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, + /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, + /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, + /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, + /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, + /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, + /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, + /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, + /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, + /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, + /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, + /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, + /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, + /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, + /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, + /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, + /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, + /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, + /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, + /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, + /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, + /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, + /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, + /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, + /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, + /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, @@ -132073,281 +134424,290 @@ static const YYCODETYPE yy_lookahead[] = { /* 90 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, /* 110 */ 49, 50, 51, 52, 53, 144, 145, 146, 147, 19, - /* 120 */ 137, 22, 139, 172, 173, 52, 53, 27, 28, 29, + /* 120 */ 16, 22, 92, 172, 173, 52, 53, 27, 28, 29, /* 130 */ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, /* 140 */ 40, 41, 81, 43, 44, 45, 46, 47, 48, 49, /* 150 */ 50, 51, 52, 53, 55, 56, 19, 152, 207, 208, /* 160 */ 115, 24, 117, 118, 27, 28, 29, 30, 31, 32, /* 170 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 79, /* 180 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 190 */ 53, 19, 0, 1, 2, 23, 97, 98, 193, 27, + /* 190 */ 53, 19, 88, 157, 90, 23, 97, 98, 193, 27, /* 200 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, /* 210 */ 38, 39, 40, 41, 152, 43, 44, 45, 46, 47, - /* 220 */ 48, 49, 50, 51, 52, 53, 19, 22, 23, 163, - /* 230 */ 23, 26, 190, 191, 27, 28, 29, 30, 31, 32, + /* 220 */ 48, 49, 50, 51, 52, 53, 19, 22, 23, 172, + /* 230 */ 23, 26, 119, 120, 27, 28, 29, 30, 31, 32, /* 240 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 187, /* 250 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 260 */ 53, 19, 196, 22, 23, 23, 49, 26, 92, 27, + /* 260 */ 53, 19, 22, 23, 228, 23, 26, 231, 152, 27, /* 270 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, /* 280 */ 38, 39, 40, 41, 172, 43, 44, 45, 46, 47, /* 290 */ 48, 49, 50, 51, 52, 53, 19, 221, 222, 223, - /* 300 */ 23, 96, 119, 120, 27, 28, 29, 30, 31, 32, - /* 310 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 172, + /* 300 */ 23, 96, 152, 172, 27, 28, 29, 30, 31, 32, + /* 310 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 152, /* 320 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 330 */ 53, 19, 152, 116, 221, 222, 223, 96, 121, 27, + /* 330 */ 53, 19, 0, 1, 2, 23, 96, 190, 191, 27, /* 340 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - /* 350 */ 38, 39, 40, 41, 241, 43, 44, 45, 46, 47, - /* 360 */ 48, 49, 50, 51, 52, 53, 19, 157, 168, 169, - /* 370 */ 170, 22, 190, 191, 27, 28, 29, 30, 31, 32, - /* 380 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 30, + /* 350 */ 38, 39, 40, 41, 238, 43, 44, 45, 46, 47, + /* 360 */ 48, 49, 50, 51, 52, 53, 19, 185, 218, 221, + /* 370 */ 222, 223, 152, 152, 27, 28, 29, 30, 31, 32, + /* 380 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 241, /* 390 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 400 */ 53, 19, 172, 152, 55, 56, 24, 247, 248, 27, + /* 400 */ 53, 19, 152, 168, 169, 170, 22, 190, 191, 27, /* 410 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, /* 420 */ 38, 39, 40, 41, 152, 43, 44, 45, 46, 47, - /* 430 */ 48, 49, 50, 51, 52, 53, 146, 147, 228, 179, - /* 440 */ 180, 231, 185, 19, 172, 173, 97, 98, 188, 26, - /* 450 */ 138, 27, 28, 29, 30, 31, 32, 33, 34, 35, - /* 460 */ 36, 37, 38, 39, 40, 41, 107, 43, 44, 45, - /* 470 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 207, - /* 480 */ 208, 30, 31, 32, 33, 138, 27, 28, 29, 30, + /* 430 */ 48, 49, 50, 51, 52, 53, 19, 19, 218, 55, + /* 440 */ 56, 24, 22, 152, 27, 28, 29, 30, 31, 32, + /* 450 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 152, + /* 460 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 470 */ 53, 250, 194, 195, 56, 55, 56, 55, 19, 172, + /* 480 */ 173, 97, 98, 152, 206, 138, 27, 28, 29, 30, /* 490 */ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - /* 500 */ 41, 250, 43, 44, 45, 46, 47, 48, 49, 50, - /* 510 */ 51, 52, 53, 19, 168, 169, 170, 7, 8, 9, - /* 520 */ 19, 152, 28, 29, 30, 31, 32, 33, 34, 35, - /* 530 */ 36, 37, 38, 39, 40, 41, 152, 43, 44, 45, - /* 540 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 108, - /* 550 */ 109, 110, 101, 130, 53, 152, 172, 173, 29, 30, + /* 500 */ 41, 152, 43, 44, 45, 46, 47, 48, 49, 50, + /* 510 */ 51, 52, 53, 19, 207, 208, 152, 97, 98, 97, + /* 520 */ 138, 27, 28, 29, 30, 31, 32, 33, 34, 35, + /* 530 */ 36, 37, 38, 39, 40, 41, 181, 43, 44, 45, + /* 540 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 30, + /* 550 */ 31, 32, 33, 247, 248, 19, 152, 28, 29, 30, /* 560 */ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 570 */ 41, 152, 43, 44, 45, 46, 47, 48, 49, 50, - /* 580 */ 51, 52, 53, 19, 20, 116, 22, 23, 169, 170, - /* 590 */ 121, 207, 85, 55, 56, 26, 19, 20, 101, 22, - /* 600 */ 99, 100, 101, 102, 103, 104, 105, 152, 152, 112, - /* 610 */ 210, 47, 48, 112, 152, 108, 109, 110, 54, 55, - /* 620 */ 56, 221, 222, 223, 47, 48, 119, 120, 172, 173, - /* 630 */ 66, 54, 55, 56, 152, 97, 98, 99, 148, 149, - /* 640 */ 102, 103, 104, 66, 154, 23, 156, 83, 26, 230, - /* 650 */ 152, 113, 152, 163, 172, 173, 92, 92, 21, 95, - /* 660 */ 83, 97, 98, 207, 208, 101, 152, 98, 186, 92, - /* 670 */ 172, 173, 95, 218, 97, 98, 152, 99, 101, 217, - /* 680 */ 102, 103, 104, 152, 119, 120, 196, 55, 56, 19, - /* 690 */ 20, 113, 22, 124, 163, 11, 132, 133, 134, 135, - /* 700 */ 136, 152, 152, 172, 173, 207, 208, 152, 152, 132, - /* 710 */ 133, 134, 135, 136, 164, 152, 84, 47, 48, 49, - /* 720 */ 98, 181, 152, 152, 54, 55, 56, 196, 91, 97, - /* 730 */ 98, 160, 218, 163, 244, 164, 66, 152, 207, 208, - /* 740 */ 103, 217, 172, 173, 19, 20, 124, 22, 193, 38, - /* 750 */ 39, 40, 41, 83, 43, 44, 45, 46, 47, 48, - /* 760 */ 49, 50, 51, 52, 53, 95, 196, 97, 98, 85, - /* 770 */ 152, 101, 47, 48, 181, 85, 92, 140, 193, 54, - /* 780 */ 55, 56, 92, 49, 195, 55, 56, 175, 163, 55, - /* 790 */ 56, 66, 108, 109, 110, 206, 163, 242, 108, 109, - /* 800 */ 110, 175, 132, 133, 134, 135, 136, 152, 83, 43, - /* 810 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 820 */ 95, 196, 97, 98, 55, 56, 101, 97, 98, 196, - /* 830 */ 152, 97, 98, 221, 222, 223, 211, 212, 22, 23, - /* 840 */ 19, 20, 181, 22, 19, 152, 152, 221, 222, 223, - /* 850 */ 172, 173, 219, 19, 124, 30, 238, 132, 133, 134, - /* 860 */ 135, 136, 169, 170, 186, 232, 97, 98, 47, 48, - /* 870 */ 237, 152, 217, 152, 5, 54, 55, 56, 152, 10, - /* 880 */ 11, 12, 13, 14, 47, 48, 17, 66, 47, 48, - /* 890 */ 56, 172, 173, 124, 194, 195, 55, 56, 172, 173, - /* 900 */ 152, 152, 22, 152, 83, 186, 206, 108, 109, 110, - /* 910 */ 22, 23, 96, 152, 193, 12, 95, 152, 97, 98, - /* 920 */ 172, 173, 101, 230, 152, 164, 12, 47, 48, 60, - /* 930 */ 152, 62, 107, 207, 186, 55, 56, 112, 97, 98, - /* 940 */ 71, 100, 193, 152, 183, 152, 185, 152, 107, 152, - /* 950 */ 109, 82, 16, 132, 133, 134, 135, 136, 89, 152, - /* 960 */ 57, 92, 93, 172, 173, 172, 173, 172, 173, 132, - /* 970 */ 133, 57, 152, 132, 133, 95, 73, 97, 75, 55, - /* 980 */ 56, 101, 163, 114, 96, 245, 246, 73, 85, 75, - /* 990 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - /* 1000 */ 48, 49, 50, 51, 52, 53, 194, 195, 152, 171, - /* 1010 */ 141, 152, 132, 133, 134, 196, 225, 179, 206, 65, - /* 1020 */ 152, 97, 98, 152, 88, 152, 90, 152, 172, 173, - /* 1030 */ 152, 219, 78, 152, 152, 238, 152, 152, 219, 152, - /* 1040 */ 86, 152, 152, 172, 173, 238, 152, 172, 173, 152, - /* 1050 */ 172, 173, 152, 172, 173, 213, 237, 172, 173, 172, - /* 1060 */ 173, 172, 173, 211, 212, 111, 172, 173, 152, 172, - /* 1070 */ 173, 152, 172, 173, 152, 193, 140, 193, 152, 59, - /* 1080 */ 152, 152, 152, 63, 152, 16, 152, 152, 172, 173, - /* 1090 */ 152, 172, 173, 152, 172, 173, 152, 77, 172, 173, - /* 1100 */ 172, 173, 172, 173, 172, 173, 172, 173, 152, 250, - /* 1110 */ 172, 173, 61, 172, 173, 152, 172, 173, 152, 92, - /* 1120 */ 152, 70, 152, 152, 152, 26, 152, 100, 172, 173, - /* 1130 */ 152, 24, 152, 22, 152, 172, 173, 152, 172, 173, - /* 1140 */ 172, 173, 172, 173, 172, 173, 172, 173, 152, 152, - /* 1150 */ 172, 173, 172, 173, 172, 173, 152, 88, 152, 90, - /* 1160 */ 152, 55, 55, 152, 193, 152, 55, 152, 172, 173, - /* 1170 */ 26, 152, 163, 163, 152, 19, 172, 173, 172, 173, - /* 1180 */ 172, 173, 22, 172, 173, 172, 173, 172, 173, 55, - /* 1190 */ 193, 172, 173, 152, 172, 173, 166, 167, 166, 167, - /* 1200 */ 163, 163, 163, 97, 97, 196, 196, 163, 97, 55, - /* 1210 */ 23, 199, 56, 26, 22, 22, 24, 100, 101, 55, - /* 1220 */ 23, 209, 123, 26, 23, 23, 23, 26, 26, 26, - /* 1230 */ 37, 97, 152, 196, 196, 196, 23, 7, 8, 26, - /* 1240 */ 196, 23, 23, 152, 26, 26, 23, 132, 133, 26, - /* 1250 */ 106, 97, 132, 133, 23, 152, 152, 26, 210, 191, - /* 1260 */ 152, 97, 152, 234, 152, 152, 152, 233, 152, 210, - /* 1270 */ 152, 152, 210, 152, 152, 152, 152, 152, 152, 197, - /* 1280 */ 210, 198, 122, 150, 239, 201, 214, 214, 201, 239, - /* 1290 */ 214, 227, 200, 184, 198, 155, 67, 243, 122, 22, - /* 1300 */ 159, 159, 69, 176, 175, 175, 175, 240, 180, 159, - /* 1310 */ 220, 240, 27, 130, 18, 18, 159, 158, 220, 137, - /* 1320 */ 159, 189, 236, 158, 74, 159, 159, 158, 192, 192, - /* 1330 */ 192, 192, 235, 22, 189, 189, 201, 159, 158, 177, - /* 1340 */ 159, 107, 158, 76, 201, 177, 174, 174, 201, 174, - /* 1350 */ 106, 177, 182, 174, 107, 159, 22, 125, 159, 182, - /* 1360 */ 174, 176, 174, 174, 216, 216, 215, 215, 177, 216, - /* 1370 */ 215, 53, 137, 128, 216, 177, 127, 129, 215, 126, - /* 1380 */ 25, 13, 162, 26, 6, 161, 165, 165, 178, 153, - /* 1390 */ 153, 151, 151, 151, 151, 224, 4, 3, 22, 142, - /* 1400 */ 15, 94, 16, 178, 165, 205, 23, 202, 204, 203, - /* 1410 */ 201, 23, 120, 131, 111, 20, 226, 123, 125, 16, - /* 1420 */ 1, 123, 131, 229, 229, 111, 37, 37, 56, 64, - /* 1430 */ 122, 1, 5, 22, 107, 140, 80, 87, 26, 80, - /* 1440 */ 107, 72, 24, 20, 19, 105, 22, 112, 22, 79, - /* 1450 */ 22, 58, 23, 22, 79, 22, 249, 249, 246, 79, - /* 1460 */ 23, 23, 23, 116, 68, 22, 26, 23, 22, 56, - /* 1470 */ 122, 23, 23, 64, 22, 124, 26, 26, 64, 64, - /* 1480 */ 23, 23, 23, 23, 11, 23, 22, 26, 23, 22, - /* 1490 */ 24, 1, 23, 22, 26, 122, 24, 23, 22, 122, - /* 1500 */ 23, 23, 22, 122, 122, 23, 15, + /* 580 */ 51, 52, 53, 19, 168, 169, 170, 238, 19, 53, + /* 590 */ 152, 172, 173, 29, 30, 31, 32, 33, 34, 35, + /* 600 */ 36, 37, 38, 39, 40, 41, 152, 43, 44, 45, + /* 610 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 20, + /* 620 */ 101, 22, 23, 169, 170, 56, 207, 85, 55, 56, + /* 630 */ 23, 19, 20, 26, 22, 99, 100, 101, 102, 103, + /* 640 */ 104, 105, 238, 152, 152, 210, 47, 48, 112, 152, + /* 650 */ 108, 109, 110, 54, 55, 56, 221, 222, 223, 47, + /* 660 */ 48, 119, 120, 172, 173, 66, 54, 55, 56, 152, + /* 670 */ 97, 98, 99, 148, 149, 102, 103, 104, 66, 154, + /* 680 */ 23, 156, 83, 26, 230, 152, 113, 152, 163, 194, + /* 690 */ 195, 92, 92, 30, 95, 83, 97, 98, 207, 208, + /* 700 */ 101, 206, 179, 180, 92, 172, 173, 95, 152, 97, + /* 710 */ 98, 188, 99, 101, 219, 102, 103, 104, 152, 119, + /* 720 */ 120, 196, 55, 56, 19, 20, 113, 22, 193, 163, + /* 730 */ 11, 132, 133, 134, 135, 136, 24, 65, 172, 173, + /* 740 */ 207, 208, 250, 152, 132, 133, 134, 135, 136, 193, + /* 750 */ 78, 84, 47, 48, 49, 98, 199, 152, 86, 54, + /* 760 */ 55, 56, 196, 152, 97, 98, 209, 55, 163, 244, + /* 770 */ 107, 66, 152, 207, 208, 164, 175, 172, 173, 19, + /* 780 */ 20, 124, 22, 111, 38, 39, 40, 41, 83, 43, + /* 790 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 800 */ 95, 196, 97, 98, 85, 152, 101, 47, 48, 97, + /* 810 */ 85, 92, 207, 193, 54, 55, 56, 92, 49, 175, + /* 820 */ 55, 56, 221, 222, 223, 12, 66, 108, 109, 110, + /* 830 */ 137, 163, 139, 108, 109, 110, 26, 132, 133, 134, + /* 840 */ 135, 136, 152, 83, 43, 44, 45, 46, 47, 48, + /* 850 */ 49, 50, 51, 52, 53, 95, 26, 97, 98, 55, + /* 860 */ 56, 101, 97, 98, 196, 221, 222, 223, 146, 147, + /* 870 */ 57, 171, 152, 22, 26, 19, 20, 49, 22, 179, + /* 880 */ 108, 109, 110, 55, 56, 116, 73, 219, 75, 124, + /* 890 */ 121, 152, 132, 133, 134, 135, 136, 163, 85, 152, + /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 98, 5, + /* 910 */ 54, 55, 56, 193, 10, 11, 12, 13, 14, 172, + /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 152, + /* 930 */ 196, 55, 56, 186, 124, 152, 106, 160, 152, 83, + /* 940 */ 152, 164, 152, 61, 22, 211, 212, 152, 97, 98, + /* 950 */ 152, 95, 70, 97, 98, 172, 173, 101, 172, 173, + /* 960 */ 172, 173, 172, 173, 60, 181, 62, 172, 173, 47, + /* 970 */ 48, 123, 186, 97, 98, 71, 100, 55, 56, 152, + /* 980 */ 181, 186, 21, 107, 152, 109, 82, 163, 132, 133, + /* 990 */ 134, 135, 136, 89, 16, 207, 92, 93, 19, 172, + /* 1000 */ 173, 169, 170, 195, 55, 56, 12, 152, 132, 30, + /* 1010 */ 134, 47, 48, 186, 206, 225, 152, 95, 114, 97, + /* 1020 */ 196, 245, 246, 101, 152, 38, 39, 40, 41, 42, + /* 1030 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 1040 */ 53, 152, 163, 219, 152, 141, 97, 98, 193, 152, + /* 1050 */ 152, 57, 91, 164, 132, 133, 134, 152, 55, 152, + /* 1060 */ 152, 237, 230, 152, 103, 193, 88, 73, 90, 75, + /* 1070 */ 172, 173, 183, 152, 185, 196, 152, 172, 173, 172, + /* 1080 */ 173, 217, 152, 172, 173, 152, 107, 22, 152, 24, + /* 1090 */ 193, 112, 152, 172, 173, 152, 132, 242, 134, 152, + /* 1100 */ 97, 140, 152, 92, 152, 172, 173, 152, 172, 173, + /* 1110 */ 152, 100, 172, 173, 152, 172, 173, 152, 140, 172, + /* 1120 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152, + /* 1130 */ 172, 173, 152, 152, 172, 173, 152, 172, 173, 213, + /* 1140 */ 152, 172, 173, 152, 152, 152, 172, 173, 152, 172, + /* 1150 */ 173, 152, 172, 173, 152, 210, 172, 173, 152, 26, + /* 1160 */ 172, 173, 152, 172, 173, 172, 173, 152, 172, 173, + /* 1170 */ 152, 172, 173, 152, 172, 173, 152, 59, 172, 173, + /* 1180 */ 152, 63, 172, 173, 152, 193, 152, 152, 152, 152, + /* 1190 */ 172, 173, 152, 172, 173, 77, 172, 173, 152, 152, + /* 1200 */ 172, 173, 152, 152, 172, 173, 172, 173, 172, 173, + /* 1210 */ 152, 22, 172, 173, 152, 152, 152, 22, 172, 173, + /* 1220 */ 152, 152, 152, 172, 173, 152, 7, 8, 9, 163, + /* 1230 */ 172, 173, 22, 23, 172, 173, 172, 173, 166, 167, + /* 1240 */ 172, 173, 172, 173, 55, 172, 173, 22, 23, 108, + /* 1250 */ 109, 110, 217, 152, 217, 166, 167, 163, 163, 163, + /* 1260 */ 163, 163, 196, 130, 217, 211, 212, 217, 116, 23, + /* 1270 */ 22, 101, 26, 121, 23, 23, 23, 26, 26, 26, + /* 1280 */ 23, 23, 112, 26, 26, 37, 97, 100, 101, 55, + /* 1290 */ 196, 196, 196, 196, 196, 23, 23, 55, 26, 26, + /* 1300 */ 7, 8, 23, 152, 23, 26, 96, 26, 132, 132, + /* 1310 */ 134, 134, 23, 152, 152, 26, 152, 122, 152, 191, + /* 1320 */ 152, 96, 234, 152, 152, 152, 152, 152, 197, 210, + /* 1330 */ 152, 97, 152, 152, 210, 233, 210, 198, 150, 97, + /* 1340 */ 184, 201, 239, 214, 214, 201, 239, 180, 214, 227, + /* 1350 */ 200, 198, 155, 67, 243, 176, 69, 175, 175, 175, + /* 1360 */ 122, 159, 159, 240, 159, 240, 22, 220, 27, 130, + /* 1370 */ 201, 18, 159, 18, 189, 158, 158, 220, 192, 159, + /* 1380 */ 137, 236, 192, 192, 192, 189, 74, 189, 159, 235, + /* 1390 */ 159, 158, 22, 177, 201, 201, 159, 107, 158, 177, + /* 1400 */ 159, 174, 158, 76, 174, 182, 174, 106, 182, 125, + /* 1410 */ 174, 107, 177, 22, 159, 216, 215, 137, 159, 53, + /* 1420 */ 216, 176, 215, 174, 174, 216, 215, 215, 174, 229, + /* 1430 */ 216, 129, 224, 177, 126, 229, 127, 177, 128, 25, + /* 1440 */ 162, 226, 26, 161, 13, 153, 6, 153, 151, 151, + /* 1450 */ 151, 151, 205, 165, 178, 178, 165, 4, 3, 22, + /* 1460 */ 165, 142, 15, 94, 202, 204, 203, 201, 16, 23, + /* 1470 */ 249, 23, 120, 249, 246, 111, 131, 123, 20, 16, + /* 1480 */ 1, 125, 123, 111, 56, 64, 37, 37, 131, 122, + /* 1490 */ 1, 37, 5, 37, 22, 107, 26, 80, 140, 80, + /* 1500 */ 87, 72, 107, 20, 24, 19, 112, 105, 23, 79, + /* 1510 */ 22, 79, 22, 22, 22, 58, 22, 79, 23, 68, + /* 1520 */ 23, 23, 26, 116, 22, 26, 23, 22, 122, 23, + /* 1530 */ 23, 56, 64, 22, 124, 26, 26, 64, 64, 23, + /* 1540 */ 23, 23, 23, 11, 23, 22, 26, 23, 22, 24, + /* 1550 */ 1, 23, 22, 26, 251, 24, 23, 22, 122, 23, + /* 1560 */ 23, 22, 15, 122, 122, 122, 23, }; -#define YY_SHIFT_USE_DFLT (-95) -#define YY_SHIFT_COUNT (442) -#define YY_SHIFT_MIN (-94) -#define YY_SHIFT_MAX (1491) +#define YY_SHIFT_USE_DFLT (1567) +#define YY_SHIFT_COUNT (455) +#define YY_SHIFT_MIN (-94) +#define YY_SHIFT_MAX (1549) static const short yy_shift_ofst[] = { - /* 0 */ 40, 564, 869, 577, 725, 725, 725, 725, 690, -19, - /* 10 */ 16, 16, 100, 725, 725, 725, 725, 725, 725, 725, - /* 20 */ 841, 841, 538, 507, 684, 565, 61, 137, 172, 207, - /* 30 */ 242, 277, 312, 347, 382, 424, 424, 424, 424, 424, - /* 40 */ 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, - /* 50 */ 459, 424, 494, 529, 529, 670, 725, 725, 725, 725, - /* 60 */ 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, - /* 70 */ 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, - /* 80 */ 725, 725, 725, 725, 821, 725, 725, 725, 725, 725, - /* 90 */ 725, 725, 725, 725, 725, 725, 725, 725, 952, 711, - /* 100 */ 711, 711, 711, 711, 766, 23, 32, 924, 637, 825, - /* 110 */ 837, 837, 924, 73, 183, -51, -95, -95, -95, 501, - /* 120 */ 501, 501, 903, 903, 632, 205, 241, 924, 924, 924, - /* 130 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, - /* 140 */ 924, 924, 924, 924, 924, 924, 924, 192, 1027, 1106, - /* 150 */ 1106, 183, 176, 176, 176, 176, 176, 176, -95, -95, - /* 160 */ -95, 880, -94, -94, 578, 734, 99, 730, 769, 349, - /* 170 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, - /* 180 */ 924, 924, 924, 924, 924, 924, 924, 954, 954, 954, - /* 190 */ 924, 924, 622, 924, 924, 924, -18, 924, 924, 914, - /* 200 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, - /* 210 */ 441, 1020, 1107, 1107, 1107, 569, 45, 217, 510, 423, - /* 220 */ 834, 834, 1156, 423, 1156, 1144, 1187, 359, 1051, 834, - /* 230 */ -17, 1051, 1051, 1099, 469, 1192, 1229, 1176, 1176, 1233, - /* 240 */ 1233, 1176, 1277, 1285, 1183, 1296, 1296, 1296, 1296, 1176, - /* 250 */ 1297, 1183, 1277, 1285, 1285, 1183, 1176, 1297, 1182, 1250, - /* 260 */ 1176, 1176, 1297, 1311, 1176, 1297, 1176, 1297, 1311, 1234, - /* 270 */ 1234, 1234, 1267, 1311, 1234, 1244, 1234, 1267, 1234, 1234, - /* 280 */ 1232, 1247, 1232, 1247, 1232, 1247, 1232, 1247, 1176, 1334, - /* 290 */ 1176, 1235, 1311, 1318, 1318, 1311, 1248, 1253, 1245, 1249, - /* 300 */ 1183, 1355, 1357, 1368, 1368, 1378, 1378, 1378, 1378, -95, - /* 310 */ -95, -95, -95, -95, -95, -95, -95, 451, 936, 816, - /* 320 */ 888, 1069, 799, 1111, 1197, 1193, 1201, 1202, 1203, 1213, - /* 330 */ 1134, 1117, 1230, 497, 1218, 1219, 1154, 1223, 1115, 1120, - /* 340 */ 1231, 1164, 1160, 1392, 1394, 1376, 1257, 1385, 1307, 1386, - /* 350 */ 1383, 1388, 1292, 1282, 1303, 1294, 1395, 1293, 1403, 1419, - /* 360 */ 1298, 1291, 1389, 1390, 1314, 1372, 1365, 1308, 1430, 1427, - /* 370 */ 1411, 1327, 1295, 1356, 1412, 1359, 1350, 1369, 1333, 1418, - /* 380 */ 1423, 1425, 1335, 1340, 1424, 1370, 1426, 1428, 1429, 1431, - /* 390 */ 1375, 1393, 1433, 1380, 1396, 1437, 1438, 1439, 1347, 1443, - /* 400 */ 1444, 1446, 1440, 1348, 1448, 1449, 1413, 1409, 1452, 1351, - /* 410 */ 1450, 1414, 1451, 1415, 1457, 1450, 1458, 1459, 1460, 1461, - /* 420 */ 1462, 1464, 1473, 1465, 1467, 1466, 1468, 1469, 1471, 1472, - /* 430 */ 1468, 1474, 1476, 1477, 1478, 1480, 1373, 1377, 1381, 1382, - /* 440 */ 1482, 1491, 1490, + /* 0 */ 40, 599, 904, 612, 760, 760, 760, 760, 725, -19, + /* 10 */ 16, 16, 100, 760, 760, 760, 760, 760, 760, 760, + /* 20 */ 876, 876, 573, 542, 719, 600, 61, 137, 172, 207, + /* 30 */ 242, 277, 312, 347, 382, 417, 459, 459, 459, 459, + /* 40 */ 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, + /* 50 */ 459, 459, 459, 494, 459, 529, 564, 564, 705, 760, + /* 60 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, + /* 70 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, + /* 80 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, + /* 90 */ 856, 760, 760, 760, 760, 760, 760, 760, 760, 760, + /* 100 */ 760, 760, 760, 760, 987, 746, 746, 746, 746, 746, + /* 110 */ 801, 23, 32, 949, 961, 979, 964, 964, 949, 73, + /* 120 */ 113, -51, 1567, 1567, 1567, 536, 536, 536, 99, 99, + /* 130 */ 813, 813, 667, 205, 240, 949, 949, 949, 949, 949, + /* 140 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, + /* 150 */ 949, 949, 949, 949, 949, 332, 1011, 422, 422, 113, + /* 160 */ 30, 30, 30, 30, 30, 30, 1567, 1567, 1567, 922, + /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 949, + /* 180 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, + /* 190 */ 949, 949, 949, 949, 949, 672, 672, 672, 949, 949, + /* 200 */ 657, 949, 949, 949, -18, 949, 949, 994, 949, 949, + /* 210 */ 949, 949, 949, 949, 949, 949, 949, 949, 772, 1118, + /* 220 */ 712, 712, 712, 810, 45, 769, 1219, 1133, 418, 418, + /* 230 */ 569, 1133, 569, 830, 607, 663, 882, 418, 693, 882, + /* 240 */ 882, 848, 1152, 1065, 1286, 1238, 1238, 1287, 1287, 1238, + /* 250 */ 1344, 1341, 1239, 1353, 1353, 1353, 1353, 1238, 1355, 1239, + /* 260 */ 1344, 1341, 1341, 1239, 1238, 1355, 1243, 1312, 1238, 1238, + /* 270 */ 1355, 1370, 1238, 1355, 1238, 1355, 1370, 1290, 1290, 1290, + /* 280 */ 1327, 1370, 1290, 1301, 1290, 1327, 1290, 1290, 1284, 1304, + /* 290 */ 1284, 1304, 1284, 1304, 1284, 1304, 1238, 1391, 1238, 1280, + /* 300 */ 1370, 1366, 1366, 1370, 1302, 1308, 1310, 1309, 1239, 1414, + /* 310 */ 1416, 1431, 1431, 1440, 1440, 1440, 1440, 1567, 1567, 1567, + /* 320 */ 1567, 1567, 1567, 1567, 1567, 519, 978, 1210, 1225, 104, + /* 330 */ 1141, 1189, 1246, 1248, 1251, 1252, 1253, 1257, 1258, 1273, + /* 340 */ 1003, 1187, 1293, 1170, 1272, 1279, 1234, 1281, 1176, 1177, + /* 350 */ 1289, 1242, 1195, 1453, 1455, 1437, 1319, 1447, 1369, 1452, + /* 360 */ 1446, 1448, 1352, 1345, 1364, 1354, 1458, 1356, 1463, 1479, + /* 370 */ 1359, 1357, 1449, 1450, 1454, 1456, 1372, 1428, 1421, 1367, + /* 380 */ 1489, 1487, 1472, 1388, 1358, 1417, 1470, 1419, 1413, 1429, + /* 390 */ 1395, 1480, 1483, 1486, 1394, 1402, 1488, 1430, 1490, 1491, + /* 400 */ 1485, 1492, 1432, 1457, 1494, 1438, 1451, 1495, 1497, 1498, + /* 410 */ 1496, 1407, 1502, 1503, 1505, 1499, 1406, 1506, 1507, 1475, + /* 420 */ 1468, 1511, 1410, 1509, 1473, 1510, 1474, 1516, 1509, 1517, + /* 430 */ 1518, 1519, 1520, 1521, 1523, 1532, 1524, 1526, 1525, 1527, + /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1436, + /* 450 */ 1441, 1442, 1443, 1543, 1547, 1549, }; #define YY_REDUCE_USE_DFLT (-130) -#define YY_REDUCE_COUNT (316) +#define YY_REDUCE_COUNT (324) #define YY_REDUCE_MIN (-129) -#define YY_REDUCE_MAX (1243) +#define YY_REDUCE_MAX (1300) static const short yy_reduce_ofst[] = { - /* 0 */ -29, 531, 490, 570, -49, 272, 456, 498, 633, 400, - /* 10 */ 612, 626, 113, 482, 678, 719, 384, 726, 748, 791, - /* 20 */ 419, 693, 761, 812, 819, 625, 76, 76, 76, 76, + /* 0 */ -29, 566, 525, 605, -49, 307, 491, 533, 668, 435, + /* 10 */ 601, 644, 148, 747, 786, 795, 419, 788, 827, 790, + /* 20 */ 454, 832, 889, 495, 824, 734, 76, 76, 76, 76, /* 30 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, /* 40 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - /* 50 */ 76, 76, 76, 76, 76, 793, 795, 856, 871, 875, - /* 60 */ 878, 881, 885, 887, 889, 894, 897, 900, 916, 919, - /* 70 */ 922, 926, 928, 930, 932, 934, 938, 941, 944, 956, - /* 80 */ 963, 966, 968, 970, 972, 974, 978, 980, 982, 996, - /* 90 */ 1004, 1006, 1008, 1011, 1013, 1015, 1019, 1022, 76, 76, - /* 100 */ 76, 76, 76, 76, 76, 76, 76, 555, 210, 260, - /* 110 */ 200, 346, 571, 76, 700, 76, 76, 76, 76, 838, - /* 120 */ 838, 838, 42, 182, 251, 160, 160, 550, 5, 455, - /* 130 */ 585, 721, 749, 882, 884, 971, 618, 462, 797, 514, - /* 140 */ 807, 524, 997, -129, 655, 859, 62, 290, 66, 1030, - /* 150 */ 1032, 589, 1009, 1010, 1037, 1038, 1039, 1044, 740, 852, - /* 160 */ 1012, 112, 147, 230, 257, 180, 369, 403, 500, 549, - /* 170 */ 556, 563, 694, 751, 765, 772, 778, 820, 868, 873, - /* 180 */ 890, 929, 935, 985, 1041, 1080, 1091, 540, 593, 661, - /* 190 */ 1103, 1104, 842, 1108, 1110, 1112, 1048, 1113, 1114, 1068, - /* 200 */ 1116, 1118, 1119, 180, 1121, 1122, 1123, 1124, 1125, 1126, - /* 210 */ 1029, 1034, 1059, 1062, 1070, 842, 1082, 1083, 1133, 1084, - /* 220 */ 1072, 1073, 1045, 1087, 1050, 1127, 1109, 1128, 1129, 1076, - /* 230 */ 1064, 1130, 1131, 1092, 1096, 1140, 1054, 1141, 1142, 1067, - /* 240 */ 1071, 1150, 1090, 1132, 1135, 1136, 1137, 1138, 1139, 1157, - /* 250 */ 1159, 1143, 1098, 1145, 1146, 1147, 1161, 1165, 1086, 1097, - /* 260 */ 1166, 1167, 1169, 1162, 1178, 1180, 1181, 1184, 1168, 1172, - /* 270 */ 1173, 1175, 1170, 1174, 1179, 1185, 1186, 1177, 1188, 1189, - /* 280 */ 1148, 1151, 1149, 1152, 1153, 1155, 1158, 1163, 1196, 1171, - /* 290 */ 1199, 1190, 1191, 1194, 1195, 1198, 1200, 1204, 1206, 1205, - /* 300 */ 1209, 1220, 1224, 1236, 1237, 1240, 1241, 1242, 1243, 1207, - /* 310 */ 1208, 1212, 1221, 1222, 1210, 1225, 1239, + /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 783, 898, + /* 60 */ 905, 907, 911, 921, 933, 936, 940, 943, 947, 950, + /* 70 */ 952, 955, 958, 962, 965, 969, 974, 977, 980, 984, + /* 80 */ 988, 991, 993, 996, 999, 1002, 1006, 1010, 1018, 1021, + /* 90 */ 1024, 1028, 1032, 1034, 1036, 1040, 1046, 1051, 1058, 1062, + /* 100 */ 1064, 1068, 1070, 1073, 76, 76, 76, 76, 76, 76, + /* 110 */ 76, 76, 76, 855, 36, 523, 235, 416, 777, 76, + /* 120 */ 278, 76, 76, 76, 76, 700, 700, 700, 150, 220, + /* 130 */ 147, 217, 221, 306, 306, 611, 5, 535, 556, 620, + /* 140 */ 720, 872, 897, 116, 864, 349, 1035, 1037, 404, 1047, + /* 150 */ 992, -129, 1050, 492, 62, 722, 879, 1072, 1089, 808, + /* 160 */ 1066, 1094, 1095, 1096, 1097, 1098, 776, 1054, 557, 57, + /* 170 */ 112, 131, 167, 182, 250, 272, 291, 331, 364, 438, + /* 180 */ 497, 517, 591, 653, 690, 739, 775, 798, 892, 908, + /* 190 */ 924, 930, 1015, 1063, 1069, 355, 784, 799, 981, 1101, + /* 200 */ 926, 1151, 1161, 1162, 945, 1164, 1166, 1128, 1168, 1171, + /* 210 */ 1172, 250, 1173, 1174, 1175, 1178, 1180, 1181, 1088, 1102, + /* 220 */ 1119, 1124, 1126, 926, 1131, 1139, 1188, 1140, 1129, 1130, + /* 230 */ 1103, 1144, 1107, 1179, 1156, 1167, 1182, 1134, 1122, 1183, + /* 240 */ 1184, 1150, 1153, 1197, 1111, 1202, 1203, 1123, 1125, 1205, + /* 250 */ 1147, 1185, 1169, 1186, 1190, 1191, 1192, 1213, 1217, 1193, + /* 260 */ 1157, 1196, 1198, 1194, 1220, 1218, 1145, 1154, 1229, 1231, + /* 270 */ 1233, 1216, 1237, 1240, 1241, 1244, 1222, 1227, 1230, 1232, + /* 280 */ 1223, 1235, 1236, 1245, 1249, 1226, 1250, 1254, 1199, 1201, + /* 290 */ 1204, 1207, 1209, 1211, 1214, 1212, 1255, 1208, 1259, 1215, + /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, + /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, + /* 320 */ 1288, 1291, 1276, 1277, 1295, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1258, 1248, 1248, 1248, 1180, 1180, 1180, 1180, 1248, 1077, - /* 10 */ 1106, 1106, 1232, 1309, 1309, 1309, 1309, 1309, 1309, 1179, - /* 20 */ 1309, 1309, 1309, 1309, 1248, 1081, 1112, 1309, 1309, 1309, - /* 30 */ 1309, 1309, 1309, 1309, 1309, 1231, 1233, 1120, 1119, 1214, - /* 40 */ 1093, 1117, 1110, 1114, 1181, 1175, 1176, 1174, 1178, 1182, - /* 50 */ 1309, 1113, 1144, 1159, 1143, 1309, 1309, 1309, 1309, 1309, - /* 60 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 70 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 80 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 90 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1153, 1158, - /* 100 */ 1165, 1157, 1154, 1146, 1145, 1147, 1148, 1309, 1000, 1048, - /* 110 */ 1309, 1309, 1309, 1149, 1309, 1150, 1162, 1161, 1160, 1239, - /* 120 */ 1266, 1265, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 130 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 140 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1258, 1248, 1006, - /* 150 */ 1006, 1309, 1248, 1248, 1248, 1248, 1248, 1248, 1244, 1081, - /* 160 */ 1072, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 170 */ 1309, 1236, 1234, 1309, 1195, 1309, 1309, 1309, 1309, 1309, - /* 180 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 190 */ 1309, 1309, 1309, 1309, 1309, 1309, 1077, 1309, 1309, 1309, - /* 200 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1260, - /* 210 */ 1309, 1209, 1077, 1077, 1077, 1079, 1061, 1071, 985, 1116, - /* 220 */ 1095, 1095, 1298, 1116, 1298, 1023, 1280, 1020, 1106, 1095, - /* 230 */ 1177, 1106, 1106, 1078, 1071, 1309, 1301, 1086, 1086, 1300, - /* 240 */ 1300, 1086, 1125, 1051, 1116, 1057, 1057, 1057, 1057, 1086, - /* 250 */ 997, 1116, 1125, 1051, 1051, 1116, 1086, 997, 1213, 1295, - /* 260 */ 1086, 1086, 997, 1188, 1086, 997, 1086, 997, 1188, 1049, - /* 270 */ 1049, 1049, 1038, 1188, 1049, 1023, 1049, 1038, 1049, 1049, - /* 280 */ 1099, 1094, 1099, 1094, 1099, 1094, 1099, 1094, 1086, 1183, - /* 290 */ 1086, 1309, 1188, 1192, 1192, 1188, 1111, 1100, 1109, 1107, - /* 300 */ 1116, 1003, 1041, 1263, 1263, 1259, 1259, 1259, 1259, 1306, - /* 310 */ 1306, 1244, 1275, 1275, 1025, 1025, 1275, 1309, 1309, 1309, - /* 320 */ 1309, 1309, 1309, 1270, 1309, 1197, 1309, 1309, 1309, 1309, - /* 330 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 340 */ 1309, 1309, 1131, 1309, 981, 1241, 1309, 1309, 1240, 1309, - /* 350 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 360 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1297, 1309, 1309, - /* 370 */ 1309, 1309, 1309, 1309, 1212, 1211, 1309, 1309, 1309, 1309, - /* 380 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 390 */ 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1063, 1309, - /* 400 */ 1309, 1309, 1284, 1309, 1309, 1309, 1309, 1309, 1309, 1309, - /* 410 */ 1108, 1309, 1101, 1309, 1309, 1288, 1309, 1309, 1309, 1309, - /* 420 */ 1309, 1309, 1309, 1309, 1309, 1309, 1250, 1309, 1309, 1309, - /* 430 */ 1249, 1309, 1309, 1309, 1309, 1309, 1133, 1309, 1132, 1136, - /* 440 */ 1309, 991, 1309, + /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, + /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, + /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, + /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, + /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, + /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, + /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, + /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, + /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, + /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, + /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, + /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, + /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, + /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, + /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, + /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, + /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, + /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, + /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, + /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, + /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, + /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, + /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, + /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, + /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, + /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, + /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, + /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, + /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, + /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, + /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, + /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, + /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, + /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, + /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, }; /********** End of lemon-generated parsing tables *****************************/ @@ -132581,7 +134941,7 @@ static const char *const yyTokenName[] = { "VALUES", "DISTINCT", "DOT", "FROM", "JOIN", "USING", "ORDER", "GROUP", "HAVING", "LIMIT", "WHERE", "INTO", - "INTEGER", "FLOAT", "BLOB", "VARIABLE", + "FLOAT", "BLOB", "INTEGER", "VARIABLE", "CASE", "WHEN", "THEN", "ELSE", "INDEX", "ALTER", "ADD", "error", "input", "cmdlist", "ecmd", "explain", @@ -132757,195 +135117,199 @@ static const char *const yyRuleName[] = { /* 136 */ "where_opt ::= WHERE expr", /* 137 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", /* 138 */ "setlist ::= setlist COMMA nm EQ expr", - /* 139 */ "setlist ::= nm EQ expr", - /* 140 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 142 */ "insert_cmd ::= INSERT orconf", - /* 143 */ "insert_cmd ::= REPLACE", - /* 144 */ "idlist_opt ::=", - /* 145 */ "idlist_opt ::= LP idlist RP", - /* 146 */ "idlist ::= idlist COMMA nm", - /* 147 */ "idlist ::= nm", - /* 148 */ "expr ::= LP expr RP", - /* 149 */ "term ::= NULL", - /* 150 */ "expr ::= ID|INDEXED", - /* 151 */ "expr ::= JOIN_KW", - /* 152 */ "expr ::= nm DOT nm", - /* 153 */ "expr ::= nm DOT nm DOT nm", - /* 154 */ "term ::= INTEGER|FLOAT|BLOB", - /* 155 */ "term ::= STRING", - /* 156 */ "expr ::= VARIABLE", - /* 157 */ "expr ::= expr COLLATE ID|STRING", - /* 158 */ "expr ::= CAST LP expr AS typetoken RP", - /* 159 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 160 */ "expr ::= ID|INDEXED LP STAR RP", - /* 161 */ "term ::= CTIME_KW", - /* 162 */ "expr ::= expr AND expr", - /* 163 */ "expr ::= expr OR expr", - /* 164 */ "expr ::= expr LT|GT|GE|LE expr", - /* 165 */ "expr ::= expr EQ|NE expr", - /* 166 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 167 */ "expr ::= expr PLUS|MINUS expr", - /* 168 */ "expr ::= expr STAR|SLASH|REM expr", - /* 169 */ "expr ::= expr CONCAT expr", - /* 170 */ "likeop ::= LIKE_KW|MATCH", - /* 171 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 172 */ "expr ::= expr likeop expr", - /* 173 */ "expr ::= expr likeop expr ESCAPE expr", - /* 174 */ "expr ::= expr ISNULL|NOTNULL", - /* 175 */ "expr ::= expr NOT NULL", - /* 176 */ "expr ::= expr IS expr", - /* 177 */ "expr ::= expr IS NOT expr", - /* 178 */ "expr ::= NOT expr", - /* 179 */ "expr ::= BITNOT expr", - /* 180 */ "expr ::= MINUS expr", - /* 181 */ "expr ::= PLUS expr", - /* 182 */ "between_op ::= BETWEEN", - /* 183 */ "between_op ::= NOT BETWEEN", - /* 184 */ "expr ::= expr between_op expr AND expr", - /* 185 */ "in_op ::= IN", - /* 186 */ "in_op ::= NOT IN", - /* 187 */ "expr ::= expr in_op LP exprlist RP", - /* 188 */ "expr ::= LP select RP", - /* 189 */ "expr ::= expr in_op LP select RP", - /* 190 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 191 */ "expr ::= EXISTS LP select RP", - /* 192 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 193 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 194 */ "case_exprlist ::= WHEN expr THEN expr", - /* 195 */ "case_else ::= ELSE expr", - /* 196 */ "case_else ::=", - /* 197 */ "case_operand ::= expr", - /* 198 */ "case_operand ::=", - /* 199 */ "exprlist ::=", - /* 200 */ "nexprlist ::= nexprlist COMMA expr", - /* 201 */ "nexprlist ::= expr", - /* 202 */ "paren_exprlist ::=", - /* 203 */ "paren_exprlist ::= LP exprlist RP", - /* 204 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 205 */ "uniqueflag ::= UNIQUE", - /* 206 */ "uniqueflag ::=", - /* 207 */ "eidlist_opt ::=", - /* 208 */ "eidlist_opt ::= LP eidlist RP", - /* 209 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 210 */ "eidlist ::= nm collate sortorder", - /* 211 */ "collate ::=", - /* 212 */ "collate ::= COLLATE ID|STRING", - /* 213 */ "cmd ::= DROP INDEX ifexists fullname", - /* 214 */ "cmd ::= VACUUM", - /* 215 */ "cmd ::= VACUUM nm", - /* 216 */ "cmd ::= PRAGMA nm dbnm", - /* 217 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 218 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 219 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 220 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 221 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 222 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 223 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 224 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 225 */ "trigger_time ::= BEFORE", - /* 226 */ "trigger_time ::= AFTER", - /* 227 */ "trigger_time ::= INSTEAD OF", - /* 228 */ "trigger_time ::=", - /* 229 */ "trigger_event ::= DELETE|INSERT", - /* 230 */ "trigger_event ::= UPDATE", - /* 231 */ "trigger_event ::= UPDATE OF idlist", - /* 232 */ "when_clause ::=", - /* 233 */ "when_clause ::= WHEN expr", - /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 236 */ "trnm ::= nm DOT nm", - /* 237 */ "tridxby ::= INDEXED BY nm", - /* 238 */ "tridxby ::= NOT INDEXED", - /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 242 */ "trigger_cmd ::= select", - /* 243 */ "expr ::= RAISE LP IGNORE RP", - /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 245 */ "raisetype ::= ROLLBACK", - /* 246 */ "raisetype ::= ABORT", - /* 247 */ "raisetype ::= FAIL", - /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 250 */ "cmd ::= DETACH database_kw_opt expr", - /* 251 */ "key_opt ::=", - /* 252 */ "key_opt ::= KEY expr", - /* 253 */ "cmd ::= REINDEX", - /* 254 */ "cmd ::= REINDEX nm dbnm", - /* 255 */ "cmd ::= ANALYZE", - /* 256 */ "cmd ::= ANALYZE nm dbnm", - /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 259 */ "add_column_fullname ::= fullname", - /* 260 */ "cmd ::= create_vtab", - /* 261 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 263 */ "vtabarg ::=", - /* 264 */ "vtabargtoken ::= ANY", - /* 265 */ "vtabargtoken ::= lp anylist RP", - /* 266 */ "lp ::= LP", - /* 267 */ "with ::=", - /* 268 */ "with ::= WITH wqlist", - /* 269 */ "with ::= WITH RECURSIVE wqlist", - /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 272 */ "input ::= cmdlist", - /* 273 */ "cmdlist ::= cmdlist ecmd", - /* 274 */ "cmdlist ::= ecmd", - /* 275 */ "ecmd ::= SEMI", - /* 276 */ "ecmd ::= explain cmdx SEMI", - /* 277 */ "explain ::=", - /* 278 */ "trans_opt ::=", - /* 279 */ "trans_opt ::= TRANSACTION", - /* 280 */ "trans_opt ::= TRANSACTION nm", - /* 281 */ "savepoint_opt ::= SAVEPOINT", - /* 282 */ "savepoint_opt ::=", - /* 283 */ "cmd ::= create_table create_table_args", - /* 284 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 285 */ "columnlist ::= columnname carglist", - /* 286 */ "nm ::= ID|INDEXED", - /* 287 */ "nm ::= STRING", - /* 288 */ "nm ::= JOIN_KW", - /* 289 */ "typetoken ::= typename", - /* 290 */ "typename ::= ID|STRING", - /* 291 */ "signed ::= plus_num", - /* 292 */ "signed ::= minus_num", - /* 293 */ "carglist ::= carglist ccons", - /* 294 */ "carglist ::=", - /* 295 */ "ccons ::= NULL onconf", - /* 296 */ "conslist_opt ::= COMMA conslist", - /* 297 */ "conslist ::= conslist tconscomma tcons", - /* 298 */ "conslist ::= tcons", - /* 299 */ "tconscomma ::=", - /* 300 */ "defer_subclause_opt ::= defer_subclause", - /* 301 */ "resolvetype ::= raisetype", - /* 302 */ "selectnowith ::= oneselect", - /* 303 */ "oneselect ::= values", - /* 304 */ "sclp ::= selcollist COMMA", - /* 305 */ "as ::= ID|STRING", - /* 306 */ "expr ::= term", - /* 307 */ "exprlist ::= nexprlist", - /* 308 */ "nmnum ::= plus_num", - /* 309 */ "nmnum ::= nm", - /* 310 */ "nmnum ::= ON", - /* 311 */ "nmnum ::= DELETE", - /* 312 */ "nmnum ::= DEFAULT", - /* 313 */ "plus_num ::= INTEGER|FLOAT", - /* 314 */ "foreach_clause ::=", - /* 315 */ "foreach_clause ::= FOR EACH ROW", - /* 316 */ "trnm ::= nm", - /* 317 */ "tridxby ::=", - /* 318 */ "database_kw_opt ::= DATABASE", - /* 319 */ "database_kw_opt ::=", - /* 320 */ "kwcolumn_opt ::=", - /* 321 */ "kwcolumn_opt ::= COLUMNKW", - /* 322 */ "vtabarglist ::= vtabarg", - /* 323 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 324 */ "vtabarg ::= vtabarg vtabargtoken", - /* 325 */ "anylist ::=", - /* 326 */ "anylist ::= anylist LP anylist RP", - /* 327 */ "anylist ::= anylist ANY", + /* 139 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 140 */ "setlist ::= nm EQ expr", + /* 141 */ "setlist ::= LP idlist RP EQ expr", + /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", + /* 143 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", + /* 144 */ "insert_cmd ::= INSERT orconf", + /* 145 */ "insert_cmd ::= REPLACE", + /* 146 */ "idlist_opt ::=", + /* 147 */ "idlist_opt ::= LP idlist RP", + /* 148 */ "idlist ::= idlist COMMA nm", + /* 149 */ "idlist ::= nm", + /* 150 */ "expr ::= LP expr RP", + /* 151 */ "term ::= NULL", + /* 152 */ "expr ::= ID|INDEXED", + /* 153 */ "expr ::= JOIN_KW", + /* 154 */ "expr ::= nm DOT nm", + /* 155 */ "expr ::= nm DOT nm DOT nm", + /* 156 */ "term ::= FLOAT|BLOB", + /* 157 */ "term ::= STRING", + /* 158 */ "term ::= INTEGER", + /* 159 */ "expr ::= VARIABLE", + /* 160 */ "expr ::= expr COLLATE ID|STRING", + /* 161 */ "expr ::= CAST LP expr AS typetoken RP", + /* 162 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 163 */ "expr ::= ID|INDEXED LP STAR RP", + /* 164 */ "term ::= CTIME_KW", + /* 165 */ "expr ::= LP nexprlist COMMA expr RP", + /* 166 */ "expr ::= expr AND expr", + /* 167 */ "expr ::= expr OR expr", + /* 168 */ "expr ::= expr LT|GT|GE|LE expr", + /* 169 */ "expr ::= expr EQ|NE expr", + /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 171 */ "expr ::= expr PLUS|MINUS expr", + /* 172 */ "expr ::= expr STAR|SLASH|REM expr", + /* 173 */ "expr ::= expr CONCAT expr", + /* 174 */ "likeop ::= LIKE_KW|MATCH", + /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 176 */ "expr ::= expr likeop expr", + /* 177 */ "expr ::= expr likeop expr ESCAPE expr", + /* 178 */ "expr ::= expr ISNULL|NOTNULL", + /* 179 */ "expr ::= expr NOT NULL", + /* 180 */ "expr ::= expr IS expr", + /* 181 */ "expr ::= expr IS NOT expr", + /* 182 */ "expr ::= NOT expr", + /* 183 */ "expr ::= BITNOT expr", + /* 184 */ "expr ::= MINUS expr", + /* 185 */ "expr ::= PLUS expr", + /* 186 */ "between_op ::= BETWEEN", + /* 187 */ "between_op ::= NOT BETWEEN", + /* 188 */ "expr ::= expr between_op expr AND expr", + /* 189 */ "in_op ::= IN", + /* 190 */ "in_op ::= NOT IN", + /* 191 */ "expr ::= expr in_op LP exprlist RP", + /* 192 */ "expr ::= LP select RP", + /* 193 */ "expr ::= expr in_op LP select RP", + /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 195 */ "expr ::= EXISTS LP select RP", + /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 198 */ "case_exprlist ::= WHEN expr THEN expr", + /* 199 */ "case_else ::= ELSE expr", + /* 200 */ "case_else ::=", + /* 201 */ "case_operand ::= expr", + /* 202 */ "case_operand ::=", + /* 203 */ "exprlist ::=", + /* 204 */ "nexprlist ::= nexprlist COMMA expr", + /* 205 */ "nexprlist ::= expr", + /* 206 */ "paren_exprlist ::=", + /* 207 */ "paren_exprlist ::= LP exprlist RP", + /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 209 */ "uniqueflag ::= UNIQUE", + /* 210 */ "uniqueflag ::=", + /* 211 */ "eidlist_opt ::=", + /* 212 */ "eidlist_opt ::= LP eidlist RP", + /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 214 */ "eidlist ::= nm collate sortorder", + /* 215 */ "collate ::=", + /* 216 */ "collate ::= COLLATE ID|STRING", + /* 217 */ "cmd ::= DROP INDEX ifexists fullname", + /* 218 */ "cmd ::= VACUUM", + /* 219 */ "cmd ::= VACUUM nm", + /* 220 */ "cmd ::= PRAGMA nm dbnm", + /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 229 */ "trigger_time ::= BEFORE", + /* 230 */ "trigger_time ::= AFTER", + /* 231 */ "trigger_time ::= INSTEAD OF", + /* 232 */ "trigger_time ::=", + /* 233 */ "trigger_event ::= DELETE|INSERT", + /* 234 */ "trigger_event ::= UPDATE", + /* 235 */ "trigger_event ::= UPDATE OF idlist", + /* 236 */ "when_clause ::=", + /* 237 */ "when_clause ::= WHEN expr", + /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 240 */ "trnm ::= nm DOT nm", + /* 241 */ "tridxby ::= INDEXED BY nm", + /* 242 */ "tridxby ::= NOT INDEXED", + /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", + /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 246 */ "trigger_cmd ::= select", + /* 247 */ "expr ::= RAISE LP IGNORE RP", + /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 249 */ "raisetype ::= ROLLBACK", + /* 250 */ "raisetype ::= ABORT", + /* 251 */ "raisetype ::= FAIL", + /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 254 */ "cmd ::= DETACH database_kw_opt expr", + /* 255 */ "key_opt ::=", + /* 256 */ "key_opt ::= KEY expr", + /* 257 */ "cmd ::= REINDEX", + /* 258 */ "cmd ::= REINDEX nm dbnm", + /* 259 */ "cmd ::= ANALYZE", + /* 260 */ "cmd ::= ANALYZE nm dbnm", + /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 263 */ "add_column_fullname ::= fullname", + /* 264 */ "cmd ::= create_vtab", + /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 267 */ "vtabarg ::=", + /* 268 */ "vtabargtoken ::= ANY", + /* 269 */ "vtabargtoken ::= lp anylist RP", + /* 270 */ "lp ::= LP", + /* 271 */ "with ::=", + /* 272 */ "with ::= WITH wqlist", + /* 273 */ "with ::= WITH RECURSIVE wqlist", + /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 276 */ "input ::= cmdlist", + /* 277 */ "cmdlist ::= cmdlist ecmd", + /* 278 */ "cmdlist ::= ecmd", + /* 279 */ "ecmd ::= SEMI", + /* 280 */ "ecmd ::= explain cmdx SEMI", + /* 281 */ "explain ::=", + /* 282 */ "trans_opt ::=", + /* 283 */ "trans_opt ::= TRANSACTION", + /* 284 */ "trans_opt ::= TRANSACTION nm", + /* 285 */ "savepoint_opt ::= SAVEPOINT", + /* 286 */ "savepoint_opt ::=", + /* 287 */ "cmd ::= create_table create_table_args", + /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 289 */ "columnlist ::= columnname carglist", + /* 290 */ "nm ::= ID|INDEXED", + /* 291 */ "nm ::= STRING", + /* 292 */ "nm ::= JOIN_KW", + /* 293 */ "typetoken ::= typename", + /* 294 */ "typename ::= ID|STRING", + /* 295 */ "signed ::= plus_num", + /* 296 */ "signed ::= minus_num", + /* 297 */ "carglist ::= carglist ccons", + /* 298 */ "carglist ::=", + /* 299 */ "ccons ::= NULL onconf", + /* 300 */ "conslist_opt ::= COMMA conslist", + /* 301 */ "conslist ::= conslist tconscomma tcons", + /* 302 */ "conslist ::= tcons", + /* 303 */ "tconscomma ::=", + /* 304 */ "defer_subclause_opt ::= defer_subclause", + /* 305 */ "resolvetype ::= raisetype", + /* 306 */ "selectnowith ::= oneselect", + /* 307 */ "oneselect ::= values", + /* 308 */ "sclp ::= selcollist COMMA", + /* 309 */ "as ::= ID|STRING", + /* 310 */ "expr ::= term", + /* 311 */ "exprlist ::= nexprlist", + /* 312 */ "nmnum ::= plus_num", + /* 313 */ "nmnum ::= nm", + /* 314 */ "nmnum ::= ON", + /* 315 */ "nmnum ::= DELETE", + /* 316 */ "nmnum ::= DEFAULT", + /* 317 */ "plus_num ::= INTEGER|FLOAT", + /* 318 */ "foreach_clause ::=", + /* 319 */ "foreach_clause ::= FOR EACH ROW", + /* 320 */ "trnm ::= nm", + /* 321 */ "tridxby ::=", + /* 322 */ "database_kw_opt ::= DATABASE", + /* 323 */ "database_kw_opt ::=", + /* 324 */ "kwcolumn_opt ::=", + /* 325 */ "kwcolumn_opt ::= COLUMNKW", + /* 326 */ "vtabarglist ::= vtabarg", + /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 328 */ "vtabarg ::= vtabarg vtabargtoken", + /* 329 */ "anylist ::=", + /* 330 */ "anylist ::= anylist LP anylist RP", + /* 331 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ @@ -133202,50 +135566,47 @@ static unsigned int yy_find_shift_action( assert( stateno <= YY_SHIFT_COUNT ); do{ i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; assert( iLookAhead!=YYNOCODE ); i += iLookAhead; if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } #endif #ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( + { + int j = i - iLookAhead + YYWILDCARD; + if( #if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 + ){ #ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* YYWILDCARD */ } +#endif /* YYWILDCARD */ return yy_default[stateno]; }else{ return yy_action[i]; @@ -133289,7 +135650,6 @@ static int yy_find_reduce_action( */ static void yyStackOverflow(yyParser *yypParser){ sqlite3ParserARG_FETCH; - yypParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); @@ -133344,12 +135704,14 @@ static void yy_shift( #endif #if YYSTACKDEPTH>0 if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ + yypParser->yytos--; yyStackOverflow(yypParser); return; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ if( yyGrowStack(yypParser) ){ + yypParser->yytos--; yyStackOverflow(yypParser); return; } @@ -133511,7 +135873,9 @@ static const struct { { 201, 2 }, { 149, 8 }, { 218, 5 }, + { 218, 7 }, { 218, 3 }, + { 218, 5 }, { 149, 6 }, { 149, 7 }, { 219, 2 }, @@ -133528,12 +135892,14 @@ static const struct { { 173, 5 }, { 172, 1 }, { 172, 1 }, + { 172, 1 }, { 173, 1 }, { 173, 3 }, { 173, 6 }, { 173, 5 }, { 173, 4 }, { 172, 1 }, + { 173, 5 }, { 173, 3 }, { 173, 3 }, { 173, 3 }, @@ -133821,7 +136187,7 @@ static void yy_reduce( case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); case 76: /* ifexists ::= */ yytestcase(yyruleno==76); case 90: /* distinct ::= */ yytestcase(yyruleno==90); - case 211: /* collate ::= */ yytestcase(yyruleno==211); + case 215: /* collate ::= */ yytestcase(yyruleno==215); {yymsp[1].minor.yy194 = 0;} break; case 17: /* ifnotexists ::= IF NOT EXISTS */ @@ -133887,7 +136253,7 @@ static void yy_reduce( case 33: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); v.zStart = yymsp[-1].minor.yy0.z; v.zEnd = yymsp[0].minor.yy190.zEnd; sqlite3AddDefaultValue(pParse,&v); @@ -133960,14 +136326,14 @@ static void yy_reduce( break; case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); - case 142: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==142); + case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} break; case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); - case 183: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==183); - case 186: /* in_op ::= NOT IN */ yytestcase(yyruleno==186); - case 212: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==212); + case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); + case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); + case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); {yymsp[-1].minor.yy194 = 1;} break; case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ @@ -134003,7 +136369,7 @@ static void yy_reduce( {yymsp[0].minor.yy194 = OE_Ignore;} break; case 73: /* resolvetype ::= REPLACE */ - case 143: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==143); + case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145); {yymsp[0].minor.yy194 = OE_Replace;} break; case 74: /* cmd ::= DROP TABLE ifexists fullname */ @@ -134131,9 +136497,9 @@ static void yy_reduce( case 91: /* sclp ::= */ case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); - case 199: /* exprlist ::= */ yytestcase(yyruleno==199); - case 202: /* paren_exprlist ::= */ yytestcase(yyruleno==202); - case 207: /* eidlist_opt ::= */ yytestcase(yyruleno==207); + case 203: /* exprlist ::= */ yytestcase(yyruleno==203); + case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); + case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); {yymsp[1].minor.yy148 = 0;} break; case 92: /* selcollist ::= sclp expr as */ @@ -134151,16 +136517,16 @@ static void yy_reduce( break; case 94: /* selcollist ::= sclp nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &yymsp[0].minor.yy0); - Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); + Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); } break; case 95: /* as ::= AS nm */ case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); - case 221: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==221); - case 222: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==222); + case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); + case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; case 97: /* from ::= */ @@ -134243,14 +136609,14 @@ static void yy_reduce( case 112: /* on_opt ::= ON expr */ case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); - case 195: /* case_else ::= ELSE expr */ yytestcase(yyruleno==195); + case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} break; case 113: /* on_opt ::= */ case 128: /* having_opt ::= */ yytestcase(yyruleno==128); case 135: /* where_opt ::= */ yytestcase(yyruleno==135); - case 196: /* case_else ::= */ yytestcase(yyruleno==196); - case 198: /* case_operand ::= */ yytestcase(yyruleno==198); + case 200: /* case_else ::= */ yytestcase(yyruleno==200); + case 202: /* case_operand ::= */ yytestcase(yyruleno==202); {yymsp[1].minor.yy72 = 0;} break; case 115: /* indexed_opt ::= INDEXED BY nm */ @@ -134263,7 +136629,7 @@ static void yy_reduce( {yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} break; case 118: /* using_opt ::= */ - case 144: /* idlist_opt ::= */ yytestcase(yyruleno==144); + case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146); {yymsp[1].minor.yy254 = 0;} break; case 120: /* orderby_opt ::= ORDER BY sortlist */ @@ -134324,69 +136690,89 @@ static void yy_reduce( sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1); } break; - case 139: /* setlist ::= nm EQ expr */ + case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ +{ + yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); +} + break; + case 140: /* setlist ::= nm EQ expr */ { yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr); sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1); } yymsp[-2].minor.yy148 = yylhsminor.yy148; break; - case 140: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 141: /* setlist ::= LP idlist RP EQ expr */ +{ + yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); +} + break; + case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ { sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194); } break; - case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 143: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ { sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); } break; - case 145: /* idlist_opt ::= LP idlist RP */ + case 147: /* idlist_opt ::= LP idlist RP */ {yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} break; - case 146: /* idlist ::= idlist COMMA nm */ + case 148: /* idlist ::= idlist COMMA nm */ {yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} break; - case 147: /* idlist ::= nm */ + case 149: /* idlist ::= nm */ {yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 148: /* expr ::= LP expr RP */ + case 150: /* expr ::= LP expr RP */ {spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} break; - case 149: /* term ::= NULL */ - case 154: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==154); - case 155: /* term ::= STRING */ yytestcase(yyruleno==155); + case 151: /* term ::= NULL */ + case 156: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==156); + case 157: /* term ::= STRING */ yytestcase(yyruleno==157); {spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} break; - case 150: /* expr ::= ID|INDEXED */ - case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); + case 152: /* expr ::= ID|INDEXED */ + case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); {spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 152: /* expr ::= nm DOT nm */ + case 154: /* expr ::= nm DOT nm */ { - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } break; - case 153: /* expr ::= nm DOT nm DOT nm */ + case 155: /* expr ::= nm DOT nm DOT nm */ { - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } break; - case 156: /* expr ::= VARIABLE */ + case 158: /* term ::= INTEGER */ +{ + yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; + yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; + if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; +} + yymsp[0].minor.yy190 = yylhsminor.yy190; + break; + case 159: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ + u32 n = yymsp[0].minor.yy0.n; spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -134398,25 +136784,26 @@ static void yy_reduce( sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); yymsp[0].minor.yy190.pExpr = 0; }else{ - yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t); + yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); } } } break; - case 157: /* expr ::= expr COLLATE ID|STRING */ + case 160: /* expr ::= expr COLLATE ID|STRING */ { yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 158: /* expr ::= CAST LP expr AS typetoken RP */ + case 161: /* expr ::= CAST LP expr AS typetoken RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); } break; - case 159: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); @@ -134429,96 +136816,113 @@ static void yy_reduce( } yymsp[-4].minor.yy190 = yylhsminor.yy190; break; - case 160: /* expr ::= ID|INDEXED LP STAR RP */ + case 163: /* expr ::= ID|INDEXED LP STAR RP */ { yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } yymsp[-3].minor.yy190 = yylhsminor.yy190; break; - case 161: /* term ::= CTIME_KW */ + case 164: /* term ::= CTIME_KW */ { yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } yymsp[0].minor.yy190 = yylhsminor.yy190; break; - case 162: /* expr ::= expr AND expr */ - case 163: /* expr ::= expr OR expr */ yytestcase(yyruleno==163); - case 164: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==164); - case 165: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==165); - case 166: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==166); - case 167: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==167); - case 168: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==168); - case 169: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==169); + case 165: /* expr ::= LP nexprlist COMMA expr RP */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); + yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yylhsminor.yy190.pExpr ){ + yylhsminor.yy190.pExpr->x.pList = pList; + spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } +} + yymsp[-4].minor.yy190 = yylhsminor.yy190; + break; + case 166: /* expr ::= expr AND expr */ + case 167: /* expr ::= expr OR expr */ yytestcase(yyruleno==167); + case 168: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==168); + case 169: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==169); + case 170: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==170); + case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); + case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); + case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} break; - case 170: /* likeop ::= LIKE_KW|MATCH */ -{yymsp[0].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[0].minor.yy392.bNot = 0;/*A-overwrites-X*/} + case 174: /* likeop ::= LIKE_KW|MATCH */ +{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} break; - case 171: /* likeop ::= NOT LIKE_KW|MATCH */ -{yymsp[-1].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[-1].minor.yy392.bNot = 1;} + case 175: /* likeop ::= NOT LIKE_KW|MATCH */ +{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 172: /* expr ::= expr likeop expr */ + case 176: /* expr ::= expr likeop expr */ { ExprList *pList; + int bNot = yymsp[-1].minor.yy0.n & 0x80000000; + yymsp[-1].minor.yy0.n &= 0x7fffffff; pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); - yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy392.eOperator); - exprNot(pParse, yymsp[-1].minor.yy392.bNot, &yymsp[-2].minor.yy190); + yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); + exprNot(pParse, bNot, &yymsp[-2].minor.yy190); yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 173: /* expr ::= expr likeop expr ESCAPE expr */ + case 177: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; + int bNot = yymsp[-3].minor.yy0.n & 0x80000000; + yymsp[-3].minor.yy0.n &= 0x7fffffff; pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy392.eOperator); - exprNot(pParse, yymsp[-3].minor.yy392.bNot, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); + exprNot(pParse, bNot, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 174: /* expr ::= expr ISNULL|NOTNULL */ + case 178: /* expr ::= expr ISNULL|NOTNULL */ {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} break; - case 175: /* expr ::= expr NOT NULL */ + case 179: /* expr ::= expr NOT NULL */ {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} break; - case 176: /* expr ::= expr IS expr */ + case 180: /* expr ::= expr IS expr */ { spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); } break; - case 177: /* expr ::= expr IS NOT expr */ + case 181: /* expr ::= expr IS NOT expr */ { spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); } break; - case 178: /* expr ::= NOT expr */ - case 179: /* expr ::= BITNOT expr */ yytestcase(yyruleno==179); + case 182: /* expr ::= NOT expr */ + case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 180: /* expr ::= MINUS expr */ + case 184: /* expr ::= MINUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 181: /* expr ::= PLUS expr */ + case 185: /* expr ::= PLUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 182: /* between_op ::= BETWEEN */ - case 185: /* in_op ::= IN */ yytestcase(yyruleno==185); + case 186: /* between_op ::= BETWEEN */ + case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); {yymsp[0].minor.yy194 = 0;} break; - case 184: /* expr ::= expr between_op expr AND expr */ + case 188: /* expr ::= expr between_op expr AND expr */ { ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = pList; }else{ @@ -134528,7 +136932,7 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; } break; - case 187: /* expr ::= expr in_op LP exprlist RP */ + case 191: /* expr ::= expr in_op LP exprlist RP */ { if( yymsp[-1].minor.yy148==0 ){ /* Expressions of the form @@ -134540,7 +136944,7 @@ static void yy_reduce( ** regardless of the value of expr1. */ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy194]); + yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1); }else if( yymsp[-1].minor.yy148->nExpr==1 ){ /* Expressions of the form: ** @@ -134567,9 +136971,9 @@ static void yy_reduce( pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS); }else{ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148; sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); @@ -134581,44 +136985,44 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 188: /* expr ::= LP select RP */ + case 192: /* expr ::= LP select RP */ { spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); } break; - case 189: /* expr ::= expr in_op LP select RP */ + case 193: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 190: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; } break; - case 191: /* expr ::= EXISTS LP select RP */ + case 195: /* expr ::= EXISTS LP select RP */ { Expr *p; spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); } break; - case 192: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ { spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); @@ -134628,78 +137032,80 @@ static void yy_reduce( } } break; - case 193: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 194: /* case_exprlist ::= WHEN expr THEN expr */ + case 198: /* case_exprlist ::= WHEN expr THEN expr */ { yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 197: /* case_operand ::= expr */ + case 201: /* case_operand ::= expr */ {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} break; - case 200: /* nexprlist ::= nexprlist COMMA expr */ + case 204: /* nexprlist ::= nexprlist COMMA expr */ {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} break; - case 201: /* nexprlist ::= expr */ + case 205: /* nexprlist ::= expr */ {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} break; - case 203: /* paren_exprlist ::= LP exprlist RP */ - case 208: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==208); + case 207: /* paren_exprlist ::= LP exprlist RP */ + case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} break; - case 204: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); } break; - case 205: /* uniqueflag ::= UNIQUE */ - case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246); + case 209: /* uniqueflag ::= UNIQUE */ + case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); {yymsp[0].minor.yy194 = OE_Abort;} break; - case 206: /* uniqueflag ::= */ + case 210: /* uniqueflag ::= */ {yymsp[1].minor.yy194 = OE_None;} break; - case 209: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ { yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); } break; - case 210: /* eidlist ::= nm collate sortorder */ + case 214: /* eidlist ::= nm collate sortorder */ { yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ } break; - case 213: /* cmd ::= DROP INDEX ifexists fullname */ + case 217: /* cmd ::= DROP INDEX ifexists fullname */ {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} break; - case 214: /* cmd ::= VACUUM */ - case 215: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==215); -{sqlite3Vacuum(pParse);} + case 218: /* cmd ::= VACUUM */ +{sqlite3Vacuum(pParse,0);} break; - case 216: /* cmd ::= PRAGMA nm dbnm */ + case 219: /* cmd ::= VACUUM nm */ +{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} + break; + case 220: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 217: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 218: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 219: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 220: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 223: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; @@ -134707,53 +137113,53 @@ static void yy_reduce( sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); } break; - case 224: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 225: /* trigger_time ::= BEFORE */ + case 229: /* trigger_time ::= BEFORE */ { yymsp[0].minor.yy194 = TK_BEFORE; } break; - case 226: /* trigger_time ::= AFTER */ + case 230: /* trigger_time ::= AFTER */ { yymsp[0].minor.yy194 = TK_AFTER; } break; - case 227: /* trigger_time ::= INSTEAD OF */ + case 231: /* trigger_time ::= INSTEAD OF */ { yymsp[-1].minor.yy194 = TK_INSTEAD;} break; - case 228: /* trigger_time ::= */ + case 232: /* trigger_time ::= */ { yymsp[1].minor.yy194 = TK_BEFORE; } break; - case 229: /* trigger_event ::= DELETE|INSERT */ - case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230); + case 233: /* trigger_event ::= DELETE|INSERT */ + case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} break; - case 231: /* trigger_event ::= UPDATE OF idlist */ + case 235: /* trigger_event ::= UPDATE OF idlist */ {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} break; - case 232: /* when_clause ::= */ - case 251: /* key_opt ::= */ yytestcase(yyruleno==251); + case 236: /* when_clause ::= */ + case 255: /* key_opt ::= */ yytestcase(yyruleno==255); { yymsp[1].minor.yy72 = 0; } break; - case 233: /* when_clause ::= WHEN expr */ - case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252); + case 237: /* when_clause ::= WHEN expr */ + case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } break; - case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { assert( yymsp[-2].minor.yy145!=0 ); yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ { assert( yymsp[-1].minor.yy145!=0 ); yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 236: /* trnm ::= nm DOT nm */ + case 240: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -134761,195 +137167,195 @@ static void yy_reduce( "statements within triggers"); } break; - case 237: /* tridxby ::= INDEXED BY nm */ + case 241: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 238: /* tridxby ::= NOT INDEXED */ + case 242: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ + case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} break; - case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ + case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} break; - case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ + case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} break; - case 242: /* trigger_cmd ::= select */ + case 246: /* trigger_cmd ::= select */ {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} break; - case 243: /* expr ::= RAISE LP IGNORE RP */ + case 247: /* expr ::= RAISE LP IGNORE RP */ { spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); if( yymsp[-3].minor.yy190.pExpr ){ yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; } } break; - case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); if( yymsp[-5].minor.yy190.pExpr ) { yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; } } break; - case 245: /* raisetype ::= ROLLBACK */ + case 249: /* raisetype ::= ROLLBACK */ {yymsp[0].minor.yy194 = OE_Rollback;} break; - case 247: /* raisetype ::= FAIL */ + case 251: /* raisetype ::= FAIL */ {yymsp[0].minor.yy194 = OE_Fail;} break; - case 248: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ { sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); } break; - case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); } break; - case 250: /* cmd ::= DETACH database_kw_opt expr */ + case 254: /* cmd ::= DETACH database_kw_opt expr */ { sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); } break; - case 253: /* cmd ::= REINDEX */ + case 257: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 254: /* cmd ::= REINDEX nm dbnm */ + case 258: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 255: /* cmd ::= ANALYZE */ + case 259: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 256: /* cmd ::= ANALYZE nm dbnm */ + case 260: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); } break; - case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 259: /* add_column_fullname ::= fullname */ + case 263: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); } break; - case 260: /* cmd ::= create_vtab */ + case 264: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 261: /* cmd ::= create_vtab LP vtabarglist RP */ + case 265: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); } break; - case 263: /* vtabarg ::= */ + case 267: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 264: /* vtabargtoken ::= ANY */ - case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265); - case 266: /* lp ::= LP */ yytestcase(yyruleno==266); + case 268: /* vtabargtoken ::= ANY */ + case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); + case 270: /* lp ::= LP */ yytestcase(yyruleno==270); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 267: /* with ::= */ + case 271: /* with ::= */ {yymsp[1].minor.yy285 = 0;} break; - case 268: /* with ::= WITH wqlist */ + case 272: /* with ::= WITH wqlist */ { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } break; - case 269: /* with ::= WITH RECURSIVE wqlist */ + case 273: /* with ::= WITH RECURSIVE wqlist */ { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } break; - case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ { yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ } break; - case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); } break; default: - /* (272) input ::= cmdlist */ yytestcase(yyruleno==272); - /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273); - /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274); - /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275); - /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276); - /* (277) explain ::= */ yytestcase(yyruleno==277); - /* (278) trans_opt ::= */ yytestcase(yyruleno==278); - /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279); - /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280); - /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281); - /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282); - /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283); - /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284); - /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285); - /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286); - /* (287) nm ::= STRING */ yytestcase(yyruleno==287); - /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288); - /* (289) typetoken ::= typename */ yytestcase(yyruleno==289); - /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290); - /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291); - /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); - /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293); - /* (294) carglist ::= */ yytestcase(yyruleno==294); - /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295); - /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296); - /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297); - /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298); - /* (299) tconscomma ::= */ yytestcase(yyruleno==299); - /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300); - /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301); - /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302); - /* (303) oneselect ::= values */ yytestcase(yyruleno==303); - /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304); - /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305); - /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306); - /* (307) exprlist ::= nexprlist */ yytestcase(yyruleno==307); - /* (308) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=308); - /* (309) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=309); - /* (310) nmnum ::= ON */ yytestcase(yyruleno==310); - /* (311) nmnum ::= DELETE */ yytestcase(yyruleno==311); - /* (312) nmnum ::= DEFAULT */ yytestcase(yyruleno==312); - /* (313) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==313); - /* (314) foreach_clause ::= */ yytestcase(yyruleno==314); - /* (315) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==315); - /* (316) trnm ::= nm */ yytestcase(yyruleno==316); - /* (317) tridxby ::= */ yytestcase(yyruleno==317); - /* (318) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==318); - /* (319) database_kw_opt ::= */ yytestcase(yyruleno==319); - /* (320) kwcolumn_opt ::= */ yytestcase(yyruleno==320); - /* (321) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==321); - /* (322) vtabarglist ::= vtabarg */ yytestcase(yyruleno==322); - /* (323) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==323); - /* (324) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==324); - /* (325) anylist ::= */ yytestcase(yyruleno==325); - /* (326) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==326); - /* (327) anylist ::= anylist ANY */ yytestcase(yyruleno==327); + /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); + /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); + /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); + /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); + /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); + /* (281) explain ::= */ yytestcase(yyruleno==281); + /* (282) trans_opt ::= */ yytestcase(yyruleno==282); + /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); + /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); + /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); + /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); + /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); + /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); + /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); + /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); + /* (291) nm ::= STRING */ yytestcase(yyruleno==291); + /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); + /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); + /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); + /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); + /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); + /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); + /* (298) carglist ::= */ yytestcase(yyruleno==298); + /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); + /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); + /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); + /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); + /* (303) tconscomma ::= */ yytestcase(yyruleno==303); + /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); + /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); + /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); + /* (307) oneselect ::= values */ yytestcase(yyruleno==307); + /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); + /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); + /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); + /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); + /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); + /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); + /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); + /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); + /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); + /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); + /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); + /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); + /* (320) trnm ::= nm */ yytestcase(yyruleno==320); + /* (321) tridxby ::= */ yytestcase(yyruleno==321); + /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); + /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); + /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); + /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); + /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); + /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); + /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); + /* (329) anylist ::= */ yytestcase(yyruleno==329); + /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); + /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); break; /********** End reduce actions ************************************************/ }; @@ -135140,7 +137546,7 @@ SQLITE_PRIVATE void sqlite3Parser( yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ - while( yypParser->yytos >= &yypParser->yystack + while( yypParser->yytos >= yypParser->yystack && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, @@ -135298,13 +137704,13 @@ static const unsigned char aiClass[] = { /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10, /* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, -/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6, /* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, /* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, /* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, -/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, /* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, /* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, /* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, @@ -136006,16 +138412,27 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); - assert( pParse->nzVar==0 ); - assert( pParse->azVar==0 ); - while( zSql[i]!=0 ){ + assert( pParse->pVList==0 ); + while( 1 ){ assert( i>=0 ); - pParse->sLastToken.z = &zSql[i]; - pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); - i += pParse->sLastToken.n; - if( i>mxSqlLen ){ - pParse->rc = SQLITE_TOOBIG; - break; + if( zSql[i]!=0 ){ + pParse->sLastToken.z = &zSql[i]; + pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType); + i += pParse->sLastToken.n; + if( i>mxSqlLen ){ + pParse->rc = SQLITE_TOOBIG; + break; + } + }else{ + /* Upon reaching the end of input, call the parser two more times + ** with tokens TK_SEMI and 0, in that order. */ + if( lastTokenParsed==TK_SEMI ){ + tokenType = 0; + }else if( lastTokenParsed==0 ){ + break; + }else{ + tokenType = TK_SEMI; + } } if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); @@ -136036,15 +138453,6 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr } assert( nErr==0 ); pParse->zTail = &zSql[i]; - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - assert( zSql[i]==0 ); - if( lastTokenParsed!=TK_SEMI ){ - sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); - } - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); - } - } #ifdef YYTRACKMAXSTACKDEPTH sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, @@ -136091,8 +138499,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); sqlite3DeleteTrigger(db, pParse->pNewTrigger); - for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); - sqlite3DbFree(db, pParse->azVar); + sqlite3DbFree(db, pParse->pVList); while( pParse->pAinc ){ AutoincInfo *p = pParse->pAinc; pParse->pAinc = p->pNext; @@ -136212,7 +138619,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ +SQLITE_API int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ @@ -136377,7 +138784,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ +SQLITE_API int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; int rc; @@ -136537,24 +138944,24 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; /* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns ** a pointer to the to the sqlite3_version[] string constant. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void){ return sqlite3_version; } +SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } /* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the ** SQLITE_SOURCE_ID C preprocessor macro. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. */ -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } /* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns ** zero if and only if SQLite was compiled with mutexing code omitted due to ** the SQLITE_THREADSAFE compile-time option being set to 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } +SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } /* ** When compiling the test fixture or with debugging enabled (on Win32), @@ -136627,7 +139034,7 @@ SQLITE_API char *sqlite3_data_directory = 0; ** * Recursive calls to this routine from thread X return immediately ** without blocking. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ +SQLITE_API int sqlite3_initialize(void){ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ #ifdef SQLITE_EXTRA_INIT @@ -136793,7 +139200,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ +SQLITE_API int sqlite3_shutdown(void){ #ifdef SQLITE_OMIT_WSD int rc = sqlite3_wsd_init(4096, 24); if( rc!=SQLITE_OK ){ @@ -136847,7 +139254,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ +SQLITE_API int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -137212,7 +139619,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ /* ** Return the mutex associated with a database connection. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -137226,7 +139633,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ ** Free up as much memory as we can from the given database ** connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ +SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ int i; #ifdef SQLITE_ENABLE_API_ARMOR @@ -137250,7 +139657,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ ** Flush any dirty pages in the pager-cache for any attached database ** to disk. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3 *db){ +SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){ int i; int rc = SQLITE_OK; int bSeenBusy = 0; @@ -137279,11 +139686,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3 *db){ /* ** Configuration settings for an individual database connection */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; va_start(ap, op); switch( op ){ + case SQLITE_DBCONFIG_MAINDBNAME: { + db->aDb[0].zDbSName = va_arg(ap,char*); + rc = SQLITE_OK; + break; + } case SQLITE_DBCONFIG_LOOKASIDE: { void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ @@ -137300,6 +139712,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -137400,7 +139813,7 @@ static int nocaseCollatingFunc( /* ** Return the ROWID of the most recent insert */ -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){ +SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -137413,7 +139826,7 @@ SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){ /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ +SQLITE_API int sqlite3_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -137426,7 +139839,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ /* ** Return the number of changes since the database handle was opened. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3 *db){ +SQLITE_API int sqlite3_total_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -137577,8 +139990,8 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } +SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } +SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } /* @@ -137985,7 +140398,7 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( +SQLITE_API int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg @@ -138008,7 +140421,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( +SQLITE_API void sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), @@ -138039,7 +140452,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ +SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -138055,9 +140468,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ /* ** Cause any pending operation to stop at its earliest opportunity. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3 *db){ +SQLITE_API void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ + if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){ (void)SQLITE_MISUSE_BKPT; return; } @@ -138171,7 +140584,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( /* ** Create new user functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunc, int nArg, @@ -138185,7 +140598,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( xFinal, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, @@ -138228,7 +140641,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -138268,7 +140681,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( ** A global function must exist in order for name resolution to work ** properly. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( +SQLITE_API int sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg @@ -138300,7 +140713,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( ** SQL statement. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){ +SQLITE_API void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){ void *pOld; #ifdef SQLITE_ENABLE_API_ARMOR @@ -138321,7 +140734,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,c /* Register a trace callback using the version-2 interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( +SQLITE_API int sqlite3_trace_v2( sqlite3 *db, /* Trace this connection */ unsigned mTrace, /* Mask of events to be traced */ int(*xTrace)(unsigned,void*,void*,void*), /* Callback to invoke */ @@ -138333,6 +140746,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( } #endif sqlite3_mutex_enter(db->mutex); + if( mTrace==0 ) xTrace = 0; + if( xTrace==0 ) mTrace = 0; db->mTrace = mTrace; db->xTrace = xTrace; db->pTraceArg = pArg; @@ -138349,7 +140764,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( ** profile is a pointer to a function that is invoked at the conclusion of ** each SQL statement that is run. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_profile( +SQLITE_API void *sqlite3_profile( sqlite3 *db, void (*xProfile)(void*,const char*,sqlite_uint64), void *pArg @@ -138377,7 +140792,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_profile( ** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( +SQLITE_API void *sqlite3_commit_hook( sqlite3 *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ @@ -138402,7 +140817,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ @@ -138427,7 +140842,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** Register a callback to be invoked each time a transaction is rolled ** back by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( +SQLITE_API void *sqlite3_rollback_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*), /* Callback function */ void *pArg /* Argument to the function */ @@ -138453,7 +140868,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_preupdate_hook( +SQLITE_API void *sqlite3_preupdate_hook( sqlite3 *db, /* Attach the hook to this database */ void(*xCallback)( /* Callback function */ void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), @@ -138502,7 +140917,7 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook( ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism ** configured by this function. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ #ifdef SQLITE_OMIT_WAL UNUSED_PARAMETER(db); UNUSED_PARAMETER(nFrame); @@ -138523,7 +140938,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3 *db, /* Attach the hook to this db handle */ int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ @@ -138550,7 +140965,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( /* ** Checkpoint database zDb. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -138594,6 +141009,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( sqlite3Error(db, rc); } rc = sqlite3ApiExit(db, rc); + + /* If there are no active statements, clear the interrupt flag at this + ** point. */ + if( db->nVdbeActive==0 ){ + db->u1.isInterrupted = 0; + } + sqlite3_mutex_leave(db->mutex); return rc; #endif @@ -138605,7 +141027,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** to contains a zero-length string, all attached databases are ** checkpointed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); @@ -138696,7 +141118,7 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ ** Return UTF-8 encoded English language explanation of the most recent ** error. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ +SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM_BKPT); @@ -138724,7 +141146,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ ** Return UTF-16 encoded English language explanation of the most recent ** error. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ +SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ static const u16 outOfMem[] = { 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 }; @@ -138769,7 +141191,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -138778,7 +141200,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ } return db->errCode & db->errMask; } -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -138787,7 +141209,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ } return db->errCode; } -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3 *db){ +SQLITE_API int sqlite3_system_errno(sqlite3 *db){ return db ? db->iSysErrno : 0; } @@ -138796,7 +141218,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3 *db){ ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int rc){ +SQLITE_API const char *sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } @@ -138944,7 +141366,7 @@ static const int aHardLimit[] = { ** It merely prevents new constructs that exceed the limit ** from forming. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ +SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ int oldLimit; #ifdef SQLITE_ENABLE_API_ARMOR @@ -139096,6 +141518,7 @@ SQLITE_PRIVATE int sqlite3ParseUri( assert( octet>=0 && octet<256 ); if( octet==0 ){ +#ifndef SQLITE_ENABLE_URI_00_ERROR /* This branch is taken when "%00" appears within the URI. In this ** case we ignore all text in the remainder of the path, name or ** value currently being parsed. So ignore the current character @@ -139108,6 +141531,12 @@ SQLITE_PRIVATE int sqlite3ParseUri( iIn++; } continue; +#else + /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ + *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); + rc = SQLITE_ERROR; + goto parse_uri_out; +#endif } c = octet; }else if( eState==1 && (c=='&' || c=='=') ){ @@ -139212,7 +141641,9 @@ SQLITE_PRIVATE int sqlite3ParseUri( }else{ zFile = sqlite3_malloc64(nUri+2); if( !zFile ) return SQLITE_NOMEM_BKPT; - memcpy(zFile, zUri, nUri); + if( nUri ){ + memcpy(zFile, zUri, nUri); + } zFile[nUri] = '\0'; zFile[nUri+1] = '\0'; flags &= ~SQLITE_OPEN_URI; @@ -139427,9 +141858,9 @@ static int openDatabase( /* The default safety_level for the main database is FULL; for the temp ** database it is OFF. This matches the pager layer defaults. */ - db->aDb[0].zName = "main"; + db->aDb[0].zDbSName = "main"; db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - db->aDb[1].zName = "temp"; + db->aDb[1].zDbSName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; db->magic = SQLITE_MAGIC_OPEN; @@ -139443,11 +141874,20 @@ static int openDatabase( */ sqlite3Error(db, SQLITE_OK); sqlite3RegisterPerConnectionBuiltinFunctions(db); + rc = sqlite3_errcode(db); + +#ifdef SQLITE_ENABLE_FTS5 + /* Register any built-in FTS5 module before loading the automatic + ** extensions. This allows automatic extensions to register FTS5 + ** tokenizers and auxiliary functions. */ + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts5Init(db); + } +#endif /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ - rc = sqlite3_errcode(db); if( rc==SQLITE_OK ){ sqlite3AutoLoadExtensions(db); rc = sqlite3_errcode(db); @@ -139476,12 +141916,6 @@ static int openDatabase( } #endif -#ifdef SQLITE_ENABLE_FTS5 - if( !db->mallocFailed && rc==SQLITE_OK ){ - rc = sqlite3Fts5Init(db); - } -#endif - #ifdef SQLITE_ENABLE_ICU if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3IcuInit(db); @@ -139568,14 +142002,14 @@ opendb_out: /* ** Open a new database handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *zFilename, sqlite3 **ppDb ){ return openDatabase(zFilename, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -139588,7 +142022,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( /* ** Open a new database handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *zFilename, sqlite3 **ppDb ){ @@ -139627,7 +142061,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open16( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3* db, const char *zName, int enc, @@ -139640,7 +142074,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3* db, const char *zName, int enc, @@ -139665,7 +142099,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3* db, const void *zName, int enc, @@ -139695,7 +142129,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) @@ -139716,7 +142150,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) @@ -139738,7 +142172,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** This function is now an anachronism. It used to be used to recover from a ** malloc() failure, but SQLite now does this automatically. */ -SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ +SQLITE_API int sqlite3_global_recover(void){ return SQLITE_OK; } #endif @@ -139749,7 +142183,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3 *db){ +SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -139806,7 +142240,7 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ ** SQLite no longer uses thread-specific data so this routine is now a ** no-op. It is retained for historical compatibility. */ -SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ +SQLITE_API void sqlite3_thread_cleanup(void){ } #endif @@ -139814,7 +142248,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ ** Return meta information about a specific column of a database table. ** See comment in sqlite3.h (sqlite.h.in) for details. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -139932,7 +142366,7 @@ error_out: /* ** Sleep for a little while. Return the amount of time slept. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ +SQLITE_API int sqlite3_sleep(int ms){ sqlite3_vfs *pVfs; int rc; pVfs = sqlite3_vfs_find(0); @@ -139948,7 +142382,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ /* ** Enable or disable the extended result codes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int onoff){ +SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -139961,7 +142395,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int ono /* ** Invoke the xFileControl method on a particular database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ +SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ int rc = SQLITE_ERROR; Btree *pBtree; @@ -140001,9 +142435,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbN /* ** Interface to the testing logic. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ +SQLITE_API int sqlite3_test_control(int op, ...){ int rc = 0; -#ifdef SQLITE_OMIT_BUILTIN_TEST +#ifdef SQLITE_UNTESTABLE UNUSED_PARAMETER(op); #else va_list ap; @@ -140269,6 +142703,15 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ break; } + /* Set the threshold at which OP_Once counters reset back to zero. + ** By default this is 0x7ffffffe (over 2 billion), but that value is + ** too big to test in a reasonable amount of time, so this control is + ** provided to set a small and easily reachable reset value. + */ + case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: { + sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int); + break; + } /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); ** @@ -140331,7 +142774,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ } } va_end(ap); -#endif /* SQLITE_OMIT_BUILTIN_TEST */ +#endif /* SQLITE_UNTESTABLE */ return rc; } @@ -140346,7 +142789,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam){ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ if( zFilename==0 || zParam==0 ) return 0; zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ @@ -140361,7 +142804,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilenam /* ** Return a boolean value for a query parameter. */ -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ +SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ const char *z = sqlite3_uri_parameter(zFilename, zParam); bDflt = bDflt!=0; return z ? sqlite3GetBoolean(z, bDflt) : bDflt; @@ -140370,7 +142813,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const c /* ** Return a 64-bit integer value for a query parameter. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64( +SQLITE_API sqlite3_int64 sqlite3_uri_int64( const char *zFilename, /* Filename as passed to xOpen */ const char *zParam, /* URI parameter sought */ sqlite3_int64 bDflt /* return if parameter is missing */ @@ -140387,22 +142830,15 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64( ** Return the Btree pointer identified by zDbName. Return NULL if not found. */ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ - int i; - for(i=0; inDb; i++){ - if( db->aDb[i].pBt - && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) - ){ - return db->aDb[i].pBt; - } - } - return 0; + int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; + return iDb<0 ? 0 : db->aDb[iDb].pBt; } /* ** Return the filename of the database associated with a database ** connection. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName){ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -140418,7 +142854,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** Return 1 if database is read-only or 0 if read/write. Return -1 if ** no such database exists. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -140435,14 +142871,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** Obtain a snapshot handle for the snapshot of database zDb currently ** being read by handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API int sqlite3_snapshot_get( sqlite3 *db, const char *zDb, sqlite3_snapshot **ppSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL - int iDb; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -140451,13 +142886,15 @@ SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( #endif sqlite3_mutex_enter(db->mutex); - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( 0==sqlite3BtreeIsInTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); + if( db->autoCommit==0 ){ + int iDb = sqlite3FindDbName(db, zDb); + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); + } } } } @@ -140470,7 +142907,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( /* ** Open a read-transaction on the snapshot idendified by pSnapshot. */ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API int sqlite3_snapshot_open( sqlite3 *db, const char *zDb, sqlite3_snapshot *pSnapshot @@ -140504,10 +142941,42 @@ SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_open( return rc; } +/* +** Recover as many snapshots as possible from the wal file associated with +** schema zDb of database db. +*/ +SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ + int rc = SQLITE_ERROR; + int iDb; +#ifndef SQLITE_OMIT_WAL + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } +#endif + + sqlite3_mutex_enter(db->mutex); + iDb = sqlite3FindDbName(db, zDb); + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); + sqlite3BtreeCommit(pBt); + } + } + } + sqlite3_mutex_leave(db->mutex); +#endif /* SQLITE_OMIT_WAL */ + return rc; +} + /* ** Free a snapshot handle obtained from sqlite3_snapshot_get(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ +SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ @@ -140661,7 +143130,7 @@ static void leaveMutex(void){ ** on the same "db". If xNotify==0 then any prior callbacks are immediately ** cancelled. */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *db, void (*xNotify)(void **, int), void *pArg @@ -147664,7 +150133,7 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts3_init( +SQLITE_API int sqlite3_fts3_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -161505,7 +163974,7 @@ static int rtreeFilter( if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - RtreeSearchPoint *p; /* Search point for the the leaf */ + RtreeSearchPoint *p; /* Search point for the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); i64 iNode = 0; rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); @@ -162975,10 +165444,12 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){ int rc; i64 nRow = 0; - if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1", - 0,0,0,0,0,0)==SQLITE_ERROR ){ + rc = sqlite3_table_column_metadata( + db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 + ); + if( rc!=SQLITE_OK ){ pRtree->nRowEst = RTREE_DEFAULT_ROWEST; - return SQLITE_OK; + return rc==SQLITE_ERROR ? SQLITE_OK : rc; } zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); if( zSql==0 ){ @@ -163465,7 +165936,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ /* ** Register a new geometry function for use with the r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zGeom, /* Name of the new SQL function */ int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ @@ -163489,7 +165960,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( ** Register a new 2nd-generation geometry function for use with the ** r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zQueryFunc, /* Name of new SQL function */ int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ @@ -163514,7 +165985,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init( +SQLITE_API int sqlite3_rtree_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -163879,7 +166350,7 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ ** of upper() or lower(). ** ** lower('I', 'en_us') -> 'i' -** lower('I', 'tr_tr') -> 'ı' (small dotless i) +** lower('I', 'tr_tr') -> '\u131' (small dotless i) ** ** http://www.icu-project.org/userguide/posix.html#case_mappings */ @@ -164030,20 +166501,20 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ void *pContext; /* sqlite3_user_data() context */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } scalars[] = { - {"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc}, + {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, - {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16}, + {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, + {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, + {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16}, + {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16}, - {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16}, + {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, + {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, + {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16}, + {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16}, - {"like", 2, SQLITE_UTF8, 0, icuLikeFunc}, - {"like", 3, SQLITE_UTF8, 0, icuLikeFunc}, + {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, + {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation}, }; @@ -164065,7 +166536,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_icu_init( +SQLITE_API int sqlite3_icu_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -164541,7 +167012,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( ** may also be named data_, where is any sequence ** of zero or more numeric characters (0-9). This can be significant because ** tables within the RBU database are always processed in order sorted by -** name. By judicious selection of the the portion of the names +** name. By judicious selection of the portion of the names ** of the RBU tables the user can therefore control the order in which they ** are processed. This can be useful, for example, to ensure that "external ** content" FTS4 tables are updated before their underlying content tables. @@ -164745,7 +167216,7 @@ typedef struct sqlite3rbu sqlite3rbu; ** not work out of the box with zipvfs. Refer to the comment describing ** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. */ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( +SQLITE_API sqlite3rbu *sqlite3rbu_open( const char *zTarget, const char *zRbu, const char *zState @@ -164756,16 +167227,22 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( ** An RBU vacuum is similar to SQLite's built-in VACUUM command, except ** that it can be suspended and resumed like an RBU update. ** -** The second argument to this function, which may not be NULL, identifies -** a database in which to store the state of the RBU vacuum operation if -** it is suspended. The first time sqlite3rbu_vacuum() is called, to start -** an RBU vacuum operation, the state database should either not exist or -** be empty (contain no tables). If an RBU vacuum is suspended by calling +** The second argument to this function identifies a database in which +** to store the state of the RBU vacuum operation if it is suspended. The +** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum +** operation, the state database should either not exist or be empty +** (contain no tables). If an RBU vacuum is suspended by calling ** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has ** returned SQLITE_DONE, the vacuum state is stored in the state database. ** The vacuum can be resumed by calling this function to open a new RBU ** handle specifying the same target and state databases. ** +** If the second argument passed to this function is NULL, then the +** name of the state database is "-vacuum", where +** is the name of the target database file. In this case, on UNIX, if the +** state database is not already present in the file-system, it is created +** with the same permissions as the target db is made. +** ** This function does not delete the state database after an RBU vacuum ** is completed, even if it created it. However, if the call to ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents @@ -164778,7 +167255,7 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( ** a description of the complications associated with using RBU with ** zipvfs databases. */ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_vacuum( +SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( const char *zTarget, const char *zState ); @@ -164814,7 +167291,7 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_vacuum( ** Database handles returned by this function remain valid until the next ** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db(). */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); +SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu); /* ** Do some work towards applying the RBU update to the target db. @@ -164828,7 +167305,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); ** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops ** that immediately return the same value. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); +SQLITE_API int sqlite3rbu_step(sqlite3rbu *pRbu); /* ** Force RBU to save its state to disk. @@ -164840,7 +167317,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *pRbu); +SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu); /* ** Close an RBU handle. @@ -164860,14 +167337,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *pRbu); ** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); +SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); +SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); /* ** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) @@ -164909,7 +167386,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); ** table exists but is not correctly populated, the value of the *pnOne ** output variable during stage 1 is undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); /* ** Obtain an indication as to the current stage of an RBU update or vacuum. @@ -164947,7 +167424,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnO #define SQLITE_RBU_STATE_DONE 4 #define SQLITE_RBU_STATE_ERROR 5 -SQLITE_API int SQLITE_STDCALL sqlite3rbu_state(sqlite3rbu *pRbu); +SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu); /* ** Create an RBU VFS named zName that accesses the underlying file-system @@ -164991,7 +167468,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_state(sqlite3rbu *pRbu); ** file-system via "rbu" all the time, even if it only uses RBU functionality ** occasionally. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent); +SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent); /* ** Deregister and destroy an RBU vfs created by an earlier call to @@ -165001,7 +167478,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const cha ** before all database handles that use it have been closed, the results ** are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); +SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); #if 0 } /* end of the 'extern "C"' block */ @@ -167257,15 +169734,18 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ ** error occurs, leave an error code and message in the RBU handle. */ static void rbuOpenDatabase(sqlite3rbu *p){ - assert( p->rc==SQLITE_OK ); - assert( p->dbMain==0 && p->dbRbu==0 ); - assert( rbuIsVacuum(p) || p->zTarget!=0 ); + assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); + assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); /* Open the RBU database */ p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + if( p->zState==0 ){ + const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); + p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); + } } /* If using separate RBU and state databases, attach the state database to @@ -168095,7 +170575,7 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){ /* ** Step the RBU object. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *p){ +SQLITE_API int sqlite3rbu_step(sqlite3rbu *p){ if( p ){ switch( p->eStage ){ case RBU_STAGE_OAL: { @@ -168400,8 +170880,7 @@ static sqlite3rbu *openRbuHandle( sqlite3rbu *p; size_t nTarget = zTarget ? strlen(zTarget) : 0; size_t nRbu = strlen(zRbu); - size_t nState = zState ? strlen(zState) : 0; - size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1; + size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1; p = (sqlite3rbu*)sqlite3_malloc64(nByte); if( p ){ @@ -168423,8 +170902,7 @@ static sqlite3rbu *openRbuHandle( memcpy(p->zRbu, zRbu, nRbu+1); pCsr += nRbu+1; if( zState ){ - p->zState = pCsr; - memcpy(p->zState, zState, nState+1); + p->zState = rbuMPrintf(p, "%s", zState); } rbuOpenDatabase(p); } @@ -168534,14 +171012,29 @@ static sqlite3rbu *openRbuHandle( return p; } +/* +** Allocate and return an RBU handle with all fields zeroed except for the +** error code, which is set to SQLITE_MISUSE. +*/ +static sqlite3rbu *rbuMisuseError(void){ + sqlite3rbu *pRet; + pRet = sqlite3_malloc64(sizeof(sqlite3rbu)); + if( pRet ){ + memset(pRet, 0, sizeof(sqlite3rbu)); + pRet->rc = SQLITE_MISUSE; + } + return pRet; +} + /* ** Open and return a new RBU handle. */ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( +SQLITE_API sqlite3rbu *sqlite3rbu_open( const char *zTarget, const char *zRbu, const char *zState ){ + if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); } /* TODO: Check that zTarget and zRbu are non-NULL */ return openRbuHandle(zTarget, zRbu, zState); } @@ -168549,10 +171042,11 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( /* ** Open a handle to begin or resume an RBU VACUUM operation. */ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_vacuum( +SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( const char *zTarget, const char *zState ){ + if( zTarget==0 ){ return rbuMisuseError(); } /* TODO: Check that both arguments are non-NULL */ return openRbuHandle(0, zTarget, zState); } @@ -168560,7 +171054,7 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_vacuum( /* ** Return the database handle used by pRbu. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ +SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ sqlite3 *db = 0; if( pRbu ){ db = (bRbu ? pRbu->dbRbu : pRbu->dbMain); @@ -168592,7 +171086,7 @@ static void rbuEditErrmsg(sqlite3rbu *p){ /* ** Close the RBU handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ +SQLITE_API int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ int rc; if( p ){ @@ -168630,6 +171124,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ rbuEditErrmsg(p); rc = p->rc; *pzErrmsg = p->zErrmsg; + sqlite3_free(p->zState); sqlite3_free(p); }else{ rc = SQLITE_NOMEM; @@ -168643,7 +171138,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ ** updates) that have been performed on the target database since the ** current RBU update was started. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu){ +SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; } @@ -168651,7 +171146,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu){ ** Return permyriadage progress indications for the two main stages of ** an RBU update. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ const int MAX_PROGRESS = 10000; switch( p->eStage ){ case RBU_STAGE_OAL: @@ -168686,7 +171181,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, /* ** Return the current state of the RBU vacuum or update operation. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_state(sqlite3rbu *p){ +SQLITE_API int sqlite3rbu_state(sqlite3rbu *p){ int aRes[] = { 0, SQLITE_RBU_STATE_OAL, SQLITE_RBU_STATE_MOVE, 0, SQLITE_RBU_STATE_CHECKPOINT, SQLITE_RBU_STATE_DONE @@ -168714,7 +171209,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_state(sqlite3rbu *p){ } } -SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *p){ +SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){ int rc = p->rc; if( rc==SQLITE_DONE ) return SQLITE_OK; @@ -169541,7 +172036,7 @@ static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ ** Deregister and destroy an RBU vfs created by an earlier call to ** sqlite3rbu_create_vfs(). */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName){ +SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); if( pVfs && pVfs->xOpen==rbuVfsOpen ){ sqlite3_mutex_free(((rbu_vfs*)pVfs)->mutex); @@ -169555,7 +172050,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName){ ** via existing VFS zParent. The new object is registered as a non-default ** VFS with SQLite before returning. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent){ +SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent){ /* Template for VFS */ static sqlite3_vfs vfs_template = { @@ -170241,7 +172736,7 @@ static int statFilter( " UNION ALL " "SELECT name, rootpage, type" " FROM \"%w\".%s WHERE rootpage!=0" - " ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster); + " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster); if( zSql==0 ){ return SQLITE_NOMEM_BKPT; }else{ @@ -170295,7 +172790,7 @@ static int statColumn( default: { /* schema */ sqlite3 *db = sqlite3_context_db_handle(ctx); int iDb = pCsr->iDb; - sqlite3_result_text(ctx, db->aDb[iDb].zName, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC); break; } } @@ -170718,9 +173213,7 @@ static int sessionSerializeValue( if( aBuf ){ sessionVarintPut(&aBuf[1], n); - memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? - sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n - ); + if( n ) memcpy(&aBuf[nVarint + 1], z, n); } nByte = 1 + nVarint + n; @@ -171800,7 +174293,7 @@ static int sessionDiffFindModified( return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3session_diff( +SQLITE_API int sqlite3session_diff( sqlite3_session *pSession, const char *zFrom, const char *zTbl, @@ -171894,7 +174387,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_diff( ** Create a session object. This session object will record changes to ** database zDb attached to connection db. */ -SQLITE_API int SQLITE_STDCALL sqlite3session_create( +SQLITE_API int sqlite3session_create( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of db (e.g. "main") */ sqlite3_session **ppSession /* OUT: New session object */ @@ -171956,7 +174449,7 @@ static void sessionDeleteTable(SessionTable *pList){ /* ** Delete a session object previously allocated using sqlite3session_create(). */ -SQLITE_API void SQLITE_STDCALL sqlite3session_delete(sqlite3_session *pSession){ +SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){ sqlite3 *db = pSession->db; sqlite3_session *pHead; sqlite3_session **pp; @@ -171985,7 +174478,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3session_delete(sqlite3_session *pSession){ /* ** Set a table filter on a Session Object. */ -SQLITE_API void SQLITE_STDCALL sqlite3session_table_filter( +SQLITE_API void sqlite3session_table_filter( sqlite3_session *pSession, int(*xFilter)(void*, const char*), void *pCtx /* First argument passed to xFilter */ @@ -172003,7 +174496,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3session_table_filter( ** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) ** or not. */ -SQLITE_API int SQLITE_STDCALL sqlite3session_attach( +SQLITE_API int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zName /* Table name */ ){ @@ -172136,7 +174629,7 @@ static void sessionAppendBlob( int nBlob, int *pRc ){ - if( 0==sessionBufferGrow(p, nBlob, pRc) ){ + if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){ memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); p->nBuf += nBlob; } @@ -172322,13 +174815,13 @@ static int sessionAppendUpdate( } default: { - int nByte; - int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte); + int n; + int nHdr = 1 + sessionVarintGet(&pCsr[1], &n); assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - nAdvance = nHdr + nByte; + nAdvance = nHdr + n; if( eType==sqlite3_column_type(pStmt, i) - && nByte==sqlite3_column_bytes(pStmt, i) - && 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), nByte) + && n==sqlite3_column_bytes(pStmt, i) + && (n==0 || 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), n)) ){ break; } @@ -172693,7 +175186,7 @@ static int sessionGenerateChangeset( ** It is the responsibility of the caller to eventually free the buffer ** using sqlite3_free(). */ -SQLITE_API int SQLITE_STDCALL sqlite3session_changeset( +SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ @@ -172704,7 +175197,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_changeset( /* ** Streaming version of sqlite3session_changeset(). */ -SQLITE_API int SQLITE_STDCALL sqlite3session_changeset_strm( +SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut @@ -172715,7 +175208,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_changeset_strm( /* ** Streaming version of sqlite3session_patchset(). */ -SQLITE_API int SQLITE_STDCALL sqlite3session_patchset_strm( +SQLITE_API int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut @@ -172730,7 +175223,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_patchset_strm( ** It is the responsibility of the caller to eventually free the buffer ** using sqlite3_free(). */ -SQLITE_API int SQLITE_STDCALL sqlite3session_patchset( +SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ void **ppPatchset /* OUT: Buffer containing changeset */ @@ -172741,7 +175234,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_patchset( /* ** Enable or disable the session object passed as the first argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3session_enable(sqlite3_session *pSession, int bEnable){ +SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ int ret; sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( bEnable>=0 ){ @@ -172755,7 +175248,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_enable(sqlite3_session *pSession, i /* ** Enable or disable the session object passed as the first argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ +SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ int ret; sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( bIndirect>=0 ){ @@ -172770,7 +175263,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3session_indirect(sqlite3_session *pSession, ** Return true if there have been no changes to monitored tables recorded ** by the session object passed as the only argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3session_isempty(sqlite3_session *pSession){ +SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession){ int ret = 0; SessionTable *pTab; @@ -172820,7 +175313,7 @@ static int sessionChangesetStart( /* ** Create an iterator used to iterate through the contents of a changeset. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_start( +SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ @@ -172831,7 +175324,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_start( /* ** Streaming version of sqlite3changeset_start(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_start_strm( +SQLITE_API int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn @@ -173252,7 +175745,7 @@ static int sessionChangesetNext( ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_next(sqlite3_changeset_iter *p){ +SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ return sessionChangesetNext(p, 0, 0); } @@ -173261,7 +175754,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_next(sqlite3_changeset_iter *p){ ** from a changeset iterator. It may only be called after changeset_next() ** has returned SQLITE_ROW. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_op( +SQLITE_API int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator handle */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ @@ -173281,7 +175774,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_op( ** to. This function may only be called after changeset_next() returns ** SQLITE_ROW. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_pk( +SQLITE_API int sqlite3changeset_pk( sqlite3_changeset_iter *pIter, /* Iterator object */ unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ int *pnCol /* OUT: Number of entries in output array */ @@ -173304,7 +175797,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_pk( ** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is ** not modified. Otherwise, SQLITE_OK. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_old( +SQLITE_API int sqlite3changeset_old( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Index of old.* value to retrieve */ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ @@ -173332,7 +175825,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_old( ** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is ** not modified. Otherwise, SQLITE_OK. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_new( +SQLITE_API int sqlite3changeset_new( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Index of new.* value to retrieve */ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ @@ -173366,7 +175859,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_new( ** If value iVal is out-of-range or some other error occurs, an SQLite error ** code is returned. Otherwise, SQLITE_OK. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_conflict( +SQLITE_API int sqlite3changeset_conflict( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Index of conflict record value to fetch */ sqlite3_value **ppValue /* OUT: Value from conflicting row */ @@ -173389,7 +175882,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_conflict( ** ** In all other cases this function returns SQLITE_MISUSE. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_fk_conflicts( +SQLITE_API int sqlite3changeset_fk_conflicts( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int *pnOut /* OUT: Number of FK violations */ ){ @@ -173407,7 +175900,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_fk_conflicts( ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_finalize(sqlite3_changeset_iter *p){ +SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ int rc = SQLITE_OK; if( p ){ int i; /* Used to iterate through p->apValue[] */ @@ -173581,7 +176074,7 @@ static int sessionChangesetInvert( /* ** Invert a changeset object. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_invert( +SQLITE_API int sqlite3changeset_invert( int nChangeset, /* Number of bytes in input */ const void *pChangeset, /* Input changeset */ int *pnInverted, /* OUT: Number of bytes in output changeset */ @@ -173600,7 +176093,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_invert( /* ** Streaming version of sqlite3changeset_invert(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_invert_strm( +SQLITE_API int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), @@ -174480,7 +176973,7 @@ static int sessionChangesetApply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_apply( +SQLITE_API int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ @@ -174508,7 +177001,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_apply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_apply_strm( +SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ @@ -174843,7 +177336,7 @@ static int sessionChangegroupOutput( /* ** Allocate a new, empty, sqlite3_changegroup. */ -SQLITE_API int SQLITE_STDCALL sqlite3changegroup_new(sqlite3_changegroup **pp){ +SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp){ int rc = SQLITE_OK; /* Return code */ sqlite3_changegroup *p; /* New object */ p = (sqlite3_changegroup*)sqlite3_malloc(sizeof(sqlite3_changegroup)); @@ -174860,7 +177353,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changegroup_new(sqlite3_changegroup **pp){ ** Add the changeset currently stored in buffer pData, size nData bytes, ** to changeset-group p. */ -SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ +SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ @@ -174876,7 +177369,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add(sqlite3_changegroup *pGrp, ** Obtain a buffer containing a changeset representing the concatenation ** of all changesets added to the group so far. */ -SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output( +SQLITE_API int sqlite3changegroup_output( sqlite3_changegroup *pGrp, int *pnData, void **ppData @@ -174887,7 +177380,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output( /* ** Streaming versions of changegroup_add(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add_strm( +SQLITE_API int sqlite3changegroup_add_strm( sqlite3_changegroup *pGrp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn @@ -174906,7 +177399,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add_strm( /* ** Streaming versions of changegroup_output(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output_strm( +SQLITE_API int sqlite3changegroup_output_strm( sqlite3_changegroup *pGrp, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut @@ -174917,7 +177410,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output_strm( /* ** Delete a changegroup object. */ -SQLITE_API void SQLITE_STDCALL sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ +SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ sessionDeleteTable(pGrp->pList); sqlite3_free(pGrp); @@ -174927,7 +177420,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3changegroup_delete(sqlite3_changegroup *pG /* ** Combine two changesets together. */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_concat( +SQLITE_API int sqlite3changeset_concat( int nLeft, /* Number of bytes in lhs input */ void *pLeft, /* Lhs input changeset */ int nRight /* Number of bytes in rhs input */, @@ -174956,7 +177449,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3changeset_concat( /* ** Streaming version of sqlite3changeset_concat(). */ -SQLITE_API int SQLITE_STDCALL sqlite3changeset_concat_strm( +SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), @@ -175037,13 +177530,15 @@ SQLITE_EXTENSION_INIT1 #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) #else /* Use the standard library for separate compilation */ #include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) #endif /* @@ -175581,12 +178076,13 @@ static void jsonReturn( c = z[++i]; if( c=='u' ){ u32 v = 0, k; - for(k=0; k<4 && i='0' && c<='9' ) v = v*16 + c - '0'; - else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10; - else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10; - else break; + assert( safe_isxdigit(c) ); + if( c<='9' ) v = v*16 + c - '0'; + else if( c<='F' ) v = v*16 + c - 'A' + 10; + else v = v*16 + c - 'a' + 10; } if( v==0 ) break; if( v<=0x7f ){ @@ -175690,6 +178186,15 @@ static int jsonParseAddNode( return pParse->nNode++; } +/* +** Return true if z[] begins with 4 (or more) hexadecimal digits +*/ +static int jsonIs4Hex(const char *z){ + int i; + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + return 1; +} + /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. @@ -175764,8 +178269,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( c==0 ) return -1; if( c=='\\' ){ c = pParse->zJson[++j]; - if( c==0 ) return -1; - jnFlags = JNODE_ESCAPE; + if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' + || c=='n' || c=='r' || c=='t' + || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){ + jnFlags = JNODE_ESCAPE; + }else{ + return -1; + } }else if( c=='"' ){ break; } @@ -176633,7 +179143,7 @@ static void jsonObjectFinal(sqlite3_context *ctx){ if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ - if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, @@ -176911,9 +179421,9 @@ static int jsonEachColumn( /* For json_each() path and root are the same so fall through ** into the root case */ } - case JEACH_ROOT: { + default: { const char *zRoot = p->zRoot; - if( zRoot==0 ) zRoot = "$"; + if( zRoot==0 ) zRoot = "$"; sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); break; } @@ -177188,7 +179698,7 @@ SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_json_init( +SQLITE_API int sqlite3_json_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -178532,6 +181042,7 @@ static void sqlite3Fts5ParseNodeFree(Fts5ExprNode*); static void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*); static void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*); +static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*); static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p); static void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*); @@ -178589,12 +181100,13 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); #define FTS5_COLON 5 #define FTS5_LP 6 #define FTS5_RP 7 -#define FTS5_LCP 8 -#define FTS5_RCP 9 -#define FTS5_STRING 10 -#define FTS5_COMMA 11 -#define FTS5_PLUS 12 -#define FTS5_STAR 13 +#define FTS5_MINUS 8 +#define FTS5_LCP 9 +#define FTS5_RCP 10 +#define FTS5_STRING 11 +#define FTS5_COMMA 12 +#define FTS5_PLUS 13 +#define FTS5_STAR 14 /* ** 2000-05-29 @@ -178708,17 +181220,17 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); #endif /************* Begin control #defines *****************************************/ #define fts5YYCODETYPE unsigned char -#define fts5YYNOCODE 27 +#define fts5YYNOCODE 28 #define fts5YYACTIONTYPE unsigned char #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token typedef union { int fts5yyinit; sqlite3Fts5ParserFTS5TOKENTYPE fts5yy0; - Fts5Colset* fts5yy3; - Fts5ExprPhrase* fts5yy11; - Fts5ExprNode* fts5yy18; - int fts5yy20; - Fts5ExprNearset* fts5yy26; + int fts5yy4; + Fts5Colset* fts5yy11; + Fts5ExprNode* fts5yy24; + Fts5ExprNearset* fts5yy46; + Fts5ExprPhrase* fts5yy53; } fts5YYMINORTYPE; #ifndef fts5YYSTACKDEPTH #define fts5YYSTACKDEPTH 100 @@ -178727,16 +181239,16 @@ typedef union { #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse #define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse #define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse -#define fts5YYNSTATE 26 -#define fts5YYNRULE 24 -#define fts5YY_MAX_SHIFT 25 -#define fts5YY_MIN_SHIFTREDUCE 40 -#define fts5YY_MAX_SHIFTREDUCE 63 -#define fts5YY_MIN_REDUCE 64 -#define fts5YY_MAX_REDUCE 87 -#define fts5YY_ERROR_ACTION 88 -#define fts5YY_ACCEPT_ACTION 89 -#define fts5YY_NO_ACTION 90 +#define fts5YYNSTATE 29 +#define fts5YYNRULE 26 +#define fts5YY_MAX_SHIFT 28 +#define fts5YY_MIN_SHIFTREDUCE 45 +#define fts5YY_MAX_SHIFTREDUCE 70 +#define fts5YY_MIN_REDUCE 71 +#define fts5YY_MAX_REDUCE 96 +#define fts5YY_ERROR_ACTION 97 +#define fts5YY_ACCEPT_ACTION 98 +#define fts5YY_NO_ACTION 99 /************* End control #defines *******************************************/ /* Define the fts5yytestcase() macro to be a no-op if is not already defined @@ -178768,7 +181280,7 @@ typedef union { ** ** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE ** and fts5YY_MAX_REDUCE - +** ** N == fts5YY_ERROR_ACTION A syntax error has occurred. ** ** N == fts5YY_ACCEPT_ACTION The parser accepts its input. @@ -178777,16 +181289,20 @@ typedef union { ** slots in the fts5yy_action[] table. ** ** The action table is constructed as a single large table named fts5yy_action[]. -** Given state S and lookahead X, the action is computed as +** Given state S and lookahead X, the action is computed as either: ** -** fts5yy_action[ fts5yy_shift_ofst[S] + X ] +** (A) N = fts5yy_action[ fts5yy_shift_ofst[S] + X ] +** (B) N = fts5yy_default[S] ** -** If the index value fts5yy_shift_ofst[S]+X is out of range or if the value -** fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X or if fts5yy_shift_ofst[S] -** is equal to fts5YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that fts5yy_default[S] should be used instead. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The fts5yy_shift_ofst[S]+X value is out of range, or +** (2) fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X, or +** (3) fts5yy_shift_ofst[S] equal fts5YY_SHIFT_USE_DFLT. +** (Implementation note: fts5YY_SHIFT_USE_DFLT is chosen so that +** fts5YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** -** The formula above is for computing the action when the lookahead is +** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the fts5yy_reduce_ofst[] array is used in place of ** the fts5yy_shift_ofst[] array and fts5YY_REDUCE_USE_DFLT is used in place of @@ -178804,48 +181320,50 @@ typedef union { ** fts5yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define fts5YY_ACTTAB_COUNT (78) +#define fts5YY_ACTTAB_COUNT (85) static const fts5YYACTIONTYPE fts5yy_action[] = { - /* 0 */ 89, 15, 46, 5, 48, 24, 12, 19, 23, 14, - /* 10 */ 46, 5, 48, 24, 20, 21, 23, 43, 46, 5, - /* 20 */ 48, 24, 6, 18, 23, 17, 46, 5, 48, 24, - /* 30 */ 75, 7, 23, 25, 46, 5, 48, 24, 62, 47, - /* 40 */ 23, 48, 24, 7, 11, 23, 9, 3, 4, 2, - /* 50 */ 62, 50, 52, 44, 64, 3, 4, 2, 49, 4, - /* 60 */ 2, 1, 23, 11, 16, 9, 12, 2, 10, 61, - /* 70 */ 53, 59, 62, 60, 22, 13, 55, 8, + /* 0 */ 98, 16, 51, 5, 53, 27, 83, 7, 26, 15, + /* 10 */ 51, 5, 53, 27, 13, 69, 26, 48, 51, 5, + /* 20 */ 53, 27, 19, 11, 26, 9, 20, 51, 5, 53, + /* 30 */ 27, 13, 22, 26, 28, 51, 5, 53, 27, 68, + /* 40 */ 1, 26, 19, 11, 17, 9, 52, 10, 53, 27, + /* 50 */ 23, 24, 26, 54, 3, 4, 2, 26, 6, 21, + /* 60 */ 49, 71, 3, 4, 2, 7, 56, 59, 55, 59, + /* 70 */ 4, 2, 12, 69, 58, 60, 18, 67, 62, 69, + /* 80 */ 25, 66, 8, 14, 2, }; static const fts5YYCODETYPE fts5yy_lookahead[] = { - /* 0 */ 15, 16, 17, 18, 19, 20, 10, 11, 23, 16, - /* 10 */ 17, 18, 19, 20, 23, 24, 23, 16, 17, 18, - /* 20 */ 19, 20, 22, 23, 23, 16, 17, 18, 19, 20, - /* 30 */ 5, 6, 23, 16, 17, 18, 19, 20, 13, 17, - /* 40 */ 23, 19, 20, 6, 8, 23, 10, 1, 2, 3, - /* 50 */ 13, 9, 10, 7, 0, 1, 2, 3, 19, 2, - /* 60 */ 3, 6, 23, 8, 21, 10, 10, 3, 10, 25, - /* 70 */ 10, 10, 13, 25, 12, 10, 7, 5, + /* 0 */ 16, 17, 18, 19, 20, 21, 5, 6, 24, 17, + /* 10 */ 18, 19, 20, 21, 11, 14, 24, 17, 18, 19, + /* 20 */ 20, 21, 8, 9, 24, 11, 17, 18, 19, 20, + /* 30 */ 21, 11, 12, 24, 17, 18, 19, 20, 21, 26, + /* 40 */ 6, 24, 8, 9, 22, 11, 18, 11, 20, 21, + /* 50 */ 24, 25, 24, 20, 1, 2, 3, 24, 23, 24, + /* 60 */ 7, 0, 1, 2, 3, 6, 10, 11, 10, 11, + /* 70 */ 2, 3, 9, 14, 11, 11, 22, 26, 7, 14, + /* 80 */ 13, 11, 5, 11, 3, }; -#define fts5YY_SHIFT_USE_DFLT (-5) -#define fts5YY_SHIFT_COUNT (25) -#define fts5YY_SHIFT_MIN (-4) -#define fts5YY_SHIFT_MAX (72) -static const signed char fts5yy_shift_ofst[] = { - /* 0 */ 55, 55, 55, 55, 55, 36, -4, 56, 58, 25, - /* 10 */ 37, 60, 59, 59, 46, 54, 42, 57, 62, 61, - /* 20 */ 62, 69, 65, 62, 72, 64, +#define fts5YY_SHIFT_USE_DFLT (85) +#define fts5YY_SHIFT_COUNT (28) +#define fts5YY_SHIFT_MIN (0) +#define fts5YY_SHIFT_MAX (81) +static const unsigned char fts5yy_shift_ofst[] = { + /* 0 */ 34, 34, 34, 34, 34, 14, 20, 3, 36, 1, + /* 10 */ 59, 64, 64, 65, 65, 53, 61, 56, 58, 63, + /* 20 */ 68, 67, 70, 67, 71, 72, 67, 77, 81, }; -#define fts5YY_REDUCE_USE_DFLT (-16) -#define fts5YY_REDUCE_COUNT (13) -#define fts5YY_REDUCE_MIN (-15) -#define fts5YY_REDUCE_MAX (48) +#define fts5YY_REDUCE_USE_DFLT (-17) +#define fts5YY_REDUCE_COUNT (14) +#define fts5YY_REDUCE_MIN (-16) +#define fts5YY_REDUCE_MAX (54) static const signed char fts5yy_reduce_ofst[] = { - /* 0 */ -15, -7, 1, 9, 17, 22, -9, 0, 39, 44, - /* 10 */ 44, 43, 44, 48, + /* 0 */ -16, -8, 0, 9, 17, 28, 26, 35, 33, 13, + /* 10 */ 13, 22, 54, 13, 51, }; static const fts5YYACTIONTYPE fts5yy_default[] = { - /* 0 */ 88, 88, 88, 88, 88, 69, 82, 88, 88, 87, - /* 10 */ 87, 88, 87, 87, 88, 88, 88, 66, 80, 88, - /* 20 */ 81, 88, 88, 78, 88, 65, + /* 0 */ 97, 97, 97, 97, 97, 76, 91, 97, 97, 96, + /* 10 */ 96, 97, 97, 96, 96, 97, 97, 97, 97, 97, + /* 20 */ 73, 89, 97, 90, 97, 97, 87, 97, 72, }; /********** End of lemon-generated parsing tables *****************************/ @@ -178952,11 +181470,11 @@ static void sqlite3Fts5ParserTrace(FILE *TraceFILE, char *zTracePrompt){ static const char *const fts5yyTokenName[] = { "$", "OR", "AND", "NOT", "TERM", "COLON", "LP", "RP", - "LCP", "RCP", "STRING", "COMMA", - "PLUS", "STAR", "error", "input", - "expr", "cnearset", "exprlist", "nearset", - "colset", "colsetlist", "nearphrases", "phrase", - "neardist_opt", "star_opt", + "MINUS", "LCP", "RCP", "STRING", + "COMMA", "PLUS", "STAR", "error", + "input", "expr", "cnearset", "exprlist", + "nearset", "colset", "colsetlist", "nearphrases", + "phrase", "neardist_opt", "star_opt", }; #endif /* NDEBUG */ @@ -178974,20 +181492,22 @@ static const char *const fts5yyRuleName[] = { /* 7 */ "exprlist ::= exprlist cnearset", /* 8 */ "cnearset ::= nearset", /* 9 */ "cnearset ::= colset COLON nearset", - /* 10 */ "colset ::= LCP colsetlist RCP", - /* 11 */ "colset ::= STRING", - /* 12 */ "colsetlist ::= colsetlist STRING", - /* 13 */ "colsetlist ::= STRING", - /* 14 */ "nearset ::= phrase", - /* 15 */ "nearset ::= STRING LP nearphrases neardist_opt RP", - /* 16 */ "nearphrases ::= phrase", - /* 17 */ "nearphrases ::= nearphrases phrase", - /* 18 */ "neardist_opt ::=", - /* 19 */ "neardist_opt ::= COMMA STRING", - /* 20 */ "phrase ::= phrase PLUS STRING star_opt", - /* 21 */ "phrase ::= STRING star_opt", - /* 22 */ "star_opt ::= STAR", - /* 23 */ "star_opt ::=", + /* 10 */ "colset ::= MINUS LCP colsetlist RCP", + /* 11 */ "colset ::= LCP colsetlist RCP", + /* 12 */ "colset ::= STRING", + /* 13 */ "colset ::= MINUS STRING", + /* 14 */ "colsetlist ::= colsetlist STRING", + /* 15 */ "colsetlist ::= STRING", + /* 16 */ "nearset ::= phrase", + /* 17 */ "nearset ::= STRING LP nearphrases neardist_opt RP", + /* 18 */ "nearphrases ::= phrase", + /* 19 */ "nearphrases ::= nearphrases phrase", + /* 20 */ "neardist_opt ::=", + /* 21 */ "neardist_opt ::= COMMA STRING", + /* 22 */ "phrase ::= phrase PLUS STRING star_opt", + /* 23 */ "phrase ::= STRING star_opt", + /* 24 */ "star_opt ::= STAR", + /* 25 */ "star_opt ::=", }; #endif /* NDEBUG */ @@ -179097,33 +181617,33 @@ static void fts5yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 15: /* input */ + case 16: /* input */ { (void)pParse; } break; - case 16: /* expr */ - case 17: /* cnearset */ - case 18: /* exprlist */ + case 17: /* expr */ + case 18: /* cnearset */ + case 19: /* exprlist */ { - sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy18)); + sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy24)); } break; - case 19: /* nearset */ - case 22: /* nearphrases */ + case 20: /* nearset */ + case 23: /* nearphrases */ { - sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy26)); + sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy46)); } break; - case 20: /* colset */ - case 21: /* colsetlist */ + case 21: /* colset */ + case 22: /* colsetlist */ { - sqlite3_free((fts5yypminor->fts5yy3)); + sqlite3_free((fts5yypminor->fts5yy11)); } break; - case 23: /* phrase */ + case 24: /* phrase */ { - sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy11)); + sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy53)); } break; /********* End destructor definitions *****************************************/ @@ -179200,50 +181720,47 @@ static unsigned int fts5yy_find_shift_action( assert( stateno <= fts5YY_SHIFT_COUNT ); do{ i = fts5yy_shift_ofst[stateno]; - if( i==fts5YY_SHIFT_USE_DFLT ) return fts5yy_default[stateno]; assert( iLookAhead!=fts5YYNOCODE ); i += iLookAhead; if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ #ifdef fts5YYFALLBACK - fts5YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[iFallback]); - } -#endif - assert( fts5yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE, "%sFALLBACK %s => %s\n", + fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[iFallback]); } +#endif + assert( fts5yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } #endif #ifdef fts5YYWILDCARD - { - int j = i - iLookAhead + fts5YYWILDCARD; - if( + { + int j = i - iLookAhead + fts5YYWILDCARD; + if( #if fts5YY_SHIFT_MIN+fts5YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT - j0 + ){ #ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n", - fts5yyTracePrompt, fts5yyTokenName[iLookAhead], - fts5yyTokenName[fts5YYWILDCARD]); - } -#endif /* NDEBUG */ - return fts5yy_action[j]; + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n", + fts5yyTracePrompt, fts5yyTokenName[iLookAhead], + fts5yyTokenName[fts5YYWILDCARD]); } +#endif /* NDEBUG */ + return fts5yy_action[j]; } -#endif /* fts5YYWILDCARD */ } +#endif /* fts5YYWILDCARD */ return fts5yy_default[stateno]; }else{ return fts5yy_action[i]; @@ -179287,7 +181804,6 @@ static int fts5yy_find_reduce_action( */ static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ sqlite3Fts5ParserARG_FETCH; - fts5yypParser->fts5yytos--; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); @@ -179342,12 +181858,14 @@ static void fts5yy_shift( #endif #if fts5YYSTACKDEPTH>0 if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH] ){ + fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } #else if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz] ){ if( fts5yyGrowStack(fts5yypParser) ){ + fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } @@ -179370,30 +181888,32 @@ static const struct { fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } fts5yyRuleInfo[] = { - { 15, 1 }, - { 16, 3 }, - { 16, 3 }, - { 16, 3 }, - { 16, 3 }, { 16, 1 }, - { 18, 1 }, - { 18, 2 }, - { 17, 1 }, { 17, 3 }, - { 20, 3 }, - { 20, 1 }, - { 21, 2 }, - { 21, 1 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 1 }, { 19, 1 }, - { 19, 5 }, - { 22, 1 }, + { 19, 2 }, + { 18, 1 }, + { 18, 3 }, + { 21, 4 }, + { 21, 3 }, + { 21, 1 }, + { 21, 2 }, { 22, 2 }, - { 24, 0 }, - { 24, 2 }, - { 23, 4 }, + { 22, 1 }, + { 20, 1 }, + { 20, 5 }, + { 23, 1 }, { 23, 2 }, - { 25, 1 }, { 25, 0 }, + { 25, 2 }, + { 24, 4 }, + { 24, 2 }, + { 26, 1 }, + { 26, 0 }, }; static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ @@ -179458,120 +181978,131 @@ static void fts5yy_reduce( /********** Begin reduce actions **********************************************/ fts5YYMINORTYPE fts5yylhsminor; case 0: /* input ::= expr */ -{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy18); } +{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy24); } break; case 1: /* expr ::= expr AND expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 2: /* expr ::= expr OR expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 3: /* expr ::= expr NOT expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 4: /* expr ::= LP expr RP */ -{fts5yymsp[-2].minor.fts5yy18 = fts5yymsp[-1].minor.fts5yy18;} +{fts5yymsp[-2].minor.fts5yy24 = fts5yymsp[-1].minor.fts5yy24;} break; case 5: /* expr ::= exprlist */ case 6: /* exprlist ::= cnearset */ fts5yytestcase(fts5yyruleno==6); -{fts5yylhsminor.fts5yy18 = fts5yymsp[0].minor.fts5yy18;} - fts5yymsp[0].minor.fts5yy18 = fts5yylhsminor.fts5yy18; +{fts5yylhsminor.fts5yy24 = fts5yymsp[0].minor.fts5yy24;} + fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 7: /* exprlist ::= exprlist cnearset */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24); } - fts5yymsp[-1].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-1].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 8: /* cnearset ::= nearset */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy26); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); } - fts5yymsp[0].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 9: /* cnearset ::= colset COLON nearset */ { - sqlite3Fts5ParseSetColset(pParse, fts5yymsp[0].minor.fts5yy26, fts5yymsp[-2].minor.fts5yy3); - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy26); + sqlite3Fts5ParseSetColset(pParse, fts5yymsp[0].minor.fts5yy46, fts5yymsp[-2].minor.fts5yy11); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; - case 10: /* colset ::= LCP colsetlist RCP */ -{ fts5yymsp[-2].minor.fts5yy3 = fts5yymsp[-1].minor.fts5yy3; } + case 10: /* colset ::= MINUS LCP colsetlist RCP */ +{ + fts5yymsp[-3].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); +} break; - case 11: /* colset ::= STRING */ + case 11: /* colset ::= LCP colsetlist RCP */ +{ fts5yymsp[-2].minor.fts5yy11 = fts5yymsp[-1].minor.fts5yy11; } + break; + case 12: /* colset ::= STRING */ { - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); } - fts5yymsp[0].minor.fts5yy3 = fts5yylhsminor.fts5yy3; + fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 12: /* colsetlist ::= colsetlist STRING */ -{ - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy3, &fts5yymsp[0].minor.fts5yy0); } - fts5yymsp[-1].minor.fts5yy3 = fts5yylhsminor.fts5yy3; - break; - case 13: /* colsetlist ::= STRING */ -{ - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); -} - fts5yymsp[0].minor.fts5yy3 = fts5yylhsminor.fts5yy3; - break; - case 14: /* nearset ::= phrase */ -{ fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); } - fts5yymsp[0].minor.fts5yy26 = fts5yylhsminor.fts5yy26; - break; - case 15: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + case 13: /* colset ::= MINUS STRING */ { - sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); - sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy26, &fts5yymsp[-1].minor.fts5yy0); - fts5yylhsminor.fts5yy26 = fts5yymsp[-2].minor.fts5yy26; + fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); } - fts5yymsp[-4].minor.fts5yy26 = fts5yylhsminor.fts5yy26; break; - case 16: /* nearphrases ::= phrase */ + case 14: /* colsetlist ::= colsetlist STRING */ { - fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); -} - fts5yymsp[0].minor.fts5yy26 = fts5yylhsminor.fts5yy26; - break; - case 17: /* nearphrases ::= nearphrases phrase */ -{ - fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy26, fts5yymsp[0].minor.fts5yy11); -} - fts5yymsp[-1].minor.fts5yy26 = fts5yylhsminor.fts5yy26; - break; - case 18: /* neardist_opt ::= */ -{ fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } - break; - case 19: /* neardist_opt ::= COMMA STRING */ -{ fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } - break; - case 20: /* phrase ::= phrase PLUS STRING star_opt */ -{ - fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy11, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy20); -} - fts5yymsp[-3].minor.fts5yy11 = fts5yylhsminor.fts5yy11; - break; - case 21: /* phrase ::= STRING star_opt */ -{ - fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy20); -} + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy11, &fts5yymsp[0].minor.fts5yy0); } fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 22: /* star_opt ::= STAR */ -{ fts5yymsp[0].minor.fts5yy20 = 1; } + case 15: /* colsetlist ::= STRING */ +{ + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); +} + fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 23: /* star_opt ::= */ -{ fts5yymsp[1].minor.fts5yy20 = 0; } + case 16: /* nearset ::= phrase */ +{ fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 17: /* nearset ::= STRING LP nearphrases neardist_opt RP */ +{ + sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); + sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); + fts5yylhsminor.fts5yy46 = fts5yymsp[-2].minor.fts5yy46; +} + fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 18: /* nearphrases ::= phrase */ +{ + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); +} + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 19: /* nearphrases ::= nearphrases phrase */ +{ + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); +} + fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 20: /* neardist_opt ::= */ +{ fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } + break; + case 21: /* neardist_opt ::= COMMA STRING */ +{ fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } + break; + case 22: /* phrase ::= phrase PLUS STRING star_opt */ +{ + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); +} + fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; + case 23: /* phrase ::= STRING star_opt */ +{ + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); +} + fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; + case 24: /* star_opt ::= STAR */ +{ fts5yymsp[0].minor.fts5yy4 = 1; } + break; + case 25: /* star_opt ::= */ +{ fts5yymsp[1].minor.fts5yy4 = 0; } break; default: break; @@ -179765,7 +182296,7 @@ static void sqlite3Fts5Parser( fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); fts5yymajor = fts5YYNOCODE; }else{ - while( fts5yypParser->fts5yytos >= &fts5yypParser->fts5yystack + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack && fts5yymx != fts5YYERRORSYMBOL && (fts5yyact = fts5yy_find_reduce_action( fts5yypParser->fts5yytos->stateno, @@ -180029,7 +182560,7 @@ static int fts5HighlightCb( if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); p->iOff = iEndOff; - if( iPositer.iEnd ){ + if( iPos>=p->iter.iStart && iPositer.iEnd ){ fts5HighlightAppend(&rc, p, p->zClose, -1); } } @@ -180086,6 +182617,118 @@ static void fts5HighlightFunction( ** End of highlight() implementation. **************************************************************************/ +/* +** Context object passed to the fts5SentenceFinderCb() function. +*/ +typedef struct Fts5SFinder Fts5SFinder; +struct Fts5SFinder { + int iPos; /* Current token position */ + int nFirstAlloc; /* Allocated size of aFirst[] */ + int nFirst; /* Number of entries in aFirst[] */ + int *aFirst; /* Array of first token in each sentence */ + const char *zDoc; /* Document being tokenized */ +}; + +/* +** Add an entry to the Fts5SFinder.aFirst[] array. Grow the array if +** necessary. Return SQLITE_OK if successful, or SQLITE_NOMEM if an +** error occurs. +*/ +static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){ + if( p->nFirstAlloc==p->nFirst ){ + int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64; + int *aNew; + + aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int)); + if( aNew==0 ) return SQLITE_NOMEM; + p->aFirst = aNew; + p->nFirstAlloc = nNew; + } + p->aFirst[p->nFirst++] = iAdd; + return SQLITE_OK; +} + +/* +** This function is an xTokenize() callback used by the auxiliary snippet() +** function. Its job is to identify tokens that are the first in a sentence. +** For each such token, an entry is added to the SFinder.aFirst[] array. +*/ +static int fts5SentenceFinderCb( + void *pContext, /* Pointer to HighlightContext object */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStartOff, /* Start offset of token */ + int iEndOff /* End offset of token */ +){ + int rc = SQLITE_OK; + + UNUSED_PARAM2(pToken, nToken); + UNUSED_PARAM(iEndOff); + + if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ + Fts5SFinder *p = (Fts5SFinder*)pContext; + if( p->iPos>0 ){ + int i; + char c = 0; + for(i=iStartOff-1; i>=0; i--){ + c = p->zDoc[i]; + if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) break; + } + if( i!=iStartOff-1 && (c=='.' || c==':') ){ + rc = fts5SentenceFinderAdd(p, p->iPos); + } + }else{ + rc = fts5SentenceFinderAdd(p, 0); + } + p->iPos++; + } + return rc; +} + +static int fts5SnippetScore( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + int nDocsize, /* Size of column in tokens */ + unsigned char *aSeen, /* Array with one element per query phrase */ + int iCol, /* Column to score */ + int iPos, /* Starting offset to score */ + int nToken, /* Max tokens per snippet */ + int *pnScore, /* OUT: Score */ + int *piPos /* OUT: Adjusted offset */ +){ + int rc; + int i; + int ip = 0; + int ic = 0; + int iOff = 0; + int iFirst = -1; + int nInst; + int nScore = 0; + int iLast = 0; + + rc = pApi->xInstCount(pFts, &nInst); + for(i=0; ixInst(pFts, i, &ip, &ic, &iOff); + if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){ + nScore += (aSeen[ip] ? 1 : 1000); + aSeen[ip] = 1; + if( iFirst<0 ) iFirst = iOff; + iLast = iOff + pApi->xPhraseSize(pFts, ip); + } + } + + *pnScore = nScore; + if( piPos ){ + int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2; + if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken; + if( iAdj<0 ) iAdj = 0; + *piPos = iAdj; + } + + return rc; +} + /* ** Implementation of snippet() function. */ @@ -180107,9 +182750,10 @@ static void fts5SnippetFunction( unsigned char *aSeen; /* Array of "seen instance" flags */ int iBestCol; /* Column containing best snippet */ int iBestStart = 0; /* First token of best snippet */ - int iBestLast; /* Last token of best snippet */ int nBestScore = 0; /* Score of best snippet */ int nColSize = 0; /* Total size of iBestCol in tokens */ + Fts5SFinder sFinder; /* Used to find the beginnings of sentences */ + int nCol; if( nVal!=5 ){ const char *zErr = "wrong number of arguments to function snippet()"; @@ -180117,13 +182761,13 @@ static void fts5SnippetFunction( return; } + nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); zEllips = (const char*)sqlite3_value_text(apVal[3]); nToken = sqlite3_value_int(apVal[4]); - iBestLast = nToken-1; iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); @@ -180131,65 +182775,94 @@ static void fts5SnippetFunction( if( aSeen==0 ){ rc = SQLITE_NOMEM; } - if( rc==SQLITE_OK ){ rc = pApi->xInstCount(pFts, &nInst); } - for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &ip, &iSnippetCol, &iStart); - if( rc==SQLITE_OK && (iCol<0 || iSnippetCol==iCol) ){ - int nScore = 1000; - int iLast = iStart - 1 + pApi->xPhraseSize(pFts, ip); - int j; - aSeen[ip] = 1; - for(j=i+1; rc==SQLITE_OK && jxInst(pFts, j, &ip, &ic, &io); - iFinal = io + pApi->xPhraseSize(pFts, ip) - 1; - if( rc==SQLITE_OK && ic==iSnippetCol && iLastiLast ) iLast = iFinal; + memset(&sFinder, 0, sizeof(Fts5SFinder)); + for(i=0; ixColumnText(pFts, i, &sFinder.zDoc, &nDoc); + if( rc!=SQLITE_OK ) break; + rc = pApi->xTokenize(pFts, + sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb + ); + if( rc!=SQLITE_OK ) break; + rc = pApi->xColumnSize(pFts, i, &nDocsize); + if( rc!=SQLITE_OK ) break; + + for(ii=0; rc==SQLITE_OK && iixInst(pFts, ii, &ip, &ic, &io); + if( ic!=i || rc!=SQLITE_OK ) continue; + memset(aSeen, 0, nPhrase); + rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, + io, nToken, &nScore, &iAdj + ); + if( rc==SQLITE_OK && nScore>nBestScore ){ + nBestScore = nScore; + iBestCol = i; + iBestStart = iAdj; + nColSize = nDocsize; } - } - if( rc==SQLITE_OK && nScore>nBestScore ){ - iBestCol = iSnippetCol; - iBestStart = iStart; - iBestLast = iLast; - nBestScore = nScore; + if( rc==SQLITE_OK && sFinder.nFirst && nDocsize>nToken ){ + for(jj=0; jj<(sFinder.nFirst-1); jj++){ + if( sFinder.aFirst[jj+1]>io ) break; + } + + if( sFinder.aFirst[jj]nBestScore ){ + nBestScore = nScore; + iBestCol = i; + iBestStart = sFinder.aFirst[jj]; + nColSize = nDocsize; + } + } + } } } } - if( rc==SQLITE_OK ){ - rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); - } if( rc==SQLITE_OK ){ rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn); } + if( rc==SQLITE_OK && nColSize==0 ){ + rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); + } if( ctx.zIn ){ if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter); } - if( (iBestStart+nToken-1)>iBestLast ){ - iBestStart -= (iBestStart+nToken-1-iBestLast) / 2; - } - if( iBestStart+nToken>nColSize ){ - iBestStart = nColSize - nToken; - } - if( iBestStart<0 ) iBestStart = 0; - ctx.iRangeStart = iBestStart; ctx.iRangeEnd = iBestStart + nToken - 1; if( iBestStart>0 ){ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } + + /* Advance iterator ctx.iter so that it points to the first coalesced + ** phrase instance at or following position iBestStart. */ + while( ctx.iter.iStart>=0 && ctx.iter.iStartxTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } @@ -180198,15 +182871,15 @@ static void fts5SnippetFunction( }else{ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } - - if( rc==SQLITE_OK ){ - sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); - }else{ - sqlite3_result_error_code(pCtx, rc); - } - sqlite3_free(ctx.zOut); } + if( rc==SQLITE_OK ){ + sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_error_code(pCtx, rc); + } + sqlite3_free(ctx.zOut); sqlite3_free(aSeen); + sqlite3_free(sFinder.aFirst); } /************************************************************************/ @@ -181925,6 +184598,7 @@ static int fts5ExprGetToken( case ',': tok = FTS5_COMMA; break; case '+': tok = FTS5_PLUS; break; case '*': tok = FTS5_STAR; break; + case '-': tok = FTS5_MINUS; break; case '\0': tok = FTS5_EOF; break; case '"': { @@ -182503,49 +185177,61 @@ static int fts5ExprNearTest( ** Initialize all term iterators in the pNear object. If any term is found ** to match no documents at all, return immediately without initializing any ** further iterators. +** +** If an error occurs, return an SQLite error code. Otherwise, return +** SQLITE_OK. It is not considered an error if some term matches zero +** documents. */ static int fts5ExprNearInitAll( Fts5Expr *pExpr, Fts5ExprNode *pNode ){ Fts5ExprNearset *pNear = pNode->pNear; - int i, j; - int rc = SQLITE_OK; + int i; assert( pNode->bNomatch==0 ); - for(i=0; rc==SQLITE_OK && inPhrase; i++){ + for(i=0; inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - for(j=0; jnTerm; j++){ - Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; - Fts5ExprTerm *p; - int bEof = 1; + if( pPhrase->nTerm==0 ){ + pNode->bEof = 1; + return SQLITE_OK; + }else{ + int j; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + Fts5ExprTerm *p; + int bHit = 0; - for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){ - if( p->pIter ){ - sqlite3Fts5IterClose(p->pIter); - p->pIter = 0; + for(p=pTerm; p; p=p->pSynonym){ + int rc; + if( p->pIter ){ + sqlite3Fts5IterClose(p->pIter); + p->pIter = 0; + } + rc = sqlite3Fts5IndexQuery( + pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), + (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | + (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), + pNear->pColset, + &p->pIter + ); + assert( (rc==SQLITE_OK)==(p->pIter!=0) ); + if( rc!=SQLITE_OK ) return rc; + if( 0==sqlite3Fts5IterEof(p->pIter) ){ + bHit = 1; + } } - rc = sqlite3Fts5IndexQuery( - pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), - (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | - (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), - pNear->pColset, - &p->pIter - ); - assert( rc==SQLITE_OK || p->pIter==0 ); - if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){ - bEof = 0; - } - } - if( bEof ){ - pNode->bEof = 1; - return rc; + if( bHit==0 ){ + pNode->bEof = 1; + return SQLITE_OK; + } } } } - return rc; + pNode->bEof = 0; + return SQLITE_OK; } /* @@ -182678,7 +185364,7 @@ static int fts5ExprNodeTest_STRING( } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - if( pIter->iRowid==iLast ) continue; + if( pIter->iRowid==iLast || pIter->bEof ) continue; bMatch = 0; if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; @@ -183089,7 +185775,10 @@ static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bD /* If not at EOF but the current rowid occurs earlier than iFirst in ** the iteration order, move to document iFirst or later. */ - if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ + if( rc==SQLITE_OK + && 0==pRoot->bEof + && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 + ){ rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); } @@ -183395,7 +186084,6 @@ static int sqlite3Fts5ExprClonePhrase( ){ int rc = SQLITE_OK; /* Return code */ Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ - int i; /* Used to iterate through phrase terms */ Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ @@ -183416,7 +186104,7 @@ static int sqlite3Fts5ExprClonePhrase( if( rc==SQLITE_OK ){ Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; if( pColsetOrig ){ - int nByte = sizeof(Fts5Colset) + pColsetOrig->nCol * sizeof(int); + int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); if( pColset ){ memcpy(pColset, pColsetOrig, nByte); @@ -183425,18 +186113,25 @@ static int sqlite3Fts5ExprClonePhrase( } } - for(i=0; rc==SQLITE_OK && inTerm; i++){ - int tflags = 0; - Fts5ExprTerm *p; - for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ - const char *zTerm = p->zTerm; - rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), - 0, 0); - tflags = FTS5_TOKEN_COLOCATED; - } - if( rc==SQLITE_OK ){ - sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + if( pOrig->nTerm ){ + int i; /* Used to iterate through phrase terms */ + for(i=0; rc==SQLITE_OK && inTerm; i++){ + int tflags = 0; + Fts5ExprTerm *p; + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ + const char *zTerm = p->zTerm; + rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), + 0, 0); + tflags = FTS5_TOKEN_COLOCATED; + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } } + }else{ + /* This happens when parsing a token or quoted phrase that contains + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); } if( rc==SQLITE_OK ){ @@ -183551,6 +186246,34 @@ static Fts5Colset *fts5ParseColset( return pNew; } +/* +** Allocate and return an Fts5Colset object specifying the inverse of +** the colset passed as the second argument. Free the colset passed +** as the second argument before returning. +*/ +static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){ + Fts5Colset *pRet; + int nCol = pParse->pConfig->nCol; + + pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, + sizeof(Fts5Colset) + sizeof(int)*nCol + ); + if( pRet ){ + int i; + int iOld = 0; + for(i=0; i=p->nCol || p->aiCol[iOld]!=i ){ + pRet->aiCol[pRet->nCol++] = i; + }else{ + iOld++; + } + } + } + + sqlite3_free(p); + return pRet; +} + static Fts5Colset *sqlite3Fts5ParseColset( Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */ Fts5Colset *pColset, /* Existing colset object */ @@ -185646,7 +188369,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ return pRet; } - /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). @@ -185655,6 +188377,18 @@ static void fts5DataRelease(Fts5Data *pData){ sqlite3_free(pData); } +static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ + Fts5Data *pRet = fts5DataRead(p, iRowid); + if( pRet ){ + if( pRet->szLeaf>pRet->nn ){ + p->rc = FTS5_CORRUPT; + fts5DataRelease(pRet); + pRet = 0; + } + } + return pRet; +} + static int fts5IndexPrepareStmt( Fts5Index *p, sqlite3_stmt **ppStmt, @@ -186463,7 +189197,7 @@ static void fts5SegIterNextPage( pIter->pLeaf = pIter->pNextLeaf; pIter->pNextLeaf = 0; }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){ - pIter->pLeaf = fts5DataRead(p, + pIter->pLeaf = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno) ); }else{ @@ -186966,9 +189700,8 @@ static void fts5SegIterNext( if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist - ); + ); } - } else if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( @@ -187213,6 +189946,11 @@ static void fts5LeafSeek( iTermOff += nKeep; iOff = iTermOff; + if( iOff>=n ){ + p->rc = FTS5_CORRUPT; + return; + } + /* Read the nKeep field of the next term. */ fts5FastGetVarint32(a, iOff, nKeep); } @@ -187769,6 +190507,7 @@ static void fts5MultiIterNext( i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; + assert( pIter->base.bEof==0 ); while( p->rc==SQLITE_OK ){ int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0; @@ -188139,6 +190878,15 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ } } +/* +** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match +** against no columns at all). +*/ +static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){ + UNUSED_PARAM(pSeg); + pIter->base.nData = 0; +} + /* ** xSetOutputs callback used by detail=col when there is a column filter ** and there are 100 or more columns. Also called as a fallback from @@ -188244,6 +190992,10 @@ static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; } + else if( pIter->pColset->nCol==0 ){ + pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset; + } + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ pIter->xSetOutputs = fts5IterSetOutputs_Full; } @@ -194020,7 +196772,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2016-08-11 18:53:32 a12d8059770df4bca59e321c266410344242bf7b", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ @@ -194108,7 +196860,7 @@ static int fts5Init(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts_init( +SQLITE_API int sqlite3_fts_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -194121,7 +196873,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_fts_init( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts5_init( +SQLITE_API int sqlite3_fts5_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -197502,8 +200254,19 @@ static int fts5VocabBestIndexMethod( } } - pInfo->idxNum = idxNum; + /* This virtual table always delivers results in ascending order of + ** the "term" column (column 0). So if the user has requested this + ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the + ** sqlite3_index_info.orderByConsumed flag to tell the core the results + ** are already in sorted order. */ + if( pInfo->nOrderBy==1 + && pInfo->aOrderBy[0].iColumn==0 + && pInfo->aOrderBy[0].desc==0 + ){ + pInfo->orderByConsumed = 1; + } + pInfo->idxNum = idxNum; return SQLITE_OK; } diff --git a/Data/SQLite/src/sqlite3.h b/Data/SQLite/src/sqlite3.h index 3b6b07cf8..7ce639160 100644 --- a/Data/SQLite/src/sqlite3.h +++ b/Data/SQLite/src/sqlite3.h @@ -108,7 +108,8 @@ extern "C" { ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since version 3.6.18, SQLite source code has been stored in the +** Since [version 3.6.18] ([dateof:3.6.18]), +** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite @@ -120,13 +121,13 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.14.1" -#define SQLITE_VERSION_NUMBER 3014001 -#define SQLITE_SOURCE_ID "2016-08-11 18:53:32 a12d8059770df4bca59e321c266410344242bf7b" +#define SQLITE_VERSION "3.16.0" +#define SQLITE_VERSION_NUMBER 3016000 +#define SQLITE_SOURCE_ID "2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf" /* ** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version, sqlite3_sourceid +** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros @@ -155,9 +156,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -182,8 +183,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* @@ -222,7 +223,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); +SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -319,8 +320,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -391,7 +392,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -452,7 +453,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( ** [result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include +** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] +** and later) include ** support for additional result codes that provide more detailed information ** about errors. These [extended result codes] are enabled or disabled ** on a per database connection basis using the @@ -976,6 +978,12 @@ struct sqlite3_io_methods { ** on whether or not the file has been renamed, moved, or deleted since it ** was first opened. ** +**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the +** underlying native file handle associated with a file handle. This file +** control interprets its argument as a pointer to a native file handle and +** writes the resulting value there. +** **
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one @@ -1026,6 +1034,8 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 +#define SQLITE_FCNTL_PDB 30 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1390,10 +1400,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1426,7 +1436,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); +SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections @@ -1445,7 +1455,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -1969,13 +1979,36 @@ struct sqlite3_mem_methods { ** be a NULL pointer, in which case the new setting is not reported back. ** ** +**
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    ^This option is used to change the name of the "main" database +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged +** until after the database connection closes. +**
    +** +**
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    +**
    Usually, when a database in wal mode is closed or detached from a +** database handle, SQLite checks if this will mean that there are now no +** connections at all to the database. If so, it performs a checkpoint +** operation before closing the connection. This option may be used to +** override this behaviour. The first parameter passed to this operation +** is an integer - non-zero to disable checkpoints-on-close, or zero (the +** default) to enable them. The second parameter is a pointer to an integer +** into which is written 0 or 1 to indicate whether checkpoints-on-close +** have been disabled - 0 if they are not disabled, 1 if they are. +**
    +** ** */ +#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ /* @@ -1986,7 +2019,7 @@ struct sqlite3_mem_methods { ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid @@ -2038,7 +2071,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff) ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified @@ -2091,7 +2124,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified @@ -2115,7 +2148,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query @@ -2155,7 +2188,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2190,8 +2223,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors @@ -2252,7 +2285,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); /* ** CAPI3REF: Set A Busy Timeout @@ -2275,7 +2308,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*,int(*)(void*,int),vo ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries @@ -2350,7 +2383,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2358,7 +2391,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions @@ -2464,10 +2497,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2557,12 +2590,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void sqlite3_free(void*); +SQLITE_API sqlite3_uint64 sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2587,8 +2620,8 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2611,7 +2644,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks @@ -2694,7 +2727,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2802,9 +2835,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_trace(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_profile(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* @@ -2893,7 +2926,7 @@ SQLITE_API SQLITE_DEPRECATED void *SQLITE_STDCALL sqlite3_profile(sqlite3*, ** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which ** are deprecated. */ -SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( +SQLITE_API int sqlite3_trace_v2( sqlite3*, unsigned uMask, int(*xCallback)(unsigned,void*,void*,void*), @@ -2932,7 +2965,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_trace_v2( ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection @@ -3161,15 +3194,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3215,9 +3248,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* @@ -3261,11 +3294,11 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); /* ** CAPI3REF: Prepared Statement Object @@ -3333,7 +3366,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3485,28 +3518,28 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); **
  • ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3545,8 +3578,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); -SQLITE_API char *SQLITE_STDCALL sqlite3_expanded_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -3577,8 +3610,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_expanded_sql(sqlite3_stmt *pStmt); ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. +** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since +** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and +** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so +** sqlite3_stmt_readonly() returns false for those commands. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -3599,7 +3636,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3763,20 +3800,20 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -3797,7 +3834,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter @@ -3825,7 +3862,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name @@ -3842,7 +3879,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_name()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement @@ -3852,7 +3889,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set @@ -3864,7 +3901,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set @@ -3893,8 +3930,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result @@ -3942,12 +3979,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result @@ -3979,8 +4016,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt* ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement @@ -4041,7 +4078,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** other than [SQLITE_ROW] before any subsequent invocation of ** sqlite3_step(). Failure to reset the prepared statement using ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from -** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], +** sqlite3_step() began ** calling [sqlite3_reset()] automatically in this circumstance rather ** than returning [SQLITE_MISUSE]. This is not considered a compatibility ** break because any application that ever receives an SQLITE_MISUSE error @@ -4060,7 +4098,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set @@ -4081,7 +4119,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -4271,16 +4309,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4308,7 +4346,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object @@ -4335,7 +4373,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions @@ -4435,7 +4473,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4445,7 +4483,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4455,7 +4493,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4501,12 +4539,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif @@ -4556,18 +4594,18 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -4583,7 +4621,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); ** from the result of one [application-defined SQL function] into the ** input of another. */ -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -4599,8 +4637,8 @@ SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); +SQLITE_API void sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context @@ -4645,7 +4683,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions @@ -4660,7 +4698,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions @@ -4672,7 +4710,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data @@ -4726,8 +4764,8 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4863,27 +4901,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* @@ -4898,7 +4936,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int); +SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -4980,14 +5018,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -4995,7 +5033,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -5030,12 +5068,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -5049,11 +5087,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( +SQLITE_API int sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -5067,11 +5105,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( +SQLITE_API int sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -5081,7 +5119,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( +SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5091,7 +5129,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( +SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5113,7 +5151,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5232,7 +5270,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement @@ -5245,7 +5283,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection @@ -5262,7 +5300,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only @@ -5272,7 +5310,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement @@ -5288,7 +5326,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks @@ -5337,8 +5375,8 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks @@ -5389,7 +5427,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], ** and [sqlite3_preupdate_hook()] interfaces. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5404,7 +5442,8 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** and disabled if the argument is false.)^ ** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent @@ -5429,7 +5468,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5445,7 +5484,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection @@ -5459,7 +5498,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); +SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5498,7 +5537,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** from the heap. ** )^ ** -** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without @@ -5511,7 +5551,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5522,7 +5562,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* @@ -5592,7 +5632,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5648,7 +5688,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( ** ** See also the [load_extension() SQL function]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5680,7 +5720,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5718,7 +5758,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void(*xEntryPoint)(void)); +SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading @@ -5730,7 +5770,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void(*xEntryPoint)(void)); ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); +SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading @@ -5738,7 +5778,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void(*xEntryPoint)(v ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); +SQLITE_API void sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered @@ -5892,13 +5932,15 @@ struct sqlite3_module { ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -** structure for SQLite version 3.8.2. If a virtual table extension is +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). +** If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for version 3.9.0. It may therefore only be used if +** was added for [version 3.9.0] ([dateof:3.9.0]). +** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ @@ -5983,13 +6025,13 @@ struct sqlite3_index_info { ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -6052,7 +6094,7 @@ struct sqlite3_vtab_cursor { ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table @@ -6071,7 +6113,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -6170,7 +6212,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -6203,7 +6245,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( ** ** ^This function sets the database handle error code and message. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle @@ -6226,7 +6268,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64) ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB @@ -6242,7 +6284,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally @@ -6271,7 +6313,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); ** ** See also: [sqlite3_blob_write()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally @@ -6313,7 +6355,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, ** ** See also: [sqlite3_blob_read()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects @@ -6344,9 +6386,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes @@ -6462,11 +6504,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object @@ -6576,8 +6618,8 @@ struct sqlite3_mutex_methods { ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* @@ -6596,7 +6638,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ @@ -6617,7 +6659,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files @@ -6652,7 +6694,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -6671,7 +6713,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); +SQLITE_API int sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes @@ -6700,6 +6742,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ +#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 @@ -6734,8 +6777,8 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); ** ** See also: [sqlite3_db_status()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); -SQLITE_API int SQLITE_STDCALL sqlite3_status64( +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int sqlite3_status64( int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, @@ -6860,7 +6903,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections @@ -7003,7 +7046,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7472,16 +7515,16 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification @@ -7598,7 +7641,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7613,8 +7656,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7631,7 +7674,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); ** ** See also: [sqlite3_strlike()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: String LIKE Matching @@ -7654,7 +7697,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zSt ** ** See also: [sqlite3_strglob()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); +SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); /* ** CAPI3REF: Error Logging Interface @@ -7677,7 +7720,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zSt ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook @@ -7713,7 +7756,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7748,7 +7791,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database @@ -7770,7 +7813,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database @@ -7864,7 +7907,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zD ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7900,7 +7943,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7953,7 +7996,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -8058,7 +8101,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -8074,7 +8117,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction @@ -8106,7 +8149,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); ** ^This function does not set the database handle error code or message ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); +SQLITE_API int sqlite3_db_cacheflush(sqlite3*); /* ** CAPI3REF: The pre-update hook. @@ -8186,7 +8229,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); ** ** See also: [sqlite3_update_hook()] */ -SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_preupdate_hook( +#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) +SQLITE_API void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ @@ -8199,10 +8243,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_preupdate_hook( ), void* ); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *); -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_count(sqlite3 *); +SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); +SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +#endif /* ** CAPI3REF: Low-level system error code @@ -8214,11 +8259,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 ** called to get back the underlying "errno" that caused the problem, such ** as ENOSPC, EAUTH, EISDIR, and so forth. */ -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); +SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} +** KEYWORDS: {snapshot} {sqlite3_snapshot} ** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] @@ -8242,7 +8287,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ -typedef struct sqlite3_snapshot sqlite3_snapshot; +typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +} sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot @@ -8253,9 +8300,32 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** schema S in database connection D. ^On success, the ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** ^If schema S of [database connection] D is not a [WAL mode] database -** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)] -** leaves the *P value unchanged and returns an appropriate [error code]. +** If there is not already a read-transaction open on schema S when +** this function is called, one is opened automatically. +** +** The following must be true for this function to succeed. If any of +** the following statements are false when sqlite3_snapshot_get() is +** called, SQLITE_ERROR is returned. The final value of *P is undefined +** in this case. +** +**
      +**
    • The database handle must be in [autocommit mode]. +** +**
    • Schema S of [database connection] D must be a [WAL mode] database. +** +**
    • There must not be a write transaction open on schema S of database +** connection D. +** +**
    • One or more transactions must have been written to the current wal +** file since it was created on disk (by any connection). This means +** that a snapshot cannot be taken on a wal mode database with no wal +** file immediately after it is first opened. At least one transaction +** must be written to it first. +**
    +** +** This function may also return SQLITE_NOMEM. If it is called with the +** database handle in autocommit mode but fails for some other reason, +** whether or not a read transaction is opened on schema S is undefined. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] @@ -8264,7 +8334,7 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -8302,7 +8372,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -8319,7 +8389,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. @@ -8343,11 +8413,33 @@ SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3 ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_cmp( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); +/* +** CAPI3REF: Recover snapshots from a wal file +** EXPERIMENTAL +** +** If all connections disconnect from a database file but do not perform +** a checkpoint, the existing wal file is opened along with the database +** file the next time the database is opened. At this point it is only +** possible to successfully call sqlite3_snapshot_open() to open the most +** recent snapshot of the database (the one at the head of the wal file), +** even though the wal file may contain other valid snapshots for which +** clients have sqlite3_snapshot handles. +** +** This function attempts to scan the wal file associated with database zDb +** of database handle db and make all valid snapshots available to +** sqlite3_snapshot_open(). It is an error if there is already a read +** transaction open on the database, or if the database is not a wal mode +** database. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -8401,7 +8493,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -8427,7 +8519,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -8639,7 +8731,7 @@ int sqlite3session_attach( ** CAPI3REF: Set a table filter on a Session Object. ** ** The second argument (xFilter) is the "filter callback". For changes to rows -** in tables that are not attached to the Session oject, the filter is called +** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. @@ -8905,7 +8997,7 @@ int sqlite3session_isempty(sqlite3_session *pSession); ** [sqlite3changeset_invert()] functions, all changes within the changeset ** that apply to a single table are grouped together. This means that when ** an application iterates through a changeset using an iterator created by -** this function, all changes that relate to a single table are visted +** this function, all changes that relate to a single table are visited ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. @@ -8992,7 +9084,7 @@ int sqlite3changeset_op( ** 0x01 if the corresponding column is part of the tables primary key, or ** 0x00 if it is not. ** -** If argumet pnCol is not NULL, then *pnCol is set to the number of columns +** If argument pnCol is not NULL, then *pnCol is set to the number of columns ** in the table. ** ** If this function is called when the iterator does not point to a valid @@ -9209,12 +9301,12 @@ int sqlite3changeset_concat( /* -** Changegroup handle. +** CAPI3REF: Changegroup Handle */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* -** CAPI3REF: Combine two or more changesets into a single changeset. +** CAPI3REF: Create A New Changegroup Object ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -9251,6 +9343,8 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; int sqlite3changegroup_new(sqlite3_changegroup **pp); /* +** CAPI3REF: Add A Changeset To A Changegroup +** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. ** @@ -9265,7 +9359,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp); ** apply to the same row as a change already present in the changegroup if ** the two rows have the same primary key. ** -** Changes to rows that that do not already appear in the changegroup are +** Changes to rows that do not already appear in the changegroup are ** simply copied into it. Or, if both the new changeset and the changegroup ** contain changes that apply to a single row, the final contents of the ** changegroup depends on the type of each change, as follows: @@ -9326,6 +9420,8 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp); int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); /* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup ** were themselves changesets, the output is a changeset. Or, if the @@ -9354,7 +9450,7 @@ int sqlite3changegroup_output( ); /* -** Delete a changegroup object. +** CAPI3REF: Delete A Changegroup Object */ void sqlite3changegroup_delete(sqlite3_changegroup*); From fc2a3398a5a1d34d9d90cc5906833328fdf356ac Mon Sep 17 00:00:00 2001 From: Jochen Sprickerhof Date: Wed, 4 Jan 2017 23:21:46 +0100 Subject: [PATCH 104/305] Use null as device file as console might not be there --- Foundation/testsuite/src/FileTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/testsuite/src/FileTest.cpp b/Foundation/testsuite/src/FileTest.cpp index 045952b4d..9afa18344 100644 --- a/Foundation/testsuite/src/FileTest.cpp +++ b/Foundation/testsuite/src/FileTest.cpp @@ -258,7 +258,7 @@ void FileTest::testFileAttributes3() #if POCO_OS==POCO_OS_CYGWIN File f("/dev/tty"); #else - File f("/dev/console"); + File f("/dev/null"); #endif #elif defined(POCO_OS_FAMILY_WINDOWS) && !defined(_WIN32_WCE) File f("CON"); From f42f17dd65a0a7baab13cf332c7417f99edc29b4 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 10 Jan 2017 17:08:18 +0100 Subject: [PATCH 105/305] fixed GH #1536: Building with OS X 10.12 SDK and 10.7 deployment target without libc++ fails --- Foundation/include/Poco/AtomicCounter.h | 2 +- build/config/AppleTV | 2 +- build/config/Darwin | 9 +-- build/config/Darwin-clang | 23 +++--- build/config/Darwin-clang-libc++ | 81 +++++++++++++++++++-- build/config/Darwin32 | 9 +-- build/config/Darwin32-clang | 3 +- build/config/Darwin32-clang-libc++ | 11 ++- build/config/Darwin64 | 9 +-- build/config/Darwin64-clang | 3 +- build/config/Darwin64-clang-libc++ | 11 ++- build/config/WatchOS | 2 +- build/config/iPhone | 21 +++--- build/config/iPhone-clang | 94 +------------------------ build/config/iPhone-clang-libc++ | 94 +------------------------ 15 files changed, 132 insertions(+), 242 deletions(-) diff --git a/Foundation/include/Poco/AtomicCounter.h b/Foundation/include/Poco/AtomicCounter.h index f8cdb731a..e5d44f0d5 100644 --- a/Foundation/include/Poco/AtomicCounter.h +++ b/Foundation/include/Poco/AtomicCounter.h @@ -24,7 +24,7 @@ #if POCO_OS == POCO_OS_WINDOWS_NT #include "Poco/UnWindows.h" #elif POCO_OS == POCO_OS_MAC_OS_X - #if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0 || __WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0 + #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 || __TV_OS_VERSION_MAX_ALLOWED >= 100000 || __WATCH_OS_VERSION_MAX_ALLOWED >= 30000 #ifndef POCO_HAVE_STD_ATOMICS #define POCO_HAVE_STD_ATOMICS #endif diff --git a/build/config/AppleTV b/build/config/AppleTV index 4f68d8bab..b20d1bbf7 100644 --- a/build/config/AppleTV +++ b/build/config/AppleTV @@ -90,7 +90,7 @@ RELEASEOPT_LINK = # # System Specific Flags # -SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES -DPOCO_NO_FORK_EXEC +SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_SOCKETADDRESS_DONT_PREFER_IPV4 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES -DPOCO_NO_FORK_EXEC # # System Specific Libraries diff --git a/build/config/Darwin b/build/config/Darwin index 5d025b145..62c26f724 100644 --- a/build/config/Darwin +++ b/build/config/Darwin @@ -1,10 +1,11 @@ # -# $Id +# $Id$ # # Darwin # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.9 (clang++, libc++, x86_64) +# The build settings defined in this file are compatible +# with XCode C++ projects. # -include $(POCO_BASE)/build/config/Darwin-clang +include $(POCO_BASE)/build/config/Darwin-clang-libc++ diff --git a/build/config/Darwin-clang b/build/config/Darwin-clang index 87439711a..80df83397 100644 --- a/build/config/Darwin-clang +++ b/build/config/Darwin-clang @@ -3,8 +3,10 @@ # # Darwin-clang # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.7 (clang, libstdc++, x86_64) +# +# NOTE: This build configuration will build 64-bit binaries. +# Use the Darwin32-clang build configuration to build 32-bit binaries. # # @@ -14,9 +16,10 @@ LINKMODE ?= SHARED POCO_TARGET_OSARCH ?= x86_64 POCO_HOST_OSARCH := $(POCO_TARGET_OSARCH) -ARCHFLAGS ?= -arch $(POCO_TARGET_OSARCH) +ARCHFLAGS ?= -arch $(POCO_TARGET_OSARCH) +OSFLAGS ?= -mmacosx-version-min=10.7 -OPENSSL_DIR ?= /usr/local/opt/openssl/ +OPENSSL_DIR ?= /usr/local/opt/openssl ifeq ($(POCO_TARGET_OSARCH),i386) RORELOCS = -read_only_relocs suppress @@ -49,11 +52,11 @@ SHAREDLIBLINKEXT = .dylib # # Compiler and Linker Flags # -CFLAGS = $(ARCHFLAGS) -CXXFLAGS = $(ARCHFLAGS) -std=c++11 -stdlib=libc++ -Wall -Wno-sign-compare -Wno-unused-variable -Wno-unused-function -Wno-unneeded-internal-declaration -LINKFLAGS = $(ARCHFLAGS) -stdlib=libc++ -SHLIBFLAGS = $(ARCHFLAGS) -stdlib=libc++ -DYLIBFLAGS = $(ARCHFLAGS) -stdlib=libc++ +CFLAGS = $(ARCHFLAGS) $(OSFLAGS) +CXXFLAGS = $(ARCHFLAGS) $(OSFLAGS) -std=c++03 -stdlib=libstdc++ -Wall -Wno-sign-compare -Wno-unused-variable -Wno-unused-function -Wno-unneeded-internal-declaration +LINKFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libstdc++ +SHLIBFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libstdc++ +DYLIBFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libstdc++ STATICOPT_CC = STATICOPT_CXX = STATICOPT_LINK = @@ -75,4 +78,4 @@ SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_STAT64 -I$(OPENSSL_DIR)/include # # System Specific Libraries # -SYSLIBS = -L$(OPENSSL_DIR)/lib -ldl +SYSLIBS = -L$(OPENSSL_DIR)/lib -ldl diff --git a/build/config/Darwin-clang-libc++ b/build/config/Darwin-clang-libc++ index 8bdee2cab..29015b882 100644 --- a/build/config/Darwin-clang-libc++ +++ b/build/config/Darwin-clang-libc++ @@ -3,10 +3,81 @@ # # Darwin-clang-libc++ # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. -# -# Note: provided for backwards compatibility. +# Build settings for Mac OS X 10.9 (clang, libc++, x86_64) +# The build settings defined in this file are compatible +# with XCode C++ projects. +# +# NOTE: This build configuration will build 64-bit binaries. +# Use the Darwin32-clang-libc++ build configuration to build 32-bit binaries. # -include $(POCO_BASE)/build/config/Darwin-clang +# +# General Settings +# +LINKMODE ?= SHARED + +POCO_TARGET_OSARCH ?= x86_64 +POCO_HOST_OSARCH := $(POCO_TARGET_OSARCH) +ARCHFLAGS ?= -arch $(POCO_TARGET_OSARCH) +OSFLAGS ?= -mmacosx-version-min=10.9 + +OPENSSL_DIR ?= /usr/local/opt/openssl + +ifeq ($(POCO_TARGET_OSARCH),i386) +RORELOCS = -read_only_relocs suppress +endif + +# +# Tools +# +CC = $(shell xcrun -find clang) +CXX = $(shell xcrun -find clang++) +LINK = $(CXX) -bind_at_load +LIB = libtool -static -o +RANLIB = ranlib +SHLIB = $(CXX) -dynamiclib -Wl,-install_name,$(POCO_LIB_INSTALLDIR)/$(notdir \$@) -o $@ +DYLIB = $(CXX) -dynamic -bundle $(RORELOCS) -Wl,-bind_at_load -o $@ +SHLIBLN = $(POCO_BASE)/build/script/shlibln +STRIP = +DEP = $(POCO_BASE)/build/script/makedepend.clang +SHELL = sh +RM = rm -rf +CP = cp +MKDIR = mkdir -p + +# +# Extension for Shared Libraries +# +SHAREDLIBEXT = .$(target_version).dylib +SHAREDLIBLINKEXT = .dylib + +# +# Compiler and Linker Flags +# +CFLAGS = $(ARCHFLAGS) $(OSFLAGS) +CXXFLAGS = $(ARCHFLAGS) $(OSFLAGS) -std=c++11 -stdlib=libc++ -Wall -Wno-sign-compare -Wno-unused-variable -Wno-unused-function -Wno-unneeded-internal-declaration +LINKFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libc++ +SHLIBFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libc++ +DYLIBFLAGS = $(ARCHFLAGS) $(OSFLAGS) -stdlib=libc++ +STATICOPT_CC = +STATICOPT_CXX = +STATICOPT_LINK = +SHAREDOPT_CC = -fPIC +SHAREDOPT_CXX = -fPIC +SHAREDOPT_LINK = +DEBUGOPT_CC = -O0 -g -gdwarf-2 -fasm-blocks -D_DEBUG=$(DEBUGLEVEL) +DEBUGOPT_CXX = -O0 -g -gdwarf-2 -fasm-blocks -D_DEBUG=$(DEBUGLEVEL) +DEBUGOPT_LINK = +RELEASEOPT_CC = -DNDEBUG -Os -fasm-blocks +RELEASEOPT_CXX = -DNDEBUG -O2 -fasm-blocks +RELEASEOPT_LINK = + +# +# System Specific Flags +# +SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_STAT64 -I$(OPENSSL_DIR)/include + +# +# System Specific Libraries +# +SYSLIBS = -L$(OPENSSL_DIR)/lib -ldl diff --git a/build/config/Darwin32 b/build/config/Darwin32 index 8fda78525..4e94353d1 100644 --- a/build/config/Darwin32 +++ b/build/config/Darwin32 @@ -1,13 +1,14 @@ # -# $Id +# $Id$ # # Darwin32 # -# Build settings for Mac OS X 10.8 or later, clang, 32-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.9 (clang, libc++, i386) +# The build settings defined in this file are compatible +# with XCode C++ projects. # ARCHFLAGS = -arch i386 POCO_TARGET_OSARCH = i386 -include $(POCO_BASE)/build/config/Darwin-clang +include $(POCO_BASE)/build/config/Darwin-clang-libc++ diff --git a/build/config/Darwin32-clang b/build/config/Darwin32-clang index 27936c74e..f624d805e 100644 --- a/build/config/Darwin32-clang +++ b/build/config/Darwin32-clang @@ -3,8 +3,7 @@ # # Darwin32-clang # -# Build settings for Mac OS X 10.8 or later, clang, 32-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.7 (clang, libstdc++, i386) # ARCHFLAGS = -arch i386 diff --git a/build/config/Darwin32-clang-libc++ b/build/config/Darwin32-clang-libc++ index 085b722f9..eab0ebefd 100644 --- a/build/config/Darwin32-clang-libc++ +++ b/build/config/Darwin32-clang-libc++ @@ -3,13 +3,12 @@ # # Darwin32-clang-libc++ # -# Build settings for Mac OS X 10.8 or later, clang, 32-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. -# -# Note: provided for backwards compatibility. -# +# Build settings for Mac OS X 10.9 (clang, libc++, i386) +# The build settings defined in this file are compatible +# with XCode C++ projects. +# ARCHFLAGS = -arch i386 POCO_TARGET_OSARCH = i386 -include $(POCO_BASE)/build/config/Darwin-clang +include $(POCO_BASE)/build/config/Darwin-clang-libc++ diff --git a/build/config/Darwin64 b/build/config/Darwin64 index 6a9e6cf08..92428622c 100644 --- a/build/config/Darwin64 +++ b/build/config/Darwin64 @@ -1,13 +1,14 @@ # -# $Id +# $Id$ # # Darwin64 # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.9 (clang, libc++, x86_64) +# The build settings defined in this file are compatible +# with XCode C++ projects. # ARCHFLAGS = -arch x86_64 POCO_TARGET_OSARCH = x86_64 -include $(POCO_BASE)/build/config/Darwin-clang +include $(POCO_BASE)/build/config/Darwin-clang-libc++ diff --git a/build/config/Darwin64-clang b/build/config/Darwin64-clang index 48a33699e..c1a258df1 100644 --- a/build/config/Darwin64-clang +++ b/build/config/Darwin64-clang @@ -3,8 +3,7 @@ # # Darwin64-clang # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. +# Build settings for Mac OS X 10.7 (clang, libstdc++, x86_64) # ARCHFLAGS = -arch x86_64 diff --git a/build/config/Darwin64-clang-libc++ b/build/config/Darwin64-clang-libc++ index db717f84f..32dacba49 100644 --- a/build/config/Darwin64-clang-libc++ +++ b/build/config/Darwin64-clang-libc++ @@ -3,13 +3,12 @@ # # Darwin64-clang-libc++ # -# Build settings for Mac OS X 10.8 or later, clang, 64-bits, with C++11 support. -# Build settings are compatible with XCode 7 C++ projects. -# -# Note: provided for backwards compatibility. -# +# Build settings for Mac OS X 10.9 (clang, libc++, x86_64) +# The build settings defined in this file are compatible +# with XCode C++ projects. +# ARCHFLAGS = -arch x86_64 POCO_TARGET_OSARCH = x86_64 -include $(POCO_BASE)/build/config/Darwin-clang +include $(POCO_BASE)/build/config/Darwin-clang-libc++ diff --git a/build/config/WatchOS b/build/config/WatchOS index d576e0235..da5e5b4ae 100644 --- a/build/config/WatchOS +++ b/build/config/WatchOS @@ -90,7 +90,7 @@ RELEASEOPT_LINK = # # System Specific Flags # -SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES -DPOCO_NO_FORK_EXEC +SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_SOCKETADDRESS_DONT_PREFER_IPV4 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES -DPOCO_NO_FORK_EXEC # # System Specific Libraries diff --git a/build/config/iPhone b/build/config/iPhone index 157da92b7..b04801b85 100644 --- a/build/config/iPhone +++ b/build/config/iPhone @@ -1,5 +1,5 @@ # -# $Id: //poco/1.4/build/config/iPhone#4 $ +# $Id: //poco/1.4/build/config/iPhone#2 $ # # iPhone # @@ -23,22 +23,23 @@ LINKMODE ?= STATIC # Otherwise use the version found. IPHONE_SDK ?= iPhoneOS -IPHONE_SDK_ROOT = $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/SDKs +IPHONE_SDK_ROOT ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/SDKs IPHONE_SDK_ROOT_DIR = $(IPHONE_SDK_ROOT)/$(IPHONE_SDK) IPHONE_SDK_BASE = $(shell ls -d $(IPHONE_SDK_ROOT_DIR)$(IPHONE_SDK_VERSION)*.sdk | tail -1) IPHONE_SDK_VERSION_MIN ?= $(patsubst %.sdk,%,$(patsubst $(IPHONE_SDK_ROOT_DIR)%,%,$(IPHONE_SDK_BASE))) POCO_TARGET_OSNAME ?= $(IPHONE_SDK) -POCO_TARGET_OSARCH ?= armv6 +POCO_TARGET_OSARCH ?= arm64 TOOL_PREFIX ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/usr/bin -OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BASE) -mthumb -miphoneos-version-min=$(IPHONE_SDK_VERSION_MIN) -fembed-bitcode +ifneq ($(POCO_TARGET_OSARCH),arm64) +THUMB = -mthumb +endif +OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BASE) $(THUMB) -miphoneos-version-min=$(IPHONE_SDK_VERSION_MIN) -fembed-bitcode # # Tools # -# If GCC_VER is defined then use it. -# Otherwise select the latest version -# + CC = $(shell xcrun -find clang) CXX = $(shell xcrun -find clang++) @@ -67,10 +68,10 @@ SHAREDLIBLINKEXT = .dylib CFLAGS = $(OSFLAGS) CFLAGS32 = CFLAGS64 = -CXXFLAGS = $(OSFLAGS) -Wall -Wno-sign-compare +CXXFLAGS = $(OSFLAGS) -std=gnu++11 -stdlib=libc++ -Wall -Wno-sign-compare CXXFLAGS32 = CXXFLAGS64 = -LINKFLAGS = $(OSFLAGS) +LINKFLAGS = $(OSFLAGS) -stdlib=libc++ LINKFLAGS32 = LINKFLAGS64 = STATICOPT_CC = @@ -89,7 +90,7 @@ RELEASEOPT_LINK = # # System Specific Flags # -SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS +SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_SOCKETADDRESS_DONT_PREFER_IPV4 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES # # System Specific Libraries diff --git a/build/config/iPhone-clang b/build/config/iPhone-clang index d40b457a9..76b8f2b55 100644 --- a/build/config/iPhone-clang +++ b/build/config/iPhone-clang @@ -6,96 +6,4 @@ # Build settings for iPhone OS, using Apple's iPhone SDK # -# -# General Settings -# -# iPhone OS does not allow dynamic linking to user libraries -# -LINKMODE ?= STATIC - -# -# If the SDK is defined use it -# Otherwise find the latest version installed -# -# IPHONE_SDK_VERSION = 2.2.1 - -# if IPHONE_SDK_VERSION_MIN is defined use that -# Otherwise use the version found. - -IPHONE_SDK ?= iPhoneOS -IPHONE_SDK_ROOT ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/SDKs -IPHONE_SDK_ROOT_DIR = $(IPHONE_SDK_ROOT)/$(IPHONE_SDK) -IPHONE_SDK_BASE = $(shell ls -d $(IPHONE_SDK_ROOT_DIR)$(IPHONE_SDK_VERSION)*.sdk | tail -1) -IPHONE_SDK_VERSION_MIN ?= $(patsubst %.sdk,%,$(patsubst $(IPHONE_SDK_ROOT_DIR)%,%,$(IPHONE_SDK_BASE))) - -POCO_TARGET_OSNAME ?= $(IPHONE_SDK) -POCO_TARGET_OSARCH ?= armv7 -TOOL_PREFIX ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/usr/bin -ifneq ($(POCO_TARGET_OSARCH),arm64) -THUMB = -mthumb -endif -OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BASE) $(THUMB) -miphoneos-version-min=$(IPHONE_SDK_VERSION_MIN) - -# -# Tools -# -# If GCC_VER is defined then use it. -# Otherwise select the latest version -# - -CC = $(shell xcrun -find clang) -CXX = $(shell xcrun -find clang++) - -LINK = $(CXX) -bind_at_load -LIB = libtool -static -o -RANLIB = ranlib -SHLIB = $(CXX) $(OSFLAGS) -dynamiclib -Wl,-install_name,$@ -o $@ -DYLIB = $(CXX) $(OSFLAGS) -dynamic -bundle -read_only_relocs suppress -Wl,-bind_at_load -o $@ -SHLIBLN = $(POCO_BASE)/build/script/shlibln -STRIP = -DEP = $(POCO_BASE)/build/script/makedepend.gcc -SHELL = sh -RM = rm -rf -CP = cp -MKDIR = mkdir -p - -# -# Extension for Shared Libraries -# -SHAREDLIBEXT = .$(target_version).dylib -SHAREDLIBLINKEXT = .dylib - -# -# Compiler and Linker Flags -# -CFLAGS = $(OSFLAGS) -CFLAGS32 = -CFLAGS64 = -CXXFLAGS = $(OSFLAGS) -Wall -Wno-sign-compare -CXXFLAGS32 = -CXXFLAGS64 = -LINKFLAGS = $(OSFLAGS) -LINKFLAGS32 = -LINKFLAGS64 = -STATICOPT_CC = -STATICOPT_CXX = -STATICOPT_LINK = -SHAREDOPT_CC = -fPIC -SHAREDOPT_CXX = -fPIC -SHAREDOPT_LINK = -DEBUGOPT_CC = -g -D_DEBUG=$(DEBUGLEVEL) -DEBUGOPT_CXX = -g -D_DEBUG=$(DEBUGLEVEL) -DEBUGOPT_LINK = -RELEASEOPT_CC = -DNDEBUG -O2 -RELEASEOPT_CXX = -DNDEBUG -O -RELEASEOPT_LINK = - -# -# System Specific Flags -# -SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES - -# -# System Specific Libraries -# -SYSLIBS = -ldl +include $(POCO_BASE)/build/config/iPhone diff --git a/build/config/iPhone-clang-libc++ b/build/config/iPhone-clang-libc++ index cc39b97b4..c9b47a121 100644 --- a/build/config/iPhone-clang-libc++ +++ b/build/config/iPhone-clang-libc++ @@ -6,96 +6,4 @@ # Build settings for iPhone OS, using Apple's iPhone SDK # -# -# General Settings -# -# iPhone OS does not allow dynamic linking to user libraries -# -LINKMODE ?= STATIC - -# -# If the SDK is defined use it -# Otherwise find the latest version installed -# -# IPHONE_SDK_VERSION = 2.2.1 - -# if IPHONE_SDK_VERSION_MIN is defined use that -# Otherwise use the version found. - -IPHONE_SDK ?= iPhoneOS -IPHONE_SDK_ROOT ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/SDKs -IPHONE_SDK_ROOT_DIR = $(IPHONE_SDK_ROOT)/$(IPHONE_SDK) -IPHONE_SDK_BASE = $(shell ls -d $(IPHONE_SDK_ROOT_DIR)$(IPHONE_SDK_VERSION)*.sdk | tail -1) -IPHONE_SDK_VERSION_MIN ?= $(patsubst %.sdk,%,$(patsubst $(IPHONE_SDK_ROOT_DIR)%,%,$(IPHONE_SDK_BASE))) - -POCO_TARGET_OSNAME ?= $(IPHONE_SDK) -POCO_TARGET_OSARCH ?= armv7 -TOOL_PREFIX ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/usr/bin -ifneq ($(POCO_TARGET_OSARCH),arm64) -THUMB = -mthumb -endif -OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BASE) $(THUMB) -miphoneos-version-min=$(IPHONE_SDK_VERSION_MIN) - -# -# Tools -# -# If GCC_VER is defined then use it. -# Otherwise select the latest version -# - -CC = $(shell xcrun -find clang) -CXX = $(shell xcrun -find clang++) - -LINK = $(CXX) -bind_at_load -LIB = libtool -static -o -RANLIB = ranlib -SHLIB = $(CXX) $(OSFLAGS) -dynamiclib -Wl,-install_name,$@ -o $@ -DYLIB = $(CXX) $(OSFLAGS) -dynamic -bundle -read_only_relocs suppress -Wl,-bind_at_load -o $@ -SHLIBLN = $(POCO_BASE)/build/script/shlibln -STRIP = -DEP = $(POCO_BASE)/build/script/makedepend.gcc -SHELL = sh -RM = rm -rf -CP = cp -MKDIR = mkdir -p - -# -# Extension for Shared Libraries -# -SHAREDLIBEXT = .$(target_version).dylib -SHAREDLIBLINKEXT = .dylib - -# -# Compiler and Linker Flags -# -CFLAGS = $(OSFLAGS) -CFLAGS32 = -CFLAGS64 = -CXXFLAGS = $(OSFLAGS) -std=c++11 -stdlib=libc++ -Wall -Wno-sign-compare -CXXFLAGS32 = -CXXFLAGS64 = -LINKFLAGS = $(OSFLAGS) -stdlib=libc++ -LINKFLAGS32 = -LINKFLAGS64 = -STATICOPT_CC = -STATICOPT_CXX = -STATICOPT_LINK = -SHAREDOPT_CC = -fPIC -SHAREDOPT_CXX = -fPIC -SHAREDOPT_LINK = -DEBUGOPT_CC = -g -D_DEBUG=$(DEBUGLEVEL) -DEBUGOPT_CXX = -g -D_DEBUG=$(DEBUGLEVEL) -DEBUGOPT_LINK = -RELEASEOPT_CC = -DNDEBUG -O2 -RELEASEOPT_CXX = -DNDEBUG -O -RELEASEOPT_LINK = - -# -# System Specific Flags -# -SYSFLAGS = -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES - -# -# System Specific Libraries -# -SYSLIBS = -ldl +include $(POCO_BASE)/build/config/iPhone From c7753d7fb4528f4ab7309d99400d732d97da4eee Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 10 Jan 2017 17:14:42 +0100 Subject: [PATCH 106/305] fixed GH #1537: Need to add multiple cflags parameters to configure --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 17f1da0cf..816b4b892 100755 --- a/configure +++ b/configure @@ -181,7 +181,7 @@ while [ $# -ge 1 ]; do odbcinclude="`echo ${1} | awk '{print substr($0,16)}'`" ;; --cflags=*) - flags="`echo ${1} | awk '{print substr($0,10)}'`" ;; + flags="$flags `echo ${1} | awk '{print substr($0,10)}'`" ;; --no-samples) samples="" ;; From ffa7b5a43013fd714b6bb586c4b260343f23eb86 Mon Sep 17 00:00:00 2001 From: proller Date: Wed, 11 Jan 2017 17:14:14 +0300 Subject: [PATCH 107/305] virtual ServerApplication::waitForTerminationRequest usage: https://github.com/yandex/ClickHouse/blob/master/libs/libdaemon/include/daemon/BaseDaemon.h#L54 https://github.com/yandex/ClickHouse/blob/master/libs/libdaemon/src/BaseDaemon.cpp#L977 --- Util/include/Poco/Util/ServerApplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/include/Poco/Util/ServerApplication.h b/Util/include/Poco/Util/ServerApplication.h index c4ddc118b..ccd93c123 100644 --- a/Util/include/Poco/Util/ServerApplication.h +++ b/Util/include/Poco/Util/ServerApplication.h @@ -163,7 +163,7 @@ public: protected: int run(); - void waitForTerminationRequest(); + virtual void waitForTerminationRequest(); #if !defined(_WIN32_WCE) void defineOptions(OptionSet& options); #endif From cc2f754d4d1d3b82dc70299cc4bd220e36005e7b Mon Sep 17 00:00:00 2001 From: proller Date: Wed, 11 Jan 2017 19:19:49 +0300 Subject: [PATCH 108/305] Net::HTTPSession: split timeout to connection, recieve, send --- Net/include/Poco/Net/HTTPSession.h | 14 ++++++++++---- Net/src/HTTPSession.cpp | 26 ++++++++++++++++++++------ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Net/include/Poco/Net/HTTPSession.h b/Net/include/Poco/Net/HTTPSession.h index 0b01c2ca8..0dec01779 100644 --- a/Net/include/Poco/Net/HTTPSession.h +++ b/Net/include/Poco/Net/HTTPSession.h @@ -55,7 +55,10 @@ public: void setTimeout(const Poco::Timespan& timeout); /// Sets the timeout for the HTTP session. - + + void setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout); + /// Sets different timeouts for the HTTP session. + Poco::Timespan getTimeout() const; /// Returns the timeout for the HTTP session. @@ -171,7 +174,8 @@ protected: private: enum { - HTTP_DEFAULT_TIMEOUT = 60000000 + HTTP_DEFAULT_TIMEOUT = 60000000, + HTTP_DEFAULT_CONNECTION_TIMEOUT = 30000000 }; HTTPSession(const HTTPSession&); @@ -182,7 +186,9 @@ private: char* _pCurrent; char* _pEnd; bool _keepAlive; - Poco::Timespan _timeout; + Poco::Timespan _connectionTimeout; + Poco::Timespan _receiveTimeout; + Poco::Timespan _sendTimeout; Poco::Exception* _pException; Poco::Any _data; @@ -204,7 +210,7 @@ inline bool HTTPSession::getKeepAlive() const inline Poco::Timespan HTTPSession::getTimeout() const { - return _timeout; + return _receiveTimeout; } diff --git a/Net/src/HTTPSession.cpp b/Net/src/HTTPSession.cpp index 030ec7246..173f6d079 100644 --- a/Net/src/HTTPSession.cpp +++ b/Net/src/HTTPSession.cpp @@ -32,7 +32,9 @@ HTTPSession::HTTPSession(): _pCurrent(0), _pEnd(0), _keepAlive(false), - _timeout(HTTP_DEFAULT_TIMEOUT), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), _pException(0) { } @@ -44,7 +46,9 @@ HTTPSession::HTTPSession(const StreamSocket& socket): _pCurrent(0), _pEnd(0), _keepAlive(false), - _timeout(HTTP_DEFAULT_TIMEOUT), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), _pException(0) { } @@ -56,7 +60,9 @@ HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive): _pCurrent(0), _pEnd(0), _keepAlive(keepAlive), - _timeout(HTTP_DEFAULT_TIMEOUT), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), _pException(0) { } @@ -91,7 +97,14 @@ void HTTPSession::setKeepAlive(bool keepAlive) void HTTPSession::setTimeout(const Poco::Timespan& timeout) { - _timeout = timeout; + setTimeout(timeout, timeout, timeout); +} + +void HTTPSession::setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout) +{ + _connectionTimeout = connectionTimeout; + _sendTimeout = sendTimeout; + _receiveTimeout = receiveTimeout; } @@ -181,8 +194,9 @@ bool HTTPSession::connected() const void HTTPSession::connect(const SocketAddress& address) { - _socket.connect(address, _timeout); - _socket.setReceiveTimeout(_timeout); + _socket.connect(address, _connectionTimeout); + _socket.setReceiveTimeout(_receiveTimeout); + _socket.setSendTimeout(_sendTimeout); _socket.setNoDelay(true); // There may be leftover data from a previous (failed) request in the buffer, // so we clear it. From 5ac7959b11d732d9949843d139e9a1a3d554208e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 12 Jan 2017 15:59:15 +0100 Subject: [PATCH 109/305] fixed GH #1212: Lost WebSocket Frames after Client Websocket Handshake is complete Conflicts: Net/include/Poco/Net/HTTPServerRequestImpl.h --- Net/include/Poco/Net/HTTPServerRequestImpl.h | 12 +++++++++ Net/include/Poco/Net/HTTPSession.h | 9 +++++++ Net/include/Poco/Net/WebSocketImpl.h | 11 ++++++-- Net/src/HTTPSession.cpp | 7 +++++ Net/src/WebSocket.cpp | 7 +++-- Net/src/WebSocketImpl.cpp | 27 +++++++++++++++++--- 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Net/include/Poco/Net/HTTPServerRequestImpl.h b/Net/include/Poco/Net/HTTPServerRequestImpl.h index 0abf0b53e..b5845cbc6 100644 --- a/Net/include/Poco/Net/HTTPServerRequestImpl.h +++ b/Net/include/Poco/Net/HTTPServerRequestImpl.h @@ -83,6 +83,12 @@ public: StreamSocket detachSocket(); /// Returns the underlying socket after detaching /// it from the server session. + + HTTPServerSession& session(); + /// Returns the underlying HTTPServerSession. + +protected: + static const std::string EXPECT; private: HTTPServerResponseImpl& _response; @@ -129,6 +135,12 @@ inline HTTPServerResponse& HTTPServerRequestImpl::response() const } +inline HTTPServerSession& HTTPServerRequestImpl::session() +{ + return _session; +} + + } } // namespace Poco::Net diff --git a/Net/include/Poco/Net/HTTPSession.h b/Net/include/Poco/Net/HTTPSession.h index 0dec01779..0ee04c0e2 100644 --- a/Net/include/Poco/Net/HTTPSession.h +++ b/Net/include/Poco/Net/HTTPSession.h @@ -25,6 +25,7 @@ #include "Poco/Timespan.h" #include "Poco/Exception.h" #include "Poco/Any.h" +#include "Poco/Buffer.h" #include @@ -103,6 +104,14 @@ public: StreamSocket& socket(); /// Returns a reference to the underlying socket. + + void drainBuffer(Poco::Buffer& buffer); + /// Copies all bytes remaining in the internal buffer to the + /// given Poco::Buffer, resizing it as necessary. + /// + /// This is usually used together with detachSocket() to + /// obtain any data already read from the socket, but not + /// yet processed. protected: HTTPSession(); diff --git a/Net/include/Poco/Net/WebSocketImpl.h b/Net/include/Poco/Net/WebSocketImpl.h index fc1135dcc..9fa91e80d 100644 --- a/Net/include/Poco/Net/WebSocketImpl.h +++ b/Net/include/Poco/Net/WebSocketImpl.h @@ -23,19 +23,23 @@ #include "Poco/Net/StreamSocketImpl.h" #include "Poco/Buffer.h" #include "Poco/Random.h" +#include "Poco/Buffer.h" namespace Poco { namespace Net { +class HTTPSession; + + class Net_API WebSocketImpl: public StreamSocketImpl /// This class implements a WebSocket, according /// to the WebSocket protocol described in RFC 6455. { public: - WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, bool mustMaskPayload); - /// Creates a StreamSocketImpl using the given native socket. + WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload); + /// Creates a WebSocketImpl. // StreamSocketImpl virtual int sendBytes(const void* buffer, int length, int flags); @@ -88,12 +92,15 @@ protected: int receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask); int receiveNBytes(void* buffer, int bytes); + int receiveSomeBytes(char* buffer, int bytes); virtual ~WebSocketImpl(); private: WebSocketImpl(); StreamSocketImpl* _pStreamSocketImpl; + Poco::Buffer _buffer; + int _bufferOffset; int _frameFlags; bool _mustMaskPayload; Poco::Random _rnd; diff --git a/Net/src/HTTPSession.cpp b/Net/src/HTTPSession.cpp index 173f6d079..b9b615d58 100644 --- a/Net/src/HTTPSession.cpp +++ b/Net/src/HTTPSession.cpp @@ -252,4 +252,11 @@ void HTTPSession::attachSessionData(const Poco::Any& data) } +void HTTPSession::drainBuffer(Poco::Buffer& buffer) +{ + buffer.assign(_pCurrent, static_cast(_pEnd - _pCurrent)); + _pCurrent = _pEnd; +} + + } } // namespace Poco::Net diff --git a/Net/src/WebSocket.cpp b/Net/src/WebSocket.cpp index 485236f32..fd6a600dc 100644 --- a/Net/src/WebSocket.cpp +++ b/Net/src/WebSocket.cpp @@ -19,6 +19,7 @@ #include "Poco/Net/HTTPServerRequestImpl.h" #include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPServerSession.h" #include "Poco/Net/NetException.h" #include "Poco/MemoryStream.h" #include "Poco/NullStream.h" @@ -144,7 +145,9 @@ WebSocketImpl* WebSocket::accept(HTTPServerRequest& request, HTTPServerResponse& response.set("Sec-WebSocket-Accept", computeAccept(key)); response.setContentLength(0); response.send().flush(); - return new WebSocketImpl(static_cast(static_cast(request).detachSocket().impl()), false); + + HTTPServerRequestImpl& requestImpl = static_cast(request); + return new WebSocketImpl(static_cast(requestImpl.detachSocket().impl()), requestImpl.session(), false); } else throw WebSocketException("No WebSocket handshake", WS_ERR_NO_HANDSHAKE); } @@ -212,7 +215,7 @@ WebSocketImpl* WebSocket::completeHandshake(HTTPClientSession& cs, HTTPResponse& std::string accept = response.get("Sec-WebSocket-Accept", ""); if (accept != computeAccept(key)) throw WebSocketException("Invalid or missing Sec-WebSocket-Accept header in handshake response", WS_ERR_HANDSHAKE_ACCEPT); - return new WebSocketImpl(static_cast(cs.detachSocket().impl()), true); + return new WebSocketImpl(static_cast(cs.detachSocket().impl()), cs, true); } diff --git a/Net/src/WebSocketImpl.cpp b/Net/src/WebSocketImpl.cpp index 0e5ac6075..de209e81f 100644 --- a/Net/src/WebSocketImpl.cpp +++ b/Net/src/WebSocketImpl.cpp @@ -17,6 +17,7 @@ #include "Poco/Net/WebSocketImpl.h" #include "Poco/Net/NetException.h" #include "Poco/Net/WebSocket.h" +#include "Poco/Net/HTTPSession.h" #include "Poco/Buffer.h" #include "Poco/BinaryWriter.h" #include "Poco/BinaryReader.h" @@ -29,14 +30,17 @@ namespace Poco { namespace Net { -WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, bool mustMaskPayload): +WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload): StreamSocketImpl(pStreamSocketImpl->sockfd()), _pStreamSocketImpl(pStreamSocketImpl), + _buffer(0), + _bufferOffset(0), _frameFlags(0), _mustMaskPayload(mustMaskPayload) { poco_check_ptr(pStreamSocketImpl); _pStreamSocketImpl->duplicate(); + session.drainBuffer(_buffer); } @@ -211,12 +215,12 @@ int WebSocketImpl::receiveBytes(Poco::Buffer& buffer, int) int WebSocketImpl::receiveNBytes(void* buffer, int bytes) { - int received = _pStreamSocketImpl->receiveBytes(reinterpret_cast(buffer), bytes); + int received = receiveSomeBytes(reinterpret_cast(buffer), bytes); if (received > 0) { while (received < bytes) { - int n = _pStreamSocketImpl->receiveBytes(reinterpret_cast(buffer) + received, bytes - received); + int n = receiveSomeBytes(reinterpret_cast(buffer) + received, bytes - received); if (n > 0) received += n; else @@ -227,6 +231,23 @@ int WebSocketImpl::receiveNBytes(void* buffer, int bytes) } +int WebSocketImpl::receiveSomeBytes(char* buffer, int bytes) +{ + int n = _buffer.size() - _bufferOffset; + if (n > 0) + { + if (bytes < n) n = bytes; + std::memcpy(buffer, _buffer.begin() + _bufferOffset, n); + _bufferOffset += n; + return n; + } + else + { + return _pStreamSocketImpl->receiveBytes(buffer, bytes); + } +} + + SocketImpl* WebSocketImpl::acceptConnection(SocketAddress& clientAddr) { throw Poco::InvalidAccessException("Cannot acceptConnection() on a WebSocketImpl"); From a44217d0a20d3019174a9fc79a7f2d70c326207c Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 12 Jan 2017 16:12:20 +0100 Subject: [PATCH 110/305] remove unneeded declaration introduced through cherry-pick --- Net/include/Poco/Net/HTTPServerRequestImpl.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Net/include/Poco/Net/HTTPServerRequestImpl.h b/Net/include/Poco/Net/HTTPServerRequestImpl.h index b5845cbc6..332c1a607 100644 --- a/Net/include/Poco/Net/HTTPServerRequestImpl.h +++ b/Net/include/Poco/Net/HTTPServerRequestImpl.h @@ -86,9 +86,6 @@ public: HTTPServerSession& session(); /// Returns the underlying HTTPServerSession. - -protected: - static const std::string EXPECT; private: HTTPServerResponseImpl& _response; From 9cce6b2dd1c6f1eec86b87c6517967b2f1cc1460 Mon Sep 17 00:00:00 2001 From: Marian Krivos Date: Thu, 12 Jan 2017 20:02:03 +0100 Subject: [PATCH 111/305] update to sqlite 3.16.2 --- Data/SQLite/src/sqlite3.c | 229 +++++++++++++++++++++++++++----------- Data/SQLite/src/sqlite3.h | 14 ++- 2 files changed, 170 insertions(+), 73 deletions(-) diff --git a/Data/SQLite/src/sqlite3.c b/Data/SQLite/src/sqlite3.c index 40bcbefe6..7f5e75921 100644 --- a/Data/SQLite/src/sqlite3.c +++ b/Data/SQLite/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.16.0. By combining all the individual C code files into this +** version 3.16.2. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -381,9 +381,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.16.0" -#define SQLITE_VERSION_NUMBER 3016000 -#define SQLITE_SOURCE_ID "2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf" +#define SQLITE_VERSION "3.16.2" +#define SQLITE_VERSION_NUMBER 3016002 +#define SQLITE_SOURCE_ID "2017-01-06 16:32:41 a65a62893ca8319e89e48b8a38cf8a59c69a8209" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -4156,8 +4156,12 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); ** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^This routine returns 0 if pStmt is an SQL -** statement that does not return data (for example an [UPDATE]). +** [prepared statement]. ^If this routine returns 0, that means the +** [prepared statement] returns no data (for example an [UPDATE]). +** ^However, just because this routine returns a positive number does not +** mean that one or more rows of data will be returned. ^A SELECT statement +** will always have a positive sqlite3_column_count() but depending on the +** WHERE clause constraints and the table content, it might return no rows. ** ** See also: [sqlite3_data_count()] */ @@ -12861,8 +12865,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); +SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #else # define sqlite3VdbeVerifyNoMallocRequired(A,B) +# define sqlite3VdbeVerifyNoResultRow(A) #endif SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); @@ -70277,6 +70283,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert( (pVal->flags & MEM_RowSet)==0 ); assert( (pVal->flags & (MEM_Null))==0 ); if( pVal->flags & (MEM_Blob|MEM_Str) ){ + if( ExpandBlob(pVal) ) return 0; pVal->flags |= MEM_Str; if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); @@ -71625,6 +71632,22 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){ } #endif +/* +** Verify that the VM passed as the only argument does not contain +** an OP_ResultRow opcode. Fail an assert() if it does. This is used +** by code in pragma.c to ensure that the implementation of certain +** pragmas comports with the flags specified in the mkpragmatab.tcl +** script. +*/ +#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) +SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){ + int i; + for(i=0; inOp; i++){ + assert( p->aOp[i].opcode!=OP_ResultRow ); + } +} +#endif + /* ** This function returns a pointer to the array of opcodes associated with ** the Vdbe passed as the first argument. It is the callers responsibility @@ -90663,9 +90686,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( assert( pVector->flags & EP_xIsSelect ); /* The TK_SELECT_COLUMN Expr node: ** - ** pLeft: pVector containing TK_SELECT + ** pLeft: pVector containing TK_SELECT. Not deleted. ** pRight: not used. But recursively deleted. ** iColumn: Index of a column in pVector + ** iTable: 0 or the number of columns on the LHS of an assignment ** pLeft->iTable: First in an array of register holding result, or 0 ** if the result is not yet computed. ** @@ -91337,7 +91361,7 @@ static int dupedExprStructSize(Expr *p, int flags){ assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags ){ + if( 0==flags || p->op==TK_SELECT_COLUMN ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); @@ -91480,6 +91504,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; + assert( p->iColumn==0 || p->pRight==0 ); + assert( p->pRight==0 || p->pRight==p->pLeft ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } @@ -91542,6 +91568,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags) ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; + Expr *pPriorSelectCol = 0; assert( db!=0 ); if( p==0 ) return 0; pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); @@ -91556,7 +91583,24 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags) pOldItem = p->a; for(i=0; inExpr; i++, pItem++, pOldItem++){ Expr *pOldExpr = pOldItem->pExpr; + Expr *pNewExpr; pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); + if( pOldExpr + && pOldExpr->op==TK_SELECT_COLUMN + && (pNewExpr = pItem->pExpr)!=0 + ){ + assert( pNewExpr->iColumn==0 || i>0 ); + if( pNewExpr->iColumn==0 ){ + assert( pOldExpr->pLeft==pOldExpr->pRight ); + pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight; + }else{ + assert( i>0 ); + assert( pItem[-1].pExpr!=0 ); + assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 ); + assert( pPriorSelectCol==pItem[-1].pExpr->pLeft ); + pNewExpr->pLeft = pPriorSelectCol; + } + } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; @@ -91748,13 +91792,19 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( ** exit prior to this routine being invoked */ if( NEVER(pColumns==0) ) goto vector_append_error; if( pExpr==0 ) goto vector_append_error; - n = sqlite3ExprVectorSize(pExpr); - if( pColumns->nId!=n ){ + + /* If the RHS is a vector, then we can immediately check to see that + ** the size of the RHS and LHS match. But if the RHS is a SELECT, + ** wildcards ("*") in the result set of the SELECT must be expanded before + ** we can do the size check, so defer the size check until code generation. + */ + if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pColumns->nId, n); goto vector_append_error; } - for(i=0; inId; i++){ Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i); pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); if( pList ){ @@ -91763,11 +91813,20 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( pColumns->a[i].zName = 0; } } + if( pExpr->op==TK_SELECT ){ if( pList && pList->a[iFirst].pExpr ){ - assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN ); - pList->a[iFirst].pExpr->pRight = pExpr; + Expr *pFirst = pList->a[iFirst].pExpr; + assert( pFirst->op==TK_SELECT_COLUMN ); + + /* Store the SELECT statement in pRight so it will be deleted when + ** sqlite3ExprListDelete() is called */ + pFirst->pRight = pExpr; pExpr = 0; + + /* Remember the size of the LHS in iTable so that we can check that + ** the RHS and LHS sizes match during code generation. */ + pFirst->iTable = pColumns->nId; } } @@ -93961,9 +94020,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) break; } case TK_SELECT_COLUMN: { + int n; if( pExpr->pLeft->iTable==0 ){ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0); } + assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT ); + if( pExpr->iTable + && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) + ){ + sqlite3ErrorMsg(pParse, "%d columns assigned %d values", + pExpr->iTable, n); + } return pExpr->pLeft->iTable + pExpr->iColumn; } case TK_IN: { @@ -109500,12 +109567,25 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( onError = OE_Abort; } - if( ix==0 && pPk==pIdx && onError==OE_Replace && pPk->pNext==0 ){ + /* Collision detection may be omitted if all of the following are true: + ** (1) The conflict resolution algorithm is REPLACE + ** (2) The table is a WITHOUT ROWID table + ** (3) There are no secondary indexes on the table + ** (4) No delete triggers need to be fired if there is a conflict + ** (5) No FK constraint counters need to be updated if a conflict occurs. + */ + if( (ix==0 && pIdx->pNext==0) /* Condition 3 */ + && pPk==pIdx /* Condition 2 */ + && onError==OE_Replace /* Condition 1 */ + && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ + 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) + && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ + (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) + ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } - /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); @@ -111751,11 +111831,12 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ -#define PragFlg_ReadOnly 0x04 /* Read-only HEADER_VALUE */ -#define PragFlg_Result0 0x08 /* Acts as query when no argument */ -#define PragFlg_Result1 0x10 /* Acts as query when has one argument */ -#define PragFlg_SchemaOpt 0x20 /* Schema restricts name search if present */ -#define PragFlg_SchemaReq 0x40 /* Schema required - "main" is default */ +#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ +#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */ +#define PragFlg_Result0 0x10 /* Acts as query when no argument */ +#define PragFlg_Result1 0x20 /* Acts as query when has one argument */ +#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */ +#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */ /* Names of columns for pragmas that return multi-column result ** or that return single-column results where the name of the @@ -111832,14 +111913,14 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "application_id", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_Result0, + /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ BTREE_APPLICATION_ID }, #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) {/* zName: */ "auto_vacuum", /* ePragTyp: */ PragTyp_AUTO_VACUUM, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -111847,7 +111928,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) {/* zName: */ "automatic_index", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_AutoIndex }, #endif @@ -111860,31 +111941,31 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "cache_size", /* ePragTyp: */ PragTyp_CACHE_SIZE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "cache_spill", /* ePragTyp: */ PragTyp_CACHE_SPILL, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif {/* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, - /* ePragFlg: */ 0, + /* ePragFlg: */ PragFlg_NoColumns, /* ColNames: */ 0, 0, /* iArg: */ 0 }, {/* zName: */ "cell_size_check", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_CellSizeCk }, #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "checkpoint_fullfsync", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_CkptFullFSync }, #endif @@ -111905,21 +111986,21 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "count_changes", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_CountRows }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN {/* zName: */ "data_store_directory", /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, - /* ePragFlg: */ 0, + /* ePragFlg: */ PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "data_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly, + /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ BTREE_DATA_VERSION }, #endif @@ -111933,7 +112014,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) {/* zName: */ "default_cache_size", /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 1, /* iArg: */ 0 }, #endif @@ -111941,7 +112022,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "defer_foreign_keys", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_DeferFKs }, #endif @@ -111949,14 +112030,14 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "empty_result_callbacks", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_NullCallback }, #endif #if !defined(SQLITE_OMIT_UTF16) {/* zName: */ "encoding", /* ePragTyp: */ PragTyp_ENCODING, - /* ePragFlg: */ PragFlg_Result0, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -111978,7 +112059,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "foreign_keys", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_ForeignKeys }, #endif @@ -111986,19 +112067,19 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "freelist_count", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly, + /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ BTREE_FREE_PAGE_COUNT }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "full_column_names", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_FullColNames }, {/* zName: */ "fullfsync", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_FullFSync }, #endif @@ -112018,7 +112099,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_CHECK) {/* zName: */ "ignore_check_constraints", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_IgnoreChecks }, #endif @@ -112076,14 +112157,14 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "legacy_file_format", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_LegacyFileFmt }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE {/* zName: */ "lock_proxy_file", /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, - /* ePragFlg: */ 0, + /* ePragFlg: */ PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -112117,7 +112198,7 @@ static const PragmaName aPragmaName[] = { /* iArg: */ 0 }, {/* zName: */ "page_size", /* ePragTyp: */ PragTyp_PAGE_SIZE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -112131,7 +112212,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "query_only", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_QueryOnly }, #endif @@ -112145,12 +112226,12 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "read_uncommitted", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_ReadUncommitted }, {/* zName: */ "recursive_triggers", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_RecTriggers }, #endif @@ -112164,14 +112245,14 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_ReverseOrder }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "schema_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_Result0, + /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ BTREE_SCHEMA_VERSION }, #endif @@ -112185,13 +112266,13 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "short_column_names", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_ShortColNames }, #endif {/* zName: */ "shrink_memory", /* ePragTyp: */ PragTyp_SHRINK_MEMORY, - /* ePragFlg: */ 0, + /* ePragFlg: */ PragFlg_NoColumns, /* ColNames: */ 0, 0, /* iArg: */ 0 }, {/* zName: */ "soft_heap_limit", @@ -112203,7 +112284,7 @@ static const PragmaName aPragmaName[] = { #if defined(SQLITE_DEBUG) {/* zName: */ "sql_trace", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_SqlTrace }, #endif @@ -112218,7 +112299,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "synchronous", /* ePragTyp: */ PragTyp_SYNCHRONOUS, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -112232,12 +112313,12 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "temp_store", /* ePragTyp: */ PragTyp_TEMP_STORE, - /* ePragFlg: */ PragFlg_Result0, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, {/* zName: */ "temp_store_directory", /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, - /* ePragFlg: */ 0, + /* ePragFlg: */ PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -112249,7 +112330,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "user_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_Result0, + /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ BTREE_USER_VERSION }, #endif @@ -112257,27 +112338,27 @@ static const PragmaName aPragmaName[] = { #if defined(SQLITE_DEBUG) {/* zName: */ "vdbe_addoptrace", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_VdbeAddopTrace }, {/* zName: */ "vdbe_debug", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, {/* zName: */ "vdbe_eqp", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_VdbeEQP }, {/* zName: */ "vdbe_listing", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_VdbeListing }, {/* zName: */ "vdbe_trace", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_VdbeTrace }, #endif @@ -112297,7 +112378,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "writable_schema", /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif @@ -112685,7 +112766,9 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* Register the result column names for pragmas that return results */ - if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 ){ + if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 + && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0) + ){ setPragmaResultColumnNames(v, pPragma); } @@ -114230,6 +114313,15 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* End of the PRAGMA switch */ + /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only + ** purpose is to execute assert() statements to verify that if the + ** PragFlg_NoColumns1 flag is set and the caller specified an argument + ** to the PRAGMA, the implementation has not added any OP_ResultRow + ** instructions to the VM. */ + if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){ + sqlite3VdbeVerifyNoResultRow(v); + } + pragma_out: sqlite3DbFree(db, zLeft); sqlite3DbFree(db, zRight); @@ -116144,8 +116236,7 @@ static void selectInnerLoop( }else{ ecelFlags = 0; } - assert( eDest!=SRT_Table || pSort==0 ); - if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab ){ + if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ /* For each expression in pEList that is a copy of an expression in ** the ORDER BY clause (pSort->pOrderBy), set the associated ** iOrderByCol value to one more than the index of the ORDER BY @@ -116687,6 +116778,7 @@ static void generateSortTail( VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } switch( eDest ){ + case SRT_Table: case SRT_EphemTab: { sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); @@ -189706,7 +189798,7 @@ static void fts5SegIterNext( else if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( &pLeaf->p[pLeaf->szLeaf], iOff - ); + ); pIter->iLeafOffset = iOff; pIter->iEndofDoclist = iOff; bNewTerm = 1; @@ -189740,6 +189832,7 @@ static void fts5SegIterNext( */ int nSz; assert( p->rc==SQLITE_OK ); + assert( pIter->iLeafOffset<=pIter->pLeaf->nn ); fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; @@ -190734,7 +190827,7 @@ static void fts5ChunkIterate( break; }else{ pgno++; - pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); + pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); if( pData==0 ) break; pChunk = &pData->p[4]; nChunk = MIN(nRem, pData->szLeaf - 4); @@ -193496,7 +193589,7 @@ static void fts5IndexIntegrityCheckSegment( ** ignore this b-tree entry. Otherwise, load it into memory. */ if( iIdxLeafpgnoFirst ) continue; iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf); - pLeaf = fts5DataRead(p, iRow); + pLeaf = fts5LeafRead(p, iRow); if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal @@ -196772,7 +196865,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2017-01-06 16:32:41 a65a62893ca8319e89e48b8a38cf8a59c69a8209", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ diff --git a/Data/SQLite/src/sqlite3.h b/Data/SQLite/src/sqlite3.h index 7ce639160..35fa4171d 100644 --- a/Data/SQLite/src/sqlite3.h +++ b/Data/SQLite/src/sqlite3.h @@ -121,9 +121,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.16.0" -#define SQLITE_VERSION_NUMBER 3016000 -#define SQLITE_SOURCE_ID "2017-01-02 11:57:58 04ac0b75b1716541b2b97704f4809cb7ef19cccf" +#define SQLITE_VERSION "3.16.2" +#define SQLITE_VERSION_NUMBER 3016002 +#define SQLITE_SOURCE_ID "2017-01-06 16:32:41 a65a62893ca8319e89e48b8a38cf8a59c69a8209" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -3896,8 +3896,12 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); ** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^This routine returns 0 if pStmt is an SQL -** statement that does not return data (for example an [UPDATE]). +** [prepared statement]. ^If this routine returns 0, that means the +** [prepared statement] returns no data (for example an [UPDATE]). +** ^However, just because this routine returns a positive number does not +** mean that one or more rows of data will be returned. ^A SELECT statement +** will always have a positive sqlite3_column_count() but depending on the +** WHERE clause constraints and the table content, it might return no rows. ** ** See also: [sqlite3_data_count()] */ From 28de783c96e2652abc03e66a79b2e88a2d06a247 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 13 Jan 2017 15:41:50 +0100 Subject: [PATCH 112/305] only use header if C++11 support is available --- Foundation/include/Poco/AtomicCounter.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Foundation/include/Poco/AtomicCounter.h b/Foundation/include/Poco/AtomicCounter.h index e5d44f0d5..61219a912 100644 --- a/Foundation/include/Poco/AtomicCounter.h +++ b/Foundation/include/Poco/AtomicCounter.h @@ -26,7 +26,9 @@ #elif POCO_OS == POCO_OS_MAC_OS_X #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 || __TV_OS_VERSION_MAX_ALLOWED >= 100000 || __WATCH_OS_VERSION_MAX_ALLOWED >= 30000 #ifndef POCO_HAVE_STD_ATOMICS - #define POCO_HAVE_STD_ATOMICS + #if __cplusplus >= 201103L + #define POCO_HAVE_STD_ATOMICS + #endif #endif #else #include From cc09e53b6a73337b06bba74295e7818518739bd6 Mon Sep 17 00:00:00 2001 From: Friedrich Wilckens Date: Mon, 16 Jan 2017 17:49:25 -0800 Subject: [PATCH 113/305] Added support for std::tuple to Data/Typehandler.h. --- Data/include/Poco/Data/TypeHandler.h | 128 +++++++++++++++++++++++++++ Data/testsuite/src/DataTest.cpp | 26 +++++- Data/testsuite/src/DataTest.h | 4 + 3 files changed, 157 insertions(+), 1 deletion(-) diff --git a/Data/include/Poco/Data/TypeHandler.h b/Data/include/Poco/Data/TypeHandler.h index 9f7d85c2e..b3ef75538 100644 --- a/Data/include/Poco/Data/TypeHandler.h +++ b/Data/include/Poco/Data/TypeHandler.h @@ -30,6 +30,9 @@ #include "Poco/SharedPtr.h" #include +#if __cplusplus >= 201103L +#include +#endif namespace Poco { namespace Data { @@ -2104,6 +2107,131 @@ private: }; +#if __cplusplus >= 201103L + +template +struct TupleBind +/// Helper for specialization of type handler for std::tuple +{ + template + static typename std::enable_if::type + bind(std::size_t& pos, const std::tuple& t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) + { + using Type = typename std::tuple_element>::type; + TypeHandler::bind(pos, std::get(t), pBinder, dir); + pos += TypeHandler::size(); + TupleBind::bind(pos, t, pBinder, dir); + } + + template + static typename std::enable_if::type + bind(std::size_t& pos, const std::tuple& t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) + {} +}; + + +template +struct TupleSize +/// Helper for specialization of type handler for std::tuple +{ + template + static typename std::enable_if::type + size(std::size_t& sz) + { + using Type = typename std::tuple_element>::type; + sz += TypeHandler::size(); + TupleSize::size(sz); + } + + template + static typename std::enable_if::type + size(std::size_t& sz) + {} +}; + + +template +struct TupleExtract +/// Helper for specialization of type handler for std::tuple +{ + template + static typename std::enable_if::type + extract(std::size_t& pos, std::tuple& t, const std::tuple& defVal, AbstractExtractor::Ptr pExt) + { + using Type = typename std::tuple_element>::type; + TypeHandler::extract(pos, std::get(t), std::get(defVal), pExt); + pos += TypeHandler::size(); + TupleExtract::extract(pos, t, defVal, pExt); + } + + template + static typename std::enable_if::type + extract(std::size_t& pos, std::tuple& t, const std::tuple& defVal, AbstractExtractor::Ptr pExt) + {} +}; + + +template +struct TuplePrepare +/// Helper for specialization of type handler for std::tuple +{ + template + static typename std::enable_if::type + prepare(std::size_t& pos, const std::tuple& t, AbstractPreparator::Ptr pPreparator) + { + using Type = typename std::tuple_element>::type; + TypeHandler::prepare(pos, std::get(t), pPreparator); + pos += TypeHandler::size(); + TuplePrepare::prepare(pos, t, pPreparator); + } + + template + static typename std::enable_if::type + prepare(std::size_t& pos, const std::tuple& t, AbstractPreparator::Ptr pPreparator) + {} +}; + + + +template +class TypeHandler> +/// Specialization of type handler for std::tuple +{ +public: + static void bind(std::size_t pos, const std::tuple & t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) + { + poco_assert_dbg (!pBinder.isNull()); + TupleBind<0>::bind(pos, t, pBinder, dir); + } + + static std::size_t size() + { + std::size_t sz = 0; + TupleSize<0>::size(sz); + return sz; + } + + static void extract(std::size_t pos, std::tuple& t, const std::tuple& defVal, AbstractExtractor::Ptr pExt) + { + poco_assert_dbg (!pExt.isNull()); + TupleExtract<0>::extract(pos, t, defVal, pExt); + } + + static void prepare(std::size_t pos, const std::tuple & t, AbstractPreparator::Ptr pPrepare) + { + poco_assert_dbg (!pPrepare.isNull()); + TuplePrepare<0>::prepare(pos, t, pPrepare); + } + +private: + TypeHandler(); + ~TypeHandler(); + TypeHandler(const TypeHandler&); + TypeHandler& operator=(const TypeHandler&); +}; + +#endif // __cplusplus >= 201103L + } } // namespace Poco::Data diff --git a/Data/testsuite/src/DataTest.cpp b/Data/testsuite/src/DataTest.cpp index 2431d1508..a7681a34a 100644 --- a/Data/testsuite/src/DataTest.cpp +++ b/Data/testsuite/src/DataTest.cpp @@ -38,6 +38,10 @@ #include #include +#if __cplusplus >= 201103L +#include +#endif + using namespace Poco::Data::Keywords; @@ -1400,6 +1404,22 @@ void DataTest::testExternalBindingAndExtraction() } +#if __cplusplus >= 201103L + +void DataTest::testStdTuple() +{ + using Row = std::tuple; + + Session sess(SessionFactory::instance().create("test", "cs")); + Row person = std::make_tuple(std::string("Scott"), std::string("Washington, DC"), 42); + sess << "INSERT INTO Person(name, address, age) VALUES (?, ?, ?)", use(person), now; + std::vector rows; + sess << "SELECT name, address, age FROM Person", into(rows) , now; +} + +#endif // __cplusplus >= 201103L + + void DataTest::setUp() { } @@ -1430,7 +1450,11 @@ CppUnit::Test* DataTest::suite() CppUnit_addTest(pSuite, DataTest, testSimpleRowFormatter); CppUnit_addTest(pSuite, DataTest, testJSONRowFormatter); CppUnit_addTest(pSuite, DataTest, testDateAndTime); - CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction); + CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction); +#if __cplusplus >= 201103L + CppUnit_addTest(pSuite, DataTest, testStdTuple); +#endif + return pSuite; } diff --git a/Data/testsuite/src/DataTest.h b/Data/testsuite/src/DataTest.h index 091bb328b..fe38ca9ed 100644 --- a/Data/testsuite/src/DataTest.h +++ b/Data/testsuite/src/DataTest.h @@ -47,6 +47,10 @@ public: void testDateAndTime(); void testExternalBindingAndExtraction(); +#if __cplusplus >= 201103L + void testStdTuple(); +#endif + void setUp(); void tearDown(); From bd19e0a0fecbd013330b7063db8c179c0d5818c4 Mon Sep 17 00:00:00 2001 From: Friedrich Wilckens Date: Mon, 16 Jan 2017 18:20:14 -0800 Subject: [PATCH 114/305] Data/TypeHandler: use std::size_t instead of size_t for template parameters. --- Data/include/Poco/Data/TypeHandler.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Data/include/Poco/Data/TypeHandler.h b/Data/include/Poco/Data/TypeHandler.h index b3ef75538..6b7da8b14 100644 --- a/Data/include/Poco/Data/TypeHandler.h +++ b/Data/include/Poco/Data/TypeHandler.h @@ -2109,7 +2109,7 @@ private: #if __cplusplus >= 201103L -template +template struct TupleBind /// Helper for specialization of type handler for std::tuple { @@ -2130,7 +2130,7 @@ struct TupleBind }; -template +template struct TupleSize /// Helper for specialization of type handler for std::tuple { @@ -2150,7 +2150,7 @@ struct TupleSize }; -template +template struct TupleExtract /// Helper for specialization of type handler for std::tuple { @@ -2171,7 +2171,7 @@ struct TupleExtract }; -template +template struct TuplePrepare /// Helper for specialization of type handler for std::tuple { From e8537a218881337633b6d80d17d9fcab34769bac Mon Sep 17 00:00:00 2001 From: Pascal Bach Date: Tue, 17 Jan 2017 14:29:42 +0100 Subject: [PATCH 115/305] make zlib build correctly again with newer Windows CE versions --- Foundation/src/zutil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Foundation/src/zutil.c b/Foundation/src/zutil.c index 56534fba0..d6df5ff08 100644 --- a/Foundation/src/zutil.c +++ b/Foundation/src/zutil.c @@ -136,8 +136,8 @@ const char * ZEXPORT zError(err) return ERR_MSG(err); } -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ From 5a8613eb2ac16529bb5509d39e056dbf6f54a923 Mon Sep 17 00:00:00 2001 From: Friedrich Wilckens Date: Tue, 17 Jan 2017 10:39:49 -0800 Subject: [PATCH 116/305] Fixed formatting in DataTest.* --- Data/testsuite/src/DataTest.cpp | 16 ++++++++-------- Data/testsuite/src/DataTest.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Data/testsuite/src/DataTest.cpp b/Data/testsuite/src/DataTest.cpp index a7681a34a..d5f1f6e32 100644 --- a/Data/testsuite/src/DataTest.cpp +++ b/Data/testsuite/src/DataTest.cpp @@ -1408,13 +1408,13 @@ void DataTest::testExternalBindingAndExtraction() void DataTest::testStdTuple() { - using Row = std::tuple; + using Row = std::tuple; - Session sess(SessionFactory::instance().create("test", "cs")); - Row person = std::make_tuple(std::string("Scott"), std::string("Washington, DC"), 42); - sess << "INSERT INTO Person(name, address, age) VALUES (?, ?, ?)", use(person), now; - std::vector rows; - sess << "SELECT name, address, age FROM Person", into(rows) , now; + Session sess(SessionFactory::instance().create("test", "cs")); + Row person = std::make_tuple(std::string("Scott"), std::string("Washington, DC"), 42); + sess << "INSERT INTO Person(name, address, age) VALUES (?, ?, ?)", use(person), now; + std::vector rows; + sess << "SELECT name, address, age FROM Person", into(rows) , now; } #endif // __cplusplus >= 201103L @@ -1450,9 +1450,9 @@ CppUnit::Test* DataTest::suite() CppUnit_addTest(pSuite, DataTest, testSimpleRowFormatter); CppUnit_addTest(pSuite, DataTest, testJSONRowFormatter); CppUnit_addTest(pSuite, DataTest, testDateAndTime); - CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction); + CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction); #if __cplusplus >= 201103L - CppUnit_addTest(pSuite, DataTest, testStdTuple); + CppUnit_addTest(pSuite, DataTest, testStdTuple); #endif diff --git a/Data/testsuite/src/DataTest.h b/Data/testsuite/src/DataTest.h index fe38ca9ed..1dc99d672 100644 --- a/Data/testsuite/src/DataTest.h +++ b/Data/testsuite/src/DataTest.h @@ -48,7 +48,7 @@ public: void testExternalBindingAndExtraction(); #if __cplusplus >= 201103L - void testStdTuple(); + void testStdTuple(); #endif void setUp(); From d98a0ae1e69d276d921e61b1a18505f6950f2c9a Mon Sep 17 00:00:00 2001 From: Friedrich Wilckens Date: Wed, 18 Jan 2017 11:28:24 -0800 Subject: [PATCH 117/305] Add tests for std::tuple to Data/MySQL. --- Data/MySQL/testsuite/src/MySQLTest.cpp | 24 ++++++++++ Data/MySQL/testsuite/src/MySQLTest.h | 7 +++ Data/MySQL/testsuite/src/SQLExecutor.cpp | 56 ++++++++++++++++++++++++ Data/MySQL/testsuite/src/SQLExecutor.h | 5 +++ 4 files changed, 92 insertions(+) diff --git a/Data/MySQL/testsuite/src/MySQLTest.cpp b/Data/MySQL/testsuite/src/MySQLTest.cpp index 7a12e7bdd..5d1ab2208 100644 --- a/Data/MySQL/testsuite/src/MySQLTest.cpp +++ b/Data/MySQL/testsuite/src/MySQLTest.cpp @@ -533,6 +533,26 @@ void MySQLTest::testTupleVector() _pExecutor->tupleVector(); } +#if __cplusplus >= 201103L + +void MySQLTest::testStdTuple() +{ + if (!_pSession) fail ("Test not available."); + + recreateTuplesTable(); + _pExecutor->stdTuples(); +} + + +void MySQLTest::testStdTupleVector() +{ + if (!_pSession) fail ("Test not available."); + + recreateTuplesTable(); + _pExecutor->stdTupleVector(); +} + +#endif // __cplusplus >= 201103L void MySQLTest::testInternalExtraction() { @@ -934,6 +954,10 @@ CppUnit::Test* MySQLTest::suite() CppUnit_addTest(pSuite, MySQLTest, testDouble); CppUnit_addTest(pSuite, MySQLTest, testTuple); CppUnit_addTest(pSuite, MySQLTest, testTupleVector); +#if __cplusplus >= 201103L + CppUnit_addTest(pSuite, MySQLTest, testStdTuple); + CppUnit_addTest(pSuite, MySQLTest, testStdTupleVector); +#endif CppUnit_addTest(pSuite, MySQLTest, testInternalExtraction); CppUnit_addTest(pSuite, MySQLTest, testNull); CppUnit_addTest(pSuite, MySQLTest, testNullableInt); diff --git a/Data/MySQL/testsuite/src/MySQLTest.h b/Data/MySQL/testsuite/src/MySQLTest.h index 5af3c7c0d..d57c9538e 100644 --- a/Data/MySQL/testsuite/src/MySQLTest.h +++ b/Data/MySQL/testsuite/src/MySQLTest.h @@ -89,6 +89,13 @@ public: void testTuple(); void testTupleVector(); +#if __cplusplus >= 201103L + + void testStdTuple(); + void testStdTupleVector(); + +#endif + void testInternalExtraction(); void testNull(); diff --git a/Data/MySQL/testsuite/src/SQLExecutor.cpp b/Data/MySQL/testsuite/src/SQLExecutor.cpp index f76edf250..5b1702eee 100644 --- a/Data/MySQL/testsuite/src/SQLExecutor.cpp +++ b/Data/MySQL/testsuite/src/SQLExecutor.cpp @@ -31,6 +31,10 @@ #include "Poco/Data/MySQL/Connector.h" #include "Poco/Data/MySQL/MySQLException.h" +#if __cplusplus >= 201103L +#include +#endif + #if POCO_MSVS_VERSION == 2015 #define HAVE_STRUCT_TIMESPEC #endif @@ -1476,6 +1480,58 @@ void SQLExecutor::tupleVector() assert (ret == v); } +#if __cplusplus >= 201103L + +void SQLExecutor::stdTuples() +{ + typedef std::tuple TupleType; + std::string funct = "stdTuples()"; + TupleType t = std::make_tuple(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); + + try { *_pSession << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(t), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); } + + TupleType ret = std::make_tuple(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19,-20,-21,-22,-23,-24,-25,-26,-27,-28,-29); + assert (ret != t); + try { *_pSession << "SELECT * FROM Tuples", into(ret), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); } + assert (ret == t); +} + + +void SQLExecutor::stdTupleVector() +{ + typedef std::tuple TupleType; + std::string funct = "stdTupleVector()"; + TupleType t = std::make_tuple(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19); + auto t10 = std::make_tuple(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29); + TupleType t100 = std::make_tuple(100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119); + std::vector v; + v.push_back(t); + v.push_back(t10); + v.push_back(t100); + + try { *_pSession << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(v), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); } + + int count = 0; + try { *_pSession << "SELECT COUNT(*) FROM Tuples", into(count), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); } + assert (v.size() == (std::size_t) count); + + std::vector ret; + try { *_pSession << "SELECT * FROM Tuples", into(ret), now; } + catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); } + catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); } + assert (ret == v); +} + +#endif //__cplusplus >= 201103L + void SQLExecutor::internalExtraction() { diff --git a/Data/MySQL/testsuite/src/SQLExecutor.h b/Data/MySQL/testsuite/src/SQLExecutor.h index 9a19eb2e3..970e33b2e 100644 --- a/Data/MySQL/testsuite/src/SQLExecutor.h +++ b/Data/MySQL/testsuite/src/SQLExecutor.h @@ -91,6 +91,11 @@ public: void tuples(); void tupleVector(); +#if __cplusplus >= 201103L + void stdTuples(); + void stdTupleVector(); +#endif + void internalExtraction(); void doNull(); From 29f259cc24a574574d4fdbd1681ad51124e93bda Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 24 Jan 2017 13:11:41 +0100 Subject: [PATCH 118/305] fix a potential DoS vulnerability by restricting the length of the HTTP chunk size in chunked transfer encoding --- Net/src/HTTPChunkedStream.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Net/src/HTTPChunkedStream.cpp b/Net/src/HTTPChunkedStream.cpp index 8c0b0ff48..e518cfc08 100644 --- a/Net/src/HTTPChunkedStream.cpp +++ b/Net/src/HTTPChunkedStream.cpp @@ -67,7 +67,8 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length) int ch = _session.get(); while (Poco::Ascii::isSpace(ch)) ch = _session.get(); std::string chunkLen; - while (Poco::Ascii::isHexDigit(ch)) { chunkLen += (char) ch; ch = _session.get(); } + while (Poco::Ascii::isHexDigit(ch) && chunkLen.size() < 8) { chunkLen += (char) ch; ch = _session.get(); } + if (ch != eof && !(Poco::Ascii::isSpace(ch) || ch == ';')) return eof; while (ch != eof && ch != '\n') ch = _session.get(); unsigned chunk; if (NumberParser::tryParseHex(chunkLen, chunk)) From 11845334dcb3a957f8d9a368e46066433d3c2ab5 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 24 Jan 2017 13:13:13 +0100 Subject: [PATCH 119/305] fix potential DoS vulnerability (through memory exhaustion) by restricting maximum line length --- Net/include/Poco/Net/DialogSocket.h | 8 +++++--- Net/src/DialogSocket.cpp | 18 +++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Net/include/Poco/Net/DialogSocket.h b/Net/include/Poco/Net/DialogSocket.h index a033979ca..dbd6a970a 100644 --- a/Net/include/Poco/Net/DialogSocket.h +++ b/Net/include/Poco/Net/DialogSocket.h @@ -22,6 +22,7 @@ #include "Poco/Net/Net.h" #include "Poco/Net/StreamSocket.h" +#include namespace Poco { @@ -80,7 +81,7 @@ public: DialogSocket& operator = (const DialogSocket& socket); /// Assignment operator. - + void sendByte(unsigned char ch); /// Sends a single byte over the socket connection. @@ -189,13 +190,14 @@ public: protected: void allocBuffer(); void refill(); - bool receiveLine(std::string& line); - int receiveStatusLine(std::string& line); + bool receiveLine(std::string& line, std::size_t lineLengthLimit = 0); + int receiveStatusLine(std::string& line, std::size_t lineLengthLimit = 0); private: enum { RECEIVE_BUFFER_SIZE = 1024, + MAX_LINE_LENGTH = 4096, EOF_CHAR = -1 }; diff --git a/Net/src/DialogSocket.cpp b/Net/src/DialogSocket.cpp index 6f60777d3..9f864e785 100644 --- a/Net/src/DialogSocket.cpp +++ b/Net/src/DialogSocket.cpp @@ -15,6 +15,7 @@ #include "Poco/Net/DialogSocket.h" +#include "Poco/Exception.h" #include "Poco/Ascii.h" #include @@ -149,20 +150,20 @@ void DialogSocket::sendMessage(const std::string& message, const std::string& ar bool DialogSocket::receiveMessage(std::string& message) { message.clear(); - return receiveLine(message); + return receiveLine(message, MAX_LINE_LENGTH); } int DialogSocket::receiveStatusMessage(std::string& message) { message.clear(); - int status = receiveStatusLine(message); + int status = receiveStatusLine(message, MAX_LINE_LENGTH); if (status < 0) { while (status <= 0) { message += '\n'; - status = receiveStatusLine(message); + status = receiveStatusLine(message, MAX_LINE_LENGTH); } } return status; @@ -236,14 +237,17 @@ void DialogSocket::allocBuffer() } -bool DialogSocket::receiveLine(std::string& line) +bool DialogSocket::receiveLine(std::string& line, std::size_t lineLengthLimit) { // An old wisdom goes: be strict in what you emit // and generous in what you accept. int ch = get(); while (ch != EOF_CHAR && ch != '\r' && ch != '\n') { - line += (char) ch; + if (lineLengthLimit == 0 || line.size() < lineLengthLimit) + line += (char) ch; + else + throw Poco::IOException("Line too long"); ch = get(); } if (ch == '\r' && peek() == '\n') @@ -254,7 +258,7 @@ bool DialogSocket::receiveLine(std::string& line) } -int DialogSocket::receiveStatusLine(std::string& line) +int DialogSocket::receiveStatusLine(std::string& line, std::size_t lineLengthLimit) { int status = 0; int ch = get(); @@ -274,7 +278,7 @@ int DialogSocket::receiveStatusLine(std::string& line) status = -status; } else status = 0; - if (ch != EOF_CHAR) receiveLine(line); + if (ch != EOF_CHAR) receiveLine(line, lineLengthLimit); return status; } From 3eda8f40bbf5c17ec3e09e3de71852643b090d9d Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 24 Jan 2017 13:14:05 +0100 Subject: [PATCH 120/305] fix a potential DoS (through memory exhaustion) by restricting HTML form field name and value sizes --- Net/include/Poco/Net/HTMLForm.h | 21 ++++++++++++++++++-- Net/src/HTMLForm.cpp | 34 +++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Net/include/Poco/Net/HTMLForm.h b/Net/include/Poco/Net/HTMLForm.h index 6e5b80f6b..2c1155e58 100644 --- a/Net/include/Poco/Net/HTMLForm.h +++ b/Net/include/Poco/Net/HTMLForm.h @@ -184,11 +184,19 @@ public: /// Specify 0 for unlimited (not recommended). /// /// The default limit is 100. + + void setValueLengthLimit(int limit); + /// Sets the maximum size for form field values + /// stored as strings. + + int getValueLengthLimit() const; + /// Returns the maximum size for form field values + /// stored as strings. static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded" static const std::string ENCODING_MULTIPART; /// "multipart/form-data" - static const int UNKNOWN_CONTENT_LENGTH; + protected: void readUrl(std::istream& istr); void readMultipart(std::istream& istr, PartHandler& handler); @@ -201,7 +209,9 @@ private: enum Limits { - DFL_FIELD_LIMIT = 100 + DFL_FIELD_LIMIT = 100, + MAX_NAME_LENGTH = 1024, + DFL_MAX_VALUE_LENGTH = 256*1024 }; struct Part @@ -213,6 +223,7 @@ private: typedef std::vector PartVec; int _fieldLimit; + int _valueLengthLimit; std::string _encoding; std::string _boundary; PartVec _parts; @@ -240,6 +251,12 @@ inline int HTMLForm::getFieldLimit() const } +inline int HTMLForm::getValueLengthLimit() const +{ + return _valueLengthLimit; +} + + } } // namespace Poco::Net diff --git a/Net/src/HTMLForm.cpp b/Net/src/HTMLForm.cpp index f6f136f96..3d8261bfd 100644 --- a/Net/src/HTMLForm.cpp +++ b/Net/src/HTMLForm.cpp @@ -73,6 +73,7 @@ private: HTMLForm::HTMLForm(): _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), _encoding(ENCODING_URL) { } @@ -80,27 +81,31 @@ HTMLForm::HTMLForm(): HTMLForm::HTMLForm(const std::string& encoding): _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), _encoding(encoding) { } HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): - _fieldLimit(DFL_FIELD_LIMIT) + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) { load(request, requestBody, handler); } HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): - _fieldLimit(DFL_FIELD_LIMIT) + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) { load(request, requestBody); } HTMLForm::HTMLForm(const HTTPRequest& request): - _fieldLimit(DFL_FIELD_LIMIT) + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) { load(request); } @@ -300,7 +305,10 @@ void HTMLForm::readUrl(std::istream& istr) while (ch != eof && ch != '=' && ch != '&') { if (ch == '+') ch = ' '; - name += (char) ch; + if (name.size() < MAX_NAME_LENGTH) + name += (char) ch; + else + throw HTMLFormException("Field name too long"); ch = istr.get(); } if (ch == '=') @@ -309,7 +317,10 @@ void HTMLForm::readUrl(std::istream& istr) while (ch != eof && ch != '&') { if (ch == '+') ch = ' '; - value += (char) ch; + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); ch = istr.get(); } } @@ -363,7 +374,10 @@ void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) int ch = istr.get(); while (ch != eof) { - value += (char) ch; + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); ch = istr.get(); } add(name, value); @@ -445,4 +459,12 @@ void HTMLForm::setFieldLimit(int limit) } +void HTMLForm::setValueLengthLimit(int limit) +{ + poco_assert (limit >= 0); + + _valueLengthLimit = limit; +} + + } } // namespace Poco::Net From 4149062e7e645d81f90203ed8ef364b9b00b2d21 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Wed, 25 Jan 2017 10:18:21 +0100 Subject: [PATCH 121/305] upgraded bundled zlib to 1.2.11 --- Foundation/include/Poco/zconf.h | 9 +++------ Foundation/include/Poco/zlib.h | 22 +++++++++------------- Foundation/src/adler32.c | 2 ++ Foundation/src/crc32.c | 4 +++- Foundation/src/deflate.c | 19 ++++++++++++------- Foundation/src/gzguts.h | 5 +++-- Foundation/src/inffast.c | 2 +- Foundation/src/inftrees.c | 4 ++-- Foundation/src/trees.c | 4 ++-- Foundation/src/zconf.h | 6 ++++-- Foundation/src/zlib.h | 17 +++++++++-------- 11 files changed, 50 insertions(+), 44 deletions(-) diff --git a/Foundation/include/Poco/zconf.h b/Foundation/include/Poco/zconf.h index eee48179b..4754e9a63 100644 --- a/Foundation/include/Poco/zconf.h +++ b/Foundation/include/Poco/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -251,11 +251,6 @@ # endif # undef z_longlong #endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL @@ -444,11 +439,13 @@ typedef uLong FAR uLongf; # define Z_HAVE_STDARG_H #endif +#ifndef _WIN32_WCE #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif +#endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO diff --git a/Foundation/include/Poco/zlib.h b/Foundation/include/Poco/zlib.h index 3cd6cb852..f09cdaf1e 100644 --- a/Foundation/include/Poco/zlib.h +++ b/Foundation/include/Poco/zlib.h @@ -1,5 +1,5 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.10, January 2nd, 2017 + version 1.2.11, January 15th, 2017 Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.10" -#define ZLIB_VERNUM 0x12a0 +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 10 +#define ZLIB_VER_REVISION 11 #define ZLIB_VER_SUBREVISION 0 /* @@ -712,10 +712,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the - strategy is changed, then the input available so far is compressed with the - old level and strategy using deflate(strm, Z_BLOCK). There are three - approaches for the compression levels 0, 1..3, and 4..9 respectively. The - new level and strategy will take effect at the next call of deflate(). + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not @@ -1883,11 +1884,6 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #endif /* !Z_SOLO */ -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); diff --git a/Foundation/src/adler32.c b/Foundation/src/adler32.c index d0be4380a..8fa49192a 100644 --- a/Foundation/src/adler32.c +++ b/Foundation/src/adler32.c @@ -7,6 +7,8 @@ #include "zutil.h" +#define local static + local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #define BASE 65521U /* largest prime smaller than 65536 */ diff --git a/Foundation/src/crc32.c b/Foundation/src/crc32.c index 9580440c0..a0fe210ab 100644 --- a/Foundation/src/crc32.c +++ b/Foundation/src/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -30,6 +30,8 @@ #include "zutil.h" /* for STDC and FAR definitions */ +#define local static + /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR diff --git a/Foundation/src/deflate.c b/Foundation/src/deflate.c index 2ad890e35..1ec761448 100644 --- a/Foundation/src/deflate.c +++ b/Foundation/src/deflate.c @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.10 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -586,7 +586,8 @@ int ZEXPORT deflateParams(strm, level, strategy) } func = configuration_table[s->level].func; - if ((strategy != s->strategy || func != configuration_table[level].func)) { + if ((strategy != s->strategy || func != configuration_table[level].func) && + s->high_water) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) @@ -1671,8 +1672,6 @@ local block_state deflate_stored(s, flush) len = left + s->strm->avail_in; /* limit len to the input */ if (len > have) len = have; /* limit len to the output */ - if (left > len) - left = len; /* limit window pull to len */ /* If the stored block would be less than min_block in length, or if * unable to copy all of the available input when flushing, then try @@ -1681,13 +1680,13 @@ local block_state deflate_stored(s, flush) */ if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || - len - left != s->strm->avail_in)) + len != left + s->strm->avail_in)) break; /* Make a dummy stored block in pending to get the header bytes, * including any pending bits. This also updates the debugging counts. */ - last = flush == Z_FINISH && len - left == s->strm->avail_in ? 1 : 0; + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; _tr_stored_block(s, (char *)0, 0L, last); /* Replace the lengths in the dummy stored block with len. */ @@ -1699,14 +1698,16 @@ local block_state deflate_stored(s, flush) /* Write the stored block header bytes. */ flush_pending(s->strm); - /* Update debugging counts for the data about to be copied. */ #ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ s->compressed_len += len << 3; s->bits_sent += len << 3; #endif /* Copy uncompressed bytes from the window to next_out. */ if (left) { + if (left > len) + left = len; zmemcpy(s->strm->next_out, s->window + s->block_start, left); s->strm->next_out += left; s->strm->avail_out -= left; @@ -1756,6 +1757,8 @@ local block_state deflate_stored(s, flush) s->block_start = s->strstart; s->insert += MIN(used, s->w_size - s->insert); } + if (s->high_water < s->strstart) + s->high_water = s->strstart; /* If the last block was written to next_out, then done. */ if (last) @@ -1783,6 +1786,8 @@ local block_state deflate_stored(s, flush) read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; } + if (s->high_water < s->strstart) + s->high_water = s->strstart; /* There was not enough avail_out to write a complete worthy or flushed * stored block to next_out. Write a stored block to pending instead, if we diff --git a/Foundation/src/gzguts.h b/Foundation/src/gzguts.h index 990a4d251..75fa55ffc 100644 --- a/Foundation/src/gzguts.h +++ b/Foundation/src/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -35,10 +35,11 @@ # include #endif +#ifndef _WIN32_WCE #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif - +#endif #if defined(_WIN32) || defined(__CYGWIN__) # define WIDECHAR #endif diff --git a/Foundation/src/inffast.c b/Foundation/src/inffast.c index 29eb7d824..0dbd1dbc0 100644 --- a/Foundation/src/inffast.c +++ b/Foundation/src/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013, 2016 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/Foundation/src/inftrees.c b/Foundation/src/inftrees.c index 8a904ddbc..2ea08fc13 100644 --- a/Foundation/src/inftrees.c +++ b/Foundation/src/inftrees.c @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.10 Copyright 1995-2017 Mark Adler "; + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 192, 202}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, diff --git a/Foundation/src/trees.c b/Foundation/src/trees.c index 357f31392..50cf4b457 100644 --- a/Foundation/src/trees.c +++ b/Foundation/src/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2016 Jean-loup Gailly + * Copyright (C) 1995-2017 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -906,7 +906,7 @@ void ZLIB_INTERNAL _tr_align(s) /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. + * trees or store, and write out the encoded block. */ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) deflate_state *s; diff --git a/Foundation/src/zconf.h b/Foundation/src/zconf.h index 5e1d68a00..4754e9a63 100644 --- a/Foundation/src/zconf.h +++ b/Foundation/src/zconf.h @@ -1,9 +1,9 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: //poco/1.4/Foundation/include/Poco/zconf.h#5 $ */ #ifndef ZCONF_H #define ZCONF_H @@ -439,11 +439,13 @@ typedef uLong FAR uLongf; # define Z_HAVE_STDARG_H #endif +#ifndef _WIN32_WCE #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif +#endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO diff --git a/Foundation/src/zlib.h b/Foundation/src/zlib.h index dc90dc8d2..f09cdaf1e 100644 --- a/Foundation/src/zlib.h +++ b/Foundation/src/zlib.h @@ -1,5 +1,5 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.10, January 2nd, 2017 + version 1.2.11, January 15th, 2017 Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.10" -#define ZLIB_VERNUM 0x12a0 +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 10 +#define ZLIB_VER_REVISION 11 #define ZLIB_VER_SUBREVISION 0 /* @@ -712,10 +712,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the - strategy is changed, then the input available so far is compressed with the - old level and strategy using deflate(strm, Z_BLOCK). There are three - approaches for the compression levels 0, 1..3, and 4..9 respectively. The - new level and strategy will take effect at the next call of deflate(). + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not From a39e374aec8ee9797c4047f2e374f77e0c36be82 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 29 Jan 2017 12:46:13 +0100 Subject: [PATCH 122/305] fixed GH #1573: Poco::File::createDirectories() should not throw Poco::FileExistsException --- Foundation/src/File.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Foundation/src/File.cpp b/Foundation/src/File.cpp index 0b2b6aa06..21b84a7b1 100644 --- a/Foundation/src/File.cpp +++ b/Foundation/src/File.cpp @@ -328,7 +328,13 @@ void File::createDirectories() File f(p); f.createDirectories(); } - createDirectoryImpl(); + try + { + createDirectoryImpl(); + } + catch (FileExistsException&) + { + } } } From d5ce48138c4b297f7412d569103be82c14eac510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Thu, 2 Feb 2017 20:22:09 +0100 Subject: [PATCH 123/305] fixed VS2015 solution files for Foundation (missing TestApp and TestLibrary) --- Foundation/Foundation_vs140.sln | 82 +++++++++++++++++++++-------- Foundation/Foundation_x64_vs140.sln | 82 +++++++++++++++++++++-------- 2 files changed, 118 insertions(+), 46 deletions(-) diff --git a/Foundation/Foundation_vs140.sln b/Foundation/Foundation_vs140.sln index 4855955df..12d0fac73 100644 --- a/Foundation/Foundation_vs140.sln +++ b/Foundation/Foundation_vs140.sln @@ -1,5 +1,7 @@ -Microsoft Visual Studio Solution File, Format Version 14.00 -# Visual Studio 2015 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Foundation", "Foundation_vs140.vcxproj", "{B01196CC-B693-4548-8464-2FF60499E73F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs140.vcxproj", "{C812E0B9-69A9-4FA1-A1D4-161CF677BD10}" @@ -7,52 +9,86 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\Test {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApp", "testsuite\TestApp_vs140.vcxproj", "{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}" + ProjectSection(ProjectDependencies) = postProject + {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLibrary", "testsuite\TestLibrary_vs140.vcxproj", "{0955EB03-544B-4BD4-9C10-89CF38078F5F}" + ProjectSection(ProjectDependencies) = postProject + {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution debug_shared|Win32 = debug_shared|Win32 - release_shared|Win32 = release_shared|Win32 - debug_static_mt|Win32 = debug_static_mt|Win32 - release_static_mt|Win32 = release_static_mt|Win32 debug_static_md|Win32 = debug_static_md|Win32 + debug_static_mt|Win32 = debug_static_mt|Win32 + release_shared|Win32 = release_shared|Win32 release_static_md|Win32 = release_static_md|Win32 + release_static_mt|Win32 = release_static_mt|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|Win32.Build.0 = debug_shared|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.ActiveCfg = release_shared|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.Build.0 = release_shared|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.Deploy.0 = release_shared|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.Build.0 = release_shared|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|Win32.Deploy.0 = release_shared|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|Win32.Build.0 = release_static_md|Win32 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|Win32.Build.0 = debug_shared|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.ActiveCfg = release_shared|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.Build.0 = release_shared|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.Deploy.0 = release_shared|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.Build.0 = release_shared|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|Win32.Deploy.0 = release_shared|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|Win32.Build.0 = release_static_md|Win32 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|Win32.Build.0 = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_md|Win32.Build.0 = release_static_md|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_md|Win32.ActiveCfg = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_md|Win32.Build.0 = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_mt|Win32.ActiveCfg = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_mt|Win32.Build.0 = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|Win32.Build.0 = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_md|Win32.ActiveCfg = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_md|Win32.Build.0 = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_mt|Win32.ActiveCfg = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_mt|Win32.Build.0 = release_shared|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Foundation/Foundation_x64_vs140.sln b/Foundation/Foundation_x64_vs140.sln index 9f5ac1d76..b5e15a71b 100644 --- a/Foundation/Foundation_x64_vs140.sln +++ b/Foundation/Foundation_x64_vs140.sln @@ -1,5 +1,7 @@ -Microsoft Visual Studio Solution File, Format Version 14.00 -# Visual Studio 2015 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Foundation", "Foundation_x64_vs140.vcxproj", "{B01196CC-B693-4548-8464-2FF60499E73F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_x64_vs140.vcxproj", "{C812E0B9-69A9-4FA1-A1D4-161CF677BD10}" @@ -7,52 +9,86 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\Test {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApp", "testsuite\TestApp_x64_vs140.vcxproj", "{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}" + ProjectSection(ProjectDependencies) = postProject + {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLibrary", "testsuite\TestLibrary_x64_vs140.vcxproj", "{0955EB03-544B-4BD4-9C10-89CF38078F5F}" + ProjectSection(ProjectDependencies) = postProject + {B01196CC-B693-4548-8464-2FF60499E73F} = {B01196CC-B693-4548-8464-2FF60499E73F} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution debug_shared|x64 = debug_shared|x64 - release_shared|x64 = release_shared|x64 - debug_static_mt|x64 = debug_static_mt|x64 - release_static_mt|x64 = release_static_mt|x64 debug_static_md|x64 = debug_static_md|x64 + debug_static_mt|x64 = debug_static_mt|x64 + release_shared|x64 = release_shared|x64 release_static_md|x64 = release_static_md|x64 + release_static_mt|x64 = release_static_mt|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|x64.ActiveCfg = debug_shared|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|x64.Build.0 = debug_shared|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_shared|x64.Deploy.0 = debug_shared|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.ActiveCfg = release_shared|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.Build.0 = release_shared|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.Deploy.0 = release_shared|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.ActiveCfg = debug_static_mt|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.Build.0 = debug_static_mt|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.Deploy.0 = debug_static_mt|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.ActiveCfg = release_static_mt|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.Build.0 = release_static_mt|x64 - {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.Deploy.0 = release_static_mt|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|x64.ActiveCfg = debug_static_md|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|x64.Build.0 = debug_static_md|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_md|x64.Deploy.0 = debug_static_md|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.ActiveCfg = debug_static_mt|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.Build.0 = debug_static_mt|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.debug_static_mt|x64.Deploy.0 = debug_static_mt|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.ActiveCfg = release_shared|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.Build.0 = release_shared|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_shared|x64.Deploy.0 = release_shared|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|x64.ActiveCfg = release_static_md|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|x64.Build.0 = release_static_md|x64 {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_md|x64.Deploy.0 = release_static_md|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.ActiveCfg = release_static_mt|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.Build.0 = release_static_mt|x64 + {B01196CC-B693-4548-8464-2FF60499E73F}.release_static_mt|x64.Deploy.0 = release_static_mt|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|x64.ActiveCfg = debug_shared|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|x64.Build.0 = debug_shared|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_shared|x64.Deploy.0 = debug_shared|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.ActiveCfg = release_shared|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.Build.0 = release_shared|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.Deploy.0 = release_shared|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.ActiveCfg = debug_static_mt|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.Build.0 = debug_static_mt|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.Deploy.0 = debug_static_mt|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.ActiveCfg = release_static_mt|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.Build.0 = release_static_mt|x64 - {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.Deploy.0 = release_static_mt|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|x64.ActiveCfg = debug_static_md|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|x64.Build.0 = debug_static_md|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_md|x64.Deploy.0 = debug_static_md|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.ActiveCfg = debug_static_mt|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.Build.0 = debug_static_mt|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.debug_static_mt|x64.Deploy.0 = debug_static_mt|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.ActiveCfg = release_shared|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.Build.0 = release_shared|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_shared|x64.Deploy.0 = release_shared|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|x64.ActiveCfg = release_static_md|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|x64.Build.0 = release_static_md|x64 {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_md|x64.Deploy.0 = release_static_md|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.ActiveCfg = release_static_mt|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.Build.0 = release_static_mt|x64 + {C812E0B9-69A9-4FA1-A1D4-161CF677BD10}.release_static_mt|x64.Deploy.0 = release_static_mt|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|x64.ActiveCfg = debug_shared|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|x64.Build.0 = debug_shared|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_md|x64.ActiveCfg = debug_static_md|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_md|x64.Build.0 = debug_static_md|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_mt|x64.ActiveCfg = debug_static_mt|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_static_mt|x64.Build.0 = debug_static_mt|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|x64.ActiveCfg = release_shared|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|x64.Build.0 = release_shared|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_md|x64.ActiveCfg = release_static_md|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_md|x64.Build.0 = release_static_md|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_mt|x64.ActiveCfg = release_static_mt|x64 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_static_mt|x64.Build.0 = release_static_mt|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|x64.ActiveCfg = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|x64.Build.0 = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_md|x64.ActiveCfg = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_md|x64.Build.0 = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_mt|x64.ActiveCfg = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_static_mt|x64.Build.0 = debug_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|x64.ActiveCfg = release_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|x64.Build.0 = release_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_md|x64.ActiveCfg = release_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_md|x64.Build.0 = release_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_mt|x64.ActiveCfg = release_shared|x64 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_static_mt|x64.Build.0 = release_shared|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 0fefd7d03a062ba053144ee069e5bfd855593067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Thu, 2 Feb 2017 20:54:59 +0100 Subject: [PATCH 124/305] fixed GH #1523: Long path names under Windows --- Foundation/include/Poco/File.h | 13 +++++++++++ Foundation/include/Poco/File_WIN32U.h | 3 +++ Foundation/include/Poco/File_WINCE.h | 3 +++ Foundation/src/DirectoryIterator_WIN32U.cpp | 2 +- Foundation/src/DirectoryWatcher.cpp | 5 +--- Foundation/src/FileStream_WIN32.cpp | 2 +- Foundation/src/File_WIN32U.cpp | 26 +++++++++++++++++---- Foundation/src/File_WINCE.cpp | 13 +++++++---- Foundation/src/LogFile_WIN32U.cpp | 2 +- Foundation/src/Process_WIN32U.cpp | 20 ++++++++++++++-- Foundation/testsuite/src/FileTest.cpp | 25 ++++++++++++++++++++ Foundation/testsuite/src/FileTest.h | 1 + 12 files changed, 98 insertions(+), 17 deletions(-) diff --git a/Foundation/include/Poco/File.h b/Foundation/include/Poco/File.h index 00ba0a32d..1dbfe6ceb 100644 --- a/Foundation/include/Poco/File.h +++ b/Foundation/include/Poco/File.h @@ -50,6 +50,19 @@ class Path; class Foundation_API File: private FileImpl /// The File class provides methods for working with a file. + /// + /// Regarding paths passed to the various methods, note that + /// platform-specific limitations regarding maximum length + /// of the entire path and its components apply. + /// + /// On Windows, if compiled with UTF-8 support (POCO_WIN32_UTF8) + /// the implementation tries to work around the rather low + /// 260 characters MAX_PATH limit by adding the "\\?\" prefix if + /// a path is absolute and exceeds MAX_PATH characters in length. + /// Note that various limitations regarding usage of the "\\?\" + /// prefix apply in that case, e.g. the path must + /// not contain relative components ("." and "..") and must not + /// use the forward slash ("/") as directory separator. { public: typedef FileSizeImpl FileSize; diff --git a/Foundation/include/Poco/File_WIN32U.h b/Foundation/include/Poco/File_WIN32U.h index fe0c7499f..6159ac278 100644 --- a/Foundation/include/Poco/File_WIN32U.h +++ b/Foundation/include/Poco/File_WIN32U.h @@ -63,6 +63,7 @@ protected: FileSizeImpl usableSpaceImpl() const; FileSizeImpl freeSpaceImpl() const; static void handleLastErrorImpl(const std::string& path); + static void convertPath(const std::string& utf8Path, std::wstring& utf16Path); private: std::string _path; @@ -71,6 +72,8 @@ private: friend class FileHandle; friend class DirectoryIteratorImpl; friend class WindowsDirectoryWatcherStrategy; + friend class FileStreamBuf; + friend class LogFileImpl; }; diff --git a/Foundation/include/Poco/File_WINCE.h b/Foundation/include/Poco/File_WINCE.h index 9a8dd5dd1..0dfa6244b 100644 --- a/Foundation/include/Poco/File_WINCE.h +++ b/Foundation/include/Poco/File_WINCE.h @@ -63,6 +63,7 @@ protected: FileSizeImpl usableSpaceImpl() const; FileSizeImpl freeSpaceImpl() const; static void handleLastErrorImpl(const std::string& path); + static void convertPath(const std::string& utf8Path, std::wstring& utf16Path); private: std::string _path; @@ -70,6 +71,8 @@ private: friend class FileHandle; friend class DirectoryIteratorImpl; + friend class FileStreamBuf; + friend class LogFileImpl; }; diff --git a/Foundation/src/DirectoryIterator_WIN32U.cpp b/Foundation/src/DirectoryIterator_WIN32U.cpp index acd1dc2a6..be3d35a43 100644 --- a/Foundation/src/DirectoryIterator_WIN32U.cpp +++ b/Foundation/src/DirectoryIterator_WIN32U.cpp @@ -35,7 +35,7 @@ DirectoryIteratorImpl::DirectoryIteratorImpl(const std::string& path): _fh(INVAL std::string findPath = p.toString(); findPath.append("*"); std::wstring uFindPath; - UnicodeConverter::toUTF16(findPath, uFindPath); + FileImpl::convertPath(findPath, uFindPath); _fh = FindFirstFileW(uFindPath.c_str(), &_fd); if (_fh == INVALID_HANDLE_VALUE) diff --git a/Foundation/src/DirectoryWatcher.cpp b/Foundation/src/DirectoryWatcher.cpp index aaf4bccb2..590bc161a 100644 --- a/Foundation/src/DirectoryWatcher.cpp +++ b/Foundation/src/DirectoryWatcher.cpp @@ -29,9 +29,6 @@ #include "Poco/Event.h" #include "Poco/Exception.h" #include "Poco/Buffer.h" -#if defined(POCO_WIN32_UTF8) - #include "Poco/UnicodeConverter.h" -#endif #if POCO_OS == POCO_OS_LINUX #include #include @@ -200,7 +197,7 @@ public: std::string path(owner().directory().path()); #if defined(POCO_WIN32_UTF8) std::wstring upath; - Poco::UnicodeConverter::toUTF16(path.c_str(), upath); + FileImpl::convertPath(path.c_str(), upath); HANDLE hChange = FindFirstChangeNotificationW(upath.c_str(), FALSE, filter); #else HANDLE hChange = FindFirstChangeNotificationA(path.c_str(), FALSE, filter); diff --git a/Foundation/src/FileStream_WIN32.cpp b/Foundation/src/FileStream_WIN32.cpp index e75f1ee4a..55d4b97e3 100644 --- a/Foundation/src/FileStream_WIN32.cpp +++ b/Foundation/src/FileStream_WIN32.cpp @@ -68,7 +68,7 @@ void FileStreamBuf::open(const std::string& path, std::ios::openmode mode) #if defined (POCO_WIN32_UTF8) std::wstring utf16Path; - UnicodeConverter::toUTF16(path, utf16Path); + FileImpl::convertPath(path, utf16Path); _handle = CreateFileW(utf16Path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL); #else _handle = CreateFileA(path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL); diff --git a/Foundation/src/File_WIN32U.cpp b/Foundation/src/File_WIN32U.cpp index 370350fda..57dd82ee5 100644 --- a/Foundation/src/File_WIN32U.cpp +++ b/Foundation/src/File_WIN32U.cpp @@ -63,7 +63,7 @@ FileImpl::FileImpl(const std::string& path): _path(path) { _path.resize(n - 1); } - UnicodeConverter::toUTF16(_path, _upath); + convertPath(_path, _upath); } @@ -87,7 +87,7 @@ void FileImpl::setPathImpl(const std::string& path) { _path.resize(n - 1); } - UnicodeConverter::toUTF16(_path, _upath); + convertPath(_path, _upath); } @@ -293,7 +293,7 @@ void FileImpl::copyToImpl(const std::string& path) const poco_assert (!_path.empty()); std::wstring upath; - UnicodeConverter::toUTF16(path, upath); + convertPath(path, upath); if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) == 0) handleLastErrorImpl(_path); } @@ -304,7 +304,7 @@ void FileImpl::renameToImpl(const std::string& path) poco_assert (!_path.empty()); std::wstring upath; - UnicodeConverter::toUTF16(path, upath); + convertPath(path, upath); if (MoveFileExW(_upath.c_str(), upath.c_str(), MOVEFILE_REPLACE_EXISTING) == 0) handleLastErrorImpl(_path); } @@ -439,4 +439,22 @@ void FileImpl::handleLastErrorImpl(const std::string& path) } +void FileImpl::convertPath(const std::string& utf8Path, std::wstring& utf16Path) +{ + UnicodeConverter::toUTF16(utf8Path, utf16Path); + if (utf16Path.size() > MAX_PATH - 12) // Note: CreateDirectory has a limit of MAX_PATH - 12 (room for 8.3 file name) + { + if (utf16Path[0] == '\\' || utf16Path[1] == ':') + { + if (utf16Path.compare(0, 4, L"\\\\?\\", 4) != 0) + { + if (utf16Path[1] == '\\') + utf16Path.insert(0, L"\\\\?\\UNC\\", 8); + else + utf16Path.insert(0, L"\\\\?\\", 4); + } + } + } +} + } // namespace Poco diff --git a/Foundation/src/File_WINCE.cpp b/Foundation/src/File_WINCE.cpp index 5f5ddc0b6..3dbc72992 100644 --- a/Foundation/src/File_WINCE.cpp +++ b/Foundation/src/File_WINCE.cpp @@ -64,7 +64,7 @@ FileImpl::FileImpl(const std::string& path): _path(path) { _path.resize(n - 1); } - UnicodeConverter::toUTF16(_path, _upath); + convertPath(_path, _upath); } @@ -88,7 +88,7 @@ void FileImpl::setPathImpl(const std::string& path) { _path.resize(n - 1); } - UnicodeConverter::toUTF16(_path, _upath); + convertPath(_path, _upath); } @@ -284,7 +284,7 @@ void FileImpl::copyToImpl(const std::string& path) const poco_assert (!_path.empty()); std::wstring upath; - UnicodeConverter::toUTF16(path, upath); + convertPath(path, upath); if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) == 0) handleLastErrorImpl(_path); } @@ -295,7 +295,7 @@ void FileImpl::renameToImpl(const std::string& path) poco_assert (!_path.empty()); std::wstring upath; - UnicodeConverter::toUTF16(path, upath); + convertPath(path, upath); if (MoveFileW(_upath.c_str(), upath.c_str()) == 0) handleLastErrorImpl(_path); } @@ -429,4 +429,9 @@ void FileImpl::handleLastErrorImpl(const std::string& path) } +void FileImpl::convertPath(const std::string& utf8Path, std::wstring& utf16Path) +{ + UnicodeConverter::toUTF16(utf8Path, utf16Path); +} + } // namespace Poco diff --git a/Foundation/src/LogFile_WIN32U.cpp b/Foundation/src/LogFile_WIN32U.cpp index 454dedc0e..972b7f240 100644 --- a/Foundation/src/LogFile_WIN32U.cpp +++ b/Foundation/src/LogFile_WIN32U.cpp @@ -90,7 +90,7 @@ const std::string& LogFileImpl::pathImpl() const void LogFileImpl::createFile() { std::wstring upath; - UnicodeConverter::toUTF16(_path, upath); + FileImpl::convertPath(_path, upath); _hFile = CreateFileW(upath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (_hFile == INVALID_HANDLE_VALUE) throw OpenFileException(_path); diff --git a/Foundation/src/Process_WIN32U.cpp b/Foundation/src/Process_WIN32U.cpp index b8e7f1c0b..8176bac2f 100644 --- a/Foundation/src/Process_WIN32U.cpp +++ b/Foundation/src/Process_WIN32U.cpp @@ -20,6 +20,9 @@ #include "Poco/NamedEvent.h" #include "Poco/UnicodeConverter.h" #include "Poco/Pipe.h" +#include "Poco/File.h" +#include "Poco/Path.h" +#include "Poco/String.h" namespace Poco { @@ -164,7 +167,7 @@ static std::string escapeArg(const std::string& arg) ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env) { - std::string commandLine = command; + std::string commandLine = escapeArg(command); for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) { commandLine.append(" "); @@ -174,6 +177,19 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg std::wstring ucommandLine; UnicodeConverter::toUTF16(commandLine, ucommandLine); + const wchar_t* applicationName = 0; + std::wstring uapplicationName; + if (command.size() > MAX_PATH) + { + Poco::Path p(command); + if (p.isAbsolute()) + { + UnicodeConverter::toUTF16(command, uapplicationName); + if (p.getExtension().empty()) uapplicationName += L".EXE"; + applicationName = uapplicationName.c_str(); + } + } + STARTUPINFOW startupInfo; GetStartupInfoW(&startupInfo); // take defaults from current process startupInfo.cb = sizeof(STARTUPINFOW); @@ -253,7 +269,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg PROCESS_INFORMATION processInfo; DWORD creationFlags = GetConsoleWindow() ? 0 : CREATE_NO_WINDOW; BOOL rc = CreateProcessW( - NULL, // applicationName + applicationName, const_cast(ucommandLine.c_str()), NULL, // processAttributes NULL, // threadAttributes diff --git a/Foundation/testsuite/src/FileTest.cpp b/Foundation/testsuite/src/FileTest.cpp index 9afa18344..db81db85a 100644 --- a/Foundation/testsuite/src/FileTest.cpp +++ b/Foundation/testsuite/src/FileTest.cpp @@ -524,6 +524,30 @@ void FileTest::testRename() } +void FileTest::testLongPath() +{ +#if defined(_WIN32) && defined(POCO_WIN32_UTF8) && !defined(_WIN32_WCE) + Poco::Path p("longpathtest"); + p.makeAbsolute(); + std::string longpath(p.toString()); + while (longpath.size() < MAX_PATH*4) + { + longpath.append("\\"); + longpath.append(64, 'x'); + } + + Poco::File d(longpath); + d.createDirectories(); + + assert (d.exists()); + assert (d.isDirectory()); + + Poco::File f(p.toString()); + f.remove(true); +#endif +} + + void FileTest::setUp() { File f("testfile.dat"); @@ -568,6 +592,7 @@ CppUnit::Test* FileTest::suite() CppUnit_addTest(pSuite, FileTest, testCopyDirectory); CppUnit_addTest(pSuite, FileTest, testRename); CppUnit_addTest(pSuite, FileTest, testRootDir); + CppUnit_addTest(pSuite, FileTest, testLongPath); return pSuite; } diff --git a/Foundation/testsuite/src/FileTest.h b/Foundation/testsuite/src/FileTest.h index 859bc137f..b475de439 100644 --- a/Foundation/testsuite/src/FileTest.h +++ b/Foundation/testsuite/src/FileTest.h @@ -40,6 +40,7 @@ public: void testCopyDirectory(); void testRename(); void testRootDir(); + void testLongPath(); void setUp(); void tearDown(); From 8557dc44698264fcbe72e084637a4119e549da90 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 12:03:37 +0100 Subject: [PATCH 125/305] fixed GH #1581: Cannot find 'pcre.h' when using POCO_UNBUNDLED, a non-system PCRE, and CMake Conflicts: Foundation/include/Poco/RegularExpression.h Foundation/src/RegularExpression.cpp --- Foundation/include/Poco/RegularExpression.h | 20 ++++---------------- Foundation/src/RegularExpression.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/Foundation/include/Poco/RegularExpression.h b/Foundation/include/Poco/RegularExpression.h index e2b3446ce..88225d649 100644 --- a/Foundation/include/Poco/RegularExpression.h +++ b/Foundation/include/Poco/RegularExpression.h @@ -28,20 +28,6 @@ #include -#ifdef POCO_UNBUNDLED -#include -#else -// -// Copy these definitions from pcre.h -// to avoid pulling in the entire header file -// -extern "C" -{ - typedef struct real_pcre8_or_16 pcre; - struct pcre_extra; -} -#endif - namespace Poco { @@ -214,8 +200,10 @@ protected: std::string::size_type substOne(std::string& subject, std::string::size_type offset, const std::string& replacement, int options) const; private: - pcre* _pcre; - pcre_extra* _extra; + // Note: to avoid a dependency on the pcre.h header the following are + // declared as void* and casted to the correct type in the implementation file. + void* _pcre; // Actual type is pcre* + void* _extra; // Actual type is struct pcre_extra* GroupMap _groups; diff --git a/Foundation/src/RegularExpression.cpp b/Foundation/src/RegularExpression.cpp index 9b789cf25..c4be5e621 100644 --- a/Foundation/src/RegularExpression.cpp +++ b/Foundation/src/RegularExpression.cpp @@ -24,6 +24,7 @@ #include "pcre.h" #endif + namespace Poco { @@ -46,7 +47,7 @@ RegularExpression::RegularExpression(const std::string& pattern, int options, bo throw RegularExpressionException(msg.str()); } if (study) - _extra = pcre_study(_pcre, 0, &error); + _extra = pcre_study(reinterpret_cast(_pcre), 0, &error); pcre_fullinfo(_pcre, _extra, PCRE_INFO_NAMECOUNT, &nmcount); pcre_fullinfo(_pcre, _extra, PCRE_INFO_NAMEENTRYSIZE, &nmentrysz); @@ -58,14 +59,13 @@ RegularExpression::RegularExpression(const std::string& pattern, int options, bo int n = pcre_get_stringnumber(_pcre, (char*) group); _groups[n] = std::string((char*) group); } - } RegularExpression::~RegularExpression() { - if (_pcre) pcre_free(_pcre); - if (_extra) pcre_free(_extra); + if (_pcre) pcre_free(reinterpret_cast(_pcre)); + if (_extra) pcre_free(reinterpret_cast(_extra)); } @@ -74,7 +74,7 @@ int RegularExpression::match(const std::string& subject, std::string::size_type poco_assert (offset <= subject.length()); int ovec[OVEC_SIZE]; - int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + int rc = pcre_exec(reinterpret_cast(_pcre), reinterpret_cast(_extra), subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { mtch.offset = std::string::npos; @@ -108,7 +108,7 @@ int RegularExpression::match(const std::string& subject, std::string::size_type matches.clear(); int ovec[OVEC_SIZE]; - int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + int rc = pcre_exec(reinterpret_cast(_pcre), reinterpret_cast(_extra), subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { return 0; @@ -230,7 +230,7 @@ std::string::size_type RegularExpression::substOne(std::string& subject, std::st if (offset >= subject.length()) return std::string::npos; int ovec[OVEC_SIZE]; - int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + int rc = pcre_exec(reinterpret_cast(_pcre), reinterpret_cast(_extra), subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { return std::string::npos; From 76ab7c65a6dc13c2e83749ecd801c4c03c763516 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 12:04:36 +0100 Subject: [PATCH 126/305] GH #1586: Upgrade bundled PCRE to 8.40 --- Foundation/include/Poco/Unicode.h | 62 +- Foundation/src/pcre.h | 4 +- Foundation/src/pcre_compile.c | 866 +++-- Foundation/src/pcre_config.h | 6 +- Foundation/src/pcre_dfa_exec.c | 7 +- Foundation/src/pcre_exec.c | 267 +- Foundation/src/pcre_get.c | 23 +- Foundation/src/pcre_internal.h | 37 +- Foundation/src/pcre_jit_compile.c | 4435 +++++++++++++++---------- Foundation/src/pcre_study.c | 108 +- Foundation/src/pcre_tables.c | 349 +- Foundation/src/pcre_ucd.c | 5117 +++++++++++++++-------------- Foundation/src/pcre_xclass.c | 2 +- Foundation/src/ucp.h | 26 +- 14 files changed, 6596 insertions(+), 4713 deletions(-) diff --git a/Foundation/include/Poco/Unicode.h b/Foundation/include/Poco/Unicode.h index be5e4d9d9..ea7aa1aa8 100644 --- a/Foundation/include/Poco/Unicode.h +++ b/Foundation/include/Poco/Unicode.h @@ -40,7 +40,7 @@ public: // Implementation note: the following definitions must be kept // in sync with those from ucp.h (PCRE). enum CharacterCategory - /// Unicode 5.0 character categories. + /// Unicode character categories. { UCP_OTHER, UCP_LETTER, @@ -52,7 +52,7 @@ public: }; enum CharacterType - /// Unicode 5.0 character types. + /// Unicode character types. { UCP_CONTROL, UCP_FORMAT, @@ -87,7 +87,7 @@ public: }; enum Script - /// Unicode 5.0 scripts. + /// Unicode 7.0 script identifiers. { UCP_ARABIC, UCP_ARMENIAN, @@ -150,11 +150,13 @@ public: UCP_TIFINAGH, UCP_UGARITIC, UCP_YI, + // Unicode 5.0 UCP_BALINESE, UCP_CUNEIFORM, UCP_NKO, UCP_PHAGS_PA, UCP_PHOENICIAN, + // Unicode 5.1 UCP_CARIAN, UCP_CHAM, UCP_KAYAH_LI, @@ -165,7 +167,59 @@ public: UCP_REJANG, UCP_SAURASHTRA, UCP_SUNDANESE, - UCP_VAI + UCP_VAI, + // Unicode 5.2 + UCP_AVESTAN, + UCP_BAMUM, + UCP_EGYPTIAN_HIEROGLYPHS, + UCP_IMPERIAL_ARAMAIC, + UCP_INSCRIPTIONAL_PAHLAVI, + UCP_INSCRIPTIONAL_PARTHIAN, + UCP_JAVANESE, + UCP_KAITHI, + UCP_LISU, + UCP_MEETEI_MAYEK, + UCP_OLD_SOUTH_ARABIAN, + UCP_OLD_TURKIC, + UCP_SAMARITAN, + UCP_TAI_THAM, + UCP_TAI_VIET, + // Unicode 6.0 + UCP_BATAK, + UCP_BRAHMI, + UCP_MANDAIC, + // Unicode 6.1 + UCP_CHAKMA, + UCP_MEROITIC_CURSIVE, + UCP_MEROITIC_HIEROGLYPHS, + UCP_MIAO, + UCP_SHARADA, + UCP_SORA_SOMPENG, + UCP_TAKRI, + // Unicode 7.0 + UCP_BASSA_VAH, + UCP_CAUCASIAN_ALBANIAN, + UCP_DUPLOYAN, + UCP_ELBASAN, + UCP_GRANTHA, + UCP_KHOJKI, + UCP_KHUDAWADI, + UCP_LINEAR_A, + UCP_MAHAJANI, + UCP_MANICHAEAN, + UCP_MENDE_KIKAKUI, + UCP_MODI, + UCP_MRO, + UCP_NABATAEAN, + UCP_OLD_NORTH_ARABIAN, + UCP_OLD_PERMIC, + UCP_PAHAWH_HMONG, + UCP_PALMYRENE, + UCP_PSALTER_PAHLAVI, + UCP_PAU_CIN_HAU, + UCP_SIDDHAM, + UCP_TIRHUTA, + UCP_WARANG_CITI }; enum diff --git a/Foundation/src/pcre.h b/Foundation/src/pcre.h index c9f7dd98a..4b017e981 100644 --- a/Foundation/src/pcre.h +++ b/Foundation/src/pcre.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE_MAJOR 8 -#define PCRE_MINOR 35 +#define PCRE_MINOR 40 #define PCRE_PRERELEASE -#define PCRE_DATE 2014-04-04 +#define PCRE_DATE 2017-01-11 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate diff --git a/Foundation/src/pcre_compile.c b/Foundation/src/pcre_compile.c index 35ea7252a..884fb4dd1 100644 --- a/Foundation/src/pcre_compile.c +++ b/Foundation/src/pcre_compile.c @@ -6,7 +6,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2014 University of Cambridge + Copyright (c) 1997-2016 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -49,8 +49,8 @@ supporting internal functions that are not used by other modules. */ #include "pcre_config.h" #define NLBLOCK cd /* Block containing newline information */ -#define PSSTART start_pattern /* Field containing processed string start */ -#define PSEND end_pattern /* Field containing processed string end */ +#define PSSTART start_pattern /* Field containing pattern start */ +#define PSEND end_pattern /* Field containing pattern end */ #include "pcre_internal.h" @@ -176,7 +176,7 @@ static const short int escapes[] = { -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, - CHAR_GRAVE_ACCENT, 7, + CHAR_GRAVE_ACCENT, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, @@ -204,9 +204,9 @@ static const short int escapes[] = { /* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, +/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, /* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, /* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, @@ -221,6 +221,12 @@ static const short int escapes[] = { /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* We also need a table of characters that may follow \c in an EBCDIC +environment for characters 0-31. */ + +static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; + #endif @@ -460,7 +466,7 @@ static const char error_texts[] = "range out of order in character class\0" "nothing to repeat\0" /* 10 */ - "operand of unlimited repeat could match the empty string\0" /** DEAD **/ + "internal error: invalid forward reference offset\0" "internal error: unexpected repeat\0" "unrecognized character after (? or (?-\0" "POSIX named classes are supported only within a class\0" @@ -481,7 +487,7 @@ static const char error_texts[] = "lookbehind assertion is not fixed length\0" "malformed number or name after (?(\0" "conditional group contains more than two branches\0" - "assertion expected after (?(\0" + "assertion expected after (?( or (?(?C)\0" "(?R or (?[+-]digits must be followed by )\0" /* 30 */ "unknown POSIX class name\0" @@ -529,7 +535,11 @@ static const char error_texts[] = "different names for subpatterns of the same number are not allowed\0" "(*MARK) must have an argument\0" "this version of PCRE is not compiled with Unicode property support\0" +#ifndef EBCDIC "\\c must be followed by an ASCII character\0" +#else + "\\c must be followed by a letter or one of [\\]^_?\0" +#endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */ "internal error: unknown opcode in find_fixedlength()\0" @@ -551,6 +561,8 @@ static const char error_texts[] = "group name must start with a non-digit\0" /* 85 */ "parentheses are too deeply nested (stack check)\0" + "digits missing in \\x{} or \\o{}\0" + "regular expression is too complicated\0" ; /* Table to identify digits and hex digits. This is used when compiling @@ -1261,6 +1273,7 @@ else case CHAR_o: if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR81; else + if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR86; else { ptr += 2; c = 0; @@ -1330,6 +1343,11 @@ else if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) { ptr += 2; + if (*ptr == CHAR_RIGHT_CURLY_BRACKET) + { + *errorcodeptr = ERR86; + break; + } c = 0; overflow = FALSE; while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0) @@ -1420,7 +1438,16 @@ else c ^= 0x40; #else /* EBCDIC coding */ if (c >= CHAR_a && c <= CHAR_z) c += 64; - c ^= 0xC0; + if (c == CHAR_QUESTION_MARK) + c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff; + else + { + for (i = 0; i < 32; i++) + { + if (c == ebcdic_escape_c[i]) break; + } + if (i < 32) c = i; else *errorcodeptr = ERR68; + } #endif break; @@ -1585,29 +1612,29 @@ read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr) int min = 0; int max = -1; -/* Read the minimum value and do a paranoid check: a negative value indicates -an integer overflow. */ - -while (IS_DIGIT(*p)) min = min * 10 + (int)(*p++ - CHAR_0); -if (min < 0 || min > 65535) +while (IS_DIGIT(*p)) { - *errorcodeptr = ERR5; - return p; + min = min * 10 + (int)(*p++ - CHAR_0); + if (min > 65535) + { + *errorcodeptr = ERR5; + return p; + } } -/* Read the maximum value if there is one, and again do a paranoid on its size. -Also, max must not be less than min. */ - if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else { if (*(++p) != CHAR_RIGHT_CURLY_BRACKET) { max = 0; - while(IS_DIGIT(*p)) max = max * 10 + (int)(*p++ - CHAR_0); - if (max < 0 || max > 65535) + while(IS_DIGIT(*p)) { - *errorcodeptr = ERR5; - return p; + max = max * 10 + (int)(*p++ - CHAR_0); + if (max > 65535) + { + *errorcodeptr = ERR5; + return p; + } } if (max < min) { @@ -1617,9 +1644,6 @@ if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else } } -/* Fill in the required variables, and pass back the pointer to the terminating -'}'. */ - *minp = min; *maxp = max; return p; @@ -1702,6 +1726,7 @@ Arguments: utf TRUE in UTF-8 / UTF-16 / UTF-32 mode atend TRUE if called when the pattern is complete cd the "compile data" structure + recurses chain of recurse_check to catch mutual recursion Returns: the fixed length, or -1 if there is no fixed length, @@ -1711,10 +1736,11 @@ Returns: the fixed length, */ static int -find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd) +find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd, + recurse_check *recurses) { int length = -1; - +recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = code + 1 + LINK_SIZE; @@ -1739,7 +1765,8 @@ for (;;) case OP_ONCE: case OP_ONCE_NC: case OP_COND: - d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd); + d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd, + recurses); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -1773,7 +1800,15 @@ for (;;) cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */ do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */ if (cc > cs && cc < ce) return -1; /* Recursion */ - d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd); + else /* Check for mutual recursion */ + { + recurse_check *r = recurses; + for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; + if (r != NULL) return -1; /* Mutual recursion */ + } + this_recurse.prev = recurses; + this_recurse.group = cs; + d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse); if (d < 0) return d; branchlength += d; cc += 1 + LINK_SIZE; @@ -1786,7 +1821,7 @@ for (;;) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + LINK_SIZE; break; /* Skip over things that don't match chars */ @@ -2127,32 +2162,60 @@ for (;;) { case OP_CHAR: case OP_CHARI: + case OP_NOT: + case OP_NOTI: case OP_EXACT: case OP_EXACTI: + case OP_NOTEXACT: + case OP_NOTEXACTI: case OP_UPTO: case OP_UPTOI: + case OP_NOTUPTO: + case OP_NOTUPTOI: case OP_MINUPTO: case OP_MINUPTOI: + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: case OP_POSUPTO: case OP_POSUPTOI: + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: case OP_STAR: case OP_STARI: + case OP_NOTSTAR: + case OP_NOTSTARI: case OP_MINSTAR: case OP_MINSTARI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: case OP_POSSTAR: case OP_POSSTARI: + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: case OP_PLUS: case OP_PLUSI: + case OP_NOTPLUS: + case OP_NOTPLUSI: case OP_MINPLUS: case OP_MINPLUSI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: case OP_POSPLUS: case OP_POSPLUSI: + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: case OP_QUERY: case OP_QUERYI: + case OP_NOTQUERY: + case OP_NOTQUERYI: case OP_MINQUERY: case OP_MINQUERYI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: case OP_POSQUERY: case OP_POSQUERYI: + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); break; } @@ -2332,11 +2395,6 @@ Arguments: Returns: TRUE if what is matched could be empty */ -typedef struct recurse_check { - struct recurse_check *prev; - const pcre_uchar *group; -} recurse_check; - static BOOL could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode, BOOL utf, compile_data *cd, recurse_check *recurses) @@ -2372,6 +2430,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_RECURSE) { const pcre_uchar *scode = cd->start_code + GET(code, 1); + const pcre_uchar *endgroup = scode; BOOL empty_branch; /* Test for forward reference or uncompleted reference. This is disabled @@ -2386,20 +2445,16 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ } - /* If we are scanning a completed pattern, there are no forward references - and all groups are complete. We need to detect whether this is a recursive - call, as otherwise there will be an infinite loop. If it is a recursion, - just skip over it. Simple recursions are easily detected. For mutual - recursions we keep a chain on the stack. */ + /* If the reference is to a completed group, we need to detect whether this + is a recursive call, as otherwise there will be an infinite loop. If it is + a recursion, just skip over it. Simple recursions are easily detected. For + mutual recursions we keep a chain on the stack. */ + do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT); + if (code >= scode && code <= endgroup) continue; /* Simple recursion */ else { recurse_check *r = recurses; - const pcre_uchar *endgroup = scode; - - do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT); - if (code >= scode && code <= endgroup) continue; /* Simple recursion */ - for (r = recurses; r != NULL; r = r->prev) if (r->group == scode) break; if (r != NULL) continue; /* Mutual recursion */ @@ -2454,7 +2509,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_BRA || c == OP_BRAPOS || c == OP_CBRA || c == OP_CBRAPOS || c == OP_ONCE || c == OP_ONCE_NC || - c == OP_COND) + c == OP_COND || c == OP_SCOND) { BOOL empty_branch; if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ @@ -2470,8 +2525,8 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); empty_branch = FALSE; do { - if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, NULL)) - empty_branch = TRUE; + if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, + recurses)) empty_branch = TRUE; code += GET(code, 1); } while (*code == OP_ALT); @@ -3040,7 +3095,7 @@ switch(c) end += 1 + 2 * IMM2_SIZE; break; } - list[2] = end - code; + list[2] = (pcre_uint32)(end - code); return end; } return NULL; /* Opcode not accepted */ @@ -3066,7 +3121,7 @@ Returns: TRUE if the auto-possessification is possible static BOOL compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd, - const pcre_uint32 *base_list, const pcre_uchar *base_end) + const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit) { pcre_uchar c; pcre_uint32 list[8]; @@ -3081,6 +3136,10 @@ const pcre_uint8 *class_bitset; const pcre_uint8 *set1, *set2, *set_end; pcre_uint32 chr; BOOL accepted, invert_bits; +BOOL entered_a_group = FALSE; + +if (*rec_limit == 0) return FALSE; +--(*rec_limit); /* Note: the base_list[1] contains whether the current opcode has greedy (represented by a non-zero value) quantifier. This is a different from @@ -3134,8 +3193,10 @@ for(;;) case OP_ONCE: case OP_ONCE_NC: /* Atomic sub-patterns and assertions can always auto-possessify their - last iterator. */ - return TRUE; + last iterator. However, if the group was entered as a result of checking + a previous iterator, this is not possible. */ + + return !entered_a_group; } code += PRIV(OP_lengths)[c]; @@ -3150,10 +3211,13 @@ for(;;) while (*next_code == OP_ALT) { - if (!compare_opcodes(code, utf, cd, base_list, base_end)) return FALSE; + if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit)) + return FALSE; code = next_code + 1 + LINK_SIZE; next_code += GET(next_code, 1); } + + entered_a_group = TRUE; continue; case OP_BRAZERO: @@ -3168,11 +3232,14 @@ for(;;) /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */ next_code += 1 + LINK_SIZE; - if (!compare_opcodes(next_code, utf, cd, base_list, base_end)) + if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit)) return FALSE; code += PRIV(OP_lengths)[c]; continue; + + default: + break; } /* Check for a supported opcode, and load its properties. */ @@ -3411,8 +3478,7 @@ for(;;) rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP && autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP]; - if (!accepted) - return FALSE; + if (!accepted) return FALSE; if (list[1] == 0) return TRUE; /* Might be an empty repeat. */ @@ -3599,11 +3665,20 @@ register pcre_uchar c; const pcre_uchar *end; pcre_uchar *repeat_opcode; pcre_uint32 list[8]; +int rec_limit; for (;;) { c = *code; + /* When a pattern with bad UTF-8 encoding is compiled with NO_UTF_CHECK, + it may compile without complaining, but may get into a loop here if the code + pointer points to a bad value. This is, of course a documentated possibility, + when NO_UTF_CHECK is set, so it isn't a bug, but we can detect this case and + just give up on this optimization. */ + + if (c >= OP_TABLE_LENGTH) return; + if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) { c -= get_repeat_base(c) - OP_STAR; @@ -3611,7 +3686,8 @@ for (;;) get_chr_property_list(code, utf, cd->fcc, list) : NULL; list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO; - if (end != NULL && compare_opcodes(end, utf, cd, list, end)) + rec_limit = 1000; + if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit)) { switch(c) { @@ -3667,7 +3743,8 @@ for (;;) list[1] = (c & 1) == 0; - if (compare_opcodes(end, utf, cd, list, end)) + rec_limit = 1000; + if (compare_opcodes(end, utf, cd, list, end, &rec_limit)) { switch (c) { @@ -3831,11 +3908,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:]. The problem in trying to be exactly like Perl is in the handling of escapes. We have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code -below handles the special case of \], but does not try to do any other escape -processing. This makes it different from Perl for cases such as [:l\ower:] -where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize -"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does, -I think. +below handles the special cases \\ and \], but does not try to do any other +escape processing. This makes it different from Perl for cases such as +[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does +not recognize "l\ower". This is a lesser evil than not diagnosing bad classes +when Perl does, I think. A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. It seems that the appearance of a nested POSIX class supersedes an apparent @@ -3862,21 +3939,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ for (++ptr; *ptr != CHAR_NULL; ptr++) { - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (*ptr == CHAR_BACKSLASH && + (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || + ptr[1] == CHAR_BACKSLASH)) ptr++; - else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; - else + else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) || + *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; + else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { - if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - *endptr = ptr; - return TRUE; - } - if (*ptr == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, endptr)) - return FALSE; + *endptr = ptr; + return TRUE; } } return FALSE; @@ -3930,48 +4002,42 @@ have their offsets adjusted. That one of the jobs of this function. Before it is called, the partially compiled regex must be temporarily terminated with OP_END. -This function has been extended with the possibility of forward references for -recursions and subroutine calls. It must also check the list of such references -for the group we are dealing with. If it finds that one of the recursions in -the current group is on this list, it adjusts the offset in the list, not the -value in the reference (which is a group number). +This function has been extended to cope with forward references for recursions +and subroutine calls. It must check the list of such references for the +group we are dealing with. If it finds that one of the recursions in the +current group is on this list, it does not adjust the value in the reference +(which is a group number). After the group has been scanned, all the offsets in +the forward reference list for the group are adjusted. Arguments: group points to the start of the group adjust the amount by which the group is to be moved utf TRUE in UTF-8 / UTF-16 / UTF-32 mode cd contains pointers to tables etc. - save_hwm the hwm forward reference pointer at the start of the group + save_hwm_offset the hwm forward reference offset at the start of the group Returns: nothing */ static void adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, - pcre_uchar *save_hwm) + size_t save_hwm_offset) { +int offset; +pcre_uchar *hc; pcre_uchar *ptr = group; while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) { - int offset; - pcre_uchar *hc; - - /* See if this recursion is on the forward reference list. If so, adjust the - reference. */ - - for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE) + for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) { offset = (int)GET(hc, 0); - if (cd->start_code + offset == ptr + 1) - { - PUT(hc, 0, offset + adjust); - break; - } + if (cd->start_code + offset == ptr + 1) break; } - /* Otherwise, adjust the recursion offset if it's after the start of this - group. */ + /* If we have not found this recursion on the forward reference list, adjust + the recursion's offset if it's after the start of this group. */ if (hc >= cd->hwm) { @@ -3981,6 +4047,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) ptr += 1 + LINK_SIZE; } + +/* Now adjust all forward reference offsets for the group. */ + +for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) + { + offset = (int)GET(hc, 0); + PUT(hc, 0, offset + adjust); + } } @@ -4165,7 +4240,11 @@ if ((options & PCRE_CASELESS) != 0) range. Otherwise, use a recursive call to add the additional range. */ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */ - else if (od > end && oc <= end + 1) end = od; /* Extend upwards */ + else if (od > end && oc <= end + 1) + { + end = od; /* Extend upwards */ + if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff); + } else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od); } } @@ -4405,7 +4484,7 @@ const pcre_uchar *tempptr; const pcre_uchar *nestptr = NULL; pcre_uchar *previous = NULL; pcre_uchar *previous_callout = NULL; -pcre_uchar *save_hwm = NULL; +size_t item_hwm_offset = 0; pcre_uint8 classbits[32]; /* We can fish out the UTF-8 setting once and for all into a BOOL, but we @@ -4490,6 +4569,10 @@ for (;; ptr++) pcre_uint32 ec; pcre_uchar mcbuffer[8]; + /* Come here to restart the loop without advancing the pointer. */ + + REDO_LOOP: + /* Get next character in the pattern */ c = *ptr; @@ -4515,7 +4598,8 @@ for (;; ptr++) if (code > cd->start_workspace + cd->workspace_size - WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */ { - *errorcodeptr = ERR52; + *errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)? + ERR52 : ERR87; goto FAILED; } @@ -4563,16 +4647,16 @@ for (;; ptr++) /* In the real compile phase, just check the workspace used by the forward reference list. */ - else if (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN) + else if (cd->hwm > cd->start_workspace + cd->workspace_size) { *errorcodeptr = ERR52; goto FAILED; } - /* If in \Q...\E, check for the end; if not, we have a literal */ + /* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an + isolated \E is ignored. */ - if (inescq && c != CHAR_NULL) + if (c != CHAR_NULL) { if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) { @@ -4580,7 +4664,7 @@ for (;; ptr++) ptr++; continue; } - else + else if (inescq) { if (previous_callout != NULL) { @@ -4595,18 +4679,27 @@ for (;; ptr++) } goto NORMAL_CHAR; } - /* Control does not reach here. */ + + /* Check for the start of a \Q...\E sequence. We must do this here rather + than later in case it is immediately followed by \E, which turns it into a + "do nothing" sequence. */ + + if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q) + { + inescq = TRUE; + ptr++; + continue; + } } - /* In extended mode, skip white space and comments. We need a loop in order - to check for more white space and more comments after a comment. */ + /* In extended mode, skip white space and comments. */ if ((options & PCRE_EXTENDED) != 0) { - for (;;) + const pcre_uchar *wscptr = ptr; + while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr); + if (c == CHAR_NUMBER_SIGN) { - while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr); - if (c != CHAR_NUMBER_SIGN) break; ptr++; while (*ptr != CHAR_NULL) { @@ -4620,8 +4713,29 @@ for (;; ptr++) if (utf) FORWARDCHAR(ptr); #endif } - c = *ptr; /* Either NULL or the char after a newline */ } + + /* If we skipped any characters, restart the loop. Otherwise, we didn't see + a comment. */ + + if (ptr > wscptr) goto REDO_LOOP; + } + + /* Skip over (?# comments. We need to do this here because we want to know if + the next thing is a quantifier, and these comments may come between an item + and its quantifier. */ + + if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK && + ptr[2] == CHAR_NUMBER_SIGN) + { + ptr += 3; + while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; + if (*ptr == CHAR_NULL) + { + *errorcodeptr = ERR18; + goto FAILED; + } + continue; } /* See if the next thing is a quantifier. */ @@ -4685,7 +4799,8 @@ for (;; ptr++) previous = NULL; if ((options & PCRE_MULTILINE) != 0) { - if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; + if (firstcharflags == REQ_UNSET) + zerofirstcharflags = firstcharflags = REQ_NONE; *code++ = OP_CIRCM; } else *code++ = OP_CIRC; @@ -4706,6 +4821,7 @@ for (;; ptr++) zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; break; @@ -4743,20 +4859,21 @@ for (;; ptr++) if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0) { nestptr = ptr + 7; - ptr = sub_start_of_word - 1; - continue; + ptr = sub_start_of_word; + goto REDO_LOOP; } if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0) { nestptr = ptr + 7; - ptr = sub_end_of_word - 1; - continue; + ptr = sub_end_of_word; + goto REDO_LOOP; } /* Handle a real character class. */ previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* PCRE supports POSIX class stuff inside a class. Perl gives an error if they are encountered at the top level, so we'll do that too. */ @@ -4862,10 +4979,11 @@ for (;; ptr++) (which is on the stack). We have to remember that there was XCLASS data, however. */ + if (class_uchardata > class_uchardata_base) xclass = TRUE; + if (lengthptr != NULL && class_uchardata > class_uchardata_base) { - xclass = TRUE; - *lengthptr += class_uchardata - class_uchardata_base; + *lengthptr += (int)(class_uchardata - class_uchardata_base); class_uchardata = class_uchardata_base; } #endif @@ -4967,10 +5085,28 @@ for (;; ptr++) ptr = tempptr + 1; continue; - /* For all other POSIX classes, no special action is taken in UCP - mode. Fall through to the non_UCP case. */ + /* For the other POSIX classes (ascii, cntrl, xdigit) we are going + to fall through to the non-UCP case and build a bit map for + characters with code points less than 256. If we are in a negated + POSIX class, characters with code points greater than 255 must + either all match or all not match. In the special case where we + have not yet generated any xclass data, and this is the final item + in the overall class, we need do nothing: later on, the opcode + OP_NCLASS will be used to indicate that characters greater than 255 + are acceptable. If we have already seen an xclass item or one may + follow (we have to assume that it might if this is not the end of + the class), explicitly list all wide codepoints, which will then + either not match or match, depending on whether the class is or is + not negated. */ default: + if (local_negate && + (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET)) + { + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + } break; } } @@ -5134,9 +5270,9 @@ for (;; ptr++) cd, PRIV(vspace_list)); continue; -#ifdef SUPPORT_UCP case ESC_p: case ESC_P: +#ifdef SUPPORT_UCP { BOOL negated; unsigned int ptype = 0, pdata = 0; @@ -5150,6 +5286,9 @@ for (;; ptr++) class_has_8bitchar--; /* Undo! */ continue; } +#else + *errorcodeptr = ERR45; + goto FAILED; #endif /* Unrecognized escapes are faulted if PCRE is running in its strict mode. By default, for compatibility with Perl, they are @@ -5306,16 +5445,20 @@ for (;; ptr++) CLASS_SINGLE_CHARACTER: if (class_one_char < 2) class_one_char++; - /* If class_one_char is 1, we have the first single character in the - class, and there have been no prior ranges, or XCLASS items generated by - escapes. If this is the final character in the class, we can optimize by - turning the item into a 1-character OP_CHAR[I] if it's positive, or - OP_NOT[I] if it's negative. In the positive case, it can cause firstchar - to be set. Otherwise, there can be no first char if this item is first, - whatever repeat count may follow. In the case of reqchar, save the - previous value for reinstating. */ + /* If xclass_has_prop is false and class_one_char is 1, we have the first + single character in the class, and there have been no prior ranges, or + XCLASS items generated by escapes. If this is the final character in the + class, we can optimize by turning the item into a 1-character OP_CHAR[I] + if it's positive, or OP_NOT[I] if it's negative. In the positive case, it + can cause firstchar to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqchar, save the previous value for reinstating. */ - if (class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (!inescq && +#ifdef SUPPORT_UCP + !xclass_has_prop && +#endif + class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { ptr++; zeroreqchar = reqchar; @@ -5431,12 +5574,41 @@ for (;; ptr++) actual compiled code. */ #ifdef SUPPORT_UTF - if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0)) + if (xclass && (xclass_has_prop || !should_flip_negation || + (options & PCRE_UCP) != 0)) #elif !defined COMPILE_PCRE8 - if (xclass && !should_flip_negation) + if (xclass && (xclass_has_prop || !should_flip_negation)) #endif #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 { + /* For non-UCP wide characters, in a non-negative class containing \S or + similar (should_flip_negation is set), all characters greater than 255 + must be in the class. */ + + if ( +#if defined COMPILE_PCRE8 + utf && +#endif + should_flip_negation && !negate_class && (options & PCRE_UCP) == 0) + { + *class_uchardata++ = XCL_RANGE; + if (utf) /* Will always be utf in the 8-bit library */ + { + class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + } + else /* Can only happen for the 16-bit & 32-bit libraries */ + { +#if defined COMPILE_PCRE16 + *class_uchardata++ = 0x100; + *class_uchardata++ = 0xffffu; +#elif defined COMPILE_PCRE32 + *class_uchardata++ = 0x100; + *class_uchardata++ = 0xffffffffu; +#endif + } + } + *class_uchardata++ = XCL_END; /* Marks the end of extra data */ *code++ = OP_XCLASS; code += LINK_SIZE; @@ -5463,6 +5635,12 @@ for (;; ptr++) PUT(previous, 1, (int)(code - previous)); break; /* End of class handling */ } + + /* Even though any XCLASS list is now discarded, we must allow for + its memory. */ + + if (lengthptr != NULL) + *lengthptr += (int)(class_uchardata - class_uchardata_base); #endif /* If there are no characters > 255, or they are all to be included or @@ -5863,6 +6041,7 @@ for (;; ptr++) { register int i; int len = (int)(code - previous); + size_t base_hwm_offset = item_hwm_offset; pcre_uchar *bralink = NULL; pcre_uchar *brazeroptr = NULL; @@ -5917,7 +6096,7 @@ for (;; ptr++) if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ { *code = OP_END; - adjust_recurse(previous, 1, utf, cd, save_hwm); + adjust_recurse(previous, 1, utf, cd, item_hwm_offset); memmove(previous + 1, previous, IN_UCHARS(len)); code++; if (repeat_max == 0) @@ -5941,7 +6120,7 @@ for (;; ptr++) { int offset; *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm); + adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); code += 2 + LINK_SIZE; *previous++ = OP_BRAZERO + repeat_type; @@ -6004,26 +6183,25 @@ for (;; ptr++) for (i = 1; i < repeat_min; i++) { pcre_uchar *hc; - pcre_uchar *this_hwm = cd->hwm; + size_t this_hwm_offset = cd->hwm - cd->start_workspace; memcpy(code, previous, IN_UCHARS(len)); while (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) + WORK_SIZE_SAFETY_MARGIN - + (this_hwm_offset - base_hwm_offset)) { - int save_offset = save_hwm - cd->start_workspace; - int this_offset = this_hwm - cd->start_workspace; *errorcodeptr = expand_workspace(cd); if (*errorcodeptr != 0) goto FAILED; - save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; - this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; } - for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) + for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset; + hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset; + hc += LINK_SIZE) { PUT(cd->hwm, 0, GET(hc, 0) + len); cd->hwm += LINK_SIZE; } - save_hwm = this_hwm; + base_hwm_offset = this_hwm_offset; code += len; } } @@ -6068,7 +6246,7 @@ for (;; ptr++) else for (i = repeat_max - 1; i >= 0; i--) { pcre_uchar *hc; - pcre_uchar *this_hwm = cd->hwm; + size_t this_hwm_offset = cd->hwm - cd->start_workspace; *code++ = OP_BRAZERO + repeat_type; @@ -6090,22 +6268,21 @@ for (;; ptr++) copying them. */ while (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) + WORK_SIZE_SAFETY_MARGIN - + (this_hwm_offset - base_hwm_offset)) { - int save_offset = save_hwm - cd->start_workspace; - int this_offset = this_hwm - cd->start_workspace; *errorcodeptr = expand_workspace(cd); if (*errorcodeptr != 0) goto FAILED; - save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; - this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; } - for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) + for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset; + hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset; + hc += LINK_SIZE) { PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1)); cd->hwm += LINK_SIZE; } - save_hwm = this_hwm; + base_hwm_offset = this_hwm_offset; code += len; } @@ -6188,6 +6365,12 @@ for (;; ptr++) while (*scode == OP_ALT); } + /* A conditional group with only one branch has an implicit empty + alternative branch. */ + + if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT) + *bracode = OP_SCOND; + /* Handle possessive quantifiers. */ if (possessive_quantifier) @@ -6201,11 +6384,11 @@ for (;; ptr++) { int nlen = (int)(code - bracode); *code = OP_END; - adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm); + adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); code += 1 + LINK_SIZE; nlen += 1 + LINK_SIZE; - *bracode = OP_BRAPOS; + *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS; *code++ = OP_KETRPOS; PUTINC(code, 0, nlen); PUT(bracode, 1, nlen); @@ -6335,7 +6518,7 @@ for (;; ptr++) else { *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6384,7 +6567,7 @@ for (;; ptr++) default: *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6413,15 +6596,10 @@ for (;; ptr++) parenthesis forms. */ case CHAR_LEFT_PARENTHESIS: - newoptions = options; - skipbytes = 0; - bravalue = OP_CBRA; - save_hwm = cd->hwm; - reset_bracount = FALSE; - - /* First deal with various "verbs" that can be introduced by '*'. */ - ptr++; + + /* Now deal with various "verbs" that can be introduced by '*'. */ + if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':' || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0)))) { @@ -6480,8 +6658,21 @@ for (;; ptr++) cd->had_accept = TRUE; for (oc = cd->open_caps; oc != NULL; oc = oc->next) { - *code++ = OP_CLOSE; - PUT2INC(code, 0, oc->number); + if (lengthptr != NULL) + { +#ifdef COMPILE_PCRE8 + *lengthptr += 1 + IMM2_SIZE; +#elif defined COMPILE_PCRE16 + *lengthptr += 2 + IMM2_SIZE; +#elif defined COMPILE_PCRE32 + *lengthptr += 4 + IMM2_SIZE; +#endif + } + else + { + *code++ = OP_CLOSE; + PUT2INC(code, 0, oc->number); + } } setverb = *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT; @@ -6510,9 +6701,17 @@ for (;; ptr++) goto FAILED; } setverb = *code++ = verbs[i].op_arg; - *code++ = arglen; - memcpy(code, arg, IN_UCHARS(arglen)); - code += arglen; + if (lengthptr != NULL) /* In pass 1 just add in the length */ + { /* to avoid potential workspace */ + *lengthptr += arglen; /* overflow. */ + *code++ = 0; + } + else + { + *code++ = arglen; + memcpy(code, arg, IN_UCHARS(arglen)); + code += arglen; + } *code++ = 0; } @@ -6542,10 +6741,18 @@ for (;; ptr++) goto FAILED; } + /* Initialize for "real" parentheses */ + + newoptions = options; + skipbytes = 0; + bravalue = OP_CBRA; + item_hwm_offset = cd->hwm - cd->start_workspace; + reset_bracount = FALSE; + /* Deal with the extended parentheses; all are introduced by '?', and the appearance of any of them means that this is not a capturing group. */ - else if (*ptr == CHAR_QUESTION_MARK) + if (*ptr == CHAR_QUESTION_MARK) { int i, set, unset, namelen; int *optset; @@ -6554,20 +6761,10 @@ for (;; ptr++) switch (*(++ptr)) { - case CHAR_NUMBER_SIGN: /* Comment; skip to ket */ - ptr++; - while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; - if (*ptr == CHAR_NULL) - { - *errorcodeptr = ERR18; - goto FAILED; - } - continue; - - /* ------------------------------------------------------------ */ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ reset_bracount = TRUE; + cd->dupgroups = TRUE; /* Record (?| encountered */ /* Fall through */ /* ------------------------------------------------------------ */ @@ -6604,6 +6801,15 @@ for (;; ptr++) for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break; if (ptr[i] == CHAR_RIGHT_PARENTHESIS) tempptr += i + 1; + + /* tempptr should now be pointing to the opening parenthesis of the + assertion condition. */ + + if (*tempptr != CHAR_LEFT_PARENTHESIS) + { + *errorcodeptr = ERR28; + goto FAILED; + } } /* For conditions that are assertions, check the syntax, and then exit @@ -6613,8 +6819,13 @@ for (;; ptr++) if (tempptr[1] == CHAR_QUESTION_MARK && (tempptr[2] == CHAR_EQUALS_SIGN || tempptr[2] == CHAR_EXCLAMATION_MARK || - tempptr[2] == CHAR_LESS_THAN_SIGN)) + (tempptr[2] == CHAR_LESS_THAN_SIGN && + (tempptr[3] == CHAR_EQUALS_SIGN || + tempptr[3] == CHAR_EXCLAMATION_MARK)))) + { + cd->iscondassert = TRUE; break; + } /* Other conditions use OP_CREF/OP_DNCREF/OP_RREF/OP_DNRREF, and all need to skip at least 1+IMM2_SIZE bytes at the start of the group. */ @@ -6663,6 +6874,12 @@ for (;; ptr++) { while (IS_DIGIT(*ptr)) { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + (int)(*ptr - CHAR_0); ptr++; } @@ -6691,7 +6908,7 @@ for (;; ptr++) ptr++; } namelen = (int)(ptr - name); - if (lengthptr != NULL) *lengthptr += IMM2_SIZE; + if (lengthptr != NULL) skipbytes += IMM2_SIZE; } /* Check the terminator */ @@ -6727,6 +6944,7 @@ for (;; ptr++) goto FAILED; } PUT2(code, 2+LINK_SIZE, recno); + if (recno > cd->top_backref) cd->top_backref = recno; break; } @@ -6735,7 +6953,8 @@ for (;; ptr++) slot = cd->name_table; for (i = 0; i < cd->names_found; i++) { - if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break; + if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 && + slot[IMM2_SIZE+namelen] == 0) break; slot += cd->name_entry_size; } @@ -6749,12 +6968,15 @@ for (;; ptr++) int offset = i++; int count = 1; recno = GET2(slot, 0); /* Number from first found */ + if (recno > cd->top_backref) cd->top_backref = recno; for (; i < cd->names_found; i++) { slot += cd->name_entry_size; - if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0) break; + if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0 || + (slot+IMM2_SIZE)[namelen] != 0) break; count++; } + if (count > 1) { PUT2(code, 2+LINK_SIZE, offset); @@ -6793,6 +7015,11 @@ for (;; ptr++) *errorcodeptr = ERR15; goto FAILED; } + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + name[i] - CHAR_0; } if (recno == 0) recno = RREF_ANY; @@ -7069,6 +7296,7 @@ for (;; ptr++) if (lengthptr != NULL) { named_group *ng; + recno = 0; if (namelen == 0) { @@ -7086,23 +7314,70 @@ for (;; ptr++) goto FAILED; } - /* The name table does not exist in the first pass; instead we must - scan the list of names encountered so far in order to get the - number. If the name is not found, set the value to 0 for a forward - reference. */ - - ng = cd->named_groups; - for (i = 0; i < cd->names_found; i++, ng++) - { - if (namelen == ng->length && - STRNCMP_UC_UC(name, ng->name, namelen) == 0) - break; - } - recno = (i < cd->names_found)? ng->number : 0; - /* Count named back references. */ if (!is_recurse) cd->namedrefcount++; + + /* We have to allow for a named reference to a duplicated name (this + cannot be determined until the second pass). This needs an extra + 16-bit data item. */ + + *lengthptr += IMM2_SIZE; + + /* If this is a forward reference and we are within a (?|...) group, + the reference may end up as the number of a group which we are + currently inside, that is, it could be a recursive reference. In the + real compile this will be picked up and the reference wrapped with + OP_ONCE to make it atomic, so we must space in case this occurs. */ + + /* In fact, this can happen for a non-forward reference because + another group with the same number might be created later. This + issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance + only mode, we finesse the bug by allowing more memory always. */ + + *lengthptr += 4 + 4*LINK_SIZE; + + /* It is even worse than that. The current reference may be to an + existing named group with a different number (so apparently not + recursive) but which later on is also attached to a group with the + current number. This can only happen if $(| has been previous + encountered. In that case, we allow yet more memory, just in case. + (Again, this is fixed "properly" in PCRE2. */ + + if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE; + + /* Otherwise, check for recursion here. The name table does not exist + in the first pass; instead we must scan the list of names encountered + so far in order to get the number. If the name is not found, leave + the value of recno as 0 for a forward reference. */ + + /* This patch (removing "else") fixes a problem when a reference is + to multiple identically named nested groups from within the nest. + Once again, it is not the "proper" fix, and it results in an + over-allocation of memory. */ + + /* else */ + { + ng = cd->named_groups; + for (i = 0; i < cd->names_found; i++, ng++) + { + if (namelen == ng->length && + STRNCMP_UC_UC(name, ng->name, namelen) == 0) + { + open_capitem *oc; + recno = ng->number; + if (is_recurse) break; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + if (oc->number == recno) + { + oc->flag = TRUE; + break; + } + } + } + } + } } /* In the real compile, search the name table. We check the name @@ -7157,6 +7432,7 @@ for (;; ptr++) { if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); @@ -7194,9 +7470,14 @@ for (;; ptr++) /* ------------------------------------------------------------ */ - case CHAR_R: /* Recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ + case CHAR_R: /* Recursion, same as (?0) */ + recno = 0; + if (*(++ptr) != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR29; + goto FAILED; + } + goto HANDLE_RECURSION; /* ------------------------------------------------------------ */ @@ -7233,7 +7514,15 @@ for (;; ptr++) recno = 0; while(IS_DIGIT(*ptr)) + { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + *ptr++ - CHAR_0; + } if (*ptr != (pcre_uchar)terminator) { @@ -7270,6 +7559,7 @@ for (;; ptr++) HANDLE_RECURSION: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; called = cd->start_code; /* When we are actually compiling, find the bracket that is being @@ -7377,39 +7667,15 @@ for (;; ptr++) newoptions = (options | set) & (~unset); /* If the options ended with ')' this is not the start of a nested - group with option changes, so the options change at this level. If this - item is right at the start of the pattern, the options can be - abstracted and made external in the pre-compile phase, and ignored in - the compile phase. This can be helpful when matching -- for instance in - caseless checking of required bytes. - - If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are - definitely *not* at the start of the pattern because something has been - compiled. In the pre-compile phase, however, the code pointer can have - that value after the start, because it gets reset as code is discarded - during the pre-compile. However, this can happen only at top level - if - we are within parentheses, the starting BRA will still be present. At - any parenthesis level, the length value can be used to test if anything - has been compiled at that level. Thus, a test for both these conditions - is necessary to ensure we correctly detect the start of the pattern in - both phases. - + group with option changes, so the options change at this level. If we are not at the pattern start, reset the greedy defaults and the case value for firstchar and reqchar. */ if (*ptr == CHAR_RIGHT_PARENTHESIS) { - if (code == cd->start_code + 1 + LINK_SIZE && - (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE)) - { - cd->external_options = newoptions; - } - else - { - greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); - greedy_non_default = greedy_default ^ 1; - req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0; - } + greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); + greedy_non_default = greedy_default ^ 1; + req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0; /* Change options at this level, and pass them back for use in subsequent branches. */ @@ -7457,12 +7723,26 @@ for (;; ptr++) goto FAILED; } - /* Assertions used not to be repeatable, but this was changed for Perl - compatibility, so all kinds can now be repeated. We copy code into a + /* All assertions used not to be repeatable, but this was changed for Perl + compatibility. All kinds can now be repeated except for assertions that are + conditions (Perl also forbids these to be repeated). We copy code into a non-register variable (tempcode) in order to be able to pass its address - because some compilers complain otherwise. */ + because some compilers complain otherwise. At the start of a conditional + group whose condition is an assertion, cd->iscondassert is set. We unset it + here so as to allow assertions later in the group to be quantified. */ + + if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT && + cd->iscondassert) + { + previous = NULL; + cd->iscondassert = FALSE; + } + else + { + previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; + } - previous = code; /* For handling repetition */ *code = bravalue; tempcode = code; tempreqvary = cd->req_varyopt; /* Save value before bracket */ @@ -7640,15 +7920,17 @@ for (;; ptr++) } } - /* For a forward assertion, we take the reqchar, if set. This can be - helpful if the pattern that follows the assertion doesn't set a different - char. For example, it's useful for /(?=abcde).+/. We can't set firstchar - for an assertion, however because it leads to incorrect effect for patterns - such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead - of a firstchar. This is overcome by a scan at the end if there's no - firstchar, looking for an asserted first char. */ + /* For a forward assertion, we take the reqchar, if set, provided that the + group has also set a first char. This can be helpful if the pattern that + follows the assertion doesn't set a different char. For example, it's + useful for /(?=abcde).+/. We can't set firstchar for an assertion, however + because it leads to incorrect effect for patterns such as /(?=a)a.+/ when + the "real" "a" would then become a reqchar instead of a firstchar. This is + overcome by a scan at the end if there's no firstchar, looking for an + asserted first char. */ - else if (bravalue == OP_ASSERT && subreqcharflags >= 0) + else if (bravalue == OP_ASSERT && subreqcharflags >= 0 && + subfirstcharflags >= 0) { reqchar = subreqchar; reqcharflags = subreqcharflags; @@ -7674,16 +7956,6 @@ for (;; ptr++) c = ec; else { - if (escape == ESC_Q) /* Handle start of quoted string */ - { - if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) - ptr += 2; /* avoid empty string */ - else inescq = TRUE; - continue; - } - - if (escape == ESC_E) continue; /* Perl ignores an orphan \E */ - /* For metasequences that actually match a character, we disable the setting of a first character if it hasn't already been set. */ @@ -7709,7 +7981,7 @@ for (;; ptr++) const pcre_uchar *p; pcre_uint32 cf; - save_hwm = cd->hwm; /* Normally this is set when '(' is read */ + item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; @@ -7738,7 +8010,7 @@ for (;; ptr++) if (*p != (pcre_uchar)terminator) { *errorcodeptr = ERR57; - break; + goto FAILED; } ptr++; goto HANDLE_NUMERICAL_RECURSION; @@ -7753,7 +8025,7 @@ for (;; ptr++) ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) { *errorcodeptr = ERR69; - break; + goto FAILED; } is_recurse = FALSE; terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? @@ -7777,6 +8049,7 @@ for (;; ptr++) HANDLE_REFERENCE: if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); cd->backref_map |= (recno < 32)? (1 << recno) : 1; @@ -7806,6 +8079,7 @@ for (;; ptr++) if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; *code++ = ptype; *code++ = pdata; @@ -7846,6 +8120,7 @@ for (;; ptr++) { previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; } } @@ -7889,6 +8164,7 @@ for (;; ptr++) ONE_CHAR: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special @@ -8036,6 +8312,7 @@ int length; unsigned int orig_bracount; unsigned int max_bracount; branch_chain bc; +size_t save_hwm_offset; /* If set, call the external function that checks for stack availability. */ @@ -8053,6 +8330,8 @@ bc.current_branch = code; firstchar = reqchar = 0; firstcharflags = reqcharflags = REQ_UNSET; +save_hwm_offset = cd->hwm - cd->start_workspace; + /* Accumulate the length for use in the pre-compile phase. Start with the length of the BRA and KET and any extra bytes that are required at the beginning. We accumulate in a local variable to save frequent testing of @@ -8194,7 +8473,7 @@ for (;;) int fixed_length; *code = OP_END; fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0, - FALSE, cd); + FALSE, cd, NULL); DPRINTF(("fixed length = %d\n", fixed_length)); if (fixed_length == -3) { @@ -8246,12 +8525,16 @@ for (;;) /* If it was a capturing subpattern, check to see if it contained any recursive back references. If so, we must wrap it in atomic brackets. - In any event, remove the block from the chain. */ + Because we are moving code along, we must ensure that any pending recursive + references are updated. In any event, remove the block from the chain. */ if (capnumber > 0) { if (cd->open_caps->flag) { + *code = OP_END; + adjust_recurse(start_bracket, 1 + LINK_SIZE, + (options & PCRE_UTF8) != 0, cd, save_hwm_offset); memmove(start_bracket + 1 + LINK_SIZE, start_bracket, IN_UCHARS(code - start_bracket)); *start_bracket = OP_ONCE; @@ -8436,8 +8719,8 @@ matching and for non-DOTALL patterns that start with .* (which must start at the beginning or after \n). As in the case of is_anchored() (see above), we have to take account of back references to capturing brackets that contain .* because in that case we can't make the assumption. Also, the appearance of .* -inside atomic brackets or in a pattern that contains *PRUNE or *SKIP does not -count, because once again the assumption no longer holds. +inside atomic brackets or in an assertion, or in a pattern that contains *PRUNE +or *SKIP does not count, because once again the assumption no longer holds. Arguments: code points to start of expression (the bracket) @@ -8446,13 +8729,14 @@ Arguments: the less precise approach cd points to the compile data atomcount atomic group level + inassert TRUE if in an assertion Returns: TRUE or FALSE */ static BOOL is_startline(const pcre_uchar *code, unsigned int bracket_map, - compile_data *cd, int atomcount) + compile_data *cd, int atomcount, BOOL inassert) { do { const pcre_uchar *scode = first_significant_code( @@ -8475,10 +8759,11 @@ do { case OP_RREF: case OP_DNRREF: case OP_DEF: + case OP_FAIL: return FALSE; default: /* Assertion */ - if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE; + if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE; do scode += GET(scode, 1); while (*scode == OP_ALT); scode += 1 + LINK_SIZE; break; @@ -8492,7 +8777,7 @@ do { if (op == OP_BRA || op == OP_BRAPOS || op == OP_SBRA || op == OP_SBRAPOS) { - if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE; + if (!is_startline(scode, bracket_map, cd, atomcount, inassert)) return FALSE; } /* Capturing brackets */ @@ -8502,33 +8787,33 @@ do { { int n = GET2(scode, 1+LINK_SIZE); int new_map = bracket_map | ((n < 32)? (1 << n) : 1); - if (!is_startline(scode, new_map, cd, atomcount)) return FALSE; + if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE; } /* Positive forward assertions */ else if (op == OP_ASSERT) { - if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE; + if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE; } /* Atomic brackets */ else if (op == OP_ONCE || op == OP_ONCE_NC) { - if (!is_startline(scode, bracket_map, cd, atomcount + 1)) return FALSE; + if (!is_startline(scode, bracket_map, cd, atomcount + 1, inassert)) return FALSE; } /* .* means "start at start or after \n" if it isn't in atomic brackets or - brackets that may be referenced, as long as the pattern does not contain - *PRUNE or *SKIP, because these break the feature. Consider, for example, - /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the - start of a line. */ + brackets that may be referenced or an assertion, as long as the pattern does + not contain *PRUNE or *SKIP, because these break the feature. Consider, for + example, /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. + not at the start of a line. */ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR) { if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 || - atomcount > 0 || cd->had_pruneorskip) + atomcount > 0 || cd->had_pruneorskip || inassert) return FALSE; } @@ -9056,9 +9341,11 @@ cd->names_found = 0; cd->name_entry_size = 0; cd->name_table = NULL; cd->dupnames = FALSE; +cd->dupgroups = FALSE; cd->namedrefcount = 0; cd->start_code = cworkspace; cd->hwm = cworkspace; +cd->iscondassert = FALSE; cd->start_workspace = cworkspace; cd->workspace_size = COMPILE_WORK_SIZE; cd->named_groups = named_groups; @@ -9096,13 +9383,6 @@ if (length > MAX_PATTERN_SIZE) goto PCRE_EARLY_ERROR_RETURN; } -/* If there are groups with duplicate names and there are also references by -name, we must allow for the possibility of named references to duplicated -groups. These require an extra data item each. */ - -if (cd->dupnames && cd->namedrefcount > 0) - length += cd->namedrefcount * IMM2_SIZE * sizeof(pcre_uchar); - /* Compute the size of the data block for storing the compiled pattern. Integer overflow should no longer be possible because nowadays we limit the maximum value of cd->names_found and cd->name_entry_size. */ @@ -9161,6 +9441,7 @@ cd->name_table = (pcre_uchar *)re + re->name_table_offset; codestart = cd->name_table + re->name_entry_size * re->name_count; cd->start_code = codestart; cd->hwm = (pcre_uchar *)(cd->start_workspace); +cd->iscondassert = FALSE; cd->req_varyopt = 0; cd->had_accept = FALSE; cd->had_pruneorskip = FALSE; @@ -9233,6 +9514,16 @@ if (cd->hwm > cd->start_workspace) int offset, recno; cd->hwm -= LINK_SIZE; offset = GET(cd->hwm, 0); + + /* Check that the hwm handling hasn't gone wrong. This whole area is + rewritten in PCRE2 because there are some obscure cases. */ + + if (offset == 0 || codestart[offset-1] != OP_RECURSE) + { + errorcode = ERR10; + break; + } + recno = GET(codestart, offset); if (recno != prev_recno) { @@ -9256,11 +9547,18 @@ subpattern. */ if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15; -/* Unless disabled, check whether single character iterators can be -auto-possessified. The function overwrites the appropriate opcode values. */ +/* Unless disabled, check whether any single character iterators can be +auto-possessified. The function overwrites the appropriate opcode values, so +the type of the pointer must be cast. NOTE: the intermediate variable "temp" is +used in this code because at least one compiler gives a warning about loss of +"const" attribute if the cast (pcre_uchar *)codestart is used directly in the +function call. */ -if ((options & PCRE_NO_AUTO_POSSESS) == 0) - auto_possessify((pcre_uchar *)codestart, utf, cd); +if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0) + { + pcre_uchar *temp = (pcre_uchar *)codestart; + auto_possessify(temp, utf, cd); + } /* If there were any lookbehind assertions that contained OP_RECURSE (recursions or subroutine calls), a flag is set for them to be checked here, @@ -9270,7 +9568,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The exceptional ones forgo this. We scan the pattern to check that they are fixed length, and set their lengths. */ -if (cd->check_lookbehind) +if (errorcode == 0 && cd->check_lookbehind) { pcre_uchar *cc = (pcre_uchar *)codestart; @@ -9290,7 +9588,7 @@ if (cd->check_lookbehind) int end_op = *be; *be = OP_END; fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE, - cd); + cd, NULL); *be = end_op; DPRINTF(("fixed length = %d\n", fixed_length)); if (fixed_length < 0) @@ -9370,7 +9668,7 @@ if ((re->options & PCRE_ANCHORED) == 0) re->flags |= PCRE_FIRSTSET; } - else if (is_startline(codestart, 0, cd, 0)) re->flags |= PCRE_STARTLINE; + else if (is_startline(codestart, 0, cd, 0, FALSE)) re->flags |= PCRE_STARTLINE; } } diff --git a/Foundation/src/pcre_config.h b/Foundation/src/pcre_config.h index b8abd65a1..ea56cf017 100644 --- a/Foundation/src/pcre_config.h +++ b/Foundation/src/pcre_config.h @@ -283,7 +283,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_NAME "PCRE" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "PCRE 8.35" +#define PACKAGE_STRING "PCRE 8.40" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre" @@ -292,7 +292,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "8.35" +#define PACKAGE_VERSION "8.40" /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system @@ -394,7 +394,7 @@ sure both macros are undefined; an emulation function will then be used. */ /* #undef SUPPORT_VALGRIND */ /* Version number of package */ -#define VERSION "8.35" +#define VERSION "8.40" /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ diff --git a/Foundation/src/pcre_dfa_exec.c b/Foundation/src/pcre_dfa_exec.c index c58b8596d..d6253a5cd 100644 --- a/Foundation/src/pcre_dfa_exec.c +++ b/Foundation/src/pcre_dfa_exec.c @@ -2735,9 +2735,10 @@ for (;;) condcode == OP_DNRREF) return PCRE_ERROR_DFA_UCOND; - /* The DEFINE condition is always false */ + /* The DEFINE condition is always false, and the assertion (?!) is + converted to OP_FAIL. */ - if (condcode == OP_DEF) + if (condcode == OP_DEF || condcode == OP_FAIL) { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } /* The only supported version of OP_RREF is for the value RREF_ANY, @@ -3241,7 +3242,7 @@ md->callout_data = NULL; if (extra_data != NULL) { - unsigned int flags = extra_data->flags; + unsigned long int flags = extra_data->flags; if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) study = (const pcre_study_data *)extra_data->study_data; if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT; diff --git a/Foundation/src/pcre_exec.c b/Foundation/src/pcre_exec.c index 91adb2ec8..6658b2b97 100644 --- a/Foundation/src/pcre_exec.c +++ b/Foundation/src/pcre_exec.c @@ -1137,88 +1137,81 @@ for (;;) printf("\n"); #endif - if (offset < md->offset_max) + if (offset >= md->offset_max) goto POSSESSIVE_NON_CAPTURE; + + matched_once = FALSE; + code_offset = (int)(ecode - md->start_code); + + save_offset1 = md->offset_vector[offset]; + save_offset2 = md->offset_vector[offset+1]; + save_offset3 = md->offset_vector[md->offset_end - number]; + save_capture_last = md->capture_last; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + + /* Each time round the loop, save the current subject position for use + when the group matches. For MATCH_MATCH, the group has matched, so we + restart it with a new subject starting position, remembering that we had + at least one match. For MATCH_NOMATCH, carry on with the alternatives, as + usual. If we haven't matched any alternatives in any iteration, check to + see if a previous iteration matched. If so, the group has matched; + continue from afterwards. Otherwise it has failed; restore the previous + capture values before returning NOMATCH. */ + + for (;;) { - matched_once = FALSE; - code_offset = (int)(ecode - md->start_code); - - save_offset1 = md->offset_vector[offset]; - save_offset2 = md->offset_vector[offset+1]; - save_offset3 = md->offset_vector[md->offset_end - number]; - save_capture_last = md->capture_last; - - DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); - - /* Each time round the loop, save the current subject position for use - when the group matches. For MATCH_MATCH, the group has matched, so we - restart it with a new subject starting position, remembering that we had - at least one match. For MATCH_NOMATCH, carry on with the alternatives, as - usual. If we haven't matched any alternatives in any iteration, check to - see if a previous iteration matched. If so, the group has matched; - continue from afterwards. Otherwise it has failed; restore the previous - capture values before returning NOMATCH. */ - - for (;;) + md->offset_vector[md->offset_end - number] = + (int)(eptr - md->start_subject); + if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM63); + if (rrc == MATCH_KETRPOS) { - md->offset_vector[md->offset_end - number] = - (int)(eptr - md->start_subject); - if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM63); - if (rrc == MATCH_KETRPOS) + offset_top = md->end_offset_top; + ecode = md->start_code + code_offset; + save_capture_last = md->capture_last; + matched_once = TRUE; + mstart = md->start_match_ptr; /* In case \K changed it */ + if (eptr == md->end_match_ptr) /* Matched an empty string */ { - offset_top = md->end_offset_top; - eptr = md->end_match_ptr; - ecode = md->start_code + code_offset; - save_capture_last = md->capture_last; - matched_once = TRUE; - mstart = md->start_match_ptr; /* In case \K changed it */ - continue; + do ecode += GET(ecode, 1); while (*ecode == OP_ALT); + break; } - - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->capture_last = save_capture_last; - ecode += GET(ecode, 1); - if (*ecode != OP_ALT) break; + eptr = md->end_match_ptr; + continue; } - if (!matched_once) + /* See comment in the code for capturing groups above about handling + THEN. */ + + if (rrc == MATCH_THEN) { - md->offset_vector[offset] = save_offset1; - md->offset_vector[offset+1] = save_offset2; - md->offset_vector[md->offset_end - number] = save_offset3; + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; } - if (allow_zero || matched_once) - { - ecode += 1 + LINK_SIZE; - break; - } - - RRETURN(MATCH_NOMATCH); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + if (*ecode != OP_ALT) break; } - /* FALL THROUGH ... Insufficient room for saving captured contents. Treat - as a non-capturing bracket. */ + if (!matched_once) + { + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + } - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + if (allow_zero || matched_once) + { + ecode += 1 + LINK_SIZE; + break; + } - DPRINTF(("insufficient capture room: treat as non-capturing\n")); - - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + RRETURN(MATCH_NOMATCH); /* Non-capturing possessive bracket with unlimited repeat. We come here from BRAZERO with allow_zero = TRUE. The code is similar to the above, @@ -1242,10 +1235,15 @@ for (;;) if (rrc == MATCH_KETRPOS) { offset_top = md->end_offset_top; - eptr = md->end_match_ptr; ecode = md->start_code + code_offset; matched_once = TRUE; mstart = md->start_match_ptr; /* In case \K reset it */ + if (eptr == md->end_match_ptr) /* Matched an empty string */ + { + do ecode += GET(ecode, 1); while (*ecode == OP_ALT); + break; + } + eptr = md->end_match_ptr; continue; } @@ -1379,6 +1377,7 @@ for (;;) break; case OP_DEF: /* DEFINE - always false */ + case OP_FAIL: /* From optimized (?!) condition */ break; /* The condition is an assertion. Call match() to evaluate it - setting @@ -1395,8 +1394,11 @@ for (;;) condition = TRUE; /* Advance ecode past the assertion to the start of the first branch, - but adjust it so that the general choosing code below works. */ + but adjust it so that the general choosing code below works. If the + assertion has a quantifier that allows zero repeats we must skip over + the BRAZERO. This is a lunatic thing to do, but somebody did! */ + if (*ecode == OP_BRAZERO) ecode++; ecode += GET(ecode, 1); while (*ecode == OP_ALT) ecode += GET(ecode, 1); ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode]; @@ -1465,7 +1467,18 @@ for (;;) md->offset_vector[offset] = md->offset_vector[md->offset_end - number]; md->offset_vector[offset+1] = (int)(eptr - md->start_subject); - if (offset_top <= offset) offset_top = offset + 2; + + /* If this group is at or above the current highwater mark, ensure that + any groups between the current high water mark and this group are marked + unset and then update the high water mark. */ + + if (offset >= offset_top) + { + register int *iptr = md->offset_vector + offset_top; + register int *iend = md->offset_vector + offset; + while (iptr < iend) *iptr++ = -1; + offset_top = offset + 2; + } } ecode += 1 + IMM2_SIZE; break; @@ -1817,7 +1830,11 @@ for (;;) are defined in a range that can be tested for. */ if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX) + { + if (new_recursive.offset_save != stacksave) + (PUBL(free))(new_recursive.offset_save); RRETURN(MATCH_NOMATCH); + } /* Any return code other than NOMATCH is an error. */ @@ -1980,6 +1997,19 @@ for (;;) } } + /* OP_KETRPOS is a possessive repeating ket. Remember the current position, + and return the MATCH_KETRPOS. This makes it possible to do the repeats one + at a time from the outer level, thus saving stack. This must precede the + empty string test - in this case that test is done at the outer level. */ + + if (*ecode == OP_KETRPOS) + { + md->start_match_ptr = mstart; /* In case \K reset it */ + md->end_match_ptr = eptr; + md->end_offset_top = offset_top; + RRETURN(MATCH_KETRPOS); + } + /* For an ordinary non-repeating ket, just continue at this level. This also happens for a repeating ket if no characters were matched in the group. This is the forcible breaking of infinite loops as implemented in @@ -2002,18 +2032,6 @@ for (;;) break; } - /* OP_KETRPOS is a possessive repeating ket. Remember the current position, - and return the MATCH_KETRPOS. This makes it possible to do the repeats one - at a time from the outer level, thus saving stack. */ - - if (*ecode == OP_KETRPOS) - { - md->start_match_ptr = mstart; /* In case \K reset it */ - md->end_match_ptr = eptr; - md->end_offset_top = offset_top; - RRETURN(MATCH_KETRPOS); - } - /* The normal repeating kets try the rest of the pattern or restart from the preceding bracket, in the appropriate order. In the second case, we can use tail recursion to avoid using another stack frame, unless we have an @@ -3466,7 +3484,7 @@ for (;;) if (possessive) continue; /* No backtracking */ for(;;) { - if (eptr == pp) goto TAIL_RECURSE; + if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM23); if (rrc != MATCH_NOMATCH) RRETURN(rrc); #ifdef SUPPORT_UCP @@ -3887,7 +3905,7 @@ for (;;) if (possessive) continue; /* No backtracking */ for(;;) { - if (eptr == pp) goto TAIL_RECURSE; + if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM30); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; @@ -4022,7 +4040,7 @@ for (;;) if (possessive) continue; /* No backtracking */ for(;;) { - if (eptr == pp) goto TAIL_RECURSE; + if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM34); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; @@ -5593,7 +5611,7 @@ for (;;) if (possessive) continue; /* No backtracking */ for(;;) { - if (eptr == pp) goto TAIL_RECURSE; + if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM44); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; @@ -5635,12 +5653,17 @@ for (;;) if (possessive) continue; /* No backtracking */ + /* We use <= pp rather than == pp to detect the start of the run while + backtracking because the use of \C in UTF mode can cause BACKCHAR to + move back past pp. This is just palliative; the use of \C in UTF mode + is fraught with danger. */ + for(;;) { int lgb, rgb; PCRE_PUCHAR fptr; - if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */ + if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ RMATCH(eptr, ecode, offset_top, md, eptrb, RM45); if (rrc != MATCH_NOMATCH) RRETURN(rrc); @@ -5658,7 +5681,7 @@ for (;;) for (;;) { - if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */ + if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ fptr = eptr - 1; if (!utf) c = *fptr; else { @@ -5682,54 +5705,25 @@ for (;;) switch(ctype) { case OP_ANY: - if (max < INT_MAX) + for (i = min; i < max; i++) { - for (i = min; i < max; i++) + if (eptr >= md->end_subject) { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (IS_NEWLINE(eptr)) break; - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - UCHAR21(eptr) == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + SCHECK_PARTIAL(); + break; } - } - - /* Handle unlimited UTF-8 repeat */ - - else - { - for (i = min; i < max; i++) + if (IS_NEWLINE(eptr)) break; + if (md->partial != 0 && /* Take care with CRLF partial */ + eptr + 1 >= md->end_subject && + NLBLOCK->nltype == NLTYPE_FIXED && + NLBLOCK->nllen == 2 && + UCHAR21(eptr) == NLBLOCK->nl[0]) { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (IS_NEWLINE(eptr)) break; - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - UCHAR21(eptr) == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + md->hitend = TRUE; + if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; @@ -5937,7 +5931,7 @@ for (;;) if (possessive) continue; /* No backtracking */ for(;;) { - if (eptr == pp) goto TAIL_RECURSE; + if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM46); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; @@ -6520,7 +6514,7 @@ tables = re->tables; if (extra_data != NULL) { - register unsigned int flags = extra_data->flags; + unsigned long int flags = extra_data->flags; if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) study = (const pcre_study_data *)extra_data->study_data; if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) @@ -6692,7 +6686,8 @@ if (md->offset_vector != NULL) register int *iend = iptr - re->top_bracket; if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; while (--iptr >= iend) *iptr = -1; - md->offset_vector[0] = md->offset_vector[1] = -1; + if (offsetcount > 0) md->offset_vector[0] = -1; + if (offsetcount > 1) md->offset_vector[1] = -1; } /* Set up the first character to match, if available. The first_char value is diff --git a/Foundation/src/pcre_get.c b/Foundation/src/pcre_get.c index b0f0bc8a0..34fcaf19c 100644 --- a/Foundation/src/pcre_get.c +++ b/Foundation/src/pcre_get.c @@ -247,6 +247,7 @@ Arguments: code the compiled regex stringname the name of the capturing substring ovector the vector of matched substrings + stringcount number of captured substrings Returns: the number of the first that is set, or the number of the last one if none are set, @@ -255,13 +256,16 @@ Returns: the number of the first that is set, #if defined COMPILE_PCRE8 static int -get_first_set(const pcre *code, const char *stringname, int *ovector) +get_first_set(const pcre *code, const char *stringname, int *ovector, + int stringcount) #elif defined COMPILE_PCRE16 static int -get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector) +get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector, + int stringcount) #elif defined COMPILE_PCRE32 static int -get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector) +get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector, + int stringcount) #endif { const REAL_PCRE *re = (const REAL_PCRE *)code; @@ -292,7 +296,7 @@ if (entrysize <= 0) return entrysize; for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize) { int n = GET2(entry, 0); - if (ovector[n*2] >= 0) return n; + if (n < stringcount && ovector[n*2] >= 0) return n; } return GET2(entry, 0); } @@ -399,7 +403,7 @@ pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, PCRE_UCHAR32 *buffer, int size) #endif { -int n = get_first_set(code, stringname, ovector); +int n = get_first_set(code, stringname, ovector, stringcount); if (n <= 0) return n; #if defined COMPILE_PCRE8 return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); @@ -454,7 +458,10 @@ pcre_uchar **stringlist; pcre_uchar *p; for (i = 0; i < double_count; i += 2) - size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1); + { + size += sizeof(pcre_uchar *) + IN_UCHARS(1); + if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]); + } stringlist = (pcre_uchar **)(PUBL(malloc))(size); if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; @@ -470,7 +477,7 @@ p = (pcre_uchar *)(stringlist + stringcount + 1); for (i = 0; i < double_count; i += 2) { - int len = ovector[i+1] - ovector[i]; + int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0; memcpy(p, subject + ovector[i], IN_UCHARS(len)); *stringlist++ = p; p += len; @@ -616,7 +623,7 @@ pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, PCRE_SPTR32 *stringptr) #endif { -int n = get_first_set(code, stringname, ovector); +int n = get_first_set(code, stringname, ovector, stringcount); if (n <= 0) return n; #if defined COMPILE_PCRE8 return pcre_get_substring(subject, ovector, stringcount, n, stringptr); diff --git a/Foundation/src/pcre_internal.h b/Foundation/src/pcre_internal.h index f3e69fcdc..2923b29f8 100644 --- a/Foundation/src/pcre_internal.h +++ b/Foundation/src/pcre_internal.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel - Copyright (c) 1997-2014 University of Cambridge + Copyright (c) 1997-2016 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -229,9 +229,9 @@ stdint.h is available, include it; it may define INT64_MAX. Systems that do not have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set by "configure". */ -#if HAVE_STDINT_H +#if defined HAVE_STDINT_H #include -#elif HAVE_INTTYPES_H +#elif defined HAVE_INTTYPES_H #include #endif @@ -275,7 +275,7 @@ pcre.h(.in) and disable (comment out) this message. */ typedef pcre_uint16 pcre_uchar; #define UCHAR_SHIFT (1) -#define IN_UCHARS(x) ((x) << UCHAR_SHIFT) +#define IN_UCHARS(x) ((x) * 2) #define MAX_255(c) ((c) <= 255u) #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) @@ -283,7 +283,7 @@ typedef pcre_uint16 pcre_uchar; typedef pcre_uint32 pcre_uchar; #define UCHAR_SHIFT (2) -#define IN_UCHARS(x) ((x) << UCHAR_SHIFT) +#define IN_UCHARS(x) ((x) * 4) #define MAX_255(c) ((c) <= 255u) #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) @@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #ifndef EBCDIC #define HSPACE_LIST \ - CHAR_HT, CHAR_SPACE, 0xa0, \ + CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \ NOTACHAR @@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ - case 0xa0 /* NBSP */ + case CHAR_NBSP #define HSPACE_CASES \ HSPACE_BYTE_CASES: \ @@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ /* ------ EBCDIC environments ------ */ #else -#define HSPACE_LIST CHAR_HT, CHAR_SPACE +#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR #define HSPACE_BYTE_CASES \ case CHAR_HT: \ - case CHAR_SPACE + case CHAR_SPACE: \ + case CHAR_NBSP #define HSPACE_CASES HSPACE_BYTE_CASES @@ -1215,6 +1216,7 @@ same code point. */ #define CHAR_ESC '\047' #define CHAR_DEL '\007' +#define CHAR_NBSP '\x41' #define STR_ESC "\047" #define STR_DEL "\007" @@ -1229,6 +1231,7 @@ a positive value. */ #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_ESC '\033' #define CHAR_DEL '\177' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_LF "\n" #define STR_NL STR_LF @@ -1606,6 +1609,7 @@ only. */ #define CHAR_VERTICAL_LINE '\174' #define CHAR_RIGHT_CURLY_BRACKET '\175' #define CHAR_TILDE '\176' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_HT "\011" #define STR_VT "\013" @@ -1762,6 +1766,10 @@ only. */ /* Escape items that are just an encoding of a particular data value. */ +#ifndef ESC_a +#define ESC_a CHAR_BEL +#endif + #ifndef ESC_e #define ESC_e CHAR_ESC #endif @@ -2281,7 +2289,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, - ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERRCOUNT }; + ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT }; /* JIT compiling modes. The function list is indexed by them. */ @@ -2446,6 +2454,8 @@ typedef struct compile_data { BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL check_lookbehind; /* Lookbehinds need later checking */ BOOL dupnames; /* Duplicate names exist */ + BOOL dupgroups; /* Duplicate groups exist: (?| found */ + BOOL iscondassert; /* Next assert is a condition */ int nltype; /* Newline type */ int nllen; /* Newline string length */ pcre_uchar nl[4]; /* Newline string when fixed length */ @@ -2459,6 +2469,13 @@ typedef struct branch_chain { pcre_uchar *current_branch; } branch_chain; +/* Structure for mutual recursion detection. */ + +typedef struct recurse_check { + struct recurse_check *prev; + const pcre_uchar *group; +} recurse_check; + /* Structure for items in a linked list that represents an explicit recursive call within the pattern; used by pcre_exec(). */ diff --git a/Foundation/src/pcre_jit_compile.c b/Foundation/src/pcre_jit_compile.c index 1db5516bc..691a4fea8 100644 --- a/Foundation/src/pcre_jit_compile.c +++ b/Foundation/src/pcre_jit_compile.c @@ -49,8 +49,8 @@ POSSIBILITY OF SUCH DAMAGE. we just include it. This way we don't need to touch the build system files. */ -#define SLJIT_MALLOC(size) (PUBL(malloc))(size) -#define SLJIT_FREE(ptr) (PUBL(free))(ptr) +#define SLJIT_MALLOC(size, allocator_data) (PUBL(malloc))(size) +#define SLJIT_FREE(ptr, allocator_data) (PUBL(free))(ptr) #define SLJIT_CONFIG_AUTO 1 #define SLJIT_CONFIG_STATIC 1 #define SLJIT_VERBOSE 0 @@ -165,23 +165,23 @@ typedef struct jit_arguments { pcre_uchar *mark_ptr; void *callout_data; /* Everything else after. */ - pcre_uint32 limit_match; + sljit_u32 limit_match; int real_offset_count; int offset_count; - pcre_uint8 notbol; - pcre_uint8 noteol; - pcre_uint8 notempty; - pcre_uint8 notempty_atstart; + sljit_u8 notbol; + sljit_u8 noteol; + sljit_u8 notempty; + sljit_u8 notempty_atstart; } jit_arguments; typedef struct executable_functions { void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; - sljit_uw *read_only_data[JIT_NUMBER_OF_COMPILE_MODES]; + void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES]; sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; PUBL(jit_callback) callback; void *userdata; - pcre_uint32 top_bracket; - pcre_uint32 limit_match; + sljit_u32 top_bracket; + sljit_u32 limit_match; } executable_functions; typedef struct jump_list { @@ -197,7 +197,7 @@ typedef struct stub_list { typedef struct label_addr_list { struct sljit_label *label; - sljit_uw *addr; + sljit_uw *update_addr; struct label_addr_list *next; } label_addr_list; @@ -274,11 +274,25 @@ typedef struct braminzero_backtrack { struct sljit_label *matchingpath; } braminzero_backtrack; -typedef struct iterator_backtrack { +typedef struct char_iterator_backtrack { backtrack_common common; /* Next iteration. */ struct sljit_label *matchingpath; -} iterator_backtrack; + union { + jump_list *backtracks; + struct { + unsigned int othercasebit; + pcre_uchar chr; + BOOL enabled; + } charpos; + } u; +} char_iterator_backtrack; + +typedef struct ref_iterator_backtrack { + backtrack_common common; + /* Next iteration. */ + struct sljit_label *matchingpath; +} ref_iterator_backtrack; typedef struct recurse_entry { struct recurse_entry *next; @@ -318,44 +332,46 @@ typedef struct compiler_common { /* First byte code. */ pcre_uchar *start; /* Maps private data offset to each opcode. */ - sljit_si *private_data_ptrs; - /* This read-only data is available during runtime. */ - sljit_uw *read_only_data; - /* The total size of the read-only data. */ - sljit_uw read_only_data_size; - /* The next free entry of the read_only_data. */ - sljit_uw *read_only_data_ptr; + sljit_s32 *private_data_ptrs; + /* Chain list of read-only data ptrs. */ + void *read_only_data_head; /* Tells whether the capturing bracket is optimized. */ - pcre_uint8 *optimized_cbracket; + sljit_u8 *optimized_cbracket; /* Tells whether the starting offset is a target of then. */ - pcre_uint8 *then_offsets; + sljit_u8 *then_offsets; /* Current position where a THEN must jump. */ then_trap_backtrack *then_trap; /* Starting offset of private data for capturing brackets. */ - int cbra_ptr; + sljit_s32 cbra_ptr; /* Output vector starting point. Must be divisible by 2. */ - int ovector_start; + sljit_s32 ovector_start; + /* Points to the starting character of the current match. */ + sljit_s32 start_ptr; /* Last known position of the requested byte. */ - int req_char_ptr; + sljit_s32 req_char_ptr; /* Head of the last recursion. */ - int recursive_head_ptr; - /* First inspected character for partial matching. */ - int start_used_ptr; + sljit_s32 recursive_head_ptr; + /* First inspected character for partial matching. + (Needed for avoiding zero length partial matches.) */ + sljit_s32 start_used_ptr; /* Starting pointer for partial soft matches. */ - int hit_start; - /* End pointer of the first line. */ - int first_line_end; + sljit_s32 hit_start; + /* Pointer of the match end position. */ + sljit_s32 match_end_ptr; /* Points to the marked string. */ - int mark_ptr; + sljit_s32 mark_ptr; /* Recursive control verb management chain. */ - int control_head_ptr; + sljit_s32 control_head_ptr; /* Points to the last matched capture block index. */ - int capture_last_ptr; - /* Points to the starting position of the current match. */ - int start_ptr; + sljit_s32 capture_last_ptr; + /* Fast forward skipping byte code pointer. */ + pcre_uchar *fast_forward_bc_ptr; + /* Locals used by fast fail optimization. */ + sljit_s32 fast_fail_start_ptr; + sljit_s32 fast_fail_end_ptr; /* Flipped and lower case tables. */ - const pcre_uint8 *fcc; + const sljit_u8 *fcc; sljit_sw lcc; /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ int mode; @@ -367,20 +383,20 @@ typedef struct compiler_common { BOOL has_skip_arg; /* (*THEN) is found in the pattern. */ BOOL has_then; - /* Needs to know the start position anytime. */ - BOOL needs_start_ptr; + /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */ + BOOL has_skip_in_assert_back; /* Currently in recurse or negative assert. */ BOOL local_exit; /* Currently in a positive assert. */ BOOL positive_assert; /* Newline control. */ int nltype; - pcre_uint32 nlmax; - pcre_uint32 nlmin; + sljit_u32 nlmax; + sljit_u32 nlmin; int newline; int bsr_nltype; - pcre_uint32 bsr_nlmax; - pcre_uint32 bsr_nlmin; + sljit_u32 bsr_nlmax; + sljit_u32 bsr_nlmin; /* Dollar endonly. */ int endonly; /* Tables. */ @@ -420,6 +436,7 @@ typedef struct compiler_common { BOOL utf; #ifdef SUPPORT_UCP BOOL use_ucp; + jump_list *getucd; #endif #ifdef COMPILE_PCRE8 jump_list *utfreadchar; @@ -427,9 +444,6 @@ typedef struct compiler_common { jump_list *utfreadtype8; #endif #endif /* SUPPORT_UTF */ -#ifdef SUPPORT_UCP - jump_list *getucd; -#endif } compiler_common; /* For byte_sequence_compare. */ @@ -440,27 +454,27 @@ typedef struct compare_context { #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED int ucharptr; union { - sljit_si asint; - sljit_uh asushort; + sljit_s32 asint; + sljit_u16 asushort; #if defined COMPILE_PCRE8 - sljit_ub asbyte; - sljit_ub asuchars[4]; + sljit_u8 asbyte; + sljit_u8 asuchars[4]; #elif defined COMPILE_PCRE16 - sljit_uh asuchars[2]; + sljit_u16 asuchars[2]; #elif defined COMPILE_PCRE32 - sljit_ui asuchars[1]; + sljit_u32 asuchars[1]; #endif } c; union { - sljit_si asint; - sljit_uh asushort; + sljit_s32 asint; + sljit_u16 asushort; #if defined COMPILE_PCRE8 - sljit_ub asbyte; - sljit_ub asuchars[4]; + sljit_u8 asbyte; + sljit_u8 asuchars[4]; #elif defined COMPILE_PCRE16 - sljit_uh asuchars[2]; + sljit_u16 asuchars[2]; #elif defined COMPILE_PCRE32 - sljit_ui asuchars[1]; + sljit_u32 asuchars[1]; #endif } oc; #endif @@ -472,16 +486,16 @@ typedef struct compare_context { /* Used for accessing the elements of the stack. */ #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) -#define TMP1 SLJIT_SCRATCH_REG1 -#define TMP2 SLJIT_SCRATCH_REG3 -#define TMP3 SLJIT_TEMPORARY_EREG2 -#define STR_PTR SLJIT_SAVED_REG1 -#define STR_END SLJIT_SAVED_REG2 -#define STACK_TOP SLJIT_SCRATCH_REG2 -#define STACK_LIMIT SLJIT_SAVED_REG3 -#define ARGUMENTS SLJIT_SAVED_EREG1 -#define COUNT_MATCH SLJIT_SAVED_EREG2 -#define RETURN_ADDR SLJIT_TEMPORARY_EREG1 +#define TMP1 SLJIT_R0 +#define TMP2 SLJIT_R2 +#define TMP3 SLJIT_R3 +#define STR_PTR SLJIT_S0 +#define STR_END SLJIT_S1 +#define STACK_TOP SLJIT_R1 +#define STACK_LIMIT SLJIT_S2 +#define COUNT_MATCH SLJIT_S3 +#define ARGUMENTS SLJIT_S4 +#define RETURN_ADDR SLJIT_R4 /* Local space layout. */ /* These two locals can be used by the current opcode. */ @@ -502,14 +516,14 @@ the start pointers when the end of the capturing group has not yet reached. */ #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) #if defined COMPILE_PCRE8 -#define MOV_UCHAR SLJIT_MOV_UB -#define MOVU_UCHAR SLJIT_MOVU_UB +#define MOV_UCHAR SLJIT_MOV_U8 +#define MOVU_UCHAR SLJIT_MOVU_U8 #elif defined COMPILE_PCRE16 -#define MOV_UCHAR SLJIT_MOV_UH -#define MOVU_UCHAR SLJIT_MOVU_UH +#define MOV_UCHAR SLJIT_MOV_U16 +#define MOVU_UCHAR SLJIT_MOVU_U16 #elif defined COMPILE_PCRE32 -#define MOV_UCHAR SLJIT_MOV_UI -#define MOVU_UCHAR SLJIT_MOVU_UI +#define MOV_UCHAR SLJIT_MOV_U32 +#define MOVU_UCHAR SLJIT_MOVU_U32 #else #error Unsupported compiling mode #endif @@ -542,7 +556,7 @@ the start pointers when the end of the capturing group has not yet reached. */ #define READ_CHAR_MAX 0x7fffffff -static pcre_uchar* bracketend(pcre_uchar* cc) +static pcre_uchar *bracketend(pcre_uchar *cc) { SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -551,7 +565,7 @@ cc += 1 + LINK_SIZE; return cc; } -static int no_alternatives(pcre_uchar* cc) +static int no_alternatives(pcre_uchar *cc) { int count = 0; SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); @@ -565,11 +579,6 @@ SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); return count; } -static int ones_in_half_byte[16] = { - /* 0 */ 0, 1, 1, 2, /* 4 */ 1, 2, 2, 3, - /* 8 */ 1, 2, 2, 3, /* 12 */ 2, 3, 3, 4 -}; - /* Functions whose might need modification for all new supported opcodes: next_opcode check_opcode_types @@ -781,6 +790,7 @@ static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uch { int count; pcre_uchar *slot; +pcre_uchar *assert_back_end = cc - 1; /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ while (cc < ccend) @@ -799,16 +809,6 @@ while (cc < ccend) cc += 1 + IMM2_SIZE; break; - case OP_BRA: - case OP_CBRA: - case OP_SBRA: - case OP_SCBRA: - count = no_alternatives(cc); - if (count > 4) - common->read_only_data_size += count * sizeof(sljit_uw); - cc += 1 + LINK_SIZE + (*cc == OP_CBRA || *cc == OP_SCBRA ? IMM2_SIZE : 0); - break; - case OP_CBRAPOS: case OP_SCBRAPOS: common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; @@ -861,15 +861,19 @@ while (cc < ccend) cc += 2 + 2 * LINK_SIZE; break; + case OP_ASSERTBACK: + slot = bracketend(cc); + if (slot > assert_back_end) + assert_back_end = slot; + cc += 1 + LINK_SIZE; + break; + case OP_THEN_ARG: common->has_then = TRUE; common->control_head_ptr = 1; /* Fall through. */ case OP_PRUNE_ARG: - common->needs_start_ptr = TRUE; - /* Fall through. */ - case OP_MARK: if (common->mark_ptr == 0) { @@ -882,17 +886,20 @@ while (cc < ccend) case OP_THEN: common->has_then = TRUE; common->control_head_ptr = 1; - /* Fall through. */ + cc += 1; + break; - case OP_PRUNE: case OP_SKIP: - common->needs_start_ptr = TRUE; + if (cc < assert_back_end) + common->has_skip_in_assert_back = TRUE; cc += 1; break; case OP_SKIP_ARG: common->control_head_ptr = 1; common->has_skip_arg = TRUE; + if (cc < assert_back_end) + common->has_skip_in_assert_back = TRUE; cc += 1 + 2 + cc[1]; break; @@ -906,8 +913,189 @@ while (cc < ccend) return TRUE; } +static BOOL is_accelerated_repeat(pcre_uchar *cc) +{ +switch(*cc) + { + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI); + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSSTAR: + case OP_POSPLUS: + + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_POSSTARI: + case OP_POSPLUSI: + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + return TRUE; + + case OP_CLASS: + case OP_NCLASS: +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: + cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar))); +#else + cc += (1 + (32 / sizeof(pcre_uchar))); +#endif + + switch(*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRPOSSTAR: + case OP_CRPOSPLUS: + return TRUE; + } + break; + } +return FALSE; +} + +static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start) +{ +pcre_uchar *cc = common->start; +pcre_uchar *end; + +/* Skip not repeated brackets. */ +while (TRUE) + { + switch(*cc) + { + case OP_SOD: + case OP_SOM: + case OP_SET_SOM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_EODN: + case OP_EOD: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + /* Zero width assertions. */ + cc++; + continue; + } + + if (*cc != OP_BRA && *cc != OP_CBRA) + break; + + end = cc + GET(cc, 1); + if (*end != OP_KET || PRIVATE_DATA(end) != 0) + return FALSE; + if (*cc == OP_CBRA) + { + if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + return FALSE; + cc += IMM2_SIZE; + } + cc += 1 + LINK_SIZE; + } + +if (is_accelerated_repeat(cc)) + { + common->fast_forward_bc_ptr = cc; + common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; + *private_data_start += sizeof(sljit_sw); + return TRUE; + } +return FALSE; +} + +static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth) +{ + pcre_uchar *next_alt; + + SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA); + + if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + return; + + next_alt = bracketend(cc) - (1 + LINK_SIZE); + if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0) + return; + + do + { + next_alt = cc + GET(cc, 1); + + cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0); + + while (TRUE) + { + switch(*cc) + { + case OP_SOD: + case OP_SOM: + case OP_SET_SOM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_EODN: + case OP_EOD: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + /* Zero width assertions. */ + cc++; + continue; + } + break; + } + + if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA)) + detect_fast_fail(common, cc, private_data_start, depth - 1); + + if (is_accelerated_repeat(cc)) + { + common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; + + if (common->fast_fail_start_ptr == 0) + common->fast_fail_start_ptr = *private_data_start; + + *private_data_start += sizeof(sljit_sw); + common->fast_fail_end_ptr = *private_data_start; + + if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) + return; + } + + cc = next_alt; + } + while (*cc == OP_ALT); +} + static int get_class_iterator_size(pcre_uchar *cc) { +sljit_u32 min; +sljit_u32 max; switch(*cc) { case OP_CRSTAR: @@ -922,9 +1110,14 @@ switch(*cc) case OP_CRRANGE: case OP_CRMINRANGE: - if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE)) - return 0; - return 2; + min = GET2(cc, 1); + max = GET2(cc, 1 + IMM2_SIZE); + if (max == 0) + return (*cc == OP_CRRANGE) ? 2 : 1; + max -= min; + if (max > 2) + max = 2; + return max; default: return 0; @@ -1075,6 +1268,7 @@ pcre_uchar *alternative; pcre_uchar *end = NULL; int private_data_ptr = *private_data_start; int space, size, bracketlen; +BOOL repeat_check = TRUE; while (cc < ccend) { @@ -1082,9 +1276,10 @@ while (cc < ccend) size = 0; bracketlen = 0; if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) - return; + break; - if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND) + if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) + { if (detect_repeat(common, cc)) { /* These brackets are converted to repeats, so no global @@ -1092,6 +1287,8 @@ while (cc < ccend) if (cc >= end) end = bracketend(cc); } + } + repeat_check = TRUE; switch(*cc) { @@ -1147,6 +1344,13 @@ while (cc < ccend) bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + repeat_check = FALSE; + size = 1; + break; + CASE_ITERATOR_PRIVATE_DATA_1 space = 1; size = -2; @@ -1173,22 +1377,27 @@ while (cc < ccend) size = 1; break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2B + case OP_TYPEUPTO: if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; size = 1 + IMM2_SIZE; break; + case OP_TYPEMINUPTO: + space = 2; + size = 1 + IMM2_SIZE; + break; + case OP_CLASS: case OP_NCLASS: - size += 1 + 32 / sizeof(pcre_uchar); space = get_class_iterator_size(cc + size); + size = 1 + 32 / sizeof(pcre_uchar); break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: - size = GET(cc, 1); space = get_class_iterator_size(cc + size); + size = GET(cc, 1); break; #endif @@ -1234,7 +1443,7 @@ while (cc < ccend) } /* Returns with a frame_types (always < 0) if no need for frame. */ -static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL* needs_control_head) +static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL *needs_control_head) { int length = 0; int possessive = 0; @@ -1327,6 +1536,13 @@ while (cc < ccend) cc += 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_THEN: + stack_restore = TRUE; + if (common->control_head_ptr != 0) + *needs_control_head = TRUE; + cc ++; + break; + default: stack_restore = TRUE; /* Fall through. */ @@ -1394,6 +1610,7 @@ while (cc < ccend) case OP_CLASS: case OP_NCLASS: case OP_XCLASS: + case OP_CALLOUT: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); @@ -1438,7 +1655,7 @@ while (cc < ccend) SLJIT_ASSERT(common->has_set_som); if (!setsom_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1454,7 +1671,7 @@ while (cc < ccend) SLJIT_ASSERT(common->mark_ptr != 0); if (!setmark_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1467,7 +1684,7 @@ while (cc < ccend) case OP_RECURSE: if (common->has_set_som && !setsom_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1476,7 +1693,7 @@ while (cc < ccend) } if (common->mark_ptr != 0 && !setmark_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1485,7 +1702,7 @@ while (cc < ccend) } if (common->capture_last_ptr != 0 && !capture_last_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1501,7 +1718,7 @@ while (cc < ccend) case OP_SCBRAPOS: if (common->capture_last_ptr != 0 && !capture_last_found) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); @@ -1511,8 +1728,8 @@ while (cc < ccend) offset = (GET2(cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); stackpos += (int)sizeof(sljit_sw); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos += (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); @@ -1544,7 +1761,11 @@ while (cc < ccend) { case OP_KET: if (PRIVATE_DATA(cc) != 0) + { private_data_length++; + SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); + cc += PRIVATE_DATA(cc + 1); + } cc += 1 + LINK_SIZE; break; @@ -1559,6 +1780,7 @@ while (cc < ccend) case OP_SBRAPOS: case OP_SCOND: private_data_length++; + SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); cc += 1 + LINK_SIZE; break; @@ -1721,6 +1943,8 @@ do { count = 1; srcw[0] = PRIVATE_DATA(cc); + SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); + cc += PRIVATE_DATA(cc + 1); } cc += 1 + LINK_SIZE; break; @@ -1892,7 +2116,7 @@ do OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); stackptr += sizeof(sljit_sw); } - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); tmp1empty = FALSE; tmp1next = FALSE; } @@ -1903,7 +2127,7 @@ do OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); stackptr += sizeof(sljit_sw); } - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); tmp2empty = FALSE; tmp1next = TRUE; } @@ -1913,7 +2137,7 @@ do if (tmp1next) { SLJIT_ASSERT(!tmp1empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP1, 0); tmp1empty = stackptr >= stacktop; if (!tmp1empty) { @@ -1925,7 +2149,7 @@ do else { SLJIT_ASSERT(!tmp2empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP2, 0); tmp2empty = stackptr >= stacktop; if (!tmp2empty) { @@ -1971,7 +2195,7 @@ if (save) SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); } -static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, pcre_uint8 *current_offset) +static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, sljit_u8 *current_offset) { pcre_uchar *end = bracketend(cc); BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; @@ -2027,7 +2251,7 @@ while (list) } } -static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump) +static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump) { jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); if (list_item) @@ -2041,7 +2265,7 @@ if (list_item) static void add_stub(compiler_common *common, struct sljit_jump *start) { DEFINE_COMPILER; -stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); +stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); if (list_item) { @@ -2055,7 +2279,7 @@ if (list_item) static void flush_stubs(compiler_common *common) { DEFINE_COMPILER; -stub_list* list_item = common->stubs; +stub_list *list_item = common->stubs; while (list_item) { @@ -2067,7 +2291,7 @@ while (list_item) common->stubs = NULL; } -static void add_label_addr(compiler_common *common) +static void add_label_addr(compiler_common *common, sljit_uw *update_addr) { DEFINE_COMPILER; label_addr_list *label_addr; @@ -2076,10 +2300,9 @@ label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list)); if (label_addr == NULL) return; label_addr->label = LABEL(); -label_addr->addr = common->read_only_data_ptr; +label_addr->update_addr = update_addr; label_addr->next = common->label_addrs; common->label_addrs = label_addr; -common->read_only_data_ptr++; } static SLJIT_INLINE void count_match(compiler_common *common) @@ -2087,7 +2310,7 @@ static SLJIT_INLINE void count_match(compiler_common *common) DEFINE_COMPILER; OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); -add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO)); +add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO)); } static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) @@ -2095,23 +2318,60 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) /* May destroy all locals and registers except TMP2. */ DEFINE_COMPILER; +SLJIT_ASSERT(size > 0); OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); #ifdef DESTROY_REGISTERS OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #endif -add_stub(common, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); +add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); } static SLJIT_INLINE void free_stack(compiler_common *common, int size) { DEFINE_COMPILER; + +SLJIT_ASSERT(size > 0); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); } +static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) +{ +DEFINE_COMPILER; +sljit_uw *result; + +if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + +result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data); +if (SLJIT_UNLIKELY(result == NULL)) + { + sljit_set_compiler_memory_error(compiler); + return NULL; + } + +*(void**)result = common->read_only_data_head; +common->read_only_data_head = (void *)result; +return result + 1; +} + +static void free_read_only_data(void *current, void *allocator_data) +{ +void *next; + +SLJIT_UNUSED_ARG(allocator_data); + +while (current != NULL) + { + next = *(void**)current; + SLJIT_FREE(current, allocator_data); + current = next; + } +} + static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) { DEFINE_COMPILER; @@ -2121,23 +2381,35 @@ int i; /* At this point we can freely use all temporary registers. */ SLJIT_ASSERT(length > 1); /* TMP1 returns with begin - 1. */ -OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); if (length < 8) { for (i = 1; i < length; i++) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0); } else { - GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START); - OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length - 1); + GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, loop); + OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, loop); } } +static SLJIT_INLINE void reset_fast_fail(compiler_common *common) +{ +DEFINE_COMPILER; +sljit_s32 i; + +SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr); + +OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw)) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0); +} + static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) { DEFINE_COMPILER; @@ -2147,11 +2419,11 @@ int i; SLJIT_ASSERT(length > 1); /* OVECTOR(1) contains the "string begin - 1" constant. */ if (length > 2) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); if (length < 8) { for (i = 2; i < length; i++) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0); } else { @@ -2160,16 +2432,16 @@ else loop = LABEL(); OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, loop); + JUMPTO(SLJIT_NOT_ZERO, loop); } OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0); if (common->control_head_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); } @@ -2191,6 +2463,7 @@ while (current != NULL) SLJIT_ASSERT_STOP(); break; } + SLJIT_ASSERT(current > (sljit_sw*)current[-1]); current = (sljit_sw*)current[-1]; } return -1; @@ -2203,44 +2476,44 @@ struct sljit_label *loop; struct sljit_jump *early_quit; /* At this point we can freely use all registers. */ -OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0); -OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); -OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offset_count)); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); +OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count)); if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_SCRATCH_REG3, 0); -OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); -OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); -GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0); +OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); +OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin)); +GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START); /* Unlikely, but possible */ -early_quit = CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 0); +early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0); loop = LABEL(); -OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_SCRATCH_REG1, 0); -OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)); +OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); +OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); /* Copy the integer value to the output buffer */ #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 -OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); +OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif -OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); -JUMPTO(SLJIT_C_NOT_ZERO, loop); +OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); +JUMPTO(SLJIT_NOT_ZERO, loop); JUMPHERE(early_quit); /* Calculate the return value, which is the maximum ovector value. */ if (topbracket > 1) { - GET_LOCAL_BASE(SLJIT_SCRATCH_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, topbracket + 1); + GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); - /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ + /* OVECTOR(0) is never equal to SLJIT_S2. */ loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), -(2 * (sljit_sw)sizeof(sljit_sw))); - OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); - CMPTO(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG3, 0, loop); - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_SCRATCH_REG2, 0); + OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); + OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); + CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); } else OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); @@ -2251,39 +2524,39 @@ static SLJIT_INLINE void return_with_partial_match(compiler_common *common, stru DEFINE_COMPILER; struct sljit_jump *jump; -SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); +SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2); SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); -OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); -OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); -CMPTO(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 2, quit); +OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); +CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit); /* Store match begin and end. */ -OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); -OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); +OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin)); +OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, offsets)); -jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3); -OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_SAVED_REG1, 0); +jump = CMP(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 3); +OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 -OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); +OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif -OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 2 * sizeof(int), SLJIT_SCRATCH_REG3, 0); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0); JUMPHERE(jump); -OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); -OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); +OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); +OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 -OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); +OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif -OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0); -OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG1, 0); +OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 -OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); +OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif -OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 0, SLJIT_SCRATCH_REG3, 0); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0); JUMPTO(SLJIT_JUMP, quit); } @@ -2297,22 +2570,22 @@ struct sljit_jump *jump; if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { /* The value of -1 must be kept for start_used_ptr! */ - OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1); + OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1); /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ - jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); + jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); JUMPHERE(jump); } else if (common->mode == JIT_PARTIAL_HARD_COMPILE) { - jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); + jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); JUMPHERE(jump); } } -static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) +static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar *cc) { /* Detects if the character has an othercase. */ unsigned int c; @@ -2355,7 +2628,7 @@ if (common->utf && c > 127) return TABLE_GET(c, common->fcc, c); } -static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc) +static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar *cc) { /* Detects if the character and its othercase has only 1 bit difference. */ unsigned int c, oc, bit; @@ -2443,12 +2716,12 @@ if (common->mode == JIT_COMPILE) return; if (!force) - jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); + jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); + jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); else { if (common->partialmatchlabel != NULL) @@ -2469,20 +2742,20 @@ struct sljit_jump *jump; if (common->mode == JIT_COMPILE) { - add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); return; } -jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); +jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { - add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); + add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); } else { - add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); + add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); if (common->partialmatchlabel != NULL) JUMPTO(SLJIT_JUMP, common->partialmatchlabel); else @@ -2498,16 +2771,16 @@ struct sljit_jump *jump; if (common->mode == JIT_COMPILE) { - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); return; } /* Partial matching mode. */ -jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); -add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); +jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); +add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); } else @@ -2520,7 +2793,7 @@ else JUMPHERE(jump); } -static void peek_char(compiler_common *common, pcre_uint32 max) +static void peek_char(compiler_common *common, sljit_u32 max) { /* Reads the character into TMP1, keeps STR_PTR. Does not check STR_END. TMP2 Destroyed. */ @@ -2537,7 +2810,7 @@ if (common->utf) { if (max < 128) return; - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); @@ -2551,7 +2824,7 @@ if (common->utf) if (max < 0xd800) return; OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); - jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); + jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); /* TMP2 contains the high surrogate. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); @@ -2565,12 +2838,12 @@ if (common->utf) #if defined SUPPORT_UTF && defined COMPILE_PCRE8 -static BOOL is_char7_bitset(const pcre_uint8 *bitset, BOOL nclass) +static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass) { /* Tells whether the character codes below 128 are enough to determine a match. */ -const pcre_uint8 value = nclass ? 0xff : 0; -const pcre_uint8* end = bitset + 32; +const sljit_u8 value = nclass ? 0xff : 0; +const sljit_u8 *end = bitset + 32; bitset += 16; do @@ -2595,12 +2868,12 @@ SLJIT_ASSERT(common->utf); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); if (full_read) { - jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); + jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); JUMPHERE(jump); } @@ -2608,7 +2881,7 @@ if (full_read) #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ -static void read_char_range(compiler_common *common, pcre_uint32 min, pcre_uint32 max, BOOL update_str_ptr) +static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr) { /* Reads the precise value of a character into TMP1, if the character is between min and max (c >= min && c <= max). Otherwise it returns with a value @@ -2634,14 +2907,14 @@ if (common->utf) { if (max < 128 && !update_str_ptr) return; - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); if (min >= 0x10000) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0); if (update_str_ptr) - OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0x7); + jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -2663,9 +2936,9 @@ if (common->utf) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0); if (update_str_ptr) - OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xf); + jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -2683,7 +2956,7 @@ if (common->utf) add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); else if (max < 128) { - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); } else @@ -2692,7 +2965,7 @@ if (common->utf) if (!update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); else - OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); @@ -2710,7 +2983,7 @@ if (common->utf) if (max >= 0x10000) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); - jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); + jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); /* TMP2 contains the high surrogate. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); @@ -2726,7 +2999,7 @@ if (common->utf) /* Skip low surrogate if necessary. */ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); - jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); + jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); if (update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); if (max >= 0xd800) @@ -2762,8 +3035,8 @@ if (common->utf) { /* This can be an extra read in some situations, but hopefully it is needed in most cases. */ - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); - jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); + jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); if (!update_str_ptr) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); @@ -2773,8 +3046,8 @@ if (common->utf) OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); - jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); + jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); JUMPHERE(jump2); } else @@ -2787,9 +3060,9 @@ if (common->utf) #if !defined COMPILE_PCRE8 /* The ctypes array contains only 256 values. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); +jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); #endif -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); #if !defined COMPILE_PCRE8 JUMPHERE(jump); #endif @@ -2799,7 +3072,7 @@ if (common->utf && update_str_ptr) { /* Skip low surrogate if necessary. */ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800); - jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); + jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPHERE(jump); } @@ -2820,7 +3093,7 @@ if (common->utf) OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); - CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); return; } #elif defined COMPILE_PCRE16 @@ -2831,7 +3104,7 @@ if (common->utf) /* Skip low surrogate if necessary. */ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); return; @@ -2850,26 +3123,26 @@ struct sljit_jump *jump; if (nltype == NLTYPE_ANY) { add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO)); } else if (nltype == NLTYPE_ANYCRLF) { if (jumpifmatch) { - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR)); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); } else { - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); + jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); JUMPHERE(jump); } } else { SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); - add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); + add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); } } @@ -2892,7 +3165,7 @@ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); -jump = JUMP(SLJIT_C_NOT_ZERO); +jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); @@ -2906,7 +3179,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000); -jump = JUMP(SLJIT_C_NOT_ZERO); +jump = JUMP(SLJIT_NOT_ZERO); /* Three byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); @@ -2940,14 +3213,14 @@ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); -jump = JUMP(SLJIT_C_NOT_ZERO); +jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_NOT_ZERO); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_NOT_ZERO); /* This code runs only in 8 bit mode. No need to shift the value. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); @@ -2971,17 +3244,17 @@ struct sljit_jump *compare; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); -jump = JUMP(SLJIT_C_NOT_ZERO); +jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); /* The upper 5 bits are known at this point. */ -compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0x3); +compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(compare); @@ -2990,7 +3263,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0); /* We only have types for characters less than 256. */ JUMPHERE(jump); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); +OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); @@ -3016,26 +3289,26 @@ SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); +OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); -OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); +OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } #endif -static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline) +static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf) { DEFINE_COMPILER; struct sljit_label *mainloop; struct sljit_label *newlinelabel = NULL; struct sljit_jump *start; struct sljit_jump *end = NULL; -struct sljit_jump *nl = NULL; +struct sljit_jump *end2 = NULL; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 struct sljit_jump *singlechar; #endif @@ -3043,39 +3316,38 @@ jump_list *newline = NULL; BOOL newlinecheck = FALSE; BOOL readuchar = FALSE; -if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || - common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) +if (!(hascrorlf || (common->match_end_ptr != 0)) && + (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) newlinecheck = TRUE; -if (firstline) +if (common->match_end_ptr != 0) { /* Search for the end of the first line. */ - SLJIT_ASSERT(common->first_line_end != 0); OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { mainloop = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); JUMPHERE(end); - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else { - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); mainloop = LABEL(); /* Continual stores does not cause data dependency. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); read_char_range(common, common->nlmin, common->nlmax, TRUE); check_newlinechar(common, common->nltype, &newline, TRUE); - CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); + CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop); JUMPHERE(end); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); set_jumps(newline, LABEL()); } @@ -3088,15 +3360,15 @@ if (newlinecheck) { newlinelabel = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - nl = JUMP(SLJIT_JUMP); + end2 = JUMP(SLJIT_JUMP); } mainloop = LABEL(); @@ -3111,25 +3383,25 @@ if (readuchar) OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); if (newlinecheck) - CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 #if defined COMPILE_PCRE8 if (common->utf) { - singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(singlechar); } #elif defined COMPILE_PCRE16 if (common->utf) { - singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); + singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(singlechar); @@ -3141,51 +3413,52 @@ JUMPHERE(start); if (newlinecheck) { JUMPHERE(end); - JUMPHERE(nl); + JUMPHERE(end2); } return mainloop; } #define MAX_N_CHARS 16 -#define MAX_N_BYTES 8 +#define MAX_DIFF_CHARS 6 -static SLJIT_INLINE void add_prefix_byte(pcre_uint8 byte, pcre_uint8 *bytes) +static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars) { -pcre_uint8 len = bytes[0]; -int i; +pcre_uchar i, len; +len = chars[0]; if (len == 255) return; if (len == 0) { - bytes[0] = 1; - bytes[1] = byte; + chars[0] = 1; + chars[1] = chr; return; } for (i = len; i > 0; i--) - if (bytes[i] == byte) + if (chars[i] == chr) return; -if (len >= MAX_N_BYTES - 1) +if (len >= MAX_DIFF_CHARS - 1) { - bytes[0] = 255; + chars[0] = 255; return; } len++; -bytes[len] = byte; -bytes[0] = len; +chars[len] = chr; +chars[0] = len; } -static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars) +static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, sljit_u32 *rec_count) { /* Recursive function, which scans prefix literals. */ -BOOL last, any, caseless; +BOOL last, any, class, caseless; int len, repeat, len_save, consumed = 0; -pcre_uint32 chr, mask; +sljit_u32 chr; /* Any unicode character. */ +sljit_u8 *bytes, *bytes_end, byte; pcre_uchar *alternative, *cc_save, *oc; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 pcre_uchar othercase[8]; @@ -3198,9 +3471,15 @@ pcre_uchar othercase[1]; repeat = 1; while (TRUE) { + if (*rec_count == 0) + return 0; + (*rec_count)--; + last = TRUE; any = FALSE; + class = FALSE; caseless = FALSE; + switch (*cc) { case OP_CHARI: @@ -3262,7 +3541,7 @@ while (TRUE) #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif - max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars); + max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count); if (max_chars == 0) return consumed; last = FALSE; @@ -3285,7 +3564,7 @@ while (TRUE) alternative = cc + GET(cc, 1); while (*alternative == OP_ALT) { - max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars); + max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count); if (max_chars == 0) return consumed; alternative += GET(alternative, 1); @@ -3298,18 +3577,17 @@ while (TRUE) case OP_CLASS: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && !is_char7_bitset((const pcre_uint8 *)(cc + 1), FALSE)) return consumed; + if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE)) + return consumed; #endif - any = TRUE; - cc += 1 + 32 / sizeof(pcre_uchar); + class = TRUE; break; case OP_NCLASS: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) return consumed; #endif - any = TRUE; - cc += 1 + 32 / sizeof(pcre_uchar); + class = TRUE; break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 @@ -3324,7 +3602,7 @@ while (TRUE) case OP_DIGIT: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) + if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) return consumed; #endif any = TRUE; @@ -3333,7 +3611,7 @@ while (TRUE) case OP_WHITESPACE: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_space, FALSE)) + if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) return consumed; #endif any = TRUE; @@ -3342,7 +3620,7 @@ while (TRUE) case OP_WORDCHAR: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_word, FALSE)) + if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) return consumed; #endif any = TRUE; @@ -3365,10 +3643,10 @@ while (TRUE) cc++; break; -#ifdef SUPPORT_UCP +#ifdef SUPPORT_UTF case OP_NOTPROP: case OP_PROP: -#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +#ifndef COMPILE_PCRE32 if (common->utf) return consumed; #endif any = TRUE; @@ -3397,27 +3675,14 @@ while (TRUE) if (any) { -#if defined COMPILE_PCRE8 - mask = 0xff; -#elif defined COMPILE_PCRE16 - mask = 0xffff; -#elif defined COMPILE_PCRE32 - mask = 0xffffffff; -#else - SLJIT_ASSERT_STOP(); -#endif - do { - chars[0] = mask; - chars[1] = mask; - bytes[0] = 255; + chars[0] = 255; consumed++; if (--max_chars == 0) return consumed; - chars += 2; - bytes += MAX_N_BYTES; + chars += MAX_DIFF_CHARS; } while (--repeat > 0); @@ -3425,6 +3690,103 @@ while (TRUE) continue; } + if (class) + { + bytes = (sljit_u8*) (cc + 1); + cc += 1 + 32 / sizeof(pcre_uchar); + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPOSSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_CRPOSQUERY: + max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count); + if (max_chars == 0) + return consumed; + break; + + default: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRPOSPLUS: + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + case OP_CRPOSRANGE: + repeat = GET2(cc, 1); + if (repeat <= 0) + return consumed; + break; + } + + do + { + if (bytes[31] & 0x80) + chars[0] = 255; + else if (chars[0] != 255) + { + bytes_end = bytes + 32; + chr = 0; + do + { + byte = *bytes++; + SLJIT_ASSERT((chr & 0x7) == 0); + if (byte == 0) + chr += 8; + else + { + do + { + if ((byte & 0x1) != 0) + add_prefix_char(chr, chars); + byte >>= 1; + chr++; + } + while (byte != 0); + chr = (chr + 7) & ~7; + } + } + while (chars[0] != 255 && bytes < bytes_end); + bytes = bytes_end - 32; + } + + consumed++; + if (--max_chars == 0) + return consumed; + chars += MAX_DIFF_CHARS; + } + while (--repeat > 0); + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPOSSTAR: + return consumed; + + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_CRPOSQUERY: + cc++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + case OP_CRPOSRANGE: + if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE)) + return consumed; + cc += 1 + 2 * IMM2_SIZE; + break; + } + + repeat = 1; + continue; + } + len = 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); @@ -3447,7 +3809,10 @@ while (TRUE) } } else + { caseless = FALSE; + othercase[0] = 0; /* Stops compiler warning - PH */ + } len_save = len; cc_save = cc; @@ -3457,43 +3822,16 @@ while (TRUE) do { chr = *cc; -#ifdef COMPILE_PCRE32 - if (SLJIT_UNLIKELY(chr == NOTACHAR)) - return consumed; -#endif - add_prefix_byte((pcre_uint8)chr, bytes); + add_prefix_char(*cc, chars); - mask = 0; if (caseless) - { - add_prefix_byte((pcre_uint8)*oc, bytes); - mask = *cc ^ *oc; - chr |= mask; - } - -#ifdef COMPILE_PCRE32 - if (chars[0] == NOTACHAR && chars[1] == 0) -#else - if (chars[0] == NOTACHAR) -#endif - { - chars[0] = chr; - chars[1] = mask; - } - else - { - mask |= chars[0] ^ chr; - chr |= mask; - chars[0] = chr; - chars[1] |= mask; - } + add_prefix_char(*oc, chars); len--; consumed++; if (--max_chars == 0) return consumed; - chars += 2; - bytes += MAX_N_BYTES; + chars += MAX_DIFF_CHARS; cc++; oc++; } @@ -3512,248 +3850,669 @@ while (TRUE) } } -static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline) +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + +static sljit_s32 character_to_int32(pcre_uchar chr) +{ +sljit_s32 value = (sljit_s32)chr; +#if defined COMPILE_PCRE8 +#define SSE2_COMPARE_TYPE_INDEX 0 +return (value << 24) | (value << 16) | (value << 8) | value; +#elif defined COMPILE_PCRE16 +#define SSE2_COMPARE_TYPE_INDEX 1 +return (value << 16) | value; +#elif defined COMPILE_PCRE32 +#define SSE2_COMPARE_TYPE_INDEX 2 +return value; +#else +#error "Unsupported unit width" +#endif +} + +static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2) +{ +DEFINE_COMPILER; +struct sljit_label *start; +struct sljit_jump *quit[3]; +struct sljit_jump *nomatch; +sljit_u8 instruction[8]; +sljit_s32 tmp1_ind = sljit_get_register_index(TMP1); +sljit_s32 tmp2_ind = sljit_get_register_index(TMP2); +sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR); +BOOL load_twice = FALSE; +pcre_uchar bit; + +bit = char1 ^ char2; +if (!is_powerof2(bit)) + bit = 0; + +if ((char1 != char2) && bit == 0) + load_twice = TRUE; + +quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + +/* First part (unaligned start) */ + +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); + +SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1); + +/* MOVD xmm, r/m32 */ +instruction[0] = 0x66; +instruction[1] = 0x0f; +instruction[2] = 0x6e; +instruction[3] = 0xc0 | (2 << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +if (char1 != char2) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); + + /* MOVD xmm, r/m32 */ + instruction[3] = 0xc0 | (3 << 3) | tmp1_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + +/* PSHUFD xmm1, xmm2/m128, imm8 */ +instruction[2] = 0x70; +instruction[3] = 0xc0 | (2 << 3) | 2; +instruction[4] = 0; +sljit_emit_op_custom(compiler, instruction, 5); + +if (char1 != char2) + { + /* PSHUFD xmm1, xmm2/m128, imm8 */ + instruction[3] = 0xc0 | (3 << 3) | 3; + instruction[4] = 0; + sljit_emit_op_custom(compiler, instruction, 5); + } + +OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf); +OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); + +/* MOVDQA xmm1, xmm2/m128 */ +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + +if (str_ptr_ind < 8) + { + instruction[2] = 0x6f; + instruction[3] = (0 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + + if (load_twice) + { + instruction[3] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + } +else + { + instruction[1] = 0x41; + instruction[2] = 0x0f; + instruction[3] = 0x6f; + instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); + sljit_emit_op_custom(compiler, instruction, 5); + + if (load_twice) + { + instruction[4] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 5); + } + instruction[1] = 0x0f; + } + +#else + +instruction[2] = 0x6f; +instruction[3] = (0 << 3) | str_ptr_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + instruction[3] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + +#endif + +if (bit != 0) + { + /* POR xmm1, xmm2/m128 */ + instruction[2] = 0xeb; + instruction[3] = 0xc0 | (0 << 3) | 3; + sljit_emit_op_custom(compiler, instruction, 4); + } + +/* PCMPEQB/W/D xmm1, xmm2/m128 */ +instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; +instruction[3] = 0xc0 | (0 << 3) | 2; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + instruction[3] = 0xc0 | (1 << 3) | 3; + sljit_emit_op_custom(compiler, instruction, 4); + } + +/* PMOVMSKB reg, xmm */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0); + instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; + sljit_emit_op_custom(compiler, instruction, 4); + + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); + OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0); + } + +OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0); + +/* BSF r32, r/m32 */ +instruction[0] = 0x0f; +instruction[1] = 0xbc; +instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 3); + +nomatch = JUMP(SLJIT_ZERO); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); +quit[1] = JUMP(SLJIT_JUMP); + +JUMPHERE(nomatch); + +start = LABEL(); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); +quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + +/* Second part (aligned) */ + +instruction[0] = 0x66; +instruction[1] = 0x0f; + +/* MOVDQA xmm1, xmm2/m128 */ +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + +if (str_ptr_ind < 8) + { + instruction[2] = 0x6f; + instruction[3] = (0 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + + if (load_twice) + { + instruction[3] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + } +else + { + instruction[1] = 0x41; + instruction[2] = 0x0f; + instruction[3] = 0x6f; + instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); + sljit_emit_op_custom(compiler, instruction, 5); + + if (load_twice) + { + instruction[4] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 5); + } + instruction[1] = 0x0f; + } + +#else + +instruction[2] = 0x6f; +instruction[3] = (0 << 3) | str_ptr_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + instruction[3] = (1 << 3) | str_ptr_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + +#endif + +if (bit != 0) + { + /* POR xmm1, xmm2/m128 */ + instruction[2] = 0xeb; + instruction[3] = 0xc0 | (0 << 3) | 3; + sljit_emit_op_custom(compiler, instruction, 4); + } + +/* PCMPEQB/W/D xmm1, xmm2/m128 */ +instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; +instruction[3] = 0xc0 | (0 << 3) | 2; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + instruction[3] = 0xc0 | (1 << 3) | 3; + sljit_emit_op_custom(compiler, instruction, 4); + } + +/* PMOVMSKB reg, xmm */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; +sljit_emit_op_custom(compiler, instruction, 4); + +if (load_twice) + { + instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; + sljit_emit_op_custom(compiler, instruction, 4); + + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); + } + +/* BSF r32, r/m32 */ +instruction[0] = 0x0f; +instruction[1] = 0xbc; +instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 3); + +JUMPTO(SLJIT_ZERO, start); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + +start = LABEL(); +SET_LABEL(quit[0], start); +SET_LABEL(quit[1], start); +SET_LABEL(quit[2], start); +} + +#undef SSE2_COMPARE_TYPE_INDEX + +#endif + +static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset) { DEFINE_COMPILER; struct sljit_label *start; struct sljit_jump *quit; -pcre_uint32 chars[MAX_N_CHARS * 2]; -pcre_uint8 bytes[MAX_N_CHARS * MAX_N_BYTES]; -pcre_uint8 ones[MAX_N_CHARS]; -int offsets[3]; -pcre_uint32 mask; -pcre_uint8 *byte_set, *byte_set_end; -int i, max, from; -int range_right = -1, range_len = 3 - 1; -sljit_ub *update_table = NULL; -BOOL in_range; +struct sljit_jump *found; +pcre_uchar mask; +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +struct sljit_label *utf_start = NULL; +struct sljit_jump *utf_quit = NULL; +#endif +BOOL has_match_end = (common->match_end_ptr != 0); -/* This is even TRUE, if both are NULL. */ -SLJIT_ASSERT(common->read_only_data_ptr == common->read_only_data); +if (offset > 0) + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); -for (i = 0; i < MAX_N_CHARS; i++) +if (has_match_end) { - chars[i << 1] = NOTACHAR; - chars[(i << 1) + 1] = 0; - bytes[i * MAX_N_BYTES] = 0; - } + OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); -max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS); - -if (max <= 1) - return FALSE; - -for (i = 0; i < max; i++) - { - mask = chars[(i << 1) + 1]; - ones[i] = ones_in_half_byte[mask & 0xf]; - mask >>= 4; - while (mask != 0) + OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1)); +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + if (sljit_x86_is_cmov_available()) { - ones[i] += ones_in_half_byte[mask & 0xf]; - mask >>= 4; + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0); + sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0); + } +#endif + { + quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0); + OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); + JUMPHERE(quit); } } +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +if (common->utf && offset > 0) + utf_start = LABEL(); +#endif + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + +/* SSE2 accelerated first character search. */ + +if (sljit_x86_is_sse2_available()) + { + fast_forward_first_char2_sse2(common, char1, char2); + + SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0); + if (common->mode == JIT_COMPILE) + { + /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */ + SLJIT_ASSERT(common->forced_quit_label == NULL); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); + add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 + if (common->utf && offset > 0) + { + SLJIT_ASSERT(common->mode == JIT_COMPILE); + + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#if defined COMPILE_PCRE8 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); +#elif defined COMPILE_PCRE16 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); +#else +#error "Unknown code width" +#endif + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } +#endif + + if (offset > 0) + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); + } + else if (sljit_x86_is_cmov_available()) + { + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); + sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0); + } + else + { + quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, STR_PTR, 0, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0); + JUMPHERE(quit); + } + + if (has_match_end) + OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); + return; + } + +#endif + +quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + +start = LABEL(); +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + +if (char1 == char2) + found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1); +else + { + mask = char1 ^ char2; + if (is_powerof2(mask)) + { + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); + found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask); + } + else + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + found = JUMP(SLJIT_NOT_ZERO); + } + } + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start); + +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +if (common->utf && offset > 0) + utf_quit = JUMP(SLJIT_JUMP); +#endif + +JUMPHERE(found); + +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +if (common->utf && offset > 0) + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#if defined COMPILE_PCRE8 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); +#elif defined COMPILE_PCRE16 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); +#else +#error "Unknown code width" +#endif + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPHERE(utf_quit); + } +#endif + +JUMPHERE(quit); + +if (has_match_end) + { + quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); + if (offset > 0) + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); + JUMPHERE(quit); + OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); + } + +if (offset > 0) + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); +} + +static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common) +{ +DEFINE_COMPILER; +struct sljit_label *start; +struct sljit_jump *quit; +struct sljit_jump *match; +/* bytes[0] represent the number of characters between 0 +and MAX_N_BYTES - 1, 255 represents any character. */ +pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS]; +sljit_s32 offset; +pcre_uchar mask; +pcre_uchar *char_set, *char_set_end; +int i, max, from; +int range_right = -1, range_len; +sljit_u8 *update_table = NULL; +BOOL in_range; +sljit_u32 rec_count; + +for (i = 0; i < MAX_N_CHARS; i++) + chars[i * MAX_DIFF_CHARS] = 0; + +rec_count = 10000; +max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); + +if (max < 1) + return FALSE; + in_range = FALSE; -from = 0; /* Prevent compiler "uninitialized" warning */ +/* Prevent compiler "uninitialized" warning */ +from = 0; +range_len = 4 /* minimum length */ - 1; for (i = 0; i <= max; i++) { - if (in_range && (i - from) > range_len && (bytes[(i - 1) * MAX_N_BYTES] <= 4)) + if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255)) { range_len = i - from; range_right = i - 1; } - if (i < max && bytes[i * MAX_N_BYTES] < 255) + if (i < max && chars[i * MAX_DIFF_CHARS] < 255) { + SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0); if (!in_range) { in_range = TRUE; from = i; } } - else if (in_range) + else in_range = FALSE; } if (range_right >= 0) { - /* Since no data is consumed (see the assert in the beginning - of this function), this space can be reallocated. */ - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); - - common->read_only_data_size += 256; - common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size); - if (common->read_only_data == NULL) + update_table = (sljit_u8 *)allocate_read_only_data(common, 256); + if (update_table == NULL) return TRUE; - - update_table = (sljit_ub *)common->read_only_data; - common->read_only_data_ptr = (sljit_uw *)(update_table + 256); memset(update_table, IN_UCHARS(range_len), 256); for (i = 0; i < range_len; i++) { - byte_set = bytes + ((range_right - i) * MAX_N_BYTES); - SLJIT_ASSERT(byte_set[0] > 0 && byte_set[0] < 255); - byte_set_end = byte_set + byte_set[0]; - byte_set++; - while (byte_set <= byte_set_end) + char_set = chars + ((range_right - i) * MAX_DIFF_CHARS); + SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255); + char_set_end = char_set + char_set[0]; + char_set++; + while (char_set <= char_set_end) { - if (update_table[*byte_set] > IN_UCHARS(i)) - update_table[*byte_set] = IN_UCHARS(i); - byte_set++; + if (update_table[(*char_set) & 0xff] > IN_UCHARS(i)) + update_table[(*char_set) & 0xff] = IN_UCHARS(i); + char_set++; } } } -offsets[0] = -1; +offset = -1; /* Scan forward. */ for (i = 0; i < max; i++) - if (ones[i] <= 2) { - offsets[0] = i; - break; - } - -if (offsets[0] < 0 && range_right < 0) - return FALSE; - -if (offsets[0] >= 0) { - /* Scan backward. */ - offsets[1] = -1; - for (i = max - 1; i > offsets[0]; i--) - if (ones[i] <= 2 && i != range_right) - { - offsets[1] = i; - break; - } - - /* This case is handled better by fast_forward_first_char. */ - if (offsets[1] == -1 && offsets[0] == 0 && range_right < 0) - return FALSE; - - offsets[2] = -1; - /* We only search for a middle character if there is no range check. */ - if (offsets[1] >= 0 && range_right == -1) + if (offset == -1) { - /* Scan from middle. */ - for (i = (offsets[0] + offsets[1]) / 2 + 1; i < offsets[1]; i++) - if (ones[i] <= 2) + if (chars[i * MAX_DIFF_CHARS] <= 2) + offset = i; + } + else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2) + { + if (chars[i * MAX_DIFF_CHARS] == 1) + offset = i; + else + { + mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; + if (!is_powerof2(mask)) { - offsets[2] = i; - break; + mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2]; + if (is_powerof2(mask)) + offset = i; } - - if (offsets[2] == -1) - { - for (i = (offsets[0] + offsets[1]) / 2; i > offsets[0]; i--) - if (ones[i] <= 2) - { - offsets[2] = i; - break; - } } } - - SLJIT_ASSERT(offsets[1] == -1 || (offsets[0] < offsets[1])); - SLJIT_ASSERT(offsets[2] == -1 || (offsets[0] < offsets[2] && offsets[1] > offsets[2])); - - chars[0] = chars[offsets[0] << 1]; - chars[1] = chars[(offsets[0] << 1) + 1]; - if (offsets[2] >= 0) - { - chars[2] = chars[offsets[2] << 1]; - chars[3] = chars[(offsets[2] << 1) + 1]; - } - if (offsets[1] >= 0) - { - chars[4] = chars[offsets[1] << 1]; - chars[5] = chars[(offsets[1] << 1) + 1]; - } } +if (range_right < 0) + { + if (offset < 0) + return FALSE; + SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2); + /* Works regardless the value is 1 or 2. */ + mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]]; + fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset); + return TRUE; + } + +if (range_right == offset) + offset = -1; + +SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2)); + max -= 1; -if (firstline) +SLJIT_ASSERT(max > 0); +if (common->match_end_ptr != 0) { - SLJIT_ASSERT(common->first_line_end != 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); - quit = CMP(SLJIT_C_LESS_EQUAL, STR_END, 0, TMP1, 0); + quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0); OP1(SLJIT_MOV, STR_END, 0, TMP1, 0); JUMPHERE(quit); } else OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); +SLJIT_ASSERT(range_right >= 0); + #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -if (range_right >= 0) - OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table); +OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table); #endif start = LABEL(); -quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -SLJIT_ASSERT(range_right >= 0 || offsets[0] >= 0); - -if (range_right >= 0) - { #if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right)); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right)); #else - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1); #endif #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0); #else - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table); +OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table); #endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start); - } +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); +CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start); -if (offsets[0] >= 0) +if (offset >= 0) { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[0])); - if (offsets[1] >= 0) - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[1])); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - if (chars[1] != 0) - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start); - if (offsets[2] >= 0) - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[2] - 1)); - - if (offsets[1] >= 0) + if (chars[offset * MAX_DIFF_CHARS] == 1) + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start); + else { - if (chars[5] != 0) - OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[5]); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[4], start); + mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; + if (is_powerof2(mask)) + { + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start); + } + else + { + match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start); + JUMPHERE(match); + } } - - if (offsets[2] >= 0) - { - if (chars[3] != 0) - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[3]); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[2], start); - } - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 +if (common->utf && offset != 0) + { + if (offset < 0) + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } + else + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); +#if defined COMPILE_PCRE8 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start); +#elif defined COMPILE_PCRE16 + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start); +#else +#error "Unknown code width" +#endif + if (offset < 0) + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } +#endif + +if (offset >= 0) + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPHERE(quit); -if (firstline) +if (common->match_end_ptr != 0) { if (range_right >= 0) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); if (range_right >= 0) { - quit = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); + quit = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); JUMPHERE(quit); } @@ -3764,66 +4523,26 @@ return TRUE; } #undef MAX_N_CHARS -#undef MAX_N_BYTES +#undef MAX_DIFF_CHARS -static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) +static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless) { -DEFINE_COMPILER; -struct sljit_label *start; -struct sljit_jump *quit; -struct sljit_jump *found; -pcre_uchar oc, bit; - -if (firstline) - { - SLJIT_ASSERT(common->first_line_end != 0); - OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); - } - -start = LABEL(); -quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); +pcre_uchar oc; oc = first_char; if (caseless) { oc = TABLE_GET(first_char, common->fcc, first_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) +#if defined SUPPORT_UCP && !defined COMPILE_PCRE8 if (first_char > 127 && common->utf) oc = UCD_OTHERCASE(first_char); #endif } -if (first_char == oc) - found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char); -else - { - bit = first_char ^ oc; - if (is_powerof2(bit)) - { - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit); - } - else - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); - found = JUMP(SLJIT_C_NOT_ZERO); - } - } -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_JUMP, start); -JUMPHERE(found); -JUMPHERE(quit); - -if (firstline) - OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); +fast_forward_first_char2(common, first_char, oc, 0); } -static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) +static SLJIT_INLINE void fast_forward_newline(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *loop; @@ -3834,24 +4553,23 @@ struct sljit_jump *foundcr = NULL; struct sljit_jump *notfoundnl; jump_list *newline = NULL; -if (firstline) +if (common->match_end_ptr != 0) { - SLJIT_ASSERT(common->first_line_end != 0); OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } if (common->nltype == NLTYPE_FIXED && common->newline > 255) { - lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); + firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -3859,33 +4577,33 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255) loop = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); JUMPHERE(quit); JUMPHERE(firstchar); JUMPHERE(lastchar); - if (firstline) + if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); return; } OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); -firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); +firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); skip_char_back(common); loop = LABEL(); common->ff_newline_shortcut = loop; read_char_range(common, common->nlmin, common->nlmax, TRUE); -lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) - foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); check_newlinechar(common, common->nltype, &newline, FALSE); set_jumps(newline, loop); @@ -3893,10 +4611,10 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) { quit = JUMP(SLJIT_JUMP); JUMPHERE(foundcr); - notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -3907,13 +4625,13 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) JUMPHERE(lastchar); JUMPHERE(firstchar); -if (firstline) +if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); } -static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); +static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); -static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, pcre_uint8 *start_bits, BOOL firstline) +static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, const sljit_u8 *start_bits) { DEFINE_COMPILER; struct sljit_label *start; @@ -3924,15 +4642,14 @@ jump_list *matches = NULL; struct sljit_jump *jump; #endif -if (firstline) +if (common->match_end_ptr != 0) { - SLJIT_ASSERT(common->first_line_end != 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } start = LABEL(); -quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); #ifdef SUPPORT_UTF if (common->utf) @@ -3942,16 +4659,16 @@ if (common->utf) if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches)) { #ifndef COMPILE_PCRE8 - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); JUMPHERE(jump); #endif OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - found = JUMP(SLJIT_C_NOT_ZERO); + found = JUMP(SLJIT_NOT_ZERO); } #ifdef SUPPORT_UTF @@ -3963,17 +4680,17 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined COMPILE_PCRE8 if (common->utf) { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); } #elif defined COMPILE_PCRE16 if (common->utf) { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); + CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); } @@ -3986,7 +4703,7 @@ if (matches != NULL) set_jumps(matches, LABEL()); JUMPHERE(quit); -if (firstline) +if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); } @@ -3999,13 +4716,13 @@ struct sljit_jump *alreadyfound; struct sljit_jump *found; struct sljit_jump *foundoc = NULL; struct sljit_jump *notfound; -pcre_uint32 oc, bit; +sljit_u32 oc, bit; SLJIT_ASSERT(common->req_char_ptr != 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr); OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); -toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); -alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); +toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0); +alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0); if (has_firstchar) OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -4013,7 +4730,7 @@ else OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); loop = LABEL(); -notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); +notfound = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); oc = req_char; @@ -4026,19 +4743,19 @@ if (caseless) #endif } if (req_char == oc) - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); else { bit = req_char ^ oc; if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); } else { - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); - foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); + foundoc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc); } } OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -4047,7 +4764,7 @@ JUMPTO(SLJIT_JUMP, loop); JUMPHERE(found); if (foundoc) JUMPHERE(foundoc); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0); JUMPHERE(alreadyfound); JUMPHERE(toolong); return notfound; @@ -4067,7 +4784,7 @@ GET_LOCAL_BASE(TMP3, 0, 0); mainloop = LABEL(); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0); -jump = JUMP(SLJIT_C_SIG_LESS_EQUAL); +jump = JUMP(SLJIT_SIG_LESS_EQUAL); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); @@ -4076,7 +4793,7 @@ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); JUMPTO(SLJIT_JUMP, mainloop); JUMPHERE(jump); -jump = JUMP(SLJIT_C_SIG_LESS); +jump = JUMP(SLJIT_SIG_LESS); /* End of dropping frames. */ sljit_emit_fast_return(compiler, RETURN_ADDR, 0); @@ -4099,12 +4816,12 @@ struct sljit_jump *jump; SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); -sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); /* Get type of the previous char, and put it to LOCALS1. */ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); -skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, SLJIT_IMM, 0); +skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); skip_char_back(common); check_start_used_ptr(common); read_char(common); @@ -4114,32 +4831,32 @@ read_char(common); if (common->use_ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); + jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); } else #endif { #ifndef COMPILE_PCRE8 - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #elif defined SUPPORT_UTF /* Here LOCALS1 has already been zeroed. */ jump = NULL; if (common->utf) - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #endif /* COMPILE_PCRE8 */ - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); #elif defined SUPPORT_UTF @@ -4158,14 +4875,14 @@ peek_char(common, READ_CHAR_MAX); if (common->use_ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); + jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); } else @@ -4174,14 +4891,14 @@ else #ifndef COMPILE_PCRE8 /* TMP2 may be destroyed by peek_char. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #elif defined SUPPORT_UTF OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); jump = NULL; if (common->utf) - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #endif - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); #ifndef COMPILE_PCRE8 @@ -4193,15 +4910,16 @@ else } set_jumps(skipread_list, LABEL()); -OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); -sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); } -static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) +static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) { +/* May destroy TMP1. */ DEFINE_COMPILER; int ranges[MAX_RANGE_SIZE]; -pcre_uint8 bit, cbit, all; +sljit_u8 bit, cbit, all; int i, byte, length = 0; bit = bits[0] & 0x1; @@ -4254,56 +4972,58 @@ switch(length) return TRUE; case 1: - add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); + add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; case 2: if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); - add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); + add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); } else - add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); + add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; case 3: if (bit != 0) { - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); } else - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; } - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0])); if (ranges[1] + 1 != ranges[2]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); } else - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1])); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1])); return TRUE; case 4: if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2]) && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2] + && (ranges[1] & (ranges[2] - ranges[0])) == 0 && is_powerof2(ranges[2] - ranges[0])) { + SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]); if (ranges[2] + 1 != ranges[3]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]); - add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); + add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); } else - add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); + add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); return TRUE; } @@ -4313,31 +5033,31 @@ switch(length) if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); i = ranges[0]; } else - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); if (ranges[2] + 1 != ranges[3]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); } else - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i)); return TRUE; } OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0])); if (ranges[1] + 1 != ranges[2]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); } else - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); return TRUE; default: @@ -4355,21 +5075,21 @@ sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -4381,33 +5101,33 @@ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); -OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); +OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -4421,21 +5141,21 @@ sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -4452,21 +5172,21 @@ struct sljit_label *label; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR2, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); label = LABEL(); OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); +jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0); OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_C_NOT_ZERO, label); +JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -4482,8 +5202,8 @@ sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, CHAR2, 0); OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -4492,26 +5212,26 @@ label = LABEL(); OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); #ifndef COMPILE_PCRE8 -jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255); +jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255); #endif -OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); +OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); -jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255); +jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255); #endif -OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); +OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); #endif -jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); +jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0); OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_C_NOT_ZERO, label); +JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); +OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); +OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -4524,11 +5244,11 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0); static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) { /* This function would be ineffective to do in JIT level. */ -pcre_uint32 c1, c2; +sljit_u32 c1, c2; const pcre_uchar *src2 = args->uchar_ptr; const pcre_uchar *end2 = args->end; const ucd_record *ur; -const pcre_uint32 *pp; +const sljit_u32 *pp; while (src1 < end1) { @@ -4553,7 +5273,7 @@ return src2; #endif /* SUPPORT_UTF && SUPPORT_UCP */ static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, - compare_context* context, jump_list **backtracks) + compare_context *context, jump_list **backtracks) { DEFINE_COMPILER; unsigned int othercasebit = 0; @@ -4588,16 +5308,16 @@ if (context->sourcereg == -1) #if defined COMPILE_PCRE8 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED if (context->length >= 4) - OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else if (context->length >= 2) - OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else #endif - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); #elif defined COMPILE_PCRE16 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED if (context->length >= 4) - OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else #endif OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); @@ -4639,12 +5359,12 @@ do #endif { if (context->length >= 4) - OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); else if (context->length >= 2) - OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); #if defined COMPILE_PCRE8 else if (context->length >= 1) - OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); #endif /* COMPILE_PCRE8 */ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; @@ -4653,20 +5373,20 @@ do case 4 / sizeof(pcre_uchar): if (context->oc.asint != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); break; case 2 / sizeof(pcre_uchar): if (context->oc.asushort != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); break; #ifdef COMPILE_PCRE8 case 1: if (context->oc.asbyte != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); break; #endif @@ -4688,10 +5408,10 @@ do if (othercasebit != 0 && othercasechar == cc) { OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); } else - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); #endif @@ -4727,6 +5447,8 @@ return cc; } \ charoffset = (value); +static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr); + static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) { DEFINE_COMPILER; @@ -4743,8 +5465,8 @@ BOOL utf = common->utf; #ifdef SUPPORT_UCP BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; BOOL charsaved = FALSE; -int typereg = TMP1, scriptreg = TMP1; -const pcre_uint32 *other_cases; +int typereg = TMP1; +const sljit_u32 *other_cases; sljit_uw typeoffset; #endif @@ -4806,6 +5528,14 @@ while (*cc != XCL_END) switch(*cc) { case PT_ANY: + /* Any either accepts everything or ignored. */ + if (cc[-1] == XCL_PROP) + { + compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE); + if (list == backtracks) + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + return; + } break; case PT_LAMP: @@ -4842,25 +5572,25 @@ while (*cc != XCL_END) } #endif } +SLJIT_ASSERT(compares > 0); /* We are not necessary in utf mode even in 8 bit mode. */ cc = ccbegin; -detect_partial_match(common, backtracks); read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0); if ((cc[-1] & XCL_HASPROP) == 0) { if ((cc[-1] & XCL_MAP) != 0) { - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); - if (!check_class_ranges(common, (const pcre_uint8 *)cc, (((const pcre_uint8 *)cc)[31] & 0x80) != 0, TRUE, &found)) + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); + if (!check_class_ranges(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found)) { OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - add_jump(compiler, &found, JUMP(SLJIT_C_NOT_ZERO)); + add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO)); } add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); @@ -4871,71 +5601,112 @@ if ((cc[-1] & XCL_HASPROP) == 0) else { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min); - add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, max - min)); + add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min)); } } else if ((cc[-1] & XCL_MAP) != 0) { - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); #ifdef SUPPORT_UCP charsaved = TRUE; #endif - if (!check_class_ranges(common, (const pcre_uint8 *)cc, FALSE, TRUE, list)) + if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list)) { #ifdef COMPILE_PCRE8 - SLJIT_ASSERT(common->utf); + jump = NULL; + if (common->utf) #endif - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); + add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO)); - JUMPHERE(jump); +#ifdef COMPILE_PCRE8 + if (common->utf) +#endif + JUMPHERE(jump); } - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); cc += 32 / sizeof(pcre_uchar); } #ifdef SUPPORT_UCP -/* Simple register allocation. TMP1 is preferred if possible. */ if (needstype || needsscript) { if (needschar && !charsaved) - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); - add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); - if (needschar) - { - if (needstype) - { - OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); - typereg = RETURN_ADDR; - } + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); - if (needsscript) - scriptreg = TMP3; - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - } - else if (needstype && needsscript) - scriptreg = TMP3; - /* In all other cases only one of them was specified, and that can goes to TMP1. */ + OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); + OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); + /* Before anything else, we deal with scripts. */ if (needsscript) { - if (scriptreg == TMP1) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); + + ccbegin = cc; + + while (*cc != XCL_END) { - OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); - OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3); + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + GETCHARINCTEST(c, cc); + } + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + if (*cc == PT_SC) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + if (cc[-1] == XCL_NOTPROP) + invertcmp ^= 0x1; + jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]); + add_jump(compiler, compares > 0 ? list : backtracks, jump); + } + cc += 2; + } + } + + cc = ccbegin; + } + + if (needschar) + { + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + } + + if (needstype) + { + if (!needschar) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); } else { OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); - OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0); + OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + typereg = RETURN_ADDR; } } } @@ -4962,19 +5733,19 @@ while (*cc != XCL_END) if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } else { - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); numberofcmps = 0; } } @@ -4988,96 +5759,92 @@ while (*cc != XCL_END) if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } else { - jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); numberofcmps = 0; } } #ifdef SUPPORT_UCP else { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); if (*cc == XCL_NOTPROP) invertcmp ^= 0x1; cc++; switch(*cc) { case PT_ANY: - if (list != backtracks) - { - if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0)) - continue; - } - else if (cc[-1] == XCL_NOTPROP) - continue; - jump = JUMP(SLJIT_JUMP); + if (!invertcmp) + jump = JUMP(SLJIT_JUMP); break; case PT_LAMP: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_GC: c = PRIV(ucp_typerange)[(int)cc[1] * 2]; SET_TYPE_OFFSET(c); - jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); + jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); break; case PT_PC: - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset); + jump = CMP(SLJIT_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset); break; case PT_SC: - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]); + compares++; + /* Do nothing. */ break; case PT_SPACE: case PT_PXSPACE: SET_CHAR_OFFSET(9); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); SET_TYPE_OFFSET(ucp_Zl); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_WORD: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); /* Fall through. */ case PT_ALNUM: SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Nd); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_CLIST: @@ -5099,7 +5866,7 @@ while (*cc != XCL_END) OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); other_cases += 2; } else if (is_powerof2(other_cases[2] ^ other_cases[1])) @@ -5112,103 +5879,107 @@ while (*cc != XCL_END) OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset)); - OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL); other_cases += 3; } else { OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); } while (*other_cases != NOTACHAR) { OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); - OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL); } - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_UCNC: OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); SET_CHAR_OFFSET(0xa0); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_GREATER_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_GREATER_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_PXGRAPH: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER); - jump = CMP(SLJIT_C_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); + jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); - jump = CMP(SLJIT_C_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); break; case PT_PXPRINT: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll); - OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_C_NOT_EQUAL); + OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL); - jump = CMP(SLJIT_C_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); + jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); - jump = CMP(SLJIT_C_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); break; case PT_PXPUNCT: SET_TYPE_OFFSET(ucp_Sc); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xff); - OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f); + OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Pc); OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + default: + SLJIT_ASSERT_STOP(); break; } cc += 2; @@ -5228,13 +5999,232 @@ if (found != NULL) #endif -static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) +static pcre_uchar *compile_simple_assertion_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) +{ +DEFINE_COMPILER; +int length; +struct sljit_jump *jump[4]; +#ifdef SUPPORT_UTF +struct sljit_label *label; +#endif /* SUPPORT_UTF */ + +switch(type) + { + case OP_SOD: + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_SOM: + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO)); + return cc; + + case OP_EODN: + /* Requires rather complex checks. */ + jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (common->mode == JIT_COMPILE) + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); + else + { + jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL)); + check_partial(common, TRUE); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + JUMPHERE(jump[1]); + } + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else if (common->nltype == NLTYPE_FIXED) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); + } + else + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); + jump[2] = JUMP(SLJIT_GREATER); + add_jump(compiler, backtracks, JUMP(SLJIT_LESS)); + /* Equal. */ + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + + JUMPHERE(jump[1]); + if (common->nltype == NLTYPE_ANYCRLF) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); + } + else + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0); + read_char_range(common, common->nlmin, common->nlmax, TRUE); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); + } + JUMPHERE(jump[2]); + JUMPHERE(jump[3]); + } + JUMPHERE(jump[0]); + check_partial(common, FALSE); + return cc; + + case OP_EOD: + add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); + check_partial(common, FALSE); + return cc; + + case OP_DOLL: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + + if (!common->endonly) + compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks); + else + { + add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); + check_partial(common, FALSE); + } + return cc; + + case OP_DOLLM: + jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + check_partial(common, FALSE); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (common->mode == JIT_COMPILE) + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0)); + else + { + jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0); + /* STR_PTR = STR_END - IN_UCHARS(1) */ + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + check_partial(common, TRUE); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + JUMPHERE(jump[1]); + } + + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + peek_char(common, common->nlmax); + check_newlinechar(common, common->nltype, backtracks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + + case OP_CIRC: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + return cc; + + case OP_CIRCM: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); + jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + skip_char_back(common); + read_char_range(common, common->nlmin, common->nlmax, TRUE); + check_newlinechar(common, common->nltype, backtracks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + + case OP_REVERSE: + length = GET(cc, 0); + if (length == 0) + return cc + LINK_SIZE; + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +#ifdef SUPPORT_UTF + if (common->utf) + { + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); + label = LABEL(); + add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); + skip_char_back(common); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + } + else +#endif + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0)); + } + check_start_used_ptr(common); + return cc + LINK_SIZE; + } +SLJIT_ASSERT_STOP(); +return cc; +} + +static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr) { DEFINE_COMPILER; int length; unsigned int c, oc, bit; compare_context context; -struct sljit_jump *jump[4]; +struct sljit_jump *jump[3]; jump_list *end_list; #ifdef SUPPORT_UTF struct sljit_label *label; @@ -5245,79 +6235,65 @@ pcre_uchar propdata[5]; switch(type) { - case OP_SOD: - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); - return cc; - - case OP_SOM: - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); - return cc; - - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - return cc; - case OP_NOT_DIGIT: case OP_DIGIT: /* Digits are usually 0-9, so it is worth to optimize them. */ - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_digit, FALSE)) + if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) read_char7_type(common, type == OP_NOT_DIGIT); else #endif read_char8_type(common, type == OP_NOT_DIGIT); /* Flip the starting bit in the negative case. */ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); - add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_NOT_WHITESPACE: case OP_WHITESPACE: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_space, FALSE)) + if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) read_char7_type(common, type == OP_NOT_WHITESPACE); else #endif read_char8_type(common, type == OP_NOT_WHITESPACE); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); - add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_NOT_WORDCHAR: case OP_WORDCHAR: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_word, FALSE)) + if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) read_char7_type(common, type == OP_NOT_WORDCHAR); else #endif read_char8_type(common, type == OP_NOT_WORDCHAR); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); - add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_ANY: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); read_char_range(common, common->nlmin, common->nlmax, TRUE); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { - jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); end_list = NULL; if (common->mode != JIT_PARTIAL_HARD_COMPILE) - add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); else check_str_end(common, &end_list); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); set_jumps(end_list, LABEL()); JUMPHERE(jump[0]); } @@ -5326,7 +6302,8 @@ switch(type) return cc; case OP_ALLANY: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #ifdef SUPPORT_UTF if (common->utf) { @@ -5334,14 +6311,14 @@ switch(type) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 #if defined COMPILE_PCRE8 - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); #elif defined COMPILE_PCRE16 - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); + jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); #endif @@ -5354,7 +6331,8 @@ switch(type) return cc; case OP_ANYBYTE: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); return cc; @@ -5367,23 +6345,26 @@ switch(type) propdata[2] = cc[0]; propdata[3] = cc[1]; propdata[4] = XCL_END; + if (check_str_ptr) + detect_partial_match(common, backtracks); compile_xclass_matchingpath(common, propdata, backtracks); return cc + 2; #endif #endif case OP_ANYNL: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE); - jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); /* We don't need to handle soft partial matching case. */ end_list = NULL; if (common->mode != JIT_PARTIAL_HARD_COMPILE) - add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); else check_str_end(common, &end_list); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump[2] = JUMP(SLJIT_JUMP); JUMPHERE(jump[0]); @@ -5395,52 +6376,55 @@ switch(type) case OP_NOT_HSPACE: case OP_HSPACE: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE); add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; case OP_NOT_VSPACE: case OP_VSPACE: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE); add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; #ifdef SUPPORT_UCP case OP_EXTUNI: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); read_char(common); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); /* Optimize register allocation: use a real register. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV_UB, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); + OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3); label = LABEL(); - jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); read_char(common); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3); OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2); - OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable)); + OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable)); OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - JUMPTO(SLJIT_C_NOT_ZERO, label); + JUMPTO(SLJIT_NOT_ZERO, label); OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); JUMPHERE(jump[0]); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); if (common->mode == JIT_PARTIAL_HARD_COMPILE) { - jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); + jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); /* Since we successfully read a char above, partial matching must occure. */ check_partial(common, TRUE); JUMPHERE(jump[0]); @@ -5448,176 +6432,17 @@ switch(type) return cc; #endif - case OP_EODN: - /* Requires rather complex checks. */ - jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); - else - { - jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_NOT_EQUAL); - add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); - } - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else if (common->nltype == NLTYPE_FIXED) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); - } - else - { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); - jump[2] = JUMP(SLJIT_C_GREATER); - add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS)); - /* Equal. */ - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - - JUMPHERE(jump[1]); - if (common->nltype == NLTYPE_ANYCRLF) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); - } - else - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); - read_char_range(common, common->nlmin, common->nlmax, TRUE); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); - add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); - } - JUMPHERE(jump[2]); - JUMPHERE(jump[3]); - } - JUMPHERE(jump[0]); - check_partial(common, FALSE); - return cc; - - case OP_EOD: - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); - check_partial(common, FALSE); - return cc; - - case OP_CIRC: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0)); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - return cc; - - case OP_CIRCM: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); - jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); - - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else - { - skip_char_back(common); - read_char_range(common, common->nlmin, common->nlmax, TRUE); - check_newlinechar(common, common->nltype, backtracks, FALSE); - } - JUMPHERE(jump[0]); - return cc; - - case OP_DOLL: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - - if (!common->endonly) - compile_char1_matchingpath(common, OP_EODN, cc, backtracks); - else - { - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); - check_partial(common, FALSE); - } - return cc; - - case OP_DOLLM: - jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - check_partial(common, FALSE); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); - - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); - else - { - jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0); - /* STR_PTR = STR_END - IN_UCHARS(1) */ - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); - } - - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else - { - peek_char(common, common->nlmax); - check_newlinechar(common, common->nltype, backtracks, FALSE); - } - JUMPHERE(jump[0]); - return cc; - case OP_CHAR: case OP_CHARI: length = 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); #endif - if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) + if (common->mode == JIT_COMPILE && check_str_ptr + && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) { OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); context.length = IN_UCHARS(length); context.sourcereg = -1; @@ -5627,7 +6452,8 @@ switch(type) return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); } - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #ifdef SUPPORT_UTF if (common->utf) { @@ -5640,7 +6466,7 @@ switch(type) if (type == OP_CHAR || !char_has_othercase(common, cc)) { read_char_range(common, c, c, FALSE); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); return cc + length; } oc = char_othercase(common, c); @@ -5649,17 +6475,18 @@ switch(type) if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); return cc + length; } - jump[0] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); + jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); JUMPHERE(jump[0]); return cc + length; case OP_NOT: case OP_NOTI: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); length = 1; #ifdef SUPPORT_UTF if (common->utf) @@ -5668,18 +6495,18 @@ switch(type) c = *cc; if (c < 128) { - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); if (type == OP_NOT || !char_has_othercase(common, cc)) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); else { /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); } /* Skip the variable-length character. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(jump[0]); @@ -5698,7 +6525,7 @@ switch(type) if (type == OP_NOT || !char_has_othercase(common, cc)) { read_char_range(common, c, c, TRUE); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); } else { @@ -5708,35 +6535,36 @@ switch(type) if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); } else { - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); } } return cc + length; case OP_CLASS: case OP_NCLASS: - detect_partial_match(common, backtracks); + if (check_str_ptr) + detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 - bit = (common->utf && is_char7_bitset((const pcre_uint8 *)cc, type == OP_NCLASS)) ? 127 : 255; + bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255; read_char_range(common, 0, bit, type == OP_NCLASS); #else read_char_range(common, 0, 255, type == OP_NCLASS); #endif - if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, FALSE, backtracks)) + if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) return cc + 32 / sizeof(pcre_uchar); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 jump[0] = NULL; if (common->utf) { - jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, bit); + jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit); if (type == OP_CLASS) { add_jump(compiler, backtracks, jump[0]); @@ -5744,7 +6572,7 @@ switch(type) } } #elif !defined COMPILE_PCRE8 - jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); if (type == OP_CLASS) { add_jump(compiler, backtracks, jump[0]); @@ -5754,49 +6582,24 @@ switch(type) OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); + add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (jump[0] != NULL) JUMPHERE(jump[0]); #endif - return cc + 32 / sizeof(pcre_uchar); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case OP_XCLASS: + if (check_str_ptr) + detect_partial_match(common, backtracks); compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks); return cc + GET(cc, 0) - 1; #endif - - case OP_REVERSE: - length = GET(cc, 0); - if (length == 0) - return cc + LINK_SIZE; - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -#ifdef SUPPORT_UTF - if (common->utf) - { - OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); - label = LABEL(); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); - skip_char_back(common); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); - } - else -#endif - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); - } - check_start_used_ptr(common); - return cc + LINK_SIZE; } SLJIT_ASSERT_STOP(); return cc; @@ -5854,7 +6657,7 @@ if (context.length > 0) { /* We have a fixed-length byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); context.sourcereg = -1; #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED @@ -5865,7 +6668,7 @@ if (context.length > 0) } /* A non-fixed length character will be checked if length == 0. */ -return compile_char1_matchingpath(common, *cc, cc + 1, backtracks); +return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE); } /* Forward definitions. */ @@ -5911,21 +6714,21 @@ jump_list *found = NULL; SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); count--; while (count-- > 0) { offset = GET2(slot, 0) << 1; GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset)); - add_jump(compiler, &found, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0)); + add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0)); slot += common->name_entry_size; } offset = GET2(slot, 0) << 1; GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset)); if (backtracks != NULL && !common->jscript_compat) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0)); set_jumps(found, LABEL()); } @@ -5942,10 +6745,10 @@ struct sljit_jump *nopartial; if (ref) { offset = GET2(cc, 1) << 1; - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); /* OVECTOR(1) contains the "string begin - 1" constant. */ if (withchecks && !common->jscript_compat) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); } else OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); @@ -5953,27 +6756,27 @@ else #if defined SUPPORT_UTF && defined SUPPORT_UCP if (common->utf && *cc == OP_REFI) { - SLJIT_ASSERT(TMP1 == SLJIT_SCRATCH_REG1 && STACK_TOP == SLJIT_SCRATCH_REG2 && TMP2 == SLJIT_SCRATCH_REG3); + SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1 && TMP2 == SLJIT_R2); if (ref) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); if (withchecks) - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); + jump = CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0); /* Needed to save important temporary registers. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); else { - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); - nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); + nopartial = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(nopartial); @@ -5984,20 +6787,20 @@ else #endif /* SUPPORT_UTF && SUPPORT_UCP */ { if (ref) - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); else OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); if (withchecks) - jump = JUMP(SLJIT_C_ZERO); + jump = JUMP(SLJIT_ZERO); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); + partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0); if (common->mode == JIT_COMPILE) add_jump(compiler, backtracks, partial); add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); if (common->mode != JIT_COMPILE) { @@ -6006,10 +6809,10 @@ else /* TMP2 -= STR_END - STR_PTR */ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); - partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); + partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); JUMPHERE(partial); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); @@ -6040,7 +6843,7 @@ pcre_uchar *ccbegin = cc; int min = 0, max = 0; BOOL minimize; -PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); +PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL); if (ref) offset = GET2(cc, 1) << 1; @@ -6087,7 +6890,7 @@ if (!minimize) { allocate_stack(common, 2); if (ref) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); /* Temporary release of STR_PTR. */ @@ -6095,13 +6898,13 @@ if (!minimize) /* Handles both invalid and empty cases. Since the minimum repeat, is zero the invalid case is basically the same as an empty case. */ if (ref) - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else { compile_dnref_search(common, ccbegin, NULL); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Restore if not zero length. */ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); @@ -6110,40 +6913,40 @@ if (!minimize) { allocate_stack(common, 1); if (ref) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); if (ref) { - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); } else { compile_dnref_search(common, ccbegin, &backtrack->topbacktracks); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } } if (min > 1 || max > 1) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0); label = LABEL(); if (!ref) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE); if (min > 1 || max > 1) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); if (min > 1) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label); + CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label); if (max > 1) { - jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); + jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); @@ -6160,7 +6963,7 @@ if (!minimize) } JUMPHERE(zerolength); - BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); + BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL(); count_match(common); return cc; @@ -6168,7 +6971,7 @@ if (!minimize) allocate_stack(common, ref ? 2 : 3); if (ref) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); if (type != OP_CRMINSTAR) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); @@ -6178,13 +6981,13 @@ if (min == 0) /* Handles both invalid and empty cases. Since the minimum repeat, is zero the invalid case is basically the same as an empty case. */ if (ref) - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else { compile_dnref_search(common, ccbegin, NULL); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Length is non-zero, we can match real repeats. */ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); @@ -6194,21 +6997,21 @@ else { if (ref) { - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); } else { compile_dnref_search(common, ccbegin, &backtrack->topbacktracks); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0); - zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } } -BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); +BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL(); if (max > 0) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); if (!ref) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); @@ -6220,7 +7023,7 @@ if (min > 1) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->matchingpath); + CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath); } else if (max > 0) OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); @@ -6280,15 +7083,15 @@ if (entry == NULL) if (common->has_set_som && common->mark_ptr != 0) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); allocate_stack(common, 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); } else if (common->has_set_som || common->mark_ptr != 0) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } @@ -6298,11 +7101,11 @@ if (entry->entry == NULL) else JUMPTO(SLJIT_FAST_CALL, entry->entry); /* Leave if the match is failed. */ -add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); +add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0)); return cc + 1 + LINK_SIZE; } -static int SLJIT_CALL do_callout(struct jit_arguments* arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector) +static int SLJIT_CALL do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector) { const pcre_uchar *begin = arguments->begin; int *offset_vector = arguments->offsets; @@ -6362,45 +7165,71 @@ PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); SLJIT_ASSERT(common->capture_last_ptr != 0); -OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); -OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); /* These pointer sized fields temporarly stores internal variables. */ -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0); if (common->mark_ptr != 0) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); -OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); -OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); +OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); /* Needed to save important temporary registers. */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); -OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE); -GET_LOCAL_BASE(SLJIT_SCRATCH_REG3, 0, OVECTOR_START); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); +OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE); +GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); -OP1(SLJIT_MOV_SI, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); /* Check return value. */ OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); -add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_C_SIG_GREATER)); +add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER)); if (common->forced_quit_label == NULL) - add_jump(compiler, &common->forced_quit, JUMP(SLJIT_C_SIG_LESS)); + add_jump(compiler, &common->forced_quit, JUMP(SLJIT_SIG_LESS)); else - JUMPTO(SLJIT_C_SIG_LESS, common->forced_quit_label); + JUMPTO(SLJIT_SIG_LESS, common->forced_quit_label); return cc + 2 + 2 * LINK_SIZE; } #undef CALLOUT_ARG_SIZE #undef CALLOUT_ARG_OFFSET +static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(pcre_uchar *cc) +{ +while (TRUE) + { + switch (*cc) + { + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + case OP_CALLOUT: + case OP_ALT: + cc += PRIV(OP_lengths)[*cc]; + break; + + case OP_KET: + return FALSE; + + default: + return TRUE; + } + } +} + static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) { DEFINE_COMPILER; @@ -6452,21 +7281,34 @@ if (bra == OP_BRAMINZERO) /* This is a braminzero backtrack path. */ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } if (framesize < 0) { - extrasize = needs_control_head ? 2 : 1; - if (framesize == no_frame) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); - allocate_stack(common, extrasize); + extrasize = 1; + if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE)) + extrasize = 0; + if (needs_control_head) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + extrasize++; + + if (framesize == no_frame) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); + + if (extrasize > 0) + allocate_stack(common, extrasize); + + if (needs_control_head) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); + + if (extrasize > 0) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + if (needs_control_head) { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); + SLJIT_ASSERT(extrasize == 2); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); } } @@ -6474,20 +7316,23 @@ else { extrasize = needs_control_head ? 3 : 2; allocate_stack(common, framesize + extrasize); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); if (needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + if (needs_control_head) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); } else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE); } @@ -6511,7 +7356,7 @@ while (1) altbacktrack.top = NULL; altbacktrack.topbacktracks = NULL; - if (*ccbegin == OP_ALT) + if (*ccbegin == OP_ALT && extrasize > 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); altbacktrack.cc = ccbegin; @@ -6539,26 +7384,27 @@ while (1) if (framesize < 0) { if (framesize == no_frame) - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); - else + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + else if (extrasize > 0) free_stack(common, extrasize); + if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); } else { if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); } else { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } } @@ -6567,7 +7413,10 @@ while (1) { /* We know that STR_PTR was stored on the top of the stack. */ if (conditional) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0); + { + if (extrasize > 0) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0); + } else if (bra == OP_BRAZERO) { if (framesize < 0) @@ -6576,7 +7425,7 @@ while (1) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); @@ -6584,7 +7433,7 @@ while (1) else if (framesize >= 0) { /* For OP_BRA and OP_BRAMINZERO. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); } } add_jump(compiler, found, JUMP(SLJIT_JUMP)); @@ -6628,10 +7477,10 @@ if (common->positive_assert_quit != NULL) set_jumps(common->positive_assert_quit, LABEL()); SLJIT_ASSERT(framesize != no_stack); if (framesize < 0) - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); else { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); } @@ -6639,12 +7488,12 @@ if (common->positive_assert_quit != NULL) } if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1)); if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { /* Assert is failed. */ - if (conditional || bra == OP_BRAZERO) + if ((conditional && extrasize > 0) || bra == OP_BRAZERO) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (framesize < 0) @@ -6656,7 +7505,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } - else + else if (extrasize > 0) free_stack(common, extrasize); } else @@ -6670,7 +7519,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) } else free_stack(common, framesize + extrasize); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } jump = JUMP(SLJIT_JUMP); if (bra != OP_BRAZERO) @@ -6681,7 +7530,9 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) if (framesize < 0) { /* We know that STR_PTR was stored on the top of the stack. */ - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); + if (extrasize > 0) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); + /* Keep the STR_PTR on the top of the stack. */ if (bra == OP_BRAZERO) { @@ -6700,13 +7551,13 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) if (bra == OP_BRA) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw)); } else { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); if (extrasize == 2) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); @@ -6732,9 +7583,9 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) JUMPHERE(brajump); if (framesize >= 0) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); } set_jumps(backtrack->common.topbacktracks, LABEL()); } @@ -6744,14 +7595,16 @@ else /* AssertNot is successful. */ if (framesize < 0) { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (extrasize > 0) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (bra != OP_BRA) { if (extrasize == 2) free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } - else + else if (extrasize > 0) free_stack(common, extrasize); } else @@ -6766,7 +7619,7 @@ else } else free_stack(common, framesize + extrasize); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } if (bra == OP_BRAZERO) @@ -6807,13 +7660,15 @@ int stacksize; if (framesize < 0) { if (framesize == no_frame) - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else { stacksize = needs_control_head ? 1 : 0; if (ket != OP_KET || has_alternatives) stacksize++; - free_stack(common, stacksize); + + if (stacksize > 0) + free_stack(common, stacksize); } if (needs_control_head) @@ -6825,13 +7680,13 @@ if (framesize < 0) else if (ket == OP_KETRMIN) { /* Move the STR_PTR to the private_data_ptr. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); } } else { stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1; - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); if (needs_control_head) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0); @@ -6842,7 +7697,7 @@ else } } if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0); } static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr) @@ -6851,20 +7706,20 @@ DEFINE_COMPILER; if (common->capture_last_ptr != 0) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); stacksize++; } if (common->optimized_cbracket[offset >> 1] == 0) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); stacksize += 2; } return stacksize; @@ -6987,7 +7842,7 @@ cc += GET(cc, 1); has_alternatives = *cc == OP_ALT; if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND)) - has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF) ? FALSE : TRUE; + has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) ? FALSE : TRUE; if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) opcode = OP_SCOND; @@ -7048,13 +7903,13 @@ if (bra == OP_BRAMINZERO) if (ket != OP_KETRMIN) { free_stack(common, 1); - braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } else { if (opcode == OP_ONCE || opcode >= OP_SBRA) { - jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); /* Nothing stored during the first run. */ skip = JUMP(SLJIT_JUMP); @@ -7063,19 +7918,19 @@ if (bra == OP_BRAMINZERO) if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) { /* When we come from outside, private_data_ptr contains the previous STR_PTR. */ - braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); } else { /* Except when the whole stack frame must be saved. */ - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); - braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw)); } JUMPHERE(skip); } else { - jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); JUMPHERE(jump); } @@ -7084,7 +7939,7 @@ if (bra == OP_BRAMINZERO) if (repeat_type != 0) { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count); if (repeat_type == OP_EXACT) rmax_label = LABEL(); } @@ -7105,7 +7960,7 @@ if (opcode == OP_ONCE) stacksize = 0; if (needs_control_head) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); stacksize++; } @@ -7116,12 +7971,12 @@ if (opcode == OP_ONCE) { stacksize += 2; if (!needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); } else { if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); if (ket == OP_KETRMAX || has_alternatives) stacksize++; } @@ -7139,10 +7994,10 @@ if (opcode == OP_ONCE) if (ket == OP_KETRMIN) { if (needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); } else if (ket == OP_KETRMAX || has_alternatives) @@ -7159,20 +8014,20 @@ if (opcode == OP_ONCE) if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); stacksize = needs_control_head ? 1 : 0; if (ket != OP_KET || has_alternatives) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); stacksize++; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); } else { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); } init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE); @@ -7185,26 +8040,26 @@ else if (opcode == OP_CBRA || opcode == OP_SCBRA) { SLJIT_ASSERT(private_data_ptr == OVECTOR(offset)); allocate_stack(common, 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); } else { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } } else if (opcode == OP_SBRA || opcode == OP_SCOND) { /* Saving the previous value. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } else if (has_alternatives) @@ -7221,7 +8076,7 @@ if (opcode == OP_COND || opcode == OP_SCOND) { SLJIT_ASSERT(has_alternatives); add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), - CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); + CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); matchingpath += 1 + IMM2_SIZE; } else if (*matchingpath == OP_DNCREF) @@ -7231,26 +8086,28 @@ if (opcode == OP_COND || opcode == OP_SCOND) i = GET2(matchingpath, 1 + IMM2_SIZE); slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size; OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); slot += common->name_entry_size; i--; while (i-- > 0) { - OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); + OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0); slot += common->name_entry_size; } OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_C_ZERO)); + add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO)); matchingpath += 1 + 2 * IMM2_SIZE; } - else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF) + else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) { /* Never has other case. */ BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; SLJIT_ASSERT(!has_alternatives); + if (*matchingpath == OP_FAIL) + stacksize = 0; if (*matchingpath == OP_RREF) { stacksize = GET2(matchingpath, 1); @@ -7325,7 +8182,7 @@ stacksize = 0; if (repeat_type == OP_MINUPTO) { /* We need to preserve the counter. TMP2 will be used below. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); stacksize++; } if (ket != OP_KET || bra != OP_BRA) @@ -7375,7 +8232,7 @@ if (has_alternatives) if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0) { SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); } if (ket == OP_KETRMAX) @@ -7384,8 +8241,8 @@ if (ket == OP_KETRMAX) { if (has_alternatives) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, rmax_label); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, rmax_label); /* Drop STR_PTR for greedy plus quantifier. */ if (opcode != OP_ONCE) free_stack(common, 1); @@ -7397,14 +8254,14 @@ if (ket == OP_KETRMAX) /* Checking zero-length iteration. */ if (opcode != OP_ONCE) { - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmax_label); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label); /* Drop STR_PTR for greedy plus quantifier. */ if (bra != OP_BRAZERO) free_stack(common, 1); } else /* TMP2 must contain the starting STR_PTR. */ - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label); } else JUMPTO(SLJIT_JUMP, rmax_label); @@ -7413,13 +8270,14 @@ if (ket == OP_KETRMAX) if (repeat_type == OP_EXACT) { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, rmax_label); + count_match(common); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, rmax_label); } else if (repeat_type == OP_UPTO) { /* We need to preserve the counter. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } @@ -7439,7 +8297,7 @@ if (bra == OP_BRAMINZERO) framesize is < 0, OP_ONCE will do the release itself. */ if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } else if (ket == OP_KETRMIN && opcode != OP_ONCE) @@ -7456,9 +8314,13 @@ while (*cc == OP_ALT) cc += GET(cc, 1); cc += 1 + LINK_SIZE; -/* Temporarily encoding the needs_control_head in framesize. */ if (opcode == OP_ONCE) + { + /* We temporarily encode the needs_control_head in the lowest bit. + Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns + the same value for small signed numbers (including negative numbers). */ BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); + } return cc + repeat_length; } @@ -7534,20 +8396,20 @@ if (framesize < 0) BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; allocate_stack(common, stacksize); if (framesize == no_frame) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); stack = 0; if (offset != 0) { stack = 2; - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); if (common->capture_last_ptr != 0) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); if (needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); if (common->capture_last_ptr != 0) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); @@ -7557,7 +8419,7 @@ if (framesize < 0) else { if (needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); stack = 1; } @@ -7584,10 +8446,10 @@ else BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; allocate_stack(common, stacksize); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); stack = 0; if (!zero) @@ -7611,7 +8473,7 @@ else } if (offset != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); loop = LABEL(); while (*cc != OP_KETRPOS) @@ -7627,16 +8489,16 @@ while (*cc != OP_KETRPOS) if (framesize < 0) { if (framesize == no_frame) - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (offset != 0) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); if (common->capture_last_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); } else { @@ -7645,8 +8507,12 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) - add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); + add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); if (!zero) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); @@ -7655,25 +8521,29 @@ while (*cc != OP_KETRPOS) { if (offset != 0) { - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); if (common->capture_last_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); } else { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); if (opcode == OP_SBRAPOS) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) - add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); + add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); if (!zero) { @@ -7684,9 +8554,6 @@ while (*cc != OP_KETRPOS) } } - if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); - JUMPTO(SLJIT_JUMP, loop); flush_stubs(common); @@ -7698,7 +8565,7 @@ while (*cc != OP_KETRPOS) if (framesize < 0) { if (offset != 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } @@ -7708,12 +8575,12 @@ while (*cc != OP_KETRPOS) { /* Last alternative. */ if (*cc == OP_KETRPOS) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); } else { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw)); } } @@ -7729,9 +8596,9 @@ backtrack->topbacktracks = NULL; if (!zero) { if (framesize < 0) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); else /* TMP2 is set to [private_data_ptr] above. */ - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0)); } /* None of them matched. */ @@ -7740,11 +8607,13 @@ count_match(common); return cc + 1 + LINK_SIZE; } -static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *max, int *min, pcre_uchar **end) +static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, sljit_u32 *max, sljit_u32 *exact, pcre_uchar **end) { int class_len; *opcode = *cc; +*exact = 0; + if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO) { cc++; @@ -7772,7 +8641,7 @@ else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO) { cc++; *opcode -= OP_TYPESTAR - OP_STAR; - *type = 0; + *type = OP_END; } else { @@ -7781,60 +8650,105 @@ else cc++; class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); *opcode = cc[class_len - 1]; + if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) { *opcode -= OP_CRSTAR - OP_STAR; - if (end != NULL) - *end = cc + class_len; + *end = cc + class_len; + + if (*opcode == OP_PLUS || *opcode == OP_MINPLUS) + { + *exact = 1; + *opcode -= OP_PLUS - OP_STAR; + } } else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY) { *opcode -= OP_CRPOSSTAR - OP_POSSTAR; - if (end != NULL) - *end = cc + class_len; + *end = cc + class_len; + + if (*opcode == OP_POSPLUS) + { + *exact = 1; + *opcode = OP_POSSTAR; + } } else { SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE); *max = GET2(cc, (class_len + IMM2_SIZE)); - *min = GET2(cc, class_len); + *exact = GET2(cc, class_len); - if (*min == 0) + if (*max == 0) { - SLJIT_ASSERT(*max != 0); - *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : (*opcode == OP_CRMINRANGE ? OP_MINUPTO : OP_POSUPTO); + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSSTAR; + else + *opcode -= OP_CRRANGE - OP_STAR; } - if (*max == *min) - *opcode = OP_EXACT; - - if (end != NULL) - *end = cc + class_len + 2 * IMM2_SIZE; + else + { + *max -= *exact; + if (*max == 0) + *opcode = OP_EXACT; + else if (*max == 1) + { + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSQUERY; + else + *opcode -= OP_CRRANGE - OP_QUERY; + } + else + { + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSUPTO; + else + *opcode -= OP_CRRANGE - OP_UPTO; + } + } + *end = cc + class_len + 2 * IMM2_SIZE; } return cc; } -if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO) +switch(*opcode) { + case OP_EXACT: + *exact = GET2(cc, 0); + cc += IMM2_SIZE; + break; + + case OP_PLUS: + case OP_MINPLUS: + *exact = 1; + *opcode -= OP_PLUS - OP_STAR; + break; + + case OP_POSPLUS: + *exact = 1; + *opcode = OP_POSSTAR; + break; + + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: *max = GET2(cc, 0); cc += IMM2_SIZE; + break; } -if (*type == 0) +if (*type == OP_END) { *type = *cc; - if (end != NULL) - *end = next_opcode(common, cc); + *end = next_opcode(common, cc); cc++; return cc; } -if (end != NULL) - { - *end = cc + 1; +*end = cc + 1; #ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); +if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); #endif - } return cc; } @@ -7844,95 +8758,110 @@ DEFINE_COMPILER; backtrack_common *backtrack; pcre_uchar opcode; pcre_uchar type; -int max = -1, min = -1; -pcre_uchar* end; -jump_list *nomatch = NULL; +sljit_u32 max = 0, exact; +BOOL fast_fail; +sljit_s32 fast_str_ptr; +BOOL charpos_enabled; +pcre_uchar charpos_char; +unsigned int charpos_othercasebit; +pcre_uchar *end; +jump_list *no_match = NULL; +jump_list *no_char1_match = NULL; struct sljit_jump *jump = NULL; struct sljit_label *label; int private_data_ptr = PRIVATE_DATA(cc); -int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG); +int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); int tmp_base, tmp_offset; -PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); +PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL); -cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, &end); +fast_str_ptr = PRIVATE_DATA(cc + 1); +fast_fail = TRUE; -switch(type) +SLJIT_ASSERT(common->fast_forward_bc_ptr == NULL || fast_str_ptr == 0 || cc == common->fast_forward_bc_ptr); + +if (cc == common->fast_forward_bc_ptr) + fast_fail = FALSE; +else if (common->fast_fail_start_ptr == 0) + fast_str_ptr = 0; + +SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || fast_str_ptr == 0 + || (fast_str_ptr >= common->fast_fail_start_ptr && fast_str_ptr <= common->fast_fail_end_ptr)); + +cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); + +if (type != OP_EXTUNI) { - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - case OP_ANYBYTE: - case OP_ANYNL: - case OP_NOT_HSPACE: - case OP_HSPACE: - case OP_NOT_VSPACE: - case OP_VSPACE: - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - case OP_CLASS: - case OP_NCLASS: tmp_base = TMP3; tmp_offset = 0; - break; - - default: - SLJIT_ASSERT_STOP(); - /* Fall through. */ - - case OP_EXTUNI: - case OP_XCLASS: - case OP_NOTPROP: - case OP_PROP: - tmp_base = SLJIT_MEM1(SLJIT_LOCALS_REG); - tmp_offset = POSSESSIVE0; - break; } +else + { + tmp_base = SLJIT_MEM1(SLJIT_SP); + tmp_offset = POSSESSIVE0; + } + +if (fast_fail && fast_str_ptr != 0) + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), fast_str_ptr)); + +/* Handle fixed part first. */ +if (exact > 1) + { + SLJIT_ASSERT(fast_str_ptr == 0); + if (common->mode == JIT_COMPILE +#ifdef SUPPORT_UTF + && !common->utf +#endif + ) + { + OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0)); + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + } + else + { + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + } + } +else if (exact == 1) + compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); switch(opcode) { case OP_STAR: - case OP_PLUS: case OP_UPTO: - case OP_CRRANGE: + SLJIT_ASSERT(fast_str_ptr == 0 || opcode == OP_STAR); + if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); - if (opcode == OP_STAR || opcode == OP_UPTO) - { - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); - } - else - { - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } + SLJIT_ASSERT(fast_str_ptr == 0); - if (opcode == OP_UPTO || opcode == OP_CRRANGE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); + + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max); label = LABEL(); - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - if (opcode == OP_UPTO || opcode == OP_CRRANGE) + compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); + if (opcode == OP_UPTO) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - if (opcode == OP_CRRANGE && min > 0) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label); - if (opcode == OP_UPTO || (opcode == OP_CRRANGE && max > 0)) - jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + jump = JUMP(SLJIT_ZERO); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); } /* We cannot use TMP3 because of this allocate_stack. */ @@ -7944,134 +8873,268 @@ switch(opcode) } else { - if (opcode == OP_PLUS) - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - if (private_data_ptr == 0) - allocate_stack(common, 2); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - if (opcode <= OP_PLUS) + charpos_enabled = FALSE; + charpos_char = 0; + charpos_othercasebit = 0; + + if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI)) + { + charpos_enabled = TRUE; +#ifdef SUPPORT_UTF + charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]); +#endif + if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1)) + { + charpos_othercasebit = char_get_othercase_bit(common, end + 1); + if (charpos_othercasebit == 0) + charpos_enabled = FALSE; + } + + if (charpos_enabled) + { + charpos_char = end[1]; + /* Consumpe the OP_CHAR opcode. */ + end += 2; +#if defined COMPILE_PCRE8 + SLJIT_ASSERT((charpos_othercasebit >> 8) == 0); +#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 + SLJIT_ASSERT((charpos_othercasebit >> 9) == 0); + if ((charpos_othercasebit & 0x100) != 0) + charpos_othercasebit = (charpos_othercasebit & 0xff) << 8; +#endif + if (charpos_othercasebit != 0) + charpos_char |= charpos_othercasebit; + + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE; + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char; + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit; + } + } + + if (charpos_enabled) + { + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1); + + /* Search the first instance of charpos_char. */ + jump = JUMP(SLJIT_JUMP); + label = LABEL(); + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO)); + } + compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + JUMPHERE(jump); + + detect_partial_match(common, &backtrack->topbacktracks); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (charpos_othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); + + if (private_data_ptr == 0) + allocate_stack(common, 2); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); - else - OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - if (opcode <= OP_PLUS) - JUMPTO(SLJIT_JUMP, label); - else if (opcode == OP_CRRANGE && max == 0) - { - OP2(SLJIT_ADD, base, offset1, base, offset1, SLJIT_IMM, 1); - JUMPTO(SLJIT_JUMP, label); + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); + } + + /* Search the last instance of charpos_char. */ + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &no_match, FALSE); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + detect_partial_match(common, &no_match); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (charpos_othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); + if (opcode == OP_STAR) + { + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + } + else + { + jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPHERE(jump); + } + + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + } + else + JUMPTO(SLJIT_JUMP, label); + + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 + else if (common->utf) + { + if (private_data_ptr == 0) + allocate_stack(common, 2); + + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); + + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); + + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &no_match, TRUE); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + } + else + JUMPTO(SLJIT_JUMP, label); + + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + } +#endif else { - OP1(SLJIT_MOV, TMP1, 0, base, offset1); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, base, offset1, TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, max + 1, label); + if (private_data_ptr == 0) + allocate_stack(common, 2); + + OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); + + label = LABEL(); + detect_partial_match(common, &no_match); + compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } + else + JUMPTO(SLJIT_JUMP, label); + + set_jumps(no_char1_match, LABEL()); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); } - set_jumps(nomatch, LABEL()); - if (opcode == OP_CRRANGE) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, base, offset1, SLJIT_IMM, min + 1)); - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); } - BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_MINSTAR: - case OP_MINPLUS: - if (opcode == OP_MINPLUS) - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); break; case OP_MINUPTO: - case OP_CRMINRANGE: + SLJIT_ASSERT(fast_str_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1); - if (opcode == OP_CRMINRANGE) - add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); - BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); + OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_QUERY: case OP_MINQUERY: + SLJIT_ASSERT(fast_str_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); if (opcode == OP_QUERY) - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL(); + compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_EXACT: - OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); break; case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSUPTO: - if (opcode == OP_POSPLUS) - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - if (opcode == OP_POSUPTO) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, max); - OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - if (opcode != OP_POSUPTO) - JUMPTO(SLJIT_JUMP, label); - else +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 + if (common->utf) { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); + OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &no_match, TRUE); + OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + break; } - set_jumps(nomatch, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); +#endif + label = LABEL(); + detect_partial_match(common, &no_match); + compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); + JUMPTO(SLJIT_JUMP, label); + set_jumps(no_char1_match, LABEL()); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_match, LABEL()); + if (fast_str_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + break; + + case OP_POSUPTO: + SLJIT_ASSERT(fast_str_ptr == 0); +#if defined SUPPORT_UTF && !defined COMPILE_PCRE32 + if (common->utf) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &no_match, TRUE); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); + break; + } +#endif + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); + label = LABEL(); + detect_partial_match(common, &no_match); + compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); + OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_char1_match, LABEL()); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_match, LABEL()); break; case OP_POSQUERY: + SLJIT_ASSERT(fast_str_ptr == 0); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - compile_char1_matchingpath(common, type, cc, &nomatch); + compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - set_jumps(nomatch, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); - break; - - case OP_CRPOSRANGE: - /* Combination of OP_EXACT and OP_POSSTAR or OP_POSUPTO */ - OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, min); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); - - if (max != 0) - { - SLJIT_ASSERT(max - min > 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, max - min); - } - OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - if (max == 0) - JUMPTO(SLJIT_JUMP, label); - else - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); - } - set_jumps(nomatch, LABEL()); + set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); break; @@ -8108,22 +9171,22 @@ if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be } if (common->accept_label == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0))); + add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0))); else - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->accept_label); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); -add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); +OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); +add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); +OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); if (common->accept_label == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + add_jump(compiler, &common->accept, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); else - CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label); + CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); if (common->accept_label == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); + add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); else - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); return cc + 1; } @@ -8139,11 +9202,11 @@ if (common->currententry != NULL) return cc + 1 + IMM2_SIZE; if (!optimized_cbracket) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset)); offset <<= 1; -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); if (!optimized_cbracket) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); return cc + 1 + IMM2_SIZE; } @@ -8170,7 +9233,7 @@ if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG) { OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); } @@ -8195,12 +9258,12 @@ BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, size = BACKTRACK_AS(then_trap_backtrack)->framesize; size = 3 + (size < 0 ? 0 : size); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); allocate_stack(common, size); if (size > 3) - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); else - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); @@ -8236,6 +9299,16 @@ while (cc < ccend) case OP_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: + case OP_EODN: + case OP_EOD: + case OP_DOLL: + case OP_DOLLM: + case OP_CIRC: + case OP_CIRCM: + case OP_REVERSE: + cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); + break; + case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: @@ -8253,23 +9326,16 @@ while (cc < ccend) case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: - case OP_EODN: - case OP_EOD: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: case OP_NOT: case OP_NOTI: - case OP_REVERSE: - cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); + cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; case OP_SET_SOM: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); cc++; break; @@ -8279,7 +9345,7 @@ while (cc < ccend) if (common->mode == JIT_COMPILE) cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); else - cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); + cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; case OP_STAR: @@ -8355,7 +9421,7 @@ while (cc < ccend) if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE) cc = compile_iterator_matchingpath(common, cc, parent); else - cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); + cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 @@ -8363,7 +9429,7 @@ while (cc < ccend) if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE) cc = compile_iterator_matchingpath(common, cc, parent); else - cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); + cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; #endif @@ -8421,8 +9487,7 @@ while (cc < ccend) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); } BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL(); - if (cc[1] > OP_ASSERTBACK_NOT) - count_match(common); + count_match(common); break; case OP_ONCE: @@ -8457,17 +9522,17 @@ while (cc < ccend) case OP_MARK: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); SLJIT_ASSERT(common->mark_ptr != 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); allocate_stack(common, common->has_skip_arg ? 5 : 1); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); if (common->has_skip_arg) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0); @@ -8540,95 +9605,82 @@ DEFINE_COMPILER; pcre_uchar *cc = current->cc; pcre_uchar opcode; pcre_uchar type; -int max = -1, min = -1; +sljit_u32 max = 0, exact; struct sljit_label *label = NULL; struct sljit_jump *jump = NULL; jump_list *jumplist = NULL; +pcre_uchar *end; int private_data_ptr = PRIVATE_DATA(cc); -int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG); +int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); -cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, NULL); +cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); switch(opcode) { case OP_STAR: - case OP_PLUS: case OP_UPTO: - case OP_CRRANGE: if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); - set_jumps(current->topbacktracks, LABEL()); + set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); } else { - if (opcode == OP_UPTO) - min = 0; - if (opcode <= OP_PLUS) + if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled) { OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - jump = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, base, offset1); + OP1(SLJIT_MOV, TMP2, 0, base, offset1); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + + jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); + label = LABEL(); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath); + skip_char_back(common); + CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label); } else { - OP1(SLJIT_MOV, TMP1, 0, base, offset1); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, min + 1); - OP2(SLJIT_SUB, base, offset1, TMP1, 0, SLJIT_IMM, 1); + jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1); + skip_char_back(common); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); } - skip_char_back(common); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath); - if (opcode == OP_CRRANGE) - set_jumps(current->topbacktracks, LABEL()); JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 2); - if (opcode == OP_PLUS) - set_jumps(current->topbacktracks, LABEL()); } break; case OP_MINSTAR: - case OP_MINPLUS: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - compile_char1_matchingpath(common, type, cc, &jumplist); + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) free_stack(common, 1); - if (opcode == OP_MINPLUS) - set_jumps(current->topbacktracks, LABEL()); break; case OP_MINUPTO: - case OP_CRMINRANGE: - if (opcode == OP_CRMINRANGE) - { - label = LABEL(); - set_jumps(current->topbacktracks, label); - } - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - compile_char1_matchingpath(common, type, cc, &jumplist); - OP1(SLJIT_MOV, TMP1, 0, base, offset1); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO)); + OP1(SLJIT_MOV, base, offset1, TMP1, 0); - - if (opcode == OP_CRMINRANGE) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min + 1, label); - - if (opcode == OP_CRMINRANGE && max == 0) - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath); - else - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, max + 2, CURRENT_AS(iterator_backtrack)->matchingpath); + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) @@ -8638,12 +9690,12 @@ switch(opcode) case OP_QUERY: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); jump = JUMP(SLJIT_JUMP); - set_jumps(current->topbacktracks, LABEL()); + set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 1); @@ -8652,9 +9704,9 @@ switch(opcode) case OP_MINQUERY: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); - jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - compile_char1_matchingpath(common, type, cc, &jumplist); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath); + jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); JUMPHERE(jump); if (private_data_ptr == 0) @@ -8662,11 +9714,6 @@ switch(opcode) break; case OP_EXACT: - case OP_POSPLUS: - case OP_CRPOSRANGE: - set_jumps(current->topbacktracks, LABEL()); - break; - case OP_POSSTAR: case OP_POSQUERY: case OP_POSUPTO: @@ -8676,6 +9723,8 @@ switch(opcode) SLJIT_ASSERT_STOP(); break; } + +set_jumps(current->topbacktracks, LABEL()); } static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -8693,12 +9742,12 @@ if ((type & 0x1) == 0) set_jumps(current->topbacktracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath); return; } OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); -CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath); +CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath); set_jumps(current->topbacktracks, LABEL()); free_stack(common, ref ? 2 : 3); } @@ -8718,14 +9767,14 @@ if (common->has_set_som && common->mark_ptr != 0) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0); } else if (common->has_set_som || common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); } } @@ -8756,7 +9805,7 @@ if (CURRENT_AS(assert_backtrack)->framesize < 0) if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); free_stack(common, 1); } return; @@ -8767,19 +9816,19 @@ if (bra == OP_BRAZERO) if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); free_stack(common, 1); return; } free_stack(common, 1); - brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw)); set_jumps(current->topbacktracks, LABEL()); } @@ -8809,6 +9858,7 @@ pcre_uchar *ccprev; pcre_uchar bra = OP_BRA; pcre_uchar ket; assert_backtrack *assert; +sljit_uw *next_update_addr = NULL; BOOL has_alternatives; BOOL needs_control_head = FALSE; struct sljit_jump *brazero = NULL; @@ -8866,9 +9916,9 @@ if (ket != OP_KET && repeat_type != 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); if (repeat_type == OP_UPTO) - OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1); else - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0); } if (ket == OP_KETRMAX) @@ -8877,7 +9927,7 @@ if (ket == OP_KETRMAX) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0); + brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0); } } else if (ket == OP_KETRMIN) @@ -8888,7 +9938,7 @@ else if (ket == OP_KETRMIN) if (repeat_type != 0) { /* TMP1 was set a few lines above. */ - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); /* Drop STR_PTR for non-greedy plus quantifier. */ if (opcode != OP_ONCE) free_stack(common, 1); @@ -8897,11 +9947,11 @@ else if (ket == OP_KETRMIN) { /* Checking zero-length iteration. */ if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); else { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); } /* Drop STR_PTR for non-greedy plus quantifier. */ if (opcode != OP_ONCE) @@ -8912,17 +9962,17 @@ else if (ket == OP_KETRMIN) } rmin_label = LABEL(); if (repeat_type != 0) - OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); + OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); } else if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); + brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); } else if (repeat_type == OP_EXACT) { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); exact_label = LABEL(); } @@ -8933,19 +9983,19 @@ if (offset != 0) SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); free_stack(common, 3); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); } else if (common->optimized_cbracket[offset >> 1] == 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); } } @@ -8953,7 +10003,7 @@ if (SLJIT_UNLIKELY(opcode == OP_ONCE)) { if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } once = JUMP(SLJIT_JUMP); @@ -8967,7 +10017,7 @@ else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND) free_stack(common, 1); alt_max = 2; - alt1 = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); + alt1 = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); } } else if (has_alternatives) @@ -8978,14 +10028,17 @@ else if (has_alternatives) if (alt_max > 4) { /* Table jump if alt_max is greater than 4. */ - sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)common->read_only_data_ptr); - add_label_addr(common); + next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw)); + if (SLJIT_UNLIKELY(next_update_addr == NULL)) + return; + sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr); + add_label_addr(common, next_update_addr++); } else { if (alt_max == 4) - alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); - alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); + alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); + alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); } } @@ -9002,9 +10055,9 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) assert = CURRENT_AS(bracket_backtrack)->u.assert; if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); } cond = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); @@ -9037,7 +10090,7 @@ if (has_alternatives) if (opcode != OP_ONCE) { if (private_data_ptr != 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } @@ -9058,7 +10111,7 @@ if (has_alternatives) if (repeat_type == OP_MINUPTO) { /* We need to preserve the counter. TMP2 will be used below. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); stacksize++; } if (ket != OP_KET || bra != OP_BRA) @@ -9103,7 +10156,7 @@ if (has_alternatives) { /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); } JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath); @@ -9111,20 +10164,20 @@ if (has_alternatives) if (opcode != OP_ONCE) { if (alt_max > 4) - add_label_addr(common); + add_label_addr(common, next_update_addr++); else { if (alt_count != 2 * sizeof(sljit_uw)) { JUMPHERE(alt1); if (alt_max == 3 && alt_count == sizeof(sljit_uw)) - alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); + alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); } else { JUMPHERE(alt2); if (alt_max == 4) - alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw)); + alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw)); } } alt_count += sizeof(sljit_uw); @@ -9143,9 +10196,9 @@ if (has_alternatives) assert = CURRENT_AS(bracket_backtrack)->u.assert; if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); } JUMPHERE(cond); } @@ -9163,19 +10216,19 @@ if (offset != 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); } else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } } else if (opcode == OP_SBRA || opcode == OP_SCOND) { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); } else if (opcode == OP_ONCE) @@ -9193,26 +10246,28 @@ else if (opcode == OP_ONCE) /* The STR_PTR must be released. */ stacksize++; } - free_stack(common, stacksize); + + if (stacksize > 0) + free_stack(common, stacksize); JUMPHERE(once); /* Restore previous private_data_ptr */ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw)); else if (ket == OP_KETRMIN) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); /* See the comment below. */ free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } } if (repeat_type == OP_EXACT) { - OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0); - CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label); + OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0); + CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label); } else if (ket == OP_KETRMAX) { @@ -9220,7 +10275,7 @@ else if (ket == OP_KETRMAX) if (bra != OP_BRAZERO) free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); @@ -9238,7 +10293,7 @@ else if (ket == OP_KETRMIN) affect badly the free_stack(2) above. */ if (opcode != OP_ONCE) free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label); if (opcode == OP_ONCE) free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); else if (bra == OP_BRAMINZERO) @@ -9265,19 +10320,19 @@ if (CURRENT_AS(bracketpos_backtrack)->framesize < 0) offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); if (common->capture_last_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0); } set_jumps(current->topbacktracks, LABEL()); free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); return; } -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); if (current->topbacktracks) @@ -9288,7 +10343,7 @@ if (current->topbacktracks) free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); JUMPHERE(jump); } -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw)); } static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -9328,7 +10383,7 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG) { SLJIT_ASSERT(common->control_head_ptr != 0); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start); jump = JUMP(SLJIT_JUMP); @@ -9336,8 +10391,8 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG) loop = LABEL(); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw)); JUMPHERE(jump); - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop); - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop); add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); return; } @@ -9360,14 +10415,14 @@ if (common->local_exit) if (opcode == OP_SKIP_ARG) { SLJIT_ASSERT(common->control_head_ptr != 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); - add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); + add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); return; } @@ -9405,7 +10460,7 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 3); JUMPHERE(jump); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0); } static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -9422,7 +10477,7 @@ while (current) case OP_SET_SOM: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0); break; case OP_STAR: @@ -9551,9 +10606,9 @@ while (current) if (common->has_skip_arg) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, common->has_skip_arg ? 5 : 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0); if (common->has_skip_arg) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0); break; case OP_THEN: @@ -9600,7 +10655,7 @@ static SLJIT_INLINE void compile_recurse(compiler_common *common) DEFINE_COMPILER; pcre_uchar *cc = common->start + common->currententry->start; pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); -pcre_uchar *ccend = bracketend(cc); +pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE); BOOL needs_control_head; int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head); int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head); @@ -9623,12 +10678,13 @@ common->currententry->entry = LABEL(); set_jumps(common->currententry->calls, common->currententry->entry); sljit_emit_fast_enter(compiler, TMP2, 0); +count_match(common); allocate_stack(common, private_data_size + framesize + alternativesize); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0); if (needs_frame) init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE); @@ -9675,7 +10731,7 @@ jump = JUMP(SLJIT_JUMP); if (common->quit != NULL) { set_jumps(common->quit, LABEL()); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); if (needs_frame) { OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); @@ -9688,7 +10744,7 @@ if (common->quit != NULL) } set_jumps(common->accept, LABEL()); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); if (needs_frame) { OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); @@ -9706,15 +10762,15 @@ if (needs_control_head) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0); } else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0); } sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); } @@ -9729,7 +10785,7 @@ struct sljit_compiler *compiler; backtrack_common rootbacktrack; compiler_common common_data; compiler_common *common = &common_data; -const pcre_uint8 *tables = re->tables; +const sljit_u8 *tables = re->tables; pcre_study_data *study; int private_data_size; pcre_uchar *ccend; @@ -9760,9 +10816,7 @@ memset(common, 0, sizeof(compiler_common)); rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; common->start = rootbacktrack.cc; -common->read_only_data = NULL; -common->read_only_data_size = 0; -common->read_only_data_ptr = NULL; +common->read_only_data_head = NULL; common->fcc = tables + fcc_offset; common->lcc = (sljit_sw)(tables + lcc_offset); common->mode = mode; @@ -9843,7 +10897,7 @@ ccend = bracketend(common->start); /* Calculate the local space size on the stack. */ common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw); -common->optimized_cbracket = (pcre_uint8 *)SLJIT_MALLOC(re->top_bracket + 1); +common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data); if (!common->optimized_cbracket) return; #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1 @@ -9859,7 +10913,7 @@ common->ovector_start += sizeof(sljit_sw); #endif if (!check_opcode_types(common, common->start, ccend)) { - SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } @@ -9878,15 +10932,10 @@ if (mode != JIT_COMPILE) common->hit_start = common->ovector_start; common->ovector_start += 2 * sizeof(sljit_sw); } - else - { - SLJIT_ASSERT(mode == JIT_PARTIAL_HARD_COMPILE); - common->needs_start_ptr = TRUE; - } } if ((re->options & PCRE_FIRSTLINE) != 0) { - common->first_line_end = common->ovector_start; + common->match_end_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD @@ -9897,14 +10946,12 @@ if (common->control_head_ptr != 0) common->control_head_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } -if (common->needs_start_ptr && common->has_set_som) +if (common->has_set_som) { /* Saving the real start pointer is necessary. */ common->start_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } -else - common->needs_start_ptr = FALSE; /* Aligning ovector to even number of sljit words. */ if ((common->ovector_start & sizeof(sljit_sw)) != 0) @@ -9921,103 +10968,92 @@ SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); total_length = ccend - common->start; -common->private_data_ptrs = (sljit_si *)SLJIT_MALLOC(total_length * (sizeof(sljit_si) + (common->has_then ? 1 : 0))); +common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), compiler->allocator_data); if (!common->private_data_ptrs) { - SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } -memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_si)); +memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32)); private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); set_private_data_ptrs(common, &private_data_size, ccend); +if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) + { + if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back) + detect_fast_fail(common, common->start, &private_data_size, 4); + } + +SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr); + if (private_data_size > SLJIT_MAX_LOCAL_SIZE) { - SLJIT_FREE(common->private_data_ptrs); - SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } if (common->has_then) { - common->then_offsets = (pcre_uint8 *)(common->private_data_ptrs + total_length); + common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length); memset(common->then_offsets, 0, total_length); set_then_offsets(common, common->start, NULL); } -if (common->read_only_data_size > 0) - { - common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size); - if (common->read_only_data == NULL) - { - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - return; - } - common->read_only_data_ptr = common->read_only_data; - } - -compiler = sljit_create_compiler(); +compiler = sljit_create_compiler(NULL); if (!compiler) { - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); + SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); return; } common->compiler = compiler; /* Main pcre_jit_exec entry. */ -sljit_emit_enter(compiler, 1, 5, 5, private_data_size); +sljit_emit_enter(compiler, 0, 1, 5, 5, 0, 0, private_data_size); /* Register init. */ reset_ovector(common, (re->top_bracket + 1) * 2); if (common->req_char_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_SCRATCH_REG1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0); -OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0); +OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_S0, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); +OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH, TMP1, 0); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); + +if (common->fast_fail_start_ptr < common->fast_fail_end_ptr) + reset_fast_fail(common); if (mode == JIT_PARTIAL_SOFT_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1); if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0); if (common->control_head_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); /* Main part of the matching */ if ((re->options & PCRE_ANCHORED) == 0) { - mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); + mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0); continue_match_label = LABEL(); /* Forward search if possible. */ if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) { - if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0)) - { - /* If read_only_data is reallocated, we might have an allocation failure. */ - if (common->read_only_data_size > 0 && common->read_only_data == NULL) - { - sljit_free_compiler(compiler); - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - return; - } - } + if (mode == JIT_COMPILE && fast_forward_first_n_chars(common)) + ; else if ((re->flags & PCRE_FIRSTSET) != 0) - fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); + fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0); else if ((re->flags & PCRE_STARTLINE) != 0) - fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0); - else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) - fast_forward_start_bits(common, study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); + fast_forward_newline(common); + else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) + fast_forward_start_bits(common, study->start_bits); } } else @@ -10027,51 +11063,47 @@ if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_ { OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); - minlength_check_failed = CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0); + minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0); } if (common->req_char_ptr != 0) reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); /* Store the current STR_PTR in OVECTOR(0). */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0); /* Copy the limit of allowed recursions. */ -OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH); +OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH); if (common->capture_last_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1); +if (common->fast_forward_bc_ptr != NULL) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0); -if (common->needs_start_ptr) - { - SLJIT_ASSERT(common->start_ptr != OVECTOR(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr, STR_PTR, 0); - } -else - SLJIT_ASSERT(common->start_ptr == OVECTOR(0)); +if (common->start_ptr != OVECTOR(0)) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0); /* Copy the beginning of the string. */ if (mode == JIT_PARTIAL_SOFT_COMPILE) { - jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start + sizeof(sljit_sw), STR_PTR, 0); + jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start + sizeof(sljit_sw), STR_PTR, 0); JUMPHERE(jump); } else if (mode == JIT_PARTIAL_HARD_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); compile_matchingpath(common, common->start, ccend, &rootbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); + SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); + free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } if (common->might_be_empty) { - empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); empty_match_found_label = LABEL(); } @@ -10103,10 +11135,9 @@ compile_backtrackingpath(common, rootbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); + SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); + free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } @@ -10116,37 +11147,33 @@ reset_match_label = LABEL(); if (mode == JIT_PARTIAL_SOFT_COMPILE) { /* Update hit_start only in the first time. */ - jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0); + jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0); JUMPHERE(jump); } /* Check we have remaining characters. */ if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0) { - SLJIT_ASSERT(common->first_line_end != 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); + SLJIT_ASSERT(common->match_end_ptr != 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), + (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr); if ((re->options & PCRE_ANCHORED) == 0) { if (common->ff_newline_shortcut != NULL) { if ((re->options & PCRE_FIRSTLINE) == 0) - CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut); + CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut); /* There cannot be more newlines here. */ } else - { - if ((re->options & PCRE_FIRSTLINE) == 0) - CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop_label); - else - CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop_label); - } + CMPTO(SLJIT_LESS, STR_PTR, 0, ((re->options & PCRE_FIRSTLINE) == 0) ? STR_END : TMP1, 0, mainloop_label); } /* No more remaining characters. */ @@ -10154,7 +11181,7 @@ if (reqbyte_notfound != NULL) JUMPHERE(reqbyte_notfound); if (mode == JIT_PARTIAL_SOFT_COMPILE) - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); JUMPTO(SLJIT_JUMP, common->quit_label); @@ -10165,15 +11192,18 @@ if (common->might_be_empty) { JUMPHERE(empty_match); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); - CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label); + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); + CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label); JUMPTO(SLJIT_JUMP, empty_match_backtrack_label); } +common->fast_forward_bc_ptr = NULL; +common->fast_fail_start_ptr = 0; +common->fast_fail_end_ptr = 0; common->currententry = common->entries; common->local_exit = TRUE; quit_label = common->quit_label; @@ -10184,10 +11214,9 @@ while (common->currententry != NULL) if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); - SLJIT_FREE(common->optimized_cbracket); - SLJIT_FREE(common->private_data_ptrs); - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); + SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); + free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } flush_stubs(common); @@ -10200,21 +11229,21 @@ common->quit_label = quit_label; /* This is a (really) rare case. */ set_jumps(common->stackalloc, LABEL()); /* RETURN_ADDR is not a saved register. */ -sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0); OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); -jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); +jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit)); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); -sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); /* Allocation failed. */ JUMPHERE(jump); @@ -10266,7 +11295,7 @@ if (common->reset_match != NULL) { set_jumps(common->reset_match, LABEL()); do_reset_match(common, (re->top_bracket + 1) * 2); - CMPTO(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label); + CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); JUMPTO(SLJIT_JUMP, reset_match_label); } @@ -10297,23 +11326,21 @@ if (common->getucd != NULL) } #endif -SLJIT_ASSERT(common->read_only_data + (common->read_only_data_size >> SLJIT_WORD_SHIFT) == common->read_only_data_ptr); -SLJIT_FREE(common->optimized_cbracket); -SLJIT_FREE(common->private_data_ptrs); +SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); +SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); executable_func = sljit_generate_code(compiler); executable_size = sljit_get_generated_code_size(compiler); label_addr = common->label_addrs; while (label_addr != NULL) { - *label_addr->addr = sljit_get_label_addr(label_addr->label); + *label_addr->update_addr = sljit_get_label_addr(label_addr->label); label_addr = label_addr->next; } sljit_free_compiler(compiler); if (executable_func == NULL) { - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } @@ -10331,14 +11358,13 @@ else * bit remains set, as the bit indicates that the pointer to the data * is valid.) */ - functions = SLJIT_MALLOC(sizeof(executable_functions)); + functions = SLJIT_MALLOC(sizeof(executable_functions), compiler->allocator_data); if (functions == NULL) { /* This case is highly unlikely since we just recently freed a lot of memory. Not impossible though. */ sljit_free_code(executable_func); - if (common->read_only_data) - SLJIT_FREE(common->read_only_data); + free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } memset(functions, 0, sizeof(executable_functions)); @@ -10349,17 +11375,17 @@ else } functions->executable_funcs[mode] = executable_func; -functions->read_only_data[mode] = common->read_only_data; +functions->read_only_data_heads[mode] = common->read_only_data_head; functions->executable_sizes[mode] = executable_size; } -static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func) +static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, void *executable_func) { union { - void* executable_func; + void *executable_func; jit_function call_executable_func; } convert_executable_func; -pcre_uint8 local_space[MACHINE_STACK_SIZE]; +sljit_u8 local_space[MACHINE_STACK_SIZE]; struct sljit_stack local_stack; local_stack.top = (sljit_sw)&local_space; @@ -10377,7 +11403,7 @@ PRIV(jit_exec)(const PUBL(extra) *extra_data, const pcre_uchar *subject, { executable_functions *functions = (executable_functions *)extra_data->executable_jit; union { - void* executable_func; + void *executable_func; jit_function call_executable_func; } convert_executable_func; jit_arguments arguments; @@ -10399,7 +11425,7 @@ arguments.begin = subject; arguments.end = subject + length; arguments.mark_ptr = NULL; /* JIT decreases this value less frequently than the interpreter. */ -arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit); +arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit); if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match) arguments.limit_match = functions->limit_match; arguments.notbol = (options & PCRE_NOTBOL) != 0; @@ -10464,7 +11490,7 @@ pcre32_jit_exec(const pcre32 *argument_re, const pcre32_extra *extra_data, pcre_uchar *subject_ptr = (pcre_uchar *)subject; executable_functions *functions = (executable_functions *)extra_data->executable_jit; union { - void* executable_func; + void *executable_func; jit_function call_executable_func; } convert_executable_func; jit_arguments arguments; @@ -10492,7 +11518,7 @@ arguments.begin = subject_ptr; arguments.end = subject_ptr + length; arguments.mark_ptr = NULL; /* JIT decreases this value less frequently than the interpreter. */ -arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit); +arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit); if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match) arguments.limit_match = functions->limit_match; arguments.notbol = (options & PCRE_NOTBOL) != 0; @@ -10536,10 +11562,9 @@ for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) { if (functions->executable_funcs[i] != NULL) sljit_free_code(functions->executable_funcs[i]); - if (functions->read_only_data[i] != NULL) - SLJIT_FREE(functions->read_only_data[i]); + free_read_only_data(functions->read_only_data_heads[i], NULL); } -SLJIT_FREE(functions); +SLJIT_FREE(functions, compiler->allocator_data); } int @@ -10576,7 +11601,7 @@ if (startsize > maxsize) startsize = maxsize; startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); -return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize); +return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize, NULL); } #if defined COMPILE_PCRE8 @@ -10590,7 +11615,7 @@ PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *stack) #endif { -sljit_free_stack((struct sljit_stack *)stack); +sljit_free_stack((struct sljit_stack *)stack, NULL); } #if defined COMPILE_PCRE8 diff --git a/Foundation/src/pcre_study.c b/Foundation/src/pcre_study.c index 4db349809..3facd6fb8 100644 --- a/Foundation/src/pcre_study.c +++ b/Foundation/src/pcre_study.c @@ -67,7 +67,8 @@ Arguments: code pointer to start of group (the bracket) startcode pointer to start of the whole pattern's code options the compiling options - int RECURSE depth + recurses chain of recurse_check to catch mutual recursion + countptr pointer to call count (to catch over complexity) Returns: the minimum length -1 if \C in UTF-8 mode or (*ACCEPT) was encountered @@ -77,15 +78,19 @@ Returns: the minimum length static int find_minlength(const REAL_PCRE *re, const pcre_uchar *code, - const pcre_uchar *startcode, int options, int recurse_depth) + const pcre_uchar *startcode, int options, recurse_check *recurses, + int *countptr) { int length = -1; /* PCRE_UTF16 has the same value as PCRE_UTF8. */ BOOL utf = (options & PCRE_UTF8) != 0; BOOL had_recurse = FALSE; +recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; +if ((*countptr)++ > 1000) return -1; /* too complex */ + if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; @@ -127,7 +132,7 @@ for (;;) case OP_SBRAPOS: case OP_ONCE: case OP_ONCE_NC: - d = find_minlength(re, cc, startcode, options, recurse_depth); + d = find_minlength(re, cc, startcode, options, recurses, countptr); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -390,7 +395,7 @@ for (;;) ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0)); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); - if (cc > cs && cc < ce) + if (cc > cs && cc < ce) /* Simple recursion */ { d = 0; had_recurse = TRUE; @@ -398,8 +403,23 @@ for (;;) } else { - int dd = find_minlength(re, cs, startcode, options, recurse_depth); - if (dd < d) d = dd; + recurse_check *r = recurses; + for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; + if (r != NULL) /* Mutual recursion */ + { + d = 0; + had_recurse = TRUE; + break; + } + else + { + int dd; + this_recurse.prev = recurses; + this_recurse.group = cs; + dd = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); + if (dd < d) d = dd; + } } slot += re->name_entry_size; } @@ -415,14 +435,27 @@ for (;;) ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1)); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); - if (cc > cs && cc < ce) + if (cc > cs && cc < ce) /* Simple recursion */ { d = 0; had_recurse = TRUE; } else { - d = find_minlength(re, cs, startcode, options, recurse_depth); + recurse_check *r = recurses; + for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; + if (r != NULL) /* Mutual recursion */ + { + d = 0; + had_recurse = TRUE; + } + else + { + this_recurse.prev = recurses; + this_recurse.group = cs; + d = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); + } } } else d = 0; @@ -471,12 +504,21 @@ for (;;) case OP_RECURSE: cs = ce = (pcre_uchar *)startcode + GET(cc, 1); do ce += GET(ce, 1); while (*ce == OP_ALT); - if ((cc > cs && cc < ce) || recurse_depth > 10) + if (cc > cs && cc < ce) /* Simple recursion */ had_recurse = TRUE; else { - branchlength += find_minlength(re, cs, startcode, options, - recurse_depth + 1); + recurse_check *r = recurses; + for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; + if (r != NULL) /* Mutual recursion */ + had_recurse = TRUE; + else + { + this_recurse.prev = recurses; + this_recurse.group = cs; + branchlength += find_minlength(re, cs, startcode, options, + &this_recurse, countptr); + } } cc += 1 + LINK_SIZE; break; @@ -860,7 +902,6 @@ do case OP_NOTUPTOI: case OP_NOT_HSPACE: case OP_NOT_VSPACE: - case OP_PROP: case OP_PRUNE: case OP_PRUNE_ARG: case OP_RECURSE: @@ -878,6 +919,31 @@ do case OP_THEN_ARG: return SSB_FAIL; + /* A "real" property test implies no starting bits, but the fake property + PT_CLIST identifies a list of characters. These lists are short, as they + are used for characters with more than one "other case", so there is no + point in recognizing them for OP_NOTPROP. */ + + case OP_PROP: + if (tcode[1] != PT_CLIST) return SSB_FAIL; + { + const pcre_uint32 *p = PRIV(ucd_caseless_sets) + tcode[2]; + while ((c = *p++) < NOTACHAR) + { +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 + if (utf) + { + pcre_uchar buff[6]; + (void)PRIV(ord2utf)(c, buff); + c = buff[0]; + } +#endif + if (c > 0xff) SET_BIT(0xff); else SET_BIT(c); + } + } + try_next = FALSE; + break; + /* We can ignore word boundary tests. */ case OP_WORD_BOUNDARY: @@ -1103,24 +1169,17 @@ do try_next = FALSE; break; - /* The cbit_space table has vertical tab as whitespace; we have to - ensure it is set as not whitespace. Luckily, the code value is the same - (0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate bit. */ + /* The cbit_space table has vertical tab as whitespace; we no longer + have to play fancy tricks because Perl added VT to its whitespace at + release 5.18. PCRE added it at release 8.34. */ case OP_NOT_WHITESPACE: set_nottype_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] |= 0x08; try_next = FALSE; break; - /* The cbit_space table has vertical tab as whitespace; we have to not - set it from the table. Luckily, the code value is the same (0x0b) in - ASCII and EBCDIC, so we can just adjust the appropriate bit. */ - case OP_WHITESPACE: - c = start_bits[1]; /* Save in case it was already set */ set_type_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] = (start_bits[1] & ~0x08) | c; try_next = FALSE; break; @@ -1309,7 +1368,7 @@ do for (c = 0; c < 16; c++) start_bits[c] |= map[c]; for (c = 128; c < 256; c++) { - if ((map[c/8] && (1 << (c&7))) != 0) + if ((map[c/8] & (1 << (c&7))) != 0) { int d = (c >> 6) | 0xc0; /* Set bit for this starter */ start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ @@ -1397,6 +1456,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr) #endif { int min; +int count = 0; BOOL bits_set = FALSE; pcre_uint8 start_bits[32]; PUBL(extra) *extra = NULL; @@ -1483,7 +1543,7 @@ if ((re->options & PCRE_ANCHORED) == 0 && /* Find the minimum length of subject string. */ -switch(min = find_minlength(re, code, code, re->options, 0)) +switch(min = find_minlength(re, code, code, re->options, NULL, &count)) { case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; case -3: *errorptr = "internal error: opcode not recognized"; return NULL; diff --git a/Foundation/src/pcre_tables.c b/Foundation/src/pcre_tables.c index 50bce1732..5786f0074 100644 --- a/Foundation/src/pcre_tables.c +++ b/Foundation/src/pcre_tables.c @@ -209,6 +209,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0" #define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0" #define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0" +#define STRING_Bassa_Vah0 STR_B STR_a STR_s STR_s STR_a STR_UNDERSCORE STR_V STR_a STR_h "\0" #define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0" #define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0" #define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0" @@ -219,6 +220,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_C0 STR_C "\0" #define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0" #define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0" +#define STRING_Caucasian_Albanian0 STR_C STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0" #define STRING_Cc0 STR_C STR_c "\0" #define STRING_Cf0 STR_C STR_f "\0" #define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0" @@ -234,11 +236,14 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0" #define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0" #define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0" +#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0" #define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" +#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0" #define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0" #define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0" #define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0" #define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0" +#define STRING_Grantha0 STR_G STR_r STR_a STR_n STR_t STR_h STR_a "\0" #define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0" #define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0" #define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0" @@ -258,12 +263,15 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0" #define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0" #define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0" +#define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0" +#define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0" #define STRING_L0 STR_L "\0" #define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0" #define STRING_Lao0 STR_L STR_a STR_o "\0" #define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0" #define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0" #define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0" +#define STRING_Linear_A0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_A "\0" #define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0" #define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0" #define STRING_Ll0 STR_L STR_l "\0" @@ -274,18 +282,24 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0" #define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0" #define STRING_M0 STR_M "\0" +#define STRING_Mahajani0 STR_M STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0" #define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0" #define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0" +#define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0" #define STRING_Mc0 STR_M STR_c "\0" #define STRING_Me0 STR_M STR_e "\0" #define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0" +#define STRING_Mende_Kikakui0 STR_M STR_e STR_n STR_d STR_e STR_UNDERSCORE STR_K STR_i STR_k STR_a STR_k STR_u STR_i "\0" #define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0" #define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" #define STRING_Miao0 STR_M STR_i STR_a STR_o "\0" #define STRING_Mn0 STR_M STR_n "\0" +#define STRING_Modi0 STR_M STR_o STR_d STR_i "\0" #define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0" +#define STRING_Mro0 STR_M STR_r STR_o "\0" #define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0" #define STRING_N0 STR_N "\0" +#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0" #define STRING_Nd0 STR_N STR_d "\0" #define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0" #define STRING_Nko0 STR_N STR_k STR_o "\0" @@ -294,12 +308,17 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0" #define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0" #define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0" +#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0" +#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0" #define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0" #define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0" #define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0" #define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0" #define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0" #define STRING_P0 STR_P "\0" +#define STRING_Pahawh_Hmong0 STR_P STR_a STR_h STR_a STR_w STR_h STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0" +#define STRING_Palmyrene0 STR_P STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0" +#define STRING_Pau_Cin_Hau0 STR_P STR_a STR_u STR_UNDERSCORE STR_C STR_i STR_n STR_UNDERSCORE STR_H STR_a STR_u "\0" #define STRING_Pc0 STR_P STR_c "\0" #define STRING_Pd0 STR_P STR_d "\0" #define STRING_Pe0 STR_P STR_e "\0" @@ -309,6 +328,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Pi0 STR_P STR_i "\0" #define STRING_Po0 STR_P STR_o "\0" #define STRING_Ps0 STR_P STR_s "\0" +#define STRING_Psalter_Pahlavi0 STR_P STR_s STR_a STR_l STR_t STR_e STR_r STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0" #define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0" #define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0" #define STRING_S0 STR_S "\0" @@ -317,6 +337,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Sc0 STR_S STR_c "\0" #define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0" #define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0" +#define STRING_Siddham0 STR_S STR_i STR_d STR_d STR_h STR_a STR_m "\0" #define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0" #define STRING_Sk0 STR_S STR_k "\0" #define STRING_Sm0 STR_S STR_m "\0" @@ -337,8 +358,10 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Thai0 STR_T STR_h STR_a STR_i "\0" #define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0" #define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0" +#define STRING_Tirhuta0 STR_T STR_i STR_r STR_h STR_u STR_t STR_a "\0" #define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0" #define STRING_Vai0 STR_V STR_a STR_i "\0" +#define STRING_Warang_Citi0 STR_W STR_a STR_r STR_a STR_n STR_g STR_UNDERSCORE STR_C STR_i STR_t STR_i "\0" #define STRING_Xan0 STR_X STR_a STR_n "\0" #define STRING_Xps0 STR_X STR_p STR_s "\0" #define STRING_Xsp0 STR_X STR_s STR_p "\0" @@ -357,6 +380,7 @@ const char PRIV(utt_names)[] = STRING_Avestan0 STRING_Balinese0 STRING_Bamum0 + STRING_Bassa_Vah0 STRING_Batak0 STRING_Bengali0 STRING_Bopomofo0 @@ -367,6 +391,7 @@ const char PRIV(utt_names)[] = STRING_C0 STRING_Canadian_Aboriginal0 STRING_Carian0 + STRING_Caucasian_Albanian0 STRING_Cc0 STRING_Cf0 STRING_Chakma0 @@ -382,11 +407,14 @@ const char PRIV(utt_names)[] = STRING_Cyrillic0 STRING_Deseret0 STRING_Devanagari0 + STRING_Duployan0 STRING_Egyptian_Hieroglyphs0 + STRING_Elbasan0 STRING_Ethiopic0 STRING_Georgian0 STRING_Glagolitic0 STRING_Gothic0 + STRING_Grantha0 STRING_Greek0 STRING_Gujarati0 STRING_Gurmukhi0 @@ -406,12 +434,15 @@ const char PRIV(utt_names)[] = STRING_Kayah_Li0 STRING_Kharoshthi0 STRING_Khmer0 + STRING_Khojki0 + STRING_Khudawadi0 STRING_L0 STRING_L_AMPERSAND0 STRING_Lao0 STRING_Latin0 STRING_Lepcha0 STRING_Limbu0 + STRING_Linear_A0 STRING_Linear_B0 STRING_Lisu0 STRING_Ll0 @@ -422,18 +453,24 @@ const char PRIV(utt_names)[] = STRING_Lycian0 STRING_Lydian0 STRING_M0 + STRING_Mahajani0 STRING_Malayalam0 STRING_Mandaic0 + STRING_Manichaean0 STRING_Mc0 STRING_Me0 STRING_Meetei_Mayek0 + STRING_Mende_Kikakui0 STRING_Meroitic_Cursive0 STRING_Meroitic_Hieroglyphs0 STRING_Miao0 STRING_Mn0 + STRING_Modi0 STRING_Mongolian0 + STRING_Mro0 STRING_Myanmar0 STRING_N0 + STRING_Nabataean0 STRING_Nd0 STRING_New_Tai_Lue0 STRING_Nko0 @@ -442,12 +479,17 @@ const char PRIV(utt_names)[] = STRING_Ogham0 STRING_Ol_Chiki0 STRING_Old_Italic0 + STRING_Old_North_Arabian0 + STRING_Old_Permic0 STRING_Old_Persian0 STRING_Old_South_Arabian0 STRING_Old_Turkic0 STRING_Oriya0 STRING_Osmanya0 STRING_P0 + STRING_Pahawh_Hmong0 + STRING_Palmyrene0 + STRING_Pau_Cin_Hau0 STRING_Pc0 STRING_Pd0 STRING_Pe0 @@ -457,6 +499,7 @@ const char PRIV(utt_names)[] = STRING_Pi0 STRING_Po0 STRING_Ps0 + STRING_Psalter_Pahlavi0 STRING_Rejang0 STRING_Runic0 STRING_S0 @@ -465,6 +508,7 @@ const char PRIV(utt_names)[] = STRING_Sc0 STRING_Sharada0 STRING_Shavian0 + STRING_Siddham0 STRING_Sinhala0 STRING_Sk0 STRING_Sm0 @@ -485,8 +529,10 @@ const char PRIV(utt_names)[] = STRING_Thai0 STRING_Tibetan0 STRING_Tifinagh0 + STRING_Tirhuta0 STRING_Ugaritic0 STRING_Vai0 + STRING_Warang_Citi0 STRING_Xan0 STRING_Xps0 STRING_Xsp0 @@ -505,146 +551,169 @@ const ucp_type_table PRIV(utt)[] = { { 20, PT_SC, ucp_Avestan }, { 28, PT_SC, ucp_Balinese }, { 37, PT_SC, ucp_Bamum }, - { 43, PT_SC, ucp_Batak }, - { 49, PT_SC, ucp_Bengali }, - { 57, PT_SC, ucp_Bopomofo }, - { 66, PT_SC, ucp_Brahmi }, - { 73, PT_SC, ucp_Braille }, - { 81, PT_SC, ucp_Buginese }, - { 90, PT_SC, ucp_Buhid }, - { 96, PT_GC, ucp_C }, - { 98, PT_SC, ucp_Canadian_Aboriginal }, - { 118, PT_SC, ucp_Carian }, - { 125, PT_PC, ucp_Cc }, - { 128, PT_PC, ucp_Cf }, - { 131, PT_SC, ucp_Chakma }, - { 138, PT_SC, ucp_Cham }, - { 143, PT_SC, ucp_Cherokee }, - { 152, PT_PC, ucp_Cn }, - { 155, PT_PC, ucp_Co }, - { 158, PT_SC, ucp_Common }, - { 165, PT_SC, ucp_Coptic }, - { 172, PT_PC, ucp_Cs }, - { 175, PT_SC, ucp_Cuneiform }, - { 185, PT_SC, ucp_Cypriot }, - { 193, PT_SC, ucp_Cyrillic }, - { 202, PT_SC, ucp_Deseret }, - { 210, PT_SC, ucp_Devanagari }, - { 221, PT_SC, ucp_Egyptian_Hieroglyphs }, - { 242, PT_SC, ucp_Ethiopic }, - { 251, PT_SC, ucp_Georgian }, - { 260, PT_SC, ucp_Glagolitic }, - { 271, PT_SC, ucp_Gothic }, - { 278, PT_SC, ucp_Greek }, - { 284, PT_SC, ucp_Gujarati }, - { 293, PT_SC, ucp_Gurmukhi }, - { 302, PT_SC, ucp_Han }, - { 306, PT_SC, ucp_Hangul }, - { 313, PT_SC, ucp_Hanunoo }, - { 321, PT_SC, ucp_Hebrew }, - { 328, PT_SC, ucp_Hiragana }, - { 337, PT_SC, ucp_Imperial_Aramaic }, - { 354, PT_SC, ucp_Inherited }, - { 364, PT_SC, ucp_Inscriptional_Pahlavi }, - { 386, PT_SC, ucp_Inscriptional_Parthian }, - { 409, PT_SC, ucp_Javanese }, - { 418, PT_SC, ucp_Kaithi }, - { 425, PT_SC, ucp_Kannada }, - { 433, PT_SC, ucp_Katakana }, - { 442, PT_SC, ucp_Kayah_Li }, - { 451, PT_SC, ucp_Kharoshthi }, - { 462, PT_SC, ucp_Khmer }, - { 468, PT_GC, ucp_L }, - { 470, PT_LAMP, 0 }, - { 473, PT_SC, ucp_Lao }, - { 477, PT_SC, ucp_Latin }, - { 483, PT_SC, ucp_Lepcha }, - { 490, PT_SC, ucp_Limbu }, - { 496, PT_SC, ucp_Linear_B }, - { 505, PT_SC, ucp_Lisu }, - { 510, PT_PC, ucp_Ll }, - { 513, PT_PC, ucp_Lm }, - { 516, PT_PC, ucp_Lo }, - { 519, PT_PC, ucp_Lt }, - { 522, PT_PC, ucp_Lu }, - { 525, PT_SC, ucp_Lycian }, - { 532, PT_SC, ucp_Lydian }, - { 539, PT_GC, ucp_M }, - { 541, PT_SC, ucp_Malayalam }, - { 551, PT_SC, ucp_Mandaic }, - { 559, PT_PC, ucp_Mc }, - { 562, PT_PC, ucp_Me }, - { 565, PT_SC, ucp_Meetei_Mayek }, - { 578, PT_SC, ucp_Meroitic_Cursive }, - { 595, PT_SC, ucp_Meroitic_Hieroglyphs }, - { 616, PT_SC, ucp_Miao }, - { 621, PT_PC, ucp_Mn }, - { 624, PT_SC, ucp_Mongolian }, - { 634, PT_SC, ucp_Myanmar }, - { 642, PT_GC, ucp_N }, - { 644, PT_PC, ucp_Nd }, - { 647, PT_SC, ucp_New_Tai_Lue }, - { 659, PT_SC, ucp_Nko }, - { 663, PT_PC, ucp_Nl }, - { 666, PT_PC, ucp_No }, - { 669, PT_SC, ucp_Ogham }, - { 675, PT_SC, ucp_Ol_Chiki }, - { 684, PT_SC, ucp_Old_Italic }, - { 695, PT_SC, ucp_Old_Persian }, - { 707, PT_SC, ucp_Old_South_Arabian }, - { 725, PT_SC, ucp_Old_Turkic }, - { 736, PT_SC, ucp_Oriya }, - { 742, PT_SC, ucp_Osmanya }, - { 750, PT_GC, ucp_P }, - { 752, PT_PC, ucp_Pc }, - { 755, PT_PC, ucp_Pd }, - { 758, PT_PC, ucp_Pe }, - { 761, PT_PC, ucp_Pf }, - { 764, PT_SC, ucp_Phags_Pa }, - { 773, PT_SC, ucp_Phoenician }, - { 784, PT_PC, ucp_Pi }, - { 787, PT_PC, ucp_Po }, - { 790, PT_PC, ucp_Ps }, - { 793, PT_SC, ucp_Rejang }, - { 800, PT_SC, ucp_Runic }, - { 806, PT_GC, ucp_S }, - { 808, PT_SC, ucp_Samaritan }, - { 818, PT_SC, ucp_Saurashtra }, - { 829, PT_PC, ucp_Sc }, - { 832, PT_SC, ucp_Sharada }, - { 840, PT_SC, ucp_Shavian }, - { 848, PT_SC, ucp_Sinhala }, - { 856, PT_PC, ucp_Sk }, - { 859, PT_PC, ucp_Sm }, - { 862, PT_PC, ucp_So }, - { 865, PT_SC, ucp_Sora_Sompeng }, - { 878, PT_SC, ucp_Sundanese }, - { 888, PT_SC, ucp_Syloti_Nagri }, - { 901, PT_SC, ucp_Syriac }, - { 908, PT_SC, ucp_Tagalog }, - { 916, PT_SC, ucp_Tagbanwa }, - { 925, PT_SC, ucp_Tai_Le }, - { 932, PT_SC, ucp_Tai_Tham }, - { 941, PT_SC, ucp_Tai_Viet }, - { 950, PT_SC, ucp_Takri }, - { 956, PT_SC, ucp_Tamil }, - { 962, PT_SC, ucp_Telugu }, - { 969, PT_SC, ucp_Thaana }, - { 976, PT_SC, ucp_Thai }, - { 981, PT_SC, ucp_Tibetan }, - { 989, PT_SC, ucp_Tifinagh }, - { 998, PT_SC, ucp_Ugaritic }, - { 1007, PT_SC, ucp_Vai }, - { 1011, PT_ALNUM, 0 }, - { 1015, PT_PXSPACE, 0 }, - { 1019, PT_SPACE, 0 }, - { 1023, PT_UCNC, 0 }, - { 1027, PT_WORD, 0 }, - { 1031, PT_SC, ucp_Yi }, - { 1034, PT_GC, ucp_Z }, - { 1036, PT_PC, ucp_Zl }, - { 1039, PT_PC, ucp_Zp }, - { 1042, PT_PC, ucp_Zs } + { 43, PT_SC, ucp_Bassa_Vah }, + { 53, PT_SC, ucp_Batak }, + { 59, PT_SC, ucp_Bengali }, + { 67, PT_SC, ucp_Bopomofo }, + { 76, PT_SC, ucp_Brahmi }, + { 83, PT_SC, ucp_Braille }, + { 91, PT_SC, ucp_Buginese }, + { 100, PT_SC, ucp_Buhid }, + { 106, PT_GC, ucp_C }, + { 108, PT_SC, ucp_Canadian_Aboriginal }, + { 128, PT_SC, ucp_Carian }, + { 135, PT_SC, ucp_Caucasian_Albanian }, + { 154, PT_PC, ucp_Cc }, + { 157, PT_PC, ucp_Cf }, + { 160, PT_SC, ucp_Chakma }, + { 167, PT_SC, ucp_Cham }, + { 172, PT_SC, ucp_Cherokee }, + { 181, PT_PC, ucp_Cn }, + { 184, PT_PC, ucp_Co }, + { 187, PT_SC, ucp_Common }, + { 194, PT_SC, ucp_Coptic }, + { 201, PT_PC, ucp_Cs }, + { 204, PT_SC, ucp_Cuneiform }, + { 214, PT_SC, ucp_Cypriot }, + { 222, PT_SC, ucp_Cyrillic }, + { 231, PT_SC, ucp_Deseret }, + { 239, PT_SC, ucp_Devanagari }, + { 250, PT_SC, ucp_Duployan }, + { 259, PT_SC, ucp_Egyptian_Hieroglyphs }, + { 280, PT_SC, ucp_Elbasan }, + { 288, PT_SC, ucp_Ethiopic }, + { 297, PT_SC, ucp_Georgian }, + { 306, PT_SC, ucp_Glagolitic }, + { 317, PT_SC, ucp_Gothic }, + { 324, PT_SC, ucp_Grantha }, + { 332, PT_SC, ucp_Greek }, + { 338, PT_SC, ucp_Gujarati }, + { 347, PT_SC, ucp_Gurmukhi }, + { 356, PT_SC, ucp_Han }, + { 360, PT_SC, ucp_Hangul }, + { 367, PT_SC, ucp_Hanunoo }, + { 375, PT_SC, ucp_Hebrew }, + { 382, PT_SC, ucp_Hiragana }, + { 391, PT_SC, ucp_Imperial_Aramaic }, + { 408, PT_SC, ucp_Inherited }, + { 418, PT_SC, ucp_Inscriptional_Pahlavi }, + { 440, PT_SC, ucp_Inscriptional_Parthian }, + { 463, PT_SC, ucp_Javanese }, + { 472, PT_SC, ucp_Kaithi }, + { 479, PT_SC, ucp_Kannada }, + { 487, PT_SC, ucp_Katakana }, + { 496, PT_SC, ucp_Kayah_Li }, + { 505, PT_SC, ucp_Kharoshthi }, + { 516, PT_SC, ucp_Khmer }, + { 522, PT_SC, ucp_Khojki }, + { 529, PT_SC, ucp_Khudawadi }, + { 539, PT_GC, ucp_L }, + { 541, PT_LAMP, 0 }, + { 544, PT_SC, ucp_Lao }, + { 548, PT_SC, ucp_Latin }, + { 554, PT_SC, ucp_Lepcha }, + { 561, PT_SC, ucp_Limbu }, + { 567, PT_SC, ucp_Linear_A }, + { 576, PT_SC, ucp_Linear_B }, + { 585, PT_SC, ucp_Lisu }, + { 590, PT_PC, ucp_Ll }, + { 593, PT_PC, ucp_Lm }, + { 596, PT_PC, ucp_Lo }, + { 599, PT_PC, ucp_Lt }, + { 602, PT_PC, ucp_Lu }, + { 605, PT_SC, ucp_Lycian }, + { 612, PT_SC, ucp_Lydian }, + { 619, PT_GC, ucp_M }, + { 621, PT_SC, ucp_Mahajani }, + { 630, PT_SC, ucp_Malayalam }, + { 640, PT_SC, ucp_Mandaic }, + { 648, PT_SC, ucp_Manichaean }, + { 659, PT_PC, ucp_Mc }, + { 662, PT_PC, ucp_Me }, + { 665, PT_SC, ucp_Meetei_Mayek }, + { 678, PT_SC, ucp_Mende_Kikakui }, + { 692, PT_SC, ucp_Meroitic_Cursive }, + { 709, PT_SC, ucp_Meroitic_Hieroglyphs }, + { 730, PT_SC, ucp_Miao }, + { 735, PT_PC, ucp_Mn }, + { 738, PT_SC, ucp_Modi }, + { 743, PT_SC, ucp_Mongolian }, + { 753, PT_SC, ucp_Mro }, + { 757, PT_SC, ucp_Myanmar }, + { 765, PT_GC, ucp_N }, + { 767, PT_SC, ucp_Nabataean }, + { 777, PT_PC, ucp_Nd }, + { 780, PT_SC, ucp_New_Tai_Lue }, + { 792, PT_SC, ucp_Nko }, + { 796, PT_PC, ucp_Nl }, + { 799, PT_PC, ucp_No }, + { 802, PT_SC, ucp_Ogham }, + { 808, PT_SC, ucp_Ol_Chiki }, + { 817, PT_SC, ucp_Old_Italic }, + { 828, PT_SC, ucp_Old_North_Arabian }, + { 846, PT_SC, ucp_Old_Permic }, + { 857, PT_SC, ucp_Old_Persian }, + { 869, PT_SC, ucp_Old_South_Arabian }, + { 887, PT_SC, ucp_Old_Turkic }, + { 898, PT_SC, ucp_Oriya }, + { 904, PT_SC, ucp_Osmanya }, + { 912, PT_GC, ucp_P }, + { 914, PT_SC, ucp_Pahawh_Hmong }, + { 927, PT_SC, ucp_Palmyrene }, + { 937, PT_SC, ucp_Pau_Cin_Hau }, + { 949, PT_PC, ucp_Pc }, + { 952, PT_PC, ucp_Pd }, + { 955, PT_PC, ucp_Pe }, + { 958, PT_PC, ucp_Pf }, + { 961, PT_SC, ucp_Phags_Pa }, + { 970, PT_SC, ucp_Phoenician }, + { 981, PT_PC, ucp_Pi }, + { 984, PT_PC, ucp_Po }, + { 987, PT_PC, ucp_Ps }, + { 990, PT_SC, ucp_Psalter_Pahlavi }, + { 1006, PT_SC, ucp_Rejang }, + { 1013, PT_SC, ucp_Runic }, + { 1019, PT_GC, ucp_S }, + { 1021, PT_SC, ucp_Samaritan }, + { 1031, PT_SC, ucp_Saurashtra }, + { 1042, PT_PC, ucp_Sc }, + { 1045, PT_SC, ucp_Sharada }, + { 1053, PT_SC, ucp_Shavian }, + { 1061, PT_SC, ucp_Siddham }, + { 1069, PT_SC, ucp_Sinhala }, + { 1077, PT_PC, ucp_Sk }, + { 1080, PT_PC, ucp_Sm }, + { 1083, PT_PC, ucp_So }, + { 1086, PT_SC, ucp_Sora_Sompeng }, + { 1099, PT_SC, ucp_Sundanese }, + { 1109, PT_SC, ucp_Syloti_Nagri }, + { 1122, PT_SC, ucp_Syriac }, + { 1129, PT_SC, ucp_Tagalog }, + { 1137, PT_SC, ucp_Tagbanwa }, + { 1146, PT_SC, ucp_Tai_Le }, + { 1153, PT_SC, ucp_Tai_Tham }, + { 1162, PT_SC, ucp_Tai_Viet }, + { 1171, PT_SC, ucp_Takri }, + { 1177, PT_SC, ucp_Tamil }, + { 1183, PT_SC, ucp_Telugu }, + { 1190, PT_SC, ucp_Thaana }, + { 1197, PT_SC, ucp_Thai }, + { 1202, PT_SC, ucp_Tibetan }, + { 1210, PT_SC, ucp_Tifinagh }, + { 1219, PT_SC, ucp_Tirhuta }, + { 1227, PT_SC, ucp_Ugaritic }, + { 1236, PT_SC, ucp_Vai }, + { 1240, PT_SC, ucp_Warang_Citi }, + { 1252, PT_ALNUM, 0 }, + { 1256, PT_PXSPACE, 0 }, + { 1260, PT_SPACE, 0 }, + { 1264, PT_UCNC, 0 }, + { 1268, PT_WORD, 0 }, + { 1272, PT_SC, ucp_Yi }, + { 1275, PT_GC, ucp_Z }, + { 1277, PT_PC, ucp_Zl }, + { 1280, PT_PC, ucp_Zp }, + { 1283, PT_PC, ucp_Zs } }; const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); diff --git a/Foundation/src/pcre_ucd.c b/Foundation/src/pcre_ucd.c index ca845a27c..8e223e383 100644 --- a/Foundation/src/pcre_ucd.c +++ b/Foundation/src/pcre_ucd.c @@ -17,7 +17,7 @@ needed. */ /* Unicode character database. */ /* This file was autogenerated by the MultiStage2.py script. */ -/* Total size: 65688 bytes, block size: 128. */ +/* Total size: 72576 bytes, block size: 128. */ /* The tables herein are needed only when UCP support is built into PCRE. This module should not be referenced otherwise, so @@ -76,7 +76,7 @@ const pcre_uint32 PRIV(ucd_caseless_sets)[] = { #ifndef PCRE_INCLUDED -const ucd_record PRIV(ucd_records)[] = { /* 5016 bytes, record size 8 */ +const ucd_record PRIV(ucd_records)[] = { /* 5760 bytes, record size 8 */ { 9, 0, 2, 0, 0, }, /* 0 */ { 9, 0, 1, 0, 0, }, /* 1 */ { 9, 0, 0, 0, 0, }, /* 2 */ @@ -163,547 +163,640 @@ const ucd_record PRIV(ucd_records)[] = { /* 5016 bytes, record size 8 */ { 33, 5, 12, 0, -205, }, /* 83 */ { 33, 5, 12, 0, -202, }, /* 84 */ { 33, 5, 12, 0, -203, }, /* 85 */ - { 33, 5, 12, 0, -207, }, /* 86 */ - { 33, 5, 12, 0, 42280, }, /* 87 */ - { 33, 5, 12, 0, 42308, }, /* 88 */ - { 33, 5, 12, 0, -209, }, /* 89 */ - { 33, 5, 12, 0, -211, }, /* 90 */ - { 33, 5, 12, 0, 10743, }, /* 91 */ - { 33, 5, 12, 0, 10749, }, /* 92 */ - { 33, 5, 12, 0, -213, }, /* 93 */ - { 33, 5, 12, 0, -214, }, /* 94 */ - { 33, 5, 12, 0, 10727, }, /* 95 */ - { 33, 5, 12, 0, -218, }, /* 96 */ - { 33, 5, 12, 0, -69, }, /* 97 */ - { 33, 5, 12, 0, -217, }, /* 98 */ - { 33, 5, 12, 0, -71, }, /* 99 */ - { 33, 5, 12, 0, -219, }, /* 100 */ - { 33, 6, 12, 0, 0, }, /* 101 */ - { 9, 6, 12, 0, 0, }, /* 102 */ - { 3, 24, 12, 0, 0, }, /* 103 */ - { 27, 12, 3, 0, 0, }, /* 104 */ - { 27, 12, 3, 21, 116, }, /* 105 */ - { 19, 9, 12, 0, 1, }, /* 106 */ - { 19, 5, 12, 0, -1, }, /* 107 */ - { 19, 24, 12, 0, 0, }, /* 108 */ - { 9, 2, 12, 0, 0, }, /* 109 */ - { 19, 6, 12, 0, 0, }, /* 110 */ - { 19, 5, 12, 0, 130, }, /* 111 */ - { 19, 9, 12, 0, 38, }, /* 112 */ - { 19, 9, 12, 0, 37, }, /* 113 */ - { 19, 9, 12, 0, 64, }, /* 114 */ - { 19, 9, 12, 0, 63, }, /* 115 */ - { 19, 5, 12, 0, 0, }, /* 116 */ - { 19, 9, 12, 0, 32, }, /* 117 */ - { 19, 9, 12, 34, 32, }, /* 118 */ - { 19, 9, 12, 59, 32, }, /* 119 */ - { 19, 9, 12, 38, 32, }, /* 120 */ - { 19, 9, 12, 21, 32, }, /* 121 */ - { 19, 9, 12, 51, 32, }, /* 122 */ - { 19, 9, 12, 26, 32, }, /* 123 */ - { 19, 9, 12, 47, 32, }, /* 124 */ - { 19, 9, 12, 55, 32, }, /* 125 */ - { 19, 9, 12, 30, 32, }, /* 126 */ - { 19, 9, 12, 43, 32, }, /* 127 */ - { 19, 9, 12, 67, 32, }, /* 128 */ - { 19, 5, 12, 0, -38, }, /* 129 */ - { 19, 5, 12, 0, -37, }, /* 130 */ - { 19, 5, 12, 0, -32, }, /* 131 */ - { 19, 5, 12, 34, -32, }, /* 132 */ - { 19, 5, 12, 59, -32, }, /* 133 */ - { 19, 5, 12, 38, -32, }, /* 134 */ - { 19, 5, 12, 21, -116, }, /* 135 */ - { 19, 5, 12, 51, -32, }, /* 136 */ - { 19, 5, 12, 26, -775, }, /* 137 */ - { 19, 5, 12, 47, -32, }, /* 138 */ - { 19, 5, 12, 55, -32, }, /* 139 */ - { 19, 5, 12, 30, 1, }, /* 140 */ - { 19, 5, 12, 30, -32, }, /* 141 */ - { 19, 5, 12, 43, -32, }, /* 142 */ - { 19, 5, 12, 67, -32, }, /* 143 */ - { 19, 5, 12, 0, -64, }, /* 144 */ - { 19, 5, 12, 0, -63, }, /* 145 */ - { 19, 9, 12, 0, 8, }, /* 146 */ - { 19, 5, 12, 34, -30, }, /* 147 */ - { 19, 5, 12, 38, -25, }, /* 148 */ - { 19, 9, 12, 0, 0, }, /* 149 */ - { 19, 5, 12, 43, -15, }, /* 150 */ - { 19, 5, 12, 47, -22, }, /* 151 */ - { 19, 5, 12, 0, -8, }, /* 152 */ - { 10, 9, 12, 0, 1, }, /* 153 */ - { 10, 5, 12, 0, -1, }, /* 154 */ - { 19, 5, 12, 51, -54, }, /* 155 */ - { 19, 5, 12, 55, -48, }, /* 156 */ - { 19, 5, 12, 0, 7, }, /* 157 */ - { 19, 9, 12, 38, -60, }, /* 158 */ - { 19, 5, 12, 59, -64, }, /* 159 */ - { 19, 25, 12, 0, 0, }, /* 160 */ - { 19, 9, 12, 0, -7, }, /* 161 */ - { 19, 9, 12, 0, -130, }, /* 162 */ - { 12, 9, 12, 0, 80, }, /* 163 */ - { 12, 9, 12, 0, 32, }, /* 164 */ - { 12, 5, 12, 0, -32, }, /* 165 */ - { 12, 5, 12, 0, -80, }, /* 166 */ - { 12, 9, 12, 0, 1, }, /* 167 */ - { 12, 5, 12, 0, -1, }, /* 168 */ - { 12, 26, 12, 0, 0, }, /* 169 */ - { 12, 12, 3, 0, 0, }, /* 170 */ - { 12, 11, 3, 0, 0, }, /* 171 */ - { 12, 9, 12, 0, 15, }, /* 172 */ - { 12, 5, 12, 0, -15, }, /* 173 */ - { 1, 9, 12, 0, 48, }, /* 174 */ - { 1, 6, 12, 0, 0, }, /* 175 */ - { 1, 21, 12, 0, 0, }, /* 176 */ - { 1, 5, 12, 0, -48, }, /* 177 */ - { 1, 5, 12, 0, 0, }, /* 178 */ - { 1, 17, 12, 0, 0, }, /* 179 */ - { 1, 23, 12, 0, 0, }, /* 180 */ - { 25, 12, 3, 0, 0, }, /* 181 */ - { 25, 17, 12, 0, 0, }, /* 182 */ - { 25, 21, 12, 0, 0, }, /* 183 */ - { 25, 7, 12, 0, 0, }, /* 184 */ - { 0, 1, 2, 0, 0, }, /* 185 */ - { 0, 25, 12, 0, 0, }, /* 186 */ - { 0, 21, 12, 0, 0, }, /* 187 */ - { 0, 23, 12, 0, 0, }, /* 188 */ - { 0, 26, 12, 0, 0, }, /* 189 */ - { 0, 12, 3, 0, 0, }, /* 190 */ - { 0, 7, 12, 0, 0, }, /* 191 */ - { 0, 6, 12, 0, 0, }, /* 192 */ - { 0, 13, 12, 0, 0, }, /* 193 */ - { 49, 21, 12, 0, 0, }, /* 194 */ - { 49, 1, 2, 0, 0, }, /* 195 */ - { 49, 7, 12, 0, 0, }, /* 196 */ - { 49, 12, 3, 0, 0, }, /* 197 */ - { 55, 7, 12, 0, 0, }, /* 198 */ - { 55, 12, 3, 0, 0, }, /* 199 */ - { 63, 13, 12, 0, 0, }, /* 200 */ - { 63, 7, 12, 0, 0, }, /* 201 */ - { 63, 12, 3, 0, 0, }, /* 202 */ - { 63, 6, 12, 0, 0, }, /* 203 */ - { 63, 26, 12, 0, 0, }, /* 204 */ - { 63, 21, 12, 0, 0, }, /* 205 */ - { 89, 7, 12, 0, 0, }, /* 206 */ - { 89, 12, 3, 0, 0, }, /* 207 */ - { 89, 6, 12, 0, 0, }, /* 208 */ - { 89, 21, 12, 0, 0, }, /* 209 */ - { 94, 7, 12, 0, 0, }, /* 210 */ - { 94, 12, 3, 0, 0, }, /* 211 */ - { 94, 21, 12, 0, 0, }, /* 212 */ - { 14, 12, 3, 0, 0, }, /* 213 */ - { 14, 10, 5, 0, 0, }, /* 214 */ - { 14, 7, 12, 0, 0, }, /* 215 */ - { 14, 13, 12, 0, 0, }, /* 216 */ - { 14, 21, 12, 0, 0, }, /* 217 */ - { 14, 6, 12, 0, 0, }, /* 218 */ - { 2, 12, 3, 0, 0, }, /* 219 */ - { 2, 10, 5, 0, 0, }, /* 220 */ - { 2, 7, 12, 0, 0, }, /* 221 */ - { 2, 10, 3, 0, 0, }, /* 222 */ - { 2, 13, 12, 0, 0, }, /* 223 */ - { 2, 23, 12, 0, 0, }, /* 224 */ - { 2, 15, 12, 0, 0, }, /* 225 */ - { 2, 26, 12, 0, 0, }, /* 226 */ - { 21, 12, 3, 0, 0, }, /* 227 */ - { 21, 10, 5, 0, 0, }, /* 228 */ - { 21, 7, 12, 0, 0, }, /* 229 */ - { 21, 13, 12, 0, 0, }, /* 230 */ - { 20, 12, 3, 0, 0, }, /* 231 */ - { 20, 10, 5, 0, 0, }, /* 232 */ - { 20, 7, 12, 0, 0, }, /* 233 */ - { 20, 13, 12, 0, 0, }, /* 234 */ - { 20, 21, 12, 0, 0, }, /* 235 */ - { 20, 23, 12, 0, 0, }, /* 236 */ - { 43, 12, 3, 0, 0, }, /* 237 */ - { 43, 10, 5, 0, 0, }, /* 238 */ - { 43, 7, 12, 0, 0, }, /* 239 */ - { 43, 10, 3, 0, 0, }, /* 240 */ - { 43, 13, 12, 0, 0, }, /* 241 */ - { 43, 26, 12, 0, 0, }, /* 242 */ - { 43, 15, 12, 0, 0, }, /* 243 */ - { 53, 12, 3, 0, 0, }, /* 244 */ - { 53, 7, 12, 0, 0, }, /* 245 */ - { 53, 10, 3, 0, 0, }, /* 246 */ - { 53, 10, 5, 0, 0, }, /* 247 */ - { 53, 13, 12, 0, 0, }, /* 248 */ - { 53, 15, 12, 0, 0, }, /* 249 */ - { 53, 26, 12, 0, 0, }, /* 250 */ - { 53, 23, 12, 0, 0, }, /* 251 */ - { 54, 10, 5, 0, 0, }, /* 252 */ - { 54, 7, 12, 0, 0, }, /* 253 */ - { 54, 12, 3, 0, 0, }, /* 254 */ - { 54, 13, 12, 0, 0, }, /* 255 */ - { 54, 15, 12, 0, 0, }, /* 256 */ - { 54, 26, 12, 0, 0, }, /* 257 */ - { 28, 10, 5, 0, 0, }, /* 258 */ - { 28, 7, 12, 0, 0, }, /* 259 */ - { 28, 12, 3, 0, 0, }, /* 260 */ - { 28, 10, 3, 0, 0, }, /* 261 */ - { 28, 13, 12, 0, 0, }, /* 262 */ - { 36, 10, 5, 0, 0, }, /* 263 */ - { 36, 7, 12, 0, 0, }, /* 264 */ - { 36, 10, 3, 0, 0, }, /* 265 */ - { 36, 12, 3, 0, 0, }, /* 266 */ - { 36, 13, 12, 0, 0, }, /* 267 */ - { 36, 15, 12, 0, 0, }, /* 268 */ - { 36, 26, 12, 0, 0, }, /* 269 */ - { 47, 10, 5, 0, 0, }, /* 270 */ - { 47, 7, 12, 0, 0, }, /* 271 */ - { 47, 12, 3, 0, 0, }, /* 272 */ - { 47, 10, 3, 0, 0, }, /* 273 */ - { 47, 21, 12, 0, 0, }, /* 274 */ - { 56, 7, 12, 0, 0, }, /* 275 */ - { 56, 12, 3, 0, 0, }, /* 276 */ - { 56, 7, 5, 0, 0, }, /* 277 */ - { 56, 6, 12, 0, 0, }, /* 278 */ - { 56, 21, 12, 0, 0, }, /* 279 */ - { 56, 13, 12, 0, 0, }, /* 280 */ - { 32, 7, 12, 0, 0, }, /* 281 */ - { 32, 12, 3, 0, 0, }, /* 282 */ - { 32, 7, 5, 0, 0, }, /* 283 */ - { 32, 6, 12, 0, 0, }, /* 284 */ - { 32, 13, 12, 0, 0, }, /* 285 */ - { 57, 7, 12, 0, 0, }, /* 286 */ - { 57, 26, 12, 0, 0, }, /* 287 */ - { 57, 21, 12, 0, 0, }, /* 288 */ - { 57, 12, 3, 0, 0, }, /* 289 */ - { 57, 13, 12, 0, 0, }, /* 290 */ - { 57, 15, 12, 0, 0, }, /* 291 */ - { 57, 22, 12, 0, 0, }, /* 292 */ - { 57, 18, 12, 0, 0, }, /* 293 */ - { 57, 10, 5, 0, 0, }, /* 294 */ - { 38, 7, 12, 0, 0, }, /* 295 */ - { 38, 10, 12, 0, 0, }, /* 296 */ - { 38, 12, 3, 0, 0, }, /* 297 */ - { 38, 10, 5, 0, 0, }, /* 298 */ - { 38, 13, 12, 0, 0, }, /* 299 */ - { 38, 21, 12, 0, 0, }, /* 300 */ - { 38, 26, 12, 0, 0, }, /* 301 */ - { 16, 9, 12, 0, 7264, }, /* 302 */ - { 16, 7, 12, 0, 0, }, /* 303 */ - { 16, 6, 12, 0, 0, }, /* 304 */ - { 23, 7, 6, 0, 0, }, /* 305 */ - { 23, 7, 7, 0, 0, }, /* 306 */ - { 23, 7, 8, 0, 0, }, /* 307 */ - { 15, 7, 12, 0, 0, }, /* 308 */ - { 15, 12, 3, 0, 0, }, /* 309 */ - { 15, 21, 12, 0, 0, }, /* 310 */ - { 15, 15, 12, 0, 0, }, /* 311 */ - { 15, 26, 12, 0, 0, }, /* 312 */ - { 8, 7, 12, 0, 0, }, /* 313 */ - { 7, 17, 12, 0, 0, }, /* 314 */ - { 7, 7, 12, 0, 0, }, /* 315 */ - { 7, 21, 12, 0, 0, }, /* 316 */ - { 40, 29, 12, 0, 0, }, /* 317 */ - { 40, 7, 12, 0, 0, }, /* 318 */ - { 40, 22, 12, 0, 0, }, /* 319 */ - { 40, 18, 12, 0, 0, }, /* 320 */ - { 45, 7, 12, 0, 0, }, /* 321 */ - { 45, 14, 12, 0, 0, }, /* 322 */ - { 50, 7, 12, 0, 0, }, /* 323 */ - { 50, 12, 3, 0, 0, }, /* 324 */ - { 24, 7, 12, 0, 0, }, /* 325 */ - { 24, 12, 3, 0, 0, }, /* 326 */ - { 6, 7, 12, 0, 0, }, /* 327 */ - { 6, 12, 3, 0, 0, }, /* 328 */ - { 51, 7, 12, 0, 0, }, /* 329 */ - { 51, 12, 3, 0, 0, }, /* 330 */ - { 31, 7, 12, 0, 0, }, /* 331 */ - { 31, 12, 3, 0, 0, }, /* 332 */ - { 31, 10, 5, 0, 0, }, /* 333 */ - { 31, 21, 12, 0, 0, }, /* 334 */ - { 31, 6, 12, 0, 0, }, /* 335 */ - { 31, 23, 12, 0, 0, }, /* 336 */ - { 31, 13, 12, 0, 0, }, /* 337 */ - { 31, 15, 12, 0, 0, }, /* 338 */ - { 37, 21, 12, 0, 0, }, /* 339 */ - { 37, 17, 12, 0, 0, }, /* 340 */ - { 37, 12, 3, 0, 0, }, /* 341 */ - { 37, 1, 2, 0, 0, }, /* 342 */ - { 37, 13, 12, 0, 0, }, /* 343 */ - { 37, 7, 12, 0, 0, }, /* 344 */ - { 37, 6, 12, 0, 0, }, /* 345 */ - { 34, 7, 12, 0, 0, }, /* 346 */ - { 34, 12, 3, 0, 0, }, /* 347 */ - { 34, 10, 5, 0, 0, }, /* 348 */ - { 34, 26, 12, 0, 0, }, /* 349 */ - { 34, 21, 12, 0, 0, }, /* 350 */ - { 34, 13, 12, 0, 0, }, /* 351 */ - { 52, 7, 12, 0, 0, }, /* 352 */ - { 39, 7, 12, 0, 0, }, /* 353 */ - { 39, 10, 12, 0, 0, }, /* 354 */ - { 39, 10, 5, 0, 0, }, /* 355 */ - { 39, 13, 12, 0, 0, }, /* 356 */ - { 39, 15, 12, 0, 0, }, /* 357 */ - { 39, 26, 12, 0, 0, }, /* 358 */ - { 31, 26, 12, 0, 0, }, /* 359 */ - { 5, 7, 12, 0, 0, }, /* 360 */ - { 5, 12, 3, 0, 0, }, /* 361 */ - { 5, 10, 5, 0, 0, }, /* 362 */ - { 5, 21, 12, 0, 0, }, /* 363 */ - { 90, 7, 12, 0, 0, }, /* 364 */ - { 90, 10, 5, 0, 0, }, /* 365 */ - { 90, 12, 3, 0, 0, }, /* 366 */ - { 90, 10, 12, 0, 0, }, /* 367 */ - { 90, 13, 12, 0, 0, }, /* 368 */ - { 90, 21, 12, 0, 0, }, /* 369 */ - { 90, 6, 12, 0, 0, }, /* 370 */ - { 61, 12, 3, 0, 0, }, /* 371 */ - { 61, 10, 5, 0, 0, }, /* 372 */ - { 61, 7, 12, 0, 0, }, /* 373 */ - { 61, 13, 12, 0, 0, }, /* 374 */ - { 61, 21, 12, 0, 0, }, /* 375 */ - { 61, 26, 12, 0, 0, }, /* 376 */ - { 75, 12, 3, 0, 0, }, /* 377 */ - { 75, 10, 5, 0, 0, }, /* 378 */ - { 75, 7, 12, 0, 0, }, /* 379 */ - { 75, 13, 12, 0, 0, }, /* 380 */ - { 92, 7, 12, 0, 0, }, /* 381 */ - { 92, 12, 3, 0, 0, }, /* 382 */ - { 92, 10, 5, 0, 0, }, /* 383 */ - { 92, 21, 12, 0, 0, }, /* 384 */ - { 69, 7, 12, 0, 0, }, /* 385 */ - { 69, 10, 5, 0, 0, }, /* 386 */ - { 69, 12, 3, 0, 0, }, /* 387 */ - { 69, 21, 12, 0, 0, }, /* 388 */ - { 69, 13, 12, 0, 0, }, /* 389 */ - { 72, 13, 12, 0, 0, }, /* 390 */ - { 72, 7, 12, 0, 0, }, /* 391 */ - { 72, 6, 12, 0, 0, }, /* 392 */ - { 72, 21, 12, 0, 0, }, /* 393 */ - { 75, 21, 12, 0, 0, }, /* 394 */ - { 9, 10, 5, 0, 0, }, /* 395 */ - { 9, 7, 12, 0, 0, }, /* 396 */ - { 12, 5, 12, 0, 0, }, /* 397 */ - { 12, 6, 12, 0, 0, }, /* 398 */ - { 33, 5, 12, 0, 35332, }, /* 399 */ - { 33, 5, 12, 0, 3814, }, /* 400 */ - { 33, 9, 12, 63, 1, }, /* 401 */ - { 33, 5, 12, 63, -1, }, /* 402 */ - { 33, 5, 12, 63, -58, }, /* 403 */ - { 33, 9, 12, 0, -7615, }, /* 404 */ - { 19, 5, 12, 0, 8, }, /* 405 */ - { 19, 9, 12, 0, -8, }, /* 406 */ - { 19, 5, 12, 0, 74, }, /* 407 */ - { 19, 5, 12, 0, 86, }, /* 408 */ - { 19, 5, 12, 0, 100, }, /* 409 */ - { 19, 5, 12, 0, 128, }, /* 410 */ - { 19, 5, 12, 0, 112, }, /* 411 */ - { 19, 5, 12, 0, 126, }, /* 412 */ - { 19, 8, 12, 0, -8, }, /* 413 */ - { 19, 5, 12, 0, 9, }, /* 414 */ - { 19, 9, 12, 0, -74, }, /* 415 */ - { 19, 8, 12, 0, -9, }, /* 416 */ - { 19, 5, 12, 21, -7173, }, /* 417 */ - { 19, 9, 12, 0, -86, }, /* 418 */ - { 19, 9, 12, 0, -100, }, /* 419 */ - { 19, 9, 12, 0, -112, }, /* 420 */ - { 19, 9, 12, 0, -128, }, /* 421 */ - { 19, 9, 12, 0, -126, }, /* 422 */ - { 27, 1, 3, 0, 0, }, /* 423 */ - { 9, 27, 2, 0, 0, }, /* 424 */ - { 9, 28, 2, 0, 0, }, /* 425 */ - { 9, 2, 2, 0, 0, }, /* 426 */ - { 27, 11, 3, 0, 0, }, /* 427 */ - { 9, 9, 12, 0, 0, }, /* 428 */ - { 9, 5, 12, 0, 0, }, /* 429 */ - { 19, 9, 12, 67, -7517, }, /* 430 */ - { 33, 9, 12, 71, -8383, }, /* 431 */ - { 33, 9, 12, 75, -8262, }, /* 432 */ - { 33, 9, 12, 0, 28, }, /* 433 */ - { 33, 5, 12, 0, -28, }, /* 434 */ - { 33, 14, 12, 0, 16, }, /* 435 */ - { 33, 14, 12, 0, -16, }, /* 436 */ - { 33, 14, 12, 0, 0, }, /* 437 */ - { 9, 26, 12, 0, 26, }, /* 438 */ - { 9, 26, 12, 0, -26, }, /* 439 */ - { 4, 26, 12, 0, 0, }, /* 440 */ - { 17, 9, 12, 0, 48, }, /* 441 */ - { 17, 5, 12, 0, -48, }, /* 442 */ - { 33, 9, 12, 0, -10743, }, /* 443 */ - { 33, 9, 12, 0, -3814, }, /* 444 */ - { 33, 9, 12, 0, -10727, }, /* 445 */ - { 33, 5, 12, 0, -10795, }, /* 446 */ - { 33, 5, 12, 0, -10792, }, /* 447 */ - { 33, 9, 12, 0, -10780, }, /* 448 */ - { 33, 9, 12, 0, -10749, }, /* 449 */ - { 33, 9, 12, 0, -10783, }, /* 450 */ - { 33, 9, 12, 0, -10782, }, /* 451 */ - { 33, 9, 12, 0, -10815, }, /* 452 */ - { 10, 5, 12, 0, 0, }, /* 453 */ - { 10, 26, 12, 0, 0, }, /* 454 */ - { 10, 12, 3, 0, 0, }, /* 455 */ - { 10, 21, 12, 0, 0, }, /* 456 */ - { 10, 15, 12, 0, 0, }, /* 457 */ - { 16, 5, 12, 0, -7264, }, /* 458 */ - { 58, 7, 12, 0, 0, }, /* 459 */ - { 58, 6, 12, 0, 0, }, /* 460 */ - { 58, 21, 12, 0, 0, }, /* 461 */ - { 58, 12, 3, 0, 0, }, /* 462 */ - { 22, 26, 12, 0, 0, }, /* 463 */ - { 22, 6, 12, 0, 0, }, /* 464 */ - { 22, 14, 12, 0, 0, }, /* 465 */ - { 23, 10, 3, 0, 0, }, /* 466 */ - { 26, 7, 12, 0, 0, }, /* 467 */ - { 26, 6, 12, 0, 0, }, /* 468 */ - { 29, 7, 12, 0, 0, }, /* 469 */ - { 29, 6, 12, 0, 0, }, /* 470 */ - { 3, 7, 12, 0, 0, }, /* 471 */ - { 23, 7, 12, 0, 0, }, /* 472 */ - { 23, 26, 12, 0, 0, }, /* 473 */ - { 29, 26, 12, 0, 0, }, /* 474 */ - { 22, 7, 12, 0, 0, }, /* 475 */ - { 60, 7, 12, 0, 0, }, /* 476 */ - { 60, 6, 12, 0, 0, }, /* 477 */ - { 60, 26, 12, 0, 0, }, /* 478 */ - { 85, 7, 12, 0, 0, }, /* 479 */ - { 85, 6, 12, 0, 0, }, /* 480 */ - { 85, 21, 12, 0, 0, }, /* 481 */ - { 76, 7, 12, 0, 0, }, /* 482 */ - { 76, 6, 12, 0, 0, }, /* 483 */ - { 76, 21, 12, 0, 0, }, /* 484 */ - { 76, 13, 12, 0, 0, }, /* 485 */ - { 12, 7, 12, 0, 0, }, /* 486 */ - { 12, 21, 12, 0, 0, }, /* 487 */ - { 78, 7, 12, 0, 0, }, /* 488 */ - { 78, 14, 12, 0, 0, }, /* 489 */ - { 78, 12, 3, 0, 0, }, /* 490 */ - { 78, 21, 12, 0, 0, }, /* 491 */ - { 33, 9, 12, 0, -35332, }, /* 492 */ - { 33, 9, 12, 0, -42280, }, /* 493 */ - { 33, 9, 12, 0, -42308, }, /* 494 */ - { 48, 7, 12, 0, 0, }, /* 495 */ - { 48, 12, 3, 0, 0, }, /* 496 */ - { 48, 10, 5, 0, 0, }, /* 497 */ - { 48, 26, 12, 0, 0, }, /* 498 */ - { 64, 7, 12, 0, 0, }, /* 499 */ - { 64, 21, 12, 0, 0, }, /* 500 */ - { 74, 10, 5, 0, 0, }, /* 501 */ - { 74, 7, 12, 0, 0, }, /* 502 */ - { 74, 12, 3, 0, 0, }, /* 503 */ - { 74, 21, 12, 0, 0, }, /* 504 */ - { 74, 13, 12, 0, 0, }, /* 505 */ - { 68, 13, 12, 0, 0, }, /* 506 */ - { 68, 7, 12, 0, 0, }, /* 507 */ - { 68, 12, 3, 0, 0, }, /* 508 */ - { 68, 21, 12, 0, 0, }, /* 509 */ - { 73, 7, 12, 0, 0, }, /* 510 */ - { 73, 12, 3, 0, 0, }, /* 511 */ - { 73, 10, 5, 0, 0, }, /* 512 */ - { 73, 21, 12, 0, 0, }, /* 513 */ - { 83, 12, 3, 0, 0, }, /* 514 */ - { 83, 10, 5, 0, 0, }, /* 515 */ - { 83, 7, 12, 0, 0, }, /* 516 */ - { 83, 21, 12, 0, 0, }, /* 517 */ - { 83, 13, 12, 0, 0, }, /* 518 */ - { 67, 7, 12, 0, 0, }, /* 519 */ - { 67, 12, 3, 0, 0, }, /* 520 */ - { 67, 10, 5, 0, 0, }, /* 521 */ - { 67, 13, 12, 0, 0, }, /* 522 */ - { 67, 21, 12, 0, 0, }, /* 523 */ - { 38, 6, 12, 0, 0, }, /* 524 */ - { 91, 7, 12, 0, 0, }, /* 525 */ - { 91, 12, 3, 0, 0, }, /* 526 */ - { 91, 6, 12, 0, 0, }, /* 527 */ - { 91, 21, 12, 0, 0, }, /* 528 */ - { 86, 7, 12, 0, 0, }, /* 529 */ - { 86, 10, 5, 0, 0, }, /* 530 */ - { 86, 12, 3, 0, 0, }, /* 531 */ - { 86, 21, 12, 0, 0, }, /* 532 */ - { 86, 6, 12, 0, 0, }, /* 533 */ - { 86, 13, 12, 0, 0, }, /* 534 */ - { 23, 7, 9, 0, 0, }, /* 535 */ - { 23, 7, 10, 0, 0, }, /* 536 */ - { 9, 4, 2, 0, 0, }, /* 537 */ - { 9, 3, 12, 0, 0, }, /* 538 */ - { 25, 25, 12, 0, 0, }, /* 539 */ - { 0, 24, 12, 0, 0, }, /* 540 */ - { 9, 6, 3, 0, 0, }, /* 541 */ - { 35, 7, 12, 0, 0, }, /* 542 */ - { 19, 14, 12, 0, 0, }, /* 543 */ - { 19, 15, 12, 0, 0, }, /* 544 */ - { 19, 26, 12, 0, 0, }, /* 545 */ - { 70, 7, 12, 0, 0, }, /* 546 */ - { 66, 7, 12, 0, 0, }, /* 547 */ - { 41, 7, 12, 0, 0, }, /* 548 */ - { 41, 15, 12, 0, 0, }, /* 549 */ - { 18, 7, 12, 0, 0, }, /* 550 */ - { 18, 14, 12, 0, 0, }, /* 551 */ - { 59, 7, 12, 0, 0, }, /* 552 */ - { 59, 21, 12, 0, 0, }, /* 553 */ - { 42, 7, 12, 0, 0, }, /* 554 */ - { 42, 21, 12, 0, 0, }, /* 555 */ - { 42, 14, 12, 0, 0, }, /* 556 */ - { 13, 9, 12, 0, 40, }, /* 557 */ - { 13, 5, 12, 0, -40, }, /* 558 */ - { 46, 7, 12, 0, 0, }, /* 559 */ - { 44, 7, 12, 0, 0, }, /* 560 */ - { 44, 13, 12, 0, 0, }, /* 561 */ - { 11, 7, 12, 0, 0, }, /* 562 */ - { 80, 7, 12, 0, 0, }, /* 563 */ - { 80, 21, 12, 0, 0, }, /* 564 */ - { 80, 15, 12, 0, 0, }, /* 565 */ - { 65, 7, 12, 0, 0, }, /* 566 */ - { 65, 15, 12, 0, 0, }, /* 567 */ - { 65, 21, 12, 0, 0, }, /* 568 */ - { 71, 7, 12, 0, 0, }, /* 569 */ - { 71, 21, 12, 0, 0, }, /* 570 */ - { 97, 7, 12, 0, 0, }, /* 571 */ - { 96, 7, 12, 0, 0, }, /* 572 */ - { 30, 7, 12, 0, 0, }, /* 573 */ - { 30, 12, 3, 0, 0, }, /* 574 */ - { 30, 15, 12, 0, 0, }, /* 575 */ - { 30, 21, 12, 0, 0, }, /* 576 */ - { 87, 7, 12, 0, 0, }, /* 577 */ - { 87, 15, 12, 0, 0, }, /* 578 */ - { 87, 21, 12, 0, 0, }, /* 579 */ - { 77, 7, 12, 0, 0, }, /* 580 */ - { 77, 21, 12, 0, 0, }, /* 581 */ - { 82, 7, 12, 0, 0, }, /* 582 */ - { 82, 15, 12, 0, 0, }, /* 583 */ - { 81, 7, 12, 0, 0, }, /* 584 */ - { 81, 15, 12, 0, 0, }, /* 585 */ - { 88, 7, 12, 0, 0, }, /* 586 */ - { 0, 15, 12, 0, 0, }, /* 587 */ - { 93, 10, 5, 0, 0, }, /* 588 */ - { 93, 12, 3, 0, 0, }, /* 589 */ - { 93, 7, 12, 0, 0, }, /* 590 */ - { 93, 21, 12, 0, 0, }, /* 591 */ - { 93, 15, 12, 0, 0, }, /* 592 */ - { 93, 13, 12, 0, 0, }, /* 593 */ - { 84, 12, 3, 0, 0, }, /* 594 */ - { 84, 10, 5, 0, 0, }, /* 595 */ - { 84, 7, 12, 0, 0, }, /* 596 */ - { 84, 21, 12, 0, 0, }, /* 597 */ - { 84, 1, 2, 0, 0, }, /* 598 */ - { 100, 7, 12, 0, 0, }, /* 599 */ - { 100, 13, 12, 0, 0, }, /* 600 */ - { 95, 12, 3, 0, 0, }, /* 601 */ - { 95, 7, 12, 0, 0, }, /* 602 */ - { 95, 10, 5, 0, 0, }, /* 603 */ - { 95, 13, 12, 0, 0, }, /* 604 */ - { 95, 21, 12, 0, 0, }, /* 605 */ - { 99, 12, 3, 0, 0, }, /* 606 */ - { 99, 10, 5, 0, 0, }, /* 607 */ - { 99, 7, 12, 0, 0, }, /* 608 */ - { 99, 21, 12, 0, 0, }, /* 609 */ - { 99, 13, 12, 0, 0, }, /* 610 */ - { 101, 7, 12, 0, 0, }, /* 611 */ - { 101, 12, 3, 0, 0, }, /* 612 */ - { 101, 10, 5, 0, 0, }, /* 613 */ - { 101, 13, 12, 0, 0, }, /* 614 */ - { 62, 7, 12, 0, 0, }, /* 615 */ - { 62, 14, 12, 0, 0, }, /* 616 */ - { 62, 21, 12, 0, 0, }, /* 617 */ - { 79, 7, 12, 0, 0, }, /* 618 */ - { 98, 7, 12, 0, 0, }, /* 619 */ - { 98, 10, 5, 0, 0, }, /* 620 */ - { 98, 12, 3, 0, 0, }, /* 621 */ - { 98, 6, 12, 0, 0, }, /* 622 */ - { 9, 10, 3, 0, 0, }, /* 623 */ - { 19, 12, 3, 0, 0, }, /* 624 */ - { 9, 26, 11, 0, 0, }, /* 625 */ - { 26, 26, 12, 0, 0, }, /* 626 */ + { 33, 5, 12, 0, 42319, }, /* 86 */ + { 33, 5, 12, 0, 42315, }, /* 87 */ + { 33, 5, 12, 0, -207, }, /* 88 */ + { 33, 5, 12, 0, 42280, }, /* 89 */ + { 33, 5, 12, 0, 42308, }, /* 90 */ + { 33, 5, 12, 0, -209, }, /* 91 */ + { 33, 5, 12, 0, -211, }, /* 92 */ + { 33, 5, 12, 0, 10743, }, /* 93 */ + { 33, 5, 12, 0, 42305, }, /* 94 */ + { 33, 5, 12, 0, 10749, }, /* 95 */ + { 33, 5, 12, 0, -213, }, /* 96 */ + { 33, 5, 12, 0, -214, }, /* 97 */ + { 33, 5, 12, 0, 10727, }, /* 98 */ + { 33, 5, 12, 0, -218, }, /* 99 */ + { 33, 5, 12, 0, 42282, }, /* 100 */ + { 33, 5, 12, 0, -69, }, /* 101 */ + { 33, 5, 12, 0, -217, }, /* 102 */ + { 33, 5, 12, 0, -71, }, /* 103 */ + { 33, 5, 12, 0, -219, }, /* 104 */ + { 33, 5, 12, 0, 42258, }, /* 105 */ + { 33, 6, 12, 0, 0, }, /* 106 */ + { 9, 6, 12, 0, 0, }, /* 107 */ + { 3, 24, 12, 0, 0, }, /* 108 */ + { 27, 12, 3, 0, 0, }, /* 109 */ + { 27, 12, 3, 21, 116, }, /* 110 */ + { 19, 9, 12, 0, 1, }, /* 111 */ + { 19, 5, 12, 0, -1, }, /* 112 */ + { 19, 24, 12, 0, 0, }, /* 113 */ + { 9, 2, 12, 0, 0, }, /* 114 */ + { 19, 6, 12, 0, 0, }, /* 115 */ + { 19, 5, 12, 0, 130, }, /* 116 */ + { 19, 9, 12, 0, 116, }, /* 117 */ + { 19, 9, 12, 0, 38, }, /* 118 */ + { 19, 9, 12, 0, 37, }, /* 119 */ + { 19, 9, 12, 0, 64, }, /* 120 */ + { 19, 9, 12, 0, 63, }, /* 121 */ + { 19, 5, 12, 0, 0, }, /* 122 */ + { 19, 9, 12, 0, 32, }, /* 123 */ + { 19, 9, 12, 34, 32, }, /* 124 */ + { 19, 9, 12, 59, 32, }, /* 125 */ + { 19, 9, 12, 38, 32, }, /* 126 */ + { 19, 9, 12, 21, 32, }, /* 127 */ + { 19, 9, 12, 51, 32, }, /* 128 */ + { 19, 9, 12, 26, 32, }, /* 129 */ + { 19, 9, 12, 47, 32, }, /* 130 */ + { 19, 9, 12, 55, 32, }, /* 131 */ + { 19, 9, 12, 30, 32, }, /* 132 */ + { 19, 9, 12, 43, 32, }, /* 133 */ + { 19, 9, 12, 67, 32, }, /* 134 */ + { 19, 5, 12, 0, -38, }, /* 135 */ + { 19, 5, 12, 0, -37, }, /* 136 */ + { 19, 5, 12, 0, -32, }, /* 137 */ + { 19, 5, 12, 34, -32, }, /* 138 */ + { 19, 5, 12, 59, -32, }, /* 139 */ + { 19, 5, 12, 38, -32, }, /* 140 */ + { 19, 5, 12, 21, -116, }, /* 141 */ + { 19, 5, 12, 51, -32, }, /* 142 */ + { 19, 5, 12, 26, -775, }, /* 143 */ + { 19, 5, 12, 47, -32, }, /* 144 */ + { 19, 5, 12, 55, -32, }, /* 145 */ + { 19, 5, 12, 30, 1, }, /* 146 */ + { 19, 5, 12, 30, -32, }, /* 147 */ + { 19, 5, 12, 43, -32, }, /* 148 */ + { 19, 5, 12, 67, -32, }, /* 149 */ + { 19, 5, 12, 0, -64, }, /* 150 */ + { 19, 5, 12, 0, -63, }, /* 151 */ + { 19, 9, 12, 0, 8, }, /* 152 */ + { 19, 5, 12, 34, -30, }, /* 153 */ + { 19, 5, 12, 38, -25, }, /* 154 */ + { 19, 9, 12, 0, 0, }, /* 155 */ + { 19, 5, 12, 43, -15, }, /* 156 */ + { 19, 5, 12, 47, -22, }, /* 157 */ + { 19, 5, 12, 0, -8, }, /* 158 */ + { 10, 9, 12, 0, 1, }, /* 159 */ + { 10, 5, 12, 0, -1, }, /* 160 */ + { 19, 5, 12, 51, -54, }, /* 161 */ + { 19, 5, 12, 55, -48, }, /* 162 */ + { 19, 5, 12, 0, 7, }, /* 163 */ + { 19, 5, 12, 0, -116, }, /* 164 */ + { 19, 9, 12, 38, -60, }, /* 165 */ + { 19, 5, 12, 59, -64, }, /* 166 */ + { 19, 25, 12, 0, 0, }, /* 167 */ + { 19, 9, 12, 0, -7, }, /* 168 */ + { 19, 9, 12, 0, -130, }, /* 169 */ + { 12, 9, 12, 0, 80, }, /* 170 */ + { 12, 9, 12, 0, 32, }, /* 171 */ + { 12, 5, 12, 0, -32, }, /* 172 */ + { 12, 5, 12, 0, -80, }, /* 173 */ + { 12, 9, 12, 0, 1, }, /* 174 */ + { 12, 5, 12, 0, -1, }, /* 175 */ + { 12, 26, 12, 0, 0, }, /* 176 */ + { 12, 12, 3, 0, 0, }, /* 177 */ + { 12, 11, 3, 0, 0, }, /* 178 */ + { 12, 9, 12, 0, 15, }, /* 179 */ + { 12, 5, 12, 0, -15, }, /* 180 */ + { 1, 9, 12, 0, 48, }, /* 181 */ + { 1, 6, 12, 0, 0, }, /* 182 */ + { 1, 21, 12, 0, 0, }, /* 183 */ + { 1, 5, 12, 0, -48, }, /* 184 */ + { 1, 5, 12, 0, 0, }, /* 185 */ + { 1, 17, 12, 0, 0, }, /* 186 */ + { 1, 26, 12, 0, 0, }, /* 187 */ + { 1, 23, 12, 0, 0, }, /* 188 */ + { 25, 12, 3, 0, 0, }, /* 189 */ + { 25, 17, 12, 0, 0, }, /* 190 */ + { 25, 21, 12, 0, 0, }, /* 191 */ + { 25, 7, 12, 0, 0, }, /* 192 */ + { 0, 1, 2, 0, 0, }, /* 193 */ + { 0, 25, 12, 0, 0, }, /* 194 */ + { 0, 21, 12, 0, 0, }, /* 195 */ + { 0, 23, 12, 0, 0, }, /* 196 */ + { 0, 26, 12, 0, 0, }, /* 197 */ + { 0, 12, 3, 0, 0, }, /* 198 */ + { 0, 7, 12, 0, 0, }, /* 199 */ + { 0, 6, 12, 0, 0, }, /* 200 */ + { 0, 13, 12, 0, 0, }, /* 201 */ + { 49, 21, 12, 0, 0, }, /* 202 */ + { 49, 1, 2, 0, 0, }, /* 203 */ + { 49, 7, 12, 0, 0, }, /* 204 */ + { 49, 12, 3, 0, 0, }, /* 205 */ + { 55, 7, 12, 0, 0, }, /* 206 */ + { 55, 12, 3, 0, 0, }, /* 207 */ + { 63, 13, 12, 0, 0, }, /* 208 */ + { 63, 7, 12, 0, 0, }, /* 209 */ + { 63, 12, 3, 0, 0, }, /* 210 */ + { 63, 6, 12, 0, 0, }, /* 211 */ + { 63, 26, 12, 0, 0, }, /* 212 */ + { 63, 21, 12, 0, 0, }, /* 213 */ + { 89, 7, 12, 0, 0, }, /* 214 */ + { 89, 12, 3, 0, 0, }, /* 215 */ + { 89, 6, 12, 0, 0, }, /* 216 */ + { 89, 21, 12, 0, 0, }, /* 217 */ + { 94, 7, 12, 0, 0, }, /* 218 */ + { 94, 12, 3, 0, 0, }, /* 219 */ + { 94, 21, 12, 0, 0, }, /* 220 */ + { 14, 12, 3, 0, 0, }, /* 221 */ + { 14, 10, 5, 0, 0, }, /* 222 */ + { 14, 7, 12, 0, 0, }, /* 223 */ + { 14, 13, 12, 0, 0, }, /* 224 */ + { 14, 21, 12, 0, 0, }, /* 225 */ + { 14, 6, 12, 0, 0, }, /* 226 */ + { 2, 7, 12, 0, 0, }, /* 227 */ + { 2, 12, 3, 0, 0, }, /* 228 */ + { 2, 10, 5, 0, 0, }, /* 229 */ + { 2, 10, 3, 0, 0, }, /* 230 */ + { 2, 13, 12, 0, 0, }, /* 231 */ + { 2, 23, 12, 0, 0, }, /* 232 */ + { 2, 15, 12, 0, 0, }, /* 233 */ + { 2, 26, 12, 0, 0, }, /* 234 */ + { 21, 12, 3, 0, 0, }, /* 235 */ + { 21, 10, 5, 0, 0, }, /* 236 */ + { 21, 7, 12, 0, 0, }, /* 237 */ + { 21, 13, 12, 0, 0, }, /* 238 */ + { 20, 12, 3, 0, 0, }, /* 239 */ + { 20, 10, 5, 0, 0, }, /* 240 */ + { 20, 7, 12, 0, 0, }, /* 241 */ + { 20, 13, 12, 0, 0, }, /* 242 */ + { 20, 21, 12, 0, 0, }, /* 243 */ + { 20, 23, 12, 0, 0, }, /* 244 */ + { 43, 12, 3, 0, 0, }, /* 245 */ + { 43, 10, 5, 0, 0, }, /* 246 */ + { 43, 7, 12, 0, 0, }, /* 247 */ + { 43, 10, 3, 0, 0, }, /* 248 */ + { 43, 13, 12, 0, 0, }, /* 249 */ + { 43, 26, 12, 0, 0, }, /* 250 */ + { 43, 15, 12, 0, 0, }, /* 251 */ + { 53, 12, 3, 0, 0, }, /* 252 */ + { 53, 7, 12, 0, 0, }, /* 253 */ + { 53, 10, 3, 0, 0, }, /* 254 */ + { 53, 10, 5, 0, 0, }, /* 255 */ + { 53, 13, 12, 0, 0, }, /* 256 */ + { 53, 15, 12, 0, 0, }, /* 257 */ + { 53, 26, 12, 0, 0, }, /* 258 */ + { 53, 23, 12, 0, 0, }, /* 259 */ + { 54, 12, 3, 0, 0, }, /* 260 */ + { 54, 10, 5, 0, 0, }, /* 261 */ + { 54, 7, 12, 0, 0, }, /* 262 */ + { 54, 13, 12, 0, 0, }, /* 263 */ + { 54, 15, 12, 0, 0, }, /* 264 */ + { 54, 26, 12, 0, 0, }, /* 265 */ + { 28, 12, 3, 0, 0, }, /* 266 */ + { 28, 10, 5, 0, 0, }, /* 267 */ + { 28, 7, 12, 0, 0, }, /* 268 */ + { 28, 10, 3, 0, 0, }, /* 269 */ + { 28, 13, 12, 0, 0, }, /* 270 */ + { 36, 12, 3, 0, 0, }, /* 271 */ + { 36, 10, 5, 0, 0, }, /* 272 */ + { 36, 7, 12, 0, 0, }, /* 273 */ + { 36, 10, 3, 0, 0, }, /* 274 */ + { 36, 13, 12, 0, 0, }, /* 275 */ + { 36, 15, 12, 0, 0, }, /* 276 */ + { 36, 26, 12, 0, 0, }, /* 277 */ + { 47, 10, 5, 0, 0, }, /* 278 */ + { 47, 7, 12, 0, 0, }, /* 279 */ + { 47, 12, 3, 0, 0, }, /* 280 */ + { 47, 10, 3, 0, 0, }, /* 281 */ + { 47, 13, 12, 0, 0, }, /* 282 */ + { 47, 21, 12, 0, 0, }, /* 283 */ + { 56, 7, 12, 0, 0, }, /* 284 */ + { 56, 12, 3, 0, 0, }, /* 285 */ + { 56, 7, 5, 0, 0, }, /* 286 */ + { 56, 6, 12, 0, 0, }, /* 287 */ + { 56, 21, 12, 0, 0, }, /* 288 */ + { 56, 13, 12, 0, 0, }, /* 289 */ + { 32, 7, 12, 0, 0, }, /* 290 */ + { 32, 12, 3, 0, 0, }, /* 291 */ + { 32, 7, 5, 0, 0, }, /* 292 */ + { 32, 6, 12, 0, 0, }, /* 293 */ + { 32, 13, 12, 0, 0, }, /* 294 */ + { 57, 7, 12, 0, 0, }, /* 295 */ + { 57, 26, 12, 0, 0, }, /* 296 */ + { 57, 21, 12, 0, 0, }, /* 297 */ + { 57, 12, 3, 0, 0, }, /* 298 */ + { 57, 13, 12, 0, 0, }, /* 299 */ + { 57, 15, 12, 0, 0, }, /* 300 */ + { 57, 22, 12, 0, 0, }, /* 301 */ + { 57, 18, 12, 0, 0, }, /* 302 */ + { 57, 10, 5, 0, 0, }, /* 303 */ + { 38, 7, 12, 0, 0, }, /* 304 */ + { 38, 10, 12, 0, 0, }, /* 305 */ + { 38, 12, 3, 0, 0, }, /* 306 */ + { 38, 10, 5, 0, 0, }, /* 307 */ + { 38, 13, 12, 0, 0, }, /* 308 */ + { 38, 21, 12, 0, 0, }, /* 309 */ + { 38, 26, 12, 0, 0, }, /* 310 */ + { 16, 9, 12, 0, 7264, }, /* 311 */ + { 16, 7, 12, 0, 0, }, /* 312 */ + { 16, 6, 12, 0, 0, }, /* 313 */ + { 23, 7, 6, 0, 0, }, /* 314 */ + { 23, 7, 7, 0, 0, }, /* 315 */ + { 23, 7, 8, 0, 0, }, /* 316 */ + { 15, 7, 12, 0, 0, }, /* 317 */ + { 15, 12, 3, 0, 0, }, /* 318 */ + { 15, 21, 12, 0, 0, }, /* 319 */ + { 15, 15, 12, 0, 0, }, /* 320 */ + { 15, 26, 12, 0, 0, }, /* 321 */ + { 8, 7, 12, 0, 0, }, /* 322 */ + { 7, 17, 12, 0, 0, }, /* 323 */ + { 7, 7, 12, 0, 0, }, /* 324 */ + { 7, 21, 12, 0, 0, }, /* 325 */ + { 40, 29, 12, 0, 0, }, /* 326 */ + { 40, 7, 12, 0, 0, }, /* 327 */ + { 40, 22, 12, 0, 0, }, /* 328 */ + { 40, 18, 12, 0, 0, }, /* 329 */ + { 45, 7, 12, 0, 0, }, /* 330 */ + { 45, 14, 12, 0, 0, }, /* 331 */ + { 50, 7, 12, 0, 0, }, /* 332 */ + { 50, 12, 3, 0, 0, }, /* 333 */ + { 24, 7, 12, 0, 0, }, /* 334 */ + { 24, 12, 3, 0, 0, }, /* 335 */ + { 6, 7, 12, 0, 0, }, /* 336 */ + { 6, 12, 3, 0, 0, }, /* 337 */ + { 51, 7, 12, 0, 0, }, /* 338 */ + { 51, 12, 3, 0, 0, }, /* 339 */ + { 31, 7, 12, 0, 0, }, /* 340 */ + { 31, 12, 3, 0, 0, }, /* 341 */ + { 31, 10, 5, 0, 0, }, /* 342 */ + { 31, 21, 12, 0, 0, }, /* 343 */ + { 31, 6, 12, 0, 0, }, /* 344 */ + { 31, 23, 12, 0, 0, }, /* 345 */ + { 31, 13, 12, 0, 0, }, /* 346 */ + { 31, 15, 12, 0, 0, }, /* 347 */ + { 37, 21, 12, 0, 0, }, /* 348 */ + { 37, 17, 12, 0, 0, }, /* 349 */ + { 37, 12, 3, 0, 0, }, /* 350 */ + { 37, 1, 2, 0, 0, }, /* 351 */ + { 37, 13, 12, 0, 0, }, /* 352 */ + { 37, 7, 12, 0, 0, }, /* 353 */ + { 37, 6, 12, 0, 0, }, /* 354 */ + { 34, 7, 12, 0, 0, }, /* 355 */ + { 34, 12, 3, 0, 0, }, /* 356 */ + { 34, 10, 5, 0, 0, }, /* 357 */ + { 34, 26, 12, 0, 0, }, /* 358 */ + { 34, 21, 12, 0, 0, }, /* 359 */ + { 34, 13, 12, 0, 0, }, /* 360 */ + { 52, 7, 12, 0, 0, }, /* 361 */ + { 39, 7, 12, 0, 0, }, /* 362 */ + { 39, 10, 12, 0, 0, }, /* 363 */ + { 39, 10, 5, 0, 0, }, /* 364 */ + { 39, 13, 12, 0, 0, }, /* 365 */ + { 39, 15, 12, 0, 0, }, /* 366 */ + { 39, 26, 12, 0, 0, }, /* 367 */ + { 31, 26, 12, 0, 0, }, /* 368 */ + { 5, 7, 12, 0, 0, }, /* 369 */ + { 5, 12, 3, 0, 0, }, /* 370 */ + { 5, 10, 5, 0, 0, }, /* 371 */ + { 5, 21, 12, 0, 0, }, /* 372 */ + { 90, 7, 12, 0, 0, }, /* 373 */ + { 90, 10, 5, 0, 0, }, /* 374 */ + { 90, 12, 3, 0, 0, }, /* 375 */ + { 90, 10, 12, 0, 0, }, /* 376 */ + { 90, 13, 12, 0, 0, }, /* 377 */ + { 90, 21, 12, 0, 0, }, /* 378 */ + { 90, 6, 12, 0, 0, }, /* 379 */ + { 27, 11, 3, 0, 0, }, /* 380 */ + { 61, 12, 3, 0, 0, }, /* 381 */ + { 61, 10, 5, 0, 0, }, /* 382 */ + { 61, 7, 12, 0, 0, }, /* 383 */ + { 61, 13, 12, 0, 0, }, /* 384 */ + { 61, 21, 12, 0, 0, }, /* 385 */ + { 61, 26, 12, 0, 0, }, /* 386 */ + { 75, 12, 3, 0, 0, }, /* 387 */ + { 75, 10, 5, 0, 0, }, /* 388 */ + { 75, 7, 12, 0, 0, }, /* 389 */ + { 75, 13, 12, 0, 0, }, /* 390 */ + { 92, 7, 12, 0, 0, }, /* 391 */ + { 92, 12, 3, 0, 0, }, /* 392 */ + { 92, 10, 5, 0, 0, }, /* 393 */ + { 92, 21, 12, 0, 0, }, /* 394 */ + { 69, 7, 12, 0, 0, }, /* 395 */ + { 69, 10, 5, 0, 0, }, /* 396 */ + { 69, 12, 3, 0, 0, }, /* 397 */ + { 69, 21, 12, 0, 0, }, /* 398 */ + { 69, 13, 12, 0, 0, }, /* 399 */ + { 72, 13, 12, 0, 0, }, /* 400 */ + { 72, 7, 12, 0, 0, }, /* 401 */ + { 72, 6, 12, 0, 0, }, /* 402 */ + { 72, 21, 12, 0, 0, }, /* 403 */ + { 75, 21, 12, 0, 0, }, /* 404 */ + { 9, 10, 5, 0, 0, }, /* 405 */ + { 9, 7, 12, 0, 0, }, /* 406 */ + { 12, 5, 12, 0, 0, }, /* 407 */ + { 12, 6, 12, 0, 0, }, /* 408 */ + { 33, 5, 12, 0, 35332, }, /* 409 */ + { 33, 5, 12, 0, 3814, }, /* 410 */ + { 33, 9, 12, 63, 1, }, /* 411 */ + { 33, 5, 12, 63, -1, }, /* 412 */ + { 33, 5, 12, 63, -58, }, /* 413 */ + { 33, 9, 12, 0, -7615, }, /* 414 */ + { 19, 5, 12, 0, 8, }, /* 415 */ + { 19, 9, 12, 0, -8, }, /* 416 */ + { 19, 5, 12, 0, 74, }, /* 417 */ + { 19, 5, 12, 0, 86, }, /* 418 */ + { 19, 5, 12, 0, 100, }, /* 419 */ + { 19, 5, 12, 0, 128, }, /* 420 */ + { 19, 5, 12, 0, 112, }, /* 421 */ + { 19, 5, 12, 0, 126, }, /* 422 */ + { 19, 8, 12, 0, -8, }, /* 423 */ + { 19, 5, 12, 0, 9, }, /* 424 */ + { 19, 9, 12, 0, -74, }, /* 425 */ + { 19, 8, 12, 0, -9, }, /* 426 */ + { 19, 5, 12, 21, -7173, }, /* 427 */ + { 19, 9, 12, 0, -86, }, /* 428 */ + { 19, 9, 12, 0, -100, }, /* 429 */ + { 19, 9, 12, 0, -112, }, /* 430 */ + { 19, 9, 12, 0, -128, }, /* 431 */ + { 19, 9, 12, 0, -126, }, /* 432 */ + { 27, 1, 3, 0, 0, }, /* 433 */ + { 9, 27, 2, 0, 0, }, /* 434 */ + { 9, 28, 2, 0, 0, }, /* 435 */ + { 9, 2, 2, 0, 0, }, /* 436 */ + { 9, 9, 12, 0, 0, }, /* 437 */ + { 9, 5, 12, 0, 0, }, /* 438 */ + { 19, 9, 12, 67, -7517, }, /* 439 */ + { 33, 9, 12, 71, -8383, }, /* 440 */ + { 33, 9, 12, 75, -8262, }, /* 441 */ + { 33, 9, 12, 0, 28, }, /* 442 */ + { 33, 5, 12, 0, -28, }, /* 443 */ + { 33, 14, 12, 0, 16, }, /* 444 */ + { 33, 14, 12, 0, -16, }, /* 445 */ + { 33, 14, 12, 0, 0, }, /* 446 */ + { 9, 26, 12, 0, 26, }, /* 447 */ + { 9, 26, 12, 0, -26, }, /* 448 */ + { 4, 26, 12, 0, 0, }, /* 449 */ + { 17, 9, 12, 0, 48, }, /* 450 */ + { 17, 5, 12, 0, -48, }, /* 451 */ + { 33, 9, 12, 0, -10743, }, /* 452 */ + { 33, 9, 12, 0, -3814, }, /* 453 */ + { 33, 9, 12, 0, -10727, }, /* 454 */ + { 33, 5, 12, 0, -10795, }, /* 455 */ + { 33, 5, 12, 0, -10792, }, /* 456 */ + { 33, 9, 12, 0, -10780, }, /* 457 */ + { 33, 9, 12, 0, -10749, }, /* 458 */ + { 33, 9, 12, 0, -10783, }, /* 459 */ + { 33, 9, 12, 0, -10782, }, /* 460 */ + { 33, 9, 12, 0, -10815, }, /* 461 */ + { 10, 5, 12, 0, 0, }, /* 462 */ + { 10, 26, 12, 0, 0, }, /* 463 */ + { 10, 12, 3, 0, 0, }, /* 464 */ + { 10, 21, 12, 0, 0, }, /* 465 */ + { 10, 15, 12, 0, 0, }, /* 466 */ + { 16, 5, 12, 0, -7264, }, /* 467 */ + { 58, 7, 12, 0, 0, }, /* 468 */ + { 58, 6, 12, 0, 0, }, /* 469 */ + { 58, 21, 12, 0, 0, }, /* 470 */ + { 58, 12, 3, 0, 0, }, /* 471 */ + { 22, 26, 12, 0, 0, }, /* 472 */ + { 22, 6, 12, 0, 0, }, /* 473 */ + { 22, 14, 12, 0, 0, }, /* 474 */ + { 23, 10, 3, 0, 0, }, /* 475 */ + { 26, 7, 12, 0, 0, }, /* 476 */ + { 26, 6, 12, 0, 0, }, /* 477 */ + { 29, 7, 12, 0, 0, }, /* 478 */ + { 29, 6, 12, 0, 0, }, /* 479 */ + { 3, 7, 12, 0, 0, }, /* 480 */ + { 23, 7, 12, 0, 0, }, /* 481 */ + { 23, 26, 12, 0, 0, }, /* 482 */ + { 29, 26, 12, 0, 0, }, /* 483 */ + { 22, 7, 12, 0, 0, }, /* 484 */ + { 60, 7, 12, 0, 0, }, /* 485 */ + { 60, 6, 12, 0, 0, }, /* 486 */ + { 60, 26, 12, 0, 0, }, /* 487 */ + { 85, 7, 12, 0, 0, }, /* 488 */ + { 85, 6, 12, 0, 0, }, /* 489 */ + { 85, 21, 12, 0, 0, }, /* 490 */ + { 76, 7, 12, 0, 0, }, /* 491 */ + { 76, 6, 12, 0, 0, }, /* 492 */ + { 76, 21, 12, 0, 0, }, /* 493 */ + { 76, 13, 12, 0, 0, }, /* 494 */ + { 12, 7, 12, 0, 0, }, /* 495 */ + { 12, 21, 12, 0, 0, }, /* 496 */ + { 78, 7, 12, 0, 0, }, /* 497 */ + { 78, 14, 12, 0, 0, }, /* 498 */ + { 78, 12, 3, 0, 0, }, /* 499 */ + { 78, 21, 12, 0, 0, }, /* 500 */ + { 33, 9, 12, 0, -35332, }, /* 501 */ + { 33, 9, 12, 0, -42280, }, /* 502 */ + { 33, 9, 12, 0, -42308, }, /* 503 */ + { 33, 9, 12, 0, -42319, }, /* 504 */ + { 33, 9, 12, 0, -42315, }, /* 505 */ + { 33, 9, 12, 0, -42305, }, /* 506 */ + { 33, 9, 12, 0, -42258, }, /* 507 */ + { 33, 9, 12, 0, -42282, }, /* 508 */ + { 48, 7, 12, 0, 0, }, /* 509 */ + { 48, 12, 3, 0, 0, }, /* 510 */ + { 48, 10, 5, 0, 0, }, /* 511 */ + { 48, 26, 12, 0, 0, }, /* 512 */ + { 64, 7, 12, 0, 0, }, /* 513 */ + { 64, 21, 12, 0, 0, }, /* 514 */ + { 74, 10, 5, 0, 0, }, /* 515 */ + { 74, 7, 12, 0, 0, }, /* 516 */ + { 74, 12, 3, 0, 0, }, /* 517 */ + { 74, 21, 12, 0, 0, }, /* 518 */ + { 74, 13, 12, 0, 0, }, /* 519 */ + { 68, 13, 12, 0, 0, }, /* 520 */ + { 68, 7, 12, 0, 0, }, /* 521 */ + { 68, 12, 3, 0, 0, }, /* 522 */ + { 68, 21, 12, 0, 0, }, /* 523 */ + { 73, 7, 12, 0, 0, }, /* 524 */ + { 73, 12, 3, 0, 0, }, /* 525 */ + { 73, 10, 5, 0, 0, }, /* 526 */ + { 73, 21, 12, 0, 0, }, /* 527 */ + { 83, 12, 3, 0, 0, }, /* 528 */ + { 83, 10, 5, 0, 0, }, /* 529 */ + { 83, 7, 12, 0, 0, }, /* 530 */ + { 83, 21, 12, 0, 0, }, /* 531 */ + { 83, 13, 12, 0, 0, }, /* 532 */ + { 38, 6, 12, 0, 0, }, /* 533 */ + { 67, 7, 12, 0, 0, }, /* 534 */ + { 67, 12, 3, 0, 0, }, /* 535 */ + { 67, 10, 5, 0, 0, }, /* 536 */ + { 67, 13, 12, 0, 0, }, /* 537 */ + { 67, 21, 12, 0, 0, }, /* 538 */ + { 91, 7, 12, 0, 0, }, /* 539 */ + { 91, 12, 3, 0, 0, }, /* 540 */ + { 91, 6, 12, 0, 0, }, /* 541 */ + { 91, 21, 12, 0, 0, }, /* 542 */ + { 86, 7, 12, 0, 0, }, /* 543 */ + { 86, 10, 5, 0, 0, }, /* 544 */ + { 86, 12, 3, 0, 0, }, /* 545 */ + { 86, 21, 12, 0, 0, }, /* 546 */ + { 86, 6, 12, 0, 0, }, /* 547 */ + { 86, 13, 12, 0, 0, }, /* 548 */ + { 23, 7, 9, 0, 0, }, /* 549 */ + { 23, 7, 10, 0, 0, }, /* 550 */ + { 9, 4, 2, 0, 0, }, /* 551 */ + { 9, 3, 12, 0, 0, }, /* 552 */ + { 25, 25, 12, 0, 0, }, /* 553 */ + { 0, 24, 12, 0, 0, }, /* 554 */ + { 9, 6, 3, 0, 0, }, /* 555 */ + { 35, 7, 12, 0, 0, }, /* 556 */ + { 19, 14, 12, 0, 0, }, /* 557 */ + { 19, 15, 12, 0, 0, }, /* 558 */ + { 19, 26, 12, 0, 0, }, /* 559 */ + { 70, 7, 12, 0, 0, }, /* 560 */ + { 66, 7, 12, 0, 0, }, /* 561 */ + { 41, 7, 12, 0, 0, }, /* 562 */ + { 41, 15, 12, 0, 0, }, /* 563 */ + { 18, 7, 12, 0, 0, }, /* 564 */ + { 18, 14, 12, 0, 0, }, /* 565 */ + { 117, 7, 12, 0, 0, }, /* 566 */ + { 117, 12, 3, 0, 0, }, /* 567 */ + { 59, 7, 12, 0, 0, }, /* 568 */ + { 59, 21, 12, 0, 0, }, /* 569 */ + { 42, 7, 12, 0, 0, }, /* 570 */ + { 42, 21, 12, 0, 0, }, /* 571 */ + { 42, 14, 12, 0, 0, }, /* 572 */ + { 13, 9, 12, 0, 40, }, /* 573 */ + { 13, 5, 12, 0, -40, }, /* 574 */ + { 46, 7, 12, 0, 0, }, /* 575 */ + { 44, 7, 12, 0, 0, }, /* 576 */ + { 44, 13, 12, 0, 0, }, /* 577 */ + { 105, 7, 12, 0, 0, }, /* 578 */ + { 103, 7, 12, 0, 0, }, /* 579 */ + { 103, 21, 12, 0, 0, }, /* 580 */ + { 109, 7, 12, 0, 0, }, /* 581 */ + { 11, 7, 12, 0, 0, }, /* 582 */ + { 80, 7, 12, 0, 0, }, /* 583 */ + { 80, 21, 12, 0, 0, }, /* 584 */ + { 80, 15, 12, 0, 0, }, /* 585 */ + { 119, 7, 12, 0, 0, }, /* 586 */ + { 119, 26, 12, 0, 0, }, /* 587 */ + { 119, 15, 12, 0, 0, }, /* 588 */ + { 115, 7, 12, 0, 0, }, /* 589 */ + { 115, 15, 12, 0, 0, }, /* 590 */ + { 65, 7, 12, 0, 0, }, /* 591 */ + { 65, 15, 12, 0, 0, }, /* 592 */ + { 65, 21, 12, 0, 0, }, /* 593 */ + { 71, 7, 12, 0, 0, }, /* 594 */ + { 71, 21, 12, 0, 0, }, /* 595 */ + { 97, 7, 12, 0, 0, }, /* 596 */ + { 96, 7, 12, 0, 0, }, /* 597 */ + { 30, 7, 12, 0, 0, }, /* 598 */ + { 30, 12, 3, 0, 0, }, /* 599 */ + { 30, 15, 12, 0, 0, }, /* 600 */ + { 30, 21, 12, 0, 0, }, /* 601 */ + { 87, 7, 12, 0, 0, }, /* 602 */ + { 87, 15, 12, 0, 0, }, /* 603 */ + { 87, 21, 12, 0, 0, }, /* 604 */ + { 116, 7, 12, 0, 0, }, /* 605 */ + { 116, 15, 12, 0, 0, }, /* 606 */ + { 111, 7, 12, 0, 0, }, /* 607 */ + { 111, 26, 12, 0, 0, }, /* 608 */ + { 111, 12, 3, 0, 0, }, /* 609 */ + { 111, 15, 12, 0, 0, }, /* 610 */ + { 111, 21, 12, 0, 0, }, /* 611 */ + { 77, 7, 12, 0, 0, }, /* 612 */ + { 77, 21, 12, 0, 0, }, /* 613 */ + { 82, 7, 12, 0, 0, }, /* 614 */ + { 82, 15, 12, 0, 0, }, /* 615 */ + { 81, 7, 12, 0, 0, }, /* 616 */ + { 81, 15, 12, 0, 0, }, /* 617 */ + { 120, 7, 12, 0, 0, }, /* 618 */ + { 120, 21, 12, 0, 0, }, /* 619 */ + { 120, 15, 12, 0, 0, }, /* 620 */ + { 88, 7, 12, 0, 0, }, /* 621 */ + { 0, 15, 12, 0, 0, }, /* 622 */ + { 93, 10, 5, 0, 0, }, /* 623 */ + { 93, 12, 3, 0, 0, }, /* 624 */ + { 93, 7, 12, 0, 0, }, /* 625 */ + { 93, 21, 12, 0, 0, }, /* 626 */ + { 93, 15, 12, 0, 0, }, /* 627 */ + { 93, 13, 12, 0, 0, }, /* 628 */ + { 84, 12, 3, 0, 0, }, /* 629 */ + { 84, 10, 5, 0, 0, }, /* 630 */ + { 84, 7, 12, 0, 0, }, /* 631 */ + { 84, 21, 12, 0, 0, }, /* 632 */ + { 84, 1, 2, 0, 0, }, /* 633 */ + { 100, 7, 12, 0, 0, }, /* 634 */ + { 100, 13, 12, 0, 0, }, /* 635 */ + { 95, 12, 3, 0, 0, }, /* 636 */ + { 95, 7, 12, 0, 0, }, /* 637 */ + { 95, 10, 5, 0, 0, }, /* 638 */ + { 95, 13, 12, 0, 0, }, /* 639 */ + { 95, 21, 12, 0, 0, }, /* 640 */ + { 110, 7, 12, 0, 0, }, /* 641 */ + { 110, 12, 3, 0, 0, }, /* 642 */ + { 110, 21, 12, 0, 0, }, /* 643 */ + { 99, 12, 3, 0, 0, }, /* 644 */ + { 99, 10, 5, 0, 0, }, /* 645 */ + { 99, 7, 12, 0, 0, }, /* 646 */ + { 99, 21, 12, 0, 0, }, /* 647 */ + { 99, 13, 12, 0, 0, }, /* 648 */ + { 47, 15, 12, 0, 0, }, /* 649 */ + { 107, 7, 12, 0, 0, }, /* 650 */ + { 107, 10, 5, 0, 0, }, /* 651 */ + { 107, 12, 3, 0, 0, }, /* 652 */ + { 107, 21, 12, 0, 0, }, /* 653 */ + { 108, 7, 12, 0, 0, }, /* 654 */ + { 108, 12, 3, 0, 0, }, /* 655 */ + { 108, 10, 5, 0, 0, }, /* 656 */ + { 108, 13, 12, 0, 0, }, /* 657 */ + { 106, 12, 3, 0, 0, }, /* 658 */ + { 106, 10, 5, 0, 0, }, /* 659 */ + { 106, 7, 12, 0, 0, }, /* 660 */ + { 106, 10, 3, 0, 0, }, /* 661 */ + { 123, 7, 12, 0, 0, }, /* 662 */ + { 123, 10, 3, 0, 0, }, /* 663 */ + { 123, 10, 5, 0, 0, }, /* 664 */ + { 123, 12, 3, 0, 0, }, /* 665 */ + { 123, 21, 12, 0, 0, }, /* 666 */ + { 123, 13, 12, 0, 0, }, /* 667 */ + { 122, 7, 12, 0, 0, }, /* 668 */ + { 122, 10, 3, 0, 0, }, /* 669 */ + { 122, 10, 5, 0, 0, }, /* 670 */ + { 122, 12, 3, 0, 0, }, /* 671 */ + { 122, 21, 12, 0, 0, }, /* 672 */ + { 113, 7, 12, 0, 0, }, /* 673 */ + { 113, 10, 5, 0, 0, }, /* 674 */ + { 113, 12, 3, 0, 0, }, /* 675 */ + { 113, 21, 12, 0, 0, }, /* 676 */ + { 113, 13, 12, 0, 0, }, /* 677 */ + { 101, 7, 12, 0, 0, }, /* 678 */ + { 101, 12, 3, 0, 0, }, /* 679 */ + { 101, 10, 5, 0, 0, }, /* 680 */ + { 101, 13, 12, 0, 0, }, /* 681 */ + { 124, 9, 12, 0, 32, }, /* 682 */ + { 124, 5, 12, 0, -32, }, /* 683 */ + { 124, 13, 12, 0, 0, }, /* 684 */ + { 124, 15, 12, 0, 0, }, /* 685 */ + { 124, 7, 12, 0, 0, }, /* 686 */ + { 121, 7, 12, 0, 0, }, /* 687 */ + { 62, 7, 12, 0, 0, }, /* 688 */ + { 62, 14, 12, 0, 0, }, /* 689 */ + { 62, 21, 12, 0, 0, }, /* 690 */ + { 79, 7, 12, 0, 0, }, /* 691 */ + { 114, 7, 12, 0, 0, }, /* 692 */ + { 114, 13, 12, 0, 0, }, /* 693 */ + { 114, 21, 12, 0, 0, }, /* 694 */ + { 102, 7, 12, 0, 0, }, /* 695 */ + { 102, 12, 3, 0, 0, }, /* 696 */ + { 102, 21, 12, 0, 0, }, /* 697 */ + { 118, 7, 12, 0, 0, }, /* 698 */ + { 118, 12, 3, 0, 0, }, /* 699 */ + { 118, 21, 12, 0, 0, }, /* 700 */ + { 118, 26, 12, 0, 0, }, /* 701 */ + { 118, 6, 12, 0, 0, }, /* 702 */ + { 118, 13, 12, 0, 0, }, /* 703 */ + { 118, 15, 12, 0, 0, }, /* 704 */ + { 98, 7, 12, 0, 0, }, /* 705 */ + { 98, 10, 5, 0, 0, }, /* 706 */ + { 98, 12, 3, 0, 0, }, /* 707 */ + { 98, 6, 12, 0, 0, }, /* 708 */ + { 104, 7, 12, 0, 0, }, /* 709 */ + { 104, 26, 12, 0, 0, }, /* 710 */ + { 104, 12, 3, 0, 0, }, /* 711 */ + { 104, 21, 12, 0, 0, }, /* 712 */ + { 9, 10, 3, 0, 0, }, /* 713 */ + { 19, 12, 3, 0, 0, }, /* 714 */ + { 112, 7, 12, 0, 0, }, /* 715 */ + { 112, 15, 12, 0, 0, }, /* 716 */ + { 112, 12, 3, 0, 0, }, /* 717 */ + { 9, 26, 11, 0, 0, }, /* 718 */ + { 26, 26, 12, 0, 0, }, /* 719 */ }; const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ @@ -739,38 +832,38 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+E800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F000 */ 123,123, 95, 95,124,125,126,127,128,128,129,130,131,132,133,134, /* U+F800 */ -135,136,137,138, 79,139,140,141,142,143, 79, 79, 79, 79, 79, 79, /* U+10000 */ -144, 79,145,146,147, 79,148, 79,149, 79, 79, 79,150, 79, 79, 79, /* U+10800 */ -151,152,153,154, 79, 79, 79, 79, 79, 79, 79, 79, 79,155, 79, 79, /* U+11000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+11800 */ -156,156,156,156,156,156,157, 79,158, 79, 79, 79, 79, 79, 79, 79, /* U+12000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+12800 */ -159,159,159,159,159,159,159,159,160, 79, 79, 79, 79, 79, 79, 79, /* U+13000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+13800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+14000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+14800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+15000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+15800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+16000 */ -161,161,161,161,162, 79, 79, 79, 79, 79, 79, 79, 79, 79,163,164, /* U+16800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+17000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+17800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+18000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+18800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+19000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+19800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1A800 */ -165, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1C800 */ - 71,166,167,168,169, 79,170, 79,171,172,173,174,175,176,177,178, /* U+1D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,179,180, 79, 79, /* U+1E800 */ -181,182,183,184,185, 79,186,187,188,189,190,191,192,193,194, 79, /* U+1F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1F800 */ +135,136,137,138,139,140,141,142,143,144,145,139,146,146,147,139, /* U+10000 */ +148,149,150,151,152,153,154,155,156,139,139,139,157,139,139,139, /* U+10800 */ +158,159,160,161,162,163,164,139,139,165,139,166,167,168,139,139, /* U+11000 */ +139,169,139,139,139,170,139,139,139,139,139,139,139,139,139,139, /* U+11800 */ +171,171,171,171,171,171,171,172,173,139,139,139,139,139,139,139, /* U+12000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+12800 */ +174,174,174,174,174,174,174,174,175,139,139,139,139,139,139,139, /* U+13000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+13800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+14000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+14800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+16000 */ +176,176,176,176,177,178,179,180,139,139,139,139,139,139,181,182, /* U+16800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+18000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+18800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+19000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+19800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A800 */ +183,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1B000 */ +139,139,139,139,139,139,139,139,184,185,139,139,139,139,139,139, /* U+1B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C800 */ + 71,186,187,188,189,139,190,139,191,192,193,194,195,196,197,198, /* U+1D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1E000 */ +199,200,139,139,139,139,139,139,139,139,139,139,201,202,139,139, /* U+1E800 */ +203,204,205,206,207,139,208,209, 71,210,211,212,213,214,215,216, /* U+1F000 */ +217,218,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1F800 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20000 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20800 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21000 */ @@ -791,402 +884,402 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28800 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29000 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,195, 95, 95, /* U+2A000 */ + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,219, 95, 95, /* U+2A000 */ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2A800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,196, 95, /* U+2B000 */ -197, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2F000 */ - 95, 95, 95, 95,197, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+30000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+30800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+31000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+31800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+32000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+32800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+33000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+33800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+34000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+34800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+35000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+35800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+36000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+36800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+37000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+37800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+38000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+38800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+39000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+39800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+40000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+40800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+41000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+41800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+42000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+42800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+43000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+43800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+44000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+44800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+45000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+45800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+46000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+46800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+47000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+47800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+48000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+48800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+49000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+49800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+50000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+50800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+51000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+51800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+52000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+52800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+53000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+53800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+54000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+54800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+55000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+55800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+56000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+56800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+57000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+57800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+58000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+58800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+59000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+59800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+60000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+60800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+61000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+61800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+62000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+62800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+63000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+63800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+64000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+64800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+65000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+65800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+66000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+66800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+67000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+67800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+68000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+68800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+69000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+69800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+70000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+70800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+71000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+71800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+72000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+72800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+73000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+73800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+74000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+74800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+75000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+75800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+76000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+76800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+77000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+77800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+78000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+78800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+79000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+79800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+80000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+80800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+81000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+81800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+82000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+82800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+83000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+83800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+84000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+84800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+85000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+85800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+86000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+86800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+87000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+87800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+88000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+88800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+89000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+89800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+90000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+90800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+91000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+91800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+92000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+92800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+93000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+93800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+94000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+94800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+95000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+95800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+96000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+96800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+97000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+97800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+98000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+98800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+99000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+99800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9A000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9A800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9B000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9B800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9C000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9C800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9D000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9D800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9E000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9E800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9F000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9F800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A0000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A0800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A1000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A1800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A2000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A2800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A3000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A3800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A4000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A4800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A5000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A5800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A6000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A6800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A7000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A7800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A8000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A8800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A9000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A9800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AA000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AA800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AB000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AB800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AC000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AC800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AD000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AD800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AE000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AE800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AF000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AF800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B0000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B0800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B1000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B1800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B2000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B2800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B3000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B3800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B4000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B4800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B5000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B5800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B6000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B6800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B7000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B7800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B8000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B8800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B9000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B9800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BA000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BA800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BB000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BB800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BC000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BC800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BD000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BD800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BE000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BE800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BF000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BF800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C0000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C0800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C1000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C1800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C2000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C2800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C3000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C3800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C4000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C4800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C5000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C5800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C6000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C6800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C7000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C7800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C8000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C8800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C9000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C9800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CA000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CA800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CB000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CB800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CC000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CC800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CD000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CD800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CE000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CE800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CF000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CF800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D0000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D0800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D1000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D1800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D2000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D2800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D3000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D3800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D4000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D4800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D5000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D5800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D6000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D6800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D7000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D7800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D8000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D8800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D9000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D9800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DA000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DA800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DB000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DB800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DC000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DC800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DD000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DD800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DE000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DE800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DF000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DF800 */ -198,199,200,201,199,199,199,199,199,199,199,199,199,199,199,199, /* U+E0000 */ -199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* U+E0800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E1000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E1800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E2000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E2800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E3000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E3800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E4000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E4800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E5000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E5800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E6000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E6800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E7000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E7800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E8000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E8800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E9000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E9800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EA000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EA800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EB000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EB800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EC000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EC800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+ED000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+ED800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EE000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EE800 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EF000 */ - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EF800 */ + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,220, 95, /* U+2B000 */ +221,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2F000 */ + 95, 95, 95, 95,221,139,139,139,139,139,139,139,139,139,139,139, /* U+2F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+31000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+31800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+32000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+32800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+33000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+33800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+34000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+34800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+35000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+35800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+36000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+36800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+37000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+37800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+38000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+38800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+39000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+39800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+40000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+40800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+41000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+41800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+42000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+42800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+43000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+43800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+44000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+44800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+45000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+45800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+46000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+46800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+47000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+47800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+48000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+48800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+49000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+49800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+50000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+50800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+51000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+51800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+52000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+52800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+53000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+53800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+54000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+54800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+55000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+55800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+56000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+56800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+57000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+57800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+58000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+58800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+59000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+59800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+60000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+60800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+61000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+61800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+62000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+62800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+63000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+63800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+64000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+64800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+65000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+65800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+66000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+66800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+67000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+67800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+68000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+68800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+69000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+69800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+70000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+70800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+71000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+71800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+72000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+72800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+73000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+73800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+74000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+74800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+75000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+75800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+76000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+76800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+77000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+77800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+78000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+78800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+79000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+79800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+80000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+80800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+81000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+81800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+82000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+82800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+83000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+83800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+84000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+84800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+85000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+85800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+86000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+86800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+87000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+87800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+88000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+88800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+89000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+89800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+90000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+90800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+91000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+91800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+92000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+92800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+93000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+93800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+94000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+94800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+95000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+95800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+96000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+96800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+97000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+97800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+98000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+98800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+99000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+99800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9A000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9A800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9B000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9B800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9C000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9C800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9D000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9D800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9E000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9E800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9F000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9F800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A0000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A0800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A1000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A1800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A2000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A2800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A3000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A3800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A4000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A4800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A5000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A5800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A6000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A6800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A7000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A7800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A8000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A8800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A9000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A9800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AA000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AA800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AB000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AB800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AC000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AC800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AD000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AD800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AE000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AE800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AF000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AF800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B0000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B0800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B1000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B1800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B2000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B2800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B3000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B3800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B4000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B4800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B5000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B5800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B6000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B6800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B7000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B7800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B8000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B8800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B9000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B9800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BA000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BA800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BB000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BB800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BC000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BC800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BD000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BD800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BE000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BE800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BF000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BF800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C0000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C0800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C1000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C1800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C2000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C2800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C3000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C3800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C4000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C4800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C5000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C5800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C6000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C6800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C7000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C7800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C8000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C8800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C9000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C9800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CA000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CA800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CB000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CB800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CC000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CC800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CD000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CD800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CE000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CE800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CF000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CF800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D0000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D0800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D1000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D1800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D2000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D2800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D3000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D3800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D4000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D4800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D5000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D5800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D6000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D6800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D7000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D7800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D8000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D8800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D9000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D9800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DA000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DA800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DB000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DB800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DC000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DC800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DD000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DD800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DE000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DE800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF800 */ +222,223,224,225,223,223,223,223,223,223,223,223,223,223,223,223, /* U+E0000 */ +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+E0800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E2000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E2800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E3000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E3800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E4000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E4800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E5000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E5800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E6000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E6800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E7000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E7800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E8000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E8800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E9000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E9800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EA000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EA800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EB000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EB800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EC000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EC800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+ED000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+ED800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EE000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EE800 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EF000 */ +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EF800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0000 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F1000 */ @@ -1218,7 +1311,7 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE000 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FF000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,202, /* U+FF800 */ +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,226, /* U+FF800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100000 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101000 */ @@ -1250,10 +1343,10 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E000 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E800 */ 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10F000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,202, /* U+10F800 */ +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,226, /* U+10F800 */ }; -const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ +const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */ /* block 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1300,539 +1393,539 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 70, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33, 33, 71, 30, 31, 72, 73, 74, 74, 30, 31, 75, 76, 77, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, - 78, 79, 80, 81, 82, 33, 83, 83, 33, 84, 33, 85, 33, 33, 33, 33, - 83, 33, 33, 86, 33, 87, 88, 33, 89, 90, 33, 91, 33, 33, 33, 90, - 33, 92, 93, 33, 33, 94, 33, 33, 33, 33, 33, 33, 33, 95, 33, 33, + 78, 79, 80, 81, 82, 33, 83, 83, 33, 84, 33, 85, 86, 33, 33, 33, + 83, 87, 33, 88, 33, 89, 90, 33, 91, 92, 33, 93, 94, 33, 33, 92, + 33, 95, 96, 33, 33, 97, 33, 33, 33, 33, 33, 33, 33, 98, 33, 33, /* block 5 */ - 96, 33, 33, 96, 33, 33, 33, 33, 96, 97, 98, 98, 99, 33, 33, 33, - 33, 33,100, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 99, 33, 33, 99, 33, 33, 33,100, 99,101,102,102,103, 33, 33, 33, + 33, 33,104, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33, 33,105, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, -101,101,101,101,101,101,101,101,101,102,102,102,102,102,102,102, -102,102, 14, 14, 14, 14,102,102,102,102,102,102,102,102,102,102, -102,102, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -101,101,101,101,101, 14, 14, 14, 14, 14,103,103,102, 14,102, 14, +106,106,106,106,106,106,106,106,106,107,107,107,107,107,107,107, +107,107, 14, 14, 14, 14,107,107,107,107,107,107,107,107,107,107, +107,107, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +106,106,106,106,106, 14, 14, 14, 14, 14,108,108,107, 14,107, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, /* block 6 */ -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,105,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -106,107,106,107,102,108,106,107,109,109,110,111,111,111, 4,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,110,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +111,112,111,112,107,113,111,112,114,114,115,116,116,116, 4,117, /* block 7 */ -109,109,109,109,108, 14,112, 4,113,113,113,109,114,109,115,115, -116,117,118,117,117,119,117,117,120,121,122,117,123,117,117,117, -124,125,109,126,117,117,127,117,117,128,117,117,129,130,130,130, -116,131,132,131,131,133,131,131,134,135,136,131,137,131,131,131, -138,139,140,141,131,131,142,131,131,143,131,131,144,145,145,146, -147,148,149,149,149,150,151,152,106,107,106,107,106,107,106,107, -106,107,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -155,156,157,116,158,159,160,106,107,161,106,107,116,162,162,162, +114,114,114,114,113, 14,118, 4,119,119,119,114,120,114,121,121, +122,123,124,123,123,125,123,123,126,127,128,123,129,123,123,123, +130,131,114,132,123,123,133,123,123,134,123,123,135,136,136,136, +122,137,138,137,137,139,137,137,140,141,142,137,143,137,137,137, +144,145,146,147,137,137,148,137,137,149,137,137,150,151,151,152, +153,154,155,155,155,156,157,158,111,112,111,112,111,112,111,112, +111,112,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +161,162,163,164,165,166,167,111,112,168,111,112,122,169,169,169, /* block 8 */ -163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, -164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, -164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, -165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, -165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, -166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, /* block 9 */ -167,168,169,170,170,104,104,170,171,171,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -172,167,168,167,168,167,168,167,168,167,168,167,168,167,168,173, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, +174,175,176,177,177,109,109,177,178,178,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +179,174,175,174,175,174,175,174,175,174,175,174,175,174,175,180, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, /* block 10 */ -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,109,109,109,109,109,109,109,109, -109,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, -174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, -174,174,174,174,174,174,174,109,109,175,176,176,176,176,176,176, -109,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, -177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +114,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,114,114,182,183,183,183,183,183,183, +114,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, /* block 11 */ -177,177,177,177,177,177,177,178,109, 4,179,109,109,109,109,180, -109,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, -181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, -181,181,181,181,181,181,181,181,181,181,181,181,181,181,182,181, -183,181,181,183,181,181,183,181,109,109,109,109,109,109,109,109, -184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, -184,184,184,184,184,184,184,184,184,184,184,109,109,109,109,109, -184,184,184,183,183,109,109,109,109,109,109,109,109,109,109,109, +184,184,184,184,184,184,184,185,114, 4,186,114,114,187,187,188, +114,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,190,189, +191,189,189,191,189,189,191,189,114,114,114,114,114,114,114,114, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,114,114,114,114,114, +192,192,192,191,191,114,114,114,114,114,114,114,114,114,114,114, /* block 12 */ -185,185,185,185,185,109,186,186,186,187,187,188, 4,187,189,189, -190,190,190,190,190,190,190,190,190,190,190, 4,185,109,187, 4, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -102,191,191,191,191,191,191,191,191,191,191,104,104,104,104,104, -104,104,104,104,104,104,190,190,190,190,190,190,190,190,190,190, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,187,187,187,187,191,191, -104,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +193,193,193,193,193, 22,194,194,194,195,195,196, 4,195,197,197, +198,198,198,198,198,198,198,198,198,198,198, 4, 22,114,195, 4, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +107,199,199,199,199,199,199,199,199,199,199,109,109,109,109,109, +109,109,109,109,109,109,198,198,198,198,198,198,198,198,198,198, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,195,195,195,195,199,199, +109,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 13 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,187,191,190,190,190,190,190,190,190, 22,189,190, -190,190,190,190,190,192,192,190,190,189,190,190,190,190,191,191, -193,193,193,193,193,193,193,193,193,193,191,191,191,189,189,191, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,195,199,198,198,198,198,198,198,198, 22,197,198, +198,198,198,198,198,200,200,198,198,197,198,198,198,198,199,199, +201,201,201,201,201,201,201,201,201,201,199,199,199,197,197,199, /* block 14 */ -194,194,194,194,194,194,194,194,194,194,194,194,194,194,109,195, -196,197,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, -197,197,197,197,197,197,197,197,197,197,197,109,109,196,196,196, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,114,203, +204,205,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,114,114,204,204,204, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 15 */ -198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, -198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, -198,198,198,198,198,198,199,199,199,199,199,199,199,199,199,199, -199,198,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -200,200,200,200,200,200,200,200,200,200,201,201,201,201,201,201, -201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, -201,201,201,201,201,201,201,201,201,201,201,202,202,202,202,202, -202,202,202,202,203,203,204,205,205,205,203,109,109,109,109,109, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,207,207,207,207,207,207,207,207,207,207, +207,206,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +208,208,208,208,208,208,208,208,208,208,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,210,210,210,210,210, +210,210,210,210,211,211,212,213,213,213,211,114,114,114,114,114, /* block 16 */ -206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, -206,206,206,206,206,206,207,207,207,207,208,207,207,207,207,207, -207,207,207,207,208,207,207,207,208,207,207,207,207,207,109,109, -209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,109, -210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, -210,210,210,210,210,210,210,210,210,211,211,211,109,109,212,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,215,215,215,215,216,215,215,215,215,215, +215,215,215,215,216,215,215,215,216,215,215,215,215,215,114,114, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,114, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,219,219,219,114,114,220,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 17 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -191,109,191,191,191,191,191,191,191,191,191,191,191,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,190,190,190,190,190,190,190,190,190,190,190,190, -190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, /* block 18 */ -213,213,213,214,215,215,215,215,215,215,215,215,215,215,215,215, -215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, -215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, -215,215,215,215,215,215,215,215,215,215,213,214,213,215,214,214, -214,213,213,213,213,213,213,213,213,214,214,214,214,213,214,214, -215,104,104,213,213,213,213,213,215,215,215,215,215,215,215,215, -215,215,213,213, 4, 4,216,216,216,216,216,216,216,216,216,216, -217,218,215,215,215,215,215,215,109,215,215,215,215,215,215,215, +221,221,221,222,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,221,222,221,223,222,222, +222,221,221,221,221,221,221,221,221,222,222,222,222,221,222,222, +223,109,109,221,221,221,221,221,223,223,223,223,223,223,223,223, +223,223,221,221, 4, 4,224,224,224,224,224,224,224,224,224,224, +225,226,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* block 19 */ -109,219,220,220,109,221,221,221,221,221,221,221,221,109,109,221, -221,109,109,221,221,221,221,221,221,221,221,221,221,221,221,221, -221,221,221,221,221,221,221,221,221,109,221,221,221,221,221,221, -221,109,221,109,109,109,221,221,221,221,109,109,219,221,222,220, -220,219,219,219,219,109,109,220,220,109,109,220,220,219,221,109, -109,109,109,109,109,109,109,222,109,109,109,109,221,221,109,221, -221,221,219,219,109,109,223,223,223,223,223,223,223,223,223,223, -221,221,224,224,225,225,225,225,225,225,226,224,109,109,109,109, +227,228,229,229,114,227,227,227,227,227,227,227,227,114,114,227, +227,114,114,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,114,227,227,227,227,227,227, +227,114,227,114,114,114,227,227,227,227,114,114,228,227,230,229, +229,228,228,228,228,114,114,229,229,114,114,229,229,228,227,114, +114,114,114,114,114,114,114,230,114,114,114,114,227,227,114,227, +227,227,228,228,114,114,231,231,231,231,231,231,231,231,231,231, +227,227,232,232,233,233,233,233,233,233,234,232,114,114,114,114, /* block 20 */ -109,227,227,228,109,229,229,229,229,229,229,109,109,109,109,229, -229,109,109,229,229,229,229,229,229,229,229,229,229,229,229,229, -229,229,229,229,229,229,229,229,229,109,229,229,229,229,229,229, -229,109,229,229,109,229,229,109,229,229,109,109,227,109,228,228, -228,227,227,109,109,109,109,227,227,109,109,227,227,227,109,109, -109,227,109,109,109,109,109,109,109,229,229,229,229,109,229,109, -109,109,109,109,109,109,230,230,230,230,230,230,230,230,230,230, -227,227,229,229,229,227,109,109,109,109,109,109,109,109,109,109, +114,235,235,236,114,237,237,237,237,237,237,114,114,114,114,237, +237,114,114,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,114,237,237,237,237,237,237, +237,114,237,237,114,237,237,114,237,237,114,114,235,114,236,236, +236,235,235,114,114,114,114,235,235,114,114,235,235,235,114,114, +114,235,114,114,114,114,114,114,114,237,237,237,237,114,237,114, +114,114,114,114,114,114,238,238,238,238,238,238,238,238,238,238, +235,235,237,237,237,235,114,114,114,114,114,114,114,114,114,114, /* block 21 */ -109,231,231,232,109,233,233,233,233,233,233,233,233,233,109,233, -233,233,109,233,233,233,233,233,233,233,233,233,233,233,233,233, -233,233,233,233,233,233,233,233,233,109,233,233,233,233,233,233, -233,109,233,233,109,233,233,233,233,233,109,109,231,233,232,232, -232,231,231,231,231,231,109,231,231,232,109,232,232,231,109,109, -233,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -233,233,231,231,109,109,234,234,234,234,234,234,234,234,234,234, -235,236,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,239,239,240,114,241,241,241,241,241,241,241,241,241,114,241, +241,241,114,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,114,241,241,241,241,241,241, +241,114,241,241,114,241,241,241,241,241,114,114,239,241,240,240, +240,239,239,239,239,239,114,239,239,240,114,240,240,239,114,114, +241,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +241,241,239,239,114,114,242,242,242,242,242,242,242,242,242,242, +243,244,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 22 */ -109,237,238,238,109,239,239,239,239,239,239,239,239,109,109,239, -239,109,109,239,239,239,239,239,239,239,239,239,239,239,239,239, -239,239,239,239,239,239,239,239,239,109,239,239,239,239,239,239, -239,109,239,239,109,239,239,239,239,239,109,109,237,239,240,237, -238,237,237,237,237,109,109,238,238,109,109,238,238,237,109,109, -109,109,109,109,109,109,237,240,109,109,109,109,239,239,109,239, -239,239,237,237,109,109,241,241,241,241,241,241,241,241,241,241, -242,239,243,243,243,243,243,243,109,109,109,109,109,109,109,109, +114,245,246,246,114,247,247,247,247,247,247,247,247,114,114,247, +247,114,114,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,114,247,247,247,247,247,247, +247,114,247,247,114,247,247,247,247,247,114,114,245,247,248,245, +246,245,245,245,245,114,114,246,246,114,114,246,246,245,114,114, +114,114,114,114,114,114,245,248,114,114,114,114,247,247,114,247, +247,247,245,245,114,114,249,249,249,249,249,249,249,249,249,249, +250,247,251,251,251,251,251,251,114,114,114,114,114,114,114,114, /* block 23 */ -109,109,244,245,109,245,245,245,245,245,245,109,109,109,245,245, -245,109,245,245,245,245,109,109,109,245,245,109,245,109,245,245, -109,109,109,245,245,109,109,109,245,245,245,109,109,109,245,245, -245,245,245,245,245,245,245,245,245,245,109,109,109,109,246,247, -244,247,247,109,109,109,247,247,247,109,247,247,247,244,109,109, -245,109,109,109,109,109,109,246,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,248,248,248,248,248,248,248,248,248,248, -249,249,249,250,250,250,250,250,250,251,250,109,109,109,109,109, +114,114,252,253,114,253,253,253,253,253,253,114,114,114,253,253, +253,114,253,253,253,253,114,114,114,253,253,114,253,114,253,253, +114,114,114,253,253,114,114,114,253,253,253,114,114,114,253,253, +253,253,253,253,253,253,253,253,253,253,114,114,114,114,254,255, +252,255,255,114,114,114,255,255,255,114,255,255,255,252,114,114, +253,114,114,114,114,114,114,254,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,256,256,256,256,256,256,256,256,256,256, +257,257,257,258,258,258,258,258,258,259,258,114,114,114,114,114, /* block 24 */ -109,252,252,252,109,253,253,253,253,253,253,253,253,109,253,253, -253,109,253,253,253,253,253,253,253,253,253,253,253,253,253,253, -253,253,253,253,253,253,253,253,253,109,253,253,253,253,253,253, -253,253,253,253,109,253,253,253,253,253,109,109,109,253,254,254, -254,252,252,252,252,109,254,254,254,109,254,254,254,254,109,109, -109,109,109,109,109,254,254,109,253,253,109,109,109,109,109,109, -253,253,254,254,109,109,255,255,255,255,255,255,255,255,255,255, -109,109,109,109,109,109,109,109,256,256,256,256,256,256,256,257, +260,261,261,261,114,262,262,262,262,262,262,262,262,114,262,262, +262,114,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,114,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,114,114,114,262,260,260, +260,261,261,261,261,114,260,260,260,114,260,260,260,260,114,114, +114,114,114,114,114,260,260,114,262,262,114,114,114,114,114,114, +262,262,260,260,114,114,263,263,263,263,263,263,263,263,263,263, +114,114,114,114,114,114,114,114,264,264,264,264,264,264,264,265, /* block 25 */ -109,109,258,258,109,259,259,259,259,259,259,259,259,109,259,259, -259,109,259,259,259,259,259,259,259,259,259,259,259,259,259,259, -259,259,259,259,259,259,259,259,259,109,259,259,259,259,259,259, -259,259,259,259,109,259,259,259,259,259,109,109,260,259,258,260, -258,258,261,258,258,109,260,258,258,109,258,258,260,260,109,109, -109,109,109,109,109,261,261,109,109,109,109,109,109,109,259,109, -259,259,260,260,109,109,262,262,262,262,262,262,262,262,262,262, -109,259,259,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,266,267,267,114,268,268,268,268,268,268,268,268,114,268,268, +268,114,268,268,268,268,268,268,268,268,268,268,268,268,268,268, +268,268,268,268,268,268,268,268,268,114,268,268,268,268,268,268, +268,268,268,268,114,268,268,268,268,268,114,114,266,268,267,266, +267,267,269,267,267,114,266,267,267,114,267,267,266,266,114,114, +114,114,114,114,114,269,269,114,114,114,114,114,114,114,268,114, +268,268,266,266,114,114,270,270,270,270,270,270,270,270,270,270, +114,268,268,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 26 */ -109,109,263,263,109,264,264,264,264,264,264,264,264,109,264,264, -264,109,264,264,264,264,264,264,264,264,264,264,264,264,264,264, -264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, -264,264,264,264,264,264,264,264,264,264,264,109,109,264,265,263, -263,266,266,266,266,109,263,263,263,109,263,263,263,266,264,109, -109,109,109,109,109,109,109,265,109,109,109,109,109,109,109,109, -264,264,266,266,109,109,267,267,267,267,267,267,267,267,267,267, -268,268,268,268,268,268,109,109,109,269,264,264,264,264,264,264, +114,271,272,272,114,273,273,273,273,273,273,273,273,114,273,273, +273,114,273,273,273,273,273,273,273,273,273,273,273,273,273,273, +273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273, +273,273,273,273,273,273,273,273,273,273,273,114,114,273,274,272, +272,271,271,271,271,114,272,272,272,114,272,272,272,271,273,114, +114,114,114,114,114,114,114,274,114,114,114,114,114,114,114,114, +273,273,271,271,114,114,275,275,275,275,275,275,275,275,275,275, +276,276,276,276,276,276,114,114,114,277,273,273,273,273,273,273, /* block 27 */ -109,109,270,270,109,271,271,271,271,271,271,271,271,271,271,271, -271,271,271,271,271,271,271,109,109,109,271,271,271,271,271,271, -271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, -271,271,109,271,271,271,271,271,271,271,271,271,109,271,109,109, -271,271,271,271,271,271,271,109,109,109,272,109,109,109,109,273, -270,270,272,272,272,109,272,109,270,270,270,270,270,270,270,273, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,270,270,274,109,109,109,109,109,109,109,109,109,109,109, +114,114,278,278,114,279,279,279,279,279,279,279,279,279,279,279, +279,279,279,279,279,279,279,114,114,114,279,279,279,279,279,279, +279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279, +279,279,114,279,279,279,279,279,279,279,279,279,114,279,114,114, +279,279,279,279,279,279,279,114,114,114,280,114,114,114,114,281, +278,278,280,280,280,114,280,114,278,278,278,278,278,278,278,281, +114,114,114,114,114,114,282,282,282,282,282,282,282,282,282,282, +114,114,278,278,283,114,114,114,114,114,114,114,114,114,114,114, /* block 28 */ -109,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275, -275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275, -275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275, -275,276,275,277,276,276,276,276,276,276,276,109,109,109,109, 5, -275,275,275,275,275,275,278,276,276,276,276,276,276,276,276,279, -280,280,280,280,280,280,280,280,280,280,279,279,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284, +284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284, +284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284, +284,285,284,286,285,285,285,285,285,285,285,114,114,114,114, 5, +284,284,284,284,284,284,287,285,285,285,285,285,285,285,285,288, +289,289,289,289,289,289,289,289,289,289,288,288,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 29 */ -109,281,281,109,281,109,109,281,281,109,281,109,109,281,109,109, -109,109,109,109,281,281,281,281,109,281,281,281,281,281,281,281, -109,281,281,281,109,281,109,281,109,109,281,281,109,281,281,281, -281,282,281,283,282,282,282,282,282,282,109,282,282,281,109,109, -281,281,281,281,281,109,284,109,282,282,282,282,282,282,109,109, -285,285,285,285,285,285,285,285,285,285,109,109,281,281,281,281, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,290,290,114,290,114,114,290,290,114,290,114,114,290,114,114, +114,114,114,114,290,290,290,290,114,290,290,290,290,290,290,290, +114,290,290,290,114,290,114,290,114,114,290,290,114,290,290,290, +290,291,290,292,291,291,291,291,291,291,114,291,291,290,114,114, +290,290,290,290,290,114,293,114,291,291,291,291,291,291,114,114, +294,294,294,294,294,294,294,294,294,294,114,114,290,290,290,290, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 30 */ -286,287,287,287,288,288,288,288,288,288,288,288,288,288,288,288, -288,288,288,287,288,287,287,287,289,289,287,287,287,287,287,287, -290,290,290,290,290,290,290,290,290,290,291,291,291,291,291,291, -291,291,291,291,287,289,287,289,287,289,292,293,292,293,294,294, -286,286,286,286,286,286,286,286,109,286,286,286,286,286,286,286, -286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, -286,286,286,286,286,286,286,286,286,286,286,286,286,109,109,109, -109,289,289,289,289,289,289,289,289,289,289,289,289,289,289,294, +295,296,296,296,297,297,297,297,297,297,297,297,297,297,297,297, +297,297,297,296,297,296,296,296,298,298,296,296,296,296,296,296, +299,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300, +300,300,300,300,296,298,296,298,296,298,301,302,301,302,303,303, +295,295,295,295,295,295,295,295,114,295,295,295,295,295,295,295, +295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, +295,295,295,295,295,295,295,295,295,295,295,295,295,114,114,114, +114,298,298,298,298,298,298,298,298,298,298,298,298,298,298,303, /* block 31 */ -289,289,289,289,289,288,289,289,286,286,286,286,286,289,289,289, -289,289,289,289,289,289,289,289,109,289,289,289,289,289,289,289, -289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289, -289,289,289,289,289,289,289,289,289,289,289,289,289,109,287,287, -287,287,287,287,287,287,289,287,287,287,287,287,287,109,287,287, -288,288,288,288,288, 19, 19, 19, 19,288,288,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +298,298,298,298,298,297,298,298,295,295,295,295,295,298,298,298, +298,298,298,298,298,298,298,298,114,298,298,298,298,298,298,298, +298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, +298,298,298,298,298,298,298,298,298,298,298,298,298,114,296,296, +296,296,296,296,296,296,298,296,296,296,296,296,296,114,296,296, +297,297,297,297,297, 19, 19, 19, 19,297,297,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 32 */ -295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, -295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, -295,295,295,295,295,295,295,295,295,295,295,296,296,297,297,297, -297,298,297,297,297,297,297,297,296,297,297,298,298,297,297,295, -299,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300, -295,295,295,295,295,295,298,298,297,297,295,295,295,295,297,297, -297,295,296,296,296,295,295,296,296,296,296,296,296,296,295,295, -295,297,297,297,297,295,295,295,295,295,295,295,295,295,295,295, +304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +304,304,304,304,304,304,304,304,304,304,304,305,305,306,306,306, +306,307,306,306,306,306,306,306,305,306,306,307,307,306,306,304, +308,308,308,308,308,308,308,308,308,308,309,309,309,309,309,309, +304,304,304,304,304,304,307,307,306,306,304,304,304,304,306,306, +306,304,305,305,305,304,304,305,305,305,305,305,305,305,304,304, +304,306,306,306,306,304,304,304,304,304,304,304,304,304,304,304, /* block 33 */ -295,295,297,296,298,297,297,296,296,296,296,296,296,297,295,296, -299,299,299,299,299,299,299,299,299,299,296,296,296,297,301,301, -302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, -302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, -302,302,302,302,302,302,109,302,109,109,109,109,109,302,109,109, -303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, -303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, -303,303,303,303,303,303,303,303,303,303,303, 4,304,303,303,303, +304,304,306,305,307,306,306,305,305,305,305,305,305,306,304,305, +308,308,308,308,308,308,308,308,308,308,305,305,305,306,310,310, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,311,311,114,311,114,114,114,114,114,311,114,114, +312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, +312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, +312,312,312,312,312,312,312,312,312,312,312, 4,313,312,312,312, /* block 34 */ -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, /* block 35 */ -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, -306,306,306,306,306,306,306,306,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +315,315,315,315,315,315,315,315,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, /* block 36 */ -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,109,308,308,308,308,109,109, -308,308,308,308,308,308,308,109,308,109,308,308,308,308,109,109, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,114,317,317,317,317,114,114, +317,317,317,317,317,317,317,114,317,114,317,317,317,317,114,114, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, /* block 37 */ -308,308,308,308,308,308,308,308,308,109,308,308,308,308,109,109, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,109, -308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, +317,317,317,317,317,317,317,317,317,114,317,317,317,317,114,114, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,114, +317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, /* block 38 */ -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,308,308,308,308,109,109,309,309,309, -310,310,310,310,310,310,310,310,310,311,311,311,311,311,311,311, -311,311,311,311,311,311,311,311,311,311,311,311,311,109,109,109, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,114,114,318,318,318, +319,319,319,319,319,319,319,319,319,320,320,320,320,320,320,320, +320,320,320,320,320,320,320,320,320,320,320,320,320,114,114,114, /* block 39 */ -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -312,312,312,312,312,312,312,312,312,312,109,109,109,109,109,109, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,109,109,109,109,109,109,109,109,109,109,109, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +321,321,321,321,321,321,321,321,321,321,114,114,114,114,114,114, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, +322,322,322,322,322,114,114,114,114,114,114,114,114,114,114,114, /* block 40 */ -314,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +323,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, /* block 41 */ -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, /* block 42 */ -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,316,316,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,325,325,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, /* block 43 */ -317,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,319,320,109,109,109, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321, 4, 4, 4,322,322, -322,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +326,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, +327,327,327,327,327,327,327,327,327,327,327,328,329,114,114,114, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330, 4, 4, 4,331,331, +331,330,330,330,330,330,330,330,330,114,114,114,114,114,114,114, /* block 44 */ -323,323,323,323,323,323,323,323,323,323,323,323,323,109,323,323, -323,323,324,324,324,109,109,109,109,109,109,109,109,109,109,109, -325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, -325,325,326,326,326, 4, 4,109,109,109,109,109,109,109,109,109, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,328,328,109,109,109,109,109,109,109,109,109,109,109,109, -329,329,329,329,329,329,329,329,329,329,329,329,329,109,329,329, -329,109,330,330,109,109,109,109,109,109,109,109,109,109,109,109, +332,332,332,332,332,332,332,332,332,332,332,332,332,114,332,332, +332,332,333,333,333,114,114,114,114,114,114,114,114,114,114,114, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, +334,334,335,335,335, 4, 4,114,114,114,114,114,114,114,114,114, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,337,337,114,114,114,114,114,114,114,114,114,114,114,114, +338,338,338,338,338,338,338,338,338,338,338,338,338,114,338,338, +338,114,339,339,114,114,114,114,114,114,114,114,114,114,114,114, /* block 45 */ -331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, -331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, -331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, -331,331,331,331,332,332,333,332,332,332,332,332,332,332,333,333, -333,333,333,333,333,333,332,333,333,332,332,332,332,332,332,332, -332,332,332,332,334,334,334,335,334,334,334,336,331,332,109,109, -337,337,337,337,337,337,337,337,337,337,109,109,109,109,109,109, -338,338,338,338,338,338,338,338,338,338,109,109,109,109,109,109, +340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, +340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, +340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, +340,340,340,340,341,341,342,341,341,341,341,341,341,341,342,342, +342,342,342,342,342,342,341,342,342,341,341,341,341,341,341,341, +341,341,341,341,343,343,343,344,343,343,343,345,340,341,114,114, +346,346,346,346,346,346,346,346,346,346,114,114,114,114,114,114, +347,347,347,347,347,347,347,347,347,347,114,114,114,114,114,114, /* block 46 */ -339,339, 4, 4,339, 4,340,339,339,339,339,341,341,341,342,109, -343,343,343,343,343,343,343,343,343,343,109,109,109,109,109,109, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,345,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,109,109,109,109,109,109,109,109, +348,348, 4, 4,348, 4,349,348,348,348,348,350,350,350,351,114, +352,352,352,352,352,352,352,352,352,352,114,114,114,114,114,114, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,354,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,114,114,114,114,114,114,114,114, /* block 47 */ -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -344,344,344,344,344,344,344,344,344,341,344,109,109,109,109,109, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,109,109,109,109,109,109,109,109,109,109, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, +353,353,353,353,353,353,353,353,353,350,353,114,114,114,114,114, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,114,114,114,114,114,114,114,114,114,114, /* block 48 */ -346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346, -346,346,346,346,346,346,346,346,346,346,346,346,346,109,109,109, -347,347,347,348,348,348,348,347,347,348,348,348,109,109,109,109, -348,348,347,348,348,348,348,348,348,347,347,347,109,109,109,109, -349,109,109,109,350,350,351,351,351,351,351,351,351,351,351,351, -352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, -352,352,352,352,352,352,352,352,352,352,352,352,352,352,109,109, -352,352,352,352,352,109,109,109,109,109,109,109,109,109,109,109, +355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, +355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,114, +356,356,356,357,357,357,357,356,356,357,357,357,114,114,114,114, +357,357,356,357,357,357,357,357,357,356,356,356,114,114,114,114, +358,114,114,114,359,359,360,360,360,360,360,360,360,360,360,360, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,114,114, +361,361,361,361,361,114,114,114,114,114,114,114,114,114,114,114, /* block 49 */ -353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, -353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, -353,353,353,353,353,353,353,353,353,353,353,353,109,109,109,109, -354,354,354,354,354,355,355,355,354,354,355,354,354,354,354,354, -354,353,353,353,353,353,353,353,354,354,109,109,109,109,109,109, -356,356,356,356,356,356,356,356,356,356,357,109,109,109,358,358, -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, +362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, +362,362,362,362,362,362,362,362,362,362,362,362,114,114,114,114, +363,363,363,363,363,364,364,364,363,363,364,363,363,363,363,363, +363,362,362,362,362,362,362,362,363,363,114,114,114,114,114,114, +365,365,365,365,365,365,365,365,365,365,366,114,114,114,367,367, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, /* block 50 */ -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,361,361,362,362,361,109,109,363,363, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, -364,364,364,364,364,365,366,365,366,366,366,366,366,366,366,109, -366,367,366,367,367,366,366,366,366,366,366,366,366,365,365,365, -365,365,365,366,366,366,366,366,366,366,366,366,366,109,109,366, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,370,370,371,371,370,114,114,372,372, +373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, +373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, +373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, +373,373,373,373,373,374,375,374,375,375,375,375,375,375,375,114, +375,376,375,376,376,375,375,375,375,375,375,375,375,374,374,374, +374,374,374,375,375,375,375,375,375,375,375,375,375,114,114,375, /* block 51 */ -368,368,368,368,368,368,368,368,368,368,109,109,109,109,109,109, -368,368,368,368,368,368,368,368,368,368,109,109,109,109,109,109, -369,369,369,369,369,369,369,370,369,369,369,369,369,369,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +377,377,377,377,377,377,377,377,377,377,114,114,114,114,114,114, +377,377,377,377,377,377,377,377,377,377,114,114,114,114,114,114, +378,378,378,378,378,378,378,379,378,378,378,378,378,378,114,114, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,380,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 52 */ -371,371,371,371,372,373,373,373,373,373,373,373,373,373,373,373, -373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, -373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, -373,373,373,373,371,372,371,371,371,371,371,372,371,372,372,372, -372,372,371,372,372,373,373,373,373,373,373,373,109,109,109,109, -374,374,374,374,374,374,374,374,374,374,375,375,375,375,375,375, -375,376,376,376,376,376,376,376,376,376,376,371,371,371,371,371, -371,371,371,371,376,376,376,376,376,376,376,376,376,109,109,109, +381,381,381,381,382,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,381,382,381,381,381,381,381,382,381,382,382,382, +382,382,381,382,382,383,383,383,383,383,383,383,114,114,114,114, +384,384,384,384,384,384,384,384,384,384,385,385,385,385,385,385, +385,386,386,386,386,386,386,386,386,386,386,381,381,381,381,381, +381,381,381,381,386,386,386,386,386,386,386,386,386,114,114,114, /* block 53 */ -377,377,378,379,379,379,379,379,379,379,379,379,379,379,379,379, -379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, -379,378,377,377,377,377,378,378,377,377,378,377,378,378,379,379, -380,380,380,380,380,380,380,380,380,380,379,379,379,379,379,379, -381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, -381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, -381,381,381,381,381,381,382,383,382,382,383,383,383,382,383,382, -382,382,383,383,109,109,109,109,109,109,109,109,384,384,384,384, +387,387,388,389,389,389,389,389,389,389,389,389,389,389,389,389, +389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +389,388,387,387,387,387,388,388,387,387,388,387,387,387,389,389, +390,390,390,390,390,390,390,390,390,390,389,389,389,389,389,389, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,392,393,392,392,393,393,393,392,393,392, +392,392,393,393,114,114,114,114,114,114,114,114,394,394,394,394, /* block 54 */ -385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385, -385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385, -385,385,385,385,386,386,386,386,386,386,386,386,387,387,387,387, -387,387,387,387,386,386,387,387,109,109,109,388,388,388,388,388, -389,389,389,389,389,389,389,389,389,389,109,109,109,385,385,385, -390,390,390,390,390,390,390,390,390,390,391,391,391,391,391,391, -391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, -391,391,391,391,391,391,391,391,392,392,392,392,392,392,393,393, +395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395, +395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395, +395,395,395,395,396,396,396,396,396,396,396,396,397,397,397,397, +397,397,397,397,396,396,397,397,114,114,114,398,398,398,398,398, +399,399,399,399,399,399,399,399,399,399,114,114,114,395,395,395, +400,400,400,400,400,400,400,400,400,400,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,402,402,402,402,402,402,403,403, /* block 55 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -394,394,394,394,394,394,394,394,109,109,109,109,109,109,109,109, -104,104,104, 4,104,104,104,104,104,104,104,104,104,104,104,104, -104,395,104,104,104,104,104,104,104,396,396,396,396,104,396,396, -396,396,395,395,104,396,396,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +404,404,404,404,404,404,404,404,114,114,114,114,114,114,114,114, +109,109,109, 4,109,109,109,109,109,109,109,109,109,109,109,109, +109,405,109,109,109,109,109,109,109,406,406,406,406,109,406,406, +406,406,405,405,109,406,406,114,109,109,114,114,114,114,114,114, /* block 56 */ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33,116,116,116,116,116,397,101,101,101,101, -101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, -101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, -101,101,101,101,101,101,101,101,101,101,101,101,101,110,110,110, -110,110,101,101,101,101,110,110,110,110,110, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33,398,399, 33, 33, 33,400, 33, 33, + 33, 33, 33, 33, 33, 33,122,122,122,122,122,407,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,115,115,115, +115,115,106,106,106,106,115,115,115,115,115, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33,408,409, 33, 33, 33,410, 33, 33, /* block 57 */ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,101,101,101,101,101, -101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, -101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,110, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,104,104,104,104, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,115, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,114,114,114,114,114,114,109,109,109,109, /* block 58 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, @@ -1841,12 +1934,12 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, -401,402, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, +411,412, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, /* block 59 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, - 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,403, 33, 33,404, 33, + 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,413, 33, 33,414, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, @@ -1855,57 +1948,57 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, /* block 60 */ -405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406, -405,405,405,405,405,405,109,109,406,406,406,406,406,406,109,109, -405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406, -405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406, -405,405,405,405,405,405,109,109,406,406,406,406,406,406,109,109, -116,405,116,405,116,405,116,405,109,406,109,406,109,406,109,406, -405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406, -407,407,408,408,408,408,409,409,410,410,411,411,412,412,109,109, +415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416, +415,415,415,415,415,415,114,114,416,416,416,416,416,416,114,114, +415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416, +415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416, +415,415,415,415,415,415,114,114,416,416,416,416,416,416,114,114, +122,415,122,415,122,415,122,415,114,416,114,416,114,416,114,416, +415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416, +417,417,418,418,418,418,419,419,420,420,421,421,422,422,114,114, /* block 61 */ -405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413, -405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413, -405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413, -405,405,116,414,116,109,116,116,406,406,415,415,416,108,417,108, -108,108,116,414,116,109,116,116,418,418,418,418,416,108,108,108, -405,405,116,116,109,109,116,116,406,406,419,419,109,108,108,108, -405,405,116,116,116,157,116,116,406,406,420,420,161,108,108,108, -109,109,116,414,116,109,116,116,421,421,422,422,416,108,108,109, +415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423, +415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423, +415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423, +415,415,122,424,122,114,122,122,416,416,425,425,426,113,427,113, +113,113,122,424,122,114,122,122,428,428,428,428,426,113,113,113, +415,415,122,122,114,114,122,122,416,416,429,429,114,113,113,113, +415,415,122,122,122,163,122,122,416,416,430,430,168,113,113,113, +114,114,122,424,122,114,122,122,431,431,432,432,426,113,113,114, /* block 62 */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,423,423, 22, 22, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,433,433, 22, 22, 9, 9, 9, 9, 9, 9, 4, 4, 21, 25, 6, 21, 21, 25, 6, 21, - 4, 4, 4, 4, 4, 4, 4, 4,424,425, 22, 22, 22, 22, 22, 3, + 4, 4, 4, 4, 4, 4, 4, 4,434,435, 22, 22, 22, 22, 22, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 21, 25, 4, 4, 4, 4, 15, 15, 4, 4, 4, 8, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, - 22, 22, 22, 22, 22,426, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 23,101,109,109, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,101, + 22, 22, 22, 22, 22,436, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23,106,114,114, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,106, /* block 63 */ - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,109, -101,101,101,101,101,101,101,101,101,101,101,101,101,109,109,109, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,114, +106,106,106,106,106,106,106,106,106,106,106,106,106,114,114,114, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -104,104,104,104,104,104,104,104,104,104,104,104,104,427,427,427, -427,104,427,427,427,104,104,104,104,104,104,104,104,104,104,104, -104,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +109,109,109,109,109,109,109,109,109,109,109,109,109,380,380,380, +380,109,380,380,380,109,109,109,109,109,109,109,109,109,109,109, +109,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 64 */ - 19, 19,428, 19, 19, 19, 19,428, 19, 19,429,428,428,428,429,429, -428,428,428,429, 19,428, 19, 19, 8,428,428,428,428,428, 19, 19, - 19, 19, 19, 19,428, 19,430, 19,428, 19,431,432,428,428, 19,429, -428,428,433,428,429,396,396,396,396,429, 19, 19,429,429,428,428, - 8, 8, 8, 8, 8,428,429,429,429,429, 19, 8, 19, 19,434, 19, + 19, 19,437, 19, 19, 19, 19,437, 19, 19,438,437,437,437,438,438, +437,437,437,438, 19,437, 19, 19, 8,437,437,437,437,437, 19, 19, + 19, 19, 19, 19,437, 19,439, 19,437, 19,440,441,437,437, 19,438, +437,437,442,437,438,406,406,406,406,438, 19, 19,438,438,437,437, + 8, 8, 8, 8, 8,437,438,438,438,438, 19, 8, 19, 19,443, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, -436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, +445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, /* block 65 */ -437,437,437, 30, 31,437,437,437,437, 23,109,109,109,109,109,109, +446,446,446, 30, 31,446,446,446,446, 23,114,114,114,114,114,114, 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 8, 8, 19, 19, 19, 19, 8, 19, 19, 8, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -1942,15 +2035,15 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114, /* block 69 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, @@ -1958,10 +2051,10 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439, 23, 23, 23, 23, 23, 23, + 19, 19, 19, 19, 19, 19,447,447,447,447,447,447,447,447,447,447, +447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, +448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, +448,448,448,448,448,448,448,448,448,448, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, /* block 71 */ @@ -1995,7 +2088,7 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 74 */ -109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -2015,14 +2108,14 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* block 76 */ -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, -440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, /* block 77 */ 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, @@ -2039,150 +2132,150 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 19, 19, 8, 8, 8, 8, 8, 8,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 8, 8, 8, 8, 8, 19, 19, 8, 8, 8, 8, 8, 8, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 79 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19,114, 19, 19, 19, 19, 19, 19, + 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 80 */ -441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, -441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, -441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,109, -442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, -442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, -442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,109, - 30, 31,443,444,445,446,447, 30, 31, 30, 31, 30, 31,448,449,450, -451, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,101,101,452,452, +450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, +450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, +450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,114, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,114, + 30, 31,452,453,454,455,456, 30, 31, 30, 31, 30, 31,457,458,459, +460, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,106,106,461,461, /* block 81 */ -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154, -153,154,153,154,453,454,454,454,454,454,454,153,154,153,154,455, -455,455,153,154,109,109,109,109,109,456,456,456,456,457,456,456, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160, +159,160,159,160,462,463,463,463,463,463,463,159,160,159,160,464, +464,464,159,160,114,114,114,114,114,465,465,465,465,466,465,465, /* block 82 */ -458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, -458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, -458,458,458,458,458,458,109,458,109,109,109,109,109,458,109,109, -459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, -459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, -459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, -459,459,459,459,459,459,459,459,109,109,109,109,109,109,109,460, -461,109,109,109,109,109,109,109,109,109,109,109,109,109,109,462, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,114,467,114,114,114,114,114,467,114,114, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468,468,468,468,468,468,468,468,114,114,114,114,114,114,114,469, +470,114,114,114,114,114,114,114,114,114,114,114,114,114,114,471, /* block 83 */ -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, -308,308,308,308,308,308,308,109,109,109,109,109,109,109,109,109, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109, -170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, -170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,114,114,114,114,114,114,114,114,114, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, /* block 84 */ 4, 4, 21, 25, 21, 25, 4, 4, 4, 21, 25, 4, 21, 25, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 21, 25, 4, 4, - 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,102, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,107, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4, 4, 4, 4, + 9, 4, 6,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 85 */ -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,109,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,109,109,109,109,109,109,109,109,109,109,109,109, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,114,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,114,114,114,114,114,114,114,114,114,114,114,114, /* block 86 */ -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, /* block 87 */ -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, -463,463,463,463,463,463,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +472,472,472,472,472,472,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114, /* block 88 */ - 3, 4, 4, 4, 19,464,396,465, 6, 7, 6, 7, 6, 7, 6, 7, + 3, 4, 4, 4, 19,473,406,474, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7, - 19,465,465,465,465,465,465,465,465,465,104,104,104,104,466,466, - 9,102,102,102,102,102, 19, 19,465,465,465,464,396, 4, 19, 19, -109,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, + 19,474,474,474,474,474,474,474,474,474,109,109,109,109,475,475, + 9,107,107,107,107,107, 19, 19,474,474,474,473,406, 4, 19, 19, +114,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, /* block 89 */ -467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -467,467,467,467,467,467,467,109,109,104,104, 14, 14,468,468,467, - 9,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469, 4,102,470,470,469, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,114,114,109,109, 14, 14,477,477,476, + 9,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478, 4,107,479,479,478, /* block 90 */ -109,109,109,109,109,471,471,471,471,471,471,471,471,471,471,471, -471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, -471,471,471,471,471,471,471,471,471,471,471,471,471,471,109,109, -109,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, +114,114,114,114,114,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,114,114, +114,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, /* block 91 */ -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,109, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,114, 19, 19, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, -471,471,471,471,471,471,471,471,471,471,471,109,109,109,109,109, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,114,114,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, + 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, /* block 92 */ -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,109, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,114, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, 19, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, 19, /* block 93 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, @@ -2190,1099 +2283,1339 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,109, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,114, /* block 94 */ -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, -474,474,474,474,474,474,474,474, 19, 19, 19, 19, 19, 19, 19, 19, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 95 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, /* block 96 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,109,109,109,109,109,109,109,109,109,109, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,114,114,114,114,114,114,114,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 97 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 98 */ -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,477,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,486,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, /* block 99 */ -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, /* block 100 */ -476,476,476,476,476,476,476,476,476,476,476,476,476,109,109,109, -478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, -478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, -478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, -478,478,478,478,478,478,478,109,109,109,109,109,109,109,109,109, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,480,480,480,480,480,480,481,481, +485,485,485,485,485,485,485,485,485,485,485,485,485,114,114,114, +487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487, +487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487, +487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487, +487,487,487,487,487,487,487,114,114,114,114,114,114,114,114,114, +488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, +488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, +488,488,488,488,488,488,488,488,489,489,489,489,489,489,490,490, /* block 101 */ -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, /* block 102 */ -482,482,482,482,482,482,482,482,482,482,482,482,483,484,484,484, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -485,485,485,485,485,485,485,485,485,485,482,482,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,167,168,167,168,167,168,486,170, -171,171,171,487,170,170,170,170,170,170,170,170,170,170,487,398, +491,491,491,491,491,491,491,491,491,491,491,491,492,493,493,493, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +494,494,494,494,494,494,494,494,494,494,491,491,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,495,177, +178,178,178,496,177,177,177,177,177,177,177,177,177,177,496,408, /* block 103 */ -167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168, -167,168,167,168,167,168,167,168,109,109,109,109,109,109,109,170, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,489,489,489,489,489,489,489,489,489,489, -490,490,491,491,491,491,491,491,109,109,109,109,109,109,109,109, +174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175, +174,175,174,175,174,175,174,175,174,175,174,175,408,408,114,177, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,498,498,498,498,498,498,498,498,498,498, +499,499,500,500,500,500,500,500,114,114,114,114,114,114,114,114, /* block 104 */ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14,102,102,102,102,102,102,102,102,102, + 14, 14, 14, 14, 14, 14, 14,107,107,107,107,107,107,107,107,107, 14, 14, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, -101, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,492, 30, 31, +106, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,501, 30, 31, /* block 105 */ - 30, 31, 30, 31, 30, 31, 30, 31,102, 14, 14, 30, 31,493, 33,109, - 30, 31, 30, 31,109,109,109,109,109,109,109,109,109,109,109,109, - 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,494,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,101,101, 33, 20, 20, 20, 20, 20, + 30, 31, 30, 31, 30, 31, 30, 31,107, 14, 14, 30, 31,502, 33,114, + 30, 31, 30, 31, 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, + 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,503,504,505,506,114,114, +507,508,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114, 20,106,106, 33, 20, 20, 20, 20, 20, /* block 106 */ -495,495,496,495,495,495,496,495,495,495,495,496,495,495,495,495, -495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495, -495,495,495,497,497,496,496,497,498,498,498,498,109,109,109,109, - 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,109,109,109,109,109,109, -499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, -499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, -499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, -499,499,499,499,500,500,500,500,109,109,109,109,109,109,109,109, +509,509,510,509,509,509,510,509,509,509,509,510,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,511,511,510,510,511,512,512,512,512,114,114,114,114, + 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,114,114,114,114,114,114, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,514,514,514,514,114,114,114,114,114,114,114,114, /* block 107 */ -501,501,502,502,502,502,502,502,502,502,502,502,502,502,502,502, -502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502, -502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502, -502,502,502,502,501,501,501,501,501,501,501,501,501,501,501,501, -501,501,501,501,503,109,109,109,109,109,109,109,109,109,504,504, -505,505,505,505,505,505,505,505,505,505,109,109,109,109,109,109, -213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, -213,213,215,215,215,215,215,215,217,217,217,215,109,109,109,109, +515,515,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,517,114,114,114,114,114,114,114,114,114,518,518, +519,519,519,519,519,519,519,519,519,519,114,114,114,114,114,114, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,223,223,223,223,223,223,225,225,225,223,114,114,114,114, /* block 108 */ -506,506,506,506,506,506,506,506,506,506,507,507,507,507,507,507, -507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, -507,507,507,507,507,507,508,508,508,508,508,508,508,508,509,509, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,511,511,511,511,511,511,511,511,511, -511,511,512,512,109,109,109,109,109,109,109,109,109,109,109,513, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,109,109,109, +520,520,520,520,520,520,520,520,520,520,521,521,521,521,521,521, +521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, +521,521,521,521,521,521,522,522,522,522,522,522,522,522, 4,523, +524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524, +524,524,524,524,524,524,524,525,525,525,525,525,525,525,525,525, +525,525,526,526,114,114,114,114,114,114,114,114,114,114,114,527, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,114,114,114, /* block 109 */ -514,514,514,515,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,514,515,515,514,514,514,514,515,515,514,515,515,515, -515,517,517,517,517,517,517,517,517,517,517,517,517,517,109,102, -518,518,518,518,518,518,518,518,518,518,109,109,109,109,517,517, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +528,528,528,529,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,528,529,529,528,528,528,528,529,529,528,529,529,529, +529,531,531,531,531,531,531,531,531,531,531,531,531,531,114,107, +532,532,532,532,532,532,532,532,532,532,114,114,114,114,531,531, +304,304,304,304,304,306,533,304,304,304,304,304,304,304,304,304, +308,308,308,308,308,308,308,308,308,308,304,304,304,304,304,114, /* block 110 */ -519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, -519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, -519,519,519,519,519,519,519,519,519,520,520,520,520,520,520,521, -521,520,520,521,521,520,520,109,109,109,109,109,109,109,109,109, -519,519,519,520,519,519,519,519,519,519,519,519,520,521,109,109, -522,522,522,522,522,522,522,522,522,522,109,109,523,523,523,523, -295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, -524,295,295,295,295,295,295,301,301,301,295,296,109,109,109,109, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,535,535,535,535,535,535,536, +536,535,535,536,536,535,535,114,114,114,114,114,114,114,114,114, +534,534,534,535,534,534,534,534,534,534,534,534,535,536,114,114, +537,537,537,537,537,537,537,537,537,537,114,114,538,538,538,538, +304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +533,304,304,304,304,304,304,310,310,310,304,305,306,305,304,304, /* block 111 */ -525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, -525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, -525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, -526,525,526,526,526,525,525,526,526,525,525,525,525,525,526,526, -525,526,525,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,525,525,527,528,528, -529,529,529,529,529,529,529,529,529,529,529,530,531,531,530,530, -532,532,529,533,533,530,531,109,109,109,109,109,109,109,109,109, +539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539, +539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539, +539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539, +540,539,540,540,540,539,539,540,540,539,539,539,539,539,540,540, +539,540,539,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,539,539,541,542,542, +543,543,543,543,543,543,543,543,543,543,543,544,545,545,544,544, +546,546,543,547,547,544,545,114,114,114,114,114,114,114,114,114, /* block 112 */ -109,308,308,308,308,308,308,109,109,308,308,308,308,308,308,109, -109,308,308,308,308,308,308,109,109,109,109,109,109,109,109,109, -308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,317,317,317,317,317,317,114,114,317,317,317,317,317,317,114, +114,317,317,317,317,317,317,114,114,114,114,114,114,114,114,114, +317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 14,106,106,106,106, +114,114,114,114, 33,122,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 113 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529, -529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529, -529,529,529,530,530,531,530,530,531,530,530,532,530,531,109,109, -534,534,534,534,534,534,534,534,534,534,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543, +543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543, +543,543,543,544,544,545,544,544,545,544,544,546,544,545,114,114, +548,548,548,548,548,548,548,548,548,548,114,114,114,114,114,114, /* block 114 */ -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, /* block 115 */ -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, /* block 116 */ -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, /* block 117 */ -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, /* block 118 */ -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, /* block 119 */ -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, /* block 120 */ -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, /* block 121 */ -536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536, -536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536, -536,536,536,536,109,109,109,109,109,109,109,109,109,109,109,109, -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, -306,306,306,306,306,306,306,109,109,109,109,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, -307,307,307,307,307,307,307,307,307,307,307,307,109,109,109,109, +550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550, +550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,114,114,114,114,114,114,114,114,114,114,114,114, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, +315,315,315,315,315,315,315,114,114,114,114,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,316,316,316,316,316,316,316,316,316,114,114,114,114, /* block 122 */ -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, /* block 123 */ -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, /* block 124 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,109,109, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,114,114, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, /* block 125 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 126 */ - 33, 33, 33, 33, 33, 33, 33,109,109,109,109,109,109,109,109,109, -109,109,109,178,178,178,178,178,109,109,109,109,109,184,181,184, -184,184,184,184,184,184,184,184,184,539,184,184,184,184,184,184, -184,184,184,184,184,184,184,109,184,184,184,184,184,109,184,109, -184,184,109,184,184,109,184,184,184,184,184,184,184,184,184,184, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, + 33, 33, 33, 33, 33, 33, 33,114,114,114,114,114,114,114,114,114, +114,114,114,185,185,185,185,185,114,114,114,114,114,192,189,192, +192,192,192,192,192,192,192,192,192,553,192,192,192,192,192,192, +192,192,192,192,192,192,192,114,192,192,192,192,192,114,192,114, +192,192,114,192,192,114,192,192,192,192,192,192,192,192,192,192, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 127 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,540,540,540,540,540,540,540,540,540,540,540,540,540,540, -540,540,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,554,554,554,554,554,554,554,554,554,554,554,554,554,554, +554,554,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 128 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 129 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191, 6, 7, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199, 7, 6, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 130 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -109,109,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -191,191,191,191,191,191,191,191,191,191,191,191,188, 19,109,109, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +114,114,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +199,199,199,199,199,199,199,199,199,199,199,199,196,197,114,114, /* block 131 */ -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, - 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,109,109,109,109,109,109, -104,104,104,104,104,104,104,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,114,114,114,114,114,114, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,114,114, 4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15, - 4, 4, 4,109, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4, - 4, 4, 8, 9, 8, 8, 8,109, 4, 5, 4, 4,109,109,109,109, -191,191,191,191,191,109,191,191,191,191,191,191,191,191,191,191, + 4, 4, 4,114, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4, + 4, 4, 8, 9, 8, 8, 8,114, 4, 5, 4, 4,114,114,114,114, +199,199,199,199,199,114,199,199,199,199,199,199,199,199,199,199, /* block 132 */ -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,109,109, 22, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,114,114, 22, /* block 133 */ -109, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4, +114, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4, 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 7, 8, 6, - 7, 4, 6, 7, 4, 4,469,469,469,469,469,469,469,469,469,469, -102,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, + 7, 4, 6, 7, 4, 4,478,478,478,478,478,478,478,478,478,478, +107,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, /* block 134 */ -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,541,541, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,109, -109,109,472,472,472,472,472,472,109,109,472,472,472,472,472,472, -109,109,472,472,472,472,472,472,109,109,472,472,472,109,109,109, - 5, 5, 8, 14, 19, 5, 5,109, 19, 8, 8, 8, 8, 19, 19,109, -426,426,426,426,426,426,426,426,426, 22, 22, 22, 19, 19,109,109, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,555,555, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,114, +114,114,481,481,481,481,481,481,114,114,481,481,481,481,481,481, +114,114,481,481,481,481,481,481,114,114,481,481,481,114,114,114, + 5, 5, 8, 14, 19, 5, 5,114, 19, 8, 8, 8, 8, 19, 19,114, +436,436,436,436,436,436,436,436,436, 22, 22, 22, 19, 19,114,114, /* block 135 */ -542,542,542,542,542,542,542,542,542,542,542,542,109,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,109,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,109,542,542,109,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,109,109, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +556,556,556,556,556,556,556,556,556,556,556,556,114,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,114,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,114,556,556,114,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,114,114, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 136 */ -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,109,109,109,109,109, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,114,114,114,114,114, /* block 137 */ - 4, 4, 4,109,109,109,109, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 4, 4, 4,114,114,114,114, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, -543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543, -543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543, -543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543, -543,543,543,543,543,544,544,544,544,545,545,545,545,545,545,545, + 23, 23, 23, 23,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, +557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, +557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, +557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, +557,557,557,557,557,558,558,558,558,559,559,559,559,559,559,559, /* block 138 */ -545,545,545,545,545,545,545,545,545,545,544,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +559,559,559,559,559,559,559,559,559,559,558,558,559,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114, +559,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,104,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,114,114, /* block 139 */ -546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546, -546,546,546,546,546,546,546,546,546,546,546,546,546,109,109,109, -547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547, -547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547, -547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547, -547,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 140 */ -548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, -548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,109, -549,549,549,549,109,109,109,109,109,109,109,109,109,109,109,109, -550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550, -550,551,550,550,550,550,550,550,550,550,551,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560, +560,560,560,560,560,560,560,560,560,560,560,560,560,114,114,114, +561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, +561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, +561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, +561,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +109, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,114,114,114,114, /* block 141 */ -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,109,553, -554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554, -554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554, -554,554,554,554,109,109,109,109,554,554,554,554,554,554,554,554, -555,556,556,556,556,556,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, +562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, +563,563,563,563,114,114,114,114,114,114,114,114,114,114,114,114, +564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564, +564,565,564,564,564,564,564,564,564,564,565,114,114,114,114,114, +566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, +566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, +566,566,566,566,566,566,567,567,567,567,567,114,114,114,114,114, /* block 142 */ -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,558,558,558,558,558,558,558,558, -558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, -558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, -559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, -559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, -559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568, +568,568,568,568,568,568,568,568,568,568,568,568,568,568,114,569, +570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570, +570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570, +570,570,570,570,114,114,114,114,570,570,570,570,570,570,570,570, +571,572,572,572,572,572,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 143 */ -560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560, -560,560,560,560,560,560,560,560,560,560,560,560,560,560,109,109, -561,561,561,561,561,561,561,561,561,561,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, +573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, +573,573,573,573,573,573,573,573,574,574,574,574,574,574,574,574, +574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, +574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, +575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, +575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, +575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, /* block 144 */ -562,562,562,562,562,562,109,109,562,109,562,562,562,562,562,562, -562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, -562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, -562,562,562,562,562,562,109,562,562,109,109,109,562,109,109,562, -563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, -563,563,563,563,563,563,109,564,565,565,565,565,565,565,565,565, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576, +576,576,576,576,576,576,576,576,576,576,576,576,576,576,114,114, +577,577,577,577,577,577,577,577,577,577,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 145 */ -566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, -566,566,566,566,566,566,567,567,567,567,567,567,109,109,109,568, -569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569, -569,569,569,569,569,569,569,569,569,569,109,109,109,109,109,570, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, +578,578,578,578,578,578,578,578,114,114,114,114,114,114,114,114, +579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, +579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, +579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, +579,579,579,579,114,114,114,114,114,114,114,114,114,114,114,580, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 146 */ -571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571, -571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571, -572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572, -572,572,572,572,572,572,572,572,109,109,109,109,109,109,572,572, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, /* block 147 */ -573,574,574,574,109,574,574,109,109,109,109,109,574,574,574,574, -573,573,573,573,109,573,573,573,109,573,573,573,573,573,573,573, -573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, -573,573,573,573,109,109,109,109,574,574,574,109,109,109,109,574, -575,575,575,575,575,575,575,575,109,109,109,109,109,109,109,109, -576,576,576,576,576,576,576,576,576,109,109,109,109,109,109,109, -577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, -577,577,577,577,577,577,577,577,577,577,577,577,577,578,578,579, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,581,114,114,114,114,114,114,114,114,114, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, +581,581,581,581,581,581,114,114,114,114,114,114,114,114,114,114, +581,581,581,581,581,581,581,581,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 148 */ -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,109,109,109,581,581,581,581,581,581,581, +582,582,582,582,582,582,114,114,582,114,582,582,582,582,582,582, 582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, -582,582,582,582,582,582,109,109,583,583,583,583,583,583,583,583, -584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, -584,584,584,109,109,109,109,109,585,585,585,585,585,585,585,585, +582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, +582,582,582,582,582,582,114,582,582,114,114,114,582,114,114,582, +583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, +583,583,583,583,583,583,114,584,585,585,585,585,585,585,585,585, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +586,586,586,586,586,586,586,587,587,588,588,588,588,588,588,588, /* block 149 */ -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,114, +114,114,114,114,114,114,114,590,590,590,590,590,590,590,590,590, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 150 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, -587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,109, +591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, +591,591,591,591,591,591,592,592,592,592,592,592,114,114,114,593, +594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594, +594,594,594,594,594,594,594,594,594,594,114,114,114,114,114,595, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 151 */ -588,589,588,590,590,590,590,590,590,590,590,590,590,590,590,590, -590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, -590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, -590,590,590,590,590,590,590,590,589,589,589,589,589,589,589,589, -589,589,589,589,589,589,589,591,591,591,591,591,591,591,109,109, -109,109,592,592,592,592,592,592,592,592,592,592,592,592,592,592, -592,592,592,592,592,592,593,593,593,593,593,593,593,593,593,593, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597, +597,597,597,597,597,597,597,597,114,114,114,114,114,114,597,597, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 152 */ -594,594,595,596,596,596,596,596,596,596,596,596,596,596,596,596, -596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, -596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, -595,595,595,594,594,594,594,595,595,594,594,597,597,598,597,597, -597,597,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, -599,599,599,599,599,599,599,599,599,109,109,109,109,109,109,109, -600,600,600,600,600,600,600,600,600,600,109,109,109,109,109,109, +598,599,599,599,114,599,599,114,114,114,114,114,599,599,599,599, +598,598,598,598,114,598,598,598,114,598,598,598,598,598,598,598, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,598,598,598,114,114,114,114,599,599,599,114,114,114,114,599, +600,600,600,600,600,600,600,600,114,114,114,114,114,114,114,114, +601,601,601,601,601,601,601,601,601,114,114,114,114,114,114,114, +602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602, +602,602,602,602,602,602,602,602,602,602,602,602,602,603,603,604, /* block 153 */ -601,601,601,602,602,602,602,602,602,602,602,602,602,602,602,602, -602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602, -602,602,602,602,602,602,602,601,601,601,601,601,603,601,601,601, -601,601,601,601,601,109,604,604,604,604,604,604,604,604,604,604, -605,605,605,605,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605, +605,605,605,605,605,605,605,605,605,605,605,605,605,606,606,606, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +607,607,607,607,607,607,607,607,608,607,607,607,607,607,607,607, +607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607, +607,607,607,607,607,609,609,114,114,114,114,610,610,610,610,610, +611,611,611,611,611,611,611,114,114,114,114,114,114,114,114,114, /* block 154 */ -606,606,607,608,608,608,608,608,608,608,608,608,608,608,608,608, -608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608, -608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608, -608,608,608,607,607,607,606,606,606,606,606,606,606,606,606,607, -607,608,608,608,608,609,609,609,609,109,109,109,109,109,109,109, -610,610,610,610,610,610,610,610,610,610,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, +612,612,612,612,612,612,114,114,114,613,613,613,613,613,613,613, +614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614, +614,614,614,614,614,614,114,114,615,615,615,615,615,615,615,615, +616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, +616,616,616,114,114,114,114,114,617,617,617,617,617,617,617,617, /* block 155 */ -611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611, -611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611, -611,611,611,611,611,611,611,611,611,611,611,612,613,612,613,613, -612,612,612,612,612,612,613,612,109,109,109,109,109,109,109,109, -614,614,614,614,614,614,614,614,614,614,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, +618,618,114,114,114,114,114,114,114,619,619,619,619,114,114,114, +114,114,114,114,114,114,114,114,114,620,620,620,620,620,620,620, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 156 */ -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 157 */ -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622, +622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,114, /* block 158 */ -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, -616,616,616,109,109,109,109,109,109,109,109,109,109,109,109,109, -617,617,617,617,109,109,109,109,109,109,109,109,109,109,109,109, +623,624,623,625,625,625,625,625,625,625,625,625,625,625,625,625, +625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625, +625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625, +625,625,625,625,625,625,625,625,624,624,624,624,624,624,624,624, +624,624,624,624,624,624,624,626,626,626,626,626,626,626,114,114, +114,114,627,627,627,627,627,627,627,627,627,627,627,627,627,627, +627,627,627,627,627,627,628,628,628,628,628,628,628,628,628,628, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,624, /* block 159 */ -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, +629,629,630,631,631,631,631,631,631,631,631,631,631,631,631,631, +631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, +631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, +630,630,630,629,629,629,629,630,630,629,629,632,632,633,632,632, +632,632,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634, +634,634,634,634,634,634,634,634,634,114,114,114,114,114,114,114, +635,635,635,635,635,635,635,635,635,635,114,114,114,114,114,114, /* block 160 */ -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, -618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +636,636,636,637,637,637,637,637,637,637,637,637,637,637,637,637, +637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637, +637,637,637,637,637,637,637,636,636,636,636,636,638,636,636,636, +636,636,636,636,636,114,639,639,639,639,639,639,639,639,639,639, +640,640,640,640,114,114,114,114,114,114,114,114,114,114,114,114, +641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, +641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, +641,641,641,642,643,643,641,114,114,114,114,114,114,114,114,114, /* block 161 */ -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, +644,644,645,646,646,646,646,646,646,646,646,646,646,646,646,646, +646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, +646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, +646,646,646,645,645,645,644,644,644,644,644,644,644,644,644,645, +645,646,646,646,646,647,647,647,647,114,114,114,114,647,114,114, +648,648,648,648,648,648,648,648,648,648,646,114,114,114,114,114, +114,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649, +649,649,649,649,649,114,114,114,114,114,114,114,114,114,114,114, /* block 162 */ -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650, +650,650,114,650,650,650,650,650,650,650,650,650,650,650,650,650, +650,650,650,650,650,650,650,650,650,650,650,650,651,651,651,652, +652,652,651,651,652,651,652,652,653,653,653,653,653,653,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 163 */ -619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619, -619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619, -619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619, -619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619, -619,619,619,619,619,109,109,109,109,109,109,109,109,109,109,109, -619,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, -620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, -620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,655, +656,656,656,655,655,655,655,655,655,655,655,114,114,114,114,114, +657,657,657,657,657,657,657,657,657,657,114,114,114,114,114,114, /* block 164 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,621, -621,621,621,622,622,622,622,622,622,622,622,622,622,622,622,622, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,658,659,659,114,660,660,660,660,660,660,660,660,114,114,660, +660,114,114,660,660,660,660,660,660,660,660,660,660,660,660,660, +660,660,660,660,660,660,660,660,660,114,660,660,660,660,660,660, +660,114,660,660,114,660,660,660,660,660,114,114,658,660,661,659, +658,659,659,659,659,114,114,659,659,114,114,659,659,659,114,114, +114,114,114,114,114,114,114,661,114,114,114,114,114,660,660,660, +660,660,659,659,114,114,658,658,658,658,658,658,658,114,114,114, +658,658,658,658,658,114,114,114,114,114,114,114,114,114,114,114, /* block 165 */ -469,467,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, +663,664,664,665,665,665,665,665,665,664,665,664,664,663,664,665, +665,664,665,665,662,662,666,662,114,114,114,114,114,114,114,114, +667,667,667,667,667,667,667,667,667,667,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 166 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,669, +670,670,671,671,671,671,114,114,670,670,670,670,671,671,670,671, +671,672,672,672,672,672,672,672,672,672,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 167 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19,109,109, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19,623,395,104,104,104, 19, 19, 19,395,623,623, -623,623,623, 22, 22, 22, 22, 22, 22, 22, 22,104,104,104,104,104, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +674,674,674,675,675,675,675,675,675,675,675,674,674,675,674,675, +675,676,676,676,673,114,114,114,114,114,114,114,114,114,114,114, +677,677,677,677,677,677,677,677,677,677,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 168 */ -104,104,104, 19, 19,104,104,104,104,104,104,104, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,104,104,104,104, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, +678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, +678,678,678,678,678,678,678,678,678,678,678,679,680,679,680,680, +679,679,679,679,679,679,680,679,114,114,114,114,114,114,114,114, +681,681,681,681,681,681,681,681,681,681,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 169 */ -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,624,624,624,545,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, +682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, +684,684,684,684,684,684,684,684,684,684,685,685,685,685,685,685, +685,685,685,114,114,114,114,114,114,114,114,114,114,114,114,686, /* block 170 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,687,687,687,687,687,687,687,687,114,114,114,114,114,114,114, /* block 171 */ -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,429,429, -429,429,429,429,429,109,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, /* block 172 */ -428,428,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,428,109,428,428, -109,109,428,109,109,428,428,109,109,428,428,428,428,109,428,428, -428,428,428,428,428,428,429,429,429,429,109,429,109,429,429,429, -429,429,429,429,109,429,429,429,429,429,429,429,429,429,429,429, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, +688,688,688,688,688,688,688,688,688,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 173 */ -429,429,429,429,428,428,109,428,428,428,428,109,109,428,428,428, -428,428,428,428,428,109,428,428,428,428,428,428,428,109,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,428,428,109,428,428,428,428,109, -428,428,428,428,428,109,428,109,109,109,428,428,428,428,428,428, -428,109,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,114, +690,690,690,690,690,114,114,114,114,114,114,114,114,114,114,114, /* block 174 */ -428,428,428,428,428,428,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, /* block 175 */ -429,429,429,429,429,429,429,429,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 176 */ -428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,109,109,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428, 8,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429, 8,429,429,429,429, -429,429,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428, 8,429,429,429,429, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, /* block 177 */ -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429, 8,429,429,429,429,429,429,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428, 8,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 8, -429,429,429,429,429,429,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 8, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,114,114,114,114,114,114,114, +692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, +692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,114, +693,693,693,693,693,693,693,693,693,693,114,114,114,114,694,694, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 178 */ -429,429,429,429,429,429,429,429,429, 8,429,429,429,429,429,429, -428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, -428,428,428,428,428,428,428,428,428, 8,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429, 8,429,429,429,429,429,429,428,429,109,109, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695, +695,695,695,695,695,695,695,695,695,695,695,695,695,695,114,114, +696,696,696,696,696,697,114,114,114,114,114,114,114,114,114,114, /* block 179 */ -191,191,191,191,109,191,191,191,191,191,191,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, -109,191,191,109,191,109,109,191,109,191,191,191,191,191,191,191, -191,191,191,109,191,191,191,191,109,191,109,191,109,109,109,109, -109,109,191,109,109,109,109,191,109,191,109,191,109,191,191,191, -109,191,191,109,191,109,109,191,109,191,109,191,109,191,109,191, -109,191,191,109,191,109,109,191,191,191,191,109,191,191,191,191, -191,191,191,109,191,191,191,191,109,191,191,191,191,109,191,109, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +699,699,699,699,699,699,699,700,700,700,700,700,701,701,701,701, +702,702,702,702,700,701,114,114,114,114,114,114,114,114,114,114, +703,703,703,703,703,703,703,703,703,703,114,704,704,704,704,704, +704,704,114,698,698,698,698,698,698,698,698,698,698,698,698,698, +698,698,698,698,698,698,698,698,114,114,114,114,114,698,698,698, /* block 180 */ -191,191,191,191,191,191,191,191,191,191,109,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,109,109,109,109, -109,191,191,191,109,191,191,191,191,191,109,191,191,191,191,191, -191,191,191,191,191,191,191,191,191,191,191,191,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -186,186,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 181 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, +705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, +705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, +705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, +705,705,705,705,705,114,114,114,114,114,114,114,114,114,114,114, +705,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706, +706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706, +706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,114, /* block 182 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109, -109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109, -109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,707, +707,707,707,708,708,708,708,708,708,708,708,708,708,708,708,708, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 183 */ - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +478,476,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 184 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,625,625,625,625,625,625,625,625,625,625, -625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,114,114,114,114,114, +709,709,709,709,709,709,709,709,709,709,709,709,709,114,114,114, /* block 185 */ -626, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109, - 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109, - 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +709,709,709,709,709,709,709,709,709,114,114,114,114,114,114,114, +709,709,709,709,709,709,709,709,709,709,114,114,710,711,711,712, + 22, 22, 22, 22,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 186 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, - 19, 19, 19, 19, 19, 19,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114, /* block 187 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19,109, 19, 19, 19, 19, 19,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19,713,405,109,109,109, 19, 19, 19,405,713,713, +713,713,713, 22, 22, 22, 22, 22, 22, 22, 22,109,109,109,109,109, /* block 188 */ +109,109,109, 19, 19,109,109,109,109,109,109,109, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109, - 19,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 189 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19,109, 19, 19, 19, 19,109,109,109, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,714,714,714,559,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 190 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 191 */ -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109, 19, 19, 19, 19, 19, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,438,438, +438,438,438,438,438,114,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, /* block 192 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19,109,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +437,437,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,437,114,437,437, +114,114,437,114,114,437,437,114,114,437,437,437,437,114,437,437, +437,437,437,437,437,437,438,438,438,438,114,438,114,438,438,438, +438,438,438,438,114,438,438,438,438,438,438,438,438,438,438,438, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, /* block 193 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +438,438,438,438,437,437,114,437,437,437,437,114,114,437,437,437, +437,437,437,437,437,114,437,437,437,437,437,437,437,114,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,437,437,114,437,437,437,437,114, +437,437,437,437,437,114,437,114,114,114,437,437,437,437,437,437, +437,114,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, /* block 194 */ - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109, +437,437,437,437,437,437,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, /* block 195 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +438,438,438,438,438,438,438,438,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, /* block 196 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,109,109,109,109,109,109,109,109,109,109,109, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,114,114,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437, 8,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438, 8,438,438,438,438, +438,438,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437, 8,438,438,438,438, /* block 197 */ -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, -109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438, 8,438,438,438,438,438,438,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437, 8,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 8, +438,438,438,438,438,438,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 8, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, /* block 198 */ -426, 22,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, +438,438,438,438,438,438,438,438,438, 8,438,438,438,438,438,438, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437, 8,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438, 8,438,438,438,438,438,438,437,438,114,114, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, /* block 199 */ -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, /* block 200 */ -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,114,114,716,716,716,716,716,716,716,716,716, +717,717,717,717,717,717,717,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* block 201 */ -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, -426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +199,199,199,199,114,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +114,199,199,114,199,114,114,199,114,199,199,199,199,199,199,199, +199,199,199,114,199,199,199,199,114,199,114,199,114,114,114,114, +114,114,199,114,114,114,114,199,114,199,114,199,114,199,199,199, +114,199,199,114,199,114,114,199,114,199,114,199,114,199,114,199, +114,199,199,114,199,114,114,199,199,199,199,114,199,199,199,199, +199,199,199,114,199,199,199,199,114,199,199,199,199,114,199,114, /* block 202 */ -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538, -538,538,538,538,538,538,538,538,538,538,538,538,538,538,109,109, +199,199,199,199,199,199,199,199,199,199,114,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,114,114,114,114, +114,199,199,199,114,199,199,199,199,199,114,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +194,194,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 203 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 204 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, +114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114, + +/* block 205 */ + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 206 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,718,718,718,718,718,718,718,718,718,718, +718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718, + +/* block 207 */ +719, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114, + 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 208 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114, + +/* block 209 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, +114,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114, + +/* block 210 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, + +/* block 211 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, 19, 19, 19, 19, 19, + +/* block 212 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 213 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 214 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114, + 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 215 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 216 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 217 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 218 */ + 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 219 */ +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 220 */ +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,114,114,114,114,114,114,114,114,114,114,114, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, + +/* block 221 */ +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + +/* block 222 */ +436, 22,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + +/* block 223 */ +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, + +/* block 224 */ +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + +/* block 225 */ +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, + +/* block 226 */ +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,114,114, }; diff --git a/Foundation/src/pcre_xclass.c b/Foundation/src/pcre_xclass.c index 2bc8ea6d1..22fc78289 100644 --- a/Foundation/src/pcre_xclass.c +++ b/Foundation/src/pcre_xclass.c @@ -242,7 +242,7 @@ while ((t = *data++) != XCL_END) case PT_PXPUNCT: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P || - (c < 256 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop) + (c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop) return !negated; break; diff --git a/Foundation/src/ucp.h b/Foundation/src/ucp.h index d8b34bfcc..2fa00296e 100644 --- a/Foundation/src/ucp.h +++ b/Foundation/src/ucp.h @@ -192,7 +192,31 @@ enum { ucp_Miao, ucp_Sharada, ucp_Sora_Sompeng, - ucp_Takri + ucp_Takri, + /* New for Unicode 7.0.0: */ + ucp_Bassa_Vah, + ucp_Caucasian_Albanian, + ucp_Duployan, + ucp_Elbasan, + ucp_Grantha, + ucp_Khojki, + ucp_Khudawadi, + ucp_Linear_A, + ucp_Mahajani, + ucp_Manichaean, + ucp_Mende_Kikakui, + ucp_Modi, + ucp_Mro, + ucp_Nabataean, + ucp_Old_North_Arabian, + ucp_Old_Permic, + ucp_Pahawh_Hmong, + ucp_Palmyrene, + ucp_Psalter_Pahlavi, + ucp_Pau_Cin_Hau, + ucp_Siddham, + ucp_Tirhuta, + ucp_Warang_Citi }; #endif From 8f4e890e32af9bbde5d98a7dd99bc2089ccb0364 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 12:24:36 +0100 Subject: [PATCH 127/305] fixed GH #1571: ODBC Preparator memory leak --- Data/ODBC/src/Preparator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/ODBC/src/Preparator.cpp b/Data/ODBC/src/Preparator.cpp index c7645cf86..34ea95635 100644 --- a/Data/ODBC/src/Preparator.cpp +++ b/Data/ODBC/src/Preparator.cpp @@ -94,7 +94,7 @@ void Preparator::freeMemory() const break; case DT_WCHAR: - deleteCachedArray(it->first); + deleteCachedArray(it->first); break; case DT_UCHAR: From 6e9052398247cefbbd80b62755c6ea568c2ea4d6 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 12:27:33 +0100 Subject: [PATCH 128/305] fixed GH #1549: Latin2Encoding and 0xFF --- Foundation/src/Latin2Encoding.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Foundation/src/Latin2Encoding.cpp b/Foundation/src/Latin2Encoding.cpp index 8508385eb..02801c8ba 100644 --- a/Foundation/src/Latin2Encoding.cpp +++ b/Foundation/src/Latin2Encoding.cpp @@ -157,6 +157,7 @@ int Latin2Encoding::convert(int ch, unsigned char* bytes, int length) const case 0x016f: if (bytes && length >= 1) *bytes = 0xf9; return 1; case 0x0171: if (bytes && length >= 1) *bytes = 0xfb; return 1; case 0x0163: if (bytes && length >= 1) *bytes = 0xfe; return 1; + case 0x02d9: if (bytes && length >= 1) *bytes = 0xff; return 1; default: return 0; } } From d35677790f7b6d526dcd7aba303296c912fa9f73 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 12:49:14 +0100 Subject: [PATCH 129/305] GH #1538: update double-conversion to v1.1.5 --- Foundation/src/bignum-dtoa.cc | 11 +++--- Foundation/src/bignum.cc | 24 +++++++------ Foundation/src/cached-powers.cc | 1 + Foundation/src/double-conversion.cc | 53 ++++++++++++++++++++--------- Foundation/src/double-conversion.h | 6 ++-- Foundation/src/fast-dtoa.cc | 19 ++++++----- Foundation/src/fixed-dtoa.cc | 12 ++++--- Foundation/src/ieee.h | 4 +++ Foundation/src/strtod.cc | 2 ++ Foundation/src/utils.h | 14 ++++++-- 10 files changed, 94 insertions(+), 52 deletions(-) diff --git a/Foundation/src/bignum-dtoa.cc b/Foundation/src/bignum-dtoa.cc index b6c2e85d1..f1ad7a5ae 100644 --- a/Foundation/src/bignum-dtoa.cc +++ b/Foundation/src/bignum-dtoa.cc @@ -192,13 +192,13 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, delta_plus = delta_minus; } *length = 0; - while (true) { + for (;;) { uint16_t digit; digit = numerator->DivideModuloIntBignum(*denominator); ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. - buffer[(*length)++] = digit + '0'; + buffer[(*length)++] = static_cast(digit + '0'); // Can we stop already? // If the remainder of the division is less than the distance to the lower @@ -282,7 +282,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, // exponent (decimal_point), when rounding upwards. static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector(buffer), int* length) { + Vector buffer, int* length) { ASSERT(count >= 0); for (int i = 0; i < count - 1; ++i) { uint16_t digit; @@ -290,7 +290,7 @@ static void GenerateCountedDigits(int count, int* decimal_point, ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. - buffer[i] = digit + '0'; + buffer[i] = static_cast(digit + '0'); // Prepare for next iteration. numerator->Times10(); } @@ -300,7 +300,8 @@ static void GenerateCountedDigits(int count, int* decimal_point, if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { digit++; } - buffer[count - 1] = digit + '0'; + ASSERT(digit <= 10); + buffer[count - 1] = static_cast(digit + '0'); // Correct bad digits (in case we had a sequence of '9's). Propagate the // carry until we hat a non-'9' or til we reach the first digit. for (int i = count - 1; i > 0; --i) { diff --git a/Foundation/src/bignum.cc b/Foundation/src/bignum.cc index 747491a08..2743d67e8 100644 --- a/Foundation/src/bignum.cc +++ b/Foundation/src/bignum.cc @@ -40,6 +40,7 @@ Bignum::Bignum() template static int BitSize(S value) { + (void) value; // Mark variable as used. return 8 * sizeof(value); } @@ -122,9 +123,8 @@ void Bignum::AssignDecimalString(Vector value) { static int HexCharValue(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('a' <= c && c <= 'f') return 10 + c - 'a'; - if ('A' <= c && c <= 'F') return 10 + c - 'A'; - UNREACHABLE(); - return 0; // To make compiler happy. + ASSERT('A' <= c && c <= 'F'); + return 10 + c - 'A'; } @@ -501,13 +501,14 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { // Start by removing multiples of 'other' until both numbers have the same // number of digits. while (BigitLength() > other.BigitLength()) { - // This naive approach is extremely inefficient if the this divided other - // might be big. This function is implemented for doubleToString where + // This naive approach is extremely inefficient if `this` divided by other + // is big. This function is implemented for doubleToString where // the result should be small (less than 10). ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); + ASSERT(bigits_[used_digits_ - 1] < 0x10000); // Remove the multiples of the first digit. // Example this = 23 and other equals 9. -> Remove 2 multiples. - result += bigits_[used_digits_ - 1]; + result += static_cast(bigits_[used_digits_ - 1]); SubtractTimes(other, bigits_[used_digits_ - 1]); } @@ -523,13 +524,15 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { // Shortcut for easy (and common) case. int quotient = this_bigit / other_bigit; bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - result += quotient; + ASSERT(quotient < 0x10000); + result += static_cast(quotient); Clamp(); return result; } int division_estimate = this_bigit / (other_bigit + 1); - result += division_estimate; + ASSERT(division_estimate < 0x10000); + result += static_cast(division_estimate); SubtractTimes(other, division_estimate); if (other_bigit * (division_estimate + 1) > this_bigit) { @@ -560,8 +563,8 @@ static int SizeInHexChars(S number) { static char HexCharOfValue(int value) { ASSERT(0 <= value && value <= 16); - if (value < 10) return value + '0'; - return value - 10 + 'A'; + if (value < 10) return static_cast(value + '0'); + return static_cast(value - 10 + 'A'); } @@ -755,7 +758,6 @@ void Bignum::SubtractTimes(const Bignum& other, int factor) { Chunk difference = bigits_[i] - borrow; bigits_[i] = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); - ++i; } Clamp(); } diff --git a/Foundation/src/cached-powers.cc b/Foundation/src/cached-powers.cc index c67642919..d1359ffe4 100644 --- a/Foundation/src/cached-powers.cc +++ b/Foundation/src/cached-powers.cc @@ -152,6 +152,7 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( ASSERT(0 <= index && index < kCachedPowersLength); CachedPower cached_power = kCachedPowers[index]; ASSERT(min_exponent <= cached_power.binary_exponent); + (void) max_exponent; // Mark variable as used. ASSERT(cached_power.binary_exponent <= max_exponent); *decimal_exponent = cached_power.decimal_exponent; *power = DiyFp(cached_power.significand, cached_power.binary_exponent); diff --git a/Foundation/src/double-conversion.cc b/Foundation/src/double-conversion.cc index 2e9ec7859..c7bedeb2f 100644 --- a/Foundation/src/double-conversion.cc +++ b/Foundation/src/double-conversion.cc @@ -348,7 +348,6 @@ static BignumDtoaMode DtoaToBignumDtoaMode( case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; default: UNREACHABLE(); - return BIGNUM_DTOA_SHORTEST; // To silence compiler. } } @@ -403,8 +402,8 @@ void DoubleToStringConverter::DoubleToAscii(double v, vector, length, point); break; default: - UNREACHABLE(); fast_worked = false; + UNREACHABLE(); } if (fast_worked) return; @@ -462,6 +461,28 @@ static double SignedZero(bool sign) { } +// Returns true if 'c' is a decimal digit that is valid for the given radix. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the last +// condition was always true. By moving it into a separate function the +// compiler wouldn't warn anymore. +static bool IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} + +// Returns true if 'c' is a character digit that is valid for the given radix. +// The 'a_character' should be 'a' or 'A'. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the first +// condition was always false. By moving it into a separate function the +// compiler wouldn't warn anymore. +static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { + return radix > 10 && c >= a_character && c < a_character + radix - 10; +} + + // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. template static double RadixStringToIeee(const char* current, @@ -492,11 +513,11 @@ static double RadixStringToIeee(const char* current, do { int digit; - if (*current >= '0' && *current <= '9' && *current < '0' + radix) { + if (IsDecimalDigitForRadix(*current, radix)) { digit = static_cast(*current) - '0'; - } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { + } else if (IsCharacterDigitForRadix(*current, radix, 'a')) { digit = static_cast(*current) - 'a' + 10; - } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { + } else if (IsCharacterDigitForRadix(*current, radix, 'A')) { digit = static_cast(*current) - 'A' + 10; } else { if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { @@ -523,7 +544,7 @@ static double RadixStringToIeee(const char* current, exponent = overflow_bits_count; bool zero_tail = true; - while (true) { + for (;;) { ++current; if (current == end || !isDigit(*current, radix)) break; zero_tail = zero_tail && *current == '0'; @@ -577,7 +598,7 @@ double StringToDoubleConverter::StringToIeee( const char* input, int length, int* processed_characters_count, - bool read_as_double) { + bool read_as_double) const { const char* current = input; const char* end = input + length; @@ -600,7 +621,7 @@ double StringToDoubleConverter::StringToIeee( if (allow_leading_spaces || allow_trailing_spaces) { if (!AdvanceToNonspace(¤t, end)) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return empty_string_value_; } if (!allow_leading_spaces && (input != current)) { @@ -649,7 +670,7 @@ double StringToDoubleConverter::StringToIeee( } ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign ? -Double::Infinity() : Double::Infinity(); } } @@ -668,7 +689,7 @@ double StringToDoubleConverter::StringToIeee( } ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign ? -Double::NaN() : Double::NaN(); } } @@ -677,7 +698,7 @@ double StringToDoubleConverter::StringToIeee( if (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } @@ -700,7 +721,7 @@ double StringToDoubleConverter::StringToIeee( &tail_pointer); if (tail_pointer != NULL) { if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end); - *processed_characters_count = tail_pointer - input; + *processed_characters_count = static_cast(tail_pointer - input); } return result; } @@ -709,7 +730,7 @@ double StringToDoubleConverter::StringToIeee( while (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } } @@ -757,7 +778,7 @@ double StringToDoubleConverter::StringToIeee( while (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } exponent--; // Move this 0 into the exponent. @@ -864,7 +885,7 @@ double StringToDoubleConverter::StringToIeee( read_as_double, &tail_pointer); ASSERT(tail_pointer != NULL); - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return result; } @@ -882,7 +903,7 @@ double StringToDoubleConverter::StringToIeee( } else { converted = Strtof(Vector(buffer, buffer_pos), exponent); } - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign? -converted: converted; } diff --git a/Foundation/src/double-conversion.h b/Foundation/src/double-conversion.h index f98edae75..1c3387d4f 100644 --- a/Foundation/src/double-conversion.h +++ b/Foundation/src/double-conversion.h @@ -502,7 +502,7 @@ class StringToDoubleConverter { // in the 'processed_characters_count'. Trailing junk is never included. double StringToDouble(const char* buffer, int length, - int* processed_characters_count) { + int* processed_characters_count) const { return StringToIeee(buffer, length, processed_characters_count, true); } @@ -511,7 +511,7 @@ class StringToDoubleConverter { // due to potential double-rounding. float StringToFloat(const char* buffer, int length, - int* processed_characters_count) { + int* processed_characters_count) const { return static_cast(StringToIeee(buffer, length, processed_characters_count, false)); } @@ -526,7 +526,7 @@ class StringToDoubleConverter { double StringToIeee(const char* buffer, int length, int* processed_characters_count, - bool read_as_double); + bool read_as_double) const; DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); }; diff --git a/Foundation/src/fast-dtoa.cc b/Foundation/src/fast-dtoa.cc index 1a0f82350..61350383a 100644 --- a/Foundation/src/fast-dtoa.cc +++ b/Foundation/src/fast-dtoa.cc @@ -248,10 +248,7 @@ static void BiggestPowerTen(uint32_t number, // Note: kPowersOf10[i] == 10^(i-1). exponent_plus_one_guess++; // We don't have any guarantees that 2^number_bits <= number. - // TODO(floitsch): can we change the 'while' into an 'if'? We definitely see - // number < (2^number_bits - 1), but I haven't encountered - // number < (2^number_bits - 2) yet. - while (number < kSmallPowersOfTen[exponent_plus_one_guess]) { + if (number < kSmallPowersOfTen[exponent_plus_one_guess]) { exponent_plus_one_guess--; } *power = kSmallPowersOfTen[exponent_plus_one_guess]; @@ -350,7 +347,8 @@ static bool DigitGen(DiyFp low, // that is smaller than integrals. while (*kappa > 0) { int digit = integrals / divisor; - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; integrals %= divisor; (*kappa)--; @@ -379,13 +377,14 @@ static bool DigitGen(DiyFp low, ASSERT(one.e() >= -60); ASSERT(fractionals < one.f()); ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); - while (true) { + for (;;) { fractionals *= 10; unit *= 10; unsafe_interval.set_f(unsafe_interval.f() * 10); // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; fractionals &= one.f() - 1; // Modulo by one. (*kappa)--; @@ -459,7 +458,8 @@ static bool DigitGenCounted(DiyFp w, // that is smaller than 'integrals'. while (*kappa > 0) { int digit = integrals / divisor; - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; integrals %= divisor; @@ -492,7 +492,8 @@ static bool DigitGenCounted(DiyFp w, w_error *= 10; // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; fractionals &= one.f() - 1; // Modulo by one. diff --git a/Foundation/src/fixed-dtoa.cc b/Foundation/src/fixed-dtoa.cc index d56b1449b..aef65fdc2 100644 --- a/Foundation/src/fixed-dtoa.cc +++ b/Foundation/src/fixed-dtoa.cc @@ -133,7 +133,7 @@ static void FillDigits32(uint32_t number, Vector buffer, int* length) { while (number != 0) { int digit = number % 10; number /= 10; - buffer[(*length) + number_length] = '0' + digit; + buffer[(*length) + number_length] = static_cast('0' + digit); number_length++; } // Exchange the digits. @@ -150,7 +150,7 @@ static void FillDigits32(uint32_t number, Vector buffer, int* length) { } -static void FillDigits64FixedLength(uint64_t number, int requested_length, +static void FillDigits64FixedLength(uint64_t number, Vector buffer, int* length) { const uint32_t kTen7 = 10000000; // For efficiency cut the number into 3 uint32_t parts, and print those. @@ -253,7 +253,8 @@ static void FillFractionals(uint64_t fractionals, int exponent, fractionals *= 5; point--; int digit = static_cast(fractionals >> point); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; fractionals -= static_cast(digit) << point; } @@ -274,7 +275,8 @@ static void FillFractionals(uint64_t fractionals, int exponent, fractionals128.Multiply(5); point--; int digit = fractionals128.DivModPowerOf2(point); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; } if (fractionals128.BitAt(point - 1) == 1) { @@ -358,7 +360,7 @@ bool FastFixedDtoa(double v, remainder = (dividend % divisor) << exponent; } FillDigits32(quotient, buffer, length); - FillDigits64FixedLength(remainder, divisor_power, buffer, length); + FillDigits64FixedLength(remainder, buffer, length); *decimal_point = *length; } else if (exponent >= 0) { // 0 <= exponent <= 11 diff --git a/Foundation/src/ieee.h b/Foundation/src/ieee.h index 839dc47d4..661141d1a 100644 --- a/Foundation/src/ieee.h +++ b/Foundation/src/ieee.h @@ -256,6 +256,8 @@ class Double { return (significand & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize); } + + DISALLOW_COPY_AND_ASSIGN(Double); }; class Single { @@ -391,6 +393,8 @@ class Single { static const uint32_t kNaN = 0x7FC00000; const uint32_t d32_; + + DISALLOW_COPY_AND_ASSIGN(Single); }; } // namespace double_conversion diff --git a/Foundation/src/strtod.cc b/Foundation/src/strtod.cc index 9758989f7..68d021719 100644 --- a/Foundation/src/strtod.cc +++ b/Foundation/src/strtod.cc @@ -137,6 +137,7 @@ static void TrimAndCut(Vector buffer, int exponent, Vector right_trimmed = TrimTrailingZeros(left_trimmed); exponent += left_trimmed.length() - right_trimmed.length(); if (right_trimmed.length() > kMaxSignificantDecimalDigits) { + (void) space_size; // Mark variable as used. ASSERT(space_size >= kMaxSignificantDecimalDigits); CutToMaxSignificantDigits(right_trimmed, exponent, buffer_copy_space, updated_exponent); @@ -515,6 +516,7 @@ float Strtof(Vector buffer, int exponent) { double double_next2 = Double(double_next).NextDouble(); f4 = static_cast(double_next2); } + (void) f2; // Mark variable as used. ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); // If the guess doesn't lie near a single-precision boundary we can simply diff --git a/Foundation/src/utils.h b/Foundation/src/utils.h index 62ac2b21a..fd41f5232 100644 --- a/Foundation/src/utils.h +++ b/Foundation/src/utils.h @@ -33,7 +33,8 @@ #include #ifndef ASSERT -#define ASSERT(condition) (assert(condition)) +#define ASSERT(condition) \ + assert(condition); #endif #ifndef UNIMPLEMENTED #define UNIMPLEMENTED() (abort()) @@ -56,7 +57,8 @@ defined(__ARMEL__) || defined(_M_ARM) || defined(__arm__) || defined(__arm64__) || \ defined(__avr32__) || \ defined(__hppa__) || defined(__ia64__) || \ - defined(__mips__) || defined(__powerpc__) || \ + defined(__mips__) || \ + defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ defined(__SH4__) || defined(__alpha__) || \ defined(_MIPS_ARCH_MIPS32R2) || \ @@ -74,6 +76,11 @@ #error Target architecture was not detected as supported by Double-Conversion. #endif +#if defined(__GNUC__) +#define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) +#else +#define DOUBLE_CONVERSION_UNUSED +#endif #if defined(_WIN32) && !defined(__MINGW32__) @@ -299,7 +306,8 @@ template inline Dest BitCast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes. - typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; + DOUBLE_CONVERSION_UNUSED + typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; Dest dest; memmove(&dest, &source, sizeof(dest)); From aa803f36577ca375b0f2b32bf56b8b51433a6224 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sat, 11 Feb 2017 19:01:12 +0100 Subject: [PATCH 130/305] fixed GH #1570: IPv6AddressImpl::toString() returns wrong output for IPv6 address "::" --- Net/src/IPAddressImpl.cpp | 17 ++++++++++------- Net/testsuite/src/IPAddressTest.cpp | 4 ++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Net/src/IPAddressImpl.cpp b/Net/src/IPAddressImpl.cpp index dd20bd052..fcdf0ac1d 100644 --- a/Net/src/IPAddressImpl.cpp +++ b/Net/src/IPAddressImpl.cpp @@ -432,13 +432,16 @@ std::string IPv6AddressImpl::toString() const else result.append("::ffff:"); const UInt8* bytes = reinterpret_cast(&_addr); - NumberFormatter::append(result, bytes[12]); - result.append("."); - NumberFormatter::append(result, bytes[13]); - result.append("."); - NumberFormatter::append(result, bytes[14]); - result.append("."); - NumberFormatter::append(result, bytes[15]); + if (bytes[12] != 0) // only 0.0.0.0 can start with zero + { + NumberFormatter::append(result, bytes[12]); + result.append("."); + NumberFormatter::append(result, bytes[13]); + result.append("."); + NumberFormatter::append(result, bytes[14]); + result.append("."); + NumberFormatter::append(result, bytes[15]); + } return result; } else diff --git a/Net/testsuite/src/IPAddressTest.cpp b/Net/testsuite/src/IPAddressTest.cpp index e80db2dd0..75b2a0cf2 100644 --- a/Net/testsuite/src/IPAddressTest.cpp +++ b/Net/testsuite/src/IPAddressTest.cpp @@ -85,6 +85,10 @@ void IPAddressTest::testStringConv6() IPAddress ia6(32, IPAddress::IPv6); assert (ia6.family() == IPAddress::IPv6); assert (ia6.toString() == "ffff:ffff::"); + + IPAddress ia7("::"); + assert (ia7.family() == IPAddress::IPv6); + assert (ia7.toString() == "::"); #endif } From d1af113f0cae2dd9097c37eb8a46a3004a7f0bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Sat, 11 Feb 2017 19:35:54 +0100 Subject: [PATCH 131/305] fixed a warning --- Foundation/src/double-conversion.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/Foundation/src/double-conversion.cc b/Foundation/src/double-conversion.cc index c7bedeb2f..a92937560 100644 --- a/Foundation/src/double-conversion.cc +++ b/Foundation/src/double-conversion.cc @@ -348,6 +348,7 @@ static BignumDtoaMode DtoaToBignumDtoaMode( case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; default: UNREACHABLE(); + return BIGNUM_DTOA_SHORTEST; } } From 2daefbff3022e2ea2fc57baf05d3d520f7c01817 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 12 Feb 2017 13:01:14 +0100 Subject: [PATCH 132/305] fixes for GH #1566, #1567, #1580 based on 1.7.8 branch fixes --- Zip/include/Poco/Zip/AutoDetectStream.h | 63 ++----- Zip/include/Poco/Zip/ZipLocalFileHeader.h | 1 + Zip/src/AutoDetectStream.cpp | 191 +++++++++++----------- Zip/src/ZipDataInfo.cpp | 1 - Zip/src/ZipLocalFileHeader.cpp | 3 +- Zip/src/ZipStream.cpp | 4 +- 6 files changed, 114 insertions(+), 149 deletions(-) diff --git a/Zip/include/Poco/Zip/AutoDetectStream.h b/Zip/include/Poco/Zip/AutoDetectStream.h index 5341e4002..f2fb91af8 100644 --- a/Zip/include/Poco/Zip/AutoDetectStream.h +++ b/Zip/include/Poco/Zip/AutoDetectStream.h @@ -23,7 +23,6 @@ #include "Poco/Zip/Zip.h" #include "Poco/BufferedStreamBuf.h" #include -#include namespace Poco { @@ -31,24 +30,18 @@ namespace Zip { class Zip_API AutoDetectStreamBuf: public Poco::BufferedStreamBuf - /// A AutoDetectStreamBuf is a class that limits one view on an inputstream to a selected view range + /// AutoDetectStreamBuf automatically detects the end of a stream using the + /// Data Descriptor signature. { public: - AutoDetectStreamBuf(std::istream& in, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start); + AutoDetectStreamBuf(std::istream& in, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start, bool needsZip64); /// Creates the AutoDetectStream. - - - AutoDetectStreamBuf(std::ostream& out); - /// Creates the AutoDetectStream. - /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned - /// to position start ~AutoDetectStreamBuf(); /// Destroys the AutoDetectStream. protected: int readFromDevice(char* buffer, std::streamsize length); - int writeToDevice(const char* buffer, std::streamsize length); private: @@ -57,14 +50,15 @@ private: STREAM_BUFFER_SIZE = 1024 }; - std::istream* _pIstr; - std::ostream* _pOstr; - bool _eofDetected; - int _matchCnt; - std::string _prefix; - std::string _postfix; - bool _reposition; - Poco::UInt32 _start; + std::istream* _pIstr; + bool _eofDetected; + int _matchCnt; + std::string _prefix; + std::string _postfix; + bool _reposition; + Poco::UInt32 _start; + bool _needsZip64; + Poco::UInt64 _length; }; @@ -75,14 +69,10 @@ class Zip_API AutoDetectIOS: public virtual std::ios /// order of the stream buffer and base classes. { public: - AutoDetectIOS(std::istream& istr, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start); + AutoDetectIOS(std::istream& istr, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start, bool needsZip64); /// Creates the basic stream and connects it /// to the given input stream. - AutoDetectIOS(std::ostream& ostr); - /// Creates the basic stream and connects it - /// to the given output stream. - ~AutoDetectIOS(); /// Destroys the stream. @@ -95,37 +85,18 @@ protected: class Zip_API AutoDetectInputStream: public AutoDetectIOS, public std::istream - /// This stream copies all characters read through it - /// to one or multiple output streams. + /// AutoDetectInputStream automatically detects the end of a stream using the + /// Data Descriptor signature. { public: - AutoDetectInputStream(std::istream& istr, const std::string& prefix = std::string(), const std::string& postfix = std::string(), bool reposition = false, Poco::UInt32 start = 0); - /// Creates the AutoDetectInputStream and connects it - /// to the given input stream. Bytes read are guaranteed to be in the range [start, end-1] - /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned - /// to position start + AutoDetectInputStream(std::istream& istr, const std::string& prefix = std::string(), const std::string& postfix = std::string(), bool reposition = false, Poco::UInt32 start = 0, bool needsZip64 = false); + /// Creates the AutoDetectInputStream and connects it to the underlying stream. ~AutoDetectInputStream(); /// Destroys the AutoDetectInputStream. }; -class Zip_API AutoDetectOutputStream: public AutoDetectIOS, public std::ostream - /// This stream copies all characters written to it - /// to one or multiple output streams. -{ -public: - AutoDetectOutputStream(std::ostream& ostr); - /// Creates the AutoDetectOutputStream and connects it - /// to the given input stream. Bytes written are guaranteed to be in the range [start, end-1] - /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned - /// to position start - - ~AutoDetectOutputStream(); - /// Destroys the AutoDetectOutputStream. -}; - - } } // namespace Poco::Zip diff --git a/Zip/include/Poco/Zip/ZipLocalFileHeader.h b/Zip/include/Poco/Zip/ZipLocalFileHeader.h index 05bf00b77..9343cd008 100644 --- a/Zip/include/Poco/Zip/ZipLocalFileHeader.h +++ b/Zip/include/Poco/Zip/ZipLocalFileHeader.h @@ -280,6 +280,7 @@ inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor) _rawHeader[VERSION_POS] = static_cast(static_cast(major)*10+static_cast(minor)); } + inline Poco::UInt16 ZipLocalFileHeader::getFileNameLength() const { return ZipUtil::get16BitValue(_rawHeader, FILE_LENGTH_POS); diff --git a/Zip/src/AutoDetectStream.cpp b/Zip/src/AutoDetectStream.cpp index 3664df9a1..61e3bec63 100644 --- a/Zip/src/AutoDetectStream.cpp +++ b/Zip/src/AutoDetectStream.cpp @@ -27,30 +27,17 @@ namespace Poco { namespace Zip { -AutoDetectStreamBuf::AutoDetectStreamBuf(std::istream& in, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): +AutoDetectStreamBuf::AutoDetectStreamBuf(std::istream& in, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start, bool needsZip64): Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), _pIstr(&in), - _pOstr(0), _eofDetected(false), _matchCnt(0), _prefix(pre), _postfix(post), _reposition(reposition), - _start(start) -{ -} - - -AutoDetectStreamBuf::AutoDetectStreamBuf(std::ostream& out): - Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), - _pIstr(0), - _pOstr(&out), - _eofDetected(false), - _matchCnt(0), - _prefix(), - _postfix(), - _reposition(false), - _start(0u) + _start(start), + _needsZip64(needsZip64), + _length(0) { } @@ -63,7 +50,7 @@ AutoDetectStreamBuf::~AutoDetectStreamBuf() int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) { poco_assert_dbg(length >= 8); - if (_pIstr == 0 ||length == 0) return -1; + if (_pIstr == 0 || length == 0) return -1; if (_reposition) { @@ -74,120 +61,138 @@ int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) if (!_prefix.empty()) { - std::streamsize tmp = (_prefix.size() > length)? length: static_cast(_prefix.size()); - std::memcpy(buffer, _prefix.c_str(), tmp); - _prefix = _prefix.substr(tmp); - return tmp; + std::streamsize n = (_prefix.size() > length) ? length : static_cast(_prefix.size()); + std::memcpy(buffer, _prefix.data(), n); + _prefix.erase(0, n); + return n; } if (_eofDetected) { if (!_postfix.empty()) { - std::streamsize tmp = (_postfix.size() > length)? length: static_cast(_postfix.size()); - std::memcpy(buffer, _postfix.c_str(), tmp); - _postfix = _postfix.substr(tmp); - return tmp; + std::streamsize n = (_postfix.size() > length) ? length : static_cast(_postfix.size()); + std::memcpy(buffer, _postfix.data(), n); + _postfix.erase(0, n); + return n; } - else - return -1; + else return -1; } - if (!_pIstr->good()) - return -1; + if (!_pIstr->good()) return -1; - char byte3('\x00'); - std::streamsize tempPos = 0; + std::streamsize offset = 0; static std::istream::int_type eof = std::istream::traits_type::eof(); - while (_pIstr->good() && !_pIstr->eof() && (tempPos+4) < length) + while (_pIstr->good() && !_pIstr->eof() && (offset + 4) < length) { std::istream::int_type c = _pIstr->get(); if (c != eof) { - // all zip headers start with the same 2byte prefix - if (_matchCnt<2) + if (_matchCnt < 3) { - if (c == ZipLocalFileHeader::HEADER[_matchCnt]) + if (c == ZipDataInfo::HEADER[_matchCnt]) + { ++_matchCnt; + } else { - // matchcnt was either 0 or 1 the headers have all unique chars -> safe to set to 0 - if (_matchCnt == 1) + for (int i = 0; i < _matchCnt; i++) { - buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; + buffer[offset++] = ZipDataInfo::HEADER[i]; } _matchCnt = 0; - - buffer[tempPos++] = static_cast(c); + buffer[offset++] = static_cast(c); } } - else + else if (_matchCnt == 3) { - //the upper 2 bytes differ: the lower one must be in range 1,3,5,7, the upper must be one larger: 2,4,6,8 - if (_matchCnt == 2) + if (ZipDataInfo::HEADER[3] == c) { - if (ZipLocalFileHeader::HEADER[2] == c || - ZipArchiveInfo::HEADER[2] == c || - ZipFileInfo::HEADER[2] == c || - ZipDataInfo::HEADER[2] == c) + std::streamsize dataInfoSize = 0; + if (_needsZip64) { - byte3 = static_cast(c);; - _matchCnt++; + ZipDataInfo64 dataInfo(*_pIstr, true); + if (!_pIstr->good()) throw Poco::IOException("Failed to read data descriptor"); + + dataInfoSize = dataInfo.getFullHeaderSize(); + if (dataInfo.getCompressedSize() == _length + offset) + { + _pIstr->seekg(-static_cast(dataInfoSize), std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); + + _eofDetected = true; + _length += offset; + + if (offset == 0 && !_postfix.empty()) + { + offset = (_postfix.size() > length) ? length : static_cast(_postfix.size()); + std::memcpy(buffer, _postfix.data(), offset); + _postfix.erase(0, offset); + } + + return offset; + } } else { - buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; - buffer[tempPos++] = ZipLocalFileHeader::HEADER[1]; - buffer[tempPos++] = static_cast(c); - _matchCnt = 0; + ZipDataInfo dataInfo(*_pIstr, true); + if (!_pIstr->good()) throw Poco::IOException("Failed to read data descriptor"); + + dataInfoSize = dataInfo.getFullHeaderSize(); + if (dataInfo.getCompressedSize() == _length + offset) + { + _pIstr->seekg(-static_cast(dataInfoSize), std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); + + _eofDetected = true; + _length += offset; + + if (offset == 0 && !_postfix.empty()) + { + offset = (_postfix.size() > length) ? length : static_cast(_postfix.size()); + std::memcpy(buffer, _postfix.data(), offset); + _postfix.erase(0, offset); + } + + return offset; + } } + + _pIstr->seekg(-static_cast(dataInfoSize - 4), std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); + + buffer[offset++] = ZipDataInfo::HEADER[0]; + buffer[offset++] = ZipDataInfo::HEADER[1]; + buffer[offset++] = ZipDataInfo::HEADER[2]; + buffer[offset++] = ZipDataInfo::HEADER[3]; + _matchCnt = 0; } - else if (_matchCnt == 3) + else { - if (c-1 == byte3) - { - // a match, seek back - _pIstr->seekg(-4, std::ios::cur); - if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); - _eofDetected = true; - return tempPos; - } - else - { - buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; - buffer[tempPos++] = ZipLocalFileHeader::HEADER[1]; - buffer[tempPos++] = byte3; - buffer[tempPos++] = c; - _matchCnt = 0; //the headers have all unique chars -> safe to set to 0 - } + buffer[offset++] = ZipDataInfo::HEADER[0]; + buffer[offset++] = ZipDataInfo::HEADER[1]; + buffer[offset++] = ZipDataInfo::HEADER[2]; + buffer[offset++] = c; + _matchCnt = 0; } } } } - return tempPos; + _length += offset; + return offset; } int AutoDetectStreamBuf::writeToDevice(const char* buffer, std::streamsize length) { - if (_pOstr == 0 || length == 0) return -1; - _pOstr->write(buffer, length); - if (_pOstr->good()) - return length; - throw Poco::IOException("Failed to write to output stream"); + return -1; // not supported } -AutoDetectIOS::AutoDetectIOS(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): - _buf(istr, pre, post, reposition, start) -{ - poco_ios_init(&_buf); -} - - -AutoDetectIOS::AutoDetectIOS(std::ostream& ostr): _buf(ostr) +AutoDetectIOS::AutoDetectIOS(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start, bool needsZip64): + _buf(istr, pre, post, reposition, start, needsZip64) { poco_ios_init(&_buf); } @@ -204,8 +209,8 @@ AutoDetectStreamBuf* AutoDetectIOS::rdbuf() } -AutoDetectInputStream::AutoDetectInputStream(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): - AutoDetectIOS(istr, pre, post, reposition, start), +AutoDetectInputStream::AutoDetectInputStream(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start, bool needsZip64): + AutoDetectIOS(istr, pre, post, reposition, start, needsZip64), std::istream(&_buf) { } @@ -216,16 +221,4 @@ AutoDetectInputStream::~AutoDetectInputStream() } -AutoDetectOutputStream::AutoDetectOutputStream(std::ostream& ostr): - AutoDetectIOS(ostr), - std::ostream(&_buf) -{ -} - - -AutoDetectOutputStream::~AutoDetectOutputStream() -{ -} - - } } // namespace Poco::Zip diff --git a/Zip/src/ZipDataInfo.cpp b/Zip/src/ZipDataInfo.cpp index e03b82074..797cad7f6 100644 --- a/Zip/src/ZipDataInfo.cpp +++ b/Zip/src/ZipDataInfo.cpp @@ -64,7 +64,6 @@ ZipDataInfo::~ZipDataInfo() } - const char ZipDataInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x07', '\x08'}; diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp index aab16fdf1..4b7d0d04d 100644 --- a/Zip/src/ZipLocalFileHeader.cpp +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -83,7 +83,7 @@ ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, { char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; inp.read(header, ZipCommon::HEADER_SIZE); - if (std::memcmp(header, ZipDataInfo64::HEADER, sizeof(header)) == 0) + if (_forceZip64) { ZipDataInfo64 nfo(inp, true); setCRC(nfo.getCRC32()); @@ -166,6 +166,7 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) ptr += 2; if (id == ZipCommon::ZIP64_EXTRA_ID) { + _forceZip64 = true; poco_assert(size >= 8); if (getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { diff --git a/Zip/src/ZipStream.cpp b/Zip/src/ZipStream.cpp index 26514feb5..2517454b9 100644 --- a/Zip/src/ZipStream.cpp +++ b/Zip/src/ZipStream.cpp @@ -63,7 +63,7 @@ ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEnt std::string crc(4, ' '); if (fileEntry.searchCRCAndSizesAfterData()) { - _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start); + _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start, fileEntry.needsZip64()); } else { @@ -75,7 +75,7 @@ ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEnt { if (fileEntry.searchCRCAndSizesAfterData()) { - _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start); + _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start, fileEntry.needsZip64()); } else { From dd65c10b53537e48f7890c2b005fe0139c61186e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 12 Feb 2017 14:00:31 +0100 Subject: [PATCH 133/305] pass POCO_BUILD_HOST, POCO_TARGET_OSNAME and POCO_TARGET_OSARCH as strings --- build/rules/global | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/rules/global b/build/rules/global index 4cd27ef3b..c3e17048e 100644 --- a/build/rules/global +++ b/build/rules/global @@ -279,7 +279,7 @@ endif # # Compose compiler flags # -COMMONFLAGS = -DPOCO_BUILD_HOST=$(HOSTNAME) -DPOCO_TARGET_OSNAME=$(OSNAME) -DPOCO_TARGET_OSARCH=$(OSARCH) $(POCO_FLAGS) +COMMONFLAGS = -DPOCO_BUILD_HOST='"'$(HOSTNAME)'"' -DPOCO_TARGET_OSNAME='"'$(OSNAME)'"' -DPOCO_TARGET_OSARCH='"'$(OSARCH)'"' $(POCO_FLAGS) CFLAGS += $(COMMONFLAGS) $(SYSFLAGS) CXXFLAGS += $(COMMONFLAGS) $(SYSFLAGS) LINKFLAGS += $(COMMONFLAGS) $(SYSFLAGS) From fbf7c4dc46247a80bb22f1c0f59ba996ab83111b Mon Sep 17 00:00:00 2001 From: FrancisANDRE Date: Sun, 12 Feb 2017 15:35:50 +0100 Subject: [PATCH 134/305] Add reinterpret_cast for the arguments of the pcre_fullinfo function. Signed-off-by: FrancisANDRE --- Foundation/src/RegularExpression.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Foundation/src/RegularExpression.cpp b/Foundation/src/RegularExpression.cpp index c4be5e621..4f1b960d4 100644 --- a/Foundation/src/RegularExpression.cpp +++ b/Foundation/src/RegularExpression.cpp @@ -49,14 +49,14 @@ RegularExpression::RegularExpression(const std::string& pattern, int options, bo if (study) _extra = pcre_study(reinterpret_cast(_pcre), 0, &error); - pcre_fullinfo(_pcre, _extra, PCRE_INFO_NAMECOUNT, &nmcount); - pcre_fullinfo(_pcre, _extra, PCRE_INFO_NAMEENTRYSIZE, &nmentrysz); - pcre_fullinfo(_pcre, _extra, PCRE_INFO_NAMETABLE, &nmtbl); + pcre_fullinfo(reinterpret_cast(_pcre), reinterpret_cast(_extra), PCRE_INFO_NAMECOUNT, &nmcount); + pcre_fullinfo(reinterpret_cast(_pcre), reinterpret_cast(_extra), PCRE_INFO_NAMEENTRYSIZE, &nmentrysz); + pcre_fullinfo(reinterpret_cast(_pcre), reinterpret_cast(_extra), PCRE_INFO_NAMETABLE, &nmtbl); for (int i = 0; i < nmcount; i++) { unsigned char* group = nmtbl + 2 + (nmentrysz * i); - int n = pcre_get_stringnumber(_pcre, (char*) group); + int n = pcre_get_stringnumber(reinterpret_cast(_pcre), (char*) group); _groups[n] = std::string((char*) group); } } From c1b868d642be7489fc357cfb517035dc254945ec Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 12 Feb 2017 15:44:27 +0100 Subject: [PATCH 135/305] detect malformed MIME messages earlier --- Net/src/MultipartReader.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Net/src/MultipartReader.cpp b/Net/src/MultipartReader.cpp index d167906d3..2bd476c2d 100644 --- a/Net/src/MultipartReader.cpp +++ b/Net/src/MultipartReader.cpp @@ -262,11 +262,13 @@ void MultipartReader::guessBoundary() { _istr.get(); ch = _istr.peek(); - while (ch != eof && ch != '\r' && ch != '\n') + while (ch != eof && ch != '\r' && ch != '\n' && _boundary.size() < 128) // Note: should be no longer than 70 chars acc. to RFC 2046 { _boundary += (char) _istr.get(); ch = _istr.peek(); } + if (ch != '\r' && ch != '\n') + throw MultipartException("Invalid boundary line found"); if (ch == '\r' || ch == '\n') _istr.get(); if (_istr.peek() == '\n') @@ -288,18 +290,21 @@ void MultipartReader::parseHeader(MessageHeader& messageHeader) bool MultipartReader::readLine(std::string& line, std::string::size_type n) { static const int eof = std::char_traits::eof(); + static const int maxLength = 1024; line.clear(); int ch = _istr.peek(); - while (ch != eof && ch != '\r' && ch != '\n') + int length = 0; + while (ch != eof && ch != '\r' && ch != '\n' && length < maxLength) { ch = (char) _istr.get(); if (line.length() < n) line += ch; ch = _istr.peek(); + length++; } if (ch != eof) _istr.get(); if (ch == '\r' && _istr.peek() == '\n') _istr.get(); - return ch != eof; + return ch != eof && length < maxLength; } From 1ffea8eea1ce47f72632503183a7a9633bc1e079 Mon Sep 17 00:00:00 2001 From: zosrothko Date: Sun, 12 Feb 2017 15:50:40 +0100 Subject: [PATCH 136/305] Cygwin: add downloading of libpcre-devel --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1d980ed37..64670b981 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -97,11 +97,11 @@ matrix: install: - if "%builder%"=="cygwin" ( if "%platform%"=="Win32" ( - C:\cygwin\setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup -P openssl-devel -P libiodbc-devel -P libiodbc2 -P odbc-mysql -P odbc-pgsql -P odbc-sqlite3 -P libmysqlclient-devel -P libsqlite3-devel -P libcrypt-devel)) + C:\cygwin\setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup -P libpcre-devel -P openssl-devel -P libiodbc-devel -P libiodbc2 -P odbc-mysql -P odbc-pgsql -P odbc-sqlite3 -P libmysqlclient-devel -P libsqlite3-devel -P libcrypt-devel)) - if "%builder%"=="cygwin" ( if "%platform%"=="x64" ( - C:\cygwin64\setup-x86_64.exe -qnNdO -R C:/cygwin64 -s http://cygwin.mirror.constant.com -l C:/cygwin64/var/cache/setup -P openssl-devel -P libiodbc-devel -P libiodbc2 -P odbc-mysql -P odbc-pgsql -P odbc-sqlite3 -P libmysqlclient-devel -P libsqlite3-devel -P libcrypt-devel)) + C:\cygwin64\setup-x86_64.exe -qnNdO -R C:/cygwin64 -s http://cygwin.mirror.constant.com -l C:/cygwin64/var/cache/setup -P libpcre-devel -P openssl-devel -P libiodbc-devel -P libiodbc2 -P odbc-mysql -P odbc-pgsql -P odbc-sqlite3 -P libmysqlclient-devel -P libsqlite3-devel -P libcrypt-devel)) - set POCO_BASE=%CD% - set PATH=C:\ProgramData\chocolatey\bin;%PATH% From ffbfcf3ee0539a50e965374e72f8a91393c07427 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Sun, 12 Feb 2017 23:23:11 +0100 Subject: [PATCH 137/305] added authentication support --- MongoDB/include/Poco/MongoDB/Binary.h | 15 ++ MongoDB/include/Poco/MongoDB/Database.h | 21 ++ MongoDB/include/Poco/MongoDB/Document.h | 4 +- MongoDB/src/Binary.cpp | 28 ++- MongoDB/src/Database.cpp | 303 +++++++++++++++++++++++- MongoDB/testsuite/src/MongoDBTest.cpp | 4 + 6 files changed, 369 insertions(+), 6 deletions(-) diff --git a/MongoDB/include/Poco/MongoDB/Binary.h b/MongoDB/include/Poco/MongoDB/Binary.h index aa81374b6..ba9f3ed4b 100644 --- a/MongoDB/include/Poco/MongoDB/Binary.h +++ b/MongoDB/include/Poco/MongoDB/Binary.h @@ -49,6 +49,12 @@ public: Binary(const UUID& uuid); /// Constructor for setting a UUID in a binary element + Binary(const std::string& data, unsigned char subtype = 0); + /// Constructor for getting binary data from a string. + + Binary(const void* data, Poco::Int32 size, unsigned char subtype = 0); + /// Constructor for getting binary data from a buffer. + virtual ~Binary(); /// Destructor @@ -64,6 +70,9 @@ public: std::string toString(int indent = 0) const; /// Returns the binary encoded in Base64 + std::string toRawString() const; + /// Returns the raw content as a string. + UUID uuid() const; /// Returns the UUID when the binary subtype is 0x04. /// Otherwise BadCastException will be thrown @@ -92,6 +101,12 @@ inline Buffer& Binary::buffer() } +inline std::string Binary::toRawString() const +{ + return std::string(reinterpret_cast(_buffer.begin()), _buffer.size()); +} + + // BSON Embedded Document // spec: binary template<> diff --git a/MongoDB/include/Poco/MongoDB/Database.h b/MongoDB/include/Poco/MongoDB/Database.h index f58bfea71..174f41b04 100644 --- a/MongoDB/include/Poco/MongoDB/Database.h +++ b/MongoDB/include/Poco/MongoDB/Database.h @@ -45,6 +45,16 @@ public: virtual ~Database(); /// Destructor + bool authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method = AUTH_MONGODB_CR); + /// Authenticates against the database using the given connection, + /// username and password, as well as authentication method. + /// + /// "MONGODB-CR" (default prior to MongoDB 3.0) and + /// "SCRAM-SHA-1" (default starting in 3.0) are the only supported + /// authentication methods. + /// + /// Returns true if authentication was successful, otherwise false. + Int64 count(Connection& connection, const std::string& collectionName) const; /// Sends a count request for the given collection to MongoDB. When /// the command fails, -1 is returned. @@ -88,6 +98,16 @@ public: /// Sends the getLastError command to the database and returns the err element /// from the error document. When err is null, an empty string is returned. + static const std::string AUTH_MONGODB_CR; + /// Default authentication mechanism prior to MongoDB 3.0. + + static const std::string AUTH_SCRAM_SHA1; + /// Default authentication mechanism for MongoDB 3.0. + +protected: + bool authCR(Connection& connection, const std::string& username, const std::string& password); + bool authSCRAM(Connection& connection, const std::string& username, const std::string& password); + private: std::string _dbname; }; @@ -128,6 +148,7 @@ Database::createUpdateRequest(const std::string& collectionName) const return new Poco::MongoDB::UpdateRequest(_dbname + '.' + collectionName); } + } } // namespace Poco::MongoDB diff --git a/MongoDB/include/Poco/MongoDB/Document.h b/MongoDB/include/Poco/MongoDB/Document.h index 056a81975..33d1c1748 100644 --- a/MongoDB/include/Poco/MongoDB/Document.h +++ b/MongoDB/include/Poco/MongoDB/Document.h @@ -68,7 +68,7 @@ public: template Document& add(const std::string& name, T value) /// Creates an element with the given name and value and - // adds it to the document. + /// adds it to the document. /// The active document is returned to allow chaining of the add methods. { return addElement(new ConcreteElement(name, value)); @@ -76,7 +76,7 @@ public: Document& add(const std::string& name, const char* value) /// Creates an element with the given name and value and - // adds it to the document. + /// adds it to the document. /// The active document is returned to allow chaining of the add methods. { return addElement(new ConcreteElement(name, std::string(value))); diff --git a/MongoDB/src/Binary.cpp b/MongoDB/src/Binary.cpp index b0e32f7c8..c70ac507e 100644 --- a/MongoDB/src/Binary.cpp +++ b/MongoDB/src/Binary.cpp @@ -23,23 +23,45 @@ namespace Poco { namespace MongoDB { -Binary::Binary() : _buffer(0) +Binary::Binary(): + _buffer(0), + _subtype(0) { } -Binary::Binary(Poco::Int32 size, unsigned char subtype) : _buffer(size), _subtype(subtype) +Binary::Binary(Poco::Int32 size, unsigned char subtype): + _buffer(size), + _subtype(subtype) { } -Binary::Binary(const UUID& uuid) : _buffer(128 / 8), _subtype(0x04) +Binary::Binary(const UUID& uuid): + _buffer(128 / 8), + _subtype(0x04) { unsigned char szUUID[16]; uuid.copyTo((char*) szUUID); _buffer.assign(szUUID, 16); } + + +Binary::Binary(const std::string& data, unsigned char subtype): + _buffer(reinterpret_cast(data.data()), data.size()), + _subtype(subtype) +{ +} + + +Binary::Binary(const void* data, Poco::Int32 size, unsigned char subtype): + _buffer(reinterpret_cast(data), size), + _subtype(subtype) +{ +} + + Binary::~Binary() { } diff --git a/MongoDB/src/Database.cpp b/MongoDB/src/Database.cpp index 339890319..f9c5c003c 100644 --- a/MongoDB/src/Database.cpp +++ b/MongoDB/src/Database.cpp @@ -17,21 +17,322 @@ #include "Poco/MongoDB/Database.h" +#include "Poco/MongoDB/Binary.h" +#include "Poco/MD5Engine.h" +#include "Poco/SHA1Engine.h" +#include "Poco/PBKDF2Engine.h" +#include "Poco/HMACEngine.h" +#include "Poco/Base64Decoder.h" +#include "Poco/MemoryStream.h" +#include "Poco/StreamCopier.h" +#include "Poco/Exception.h" +#include "Poco/RandomStream.h" +#include "Poco/Random.h" +#include "Poco/Format.h" +#include "Poco/NumberParser.h" +#include +#include namespace Poco { namespace MongoDB { -Database::Database(const std::string& db) : _dbname(db) +const std::string Database::AUTH_MONGODB_CR("MONGODB-CR"); +const std::string Database::AUTH_SCRAM_SHA1("SCRAM-SHA-1"); + + +namespace +{ + std::map parseKeyValueList(const std::string& str) + { + std::map kvm; + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end) + { + std::string k; + std::string v; + while (it != end && *it != '=') k += *it++; + if (it != end) ++it; + while (it != end && *it != ',') v += *it++; + if (it != end) ++it; + kvm[k] = v; + } + return kvm; + } + + std::string hashCredentials(const std::string& username, const std::string& password) + { + Poco::MD5Engine md5; + md5.update(username); + md5.update(std::string(":mongo:")); + md5.update(password); + return Poco::DigestEngine::digestToHex(md5.digest()); + } + + std::string decodeBase64(const std::string& base64) + { + Poco::MemoryInputStream istr(base64.data(), base64.size()); + Poco::Base64Decoder decoder(istr); + std::string result; + Poco::StreamCopier::copyToString(decoder, result); + return result; + } + + std::string encodeBase64(const std::string& data) + { + std::ostringstream ostr; + Poco::Base64Encoder encoder(ostr); + encoder.rdbuf()->setLineLength(0); + encoder << data; + encoder.close(); + return ostr.str(); + } + + std::string digestToBinaryString(Poco::DigestEngine& engine) + { + Poco::DigestEngine::Digest d = engine.digest(); + return std::string(reinterpret_cast(&d[0]), d.size()); + } + + std::string digestToHexString(Poco::DigestEngine& engine) + { + Poco::DigestEngine::Digest d = engine.digest(); + return Poco::DigestEngine::digestToHex(d); + } + + std::string digestToBase64(Poco::DigestEngine& engine) + { + return encodeBase64(digestToBinaryString(engine)); + } + + std::string createNonce() + { + Poco::MD5Engine md5; + Poco::RandomInputStream randomStream; + Poco::Random random; + for (int i = 0; i < 4; i++) + { + md5.update(randomStream.get()); + md5.update(random.nextChar()); + } + return digestToHexString(md5); + } +} + + +Database::Database(const std::string& db): + _dbname(db) { } + Database::~Database() { } +bool Database::authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method) +{ + if (username.empty()) throw Poco::InvalidArgumentException("empty username"); + if (password.empty()) throw Poco::InvalidArgumentException("empty password"); + + if (method == AUTH_MONGODB_CR) + return authCR(connection, username, password); + else if (method == AUTH_SCRAM_SHA1) + return authSCRAM(connection, username, password); + else + throw Poco::InvalidArgumentException("authentication method", method); +} + + +bool Database::authCR(Connection& connection, const std::string& username, const std::string& password) +{ + std::string nonce; + Poco::SharedPtr pCommand = createCommand(); + pCommand->selector().add("getnonce", 1); + + ResponseMessage response; + connection.sendRequest(*pCommand, response); + if (response.documents().size() > 0) + { + Document::Ptr pDoc = response.documents()[0]; + try + { + double ok = pDoc->get("ok"); + if (ok != 1) return false; + nonce = pDoc->get("nonce", ""); + if (nonce.empty()) return false; + } + catch (Poco::NotFoundException&) + { + return false; + } + } + else return false; + + std::string credsDigest = hashCredentials(username, password); + + Poco::MD5Engine md5; + md5.update(nonce); + md5.update(username); + md5.update(credsDigest); + std::string key = digestToHexString(md5); + + pCommand = createCommand(); + pCommand->selector() + .add("authenticate", 1) + .add("user", username) + .add("nonce", nonce) + .add("key", key); + + connection.sendRequest(*pCommand, response); + if (response.documents().size() > 0) + { + Document::Ptr pDoc = response.documents()[0]; + try + { + return pDoc->get("ok") == 1; + } + catch (Poco::NotFoundException&) + { + } + } + return false; +} + + +bool Database::authSCRAM(Connection& connection, const std::string& username, const std::string& password) +{ + std::string clientNonce(createNonce()); + std::string clientFirstMsg = Poco::format("n=%s,r=%s", username, clientNonce); + + Poco::SharedPtr pCommand = createCommand(); + pCommand->selector() + .add("saslStart", 1) + .add("mechanism", AUTH_SCRAM_SHA1) + .add("payload", new Binary(Poco::format("n,,%s", clientFirstMsg))) + .add("authAuthorize", true); + + ResponseMessage response; + connection.sendRequest(*pCommand, response); + + Int32 conversationId = 0; + std::string serverFirstMsg; + + if (response.documents().size() > 0) + { + Document::Ptr pDoc = response.documents()[0]; + try + { + if (pDoc->get("ok") == 1) + { + Binary::Ptr pPayload = pDoc->get("payload"); + serverFirstMsg = pPayload->toRawString(); + conversationId = pDoc->get("conversationId"); + } + else return false; + } + catch (Poco::NotFoundException&) + { + return false; + } + } + else return false; + + std::map kvm = parseKeyValueList(serverFirstMsg); + const std::string serverNonce = kvm["r"]; + const std::string salt = decodeBase64(kvm["s"]); + const unsigned iterations = Poco::NumberParser::parseUnsigned(kvm["i"]); + const Poco::UInt32 dkLen = 20; + + std::string hashedPassword = hashCredentials(username, password); + + Poco::PBKDF2Engine > pbkdf2(salt, iterations, dkLen); + pbkdf2.update(hashedPassword); + std::string saltedPassword = digestToBinaryString(pbkdf2); + + std::string clientFinalNoProof = Poco::format("c=biws,r=%s", serverNonce); + std::string authMessage = Poco::format("%s,%s,%s", clientFirstMsg, serverFirstMsg, clientFinalNoProof); + + Poco::HMACEngine hmacKey(saltedPassword); + hmacKey.update(std::string("Client Key")); + std::string clientKey = digestToBinaryString(hmacKey); + + Poco::SHA1Engine sha1; + sha1.update(clientKey); + std::string storedKey = digestToBinaryString(sha1); + + Poco::HMACEngine hmacSig(storedKey); + hmacSig.update(authMessage); + std::string clientSignature = digestToBinaryString(hmacSig); + + std::string clientProof(clientKey); + for (std::size_t i = 0; i < clientProof.size(); i++) + { + clientProof[i] ^= clientSignature[i]; + } + + std::string clientFinal = Poco::format("%s,p=%s", clientFinalNoProof, encodeBase64(clientProof)); + + pCommand = createCommand(); + pCommand->selector() + .add("saslContinue", 1) + .add("conversationId", conversationId) + .add("payload", new Binary(clientFinal)); + + std::string serverSecondMsg; + connection.sendRequest(*pCommand, response); + if (response.documents().size() > 0) + { + Document::Ptr pDoc = response.documents()[0]; + try + { + if (pDoc->get("ok") == 1) + { + Binary::Ptr pPayload = pDoc->get("payload"); + serverSecondMsg.assign(reinterpret_cast(pPayload->buffer().begin()), pPayload->buffer().size()); + } + else return false; + } + catch (Poco::NotFoundException&) + { + return false; + } + } + else return false; + + Poco::HMACEngine hmacSKey(saltedPassword); + hmacSKey.update(std::string("Server Key")); + std::string serverKey = digestToBinaryString(hmacSKey); + + Poco::HMACEngine hmacSSig(serverKey); + hmacSSig.update(authMessage); + std::string serverSignature = digestToBase64(hmacSSig); + + kvm = parseKeyValueList(serverSecondMsg); + std::string serverSignatureReceived = kvm["v"]; + + if (serverSignature != serverSignatureReceived) return false; + + pCommand = createCommand(); + pCommand->selector() + .add("saslContinue", 1) + .add("conversationId", conversationId) + .add("payload", new Binary); + + connection.sendRequest(*pCommand, response); + if (response.documents().size() > 0) + { + Document::Ptr pDoc = response.documents()[0]; + return pDoc->get("ok") == 1; + } + + return false; +} + + Int64 Database::count(Connection& connection, const std::string& collectionName) const { Poco::SharedPtr countRequest = createCountRequest(collectionName); diff --git a/MongoDB/testsuite/src/MongoDBTest.cpp b/MongoDB/testsuite/src/MongoDBTest.cpp index 7b1ae7d6b..4a90acb86 100644 --- a/MongoDB/testsuite/src/MongoDBTest.cpp +++ b/MongoDB/testsuite/src/MongoDBTest.cpp @@ -221,6 +221,10 @@ void MongoDBTest::testDeleteRequest() void MongoDBTest::testCursorRequest() { Poco::MongoDB::Database db("team"); + + Poco::SharedPtr deleteRequest = db.createDeleteRequest("numbers"); + _mongo->sendRequest(*deleteRequest); + Poco::SharedPtr insertRequest = db.createInsertRequest("numbers"); for(int i = 0; i < 10000; ++i) { From 4e0b11f306eef0f7a67aa83ec85ed54f157bdf1e Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 13 Feb 2017 16:06:20 +0100 Subject: [PATCH 138/305] MongoDB: fixes for consistency and code style --- MongoDB/include/Poco/MongoDB/Array.h | 40 +++++---- MongoDB/include/Poco/MongoDB/BSONReader.h | 15 ++-- MongoDB/include/Poco/MongoDB/BSONWriter.h | 16 ++-- MongoDB/include/Poco/MongoDB/Binary.h | 37 ++++---- MongoDB/include/Poco/MongoDB/Connection.h | 62 +++++++++----- MongoDB/include/Poco/MongoDB/Cursor.h | 28 ++++--- MongoDB/include/Poco/MongoDB/Database.h | 37 ++++---- MongoDB/include/Poco/MongoDB/DeleteRequest.h | 49 ++++++----- MongoDB/include/Poco/MongoDB/Document.h | 49 ++++++----- MongoDB/include/Poco/MongoDB/Element.h | 23 +++-- MongoDB/include/Poco/MongoDB/GetMoreRequest.h | 22 ++--- MongoDB/include/Poco/MongoDB/InsertRequest.h | 35 +++++--- MongoDB/include/Poco/MongoDB/JavaScriptCode.h | 22 +++-- .../include/Poco/MongoDB/KillCursorsRequest.h | 13 +-- MongoDB/include/Poco/MongoDB/Message.h | 11 ++- MongoDB/include/Poco/MongoDB/MessageHeader.h | 51 +++++------ MongoDB/include/Poco/MongoDB/ObjectId.h | 37 ++++---- .../Poco/MongoDB/PoolableConnectionFactory.h | 18 ++-- MongoDB/include/Poco/MongoDB/QueryRequest.h | 81 ++++++++++++------ .../include/Poco/MongoDB/RegularExpression.h | 23 ++--- MongoDB/include/Poco/MongoDB/ReplicaSet.h | 15 ++-- MongoDB/include/Poco/MongoDB/RequestMessage.h | 14 ++-- .../include/Poco/MongoDB/ResponseMessage.h | 32 +++---- MongoDB/include/Poco/MongoDB/UpdateRequest.h | 48 ++++++----- MongoDB/src/Array.cpp | 23 +++-- MongoDB/src/Binary.cpp | 6 +- MongoDB/src/Connection.cpp | 46 +++++++--- MongoDB/src/Cursor.cpp | 15 ++-- MongoDB/src/Database.cpp | 84 ++++++------------- MongoDB/src/DeleteRequest.cpp | 12 ++- MongoDB/src/Document.cpp | 66 +++++++-------- MongoDB/src/Element.cpp | 2 - MongoDB/src/GetMoreRequest.cpp | 6 +- MongoDB/src/InsertRequest.cpp | 10 +-- MongoDB/src/JavaScriptCode.cpp | 2 - MongoDB/src/KillCursorsRequest.cpp | 8 +- MongoDB/src/Message.cpp | 5 +- MongoDB/src/MessageHeader.cpp | 10 +-- MongoDB/src/ObjectId.cpp | 19 +++-- MongoDB/src/QueryRequest.cpp | 8 +- MongoDB/src/RegularExpression.cpp | 10 +-- MongoDB/src/ReplicaSet.cpp | 22 ++--- MongoDB/src/RequestMessage.cpp | 5 +- MongoDB/src/ResponseMessage.cpp | 11 ++- MongoDB/src/UpdateRequest.cpp | 6 +- MongoDB/testsuite/src/MongoDBTest.cpp | 13 +-- MongoDB/testsuite/src/MongoDBTest.h | 4 - 47 files changed, 649 insertions(+), 522 deletions(-) diff --git a/MongoDB/include/Poco/MongoDB/Array.h b/MongoDB/include/Poco/MongoDB/Array.h index 4e139a1f6..bc2b588c6 100644 --- a/MongoDB/include/Poco/MongoDB/Array.h +++ b/MongoDB/include/Poco/MongoDB/Array.h @@ -15,62 +15,68 @@ // SPDX-License-Identifier: BSL-1.0 // + #ifndef MongoDB_Array_INCLUDED #define MongoDB_Array_INCLUDED -#include "Poco/NumberFormatter.h" +#include "Poco/NumberFormatter.h" #include "Poco/MongoDB/MongoDB.h" #include "Poco/MongoDB/Document.h" + namespace Poco { namespace MongoDB { -class MongoDB_API Array : public Document - /// Implements the BSON Array + +class MongoDB_API Array: public Document + /// This class represents a BSON Array. { public: typedef SharedPtr Ptr; Array(); - /// Constructor + /// Creates an empty Array. virtual ~Array(); - /// Destructor + /// Destroys the Array. template T get(int pos) const - /// Returns the element on the given index and tries to convert - /// it to the template type. When the element is not found, a - /// NotFoundException will be thrown. When the element can't be + /// Returns the element at the given index and tries to convert + /// it to the template type. If the element is not found, a + /// Poco::NotFoundException will be thrown. If the element cannot be /// converted a BadCastException will be thrown. { return Document::get(Poco::NumberFormatter::format(pos)); } template - T get(int pos, const T& def) const - /// Returns the element on the given index and tries to convert - /// it to the template type. When the element is not found, or - /// has the wrong type, the def argument will be returned. + T get(int pos, const T& deflt) const + /// Returns the element at the given index and tries to convert + /// it to the template type. If the element is not found, or + /// has the wrong type, the deflt argument will be returned. { - return Document::get(Poco::NumberFormatter::format(pos), def); + return Document::get(Poco::NumberFormatter::format(pos), deflt); } Element::Ptr get(int pos) const; - /// Returns the element on the given index. - /// An empty element will be returned when the element is not found. + /// Returns the element at the given index. + /// An empty element will be returned if the element is not found. template bool isType(int pos) const - /// Returns true when the type of the element equals the TypeId of ElementTrait + /// Returns true if the type of the element equals the TypeId of ElementTrait, + /// otherwise false. { return Document::isType(Poco::NumberFormatter::format(pos)); } std::string toString(int indent = 0) const; + /// Returns a string representation of the Array. }; + // BSON Embedded Array // spec: document template<> @@ -103,4 +109,4 @@ inline void BSONWriter::write(Array::Ptr& from) } } // namespace Poco::MongoDB -#endif //MongoDB_Array_INCLUDED +#endif // MongoDB_Array_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/BSONReader.h b/MongoDB/include/Poco/MongoDB/BSONReader.h index ce915f3a8..e8567cdb6 100644 --- a/MongoDB/include/Poco/MongoDB/BSONReader.h +++ b/MongoDB/include/Poco/MongoDB/BSONReader.h @@ -29,16 +29,17 @@ namespace MongoDB { class MongoDB_API BSONReader - /// Class for reading BSON from a Poco::BinaryReader + /// Class for reading BSON using a Poco::BinaryReader { public: - BSONReader(const Poco::BinaryReader& reader) : _reader(reader) - /// Constructor + BSONReader(const Poco::BinaryReader& reader): + _reader(reader) + /// Creates the BSONReader using the given BinaryWriter. { } virtual ~BSONReader() - /// Destructor + /// Destroys the BSONReader. { } @@ -55,11 +56,13 @@ public: /// A cstring is a string terminated with a 0x00. private: - Poco::BinaryReader _reader; }; +// +// inlines +// inline std::string BSONReader::readCString() { std::string val; @@ -80,4 +83,4 @@ inline std::string BSONReader::readCString() } } // namespace Poco::MongoDB -#endif // MongoDB_BSONReader_INCLUDED +#endif // MongoDB_BSONReader_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/BSONWriter.h b/MongoDB/include/Poco/MongoDB/BSONWriter.h index 80e553d4e..92b6e1db3 100644 --- a/MongoDB/include/Poco/MongoDB/BSONWriter.h +++ b/MongoDB/include/Poco/MongoDB/BSONWriter.h @@ -29,16 +29,17 @@ namespace MongoDB { class MongoDB_API BSONWriter - /// Class for writing BSON to a Poco::BinaryWriter. + /// Class for writing BSON using a Poco::BinaryWriter. { public: - BSONWriter(const Poco::BinaryWriter& writer) : _writer(writer) - /// Constructor + BSONWriter(const Poco::BinaryWriter& writer): + _writer(writer) + /// Creates the BSONWriter. { } virtual ~BSONWriter() - /// Destructor + /// Destroys the BSONWriter. { } @@ -52,13 +53,16 @@ public: void writeCString(const std::string& value); /// Writes a cstring to the writer. A cstring is a string - /// terminated with 0x00 + /// terminated a null character. private: Poco::BinaryWriter _writer; }; +// +// inlines +// inline void BSONWriter::writeCString(const std::string& value) { _writer.writeRaw(value); @@ -69,4 +73,4 @@ inline void BSONWriter::writeCString(const std::string& value) } } // namespace Poco::MongoDB -#endif // MongoDB_BSONWriter_INCLUDED +#endif // MongoDB_BSONWriter_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Binary.h b/MongoDB/include/Poco/MongoDB/Binary.h index ba9f3ed4b..f6fc3bdfc 100644 --- a/MongoDB/include/Poco/MongoDB/Binary.h +++ b/MongoDB/include/Poco/MongoDB/Binary.h @@ -35,47 +35,49 @@ namespace MongoDB { class MongoDB_API Binary - /// Implements BSON Binary. It's a wrapper around a Poco::Buffer. + /// Implements BSON Binary. + /// + /// A Binary stores its data in a Poco::Buffer. { public: typedef SharedPtr Ptr; Binary(); - /// Constructor + /// Creates an empty Binary with subtype 0. Binary(Poco::Int32 size, unsigned char subtype); - /// Constructor + /// Creates a Binary with a buffer of the given size and the given subtype. Binary(const UUID& uuid); - /// Constructor for setting a UUID in a binary element - + /// Creates a Binary containing an UUID. + Binary(const std::string& data, unsigned char subtype = 0); - /// Constructor for getting binary data from a string. + /// Creates a Binary with the contents of the given string and the given subtype. Binary(const void* data, Poco::Int32 size, unsigned char subtype = 0); - /// Constructor for getting binary data from a buffer. + /// Creates a Binary with the contents of the given buffer and the given subtype. virtual ~Binary(); - /// Destructor + /// Destroys the Binary. Buffer& buffer(); - /// Returns a reference to the buffer + /// Returns a reference to the internal buffer unsigned char subtype() const; - /// Returns the subtype + /// Returns the subtype. void subtype(unsigned char type); - /// Sets the subtype + /// Sets the subtype. std::string toString(int indent = 0) const; - /// Returns the binary encoded in Base64 - + /// Returns the contents of the Binary as Base64-encoded string. + std::string toRawString() const; - /// Returns the raw content as a string. + /// Returns the raw content of the Binary as a string. UUID uuid() const; /// Returns the UUID when the binary subtype is 0x04. - /// Otherwise BadCastException will be thrown + /// Otherwise, throws a Poco::BadCastException. private: Buffer _buffer; @@ -83,6 +85,9 @@ private: }; +// +// inlines +// inline unsigned char Binary::subtype() const { return _subtype; @@ -132,7 +137,7 @@ inline void BSONReader::read(Binary::Ptr& to) unsigned char subtype; _reader >> subtype; to->subtype(subtype); - + _reader.readRaw((char*) to->buffer().begin(), size); } diff --git a/MongoDB/include/Poco/MongoDB/Connection.h b/MongoDB/include/Poco/MongoDB/Connection.h index 957235e54..825c6e4a4 100644 --- a/MongoDB/include/Poco/MongoDB/Connection.h +++ b/MongoDB/include/Poco/MongoDB/Connection.h @@ -33,60 +33,80 @@ namespace MongoDB { class MongoDB_API Connection /// Represents a connection to a MongoDB server + /// using the MongoDB wire protocol. + /// + /// See https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/ + /// for more information on the wire protocol. { public: typedef Poco::SharedPtr Ptr; Connection(); - /// Default constructor. Use this when you want to - /// connect later on. + /// Creates an unconnected Connection. + /// + /// Use this when you want to connect later on. Connection(const std::string& hostAndPort); - /// Constructor which connects to the given MongoDB host/port. + /// Creates a Connection connected to the given MongoDB instance at host:port. + /// /// The host and port must be separated with a colon. Connection(const std::string& host, int port); - /// Constructor which connects to the given MongoDB host/port. + /// Creates a Connection connected to the given MongoDB instance at host and port. - Connection(const Net::SocketAddress& addrs); - /// Constructor which connects to the given MongoDB host/port. + Connection(const Poco::Net::SocketAddress& addrs); + /// Creates a Connection connected to the given MongoDB instance at the given address. + + Connection(const Poco::Net::StreamSocket& socket); + /// Creates a Connection connected to the given MongoDB instance using the given socket, + /// which must already be connected. virtual ~Connection(); - /// Destructor + /// Destroys the Connection. - Net::SocketAddress address() const; - /// Returns the address of the MongoDB connection + Poco::Net::SocketAddress address() const; + /// Returns the address of the MongoDB server. void connect(const std::string& hostAndPort); - /// Connects to the given MongoDB server. The host and port must be separated - /// with a colon. + /// Connects to the given MongoDB server. + /// + /// The host and port must be separated with a colon. void connect(const std::string& host, int port); /// Connects to the given MongoDB server. - void connect(const Net::SocketAddress& addrs); + void connect(const Poco::Net::SocketAddress& addrs); /// Connects to the given MongoDB server. + + void connect(const Poco::Net::StreamSocket& socket); + /// Connects using an already connected socket. void disconnect(); - /// Disconnects from the MongoDB server + /// Disconnects from the MongoDB server. void sendRequest(RequestMessage& request); - /// Sends a request to the MongoDB server - /// Only use this when the request hasn't a response. + /// Sends a request to the MongoDB server. + /// + /// Used for one-way requests without a response. void sendRequest(RequestMessage& request, ResponseMessage& response); /// Sends a request to the MongoDB server and receives the response. - /// Use this when a response is expected: only a query or getmore + /// + /// Use this when a response is expected: only a "query" or "getmore" /// request will return a response. -private: - Net::SocketAddress _address; - Net::StreamSocket _socket; +protected: void connect(); - /// Connects to the MongoDB server + +private: + Poco::Net::SocketAddress _address; + Poco::Net::StreamSocket _socket; }; +// +// inlines +// inline Net::SocketAddress Connection::address() const { return _address; @@ -96,4 +116,4 @@ inline Net::SocketAddress Connection::address() const } } // namespace Poco::MongoDB -#endif //MongoDB_Connection_INCLUDED +#endif // MongoDB_Connection_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Cursor.h b/MongoDB/include/Poco/MongoDB/Cursor.h index 9f344f65a..dbf98a5cc 100644 --- a/MongoDB/include/Poco/MongoDB/Cursor.h +++ b/MongoDB/include/Poco/MongoDB/Cursor.h @@ -30,26 +30,27 @@ namespace Poco { namespace MongoDB { -class MongoDB_API Cursor : public Document - /// Cursor is an helper class for querying multiple documents +class MongoDB_API Cursor: public Document + /// Cursor is an helper class for querying multiple documents. { public: - Cursor(const std::string& dbname, const std::string& collectionName, QueryRequest::Flags flags = QueryRequest::QUERY_NONE); - /// Constructor + Cursor(const std::string& dbname, const std::string& collectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT); + /// Creates a Cursor for the given database and collection, using the specified flags. - Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags = QueryRequest::QUERY_NONE); - /// Constructor + Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT); + /// Creates a Cursor for the given database and collection ("database.collection"), using the specified flags. virtual ~Cursor(); - /// Destructor + /// Destroys the Cursor. ResponseMessage& next(Connection& connection); - /// Try to get the next documents. As long as ResponseMessage has a - /// cursor id next can be called to retrieve the next bunch of documents. - /// kill must be called when not all documents are needed. + /// Tries to get the next documents. As long as ResponseMessage has a + /// cursor ID next can be called to retrieve the next bunch of documents. + /// + /// The cursor must be killed (see kill()) when not all documents are needed. QueryRequest& query(); - /// Returns the associated query + /// Returns the associated query. void kill(Connection& connection); /// Kills the cursor and reset it so that it can be reused. @@ -60,6 +61,9 @@ private: }; +// +// inlines +// inline QueryRequest& Cursor::query() { return _query; @@ -69,4 +73,4 @@ inline QueryRequest& Cursor::query() } } // namespace Poco::MongoDB -#endif //MongoDB_Cursor_INCLUDED +#endif // MongoDB_Cursor_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Database.h b/MongoDB/include/Poco/MongoDB/Database.h index 174f41b04..84b81de16 100644 --- a/MongoDB/include/Poco/MongoDB/Database.h +++ b/MongoDB/include/Poco/MongoDB/Database.h @@ -39,13 +39,13 @@ class MongoDB_API Database /// the database. { public: - Database(const std::string& db); - /// Constructor + explicit Database(const std::string& name); + /// Creates a Database for the database with the given name. virtual ~Database(); - /// Destructor - - bool authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method = AUTH_MONGODB_CR); + /// Destroys the Database. + + bool authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method = AUTH_SCRAM_SHA1); /// Authenticates against the database using the given connection, /// username and password, as well as authentication method. /// @@ -54,31 +54,37 @@ public: /// authentication methods. /// /// Returns true if authentication was successful, otherwise false. + /// + /// May throw a Poco::ProtocolException if authentication fails for a reason other than + /// invalid credentials. Int64 count(Connection& connection, const std::string& collectionName) const; - /// Sends a count request for the given collection to MongoDB. When - /// the command fails, -1 is returned. + /// Sends a count request for the given collection to MongoDB. + /// + /// If the command fails, -1 is returned. Poco::SharedPtr createCommand() const; /// Creates a QueryRequest for a command. Poco::SharedPtr createCountRequest(const std::string& collectionName) const; - /// Creates a QueryRequest to count the given collection. The collectionname must not contain - /// the database name! + /// Creates a QueryRequest to count the given collection. + /// The collectionname must not contain the database name. Poco::SharedPtr createDeleteRequest(const std::string& collectionName) const; /// Creates a DeleteRequest to delete documents in the given collection. - /// The collectionname must not contain the database name! + /// The collectionname must not contain the database name. Poco::SharedPtr createInsertRequest(const std::string& collectionName) const; /// Creates an InsertRequest to insert new documents in the given collection. - /// The collectionname must not contain the database name! + /// The collectionname must not contain the database name. Poco::SharedPtr createQueryRequest(const std::string& collectionName) const; - /// Creates a QueryRequest. The collectionname must not contain the database name! + /// Creates a QueryRequest. + /// The collectionname must not contain the database name. Poco::SharedPtr createUpdateRequest(const std::string& collectionName) const; - /// Creates an UpdateRequest. The collectionname must not contain the database name! + /// Creates an UpdateRequest. + /// The collectionname must not contain the database name. Poco::MongoDB::Document::Ptr ensureIndex(Connection& connection, const std::string& collection, @@ -92,7 +98,7 @@ public: /// For more info look at the ensureIndex information on the MongoDB website. Document::Ptr getLastErrorDoc(Connection& connection) const; - /// Sends the getLastError command to the database and returns the document + /// Sends the getLastError command to the database and returns the error document. std::string getLastError(Connection& connection) const; /// Sends the getLastError command to the database and returns the err element @@ -113,6 +119,9 @@ private: }; +// +// inlines +// inline Poco::SharedPtr Database::createCommand() const { Poco::SharedPtr cmd = createQueryRequest("$cmd"); diff --git a/MongoDB/include/Poco/MongoDB/DeleteRequest.h b/MongoDB/include/Poco/MongoDB/DeleteRequest.h index 358b30521..d5cecfa45 100644 --- a/MongoDB/include/Poco/MongoDB/DeleteRequest.h +++ b/MongoDB/include/Poco/MongoDB/DeleteRequest.h @@ -29,51 +29,57 @@ namespace Poco { namespace MongoDB { -class MongoDB_API DeleteRequest : public RequestMessage - /// Class for creating an OP_DELETE client request. This request - /// is used to delete one ore more documents from a database. +class MongoDB_API DeleteRequest: public RequestMessage + /// A DeleteRequest is used to delete one ore more documents from a database. /// /// Specific flags for this request - /// - DELETE_NONE - /// No flags - /// - DELETE_SINGLE_REMOVE - /// Delete only the first document + /// - DELETE_DEFAULT: default delete operation + /// - DELETE_SINGLE_REMOVE: delete only the first document { public: - typedef enum + enum Flags { - DELETE_NONE = 0, - DELETE_SINGLE_REMOVE = 1 - } Flags; + DELETE_DEFAULT = 0, + /// Default - DeleteRequest(const std::string& collectionName, Flags flags = DELETE_NONE); - /// Constructor. The full collection name is the concatenation of the database + DELETE_SINGLE_REMOVE = 1 + /// Delete only the first document. + }; + + DeleteRequest(const std::string& collectionName, Flags flags = DELETE_DEFAULT); + /// Creates a DeleteRequest for the given collection using the given flags. + /// + /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is /// "foo.bar". DeleteRequest(const std::string& collectionName, bool justOne); - /// Constructor. The full collection name is the concatenation of the database + /// Creates a DeleteRequest for the given collection. + /// + /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is - /// "foo.bar". When justOne is true, only the first matching document will + /// "foo.bar". + /// + /// If justOne is true, only the first matching document will /// be removed (the same as using flag DELETE_SINGLE_REMOVE). virtual ~DeleteRequest(); /// Destructor Flags flags() const; - /// Returns flags + /// Returns the flags. void flags(Flags flag); - /// Sets flags + /// Sets the flags. Document& selector(); - /// Returns the selector document + /// Returns the selector document. protected: void buildRequest(BinaryWriter& writer); - /// Writes the OP_DELETE request to the writer + /// Writes the OP_DELETE request to the writer. private: Flags _flags; @@ -82,6 +88,9 @@ private: }; +/// +/// inlines +/// inline DeleteRequest::Flags DeleteRequest::flags() const { return _flags; @@ -103,4 +112,4 @@ inline Document& DeleteRequest::selector() } } // namespace Poco::MongoDB -#endif //MongoDB_DeleteRequest_INCLUDED +#endif // MongoDB_DeleteRequest_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Document.h b/MongoDB/include/Poco/MongoDB/Document.h index 33d1c1748..77cc451bc 100644 --- a/MongoDB/include/Poco/MongoDB/Document.h +++ b/MongoDB/include/Poco/MongoDB/Document.h @@ -25,6 +25,7 @@ #include "Poco/MongoDB/MongoDB.h" #include "Poco/MongoDB/Element.h" #include +#include namespace Poco { @@ -34,7 +35,8 @@ namespace MongoDB { class ElementFindByName { public: - ElementFindByName(const std::string& name) : _name(name) + ElementFindByName(const std::string& name): + _name(name) { } @@ -49,26 +51,28 @@ private: class MongoDB_API Document - /// Represents a BSON document + /// Represents a MongoDB (BSON) document. { public: typedef SharedPtr Ptr; typedef std::vector Vector; Document(); - /// Constructor + /// Creates an empty Document. virtual ~Document(); - /// Destructor + /// Destroys the Document. Document& addElement(Element::Ptr element); /// Add an element to the document. + /// /// The active document is returned to allow chaining of the add methods. template Document& add(const std::string& name, T value) /// Creates an element with the given name and value and /// adds it to the document. + /// /// The active document is returned to allow chaining of the add methods. { return addElement(new ConcreteElement(name, value)); @@ -77,6 +81,7 @@ public: Document& add(const std::string& name, const char* value) /// Creates an element with the given name and value and /// adds it to the document. + /// /// The active document is returned to allow chaining of the add methods. { return addElement(new ConcreteElement(name, std::string(value))); @@ -94,10 +99,10 @@ public: /// Puts all element names into std::vector. bool empty() const; - /// Returns true when the document doesn't contain any documents. + /// Returns true if the document doesn't contain any documents. bool exists(const std::string& name); - /// Returns true when the document has an element with the given name + /// Returns true if the document has an element with the given name. template T get(const std::string& name) const @@ -107,16 +112,16 @@ public: /// converted a BadCastException will be thrown. { Element::Ptr element = get(name); - if ( element.isNull() ) + if (element.isNull()) { throw NotFoundException(name); } else { - if ( ElementTraits::TypeId == element->type() ) + if (ElementTraits::TypeId == element->type()) { ConcreteElement* concrete = dynamic_cast* >(element.get()); - if ( concrete != NULL ) + if (concrete != 0) { return concrete->value(); } @@ -132,15 +137,15 @@ public: /// has the wrong type, the def argument will be returned. { Element::Ptr element = get(name); - if ( element.isNull() ) + if (element.isNull()) { return def; } - if ( ElementTraits::TypeId == element->type() ) + if (ElementTraits::TypeId == element->type()) { ConcreteElement* concrete = dynamic_cast* >(element.get()); - if ( concrete != NULL ) + if (concrete != 0) { return concrete->value(); } @@ -154,17 +159,17 @@ public: /// An empty element will be returned when the element is not found. Int64 getInteger(const std::string& name) const; - /// Returns an integer. Useful when MongoDB returns int32, int64 + /// Returns an integer. Useful when MongoDB returns Int32, Int64 /// or double for a number (count for example). This method will always /// return an Int64. When the element is not found, a - /// NotFoundException will be thrown. + /// Poco::NotFoundException will be thrown. template bool isType(const std::string& name) const - /// Returns true when the type of the element equals the TypeId of ElementTrait + /// Returns true when the type of the element equals the TypeId of ElementTrait. { Element::Ptr element = get(name); - if ( element.isNull() ) + if (element.isNull()) { return false; } @@ -175,7 +180,7 @@ public: void read(BinaryReader& reader); /// Reads a document from the reader - size_t size() const; + std::size_t size() const; /// Returns the number of elements in the document. virtual std::string toString(int indent = 0) const; @@ -189,6 +194,9 @@ protected: }; +// +// inlines +// inline Document& Document::addElement(Element::Ptr element) { _elements.push_back(element); @@ -218,7 +226,7 @@ inline bool Document::empty() const inline void Document::elementNames(std::vector& keys) const { - for(ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) + for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) { keys.push_back((*it)->name()); } @@ -231,7 +239,7 @@ inline bool Document::exists(const std::string& name) } -inline size_t Document::size() const +inline std::size_t Document::size() const { return _elements.size(); } @@ -264,7 +272,8 @@ inline void BSONWriter::write(Document::Ptr& from) from->write(_writer); } + } } // namespace Poco::MongoDB -#endif // MongoDB_Document_INCLUDED +#endif // MongoDB_Document_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Element.h b/MongoDB/include/Poco/MongoDB/Element.h index e383adb7c..ee2b2023f 100644 --- a/MongoDB/include/Poco/MongoDB/Element.h +++ b/MongoDB/include/Poco/MongoDB/Element.h @@ -42,19 +42,19 @@ namespace MongoDB { class MongoDB_API Element - /// Represents an element of a Document or an Array + /// Represents an Element of a Document or an Array. { public: typedef Poco::SharedPtr Ptr; - Element(const std::string& name); - /// Constructor + explicit Element(const std::string& name); + /// Creates the Element with the given name. virtual ~Element(); /// Destructor - std::string name() const; - /// Returns the name of the element + const std::string& name() const; + /// Returns the name of the element. virtual std::string toString(int indent = 0) const = 0; /// Returns a string representation of the element. @@ -71,7 +71,10 @@ private: }; -inline std::string Element::name() const +// +// inlines +// +inline const std::string& Element::name() const { return _name; } @@ -310,10 +313,12 @@ struct ElementTraits template -class ConcreteElement : public Element +class ConcreteElement: public Element { public: - ConcreteElement(const std::string& name, const T& init) : Element(name), _value(init) + ConcreteElement(const std::string& name, const T& init): + Element(name), + _value(init) { } @@ -357,4 +362,4 @@ private: } } // namespace Poco::MongoDB -#endif // MongoDB_Element_INCLUDED +#endif // MongoDB_Element_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/GetMoreRequest.h b/MongoDB/include/Poco/MongoDB/GetMoreRequest.h index e73941e1e..778841ba7 100644 --- a/MongoDB/include/Poco/MongoDB/GetMoreRequest.h +++ b/MongoDB/include/Poco/MongoDB/GetMoreRequest.h @@ -28,31 +28,31 @@ namespace Poco { namespace MongoDB { -class MongoDB_API GetMoreRequest : public RequestMessage - /// Class for creating an OP_GETMORE client request. This request is used - /// to query the database for more documents in a collection after - /// a query request is send. +class MongoDB_API GetMoreRequest: public RequestMessage + /// A GetMoreRequest is used to query the database for more documents in a collection + /// after a query request is send (OP_GETMORE). { public: GetMoreRequest(const std::string& collectionName, Int64 cursorID); - /// Constructor. The full collection name is the concatenation of the database + /// Creates a GetMoreRequest for the give collection and cursor. + /// + /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is /// "foo.bar". The cursorID has been returned by the response on the query request. /// By default the numberToReturn is set to 100. - virtual ~GetMoreRequest(); - /// Destructor + /// Destroys the GetMoreRequest. Int32 getNumberToReturn() const; - /// Returns the limit of returned documents + /// Returns the limit of returned documents. void setNumberToReturn(Int32 n); - /// Sets the limit of returned documents + /// Sets the limit of returned documents. Int64 cursorID() const; - /// Returns the cursor id + /// Returns the cursor ID. protected: void buildRequest(BinaryWriter& writer); @@ -88,4 +88,4 @@ inline Int64 GetMoreRequest::cursorID() const } } // namespace Poco::MongoDB -#endif //MongoDB_GetMoreRequest_INCLUDED +#endif // MongoDB_GetMoreRequest_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/InsertRequest.h b/MongoDB/include/Poco/MongoDB/InsertRequest.h index d273f6492..655d583a2 100644 --- a/MongoDB/include/Poco/MongoDB/InsertRequest.h +++ b/MongoDB/include/Poco/MongoDB/InsertRequest.h @@ -29,26 +29,34 @@ namespace Poco { namespace MongoDB { -class MongoDB_API InsertRequest : public RequestMessage - /// Class for creating an OP_INSERT client request. This request is used - /// to insert one or more documents to the database. +class MongoDB_API InsertRequest: public RequestMessage + /// A request for inserting one or more documents to the database + /// (OP_INSERT). { public: - typedef enum + enum Flags { - INSERT_NONE = 0, + INSERT_DEFAULT = 0, + /// If specified, perform a normal insert operation. + INSERT_CONTINUE_ON_ERROR = 1 - } Flags; + /// If set, the database will not stop processing a bulk insert if one + /// fails (e.g. due to duplicate IDs). This makes bulk insert behave similarly + /// to a series of single inserts, except lastError will be set if any insert + /// fails, not just the last one. If multiple errors occur, only the most + /// recent will be reported. + }; - InsertRequest(const std::string& collectionName, Flags flags = INSERT_NONE ); - /// Constructor. + InsertRequest(const std::string& collectionName, Flags flags = INSERT_DEFAULT); + /// Creates an InsertRequest. + /// /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is /// "foo.bar". virtual ~InsertRequest(); - /// Destructor + /// Destroys the InsertRequest. Document& addNewDocument(); /// Adds a new document for insertion. A reference to the empty document is @@ -56,20 +64,21 @@ public: /// on destruction. Document::Vector& documents(); - /// Returns the documents to insert into the database + /// Returns the documents to insert into the database. protected: - void buildRequest(BinaryWriter& writer); private: - Int32 _flags; std::string _fullCollectionName; Document::Vector _documents; }; +// +// inlines +// inline Document& InsertRequest::addNewDocument() { Document::Ptr doc = new Document(); @@ -87,4 +96,4 @@ inline Document::Vector& InsertRequest::documents() } } // namespace Poco::MongoDB -#endif //MongoDB_InsertRequest_INCLUDED +#endif // MongoDB_InsertRequest_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/JavaScriptCode.h b/MongoDB/include/Poco/MongoDB/JavaScriptCode.h index 49076d29d..693095ac3 100644 --- a/MongoDB/include/Poco/MongoDB/JavaScriptCode.h +++ b/MongoDB/include/Poco/MongoDB/JavaScriptCode.h @@ -32,31 +32,34 @@ namespace MongoDB { class MongoDB_API JavaScriptCode - /// Represents JavaScript type in BSON + /// Represents JavaScript type in BSON. { public: typedef SharedPtr Ptr; JavaScriptCode(); - /// Constructor + /// Creates an empty JavaScriptCode object. virtual ~JavaScriptCode(); - /// Destructor + /// Destroys the JavaScriptCode. - void setCode(const std::string& s); - /// Set the code + void setCode(const std::string& code); + /// Sets the JavaScript code. std::string getCode() const; - /// Get the code + /// Returns the JavaScript code. private: std::string _code; }; -inline void JavaScriptCode::setCode(const std::string& s) +// +// inlines +// +inline void JavaScriptCode::setCode(const std::string& code) { - _code = s; + _code = code; } @@ -65,6 +68,7 @@ inline std::string JavaScriptCode::getCode() const return _code; } + // BSON JavaScript code // spec: string template<> @@ -100,4 +104,4 @@ inline void BSONWriter::write(JavaScriptCode::Ptr& from) } } // namespace Poco::MongoDB -#endif // MongoDB_JavaScriptCode_INCLUDED +#endif // MongoDB_JavaScriptCode_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/KillCursorsRequest.h b/MongoDB/include/Poco/MongoDB/KillCursorsRequest.h index 7e14ccf82..7fd5d593d 100644 --- a/MongoDB/include/Poco/MongoDB/KillCursorsRequest.h +++ b/MongoDB/include/Poco/MongoDB/KillCursorsRequest.h @@ -28,20 +28,20 @@ namespace Poco { namespace MongoDB { -class MongoDB_API KillCursorsRequest : public RequestMessage +class MongoDB_API KillCursorsRequest: public RequestMessage /// Class for creating an OP_KILL_CURSORS client request. This /// request is used to kill cursors, which are still open, /// returned by query requests. { public: KillCursorsRequest(); - /// Constructor + /// Creates a KillCursorsRequest. virtual ~KillCursorsRequest(); - /// Destructor + /// Destroys the KillCursorsRequest. std::vector& cursors(); - /// Return the cursors + /// The internal list of cursors. protected: void buildRequest(BinaryWriter& writer); @@ -49,6 +49,9 @@ protected: }; +// +// inlines +// inline std::vector& KillCursorsRequest::cursors() { return _cursors; @@ -58,4 +61,4 @@ inline std::vector& KillCursorsRequest::cursors() } } // namespace Poco::MongoDB -#endif //MongoDB_KillCursorsRequest_INCLUDED +#endif // MongoDB_KillCursorsRequest_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/Message.h b/MongoDB/include/Poco/MongoDB/Message.h index 122a3353e..d0ddb2991 100644 --- a/MongoDB/include/Poco/MongoDB/Message.h +++ b/MongoDB/include/Poco/MongoDB/Message.h @@ -33,11 +33,11 @@ namespace MongoDB { class MongoDB_API Message - /// Base class for all messages send or retrieved from MongoDB server + /// Base class for all messages send or retrieved from MongoDB server. { public: - Message(MessageHeader::OpCode opcode); - /// Constructor + explicit Message(MessageHeader::OpCode opcode); + /// Creates a Message using the given OpCode. virtual ~Message(); /// Destructor @@ -53,6 +53,9 @@ protected: }; +// +// inlines +// inline MessageHeader& Message::header() { return _header; @@ -69,4 +72,4 @@ inline void Message::messageLength(Poco::Int32 length) } } // namespace Poco::MongoDB -#endif //MongoDB_Message_INCLUDED +#endif // MongoDB_Message_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/MessageHeader.h b/MongoDB/include/Poco/MongoDB/MessageHeader.h index cd9b5fba6..813f7dc5f 100644 --- a/MongoDB/include/Poco/MongoDB/MessageHeader.h +++ b/MongoDB/include/Poco/MongoDB/MessageHeader.h @@ -29,54 +29,54 @@ namespace MongoDB { class MongoDB_API MessageHeader - /// Represents the header which is always prepended to a request - /// or response of MongoDB + /// Represents the message header which is always prepended to a + /// MongoDB request or response message. { public: static const unsigned int MSG_HEADER_SIZE = 16; - typedef enum + enum OpCode { - Reply = 1 - , Msg = 1000 - , Update = 2001 - , Insert = 2002 - , Query = 2004 - , GetMore = 2005 - , Delete = 2006 - , KillCursors = 2007 - } OpCode; + OP_REPLY = 1, + OP_MSG = 1000, + OP_UPDATE = 2001, + OP_INSERT = 2002, + OP_QUERY = 2004, + OP_GET_MORE = 2005, + OP_DELETE = 2006, + OP_KILL_CURSORS = 2007 + }; + + explicit MessageHeader(OpCode); + /// Creates the MessageHeader using the given OpCode. virtual ~MessageHeader(); - /// Destructor + /// Destroys the MessageHeader. void read(BinaryReader& reader); - /// Reads the header + /// Reads the header using the given BinaryReader. void write(BinaryWriter& writer); - /// Writes the header + /// Writes the header using the given BinaryWriter. Int32 getMessageLength() const; - /// Returns the message length + /// Returns the message length. OpCode opCode() const; - /// Returns the OpCode + /// Returns the OpCode. Int32 getRequestID() const; - /// Returns the request id of the current message + /// Returns the request ID of the current message. void setRequestID(Int32 id); - /// Sets the request id of the current message + /// Sets the request ID of the current message. Int32 responseTo() const; /// Returns the request id from the original request. private: - MessageHeader(OpCode opcode); - /// Constructor. - void setMessageLength(Int32 length); - /// Sets the message length + /// Sets the message length. Int32 _messageLength; Int32 _requestID; @@ -87,6 +87,9 @@ private: }; +// +// inlines +// inline MessageHeader::OpCode MessageHeader::opCode() const { return _opCode; @@ -126,4 +129,4 @@ inline Int32 MessageHeader::responseTo() const } } // namespace Poco::MongoDB -#endif //MongoDB_MessageHeader_INCLUDED +#endif // MongoDB_MessageHeader_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/ObjectId.h b/MongoDB/include/Poco/MongoDB/ObjectId.h index aa85a2907..57157d4c2 100644 --- a/MongoDB/include/Poco/MongoDB/ObjectId.h +++ b/MongoDB/include/Poco/MongoDB/ObjectId.h @@ -32,10 +32,10 @@ namespace MongoDB { class MongoDB_API ObjectId /// ObjectId is a 12-byte BSON type, constructed using: /// - /// - a 4-byte timestamp, - /// - a 3-byte machine identifier, - /// - a 2-byte process id, and - /// - a 3-byte counter, starting with a random value. + /// - a 4-byte timestamp, + /// - a 3-byte machine identifier, + /// - a 2-byte process id, and + /// - a 3-byte counter, starting with a random value. /// /// In MongoDB, documents stored in a collection require a unique _id field that acts /// as a primary key. Because ObjectIds are small, most likely unique, and fast to generate, @@ -46,15 +46,17 @@ class MongoDB_API ObjectId public: typedef SharedPtr Ptr; - ObjectId(const std::string& id); - /// Constructor. The string must contain a hexidecimal representation - /// of an object id. This means a string of 24 characters. + explicit ObjectId(const std::string& id); + /// Creates an ObjectId from a string. + /// + /// The string must contain a hexidecimal representation + /// of an object ID. This means a string of 24 characters. ObjectId(const ObjectId& copy); - /// Copy constructor. + /// Creates an ObjectId by copying another one. virtual ~ObjectId(); - /// Destructor + /// Destroys the ObjectId. Timestamp timestamp() const; /// Returns the timestamp which is stored in the first four bytes of the id @@ -65,22 +67,22 @@ public: /// of the ID char array. private: - ObjectId(); - /// Constructor. Creates an empty Id + static int fromHex(char c); + static char fromHex(const char* c); + unsigned char _id[12]; friend class BSONWriter; friend class BSONReader; friend class Document; - - static int fromHex(char c); - - static char fromHex(const char* c); }; +// +// inlines +// inline Timestamp ObjectId::timestamp() const { int time; @@ -92,6 +94,7 @@ inline Timestamp ObjectId::timestamp() const return Timestamp::fromEpochTime((time_t) time); } + inline int ObjectId::fromHex(char c) { if ( '0' <= c && c <= '9' ) @@ -103,11 +106,13 @@ inline int ObjectId::fromHex(char c) return 0xff; } + inline char ObjectId::fromHex(const char* c) { return (char)((fromHex(c[0]) << 4 ) | fromHex(c[1])); } + // BSON Embedded Document // spec: ObjectId template<> @@ -141,4 +146,4 @@ inline void BSONWriter::write(ObjectId::Ptr& from) } } // namespace Poco::MongoDB -#endif //MongoDB_ObjectId_INCLUDED +#endif // MongoDB_ObjectId_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/PoolableConnectionFactory.h b/MongoDB/include/Poco/MongoDB/PoolableConnectionFactory.h index e077f10bf..0f9556b33 100644 --- a/MongoDB/include/Poco/MongoDB/PoolableConnectionFactory.h +++ b/MongoDB/include/Poco/MongoDB/PoolableConnectionFactory.h @@ -33,13 +33,13 @@ class PoolableObjectFactory /// are created with the given address. { public: - PoolableObjectFactory(Net::SocketAddress& address) - : _address(address) + PoolableObjectFactory(Net::SocketAddress& address): + _address(address) { } - PoolableObjectFactory(const std::string& address) - : _address(address) + PoolableObjectFactory(const std::string& address): + _address(address) { } @@ -77,9 +77,9 @@ class PooledConnection /// Helper class for borrowing and returning a connection automatically from a pool. { public: - PooledConnection(Poco::ObjectPool& pool, long timeoutMilliseconds = 0) : _pool(pool) + PooledConnection(Poco::ObjectPool& pool) : _pool(pool) { - _connection = _pool.borrowObject(timeoutMilliseconds); + _connection = _pool.borrowObject(); } virtual ~PooledConnection() @@ -113,7 +113,6 @@ public: #endif private: - #if ! defined(POCO_ENABLE_CPP11) // Disable copy to prevent unwanted release of resources: pre C++11 way PooledConnection(const PooledConnection&); @@ -125,8 +124,7 @@ private: }; -} // namespace MongoDB -} // namespace Poco +} } // namespace Poco::MongoDB -#endif //MongoDB_PoolableConnectionFactory_INCLUDED +#endif // MongoDB_PoolableConnectionFactory_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/QueryRequest.h b/MongoDB/include/Poco/MongoDB/QueryRequest.h index 7e452d7b0..cc4039822 100644 --- a/MongoDB/include/Poco/MongoDB/QueryRequest.h +++ b/MongoDB/include/Poco/MongoDB/QueryRequest.h @@ -29,59 +29,89 @@ namespace Poco { namespace MongoDB { -class MongoDB_API QueryRequest : public RequestMessage - /// Class for creating an OP_QUERY client request. This request - /// is used to query documents from the database. +class MongoDB_API QueryRequest: public RequestMessage + /// A request to query documents in a MongoDB database + /// using an OP_QUERY request. { public: - typedef enum + enum Flags { - QUERY_NONE = 0, - QUERY_TAILABLECURSOR = 2, + QUERY_DEFAULT = 0, + /// Do not set any flags. + + QUERY_TAILABLE_CURSOR = 2, + /// Tailable means cursor is not closed when the last data is retrieved. + /// Rather, the cursor marks the final object’s position. + /// You can resume using the cursor later, from where it was located, + /// if more data were received. Like any "latent cursor", the cursor may + /// become invalid at some point (CursorNotFound) – for example if the final + /// object it references were deleted. + QUERY_SLAVE_OK = 4, - //QUERY_OPLOG_REPLAY = 8 (internal replication use only - drivers should not implement) - QUERY_NOCUROSR_TIMEOUT = 16, + /// Allow query of replica slave. Normally these return an error except + /// for namespace "local". + + // QUERY_OPLOG_REPLAY = 8 (internal replication use only - drivers should not implement) + + QUERY_NO_CURSOR_TIMEOUT = 16, + /// The server normally times out idle cursors after an inactivity period + /// (10 minutes) to prevent excess memory use. Set this option to prevent that. + QUERY_AWAIT_DATA = 32, - QUERY_EXHAUST = 64, - QUERY_PARTIAL = 128 - } Flags; + /// Use with QUERY_TAILABLECURSOR. If we are at the end of the data, block for + /// a while rather than returning no data. After a timeout period, we do + /// return as normal. - QueryRequest(const std::string& collectionName, Flags flags = QUERY_NONE); - /// Constructor. + QUERY_EXHAUST = 64, + /// Stream the data down full blast in multiple "more" packages, on the + /// assumption that the client will fully read all data queried. + /// Faster when you are pulling a lot of data and know you want to pull + /// it all down. + /// Note: the client is not allowed to not read all the data unless it + /// closes the connection. + + QUERY_PARTIAL = 128 + /// Get partial results from a mongos if some shards are down + /// (instead of throwing an error). + }; + + QueryRequest(const std::string& collectionName, Flags flags = QUERY_DEFAULT); + /// Creates a QueryRequest. + /// /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is /// "foo.bar". virtual ~QueryRequest(); - /// Destructor + /// Destroys the QueryRequest. Flags getFlags() const; - /// Returns the flags + /// Returns the flags. void setFlags(Flags flag); - /// Set the flags + /// Set the flags. std::string fullCollectionName() const; - /// Returns the . used for this query + /// Returns the . used for this query. Int32 getNumberToSkip() const; - /// Returns the number of documents to skip + /// Returns the number of documents to skip. void setNumberToSkip(Int32 n); - /// Sets the number of documents to skip + /// Sets the number of documents to skip. Int32 getNumberToReturn() const; - /// Returns the number to return + /// Returns the number of documents to return. void setNumberToReturn(Int32 n); - /// Sets the number to return (limit) + /// Sets the number of documents to return (limit). Document& selector(); - /// Returns the selector document + /// Returns the selector document. Document& returnFieldSelector(); - /// Returns the field selector document + /// Returns the field selector document. protected: void buildRequest(BinaryWriter& writer); @@ -96,6 +126,9 @@ private: }; +// +// inlines +// inline QueryRequest::Flags QueryRequest::getFlags() const { return _flags; @@ -153,4 +186,4 @@ inline void QueryRequest::setNumberToReturn(Int32 n) } } // namespace Poco::MongoDB -#endif //MongoDB_QueryRequest_INCLUDED +#endif // MongoDB_QueryRequest_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/RegularExpression.h b/MongoDB/include/Poco/MongoDB/RegularExpression.h index ee048790e..f962f41aa 100644 --- a/MongoDB/include/Poco/MongoDB/RegularExpression.h +++ b/MongoDB/include/Poco/MongoDB/RegularExpression.h @@ -30,34 +30,34 @@ namespace MongoDB { class MongoDB_API RegularExpression - /// Represents a regular expression in BSON format + /// Represents a regular expression in BSON format. { public: typedef SharedPtr Ptr; RegularExpression(); - /// Constructor + /// Creates an empty RegularExpression. RegularExpression(const std::string& pattern, const std::string& options); - /// Constructor + /// Creates a RegularExpression using the given pattern and options. virtual ~RegularExpression(); - /// Destructor + /// Destroys the RegularExpression. SharedPtr createRE() const; - /// Tries to create a Poco::RegularExpression + /// Tries to create a Poco::RegularExpression from the MongoDB regular expression. std::string getOptions() const; - /// Returns the options + /// Returns the options string. void setOptions(const std::string& options); - /// Sets the options + /// Sets the options string. std::string getPattern() const; - /// Returns the pattern + /// Returns the pattern. void setPattern(const std::string& pattern); - /// Sets the pattern + /// Sets the pattern. private: std::string _pattern; @@ -65,6 +65,9 @@ private: }; +/// +/// inlines +/// inline std::string RegularExpression::getPattern() const { return _pattern; @@ -125,4 +128,4 @@ inline void BSONWriter::write(RegularExpression::Ptr& fr } } // namespace Poco::MongoDB -#endif // MongoDB_RegularExpression_INCLUDED +#endif // MongoDB_RegularExpression_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/ReplicaSet.h b/MongoDB/include/Poco/MongoDB/ReplicaSet.h index 3269f55d8..16cd7add4 100644 --- a/MongoDB/include/Poco/MongoDB/ReplicaSet.h +++ b/MongoDB/include/Poco/MongoDB/ReplicaSet.h @@ -30,21 +30,26 @@ namespace MongoDB { class MongoDB_API ReplicaSet - /// Class for working with a replicaset + /// Class for working with a MongoDB replica set. { public: - ReplicaSet(const std::vector& addresses); - /// Constructor + explicit ReplicaSet(const std::vector& addresses); + /// Creates the ReplicaSet using the given server addresses. virtual ~ReplicaSet(); - /// Destructor + /// Destroys the ReplicaSet. Connection::Ptr findMaster(); /// Tries to find the master MongoDB instance from the addresses + /// passed to the constructor. + /// + /// Returns the Connection to the master, or null if no master + /// instance was found. -private: +protected: Connection::Ptr isMaster(const Net::SocketAddress& host); +private: std::vector _addresses; }; diff --git a/MongoDB/include/Poco/MongoDB/RequestMessage.h b/MongoDB/include/Poco/MongoDB/RequestMessage.h index d418263aa..09470dc44 100644 --- a/MongoDB/include/Poco/MongoDB/RequestMessage.h +++ b/MongoDB/include/Poco/MongoDB/RequestMessage.h @@ -29,18 +29,18 @@ namespace Poco { namespace MongoDB { -class MongoDB_API RequestMessage : public Message - /// Base class for a request +class MongoDB_API RequestMessage: public Message + /// Base class for a request sent to the MongoDB server. { public: - RequestMessage(MessageHeader::OpCode opcode); - /// Constructor + explicit RequestMessage(MessageHeader::OpCode opcode); + /// Creates a RequestMessage using the given opcode. virtual ~RequestMessage(); - /// Destructor + /// Destroys the RequestMessage. void send(std::ostream& ostr); - /// Sends the request to stream + /// Writes the request to stream. protected: virtual void buildRequest(BinaryWriter& ss) = 0; @@ -50,4 +50,4 @@ protected: } } // namespace Poco::MongoDB -#endif //MongoDB_RequestMessage_INCLUDED +#endif // MongoDB_RequestMessage_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/ResponseMessage.h b/MongoDB/include/Poco/MongoDB/ResponseMessage.h index 675b48c46..5450f41ec 100644 --- a/MongoDB/include/Poco/MongoDB/ResponseMessage.h +++ b/MongoDB/include/Poco/MongoDB/ResponseMessage.h @@ -24,42 +24,43 @@ #include "Poco/MongoDB/Message.h" #include "Poco/MongoDB/Document.h" #include +#include namespace Poco { namespace MongoDB { -class MongoDB_API ResponseMessage : public Message - /// Class that represents a response (OP_REPLY) from MongoDB +class MongoDB_API ResponseMessage: public Message + /// This class represents a response (OP_REPLY) from MongoDB. { public: ResponseMessage(); - /// Constructor + /// Creates an empty ResponseMessage. virtual ~ResponseMessage(); - /// Destructor + /// Destroys the ResponseMessage. Int64 cursorID() const; - /// Returns the cursor id + /// Returns the cursor ID. void clear(); - /// Clears the response + /// Clears the response. - size_t count() const; - /// Returns the number of documents in the response + std::size_t count() const; + /// Returns the number of documents in the response. Document::Vector& documents(); - /// Returns the retrieved documents + /// Returns a vector containing the received documents. bool empty() const; - /// Returns true when the response doesn't contain any documents + /// Returns true if the response does not contain any documents. bool hasDocuments() const; - /// Returns true when there is at least one document + /// Returns true if there is at least one document in the response. void read(std::istream& istr); - /// Reads the response from the stream + /// Reads the response from the stream. private: Int32 _responseFlags; @@ -70,7 +71,10 @@ private: }; -inline size_t ResponseMessage::count() const +// +// inlines +// +inline std::size_t ResponseMessage::count() const { return _documents.size(); } @@ -103,4 +107,4 @@ inline bool ResponseMessage::hasDocuments() const } } // namespace Poco::MongoDB -#endif //MongoDB_ResponseMessage_INCLUDED +#endif // MongoDB_ResponseMessage_INCLUDED diff --git a/MongoDB/include/Poco/MongoDB/UpdateRequest.h b/MongoDB/include/Poco/MongoDB/UpdateRequest.h index 2a729ae71..ec08c810d 100644 --- a/MongoDB/include/Poco/MongoDB/UpdateRequest.h +++ b/MongoDB/include/Poco/MongoDB/UpdateRequest.h @@ -29,39 +29,42 @@ namespace Poco { namespace MongoDB { -class UpdateRequest : public RequestMessage - /// Class for creating an OP_UPDATE client request. This request is used - /// to update a document. +class UpdateRequest: public RequestMessage + /// This request is used to update a document in a database + /// using the OP_UPDATE client request. { public: - typedef enum + enum Flags { - UPDATE_NOFLAGS = 0, - // If set, the database will insert the supplied object into the - // collection if no matching document is found. + UPDATE_DEFAULT = 0, + /// If set, the database will insert the supplied object into the + /// collection if no matching document is found. + UPDATE_UPSERT = 1, - // if set, the database will update all matching objects in the collection. - // Otherwise only updates first matching doc. - UPDATE_MULTIUPDATE = 2 - } Flags; + /// If set, the database will update all matching objects in the collection. + /// Otherwise only updates first matching doc. - UpdateRequest(const std::string& collectionName, Flags flags = UPDATE_NOFLAGS); - /// Constructor. + UPDATE_MULTIUPDATE = 2 + /// If set to, updates multiple documents that meet the query criteria. + /// Otherwise only updates one document. + }; + + UpdateRequest(const std::string& collectionName, Flags flags = UPDATE_DEFAULT); + /// Creates the UpdateRequest. + /// /// The full collection name is the concatenation of the database /// name with the collection name, using a "." for the concatenation. For example, /// for the database "foo" and the collection "bar", the full collection name is /// "foo.bar". virtual ~UpdateRequest(); - /// Destructor - + /// Destroys the UpdateRequest. Document& selector(); - /// Returns the selector document - + /// Returns the selector document. Document& update(); - /// The document to update + /// Returns the document to update. Flags flags() const; /// Returns the flags @@ -72,7 +75,6 @@ public: protected: void buildRequest(BinaryWriter& writer); - private: Flags _flags; std::string _fullCollectionName; @@ -81,21 +83,27 @@ private: }; +// +// inlines +// inline UpdateRequest::Flags UpdateRequest::flags() const { return _flags; } + inline void UpdateRequest::flags(UpdateRequest::Flags flags) { _flags = flags; } + inline Document& UpdateRequest::selector() { return _selector; } + inline Document& UpdateRequest::update() { return _update; @@ -105,4 +113,4 @@ inline Document& UpdateRequest::update() } } // namespace Poco::MongoDB -#endif //MongoDB_UpdateRequest_INCLUDED +#endif // MongoDB_UpdateRequest_INCLUDED diff --git a/MongoDB/src/Array.cpp b/MongoDB/src/Array.cpp index dd0e57782..0ed520b2e 100644 --- a/MongoDB/src/Array.cpp +++ b/MongoDB/src/Array.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Array // -// Implementation of the Array class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -24,7 +22,8 @@ namespace Poco { namespace MongoDB { -Array::Array() : Document() +Array::Array(): + Document() { } @@ -47,26 +46,26 @@ std::string Array::toString(int indent) const oss << "["; - if ( indent > 0 ) oss << std::endl; + if (indent > 0) oss << std::endl; - for(ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) + for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) { - if ( it != _elements.begin() ) + if (it != _elements.begin()) { oss << ","; - if ( indent > 0 ) oss << std::endl; + if (indent > 0) oss << std::endl; } - for(int i = 0; i < indent; ++i) oss << ' '; + for (int i = 0; i < indent; ++i) oss << ' '; oss << (*it)->toString(indent > 0 ? indent + 2 : 0); } - if ( indent > 0 ) + if (indent > 0) { oss << std::endl; - if ( indent >= 2 ) indent -= 2; - for(int i = 0; i < indent; ++i) oss << ' '; + if (indent >= 2) indent -= 2; + for (int i = 0; i < indent; ++i) oss << ' '; } oss << "]"; @@ -75,4 +74,4 @@ std::string Array::toString(int indent) const } -}} // Namespace Poco::Mongo +} } // Namespace Poco::Mongo diff --git a/MongoDB/src/Binary.cpp b/MongoDB/src/Binary.cpp index c70ac507e..98e840722 100644 --- a/MongoDB/src/Binary.cpp +++ b/MongoDB/src/Binary.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Binary // -// Implementation of the Binary class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -76,9 +74,10 @@ std::string Binary::toString(int indent) const return oss.str(); } + UUID Binary::uuid() const { - if ( _subtype == 0x04 && _buffer.size() == 16 ) + if (_subtype == 0x04 && _buffer.size() == 16) { UUID uuid; uuid.copyFrom((const char*) _buffer.begin()); @@ -87,4 +86,5 @@ UUID Binary::uuid() const throw BadCastException("Invalid subtype"); } + } } // namespace Poco::MongoDB diff --git a/MongoDB/src/Connection.cpp b/MongoDB/src/Connection.cpp index 93dd27f7e..edca15d1e 100644 --- a/MongoDB/src/Connection.cpp +++ b/MongoDB/src/Connection.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Connection // -// Implementation of the Connection class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -18,41 +16,55 @@ #include "Poco/Net/SocketStream.h" #include "Poco/MongoDB/Connection.h" -#include namespace Poco { namespace MongoDB { -Connection::Connection() : _address(), _socket() +Connection::Connection(): + _address(), + _socket() { } -Connection::Connection(const std::string& hostAndPort) : _address(hostAndPort), _socket() +Connection::Connection(const std::string& hostAndPort): + _address(hostAndPort), + _socket() { connect(); } -Connection::Connection(const std::string& host, int port) : _address(host, port), _socket() +Connection::Connection(const std::string& host, int port): + _address(host, port), + _socket() { connect(); } -Connection::Connection(const Net::SocketAddress& addrs) : _address(addrs), _socket() +Connection::Connection(const Poco::Net::SocketAddress& addrs): + _address(addrs), + _socket() { connect(); } +Connection::Connection(const Poco::Net::StreamSocket& socket): + _address(socket.peerAddress()), + _socket(socket) +{ +} + + Connection::~Connection() { try { - _socket.close(); + disconnect(); } catch (...) { @@ -68,25 +80,32 @@ void Connection::connect() void Connection::connect(const std::string& hostAndPort) { - _address = Net::SocketAddress(hostAndPort); + _address = Poco::Net::SocketAddress(hostAndPort); connect(); } void Connection::connect(const std::string& host, int port) { - _address = Net::SocketAddress(host, port); + _address = Poco::Net::SocketAddress(host, port); connect(); } -void Connection::connect(const Net::SocketAddress& addrs) +void Connection::connect(const Poco::Net::SocketAddress& addrs) { _address = addrs; connect(); } +void Connection::connect(const Poco::Net::StreamSocket& socket) +{ + _address = socket.peerAddress(); + _socket = socket; +} + + void Connection::disconnect() { _socket.close(); @@ -95,7 +114,7 @@ void Connection::disconnect() void Connection::sendRequest(RequestMessage& request) { - Net::SocketOutputStream sos(_socket); + Poco::Net::SocketOutputStream sos(_socket); request.send(sos); } @@ -104,8 +123,9 @@ void Connection::sendRequest(RequestMessage& request, ResponseMessage& response) { sendRequest(request); - Net::SocketInputStream sis(_socket); + Poco::Net::SocketInputStream sis(_socket); response.read(sis); } + } } // Poco::MongoDB diff --git a/MongoDB/src/Cursor.cpp b/MongoDB/src/Cursor.cpp index 8ce5b4882..14f77f0e3 100644 --- a/MongoDB/src/Cursor.cpp +++ b/MongoDB/src/Cursor.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Cursor // -// Implementation of the Cursor class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -25,14 +23,14 @@ namespace Poco { namespace MongoDB { -Cursor::Cursor(const std::string& db, const std::string& collection, QueryRequest::Flags flags) - : _query(db + '.' + collection, flags) +Cursor::Cursor(const std::string& db, const std::string& collection, QueryRequest::Flags flags): + _query(db + '.' + collection, flags) { } -Cursor::Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags) - : _query(fullCollectionName, flags) +Cursor::Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags): + _query(fullCollectionName, flags) { } @@ -42,7 +40,6 @@ Cursor::~Cursor() try { poco_assert_dbg(!_response.cursorID()); - } catch (...) { @@ -52,7 +49,7 @@ Cursor::~Cursor() ResponseMessage& Cursor::next(Connection& connection) { - if ( _response.cursorID() == 0 ) + if (_response.cursorID() == 0) { connection.sendRequest(_query, _response); } @@ -69,7 +66,7 @@ ResponseMessage& Cursor::next(Connection& connection) void Cursor::kill(Connection& connection) { - if ( _response.cursorID() != 0 ) + if (_response.cursorID() != 0) { KillCursorsRequest killRequest; killRequest.cursors().push_back(_response.cursorID()); diff --git a/MongoDB/src/Database.cpp b/MongoDB/src/Database.cpp index f9c5c003c..6300ecae3 100644 --- a/MongoDB/src/Database.cpp +++ b/MongoDB/src/Database.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Database // -// Implementation of the Database class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -158,19 +156,11 @@ bool Database::authCR(Connection& connection, const std::string& username, const if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - try - { - double ok = pDoc->get("ok"); - if (ok != 1) return false; - nonce = pDoc->get("nonce", ""); - if (nonce.empty()) return false; - } - catch (Poco::NotFoundException&) - { - return false; - } + if (pDoc->get("ok") != 1) return false; + nonce = pDoc->get("nonce", ""); + if (nonce.empty()) throw Poco::ProtocolException("no nonce received"); } - else return false; + else throw Poco::ProtocolException("empty response for getnonce"); std::string credsDigest = hashCredentials(username, password); @@ -191,15 +181,9 @@ bool Database::authCR(Connection& connection, const std::string& username, const if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - try - { - return pDoc->get("ok") == 1; - } - catch (Poco::NotFoundException&) - { - } + return pDoc->get("ok") == 1; } - return false; + else throw Poco::ProtocolException("empty response for authenticate"); } @@ -224,22 +208,15 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - try + if (pDoc->get("ok") == 1) { - if (pDoc->get("ok") == 1) - { - Binary::Ptr pPayload = pDoc->get("payload"); - serverFirstMsg = pPayload->toRawString(); - conversationId = pDoc->get("conversationId"); - } - else return false; - } - catch (Poco::NotFoundException&) - { - return false; + Binary::Ptr pPayload = pDoc->get("payload"); + serverFirstMsg = pPayload->toRawString(); + conversationId = pDoc->get("conversationId"); } + else return false; } - else return false; + else throw Poco::ProtocolException("empty response for saslStart"); std::map kvm = parseKeyValueList(serverFirstMsg); const std::string serverNonce = kvm["r"]; @@ -287,21 +264,14 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - try + if (pDoc->get("ok") == 1) { - if (pDoc->get("ok") == 1) - { - Binary::Ptr pPayload = pDoc->get("payload"); - serverSecondMsg.assign(reinterpret_cast(pPayload->buffer().begin()), pPayload->buffer().size()); - } - else return false; - } - catch (Poco::NotFoundException&) - { - return false; + Binary::Ptr pPayload = pDoc->get("payload"); + serverSecondMsg.assign(reinterpret_cast(pPayload->buffer().begin()), pPayload->buffer().size()); } + else return false; } - else return false; + else throw Poco::ProtocolException("empty response for saslContinue"); Poco::HMACEngine hmacSKey(saltedPassword); hmacSKey.update(std::string("Server Key")); @@ -314,7 +284,8 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co kvm = parseKeyValueList(serverSecondMsg); std::string serverSignatureReceived = kvm["v"]; - if (serverSignature != serverSignatureReceived) return false; + if (serverSignature != serverSignatureReceived) + throw Poco::ProtocolException("server signature verification failed"); pCommand = createCommand(); pCommand->selector() @@ -328,8 +299,7 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co Document::Ptr pDoc = response.documents()[0]; return pDoc->get("ok") == 1; } - - return false; + else throw Poco::ProtocolException("empty response for saslContinue"); } @@ -340,7 +310,7 @@ Int64 Database::count(Connection& connection, const std::string& collectionName) Poco::MongoDB::ResponseMessage response; connection.sendRequest(*countRequest, response); - if ( response.documents().size() > 0 ) + if (response.documents().size() > 0) { Poco::MongoDB::Document::Ptr doc = response.documents()[0]; return doc->getInteger("n"); @@ -357,22 +327,22 @@ Poco::MongoDB::Document::Ptr Database::ensureIndex(Connection& connection, const index->add("name", indexName); index->add("key", keys); - if ( version > 0 ) + if (version > 0) { index->add("version", version); } - if ( unique ) + if (unique) { index->add("unique", true); } - if ( background ) + if (background) { index->add("background", true); } - if ( ttl > 0 ) + if (ttl > 0) { index->add("expireAfterSeconds", ttl); } @@ -396,7 +366,7 @@ Document::Ptr Database::getLastErrorDoc(Connection& connection) const Poco::MongoDB::ResponseMessage response; connection.sendRequest(*request, response); - if ( response.documents().size() > 0 ) + if (response.documents().size() > 0) { errorDoc = response.documents()[0]; } @@ -408,7 +378,7 @@ Document::Ptr Database::getLastErrorDoc(Connection& connection) const std::string Database::getLastError(Connection& connection) const { Document::Ptr errorDoc = getLastErrorDoc(connection); - if ( !errorDoc.isNull() && errorDoc->isType("err") ) + if (!errorDoc.isNull() && errorDoc->isType("err")) { return errorDoc->get("err"); } diff --git a/MongoDB/src/DeleteRequest.cpp b/MongoDB/src/DeleteRequest.cpp index 5662ced92..7215f3c2e 100644 --- a/MongoDB/src/DeleteRequest.cpp +++ b/MongoDB/src/DeleteRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: DeleteRequest // -// Implementation of the DeleteRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,8 +21,8 @@ namespace Poco { namespace MongoDB { -DeleteRequest::DeleteRequest(const std::string& collectionName, DeleteRequest::Flags flags) - : RequestMessage(MessageHeader::Delete), +DeleteRequest::DeleteRequest(const std::string& collectionName, DeleteRequest::Flags flags): + RequestMessage(MessageHeader::OP_DELETE), _flags(flags), _fullCollectionName(collectionName), _selector() @@ -32,9 +30,9 @@ DeleteRequest::DeleteRequest(const std::string& collectionName, DeleteRequest::F } -DeleteRequest::DeleteRequest(const std::string& collectionName, bool justOne) - : RequestMessage(MessageHeader::Delete), - _flags(justOne ? DELETE_SINGLE_REMOVE : DELETE_NONE), +DeleteRequest::DeleteRequest(const std::string& collectionName, bool justOne): + RequestMessage(MessageHeader::OP_DELETE), + _flags(justOne ? DELETE_SINGLE_REMOVE : DELETE_DEFAULT), _fullCollectionName(collectionName), _selector() { diff --git a/MongoDB/src/Document.cpp b/MongoDB/src/Document.cpp index a968f1780..1a153589f 100644 --- a/MongoDB/src/Document.cpp +++ b/MongoDB/src/Document.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Document // -// Implementation of the Document class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -44,7 +42,7 @@ Element::Ptr Document::get(const std::string& name) const Element::Ptr element; ElementSet::const_iterator it = std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name)); - if ( it != _elements.end() ) + if (it != _elements.end()) { return *it; } @@ -52,29 +50,31 @@ Element::Ptr Document::get(const std::string& name) const return element; } + Int64 Document::getInteger(const std::string& name) const { Element::Ptr element = get(name); - if ( element.isNull() ) throw NotFoundException(name); + if (element.isNull()) throw Poco::NotFoundException(name); - if ( ElementTraits::TypeId == element->type() ) + if (ElementTraits::TypeId == element->type()) { - ConcreteElement* concrete = dynamic_cast* >(element.get()); - if ( concrete != NULL ) return concrete->value(); + ConcreteElement* concrete = dynamic_cast*>(element.get()); + if (concrete) return concrete->value(); } - else if ( ElementTraits::TypeId == element->type() ) + else if (ElementTraits::TypeId == element->type()) { - ConcreteElement* concrete = dynamic_cast* >(element.get()); - if ( concrete != NULL ) return concrete->value(); + ConcreteElement* concrete = dynamic_cast*>(element.get()); + if (concrete) return concrete->value(); } - else if ( ElementTraits::TypeId == element->type() ) + else if (ElementTraits::TypeId == element->type()) { - ConcreteElement* concrete = dynamic_cast* >(element.get()); - if ( concrete != NULL ) return concrete->value(); + ConcreteElement* concrete = dynamic_cast*>(element.get()); + if (concrete) return concrete->value(); } - throw BadCastException("Invalid type mismatch!"); + throw Poco::BadCastException("Invalid type mismatch!"); } + void Document::read(BinaryReader& reader) { int size; @@ -83,13 +83,13 @@ void Document::read(BinaryReader& reader) unsigned char type; reader >> type; - while( type != '\0' ) + while (type != '\0') { Element::Ptr element; - + std::string name = BSONReader(reader).readCString(); - switch(type) + switch (type) { case ElementTraits::TypeId: element = new ConcreteElement(name, 0); @@ -101,16 +101,16 @@ void Document::read(BinaryReader& reader) element = new ConcreteElement(name, ""); break; case ElementTraits::TypeId: - element = new ConcreteElement(name, new Document()); + element = new ConcreteElement(name, new Document); break; case ElementTraits::TypeId: - element = new ConcreteElement(name, new Array()); + element = new ConcreteElement(name, new Array); break; case ElementTraits::TypeId: - element = new ConcreteElement(name, new Binary()); + element = new ConcreteElement(name, new Binary); break; case ElementTraits::TypeId: - element = new ConcreteElement(name, new ObjectId()); + element = new ConcreteElement(name, new ObjectId); break; case ElementTraits::TypeId: element = new ConcreteElement(name, false); @@ -158,31 +158,31 @@ std::string Document::toString(int indent) const oss << '{'; - if ( indent > 0 ) oss << std::endl; + if (indent > 0) oss << std::endl; - for(ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) + for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it) { - if ( it != _elements.begin() ) + if (it != _elements.begin()) { oss << ','; - if ( indent > 0 ) oss << std::endl; + if (indent > 0) oss << std::endl; } - for(int i = 0; i < indent; ++i) oss << ' '; + for (int i = 0; i < indent; ++i) oss << ' '; oss << '"' << (*it)->name() << '"'; - oss << (( indent > 0 ) ? " : " : ":"); + oss << (indent > 0 ? " : " : ":"); oss << (*it)->toString(indent > 0 ? indent + 2 : 0); } - if ( indent > 0 ) + if (indent > 0) { oss << std::endl; - if ( indent >= 2 ) indent -= 2; + if (indent >= 2) indent -= 2; - for(int i = 0; i < indent; ++i) oss << ' '; + for (int i = 0; i < indent; ++i) oss << ' '; } oss << '}'; @@ -193,7 +193,7 @@ std::string Document::toString(int indent) const void Document::write(BinaryWriter& writer) { - if ( _elements.empty() ) + if (_elements.empty()) { writer << 5; } @@ -201,7 +201,7 @@ void Document::write(BinaryWriter& writer) { std::stringstream sstream; Poco::BinaryWriter tempWriter(sstream); - for(ElementSet::iterator it = _elements.begin(); it != _elements.end(); ++it) + for (ElementSet::iterator it = _elements.begin(); it != _elements.end(); ++it) { tempWriter << static_cast((*it)->type()); BSONWriter(tempWriter).writeCString((*it)->name()); @@ -209,7 +209,7 @@ void Document::write(BinaryWriter& writer) element->write(tempWriter); } tempWriter.flush(); - + Poco::Int32 len = static_cast(5 + sstream.tellp()); /* 5 = sizeof(len) + 0-byte */ writer << len; writer.writeRaw(sstream.str()); diff --git a/MongoDB/src/Element.cpp b/MongoDB/src/Element.cpp index 8b26d8022..a1e3d91e8 100644 --- a/MongoDB/src/Element.cpp +++ b/MongoDB/src/Element.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Element // -// Implementation of the Element class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // diff --git a/MongoDB/src/GetMoreRequest.cpp b/MongoDB/src/GetMoreRequest.cpp index 08ffd6f7d..ae877f5c4 100644 --- a/MongoDB/src/GetMoreRequest.cpp +++ b/MongoDB/src/GetMoreRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: GetMoreRequest // -// Implementation of the GetMoreRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -24,8 +22,8 @@ namespace Poco { namespace MongoDB { -GetMoreRequest::GetMoreRequest(const std::string& collectionName, Int64 cursorID) - : RequestMessage(MessageHeader::GetMore), +GetMoreRequest::GetMoreRequest(const std::string& collectionName, Int64 cursorID): + RequestMessage(MessageHeader::OP_GET_MORE), _fullCollectionName(collectionName), _numberToReturn(100), _cursorID(cursorID) diff --git a/MongoDB/src/InsertRequest.cpp b/MongoDB/src/InsertRequest.cpp index 3ddaa6457..5a940ef9e 100644 --- a/MongoDB/src/InsertRequest.cpp +++ b/MongoDB/src/InsertRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: InsertRequest // -// Implementation of the InsertRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,8 +21,8 @@ namespace Poco { namespace MongoDB { -InsertRequest::InsertRequest(const std::string& collectionName, Flags flags) - : RequestMessage(MessageHeader::Insert), +InsertRequest::InsertRequest(const std::string& collectionName, Flags flags): + RequestMessage(MessageHeader::OP_INSERT), _flags(flags), _fullCollectionName(collectionName) { @@ -38,12 +36,12 @@ InsertRequest::~InsertRequest() void InsertRequest::buildRequest(BinaryWriter& writer) { - //TODO: throw exception when no document is added + poco_assert (!_documents.empty()); writer << _flags; BSONWriter bsonWriter(writer); bsonWriter.writeCString(_fullCollectionName); - for(Document::Vector::iterator it = _documents.begin(); it != _documents.end(); ++it) + for (Document::Vector::iterator it = _documents.begin(); it != _documents.end(); ++it) { bsonWriter.write(*it); } diff --git a/MongoDB/src/JavaScriptCode.cpp b/MongoDB/src/JavaScriptCode.cpp index b2cf9d88a..8ae8ca144 100644 --- a/MongoDB/src/JavaScriptCode.cpp +++ b/MongoDB/src/JavaScriptCode.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: JavaScriptCode // -// Implementation of the JavaScriptCode class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // diff --git a/MongoDB/src/KillCursorsRequest.cpp b/MongoDB/src/KillCursorsRequest.cpp index ffc141973..912d18e98 100644 --- a/MongoDB/src/KillCursorsRequest.cpp +++ b/MongoDB/src/KillCursorsRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: KillCursorsRequest // -// Implementation of the KillCursorsRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,8 +21,8 @@ namespace Poco { namespace MongoDB { -KillCursorsRequest::KillCursorsRequest() - : RequestMessage(MessageHeader::KillCursors) +KillCursorsRequest::KillCursorsRequest(): + RequestMessage(MessageHeader::OP_KILL_CURSORS) { } @@ -38,7 +36,7 @@ void KillCursorsRequest::buildRequest(BinaryWriter& writer) { writer << 0; // 0 - reserved for future use writer << _cursors.size(); - for(std::vector::iterator it = _cursors.begin(); it != _cursors.end(); ++it) + for (std::vector::iterator it = _cursors.begin(); it != _cursors.end(); ++it) { writer << *it; } diff --git a/MongoDB/src/Message.cpp b/MongoDB/src/Message.cpp index efe84929e..fee51e77e 100644 --- a/MongoDB/src/Message.cpp +++ b/MongoDB/src/Message.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: Message // -// Implementation of the Message class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,7 +21,8 @@ namespace Poco { namespace MongoDB { -Message::Message(MessageHeader::OpCode opcode) : _header(opcode) +Message::Message(MessageHeader::OpCode opcode): + _header(opcode) { } diff --git a/MongoDB/src/MessageHeader.cpp b/MongoDB/src/MessageHeader.cpp index 6d12f8ca6..949c6cc4d 100644 --- a/MongoDB/src/MessageHeader.cpp +++ b/MongoDB/src/MessageHeader.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: MessageHeader // -// Implementation of the MessageHeader class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -18,15 +16,17 @@ #include "Poco/MongoDB/Message.h" #include "Poco/Exception.h" -#include "Poco/Net/SocketStream.h" -#include "Poco/StreamCopier.h" namespace Poco { namespace MongoDB { -MessageHeader::MessageHeader(OpCode opCode) : _messageLength(0), _requestID(0), _responseTo(0), _opCode(opCode) +MessageHeader::MessageHeader(OpCode opCode): + _messageLength(0), + _requestID(0), + _responseTo(0), + _opCode(opCode) { } diff --git a/MongoDB/src/ObjectId.cpp b/MongoDB/src/ObjectId.cpp index 0111c7af7..5a79f6989 100644 --- a/MongoDB/src/ObjectId.cpp +++ b/MongoDB/src/ObjectId.cpp @@ -7,42 +7,47 @@ // Package: MongoDB // Module: ObjectId // -// Implementation of the ObjectId class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // + #include "Poco/MongoDB/ObjectId.h" #include "Poco/Format.h" +#include namespace Poco { namespace MongoDB { + ObjectId::ObjectId() { - memset(_id, 0, sizeof(_id)); + std::memset(_id, 0, sizeof(_id)); } + ObjectId::ObjectId(const std::string& id) { poco_assert_dbg(id.size() == 24); - const char *p = id.c_str(); - for (std::size_t i = 0; i < 12; ++i) { + const char* p = id.c_str(); + for (std::size_t i = 0; i < 12; ++i) + { _id[i] = fromHex(p); p += 2; } } + ObjectId::ObjectId(const ObjectId& copy) { - memcpy(_id, copy._id, sizeof(_id)); + std::memcpy(_id, copy._id, sizeof(_id)); } + ObjectId::~ObjectId() { } @@ -52,7 +57,7 @@ std::string ObjectId::toString(const std::string& fmt) const { std::string s; - for(int i = 0; i < 12; ++i) + for (int i = 0; i < 12; ++i) { s += format(fmt, (unsigned int) _id[i]); } diff --git a/MongoDB/src/QueryRequest.cpp b/MongoDB/src/QueryRequest.cpp index 49f3e549b..216dfe7e7 100644 --- a/MongoDB/src/QueryRequest.cpp +++ b/MongoDB/src/QueryRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: QueryRequest // -// Implementation of the QueryRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,8 +21,8 @@ namespace Poco { namespace MongoDB { -QueryRequest::QueryRequest(const std::string& collectionName, QueryRequest::Flags flags) - : RequestMessage(MessageHeader::Query), +QueryRequest::QueryRequest(const std::string& collectionName, QueryRequest::Flags flags): + RequestMessage(MessageHeader::OP_QUERY), _flags(flags), _fullCollectionName(collectionName), _numberToSkip(0), @@ -48,7 +46,7 @@ void QueryRequest::buildRequest(BinaryWriter& writer) writer << _numberToReturn; _selector.write(writer); - if ( ! _returnFieldSelector.empty() ) + if (!_returnFieldSelector.empty()) { _returnFieldSelector.write(writer); } diff --git a/MongoDB/src/RegularExpression.cpp b/MongoDB/src/RegularExpression.cpp index c599c5484..4c6ce193e 100644 --- a/MongoDB/src/RegularExpression.cpp +++ b/MongoDB/src/RegularExpression.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: RegularExpression // -// Implementation of the RegularExpression class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -29,7 +27,9 @@ RegularExpression::RegularExpression() } -RegularExpression::RegularExpression(const std::string& pattern, const std::string& options) : _pattern(pattern), _options(options) +RegularExpression::RegularExpression(const std::string& pattern, const std::string& options): + _pattern(pattern), + _options(options) { } @@ -42,9 +42,9 @@ RegularExpression::~RegularExpression() SharedPtr RegularExpression::createRE() const { int options = 0; - for(std::string::const_iterator optIt = _options.begin(); optIt != _options.end(); ++optIt) + for (std::string::const_iterator optIt = _options.begin(); optIt != _options.end(); ++optIt) { - switch(*optIt) + switch (*optIt) { case 'i': // Case Insensitive options |= Poco::RegularExpression::RE_CASELESS; diff --git a/MongoDB/src/ReplicaSet.cpp b/MongoDB/src/ReplicaSet.cpp index 3f6a0df0f..d00034093 100644 --- a/MongoDB/src/ReplicaSet.cpp +++ b/MongoDB/src/ReplicaSet.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: ReplicaSet // -// Implementation of the ReplicaSet class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -20,11 +18,13 @@ #include "Poco/MongoDB/QueryRequest.h" #include "Poco/MongoDB/ResponseMessage.h" + namespace Poco { namespace MongoDB { -ReplicaSet::ReplicaSet(const std::vector &addresses) : _addresses(addresses) +ReplicaSet::ReplicaSet(const std::vector &addresses): + _addresses(addresses) { } @@ -38,10 +38,10 @@ Connection::Ptr ReplicaSet::findMaster() { Connection::Ptr master; - for(std::vector::iterator it = _addresses.begin(); it != _addresses.end(); ++it) + for (std::vector::iterator it = _addresses.begin(); it != _addresses.end(); ++it) { master = isMaster(*it); - if ( ! master.isNull() ) + if (!master.isNull()) { break; } @@ -66,25 +66,25 @@ Connection::Ptr ReplicaSet::isMaster(const Net::SocketAddress& address) ResponseMessage response; conn->sendRequest(request, response); - if ( response.documents().size() > 0 ) + if (response.documents().size() > 0) { Document::Ptr doc = response.documents()[0]; - if ( doc->get("ismaster") ) + if (doc->get("ismaster")) { return conn; } - else if ( doc->exists("primary") ) + else if (doc->exists("primary")) { return isMaster(Net::SocketAddress(doc->get("primary"))); } } } - catch(...) + catch (...) { - conn = NULL; + conn = 0; } - return NULL; + return 0; } diff --git a/MongoDB/src/RequestMessage.cpp b/MongoDB/src/RequestMessage.cpp index 9af9c4efe..602a2f839 100644 --- a/MongoDB/src/RequestMessage.cpp +++ b/MongoDB/src/RequestMessage.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: RequestMessage // -// Implementation of the RequestMessage class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -25,7 +23,8 @@ namespace Poco { namespace MongoDB { -RequestMessage::RequestMessage(MessageHeader::OpCode opcode) : Message(opcode) +RequestMessage::RequestMessage(MessageHeader::OpCode opcode): + Message(opcode) { } diff --git a/MongoDB/src/ResponseMessage.cpp b/MongoDB/src/ResponseMessage.cpp index a46e27161..56b129554 100644 --- a/MongoDB/src/ResponseMessage.cpp +++ b/MongoDB/src/ResponseMessage.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: ResponseMessage // -// Implementation of the ResponseMessage class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -24,7 +22,12 @@ namespace Poco { namespace MongoDB { -ResponseMessage::ResponseMessage() : Message(MessageHeader::Reply), _responseFlags(0), _cursorID(0), _startingFrom(0), _numberReturned(0) +ResponseMessage::ResponseMessage(): + Message(MessageHeader::OP_REPLY), + _responseFlags(0), + _cursorID(0), + _startingFrom(0), + _numberReturned(0) { } @@ -57,7 +60,7 @@ void ResponseMessage::read(std::istream& istr) reader >> _startingFrom; reader >> _numberReturned; - for(int i = 0; i < _numberReturned; ++i) + for (int i = 0; i < _numberReturned; ++i) { Document::Ptr doc = new Document(); doc->read(reader); diff --git a/MongoDB/src/UpdateRequest.cpp b/MongoDB/src/UpdateRequest.cpp index f8d17fd41..9007ed1d1 100644 --- a/MongoDB/src/UpdateRequest.cpp +++ b/MongoDB/src/UpdateRequest.cpp @@ -7,8 +7,6 @@ // Package: MongoDB // Module: UpdateRequest // -// Implementation of the UpdateRequest class. -// // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // @@ -23,8 +21,8 @@ namespace Poco { namespace MongoDB { -UpdateRequest::UpdateRequest(const std::string& collectionName, UpdateRequest::Flags flags) - : RequestMessage(MessageHeader::Update), +UpdateRequest::UpdateRequest(const std::string& collectionName, UpdateRequest::Flags flags): + RequestMessage(MessageHeader::OP_UPDATE), _flags(flags), _fullCollectionName(collectionName), _selector(), diff --git a/MongoDB/testsuite/src/MongoDBTest.cpp b/MongoDB/testsuite/src/MongoDBTest.cpp index 4a90acb86..d03324799 100644 --- a/MongoDB/testsuite/src/MongoDBTest.cpp +++ b/MongoDB/testsuite/src/MongoDBTest.cpp @@ -8,11 +8,10 @@ // // SPDX-License-Identifier: BSL-1.0 // -#include + #include "Poco/DateTime.h" #include "Poco/ObjectPool.h" - #include "Poco/MongoDB/InsertRequest.h" #include "Poco/MongoDB/QueryRequest.h" #include "Poco/MongoDB/DeleteRequest.h" @@ -22,16 +21,17 @@ #include "Poco/MongoDB/Cursor.h" #include "Poco/MongoDB/ObjectId.h" #include "Poco/MongoDB/Binary.h" - #include "Poco/Net/NetException.h" #include "Poco/UUIDGenerator.h" - -#include "MongoDBTest.h" #include "Poco/CppUnit/TestCaller.h" #include "Poco/CppUnit/TestSuite.h" +#include "MongoDBTest.h" +#include + using namespace Poco::MongoDB; + Poco::MongoDB::Connection::Ptr MongoDBTest::_mongo; @@ -79,6 +79,7 @@ void MongoDBTest::testInsertRequest() _mongo->sendRequest(request); } + void MongoDBTest::testQueryRequest() { Poco::MongoDB::QueryRequest request("team.players"); @@ -120,6 +121,7 @@ void MongoDBTest::testQueryRequest() } } + void MongoDBTest::testDBQueryRequest() { Database db("team"); @@ -345,6 +347,7 @@ void MongoDBTest::testCommand() { } } + void MongoDBTest::testUUID() { Poco::MongoDB::Document::Ptr club = new Poco::MongoDB::Document(); diff --git a/MongoDB/testsuite/src/MongoDBTest.h b/MongoDB/testsuite/src/MongoDBTest.h index 0772cac29..5fab60d61 100644 --- a/MongoDB/testsuite/src/MongoDBTest.h +++ b/MongoDB/testsuite/src/MongoDBTest.h @@ -18,7 +18,6 @@ #include "Poco/MongoDB/MongoDB.h" #include "Poco/MongoDB/Connection.h" - #include "Poco/CppUnit/TestCase.h" @@ -27,7 +26,6 @@ class MongoDBTest: public CppUnit::TestCase public: MongoDBTest(const std::string& name); - virtual ~MongoDBTest(); void testInsertRequest(); @@ -49,9 +47,7 @@ public: static CppUnit::Test* suite(); private: - static Poco::MongoDB::Connection::Ptr _mongo; - }; From 5c0db0bb89e72a23ad8c5efc33a890cd1968baf8 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 13 Feb 2017 16:41:37 +0100 Subject: [PATCH 139/305] fix sample --- MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp | 115 +++++++----------- 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp b/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp index 82c06d800..ecc90a195 100644 --- a/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp +++ b/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp @@ -134,7 +134,7 @@ void sample1(Poco::MongoDB::Connection& connection) connection.sendRequest(*insertPlayerRequest); std::string lastError = db.getLastError(connection); - if ( !lastError.empty() ) + if (!lastError.empty()) { std::cout << "Last Error: " << db.getLastError(connection) << std::endl; } @@ -152,15 +152,15 @@ void sample2(Poco::MongoDB::Connection& connection) cursor.query().returnFieldSelector().add("lastname", 1); cursor.query().returnFieldSelector().add("birthyear", 1); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -178,15 +178,15 @@ void sample3(Poco::MongoDB::Connection& connection) Poco::MongoDB::Cursor cursor("sample", "players"); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -206,15 +206,15 @@ void sample4(Poco::MongoDB::Connection& connection) cursor.query().selector().add("birthyear", 1978); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -234,18 +234,18 @@ void sample5(Poco::MongoDB::Connection& connection) // When orderby is needed, use 2 separate documents in the query selector cursor.query().selector().addNewDocument("$query").add("birthyear", 1987); - cursor.query().selector().addNewDocument("$orderby").add("lastname", -1); + cursor.query().selector().addNewDocument("$orderby").add("lastname", 1); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -268,15 +268,15 @@ void sample6(Poco::MongoDB::Connection& connection) .add("$lte", 1980); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -322,15 +322,15 @@ void sample8(Poco::MongoDB::Connection& connection) cursor.query().setNumberToReturn(10); cursor.query().setNumberToSkip(20); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) + for (;;) { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) + for (Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) { std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; } // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) + if (response.cursorID() == 0) { break; } @@ -350,7 +350,7 @@ void sample9(Poco::MongoDB::Connection& connection) query.setNumberToReturn(1); Poco::MongoDB::ResponseMessage response; connection.sendRequest(query, response); - if ( response.hasDocuments() ) + if (response.hasDocuments()) { std::cout << response.documents()[0]->toString(2) << std::endl; } @@ -360,7 +360,7 @@ void sample9(Poco::MongoDB::Connection& connection) Poco::SharedPtr queryPtr = db.createQueryRequest("players"); queryPtr->setNumberToReturn(1); connection.sendRequest(*queryPtr, response); - if ( response.hasDocuments() ) + if (response.hasDocuments()) { std::cout << response.documents()[0]->toString(2) << std::endl; } @@ -383,10 +383,10 @@ void sample10(Poco::MongoDB::Connection& connection) Poco::MongoDB::ResponseMessage response; connection.sendRequest(*command, response); - if ( response.hasDocuments() ) + if (response.hasDocuments()) { Poco::MongoDB::Array::Ptr values = response.documents()[0]->get("values"); - for(int i = 0; i < values->size(); ++i ) + for (int i = 0; i < values->size(); ++i ) { std::cout << values->get(i) << std::endl; } @@ -408,9 +408,9 @@ void sample11(Poco::MongoDB::Connection& connection) Poco::MongoDB::ResponseMessage response; connection.sendRequest(*count, response); - if ( response.hasDocuments() ) + if (response.hasDocuments()) { - std::cout << "Count: " << response.documents()[0]->get("n") << std::endl; + std::cout << "Count: " << response.documents()[0]->getInteger("n") << std::endl; } } @@ -448,54 +448,31 @@ void sample13(Poco::MongoDB::Connection& connection) std::cout << "LastError: " << lastError->toString(2) << std::endl; } -//SELECT players WHERE birthyear IN (1982, 1983) -void sample14(Poco::MongoDB::Connection& connection) -{ - std::cout << "*** SAMPLE 14 ***" << std::endl; - - Poco::MongoDB::Cursor cursor("sample", "players"); - Poco::MongoDB::Array::Ptr years = new Poco::MongoDB::Array(); - years->add("0", 1982); - years->add("1", 1983); - cursor.query().selector().addNewDocument("birthyear").add("$in", years); - - Poco::MongoDB::ResponseMessage& response = cursor.next(connection); - while(1) - { - for(Poco::MongoDB::Document::Vector::const_iterator it = response.documents().begin(); it != response.documents().end(); ++it) - { - std::cout << (*it)->get("lastname") << ' ' << (*it)->get("firstname") << " (" << (*it)->get("birthyear") << ')' << std::endl; - } - - // When the cursorID is 0, there are no documents left, so break out ... - if ( response.cursorID() == 0 ) - { - break; - } - - // Get the next bunch of documents - response = cursor.next(connection); - }; -} int main(int argc, char** argv) { Poco::MongoDB::Connection connection("localhost", 27017); - sample1(connection); - sample2(connection); - sample3(connection); - sample4(connection); - sample5(connection); - sample6(connection); - sample7(connection); - sample8(connection); - sample9(connection); - sample10(connection); - sample11(connection); - sample12(connection); - sample13(connection); - sample14(connection); + try + { + sample1(connection); + sample2(connection); + sample3(connection); + sample4(connection); + sample5(connection); + sample6(connection); + sample7(connection); + sample8(connection); + sample9(connection); + sample10(connection); + sample11(connection); + sample12(connection); + sample13(connection); + } + catch (Poco::Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + } return 0; } From 83bc36c9230d69a06d0842ef4c5d05747a6ea1e7 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 13 Feb 2017 20:45:53 +0100 Subject: [PATCH 140/305] fix compatibility with DocumentDB --- MongoDB/src/Database.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MongoDB/src/Database.cpp b/MongoDB/src/Database.cpp index 6300ecae3..76b8d31bd 100644 --- a/MongoDB/src/Database.cpp +++ b/MongoDB/src/Database.cpp @@ -156,7 +156,7 @@ bool Database::authCR(Connection& connection, const std::string& username, const if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - if (pDoc->get("ok") != 1) return false; + if (pDoc->getInteger("ok") != 1) return false; nonce = pDoc->get("nonce", ""); if (nonce.empty()) throw Poco::ProtocolException("no nonce received"); } @@ -181,7 +181,7 @@ bool Database::authCR(Connection& connection, const std::string& username, const if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - return pDoc->get("ok") == 1; + return pDoc->getInteger("ok") == 1; } else throw Poco::ProtocolException("empty response for authenticate"); } @@ -208,7 +208,7 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - if (pDoc->get("ok") == 1) + if (pDoc->getInteger("ok") == 1) { Binary::Ptr pPayload = pDoc->get("payload"); serverFirstMsg = pPayload->toRawString(); @@ -264,7 +264,7 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - if (pDoc->get("ok") == 1) + if (pDoc->getInteger("ok") == 1) { Binary::Ptr pPayload = pDoc->get("payload"); serverSecondMsg.assign(reinterpret_cast(pPayload->buffer().begin()), pPayload->buffer().size()); @@ -297,7 +297,7 @@ bool Database::authSCRAM(Connection& connection, const std::string& username, co if (response.documents().size() > 0) { Document::Ptr pDoc = response.documents()[0]; - return pDoc->get("ok") == 1; + return pDoc->getInteger("ok") == 1; } else throw Poco::ProtocolException("empty response for saslContinue"); } From 8392544e83e1ee68e873e7af284b5091ff4bbe3a Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Mon, 13 Feb 2017 22:33:48 +0100 Subject: [PATCH 141/305] minor improvements to documentation and style Conflicts: JSON/include/Poco/JSON/Stringifier.h JSON/src/PrintHandler.cpp JSON/src/Stringifier.cpp --- JSON/include/Poco/JSON/Array.h | 50 ++++---- JSON/include/Poco/JSON/Handler.h | 31 +++-- JSON/include/Poco/JSON/JSONException.h | 4 +- JSON/include/Poco/JSON/Object.h | 72 ++++++----- JSON/include/Poco/JSON/ParseHandler.h | 22 ++-- JSON/include/Poco/JSON/Parser.h | 74 ++++++----- JSON/include/Poco/JSON/PrintHandler.h | 13 +- JSON/include/Poco/JSON/Query.h | 41 ++++-- JSON/include/Poco/JSON/Stringifier.h | 7 +- JSON/include/Poco/JSON/Template.h | 16 ++- JSON/include/Poco/JSON/TemplateCache.h | 30 +++-- JSON/src/Array.cpp | 12 +- JSON/src/JSONException.cpp | 2 +- JSON/src/Object.cpp | 4 +- JSON/src/ParseHandler.cpp | 16 +-- JSON/src/Parser.cpp | 40 +++--- JSON/src/PrintHandler.cpp | 4 +- JSON/src/Query.cpp | 8 +- JSON/src/Stringifier.cpp | 2 +- JSON/src/Template.cpp | 166 ++++++++++++------------- JSON/src/TemplateCache.cpp | 66 +++++----- 21 files changed, 373 insertions(+), 307 deletions(-) diff --git a/JSON/include/Poco/JSON/Array.h b/JSON/include/Poco/JSON/Array.h index 54769460c..821c079ff 100644 --- a/JSON/include/Poco/JSON/Array.h +++ b/JSON/include/Poco/JSON/Array.h @@ -35,9 +35,9 @@ class Object; class JSON_API Array - /// Represents a JSON array. JSON array provides a representation + /// Represents a JSON array. Array provides a representation /// based on shared pointers and optimized for performance. It is possible to - /// convert object to Poco::Dynamic::Array. Conversion requires copying and therefore + /// convert Array to Poco::Dynamic::Array. Conversion requires copying and therefore /// has performance penalty; the benefit is in improved syntax, eg: /// /// // use pointers to avoid copying @@ -57,7 +57,7 @@ class JSON_API Array /// i = da[0]["test"]; // i == 0 /// i = da[1]["test1"][1]; // i == 2 /// i = da[1]["test2"]; // i == 4 - /// + /// ---- { public: typedef std::vector ValueVec; @@ -66,27 +66,27 @@ public: typedef SharedPtr Ptr; Array(); - /// Default constructor + /// Creates an empty Array. Array(const Array& copy); - /// Copy Constructor + /// Creates an Array by copying another one. virtual ~Array(); - /// Destructor + /// Destroys the Array. ValueVec::const_iterator begin() const; - /// Returns iterator + /// Returns the begin iterator for values. ValueVec::const_iterator end() const; - /// Returns iterator + /// Returns the end iterator for values. Dynamic::Var get(unsigned int index) const; - /// Retrieves an element. Will return an empty value - /// when the element doesn't exist. + /// Retrieves the element at the given index. + /// Will return an empty value when the element doesn't exist. Array::Ptr getArray(unsigned int index) const; /// Retrieves an array. When the element is not - /// an array or doesn't exist, an empty SharedPtr is returned. + /// an Array or doesn't exist, an empty SharedPtr is returned. template T getElement(unsigned int index) const @@ -104,30 +104,30 @@ public: /// Retrieves an object. When the element is not /// an object or doesn't exist, an empty SharedPtr is returned. - std::size_t size() const; - /// Returns the size of the array + std::size_t size() const; + /// Returns the size of the array. bool isArray(unsigned int index) const; - /// Returns true when the element is an array + /// Returns true when the element is an array. bool isArray(const Dynamic::Var& value) const; - /// Returns true when the element is an array + /// Returns true when the element is an array. bool isArray(ConstIterator& value) const; - /// Returns true when the element is an array + /// Returns true when the element is an array. bool isNull(unsigned int index) const; /// Returns true when the element is null or /// when the element doesn't exist. bool isObject(unsigned int index) const; - /// Returns true when the element is an object + /// Returns true when the element is an object. bool isObject(const Dynamic::Var& value) const; - /// Returns true when the element is an object + /// Returns true when the element is an object. bool isObject(ConstIterator& value) const; - /// Returns true when the element is an object + /// Returns true when the element is an object. template T optElement(unsigned int index, const T& def) const @@ -137,13 +137,13 @@ public: /// value will be returned { T value = def; - if ( index < _values.size() ) + if (index < _values.size()) { try { value = _values[index].convert(); } - catch(...) + catch (...) { // Default value is returned. } @@ -180,6 +180,9 @@ private: }; +// +// inlines +// inline Array::ValueVec::const_iterator Array::begin() const { return _values.begin(); @@ -236,7 +239,8 @@ inline void Array::remove(unsigned int index) _values.erase(_values.begin() + index); } -}} // Namespace Poco::JSON + +} } // namespace Poco::JSON namespace Poco { @@ -521,7 +525,7 @@ private: }; -}} // namespace Poco::JSON +} } // namespace Poco::Dynamic #endif // JSON_Array_INCLUDED diff --git a/JSON/include/Poco/JSON/Handler.h b/JSON/include/Poco/JSON/Handler.h index 7dd7a7b75..e21e20ff2 100644 --- a/JSON/include/Poco/JSON/Handler.h +++ b/JSON/include/Poco/JSON/Handler.h @@ -31,39 +31,44 @@ namespace JSON { class JSON_API Handler + /// Interface for handling parsing events generated by the JSON Parser. + /// + /// An application can implement a subclass of Handler to implement + /// callback-based parsing of a JSON document, similar to how a SAX + /// parser would handle XML. { public: typedef SharedPtr Ptr; Handler(); - /// Constructor; + /// Creates an empty Handler. virtual ~Handler(); - /// Destructor + /// Destroys the Handler. virtual void reset() = 0; /// Resets the handler state. virtual void startObject() = 0; - /// The parser has read a {, meaning a new object will be read + /// The parser has read a {, meaning a new object will be read. virtual void endObject() = 0; - /// The parser has read a }, meaning the object is read + /// The parser has read a }, meaning the object is read. virtual void startArray() = 0; - /// The parser has read a [, meaning a new array will be read + /// The parser has read a [, meaning a new array will be read. virtual void endArray() = 0; - /// The parser has read a ], meaning the array is read + /// The parser has read a ], meaning the array is read. virtual void key(const std::string& k) = 0; - /// A key of an object is read + /// A key of an object is read. virtual void null() = 0; - /// A null value is read + /// A null value is read. virtual void value(int v) = 0; - /// An integer value is read + /// An integer value is read. virtual void value(unsigned v) = 0; /// An unsigned value is read. This will only be triggered if the @@ -71,7 +76,7 @@ public: #if defined(POCO_HAVE_INT64) virtual void value(Int64 v) = 0; - /// A 64-bit integer value is read + /// A 64-bit integer value is read. virtual void value(UInt64 v) = 0; /// An unsigned 64-bit integer value is read. This will only be @@ -82,10 +87,10 @@ public: /// A string value is read. virtual void value(double d) = 0; - /// A double value is read + /// A double value is read. virtual void value(bool b) = 0; - /// A boolean value is read + /// A boolean value is read. virtual Poco::Dynamic::Var asVar() const; /// Returns the result of the parser (an object, array or string), @@ -97,7 +102,7 @@ public: }; -}} // namespace Poco::JSON +} } // namespace Poco::JSON #endif // JSON_Handler_INCLUDED diff --git a/JSON/include/Poco/JSON/JSONException.h b/JSON/include/Poco/JSON/JSONException.h index 2c0359277..76d166dc8 100644 --- a/JSON/include/Poco/JSON/JSONException.h +++ b/JSON/include/Poco/JSON/JSONException.h @@ -31,7 +31,7 @@ namespace JSON { POCO_DECLARE_EXCEPTION(JSON_API, JSONException, Poco::Exception) -}} // namespace Poco::JSON +} } // namespace Poco::JSON -#endif //JSON_JSONException_INCLUDED +#endif // JSON_JSONException_INCLUDED diff --git a/JSON/include/Poco/JSON/Object.h b/JSON/include/Poco/JSON/Object.h index a14e022d3..cd73f35aa 100644 --- a/JSON/include/Poco/JSON/Object.h +++ b/JSON/include/Poco/JSON/Object.h @@ -39,9 +39,9 @@ namespace JSON { class JSON_API Object - /// Represents a JSON object. JSON object provides a representation + /// Represents a JSON object. Object provides a representation /// based on shared pointers and optimized for performance. It is possible to - /// convert object to DynamicStruct. Conversion requires copying and therefore + /// convert Object to DynamicStruct. Conversion requires copying and therefore /// has performance penalty; the benefit is in improved syntax, eg: /// /// std::string json = "{ \"test\" : { \"property\" : \"value\" } }"; @@ -58,7 +58,7 @@ class JSON_API Object /// // copy/convert to Poco::DynamicStruct /// Poco::DynamicStruct ds = *object; /// val = ds["test"]["property"]; // val holds "value" - /// + /// ---- { public: typedef SharedPtr Ptr; @@ -68,16 +68,19 @@ public: typedef ValueMap::const_iterator ConstIterator; explicit Object(bool preserveInsertionOrder = false); - /// Default constructor. If preserveInsertionOrder, object - /// will preserve the items insertion order. Otherwise, items - /// will be sorted by keys. + /// Creates an empty Object. + /// + /// If preserveInsertionOrder, object will preserve the items insertion + /// order. Otherwise, items will be sorted by keys. Object(const Object& copy); - /// Copy constructor. Struct is not copied to keep the operation as + /// Creates an Object by copying another one. + /// + /// Struct is not copied to keep the operation as /// efficient as possible (when needed, it will be generated upon request). virtual ~Object(); - /// Destroys Object. + /// Destroys the Object. Iterator begin() { @@ -117,7 +120,7 @@ public: T getValue(const std::string& key) const /// Retrieves the property with the given name and will /// try to convert the value to the given template type. - /// The convert method of Dynamic is called + /// The convert() method of Var is called /// which can also throw exceptions for invalid values. /// Note: This will not work for an array or an object. { @@ -129,8 +132,8 @@ public: Poco::Nullable getNullableValue(const std::string& key) const /// Retrieves the property with the given name and will /// try to convert the value to the given template type. - /// Returns null if isNull. - /// The convert method of Dynamic is called + /// + /// The convert method of Var is called /// which can also throw exceptions for invalid values. /// Note: This will not work for an array or an object. { @@ -142,25 +145,25 @@ public: } void getNames(std::vector& names) const; - /// Returns all property names + /// Returns all property names. bool has(const std::string& key) const; - /// Returns true when the given property exists + /// Returns true when the given property exists. bool isArray(const std::string& key) const; - /// Returns true when the given property contains an array + /// Returns true when the given property contains an array. bool isArray(ConstIterator& it) const; - /// Returns true when the given property contains an array + /// Returns true when the given property contains an array. bool isNull(const std::string& key) const; - /// Returns true when the given property contains a null value + /// Returns true when the given property contains a null value. bool isObject(const std::string& key) const; - /// Returns true when the given property contains an object + /// Returns true when the given property contains an object. bool isObject(ConstIterator& it) const; - /// Returns true when the given property contains an object + /// Returns true when the given property contains an object. template T optValue(const std::string& key, const T& def) const @@ -170,13 +173,13 @@ public: { T value = def; ValueMap::const_iterator it = _values.find(key); - if (it != _values.end() && ! it->second.isEmpty() ) + if (it != _values.end() && ! it->second.isEmpty()) { try { value = it->second.convert(); } - catch(...) + catch (...) { // The default value will be returned } @@ -185,17 +188,19 @@ public: } std::size_t size() const; - /// Returns the number of properties + /// Returns the number of properties. void set(const std::string& key, const Dynamic::Var& value); - /// Sets a new value + /// Sets a new value. void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const; - /// Prints the object to out stream. When indent is 0, the object - /// will be printed on a single line without indentation. + /// Prints the object to out stream. + /// + /// When indent is 0, the object will be printed on a single + /// line without indentation. void remove(const std::string& key); - /// Removes the property with the given key + /// Removes the property with the given key. static Poco::DynamicStruct makeStruct(const Object::Ptr& obj); /// Utility function for creation of struct. @@ -204,8 +209,9 @@ public: /// Cast operator to Poco::DynamiStruct. void clear(); - /// Clears the contents of the object. Insertion order - /// preservation property is left intact. + /// Clears the contents of the object. + /// + /// Insertion order preservation property is left intact. private: template @@ -219,7 +225,7 @@ private: typename C::const_iterator end = container.end(); for (; it != end;) { - for(unsigned int i = 0; i < indent; i++) out << ' '; + for (unsigned int i = 0; i < indent; i++) out << ' '; Stringifier::stringify(getKey(it), out); out << ((indent > 0) ? " : " : ":"); @@ -233,8 +239,7 @@ private: if (indent >= step) indent -= step; - for (unsigned int i = 0; i < indent; i++) - out << ' '; + for (unsigned int i = 0; i < indent; i++) out << ' '; out << '}'; } @@ -254,6 +259,9 @@ private: }; +// +// inlines +// inline bool Object::has(const std::string& key) const { ValueMap::const_iterator it = _values.find(key); @@ -341,7 +349,7 @@ inline const Dynamic::Var& Object::getValue(KeyPtrList::const_iterator& it) cons } -}} // Namespace Poco::JSON +} } // namespace Poco::JSON namespace Poco { @@ -632,7 +640,7 @@ private: }; -}} // namespace Poco::JSON +} } // namespace Poco::Dynamic #endif // JSON_Object_INCLUDED diff --git a/JSON/include/Poco/JSON/ParseHandler.h b/JSON/include/Poco/JSON/ParseHandler.h index cde518381..3b88167bf 100644 --- a/JSON/include/Poco/JSON/ParseHandler.h +++ b/JSON/include/Poco/JSON/ParseHandler.h @@ -28,14 +28,19 @@ namespace Poco { namespace JSON { -class JSON_API ParseHandler : public Handler - /// Provides a default handler for the JSON parser. - /// This handler will build up an object or array based - /// on the handlers called by the parser. +class JSON_API ParseHandler: public Handler + /// ParseHandler is the default handler for the JSON Parser. + /// + /// This handler will construct an Object or Array based + /// on the handlers called by the Parser. { public: ParseHandler(bool preserveObjectOrder = false); /// Creates the ParseHandler. + /// + /// If preserveObjectOrder is true, the order of properties + /// inside objects is preserved. Otherwise, items + /// will be sorted by keys. virtual ~ParseHandler(); /// Destroys the ParseHandler. @@ -100,6 +105,9 @@ private: }; +// +// inlines +// inline Dynamic::Var ParseHandler::asVar() const { return _result; @@ -157,11 +165,7 @@ inline void ParseHandler::null() } -typedef ParseHandler ParseHandler; -//@ deprecated - - -}} // namespace Poco::JSON +} } // namespace Poco::JSON #endif // JSON_ParseHandler_INCLUDED diff --git a/JSON/include/Poco/JSON/Parser.h b/JSON/include/Poco/JSON/Parser.h index b44484f46..05022f70a 100644 --- a/JSON/include/Poco/JSON/Parser.h +++ b/JSON/include/Poco/JSON/Parser.h @@ -15,6 +15,7 @@ // SPDX-License-Identifier: BSL-1.0 // + /* Copyright (c) 2005 JSON.org @@ -39,6 +40,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + #ifndef JSON_JSONParser_INCLUDED #define JSON_JSONParser_INCLUDED @@ -58,22 +60,34 @@ namespace JSON { class JSON_API Parser - /// A RFC 4627 compatible class for parsing JSON strings or streams. + /// A parser for reading RFC 4627 compliant JSON from strings or streams. /// - /// See http://www.ietf.org/rfc/rfc4627.txt for specification. - /// - /// Usage example: + /// Simple usage example: /// /// std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }"; /// Parser parser; /// Var result = parser.parse(json); - /// // ... use result + /// // ... use result (see next example) /// parser.reset(); /// std::ostringstream ostr; /// PrintHandler::Ptr pHandler = new PrintHandler(ostr); /// parser.setHandler(pHandler); /// parser.parse(json); // ostr.str() == json + /// ---- + /// + /// The result of parsing a valid JSON document will be either an Object + /// or an Array. Therefore the result of parse() is a Poco::Dynamic::Var + /// containing a Poco::SharedPtr to an Object or Array instance. + /// + /// Example: /// + /// std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }"; + /// Parser parser; + /// Var result = parser.parse(json); + /// Object::Ptr object = result.extract(); + /// std::string name = object.getValue("name"); + /// Array::Ptr children = object.getArray("children"); + /// ---- { public: typedef std::char_traits CharTraits; @@ -201,7 +215,7 @@ public: static const int JSON_UNLIMITED_DEPTH = -1; Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE); - /// Creates JSON Parser. + /// Creates JSON Parser, using the given Handler and buffer size. virtual ~Parser(); /// Destroys JSON Parser. @@ -210,17 +224,21 @@ public: /// Resets the parser. void setAllowComments(bool comments); - /// Allow comments. By default, comments are not allowed. + /// Allow or disallow comments. By default, comments are not allowed. bool getAllowComments() const; /// Returns true if comments are allowed, false otherwise. + /// /// By default, comments are not allowed. void setAllowNullByte(bool nullByte); - /// Allow null byte in strings. By default, null byte is allowed. + /// Allow or disallow null byte in strings. + /// + /// By default, null byte is allowed. bool getAllowNullByte() const; /// Returns true if null byte is allowed, false otherwise. + /// /// By default, null bytes are allowed. void setDepth(std::size_t depth); @@ -230,16 +248,16 @@ public: /// Returns the allowed JSON depth. Dynamic::Var parse(const std::string& json); - /// Parses a string. + /// Parses JSON from a string. Dynamic::Var parse(std::istream& in); - /// Parses a JSON from the input stream. + /// Parses JSON from an input stream. void setHandler(const Handler::Ptr& pHandler); - /// Set the handler. + /// Set the Handler. const Handler::Ptr& getHandler(); - /// Returns the handler. + /// Returns the Handler. Dynamic::Var asVar() const; /// Returns the result of parsing; @@ -261,23 +279,14 @@ private: /// Returns false if there is underflow or if the modes mismatch. void growBuffer(); - void clearBuffer(); - void parseBufferPushBackChar(char c); - void parseBufferPopBackChar(); - void addCharToParseBuffer(CharIntType nextChar, int nextClass); - void addEscapedCharToParseBuffer(CharIntType nextChar); - CharIntType decodeUnicodeChar(); - void assertNotStringNullBool(); - void assertNonContainer(); - void parseBuffer(); template @@ -315,7 +324,7 @@ private: unsigned char ch = static_cast(CharTraits::to_char_type(nextChar)); // Determine the character's class. - if ((!_allowNullByte && ch == 0)) return false; + if (!_allowNullByte && ch == 0) return false; if (ch >= 0x80) { nextClass = C_ETC; @@ -327,7 +336,7 @@ private: char buffer[4]; buffer[0] = nextChar; - for(int i = 1; i < count; ++i) + for (int i = 1; i < count; ++i) { int c = 0; if (!source.nextChar(c)) throw Poco::JSON::JSONException("Invalid UTF8 sequence found"); @@ -339,7 +348,7 @@ private: throw Poco::JSON::JSONException("No legal UTF8 found"); } - for(int i = 0; i < count; ++i) + for (int i = 0; i < count; ++i) { parseBufferPushBackChar(buffer[i]); } @@ -366,7 +375,7 @@ private: { // Unicode character case UC: - if(!decodeUnicodeChar()) return false; + if (!decodeUnicodeChar()) return false; // check if we need to read a second UTF-16 char if (_utf16HighSurrogate) _state = D1; else _state = ST; @@ -449,7 +458,7 @@ private: { case MODE_ARRAY: case MODE_OBJECT: - switch(_state) + switch (_state) { case VA: case AR: @@ -591,8 +600,10 @@ private: } bool done(); - static CharIntType utf8CheckFirst(char byte); + bool isHighSurrogate(unsigned uc); + bool isLowSurrogate(unsigned uc); + unsigned decodeSurrogatePair(unsigned hi, unsigned lo); static const int _asciiClass[128]; /// This array maps the 128 ASCII characters into character classes. @@ -602,10 +613,6 @@ private: static const int _stateTransitionTable[NR_STATES][NR_CLASSES]; static const int xx = -1; - bool isHighSurrogate(unsigned uc); - bool isLowSurrogate(unsigned uc); - unsigned decodeSurrogatePair(unsigned hi, unsigned lo); - Handler::Ptr _pHandler; signed char _state; signed char _beforeCommentState; @@ -623,6 +630,9 @@ private: }; +// +// inlines +// inline void Parser::setAllowComments(bool comments) { _allowComments = comments; @@ -735,7 +745,7 @@ inline unsigned Parser::decodeSurrogatePair(unsigned hi, unsigned lo) } -}} // namespace Poco::JSON +} } // namespace Poco::JSON #endif // JSON_JSONParser_INCLUDED diff --git a/JSON/include/Poco/JSON/PrintHandler.h b/JSON/include/Poco/JSON/PrintHandler.h index b063565ad..852bc5199 100644 --- a/JSON/include/Poco/JSON/PrintHandler.h +++ b/JSON/include/Poco/JSON/PrintHandler.h @@ -28,10 +28,10 @@ namespace Poco { namespace JSON { -class JSON_API PrintHandler : public Handler +class JSON_API PrintHandler: public Handler /// PrintHandler formats and prints the JSON object - /// to either user-provided std::ostream or standard out. - /// If indent i zero, the output is condensed JSON string, + /// to either user-provided std::ostream or standard output. + /// If indent is zero, the output is a condensed JSON string, /// otherwise, the proper indentation is applied to elements. { public: @@ -104,7 +104,6 @@ public: /// Sets indentation. private: - const char* endLine() const; unsigned indent(); bool printFlat() const; @@ -119,6 +118,9 @@ private: }; +// +// inlines +// inline void PrintHandler::setIndent(unsigned indent) { _indent = indent; @@ -131,8 +133,7 @@ inline bool PrintHandler::array() const } - -}} // namespace Poco::JSON +} } // namespace Poco::JSON #endif // JSON_PrintHandler_INCLUDED diff --git a/JSON/include/Poco/JSON/Query.h b/JSON/include/Poco/JSON/Query.h index f009cfb16..a2e57830b 100644 --- a/JSON/include/Poco/JSON/Query.h +++ b/JSON/include/Poco/JSON/Query.h @@ -15,6 +15,7 @@ // SPDX-License-Identifier: BSL-1.0 // + #ifndef JSON_JSONQuery_INCLUDED #define JSON_JSONQuery_INCLUDED @@ -33,44 +34,56 @@ class JSON_API Query { public: Query(const Dynamic::Var& source); - /// Creates the Query; source must be JSON Object, Array, Object::Ptr, + /// Creates a Query/ + /// + /// Source must be JSON Object, Array, Object::Ptr, /// Array::Ptr or empty Var. Any other type will trigger throwing of /// InvalidArgumentException. + /// /// Creating Query holding Ptr will typically result in faster /// performance. virtual ~Query(); - /// Destructor + /// Destroys the Query. Object::Ptr findObject(const std::string& path) const; - /// Search for an object. When the object can't be found, a zero Ptr - /// is returned; otherwise, a shared pointer to internally held object + /// Search for an object. + /// + /// When the object can't be found, a zero Ptr is returned; + /// otherwise, a shared pointer to internally held object /// is returned. /// If object (as opposed to a pointer to object) is held /// internally, a shared pointer to new (heap-allocated) Object is /// returned; this may be expensive operation. Object& findObject(const std::string& path, Object& obj) const; - /// Search for an object. If object is found, it is assigned to the + /// Search for an object. + /// + /// If object is found, it is assigned to the /// Object through the reference passed in. When the object can't be /// found, the provided Object is emptied and returned. Array::Ptr findArray(const std::string& path) const; - /// Search for an array. When the array can't be found, a zero Ptr - /// is returned; otherwise, a shared pointer to internally held array + /// Search for an array. + /// + /// When the array can't be found, a zero Ptr is returned; + /// otherwise, a shared pointer to internally held array /// is returned. /// If array (as opposed to a pointer to array) is held /// internally, a shared pointer to new (heap-allocated) Object is /// returned; this may be expensive operation. Array& findArray(const std::string& path, Array& obj) const; - /// Search for an array. If array is found, it is assigned to the + /// Search for an array. + /// + /// If array is found, it is assigned to the /// Object through the reference passed in. When the array can't be /// found, the provided Object is emptied and returned. Dynamic::Var find(const std::string& path) const; - /// Searches a value - /// For example: "person.children[0].name" will return the + /// Searches a value. + /// + /// Example: "person.children[0].name" will return the /// the name of the first child. When the value can't be found /// an empty value is returned. @@ -82,13 +95,15 @@ public: { T result = def; Dynamic::Var value = find(path); - if ( ! value.isEmpty() ) + if (!value.isEmpty()) { try { result = value.convert(); } - catch(...) { } + catch (...) + { + } } return result; } @@ -106,7 +121,7 @@ private: }; -}} // namespace Poco::JSON +} } // namespace Poco::JSON #endif // JSON_JSONQuery_INCLUDED diff --git a/JSON/include/Poco/JSON/Stringifier.h b/JSON/include/Poco/JSON/Stringifier.h index de3336ff1..f22d8633d 100644 --- a/JSON/include/Poco/JSON/Stringifier.h +++ b/JSON/include/Poco/JSON/Stringifier.h @@ -30,15 +30,17 @@ namespace JSON { class JSON_API Stringifier - /// Helper class for creating a String from a JSON object or array + /// Helper class for creating a string from a JSON object or array. { public: static void condense(const Dynamic::Var& any, std::ostream& out); /// Writes a condensed string representation of the value to the output stream while preserving the insertion order. + /// /// This is just a "shortcut" to stringify(any, out) with name indicating the function effect. static void stringify(const Dynamic::Var& any, std::ostream& out, unsigned int indent = 0, int step = -1); /// Writes a string representation of the value to the output stream. + /// /// When indent is 0, the string will be created as small as possible. /// When preserveInsertionOrder is true, the original string object members order will be preserved; /// otherwise, object members are sorted by their names. @@ -53,7 +55,8 @@ inline void Stringifier::condense(const Dynamic::Var& any, std::ostream& out) stringify(any, out, 0, -1); } -}} // namespace Poco::JSON + +} } // namespace Poco::JSON #endif // JSON_JSONStringifier_INCLUDED diff --git a/JSON/include/Poco/JSON/Template.h b/JSON/include/Poco/JSON/Template.h index 5118ea3f7..0b5c42c19 100644 --- a/JSON/include/Poco/JSON/Template.h +++ b/JSON/include/Poco/JSON/Template.h @@ -15,6 +15,7 @@ // SPDX-License-Identifier: BSL-1.0 // + #ifndef JSON_JSONTemplate_INCLUDED #define JSON_JSONTemplate_INCLUDED @@ -42,7 +43,7 @@ class JSON_API Template /// Template is a template engine which uses JSON as input /// for generating output. There are commands for /// looping over JSON arrays, include other templates, - /// conditional output, ... + /// conditional output, etc. /// /// All text is send to the outputstream. A command is placed /// between @@ -91,13 +92,13 @@ public: typedef SharedPtr