summaryrefslogtreecommitdiffstats
path: root/lib/libsqlite3/tool
diff options
context:
space:
mode:
authorsthen <sthen@openbsd.org>2016-09-23 09:21:58 +0000
committersthen <sthen@openbsd.org>2016-09-23 09:21:58 +0000
commit25e4f8ab5acd0ef40feec6767a572bebbbe294b3 (patch)
tree20197c0e46bb6d260f4a310b6d5dd73b8d826f01 /lib/libsqlite3/tool
parentremove usr.bin/sqlite3, it has moved back to ports (diff)
downloadwireguard-openbsd-25e4f8ab5acd0ef40feec6767a572bebbbe294b3.tar.xz
wireguard-openbsd-25e4f8ab5acd0ef40feec6767a572bebbbe294b3.zip
remove lib/libsqlite3, it has moved back to ports
Diffstat (limited to 'lib/libsqlite3/tool')
-rwxr-xr-xlib/libsqlite3/tool/build-all-msvc.bat771
-rw-r--r--lib/libsqlite3/tool/build-shell.sh22
-rw-r--r--lib/libsqlite3/tool/checkSpacing.c84
-rw-r--r--lib/libsqlite3/tool/diffdb.c44
-rw-r--r--lib/libsqlite3/tool/extract.c46
-rw-r--r--lib/libsqlite3/tool/fast_vacuum.c234
-rw-r--r--lib/libsqlite3/tool/fragck.tcl149
-rw-r--r--lib/libsqlite3/tool/fuzzershell.c866
-rw-r--r--lib/libsqlite3/tool/genfkey.README137
-rw-r--r--lib/libsqlite3/tool/genfkey.test354
-rw-r--r--lib/libsqlite3/tool/getlock.c134
-rw-r--r--lib/libsqlite3/tool/lemon.c5171
-rw-r--r--lib/libsqlite3/tool/lempar.c880
-rw-r--r--lib/libsqlite3/tool/loadfts.c242
-rw-r--r--lib/libsqlite3/tool/logest.c170
-rw-r--r--lib/libsqlite3/tool/mkautoconfamal.sh82
-rw-r--r--lib/libsqlite3/tool/mkkeywordhash.c610
-rw-r--r--lib/libsqlite3/tool/mkopts.tcl51
-rw-r--r--lib/libsqlite3/tool/mkpragmatab.tcl471
-rw-r--r--lib/libsqlite3/tool/mkspeedsql.tcl237
-rw-r--r--lib/libsqlite3/tool/mksqlite3c-noext.tcl355
-rw-r--r--lib/libsqlite3/tool/mksqlite3c.tcl388
-rw-r--r--lib/libsqlite3/tool/mksqlite3h.tcl127
-rw-r--r--lib/libsqlite3/tool/mksqlite3internalh.tcl148
-rw-r--r--lib/libsqlite3/tool/mkvsix.tcl840
-rw-r--r--lib/libsqlite3/tool/offsets.c329
-rw-r--r--lib/libsqlite3/tool/omittest.tcl299
-rw-r--r--lib/libsqlite3/tool/opcodeDoc.awk23
-rw-r--r--lib/libsqlite3/tool/pagesig.c92
-rw-r--r--lib/libsqlite3/tool/restore_jrnl.tcl233
-rw-r--r--lib/libsqlite3/tool/rollback-test.c155
-rw-r--r--lib/libsqlite3/tool/showdb.c1177
-rw-r--r--lib/libsqlite3/tool/showjournal.c138
-rw-r--r--lib/libsqlite3/tool/showlocks.c64
-rw-r--r--lib/libsqlite3/tool/showstat4.c158
-rw-r--r--lib/libsqlite3/tool/showwal.c596
-rw-r--r--lib/libsqlite3/tool/soak1.tcl103
-rw-r--r--lib/libsqlite3/tool/space_used.tcl111
-rw-r--r--lib/libsqlite3/tool/spaceanal.tcl805
-rw-r--r--lib/libsqlite3/tool/speedtest.tcl275
-rw-r--r--lib/libsqlite3/tool/speedtest16.c169
-rw-r--r--lib/libsqlite3/tool/speedtest2.tcl207
-rw-r--r--lib/libsqlite3/tool/speedtest8.c260
-rw-r--r--lib/libsqlite3/tool/speedtest8inst1.c216
-rw-r--r--lib/libsqlite3/tool/split-sqlite3c.tcl82
-rw-r--r--lib/libsqlite3/tool/sqldiff.c1857
-rw-r--r--lib/libsqlite3/tool/stack_usage.tcl98
-rw-r--r--lib/libsqlite3/tool/symbols-mingw.sh33
-rw-r--r--lib/libsqlite3/tool/symbols.sh34
-rw-r--r--lib/libsqlite3/tool/tostr.awk9
-rw-r--r--lib/libsqlite3/tool/varint.c123
-rw-r--r--lib/libsqlite3/tool/vdbe-compress.tcl143
-rw-r--r--lib/libsqlite3/tool/vdbe_profile.tcl82
-rw-r--r--lib/libsqlite3/tool/warnings-clang.sh14
-rw-r--r--lib/libsqlite3/tool/warnings.sh41
-rw-r--r--lib/libsqlite3/tool/win/sqlite.vsixbin32825 -> 0 bytes
56 files changed, 0 insertions, 20539 deletions
diff --git a/lib/libsqlite3/tool/build-all-msvc.bat b/lib/libsqlite3/tool/build-all-msvc.bat
deleted file mode 100755
index 4842dc40744..00000000000
--- a/lib/libsqlite3/tool/build-all-msvc.bat
+++ /dev/null
@@ -1,771 +0,0 @@
-@ECHO OFF
-
-::
-:: build-all-msvc.bat --
-::
-:: Multi-Platform Build Tool for MSVC
-::
-
-REM
-REM This batch script is used to build the SQLite DLL for multiple platforms
-REM and configurations using MSVC. The built SQLite DLLs, their associated
-REM import libraries, and optionally their symbols files, are placed within
-REM the directory specified on the command line, in sub-directories named for
-REM their respective platforms and configurations. This batch script must be
-REM run from inside a Visual Studio Command Prompt for the desired version of
-REM Visual Studio ^(the initial platform configured for the command prompt does
-REM not really matter^). Exactly one command line argument is required, the
-REM name of an existing directory to be used as the final destination directory
-REM for the generated output files, which will be placed in sub-directories
-REM created therein. Ideally, the directory specified should be empty.
-REM
-REM Example:
-REM
-REM CD /D C:\dev\sqlite\core
-REM tool\build-all-msvc.bat C:\Temp
-REM
-REM In the example above, "C:\dev\sqlite\core" represents the root of the
-REM source tree for SQLite and "C:\Temp" represents the final destination
-REM directory for the generated output files.
-REM
-REM Please note that the SQLite build process performed by the Makefile
-REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl
-REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH
-REM environment variable unless a pre-existing amalgamation file is used.
-REM
-REM There are several environment variables that may be set to modify the
-REM behavior of this batch script and its associated Makefile. The list of
-REM platforms to build may be overriden by using the PLATFORMS environment
-REM variable, which should contain a list of platforms ^(e.g. x86 x86_amd64
-REM x86_arm^). All platforms must be supported by the version of Visual Studio
-REM being used. The list of configurations to build may be overridden by
-REM setting the CONFIGURATIONS environment variable, which should contain a
-REM list of configurations to build ^(e.g. Debug Retail^). Neither of these
-REM variable values may contain any double quotes, surrounding or embedded.
-REM
-REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment
-REM variables may be set to specify the location of the CRT, Universal CRT, and
-REM Windows SDK, respectively, that may be needed to compile executables native
-REM to the architecture of the build machine during any cross-compilation that
-REM may be necessary, depending on the platforms to be built. These values in
-REM these three variables should be surrounded by double quotes if they contain
-REM spaces.
-REM
-REM There are a few other environment variables that impact the build process
-REM when set ^(to anything^), they are:
-REM
-REM NOCLEAN
-REM
-REM When set, the "clean" target will not be used during each build iteration.
-REM However, the target binaries, if any, will still be deleted manually prior
-REM to being rebuilt. Setting this environment variable is only rarely needed
-REM and could cause issues in some circumstances; therefore, setting it is not
-REM recommended.
-REM
-REM NOSYMBOLS
-REM
-REM When set, copying of symbol files ^(*.pdb^) created during the build will
-REM be skipped and they will not appear in the final destination directory.
-REM Setting this environment variable is never strictly needed and could cause
-REM issues in some circumstances; therefore, setting it is not recommended.
-REM
-REM BUILD_ALL_SHELL
-REM
-REM When set, the command line shell will be built for each selected platform
-REM and configuration as well. In addition, the command line shell binaries
-REM will be copied, with their symbols, to the final destination directory.
-REM
-REM USE_WINV63_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It forces this batch script to
-REM assume the Windows 8.1 SDK location should be used.
-REM
-REM USE_WINV100_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It causes this batch script to
-REM assume the Windows 10.0 SDK location should be used.
-REM
-REM NMAKE_ARGS
-REM
-REM When set, the value is expanded and passed to the NMAKE command line, after
-REM its other arguments. This is used to specify additional NMAKE options, for
-REM example:
-REM
-REM SET NMAKE_ARGS=FOR_WINRT=1
-REM
-SETLOCAL
-
-REM SET __ECHO=ECHO
-REM SET __ECHO2=ECHO
-REM SET __ECHO3=ECHO
-IF NOT DEFINED _AECHO (SET _AECHO=REM)
-IF NOT DEFINED _CECHO (SET _CECHO=REM)
-IF NOT DEFINED _VECHO (SET _VECHO=REM)
-
-SET REDIRECT=^>
-IF DEFINED __ECHO SET REDIRECT=^^^>
-
-%_AECHO% Running %0 %*
-
-REM SET DFLAGS=/L
-
-%_VECHO% DFlags = '%DFLAGS%'
-
-SET FFLAGS=/V /F /G /H /I /R /Y /Z
-
-%_VECHO% FFlags = '%FFLAGS%'
-
-SET ROOT=%~dp0\..
-SET ROOT=%ROOT:\\=\%
-
-%_VECHO% Root = '%ROOT%'
-
-REM
-REM NOTE: The first and only argument to this batch file should be the output
-REM directory where the platform-specific binary directories should be
-REM created.
-REM
-SET BINARYDIRECTORY=%1
-
-IF NOT DEFINED BINARYDIRECTORY (
- GOTO usage
-)
-
-%_VECHO% BinaryDirectory = '%BINARYDIRECTORY%'
-
-SET DUMMY=%2
-
-IF DEFINED DUMMY (
- GOTO usage
-)
-
-REM
-REM NOTE: From this point, we need a clean error level. Reset it now.
-REM
-CALL :fn_ResetErrorLevel
-
-REM
-REM NOTE: Change the current directory to the root of the source tree, saving
-REM the current directory on the directory stack.
-REM
-%__ECHO2% PUSHD "%ROOT%"
-
-IF ERRORLEVEL 1 (
- ECHO Could not change directory to "%ROOT%".
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the ComSpec environment variable to be set,
-REM typically to something like "C:\Windows\System32\cmd.exe".
-REM
-IF NOT DEFINED ComSpec (
- ECHO The ComSpec environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the VcInstallDir environment variable to be
-REM set. Tyipcally, this means this batch file needs to be run from an
-REM MSVC command prompt.
-REM
-IF NOT DEFINED VCINSTALLDIR (
- ECHO The VCINSTALLDIR environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: If the list of platforms is not already set, use the default list.
-REM
-IF NOT DEFINED PLATFORMS (
- SET PLATFORMS=x86 x86_amd64 x86_arm
-)
-
-%_VECHO% Platforms = '%PLATFORMS%'
-
-REM
-REM NOTE: If the list of configurations is not already set, use the default
-REM list.
-REM
-IF NOT DEFINED CONFIGURATIONS (
- SET CONFIGURATIONS=Debug Retail
-)
-
-%_VECHO% Configurations = '%CONFIGURATIONS%'
-
-REM
-REM NOTE: If the command used to invoke NMAKE is not already set, use the
-REM default.
-REM
-IF NOT DEFINED NMAKE_CMD (
- SET NMAKE_CMD=nmake -B -f Makefile.msc
-)
-
-%_VECHO% NmakeCmd = '%NMAKE_CMD%'
-%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
-
-REM
-REM NOTE: Setup environment variables to translate between the MSVC platform
-REM names and the names to be used for the platform-specific binary
-REM directories.
-REM
-SET amd64_NAME=x64
-SET arm_NAME=ARM
-SET x64_NAME=x64
-SET x86_NAME=x86
-SET x86_amd64_NAME=x64
-SET x86_arm_NAME=ARM
-SET x86_x64_NAME=x64
-
-%_VECHO% amd64_Name = '%amd64_NAME%'
-%_VECHO% arm_Name = '%arm_NAME%'
-%_VECHO% x64_Name = '%x64_NAME%'
-%_VECHO% x86_Name = '%x86_NAME%'
-%_VECHO% x86_amd64_Name = '%x86_amd64_NAME%'
-%_VECHO% x86_arm_Name = '%x86_arm_NAME%'
-%_VECHO% x86_x64_Name = '%x86_x64_NAME%'
-
-REM
-REM NOTE: Check for the external tools needed during the build process ^(i.e.
-REM those that do not get compiled as part of the build process itself^)
-REM along the PATH.
-REM
-FOR %%T IN (gawk.exe tclsh85.exe) DO (
- SET %%T_PATH=%%~dp$PATH:T
-)
-
-REM
-REM NOTE: The Gawk executable "gawk.exe" is required during the SQLite build
-REM process unless a pre-existing amalgamation file is used.
-REM
-IF NOT DEFINED gawk.exe_PATH (
- ECHO The Gawk executable "gawk.exe" is required to be in the PATH.
- GOTO errors
-)
-
-REM
-REM NOTE: The Tcl 8.5 executable "tclsh85.exe" is required during the SQLite
-REM build process unless a pre-existing amalgamation file is used.
-REM
-IF NOT DEFINED tclsh85.exe_PATH (
- ECHO The Tcl 8.5 executable "tclsh85.exe" is required to be in the PATH.
- GOTO errors
-)
-
-REM
-REM NOTE: Set the TOOLPATH variable to contain all the directories where the
-REM external tools were found in the search above.
-REM
-SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH%
-
-%_VECHO% ToolPath = '%TOOLPATH%'
-
-REM
-REM NOTE: Setting the Windows SDK library path is only required for MSVC
-REM 2012, 2013, and 2015.
-REM
-CALL :fn_UnsetVariable SET_NSDKLIBPATH
-
-REM
-REM NOTE: Setting the Universal CRT library path is only required for MSVC
-REM 2015.
-REM
-CALL :fn_UnsetVariable SET_NUCRTLIBPATH
-
-REM
-REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows
-REM SDK directory handling is slightly different for those versions.
-REM
-IF "%VisualStudioVersion%" == "11.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "12.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "14.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-
- REM
- REM NOTE: If the Universal CRT library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NUCRTLIBPATH (
- SET SET_NUCRTLIBPATH=1
- )
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the UCRT libraries may
-REM be found. It is only used when compiling against the UCRT.
-REM
-IF DEFINED UCRTVersion (
- SET NUCRTVER=%UCRTVersion%
-) ELSE (
- SET NUCRTVER=10.0.10240.0
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK
-REM libraries may be found. It is only used when compiling with the
-REM Windows 10.0 SDK.
-REM
-IF DEFINED WindowsSDKLibVersion (
- SET WIN10SDKVER=%WindowsSDKLibVersion:\=%
-) ELSE (
- SET WIN10SDKVER=%NUCRTVER%
-)
-
-REM
-REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch
-REM file is necessary to setup the build environment. Since the variable
-REM values involved here may contain parenthesis, using GOTO instead of
-REM an IF block is required.
-REM
-IF DEFINED WindowsPhoneKitDir GOTO set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\vcvarsall.bat
-GOTO set_vcvarsall_done
-:set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat
-:set_vcvarsall_done
-SET VCVARSALL=%VCVARSALL:\\=\%
-
-REM
-REM NOTE: This is the outer loop. There should be exactly one iteration per
-REM platform.
-REM
-FOR %%P IN (%PLATFORMS%) DO (
- REM
- REM NOTE: Using the MSVC platform name, lookup the simpler platform name to
- REM be used for the name of the platform-specific binary directory via
- REM the environment variables setup earlier.
- REM
- CALL :fn_CopyVariable %%P_NAME PLATFORMNAME
-
- REM
- REM NOTE: This is the second loop. There should be exactly one iteration.
- REM This loop is necessary because the PlatformName environment
- REM variable was set above and that value is needed by some of the
- REM commands contained in the inner loop. If these commands were
- REM directly contained in the outer loop, the PlatformName environment
- REM variable would be stuck with its initial empty value instead.
- REM
- FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO (
- REM
- REM NOTE: Attempt to clean the environment of all variables used by MSVC
- REM and/or Visual Studio. This block may need to be updated in the
- REM future to account for additional environment variables.
- REM
- CALL :fn_UnsetVariable CommandPromptType
- CALL :fn_UnsetVariable DevEnvDir
- CALL :fn_UnsetVariable DNX_HOME
- CALL :fn_UnsetVariable ExtensionSdkDir
- CALL :fn_UnsetVariable Framework35Version
- CALL :fn_UnsetVariable Framework40Version
- CALL :fn_UnsetVariable FrameworkDir
- CALL :fn_UnsetVariable FrameworkDir32
- CALL :fn_UnsetVariable FrameworkVersion
- CALL :fn_UnsetVariable FrameworkVersion32
- CALL :fn_UnsetVariable FSHARPINSTALLDIR
- CALL :fn_UnsetVariable INCLUDE
- CALL :fn_UnsetVariable LIB
- CALL :fn_UnsetVariable LIBPATH
- CALL :fn_UnsetVariable NETFXSDKDir
- CALL :fn_UnsetVariable Platform
- CALL :fn_UnsetVariable UCRTVersion
- CALL :fn_UnsetVariable UniversalCRTSdkDir
- REM CALL :fn_UnsetVariable VCINSTALLDIR
- CALL :fn_UnsetVariable VSINSTALLDIR
- CALL :fn_UnsetVariable WindowsLibPath
- CALL :fn_UnsetVariable WindowsPhoneKitDir
- CALL :fn_UnsetVariable WindowsSdkDir
- CALL :fn_UnsetVariable WindowsSdkDir_35
- CALL :fn_UnsetVariable WindowsSdkDir_old
- CALL :fn_UnsetVariable WindowsSDKLibVersion
- CALL :fn_UnsetVariable WindowsSDKVersion
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
-
- REM
- REM NOTE: Reset the PATH here to the absolute bare minimum required.
- REM
- SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
-
- REM
- REM NOTE: This is the inner loop. There are normally two iterations, one
- REM for each supported build configuration, e.g. Debug or Retail.
- REM
- FOR %%B IN (%CONFIGURATIONS%) DO (
- REM
- REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG
- REM environment variables to be picked up by the MSVC makefile
- REM itself.
- REM
- %_AECHO% Building the %%B configuration for platform %%P with name %%D...
-
- IF /I "%%B" == "Debug" (
- REM
- REM NOTE: Using this level for the DEBUG environment variable should
- REM disable all compiler optimizations and prevent use of the
- REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR
- REM and SQLITE_DEBUG defines should be enabled.
- REM
- SET DEBUG=3
-
- REM
- REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG
- REM define.
- REM
- SET MEMDEBUG=1
- ) ELSE (
- CALL :fn_UnsetVariable DEBUG
- CALL :fn_UnsetVariable MEMDEBUG
- )
-
- REM
- REM NOTE: Launch a nested command shell to perform the following steps:
- REM
- REM 1. Setup the MSVC environment for this platform using the
- REM official batch file.
- REM
- REM 2. Make sure that no stale build output files are present.
- REM
- REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform.
- REM
- REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform to the platform-specific directory beneath the
- REM binary directory.
- REM
- REM 5. Unless prevented from doing so, copy the "sqlite3.pdb"
- REM symbols file for this platform to the platform-specific
- REM directory beneath the binary directory.
- REM
- "%ComSpec%" /C (
- REM
- REM NOTE: Attempt to setup the MSVC environment for this platform.
- REM
- %__ECHO3% CALL "%VCVARSALL%" %%P
-
- IF ERRORLEVEL 1 (
- ECHO Failed to call "%VCVARSALL%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: If this batch file is not running in "what-if" mode, check to
- REM be sure we were actually able to setup the MSVC environment
- REM as current versions of their official batch file do not set
- REM the exit code upon failure.
- REM
- IF NOT DEFINED __ECHO3 (
- IF NOT DEFINED WindowsPhoneKitDir (
- IF NOT DEFINED WindowsSdkDir (
- ECHO Cannot build, Windows SDK not found for platform %%P.
- GOTO errors
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path
- REM cannot simply be the "lib" sub-directory beneath the location
- REM specified in the WindowsSdkDir environment variable because
- REM that location does not actually contain the necessary library
- REM files for x86. This must be done for each iteration because
- REM it relies upon the WindowsSdkDir environment variable being
- REM set by the batch file used to setup the MSVC environment.
- REM
- IF DEFINED SET_NSDKLIBPATH (
- REM
- REM NOTE: The Windows Phone SDK has a slightly different directory
- REM structure and must be handled specially here.
- REM
- IF DEFINED WindowsPhoneKitDir (
- CALL :fn_CopyVariable WindowsPhoneKitDir NSDKLIBPATH
- CALL :fn_AppendVariable NSDKLIBPATH \lib\x86
- ) ELSE IF DEFINED WindowsSdkDir (
- CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
-
- REM
- REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly
- REM different directory naming conventions.
- REM
- IF DEFINED USE_WINV100_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10SDKVER%\um\x86
- CALL :fn_CopyVariable WindowsSdkDir PSDKLIBPATH
- CALL :fn_AppendVariable PSDKLIBPATH lib\%WIN10SDKVER%\um\%%D
- ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "12.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "14.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2015, setting the Universal CRT library path
- REM for x86 may be required as well. This must also be done for
- REM each iteration because it relies upon the UniversalCRTSdkDir
- REM environment variable being set by the batch file used to
- REM setup the MSVC environment.
- REM
- IF DEFINED SET_NUCRTLIBPATH (
- IF DEFINED UniversalCRTSdkDir (
- CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
- CALL :fn_AppendVariable NUCRTLIBPATH \lib\%NUCRTVER%\ucrt\x86
- )
- )
-
- REM
- REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
- REM makefile to clean any stale build output from previous
- REM iterations of this loop and/or previous runs of this batch
- REM file, etc.
- REM
- IF NOT DEFINED NOCLEAN (
- %__ECHO% %NMAKE_CMD% clean
-
- IF ERRORLEVEL 1 (
- ECHO Failed to clean for platform %%P.
- GOTO errors
- )
- ) ELSE (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final core library output files only...
- %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- %__ECHO% %NMAKE_CMD% sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "sqlite3.dll" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
- REM the build and platform beneath the binary directory unless we
- REM are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
-
- REM
- REM NOTE: If requested, also build the shell executable.
- REM
- IF DEFINED BUILD_ALL_SHELL (
- REM
- REM NOTE: If necessary, make sure any previous build output for the
- REM shell executable is deleted.
- REM
- IF DEFINED NOCLEAN (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final shell executable output files only...
- %__ECHO% DEL /Q sqlite3.exe sqlite3sh.pdb 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- %__ECHO% %NMAKE_CMD% sqlite3.exe XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "sqlite3.exe" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory
- REM for the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY sqlite3.exe "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "sqlite3.exe" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
- REM for the build and platform beneath the binary directory
- REM unless we are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- %__ECHO% XCOPY sqlite3sh.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "sqlite3sh.pdb" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
- )
- )
- )
- )
-
- REM
- REM NOTE: Handle any errors generated during the nested command shell.
- REM
- IF ERRORLEVEL 1 (
- GOTO errors
- )
-)
-
-REM
-REM NOTE: Restore the saved current directory from the directory stack.
-REM
-%__ECHO2% POPD
-
-IF ERRORLEVEL 1 (
- ECHO Could not restore directory.
- GOTO errors
-)
-
-REM
-REM NOTE: If we get to this point, we have succeeded.
-REM
-GOTO no_errors
-
-:fn_ShowVariable
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%2%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- IF NOT "%%V" == "" (
- IF NOT "%%V" == "%%%2%%" (
- %_VECHO% %1 = '%%V'
- )
- )
- )
- ENDLOCAL
- GOTO :EOF
-
-:fn_ResetErrorLevel
- VERIFY > NUL
- GOTO :EOF
-
-:fn_SetErrorLevel
- VERIFY MAYBE 2> NUL
- GOTO :EOF
-
-:fn_CopyVariable
- IF NOT DEFINED %1 GOTO :EOF
- IF "%2" == "" GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- ENDLOCAL && SET %2=%VALUE%
- GOTO :EOF
-
-:fn_UnsetVariable
- IF NOT "%1" == "" (
- SET %1=
- CALL :fn_ResetErrorLevel
- )
- GOTO :EOF
-
-:fn_AppendVariable
- SET __ECHO_CMD=ECHO %%%1%%
- IF DEFINED %1 (
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET %1=%%V%~2
- )
- ) ELSE (
- SET %1=%~2
- )
- SET __ECHO_CMD=
- CALL :fn_ResetErrorLevel
- GOTO :EOF
-
-:usage
- ECHO.
- ECHO Usage: %~nx0 ^<binaryDirectory^>
- ECHO.
- GOTO errors
-
-:errors
- CALL :fn_SetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Failure, errors were encountered.
- GOTO end_of_file
-
-:no_errors
- CALL :fn_ResetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Success, no errors were encountered.
- GOTO end_of_file
-
-:end_of_file
-%__ECHO% EXIT /B %ERRORLEVEL%
diff --git a/lib/libsqlite3/tool/build-shell.sh b/lib/libsqlite3/tool/build-shell.sh
deleted file mode 100644
index 6a48299d73b..00000000000
--- a/lib/libsqlite3/tool/build-shell.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-#
-# This script demonstrates how to do a full-featured build of the sqlite3
-# command-line shell on Linux.
-#
-# SQLite source code should be in a sibling directory named "sqlite". For
-# example, put SQLite sources in ~/sqlite/sqlite and run this script from
-# ~/sqlite/bld. There should be an appropriate Makefile in the current
-# directory as well.
-#
-make sqlite3.c
-gcc -o sqlite3 -g -Os -I. \
- -DSQLITE_THREADSAFE=0 \
- -DSQLITE_ENABLE_VFSTRACE \
- -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_FTS4 \
- -DSQLITE_ENABLE_RTREE \
- -DHAVE_READLINE \
- -DHAVE_USLEEP=1 \
- ../sqlite/src/shell.c \
- ../sqlite/src/test_vfstrace.c \
- sqlite3.c -ldl -lreadline -lncurses
diff --git a/lib/libsqlite3/tool/checkSpacing.c b/lib/libsqlite3/tool/checkSpacing.c
deleted file mode 100644
index ce38b08ce4c..00000000000
--- a/lib/libsqlite3/tool/checkSpacing.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-** This program checks for formatting problems in source code:
-**
-** * Any use of tab characters
-** * White space at the end of a line
-** * Blank lines at the end of a file
-**
-** Any violations are reported.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define CR_OK 0x001
-#define WSEOL_OK 0x002
-
-static void checkSpacing(const char *zFile, unsigned flags){
- FILE *in = fopen(zFile, "rb");
- int i;
- int seenSpace;
- int seenTab;
- int ln = 0;
- int lastNonspace = 0;
- char zLine[2000];
- if( in==0 ){
- printf("cannot open %s\n", zFile);
- return;
- }
- while( fgets(zLine, sizeof(zLine), in) ){
- seenSpace = 0;
- seenTab = 0;
- ln++;
- for(i=0; zLine[i]; i++){
- if( zLine[i]=='\t' && seenTab==0 ){
- printf("%s:%d: tab (\\t) character\n", zFile, ln);
- seenTab = 1;
- }else if( zLine[i]=='\r' ){
- if( (flags & CR_OK)==0 ){
- printf("%s:%d: carriage-return (\\r) character\n", zFile, ln);
- }
- }else if( zLine[i]==' ' ){
- seenSpace = 1;
- }else if( zLine[i]!='\n' ){
- lastNonspace = ln;
- seenSpace = 0;
- }
- }
- if( seenSpace && (flags & WSEOL_OK)==0 ){
- printf("%s:%d: whitespace at end-of-line\n", zFile, ln);
- }
- }
- fclose(in);
- if( lastNonspace<ln ){
- printf("%s:%d: blank lines at end of file (%d)\n",
- zFile, ln, ln - lastNonspace);
- }
-}
-
-int main(int argc, char **argv){
- int i;
- unsigned flags = WSEOL_OK;
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- while( z[0]=='-' ) z++;
- if( strcmp(z,"crok")==0 ){
- flags |= CR_OK;
- }else if( strcmp(z, "wseol")==0 ){
- flags &= ~WSEOL_OK;
- }else if( strcmp(z, "help")==0 ){
- printf("Usage: %s [options] FILE ...\n", argv[0]);
- printf(" --crok Do not report on carriage-returns\n");
- printf(" --wseol Complain about whitespace at end-of-line\n");
- printf(" --help This message\n");
- }else{
- printf("unknown command-line option: [%s]\n", argv[i]);
- printf("use --help for additional information\n");
- }
- }else{
- checkSpacing(argv[i], flags);
- }
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/diffdb.c b/lib/libsqlite3/tool/diffdb.c
deleted file mode 100644
index 0537d38723e..00000000000
--- a/lib/libsqlite3/tool/diffdb.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-** A utility for printing the differences between two SQLite database files.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-
-#define PAGESIZE 1024
-static int db1 = -1;
-static int db2 = -1;
-
-int main(int argc, char **argv){
- int iPg;
- unsigned char a1[PAGESIZE], a2[PAGESIZE];
- if( argc!=3 ){
- fprintf(stderr,"Usage: %s FILENAME FILENAME\n", argv[0]);
- exit(1);
- }
- db1 = open(argv[1], O_RDONLY);
- if( db1<0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- db2 = open(argv[2], O_RDONLY);
- if( db2<0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[2]);
- exit(1);
- }
- iPg = 1;
- while( read(db1, a1, PAGESIZE)==PAGESIZE && read(db2,a2,PAGESIZE)==PAGESIZE ){
- if( memcmp(a1,a2,PAGESIZE) ){
- printf("Page %d\n", iPg);
- }
- iPg++;
- }
- printf("%d pages checked\n", iPg-1);
- close(db1);
- close(db2);
-}
diff --git a/lib/libsqlite3/tool/extract.c b/lib/libsqlite3/tool/extract.c
deleted file mode 100644
index 5bf5caa31c9..00000000000
--- a/lib/libsqlite3/tool/extract.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-** Extract a range of bytes from a file.
-**
-** Usage:
-**
-** extract FILENAME OFFSET AMOUNT
-**
-** The bytes are written to standard output.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv){
- FILE *f;
- char *zBuf;
- int ofst;
- int n;
- size_t got;
-
- if( argc!=4 ){
- fprintf(stderr, "Usage: %s FILENAME OFFSET AMOUNT\n", *argv);
- return 1;
- }
- f = fopen(argv[1], "rb");
- if( f==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
- return 1;
- }
- ofst = atoi(argv[2]);
- n = atoi(argv[3]);
- zBuf = malloc( n );
- if( zBuf==0 ){
- fprintf(stderr, "out of memory\n");
- return 1;
- }
- fseek(f, ofst, SEEK_SET);
- got = fread(zBuf, 1, n, f);
- fclose(f);
- if( got<n ){
- fprintf(stderr, "got only %d of %d bytes\n", got, n);
- return 1;
- }else{
- fwrite(zBuf, 1, n, stdout);
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/fast_vacuum.c b/lib/libsqlite3/tool/fast_vacuum.c
deleted file mode 100644
index 6a50dcc6805..00000000000
--- a/lib/libsqlite3/tool/fast_vacuum.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-** 2013-10-01
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This program implements a high-speed version of the VACUUM command.
-** It repacks an SQLite database to remove as much unused space as
-** possible and to relocate content sequentially in the file.
-**
-** This program runs faster and uses less temporary disk space than the
-** built-in VACUUM command. On the other hand, this program has a number
-** of important restrictions relative to the built-in VACUUM command.
-**
-** (1) The caller must ensure that no other processes are accessing the
-** database file while the vacuum is taking place. The usual SQLite
-** file locking is insufficient for this. The caller must use
-** external means to make sure only this one routine is reading and
-** writing the database.
-**
-** (2) Database reconfiguration such as page size or auto_vacuum changes
-** are not supported by this utility.
-**
-** (3) The database file might be renamed if a power loss or crash
-** occurs at just the wrong moment. Recovery must be prepared to
-** to deal with the possibly changed filename.
-**
-** This program is intended as a *Demonstration Only*. The intent of this
-** program is to provide example code that application developers can use
-** when creating similar functionality in their applications.
-**
-** To compile this program:
-**
-** cc fast_vacuum.c sqlite3.c
-**
-** Add whatever linker options are required. (Example: "-ldl -lpthread").
-** Then to run the program:
-**
-** ./a.out file-to-vacuum
-**
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
-** Finalize a prepared statement. If an error has occurred, print the
-** error message and exit.
-*/
-static void vacuumFinalize(sqlite3_stmt *pStmt){
- sqlite3 *db = sqlite3_db_handle(pStmt);
- int rc = sqlite3_finalize(pStmt);
- if( rc ){
- fprintf(stderr, "finalize error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
-}
-
-/*
-** Execute zSql on database db. The SQL text is printed to standard
-** output. If an error occurs, print an error message and exit the
-** process.
-*/
-static void execSql(sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- if( !zSql ){
- fprintf(stderr, "out of memory!\n");
- exit(1);
- }
- printf("%s;\n", zSql);
- if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
- sqlite3_step(pStmt);
- vacuumFinalize(pStmt);
-}
-
-/*
-** Execute zSql on database db. The zSql statement returns exactly
-** one column. Execute this return value as SQL on the same database.
-**
-** The zSql statement is printed on standard output prior to being
-** run. If any errors occur, an error is printed and the process
-** exits.
-*/
-static void execExecSql(sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- int rc;
-
- printf("%s;\n", zSql);
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- execSql(db, (char*)sqlite3_column_text(pStmt, 0));
- }
- vacuumFinalize(pStmt);
-}
-
-
-int main(int argc, char **argv){
- sqlite3 *db; /* Connection to the database file */
- int rc; /* Return code from SQLite interface calls */
- sqlite3_uint64 r; /* A random number */
- const char *zDbToVacuum; /* Database to be vacuumed */
- char *zBackupDb; /* Backup copy of the original database */
- char *zTempDb; /* Temporary database */
- char *zSql; /* An SQL statement */
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s DATABASE\n", argv[0]);
- return 1;
- }
-
- /* Identify the database file to be vacuumed and open it.
- */
- zDbToVacuum = argv[1];
- printf("-- open database file \"%s\"\n", zDbToVacuum);
- rc = sqlite3_open(zDbToVacuum, &db);
- if( rc ){
- fprintf(stderr, "%s: %s\n", zDbToVacuum, sqlite3_errstr(rc));
- return 1;
- }
-
- /* Create names for two other files. zTempDb will be a new database
- ** into which we construct a vacuumed copy of zDbToVacuum. zBackupDb
- ** will be a new name for zDbToVacuum after it is vacuumed.
- */
- sqlite3_randomness(sizeof(r), &r);
- zTempDb = sqlite3_mprintf("%s-vacuum-%016llx", zDbToVacuum, r);
- zBackupDb = sqlite3_mprintf("%s-backup-%016llx", zDbToVacuum, r);
-
- /* Attach the zTempDb database to the database connection.
- */
- zSql = sqlite3_mprintf("ATTACH '%q' AS vacuum_db;", zTempDb);
- execSql(db, zSql);
- sqlite3_free(zSql);
-
- /* TODO:
- ** Set the page_size and auto_vacuum mode for zTempDb here, if desired.
- */
-
- /* The vacuum will occur inside of a transaction. Set writable_schema
- ** to ON so that we can directly update the sqlite_master table in the
- ** zTempDb database.
- */
- execSql(db, "PRAGMA writable_schema=ON");
- execSql(db, "BEGIN");
-
-
- /* Query the schema of the main database. Create a mirror schema
- ** in the temporary database.
- */
- execExecSql(db,
- "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
- " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
- " AND rootpage>0"
- );
- execExecSql(db,
- "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
- " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %'"
- );
- execExecSql(db,
- "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
- " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
- );
-
- /* 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.
- */
- execExecSql(db,
- "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
- "|| ' SELECT * FROM main.' || quote(name) "
- "FROM main.sqlite_master "
- "WHERE type = 'table' AND name!='sqlite_sequence' "
- " AND rootpage>0"
- );
-
- /* Copy over the sequence table
- */
- execExecSql(db,
- "SELECT 'DELETE FROM vacuum_db.' || quote(name) "
- "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence'"
- );
- execExecSql(db,
- "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
- "|| ' SELECT * FROM main.' || quote(name) "
- "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence'"
- );
-
- /* 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.
- */
- execSql(db,
- "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)"
- );
-
- /* Commit the transaction and close the database
- */
- execSql(db, "COMMIT");
- printf("-- close database\n");
- sqlite3_close(db);
-
-
- /* At this point, zDbToVacuum is unchanged. zTempDb contains a
- ** vacuumed copy of zDbToVacuum. Rearrange filenames so that
- ** zTempDb becomes thenew zDbToVacuum.
- */
- printf("-- rename \"%s\" to \"%s\"\n", zDbToVacuum, zBackupDb);
- rename(zDbToVacuum, zBackupDb);
- printf("-- rename \"%s\" to \"%s\"\n", zTempDb, zDbToVacuum);
- rename(zTempDb, zDbToVacuum);
-
- /* Release allocated memory */
- sqlite3_free(zTempDb);
- sqlite3_free(zBackupDb);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/fragck.tcl b/lib/libsqlite3/tool/fragck.tcl
deleted file mode 100644
index 35e76f482b6..00000000000
--- a/lib/libsqlite3/tool/fragck.tcl
+++ /dev/null
@@ -1,149 +0,0 @@
-# Run this TCL script using "testfixture" to get a report that shows
-# the sequence of database pages used by a particular table or index.
-# This information is used for fragmentation analysis.
-#
-
-# Get the name of the database to analyze
-#
-
-if {[llength $argv]!=2} {
- puts stderr "Usage: $argv0 database-name table-or-index-name"
- exit 1
-}
-set file_to_analyze [lindex $argv 0]
-if {![file exists $file_to_analyze]} {
- puts stderr "No such file: $file_to_analyze"
- exit 1
-}
-if {![file readable $file_to_analyze]} {
- puts stderr "File is not readable: $file_to_analyze"
- exit 1
-}
-if {[file size $file_to_analyze]<512} {
- puts stderr "Empty or malformed database: $file_to_analyze"
- exit 1
-}
-set objname [lindex $argv 1]
-
-# Open the database
-#
-sqlite3 db [lindex $argv 0]
-set DB [btree_open [lindex $argv 0] 1000 0]
-
-# This proc is a wrapper around the btree_cursor_info command. The
-# second argument is an open btree cursor returned by [btree_cursor].
-# The first argument is the name of an array variable that exists in
-# the scope of the caller. If the third argument is non-zero, then
-# info is returned for the page that lies $up entries upwards in the
-# tree-structure. (i.e. $up==1 returns the parent page, $up==2 the
-# grandparent etc.)
-#
-# The following entries in that array are filled in with information retrieved
-# using [btree_cursor_info]:
-#
-# $arrayvar(page_no) = The page number
-# $arrayvar(entry_no) = The entry number
-# $arrayvar(page_entries) = Total number of entries on this page
-# $arrayvar(cell_size) = Cell size (local payload + header)
-# $arrayvar(page_freebytes) = Number of free bytes on this page
-# $arrayvar(page_freeblocks) = Number of free blocks on the page
-# $arrayvar(payload_bytes) = Total payload size (local + overflow)
-# $arrayvar(header_bytes) = Header size in bytes
-# $arrayvar(local_payload_bytes) = Local payload size
-# $arrayvar(parent) = Parent page number
-#
-proc cursor_info {arrayvar csr {up 0}} {
- upvar $arrayvar a
- foreach [list a(page_no) \
- a(entry_no) \
- a(page_entries) \
- a(cell_size) \
- a(page_freebytes) \
- a(page_freeblocks) \
- a(payload_bytes) \
- a(header_bytes) \
- a(local_payload_bytes) \
- a(parent) \
- a(first_ovfl) ] [btree_cursor_info $csr $up] break
-}
-
-# Determine the page-size of the database. This global variable is used
-# throughout the script.
-#
-set pageSize [db eval {PRAGMA page_size}]
-
-# Find the root page of table or index to be analyzed. Also find out
-# if the object is a table or an index.
-#
-if {$objname=="sqlite_master"} {
- set rootpage 1
- set type table
-} else {
- db eval {
- SELECT rootpage, type FROM sqlite_master
- WHERE name=$objname
- } break
- if {![info exists rootpage]} {
- puts stderr "no such table or index: $objname"
- exit 1
- }
- if {$type!="table" && $type!="index"} {
- puts stderr "$objname is something other than a table or index"
- exit 1
- }
- if {![string is integer -strict $rootpage]} {
- puts stderr "invalid root page for $objname: $rootpage"
- exit 1
- }
-}
-
-# The cursor $csr is pointing to an entry. Print out information
-# about the page that $up levels above that page that contains
-# the entry. If $up==0 use the page that contains the entry.
-#
-# If information about the page has been printed already, then
-# this is a no-op.
-#
-proc page_info {csr up} {
- global seen
- cursor_info ci $csr $up
- set pg $ci(page_no)
- if {[info exists seen($pg)]} return
- set seen($pg) 1
-
- # Do parent pages first
- #
- if {$ci(parent)} {
- page_info $csr [expr {$up+1}]
- }
-
- # Find the depth of this page
- #
- set depth 1
- set i $up
- while {$ci(parent)} {
- incr i
- incr depth
- cursor_info ci $csr $i
- }
-
- # print the results
- #
- puts [format {LEVEL %d: %6d} $depth $pg]
-}
-
-
-
-
-# Loop through the object and print out page numbers
-#
-set csr [btree_cursor $DB $rootpage 0]
-for {btree_first $csr} {![btree_eof $csr]} {btree_next $csr} {
- page_info $csr 0
- set i 1
- foreach pg [btree_ovfl_info $DB $csr] {
- puts [format {OVFL %3d: %6d} $i $pg]
- incr i
- }
-}
-exit 0
diff --git a/lib/libsqlite3/tool/fuzzershell.c b/lib/libsqlite3/tool/fuzzershell.c
deleted file mode 100644
index 6754a071e37..00000000000
--- a/lib/libsqlite3/tool/fuzzershell.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
-** 2015-04-17
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This is a utility program designed to aid running the SQLite library
-** against an external fuzzer, such as American Fuzzy Lop (AFL)
-** (http://lcamtuf.coredump.cx/afl/). Basically, this program reads
-** SQL text from standard input and passes it through to SQLite for evaluation,
-** just like the "sqlite3" command-line shell. Differences from the
-** command-line shell:
-**
-** (1) The complex "dot-command" extensions are omitted. This
-** prevents the fuzzer from discovering that it can run things
-** like ".shell rm -rf ~"
-**
-** (2) The database is opened with the SQLITE_OPEN_MEMORY flag so that
-** no disk I/O from the database is permitted. The ATTACH command
-** with a filename still uses an in-memory database.
-**
-** (3) The main in-memory database can be initialized from a template
-** disk database so that the fuzzer starts with a database containing
-** content.
-**
-** (4) The eval() SQL function is added, allowing the fuzzer to do
-** interesting recursive operations.
-**
-** (5) An error is raised if there is a memory leak.
-**
-** The input text can be divided into separate test cases using comments
-** of the form:
-**
-** |****<...>****|
-**
-** where the "..." is arbitrary text. (Except the "|" should really be "/".
-** "|" is used here to avoid compiler errors about nested comments.)
-** A separate in-memory SQLite database is created to run each test case.
-** This feature allows the "queue" of AFL to be captured into a single big
-** file using a command like this:
-**
-** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
-**
-** (Once again, change the "|" to "/") Then all elements of the AFL queue
-** can be run in a single go (for regression testing, for example) by typing:
-**
-** fuzzershell -f ~/all-queue.txt
-**
-** After running each chunk of SQL, the database connection is closed. The
-** program aborts if the close fails or if there is any unfreed memory after
-** the close.
-**
-** New test cases can be appended to all-queue.txt at any time. If redundant
-** test cases are added, they can be eliminated by running:
-**
-** fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include "sqlite3.h"
-
-/*
-** All global variables are gathered into the "g" singleton.
-*/
-struct GlobalVars {
- const char *zArgv0; /* Name of program */
- sqlite3_mem_methods sOrigMem; /* Original memory methods */
- sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */
- int iOomCntdown; /* Memory fails on 1 to 0 transition */
- int nOomFault; /* Increments for each OOM fault */
- int bOomOnce; /* Fail just once if true */
- int bOomEnable; /* True to enable OOM simulation */
- int nOomBrkpt; /* Number of calls to oomFault() */
- char zTestName[100]; /* Name of current test */
-} g;
-
-/*
-** Maximum number of iterations for an OOM test
-*/
-#ifndef OOM_MAX
-# define OOM_MAX 625
-#endif
-
-/*
-** This routine is called when a simulated OOM occurs. It exists as a
-** convenient place to set a debugger breakpoint.
-*/
-static void oomFault(void){
- g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */
-}
-
-
-/* Versions of malloc() and realloc() that simulate OOM conditions */
-static void *oomMalloc(int nByte){
- if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
- g.iOomCntdown--;
- if( g.iOomCntdown==0 ){
- if( g.nOomFault==0 ) oomFault();
- g.nOomFault++;
- if( !g.bOomOnce ) g.iOomCntdown = 1;
- return 0;
- }
- }
- return g.sOrigMem.xMalloc(nByte);
-}
-static void *oomRealloc(void *pOld, int nByte){
- if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
- g.iOomCntdown--;
- if( g.iOomCntdown==0 ){
- if( g.nOomFault==0 ) oomFault();
- g.nOomFault++;
- if( !g.bOomOnce ) g.iOomCntdown = 1;
- return 0;
- }
- }
- return g.sOrigMem.xRealloc(pOld, nByte);
-}
-
-/*
-** Print an error message and abort in such a way to indicate to the
-** fuzzer that this counts as a crash.
-*/
-static void abendError(const char *zFormat, ...){
- va_list ap;
- if( g.zTestName[0] ){
- fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
- }else{
- fprintf(stderr, "%s: ", g.zArgv0);
- }
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- abort();
-}
-/*
-** Print an error message and quit, but not in a way that would look
-** like a crash.
-*/
-static void fatalError(const char *zFormat, ...){
- va_list ap;
- if( g.zTestName[0] ){
- fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
- }else{
- fprintf(stderr, "%s: ", g.zArgv0);
- }
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-/*
-** Evaluate some SQL. Abort if unable.
-*/
-static void sqlexec(sqlite3 *db, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- char *zErrMsg = 0;
- int rc;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
- if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
- sqlite3_free(zSql);
-}
-
-/*
-** This callback is invoked by sqlite3_log().
-*/
-static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
- printf("LOG: (%d) %s\n", iErrCode, zMsg);
- fflush(stdout);
-}
-static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){
- return;
-}
-
-/*
-** This callback is invoked by sqlite3_exec() to return query results.
-*/
-static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
- int i;
- static unsigned cnt = 0;
- printf("ROW #%u:\n", ++cnt);
- for(i=0; i<argc; i++){
- printf(" %s=", colv[i]);
- if( argv[i] ){
- printf("[%s]\n", argv[i]);
- }else{
- printf("NULL\n");
- }
- }
- fflush(stdout);
- return 0;
-}
-static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
- return 0;
-}
-
-#ifndef SQLITE_OMIT_TRACE
-/*
-** This callback is invoked by sqlite3_trace() as each SQL statement
-** starts.
-*/
-static void traceCallback(void *NotUsed, const char *zMsg){
- printf("TRACE: %s\n", zMsg);
- fflush(stdout);
-}
-static void traceNoop(void *NotUsed, const char *zMsg){
- return;
-}
-#endif
-
-/***************************************************************************
-** eval() implementation copied from ../ext/misc/eval.c
-*/
-/*
-** Structure used to accumulate the output
-*/
-struct EvalResult {
- char *z; /* Accumulated output */
- const char *zSep; /* Separator */
- int szSep; /* Size of the separator string */
- sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
- sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
-};
-
-/*
-** Callback from sqlite_exec() for the eval() function.
-*/
-static int callback(void *pCtx, int argc, char **argv, char **colnames){
- struct EvalResult *p = (struct EvalResult*)pCtx;
- int i;
- for(i=0; i<argc; i++){
- const char *z = argv[i] ? argv[i] : "";
- size_t sz = strlen(z);
- if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
- /* Using sqlite3_realloc64() would be better, but it is a recent
- ** addition and will cause a segfault if loaded by an older version
- ** of SQLite. */
- zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
- if( zNew==0 ){
- sqlite3_free(p->z);
- memset(p, 0, sizeof(*p));
- return 1;
- }
- p->z = zNew;
- }
- if( p->nUsed>0 ){
- memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
- p->nUsed += p->szSep;
- }
- memcpy(&p->z[p->nUsed], z, sz);
- p->nUsed += sz;
- }
- return 0;
-}
-
-/*
-** Implementation of the eval(X) and eval(X,Y) SQL functions.
-**
-** Evaluate the SQL text in X. Return the results, using string
-** Y as the separator. If Y is omitted, use a single space character.
-*/
-static void sqlEvalFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zSql;
- sqlite3 *db;
- char *zErr = 0;
- int rc;
- struct EvalResult x;
-
- memset(&x, 0, sizeof(x));
- x.zSep = " ";
- zSql = (const char*)sqlite3_value_text(argv[0]);
- if( zSql==0 ) return;
- if( argc>1 ){
- x.zSep = (const char*)sqlite3_value_text(argv[1]);
- if( x.zSep==0 ) return;
- }
- x.szSep = (int)strlen(x.zSep);
- db = sqlite3_context_db_handle(context);
- rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
- if( rc!=SQLITE_OK ){
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- }else if( x.zSep==0 ){
- sqlite3_result_error_nomem(context);
- sqlite3_free(x.z);
- }else{
- sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
- }
-}
-/* End of the eval() implementation
-******************************************************************************/
-
-/*
-** Print sketchy documentation for this utility program
-*/
-static void showHelp(void){
- printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
- printf(
-"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
-"and then evaluate each block of SQL contained therein.\n"
-"Options:\n"
-" --autovacuum Enable AUTOVACUUM mode\n"
-" --database FILE Use database FILE instead of an in-memory database\n"
-" --disable-lookaside Turn off lookaside memory\n"
-" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
-" --help Show this help text\n"
-" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
-" --oom Run each test multiple times in a simulated OOM loop\n"
-" --pagesize N Set the page size to N\n"
-" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
-" -q Reduced output\n"
-" --quiet Reduced output\n"
-" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
-" --unique-cases FILE Write all unique test cases to FILE\n"
-" --utf16be Set text encoding to UTF-16BE\n"
-" --utf16le Set text encoding to UTF-16LE\n"
-" -v Increased output\n"
-" --verbose Increased output\n"
- );
-}
-
-/*
-** Return the value of a hexadecimal digit. Return -1 if the input
-** is not a hex digit.
-*/
-static int hexDigitValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-/*
-** Interpret zArg as an integer value, possibly with suffixes.
-*/
-static int integerValue(const char *zArg){
- sqlite3_int64 v = 0;
- static const struct { char *zSuffix; int iMult; } aMult[] = {
- { "KiB", 1024 },
- { "MiB", 1024*1024 },
- { "GiB", 1024*1024*1024 },
- { "KB", 1000 },
- { "MB", 1000000 },
- { "GB", 1000000000 },
- { "K", 1000 },
- { "M", 1000000 },
- { "G", 1000000000 },
- };
- int i;
- int isNeg = 0;
- if( zArg[0]=='-' ){
- isNeg = 1;
- zArg++;
- }else if( zArg[0]=='+' ){
- zArg++;
- }
- if( zArg[0]=='0' && zArg[1]=='x' ){
- int x;
- zArg += 2;
- while( (x = hexDigitValue(zArg[0]))>=0 ){
- v = (v<<4) + x;
- zArg++;
- }
- }else{
- while( isdigit(zArg[0]) ){
- v = v*10 + zArg[0] - '0';
- zArg++;
- }
- }
- for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
- if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
- v *= aMult[i].iMult;
- break;
- }
- }
- if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
- return (int)(isNeg? -v : v);
-}
-
-/* Return the current wall-clock time */
-static sqlite3_int64 timeOfDay(void){
- static sqlite3_vfs *clockVfs = 0;
- sqlite3_int64 t;
- if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
- if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
- clockVfs->xCurrentTimeInt64(clockVfs, &t);
- }else{
- double r;
- clockVfs->xCurrentTime(clockVfs, &r);
- t = (sqlite3_int64)(r*86400000.0);
- }
- return t;
-}
-
-int main(int argc, char **argv){
- char *zIn = 0; /* Input text */
- int nAlloc = 0; /* Number of bytes allocated for zIn[] */
- int nIn = 0; /* Number of bytes of zIn[] used */
- size_t got; /* Bytes read from input */
- int rc = SQLITE_OK; /* Result codes from API functions */
- int i; /* Loop counter */
- int iNext; /* Next block of SQL */
- sqlite3 *db; /* Open database */
- char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
- const char *zEncoding = 0; /* --utf16be or --utf16le */
- int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
- int nLook = 0, szLook = 0; /* --lookaside configuration */
- int nPCache = 0, szPCache = 0;/* --pcache configuration */
- int nScratch = 0, szScratch=0;/* --scratch configuration */
- int pageSize = 0; /* Desired page size. 0 means default */
- void *pHeap = 0; /* Allocated heap space */
- void *pLook = 0; /* Allocated lookaside space */
- void *pPCache = 0; /* Allocated storage for pcache */
- void *pScratch = 0; /* Allocated storage for scratch */
- int doAutovac = 0; /* True for --autovacuum */
- char *zSql; /* SQL to run */
- char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
- int verboseFlag = 0; /* --verbose or -v flag */
- int quietFlag = 0; /* --quiet or -q flag */
- int nTest = 0; /* Number of test cases run */
- int multiTest = 0; /* True if there will be multiple test cases */
- int lastPct = -1; /* Previous percentage done output */
- sqlite3 *dataDb = 0; /* Database holding compacted input data */
- sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */
- const char *zDataOut = 0; /* Write compacted data to this output file */
- int nHeader = 0; /* Bytes of header comment text on input file */
- int oomFlag = 0; /* --oom */
- int oomCnt = 0; /* Counter for the OOM loop */
- char zErrBuf[200]; /* Space for the error message */
- const char *zFailCode; /* Value of the TEST_FAILURE environment var */
- const char *zPrompt; /* Initial prompt when large-file fuzzing */
- int nInFile = 0; /* Number of input files to read */
- char **azInFile = 0; /* Array of input file names */
- int jj; /* Loop counter for azInFile[] */
- sqlite3_int64 iBegin; /* Start time for the whole program */
- sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */
- const char *zDbName = 0; /* Name of an on-disk database file to open */
-
- iBegin = timeOfDay();
- sqlite3_shutdown();
- zFailCode = getenv("TEST_FAILURE");
- g.zArgv0 = argv[0];
- zPrompt = "<stdin>";
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"autovacuum")==0 ){
- doAutovac = 1;
- }else
- if( strcmp(z,"database")==0 ){
- if( i>=argc-1 ) abendError("missing argument on %s\n", argv[i]);
- zDbName = argv[i+1];
- i += 1;
- }else
- if( strcmp(z,"disable-lookaside")==0 ){
- nLook = 1;
- szLook = 0;
- }else
- if( strcmp(z, "f")==0 && i+1<argc ){
- i++;
- goto addNewInFile;
- }else
- if( strcmp(z,"heap")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
- nHeap = integerValue(argv[i+1]);
- mnHeap = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"help")==0 ){
- showHelp();
- return 0;
- }else
- if( strcmp(z,"lookaside")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nLook = integerValue(argv[i+1]);
- szLook = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"oom")==0 ){
- oomFlag = 1;
- }else
- if( strcmp(z,"pagesize")==0 ){
- if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
- pageSize = integerValue(argv[++i]);
- }else
- if( strcmp(z,"pcache")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nPCache = integerValue(argv[i+1]);
- szPCache = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
- quietFlag = 1;
- verboseFlag = 0;
- }else
- if( strcmp(z,"scratch")==0 ){
- if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
- nScratch = integerValue(argv[i+1]);
- szScratch = integerValue(argv[i+2]);
- i += 2;
- }else
- if( strcmp(z, "unique-cases")==0 ){
- if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]);
- if( zDataOut ) abendError("only one --minimize allowed");
- zDataOut = argv[++i];
- }else
- if( strcmp(z,"utf16le")==0 ){
- zEncoding = "utf16le";
- }else
- if( strcmp(z,"utf16be")==0 ){
- zEncoding = "utf16be";
- }else
- if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
- quietFlag = 0;
- verboseFlag = 1;
- }else
- {
- abendError("unknown option: %s", argv[i]);
- }
- }else{
- addNewInFile:
- nInFile++;
- azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile);
- if( azInFile==0 ) abendError("out of memory");
- azInFile[nInFile-1] = argv[i];
- }
- }
-
- /* Do global SQLite initialization */
- sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
- if( nHeap>0 ){
- pHeap = malloc( nHeap );
- if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
- rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
- if( rc ) abendError("heap configuration failed: %d\n", rc);
- }
- if( oomFlag ){
- sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem);
- g.sOomMem = g.sOrigMem;
- g.sOomMem.xMalloc = oomMalloc;
- g.sOomMem.xRealloc = oomRealloc;
- sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem);
- }
- if( nLook>0 ){
- sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
- if( szLook>0 ){
- pLook = malloc( nLook*szLook );
- if( pLook==0 ) fatalError("out of memory");
- }
- }
- if( nScratch>0 && szScratch>0 ){
- pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
- if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
- nScratch*(sqlite3_int64)szScratch);
- rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
- if( rc ) abendError("scratch configuration failed: %d\n", rc);
- }
- if( nPCache>0 && szPCache>0 ){
- pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
- if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
- nPCache*(sqlite3_int64)szPCache);
- rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
- if( rc ) abendError("pcache configuration failed: %d", rc);
- }
-
- /* If the --unique-cases option was supplied, open the database that will
- ** be used to gather unique test cases.
- */
- if( zDataOut ){
- rc = sqlite3_open(":memory:", &dataDb);
- if( rc ) abendError("cannot open :memory: database");
- rc = sqlite3_exec(dataDb,
- "CREATE TABLE testcase(sql BLOB PRIMARY KEY, tm) WITHOUT ROWID;",0,0,0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- rc = sqlite3_prepare_v2(dataDb,
- "INSERT OR IGNORE INTO testcase(sql,tm)VALUES(?1,?2)",
- -1, &pStmt, 0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- }
-
- /* Initialize the input buffer used to hold SQL text */
- if( nInFile==0 ) nInFile = 1;
- nAlloc = 1000;
- zIn = malloc(nAlloc);
- if( zIn==0 ) fatalError("out of memory");
-
- /* Loop over all input files */
- for(jj=0; jj<nInFile; jj++){
-
- /* Read the complete content of the next input file into zIn[] */
- FILE *in;
- if( azInFile ){
- int j, k;
- in = fopen(azInFile[jj],"rb");
- if( in==0 ){
- abendError("cannot open %s for reading", azInFile[jj]);
- }
- zPrompt = azInFile[jj];
- for(j=k=0; zPrompt[j]; j++) if( zPrompt[j]=='/' ) k = j+1;
- zPrompt += k;
- }else{
- in = stdin;
- zPrompt = "<stdin>";
- }
- while( !feof(in) ){
- got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
- nIn += (int)got;
- zIn[nIn] = 0;
- if( got==0 ) break;
- if( nAlloc - nIn - 1 < 100 ){
- nAlloc += nAlloc+1000;
- zIn = realloc(zIn, nAlloc);
- if( zIn==0 ) fatalError("out of memory");
- }
- }
- if( in!=stdin ) fclose(in);
- lastPct = -1;
-
- /* Skip initial lines of the input file that begin with "#" */
- for(i=0; i<nIn; i=iNext+1){
- if( zIn[i]!='#' ) break;
- for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
- }
- nHeader = i;
-
- /* Process all test cases contained within the input file.
- */
- for(; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
- char cSaved;
- if( strncmp(&zIn[i], "/****<",6)==0 ){
- char *z = strstr(&zIn[i], ">****/");
- if( z ){
- z += 6;
- sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s",
- (int)(z-&zIn[i]) - 12, &zIn[i+6]);
- if( verboseFlag ){
- printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
- fflush(stdout);
- }
- i += (int)(z-&zIn[i]);
- multiTest = 1;
- }
- }
- for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
- cSaved = zIn[iNext];
- zIn[iNext] = 0;
-
-
- /* Print out the SQL of the next test case is --verbose is enabled
- */
- zSql = &zIn[i];
- if( verboseFlag ){
- printf("INPUT (offset: %d, size: %d): [%s]\n",
- i, (int)strlen(&zIn[i]), &zIn[i]);
- }else if( multiTest && !quietFlag ){
- if( oomFlag ){
- printf("%s\n", g.zTestName);
- }else{
- int pct = (10*iNext)/nIn;
- if( pct!=lastPct ){
- if( lastPct<0 ) printf("%s:", zPrompt);
- printf(" %d%%", pct*10);
- lastPct = pct;
- }
- }
- }else if( nInFile>1 ){
- printf("%s\n", zPrompt);
- }
- fflush(stdout);
-
- /* Run the next test case. Run it multiple times in --oom mode
- */
- if( oomFlag ){
- oomCnt = g.iOomCntdown = 1;
- g.nOomFault = 0;
- g.bOomOnce = 1;
- if( verboseFlag ){
- printf("Once.%d\n", oomCnt);
- fflush(stdout);
- }
- }else{
- oomCnt = 0;
- }
- do{
- if( zDbName ){
- rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0);
- if( rc!=SQLITE_OK ){
- abendError("Cannot open database file %s", zDbName);
- }
- }else{
- rc = sqlite3_open_v2(
- "main.db", &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
- 0);
- if( rc!=SQLITE_OK ){
- abendError("Unable to open the in-memory database");
- }
- }
- if( pLook ){
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
- if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
- }
- #ifndef SQLITE_OMIT_TRACE
- sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
- #endif
- sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
- sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
- sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
- if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
- if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
- if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
- iStart = timeOfDay();
- g.bOomEnable = 1;
- if( verboseFlag ){
- zErrMsg = 0;
- rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
- if( zErrMsg ){
- sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
- zErrMsg = 0;
- }
- }else {
- rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
- }
- g.bOomEnable = 0;
- iEnd = timeOfDay();
- rc = sqlite3_close(db);
- if( rc ){
- abendError("sqlite3_close() failed with rc=%d", rc);
- }
- if( !zDataOut && sqlite3_memory_used()>0 ){
- abendError("memory in use after close: %lld bytes",sqlite3_memory_used());
- }
- if( oomFlag ){
- /* Limit the number of iterations of the OOM loop to OOM_MAX. If the
- ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
- ** second pass (continuous failure after first) completely. */
- if( g.nOomFault==0 || oomCnt>OOM_MAX ){
- if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
- oomCnt = g.iOomCntdown = 1;
- g.bOomOnce = 0;
- }else{
- oomCnt = 0;
- }
- }else{
- g.iOomCntdown = ++oomCnt;
- g.nOomFault = 0;
- }
- if( oomCnt ){
- if( verboseFlag ){
- printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
- fflush(stdout);
- }
- nTest++;
- }
- }
- }while( oomCnt>0 );
-
- /* Store unique test cases in the in the dataDb database if the
- ** --unique-cases flag is present
- */
- if( zDataOut ){
- sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
- sqlite3_bind_int64(pStmt, 2, iEnd - iStart);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
- sqlite3_reset(pStmt);
- }
-
- /* Free the SQL from the current test case
- */
- if( zToFree ){
- sqlite3_free(zToFree);
- zToFree = 0;
- }
- zIn[iNext] = cSaved;
-
- /* Show test-case results in --verbose mode
- */
- if( verboseFlag ){
- printf("RESULT-CODE: %d\n", rc);
- if( zErrMsg ){
- printf("ERROR-MSG: [%s]\n", zErrBuf);
- }
- fflush(stdout);
- }
-
- /* Simulate an error if the TEST_FAILURE environment variable is "5".
- ** This is used to verify that automated test script really do spot
- ** errors that occur in this test program.
- */
- if( zFailCode ){
- if( zFailCode[0]=='5' && zFailCode[1]==0 ){
- abendError("simulated failure");
- }else if( zFailCode[0]!=0 ){
- /* If TEST_FAILURE is something other than 5, just exit the test
- ** early */
- printf("\nExit early due to TEST_FAILURE being set");
- break;
- }
- }
- }
- if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
- }
-
- /* Report total number of tests run
- */
- if( nTest>1 && !quietFlag ){
- sqlite3_int64 iElapse = timeOfDay() - iBegin;
- printf("%s: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
- g.zArgv0, nTest, (int)(iElapse/1000), (int)(iElapse%1000),
- sqlite3_libversion(), sqlite3_sourceid());
- }
-
- /* Write the unique test cases if the --unique-cases flag was used
- */
- if( zDataOut ){
- int n = 0;
- FILE *out = fopen(zDataOut, "wb");
- if( out==0 ) abendError("cannot open %s for writing", zDataOut);
- if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
- sqlite3_finalize(pStmt);
- rc = sqlite3_prepare_v2(dataDb, "SELECT sql, tm FROM testcase ORDER BY tm, sql",
- -1, &pStmt, 0);
- if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- fprintf(out,"/****<%d:%dms>****/", ++n, sqlite3_column_int(pStmt,1));
- fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
- }
- fclose(out);
- sqlite3_finalize(pStmt);
- sqlite3_close(dataDb);
- }
-
- /* Clean up and exit.
- */
- free(azInFile);
- free(zIn);
- free(pHeap);
- free(pLook);
- free(pScratch);
- free(pPCache);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/genfkey.README b/lib/libsqlite3/tool/genfkey.README
deleted file mode 100644
index 57cdff87f8b..00000000000
--- a/lib/libsqlite3/tool/genfkey.README
+++ /dev/null
@@ -1,137 +0,0 @@
-
-OVERVIEW
-
- The SQLite library is capable of parsing SQL foreign key constraints
- supplied as part of CREATE TABLE statements, but it does not actually
- implement them. However, most of the features of foreign keys may be
- implemented using SQL triggers, which SQLite does support. This text
- file describes a feature of the SQLite shell tool (sqlite3) that
- extracts foreign key definitions from an existing SQLite database and
- creates the set of CREATE TRIGGER statements required to implement
- the foreign key constraints.
-
-CAPABILITIES
-
- An SQL foreign key is a constraint that requires that each row in
- the "child" table corresponds to a row in the "parent" table. For
- example, the following schema:
-
- CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b));
-
- implies that for each row in table "child", there must be a row in
- "parent" for which the expression (child.d==parent.a AND child.e==parent.b)
- is true. The columns in the parent table are required to be either the
- primary key columns or subject to a UNIQUE constraint. There is no such
- requirement for the columns of the child table.
-
- At this time, all foreign keys are implemented as if they were
- "MATCH NONE", even if the declaration specified "MATCH PARTIAL" or
- "MATCH FULL". "MATCH NONE" means that if any of the key columns in
- the child table are NULL, then there is no requirement for a corresponding
- row in the parent table. So, taking this into account, the expression that
- must be true for every row of the child table in the above example is
- actually:
-
- (child.d IS NULL) OR
- (child.e IS NULL) OR
- (child.d==parent.a AND child.e==parent.b)
-
- Attempting to insert or update a row in the child table so that the
- affected row violates this constraint results in an exception being
- thrown.
-
- The effect of attempting to delete or update a row in the parent table
- so that the constraint becomes untrue for one or more rows in the child
- table depends on the "ON DELETE" or "ON UPDATE" actions specified as
- part of the foreign key definition, respectively. Three different actions
- are supported: "RESTRICT" (the default), "CASCADE" and "SET NULL". SQLite
- will also parse the "SET DEFAULT" action, but this is not implemented
- and "RESTRICT" is used instead.
-
- RESTRICT: Attempting to update or delete a row in the parent table so
- that the constraint becomes untrue for one or more rows in
- the child table is not allowed. An exception is thrown.
-
- CASCADE: Instead of throwing an exception, all corresponding child table
- rows are either deleted (if the parent row is being deleted)
- or updated to match the new parent key values (if the parent
- row is being updated).
-
- SET NULL: Instead of throwing an exception, the foreign key fields of
- all corresponding child table rows are set to NULL.
-
-LIMITATIONS
-
- Apart from those limitiations described above:
-
- * Implicit mapping to composite primary keys is not supported. If
- a parent table has a composite primary key, then any child table
- that refers to it must explicitly map each column. For example, given
- the following definition of table "parent":
-
- CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b));
-
- only the first of the following two definitions of table "child"
- is supported:
-
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b));
- CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent);
-
- An implicit reference to a composite primary key is detected as an
- error when the program is run (see below).
-
- * SQLite does not support recursive triggers, and therefore this program
- does not support recursive CASCADE or SET NULL foreign key
- relationships. If the parent and the child tables of a CASCADE or
- SET NULL foreign key are the same table, the generated triggers will
- malfunction. This is also true if the recursive foreign key constraint
- is indirect (for example if table A references table B which references
- table A with a CASCADE or SET NULL foreign key constraint).
-
- Recursive CASCADE or SET NULL foreign key relationships are *not*
- detected as errors when the program is run. Buyer beware.
-
-USAGE
-
- The functionality is accessed through an sqlite3 shell tool "dot-command":
-
- .genfkey ?--no-drop? ?--ignore-errors? ?--exec?
-
- When this command is run, it first checks the schema of the open SQLite
- database for foreign key related errors or inconsistencies. For example,
- a foreign key that refers to a parent table that does not exist, or
- a foreign key that refers to columns in a parent table that are not
- guaranteed to be unique. If such errors are found and the --ignore-errors
- option was not present, a message for each one is printed to stderr and
- no further processing takes place.
-
- If errors are found and the --ignore-errors option is passed, then
- no error messages are printed. No "CREATE TRIGGER" statements are generated
- for foriegn-key definitions that contained errors, they are silently
- ignored by subsequent processing.
-
- All triggers generated by this command have names that match the pattern
- "genfkey*". Unless the --no-drop option is specified, then the program
- also generates a "DROP TRIGGER" statement for each trigger that exists
- in the database with a name that matches this pattern. This allows the
- program to be used to upgrade a database schema for which foreign key
- triggers have already been installed (i.e. after new tables are created
- or existing tables dropped).
-
- Finally, a series of SQL trigger definitions (CREATE TRIGGER statements)
- that implement the foreign key constraints found in the database schema are
- generated.
-
- If the --exec option was passed, then all generated SQL is immediately
- executed on the database. Otherwise, the generated SQL strings are output
- in the same way as the results of SELECT queries are. Normally, this means
- they will be printed to stdout, but this can be configured using other
- dot-commands (i.e. ".output").
-
- The simplest way to activate the foriegn key definitions in a database
- is simply to open it using the shell tool and enter the command
- ".genfkey --exec":
-
- sqlite> .genfkey --exec
-
diff --git a/lib/libsqlite3/tool/genfkey.test b/lib/libsqlite3/tool/genfkey.test
deleted file mode 100644
index 3c0073e953d..00000000000
--- a/lib/libsqlite3/tool/genfkey.test
+++ /dev/null
@@ -1,354 +0,0 @@
-
-package require sqlite3
-
-proc do_test {name cmd expected} {
- puts -nonewline "$name ..."
- set res [uplevel $cmd]
- if {$res eq $expected} {
- puts Ok
- } else {
- puts Error
- puts " Got: $res"
- puts " Expected: $expected"
- exit
- }
-}
-
-proc execsql {sql} {
- uplevel [list db eval $sql]
-}
-
-proc catchsql {sql} {
- set rc [catch {uplevel [list db eval $sql]} msg]
- list $rc $msg
-}
-
-file delete -force test.db test.db.journal
-sqlite3 db test.db
-
-# The following tests - genfkey-1.* - test RESTRICT foreign keys.
-#
-do_test genfkey-1.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
- CREATE TABLE t2(e REFERENCES t1, f);
- CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
- }
-} {}
-do_test genfkey-1.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-1.3 {
- catchsql { INSERT INTO t2 VALUES(1, 2) }
-} {1 {constraint failed}}
-do_test genfkey-1.4 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t2 VALUES(1, 2);
- }
-} {}
-do_test genfkey-1.5 {
- execsql { INSERT INTO t2 VALUES(NULL, 3) }
-} {}
-do_test genfkey-1.6 {
- catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
-} {1 {constraint failed}}
-do_test genfkey-1.7 {
- execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
-} {}
-do_test genfkey-1.8 {
- execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
-} {}
-do_test genfkey-1.9 {
- catchsql { UPDATE t1 SET a = 10 }
-} {1 {constraint failed}}
-do_test genfkey-1.9a {
- catchsql { UPDATE t1 SET a = NULL }
-} {1 {datatype mismatch}}
-do_test genfkey-1.10 {
- catchsql { DELETE FROM t1 }
-} {1 {constraint failed}}
-do_test genfkey-1.11 {
- execsql { UPDATE t2 SET e = NULL }
-} {}
-do_test genfkey-1.12 {
- execsql {
- UPDATE t1 SET a = 10 ;
- DELETE FROM t1;
- DELETE FROM t2;
- }
-} {}
-
-do_test genfkey-1.13 {
- execsql {
- INSERT INTO t3 VALUES(1, NULL, NULL);
- INSERT INTO t3 VALUES(1, 2, NULL);
- INSERT INTO t3 VALUES(1, NULL, 3);
- }
-} {}
-do_test genfkey-1.14 {
- catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
-} {1 {constraint failed}}
-do_test genfkey-1.15 {
- execsql {
- INSERT INTO t1 VALUES(1, 1, 4);
- INSERT INTO t3 VALUES(3, 1, 4);
- }
-} {}
-do_test genfkey-1.16 {
- catchsql { DELETE FROM t1 }
-} {1 {constraint failed}}
-do_test genfkey-1.17 {
- catchsql { UPDATE t1 SET b = 10}
-} {1 {constraint failed}}
-do_test genfkey-1.18 {
- execsql { UPDATE t1 SET a = 10}
-} {}
-do_test genfkey-1.19 {
- catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
-} {1 {constraint failed}}
-
-do_test genfkey-1.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-# The following tests - genfkey-2.* - test CASCADE foreign keys.
-#
-do_test genfkey-2.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
- CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
- CREATE TABLE t3(g, h, i,
- FOREIGN KEY (h, i)
- REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
- );
- }
-} {}
-do_test genfkey-2.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-2.3 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(4, 'four');
- }
-} {}
-do_test genfkey-2.4 {
- execsql {
- UPDATE t1 SET a = 2 WHERE a = 1;
- SELECT * FROM t2;
- }
-} {2 one 4 four}
-do_test genfkey-2.5 {
- execsql {
- DELETE FROM t1 WHERE a = 4;
- SELECT * FROM t2;
- }
-} {2 one}
-do_test genfkey-2.6 {
- execsql {
- INSERT INTO t3 VALUES('hello', 2, 3);
- UPDATE t1 SET c = 2;
- SELECT * FROM t3;
- }
-} {hello 2 2}
-do_test genfkey-2.7 {
- execsql {
- DELETE FROM t1;
- SELECT * FROM t3;
- }
-} {}
-do_test genfkey-2.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-
-# The following tests - genfkey-3.* - test SET NULL foreign keys.
-#
-do_test genfkey-3.1 {
- execsql {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b));
- CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
- CREATE TABLE t3(g, h, i,
- FOREIGN KEY (h, i)
- REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
- );
- }
-} {}
-do_test genfkey-3.2 {
- execsql [exec ./sqlite3 test.db .genfkey]
-} {}
-do_test genfkey-3.3 {
- execsql {
- INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES(4, 5, 6);
- INSERT INTO t2 VALUES(1, 'one');
- INSERT INTO t2 VALUES(4, 'four');
- }
-} {}
-do_test genfkey-3.4 {
- execsql {
- UPDATE t1 SET a = 2 WHERE a = 1;
- SELECT * FROM t2;
- }
-} {{} one 4 four}
-do_test genfkey-3.5 {
- execsql {
- DELETE FROM t1 WHERE a = 4;
- SELECT * FROM t2;
- }
-} {{} one {} four}
-do_test genfkey-3.6 {
- execsql {
- INSERT INTO t3 VALUES('hello', 2, 3);
- UPDATE t1 SET c = 2;
- SELECT * FROM t3;
- }
-} {hello {} {}}
-do_test genfkey-2.7 {
- execsql {
- UPDATE t3 SET h = 2, i = 2;
- DELETE FROM t1;
- SELECT * FROM t3;
- }
-} {hello {} {}}
-do_test genfkey-3.X {
- execsql {
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- }
-} {}
-
-# The following tests - genfkey-4.* - test that errors in the schema
-# are detected correctly.
-#
-do_test genfkey-4.1 {
- execsql {
- CREATE TABLE t1(a REFERENCES nosuchtable, b);
- CREATE TABLE t2(a REFERENCES t1, b);
-
- CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
- CREATE TABLE t4(a, b, c, FOREIGN KEY(c, b) REFERENCES t3);
-
- CREATE TABLE t5(a REFERENCES t4(d), b, c);
- CREATE TABLE t6(a REFERENCES t4(a), b, c);
- CREATE TABLE t7(a REFERENCES t3(a), b, c);
- CREATE TABLE t8(a REFERENCES nosuchtable(a), b, c);
- }
-} {}
-
-do_test genfkey-4.X {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
- list $rc $msg
-} "1 {[string trim {
-Error in table t5: foreign key columns do not exist
-Error in table t8: foreign key columns do not exist
-Error in table t4: implicit mapping to composite primary key
-Error in table t1: implicit mapping to non-existant primary key
-Error in table t2: implicit mapping to non-existant primary key
-Error in table t6: foreign key is not unique
-Error in table t7: foreign key is not unique
-}]}"
-
-# Test that ticket #3800 has been resolved.
-#
-do_test genfkey-5.1 {
- execsql {
- DROP TABLE t1; DROP TABLE t2; DROP TABLE t3;
- DROP TABLE t4; DROP TABLE t5; DROP TABLE t6;
- DROP TABLE t7; DROP TABLE t8;
- }
-} {}
-do_test genfkey-5.2 {
- execsql {
- CREATE TABLE "t.3" (c1 PRIMARY KEY);
- CREATE TABLE t13 (c1, foreign key(c1) references "t.3"(c1));
- }
-} {}
-do_test genfkey-5.3 {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-5.4 {
- db eval $msg
-} {}
-do_test genfkey-5.5 {
- catchsql { INSERT INTO t13 VALUES(1) }
-} {1 {constraint failed}}
-do_test genfkey-5.5 {
- catchsql {
- INSERT INTO "t.3" VALUES(1);
- INSERT INTO t13 VALUES(1);
- }
-} {0 {}}
-
-# Test also column names that require quoting.
-do_test genfkey-6.1 {
- execsql {
- DROP TABLE "t.3";
- DROP TABLE t13;
- CREATE TABLE p(
- "a.1 first", "b.2 second",
- UNIQUE("a.1 first", "b.2 second")
- );
- CREATE TABLE c(
- "c.1 I", "d.2 II",
- FOREIGN KEY("c.1 I", "d.2 II")
- REFERENCES p("a.1 first", "b.2 second")
- ON UPDATE CASCADE ON DELETE CASCADE
- );
- }
-} {}
-do_test genfkey-6.2 {
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-6.3 {
- execsql $msg
- execsql {
- INSERT INTO p VALUES('A', 'B');
- INSERT INTO p VALUES('C', 'D');
- INSERT INTO c VALUES('A', 'B');
- INSERT INTO c VALUES('C', 'D');
- UPDATE p SET "a.1 first" = 'X' WHERE rowid = 1;
- DELETE FROM p WHERE rowid = 2;
- }
- execsql { SELECT * FROM c }
-} {X B}
-
-do_test genfkey-6.4 {
- execsql {
- DROP TABLE p;
- DROP TABLE c;
- CREATE TABLE parent("a.1", PRIMARY KEY("a.1"));
- CREATE TABLE child("b.2", FOREIGN KEY("b.2") REFERENCES parent("a.1"));
- }
- set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
-} {0}
-do_test genfkey-6.5 {
- execsql $msg
- execsql {
- INSERT INTO parent VALUES(1);
- INSERT INTO child VALUES(1);
- }
- catchsql { UPDATE parent SET "a.1"=0 }
-} {1 {constraint failed}}
-do_test genfkey-6.6 {
- catchsql { UPDATE child SET "b.2"=7 }
-} {1 {constraint failed}}
-do_test genfkey-6.7 {
- execsql {
- SELECT * FROM parent;
- SELECT * FROM child;
- }
-} {1 1}
-
diff --git a/lib/libsqlite3/tool/getlock.c b/lib/libsqlite3/tool/getlock.c
deleted file mode 100644
index 7eff04d7f97..00000000000
--- a/lib/libsqlite3/tool/getlock.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-** This utility program looks at an SQLite database and determines whether
-** or not it is locked, the kind of lock, and who is holding this lock.
-**
-** This only works on unix when the posix advisory locking method is used
-** (which is the default on unix) and when the PENDING_BYTE is in its
-** usual place.
-*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-static void usage(const char *argv0){
- fprintf(stderr, "Usage: %s database\n", argv0);
- exit(1);
-}
-
-/* Check for a conflicting lock. If one is found, print an this
-** on standard output using the format string given and return 1.
-** If there are no conflicting locks, return 0.
-*/
-static int isLocked(
- int h, /* File descriptor to check */
- int type, /* F_RDLCK or F_WRLCK */
- unsigned int iOfst, /* First byte of the lock */
- unsigned int iCnt, /* Number of bytes in the lock range */
- const char *zType /* Type of lock */
-){
- struct flock lk;
-
- memset(&lk, 0, sizeof(lk));
- lk.l_type = type;
- lk.l_whence = SEEK_SET;
- lk.l_start = iOfst;
- lk.l_len = iCnt;
- if( fcntl(h, F_GETLK, &lk)==(-1) ){
- fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
- exit(1);
- }
- if( lk.l_type==F_UNLCK ) return 0;
- printf("%s lock held by %d\n", zType, (int)lk.l_pid);
- return 1;
-}
-
-/*
-** Location of locking bytes in the database file
-*/
-#define PENDING_BYTE (0x40000000)
-#define RESERVED_BYTE (PENDING_BYTE+1)
-#define SHARED_FIRST (PENDING_BYTE+2)
-#define SHARED_SIZE 510
-
-/*
-** Lock locations for shared-memory locks used by WAL mode.
-*/
-#define SHM_BASE 120
-#define SHM_WRITE SHM_BASE
-#define SHM_CHECKPOINT (SHM_BASE+1)
-#define SHM_RECOVER (SHM_BASE+2)
-#define SHM_READ_FIRST (SHM_BASE+3)
-#define SHM_READ_SIZE 5
-
-
-int main(int argc, char **argv){
- int hDb; /* File descriptor for the open database file */
- int hShm; /* File descriptor for WAL shared-memory file */
- char *zShm; /* Name of the shared-memory file for WAL mode */
- ssize_t got; /* Bytes read from header */
- int isWal; /* True if in WAL mode */
- int nName; /* Length of filename */
- unsigned char aHdr[100]; /* Database header */
- int nLock = 0; /* Number of locks held */
- int i; /* Loop counter */
-
- if( argc!=2 ) usage(argv[0]);
- hDb = open(argv[1], O_RDONLY, 0);
- if( hDb<0 ){
- fprintf(stderr, "cannot open %s\n", argv[1]);
- return 1;
- }
-
- /* Make sure we are dealing with an database file */
- got = read(hDb, aHdr, 100);
- if( got!=100 || memcmp(aHdr, "SQLite format 3",16)!=0 ){
- fprintf(stderr, "not an SQLite database: %s\n", argv[1]);
- exit(1);
- }
-
- /* First check for an exclusive lock */
- if( isLocked(hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE") ){
- return 0;
- }
- isWal = aHdr[18]==2;
- if( isWal==0 ){
- /* Rollback mode */
- if( isLocked(hDb, F_RDLCK, PENDING_BYTE, 1, "PENDING") ) return 0;
- if( isLocked(hDb, F_RDLCK, RESERVED_BYTE, 1, "RESERVED") ) return 0;
- if( isLocked(hDb, F_WRLCK, SHARED_FIRST, SHARED_SIZE, "SHARED") ){
- return 0;
- }
- }else{
- /* WAL mode */
- nName = (int)strlen(argv[1]);
- zShm = malloc( nName + 100 );
- if( zShm==0 ){
- fprintf(stderr, "out of memory\n");
- exit(1);
- }
- memcpy(zShm, argv[1], nName);
- memcpy(&zShm[nName], "-shm", 5);
- hShm = open(zShm, O_RDONLY, 0);
- if( hShm<0 ){
- fprintf(stderr, "cannot open %s\n", zShm);
- return 1;
- }
- if( isLocked(hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ){
- return 0;
- }
- nLock += isLocked(hShm, F_RDLCK, SHM_CHECKPOINT, 1, "WAL-CHECKPOINT");
- nLock += isLocked(hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE");
- for(i=0; i<SHM_READ_SIZE; i++){
- nLock += isLocked(hShm, F_WRLCK, SHM_READ_FIRST+i, 1, "WAL-READ");
- }
- }
- if( nLock==0 ){
- printf("file is not locked\n");
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/lemon.c b/lib/libsqlite3/tool/lemon.c
deleted file mode 100644
index 2e8054b5ccb..00000000000
--- a/lib/libsqlite3/tool/lemon.c
+++ /dev/null
@@ -1,5171 +0,0 @@
-/*
-** This file contains all sources (including headers) to the LEMON
-** LALR(1) parser generator. The sources have been combined into a
-** single file to make it easy to include LEMON in the source tree
-** and Makefile of another program.
-**
-** The author of this program disclaims copyright.
-*/
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef __WIN32__
-# if defined(_WIN32) || defined(WIN32)
-# define __WIN32__
-# endif
-#endif
-
-#ifdef __WIN32__
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int access(const char *path, int mode);
-#ifdef __cplusplus
-}
-#endif
-#else
-#include <unistd.h>
-#endif
-
-/* #define PRIVATE static */
-#define PRIVATE
-
-#ifdef TEST
-#define MAXRHS 5 /* Set low to exercise exception code */
-#else
-#define MAXRHS 1000
-#endif
-
-static int showPrecedenceConflict = 0;
-static char *msort(char*,char**,int(*)(const char*,const char*));
-
-/*
-** Compilers are getting increasingly pedantic about type conversions
-** as C evolves ever closer to Ada.... To work around the latest problems
-** we have to define the following variant of strlen().
-*/
-#define lemonStrlen(X) ((int)strlen(X))
-
-/*
-** Compilers are starting to complain about the use of sprintf() and strcpy(),
-** saying they are unsafe. So we define our own versions of those routines too.
-**
-** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and
-** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
-** The third is a helper routine for vsnprintf() that adds texts to the end of a
-** buffer, making sure the buffer is always zero-terminated.
-**
-** The string formatter is a minimal subset of stdlib sprintf() supporting only
-** a few simply conversions:
-**
-** %d
-** %s
-** %.*s
-**
-*/
-static void lemon_addtext(
- char *zBuf, /* The buffer to which text is added */
- int *pnUsed, /* Slots of the buffer used so far */
- const char *zIn, /* Text to add */
- int nIn, /* Bytes of text to add. -1 to use strlen() */
- int iWidth /* Field width. Negative to left justify */
-){
- if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
- while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; }
- if( nIn==0 ) return;
- memcpy(&zBuf[*pnUsed], zIn, nIn);
- *pnUsed += nIn;
- while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; }
- zBuf[*pnUsed] = 0;
-}
-static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
- int i, j, k, c;
- int nUsed = 0;
- const char *z;
- char zTemp[50];
- str[0] = 0;
- for(i=j=0; (c = zFormat[i])!=0; i++){
- if( c=='%' ){
- int iWidth = 0;
- lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
- c = zFormat[++i];
- if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){
- if( c=='-' ) i++;
- while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0';
- if( c=='-' ) iWidth = -iWidth;
- c = zFormat[i];
- }
- if( c=='d' ){
- int v = va_arg(ap, int);
- if( v<0 ){
- lemon_addtext(str, &nUsed, "-", 1, iWidth);
- v = -v;
- }else if( v==0 ){
- lemon_addtext(str, &nUsed, "0", 1, iWidth);
- }
- k = 0;
- while( v>0 ){
- k++;
- zTemp[sizeof(zTemp)-k] = (v%10) + '0';
- v /= 10;
- }
- lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth);
- }else if( c=='s' ){
- z = va_arg(ap, const char*);
- lemon_addtext(str, &nUsed, z, -1, iWidth);
- }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
- i += 2;
- k = va_arg(ap, int);
- z = va_arg(ap, const char*);
- lemon_addtext(str, &nUsed, z, k, iWidth);
- }else if( c=='%' ){
- lemon_addtext(str, &nUsed, "%", 1, 0);
- }else{
- fprintf(stderr, "illegal format\n");
- exit(1);
- }
- j = i+1;
- }
- }
- lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
- return nUsed;
-}
-static int lemon_sprintf(char *str, const char *format, ...){
- va_list ap;
- int rc;
- va_start(ap, format);
- rc = lemon_vsprintf(str, format, ap);
- va_end(ap);
- return rc;
-}
-static void lemon_strcpy(char *dest, const char *src){
- while( (*(dest++) = *(src++))!=0 ){}
-}
-static void lemon_strcat(char *dest, const char *src){
- while( *dest ) dest++;
- lemon_strcpy(dest, src);
-}
-
-
-/* a few forward declarations... */
-struct rule;
-struct lemon;
-struct action;
-
-static struct action *Action_new(void);
-static struct action *Action_sort(struct action *);
-
-/********** From the file "build.h" ************************************/
-void FindRulePrecedences();
-void FindFirstSets();
-void FindStates();
-void FindLinks();
-void FindFollowSets();
-void FindActions();
-
-/********* From the file "configlist.h" *********************************/
-void Configlist_init(void);
-struct config *Configlist_add(struct rule *, int);
-struct config *Configlist_addbasis(struct rule *, int);
-void Configlist_closure(struct lemon *);
-void Configlist_sort(void);
-void Configlist_sortbasis(void);
-struct config *Configlist_return(void);
-struct config *Configlist_basis(void);
-void Configlist_eat(struct config *);
-void Configlist_reset(void);
-
-/********* From the file "error.h" ***************************************/
-void ErrorMsg(const char *, int,const char *, ...);
-
-/****** From the file "option.h" ******************************************/
-enum option_type { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
- OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR};
-struct s_options {
- enum option_type type;
- const char *label;
- char *arg;
- const char *message;
-};
-int OptInit(char**,struct s_options*,FILE*);
-int OptNArgs(void);
-char *OptArg(int);
-void OptErr(int);
-void OptPrint(void);
-
-/******** From the file "parse.h" *****************************************/
-void Parse(struct lemon *lemp);
-
-/********* From the file "plink.h" ***************************************/
-struct plink *Plink_new(void);
-void Plink_add(struct plink **, struct config *);
-void Plink_copy(struct plink **, struct plink *);
-void Plink_delete(struct plink *);
-
-/********** From the file "report.h" *************************************/
-void Reprint(struct lemon *);
-void ReportOutput(struct lemon *);
-void ReportTable(struct lemon *, int);
-void ReportHeader(struct lemon *);
-void CompressTables(struct lemon *);
-void ResortStates(struct lemon *);
-
-/********** From the file "set.h" ****************************************/
-void SetSize(int); /* All sets will be of size N */
-char *SetNew(void); /* A new set for element 0..N */
-void SetFree(char*); /* Deallocate a set */
-int SetAdd(char*,int); /* Add element to a set */
-int SetUnion(char *,char *); /* A <- A U B, thru element N */
-#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
-
-/********** From the file "struct.h" *************************************/
-/*
-** Principal data structures for the LEMON parser generator.
-*/
-
-typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
-
-/* Symbols (terminals and nonterminals) of the grammar are stored
-** in the following: */
-enum symbol_type {
- TERMINAL,
- NONTERMINAL,
- MULTITERMINAL
-};
-enum e_assoc {
- LEFT,
- RIGHT,
- NONE,
- UNK
-};
-struct symbol {
- const char *name; /* Name of the symbol */
- int index; /* Index number for this symbol */
- enum symbol_type type; /* Symbols are all either TERMINALS or NTs */
- struct rule *rule; /* Linked list of rules of this (if an NT) */
- struct symbol *fallback; /* fallback token in case this token doesn't parse */
- int prec; /* Precedence if defined (-1 otherwise) */
- enum e_assoc assoc; /* Associativity if precedence is defined */
- char *firstset; /* First-set for all rules of this symbol */
- Boolean lambda; /* True if NT and can generate an empty string */
- int useCnt; /* Number of times used */
- char *destructor; /* Code which executes whenever this symbol is
- ** popped from the stack during error processing */
- int destLineno; /* Line number for start of destructor */
- char *datatype; /* The data type of information held by this
- ** object. Only used if type==NONTERMINAL */
- int dtnum; /* The data type number. In the parser, the value
- ** stack is a union. The .yy%d element of this
- ** union is the correct data type for this object */
- /* The following fields are used by MULTITERMINALs only */
- int nsubsym; /* Number of constituent symbols in the MULTI */
- struct symbol **subsym; /* Array of constituent symbols */
-};
-
-/* Each production rule in the grammar is stored in the following
-** structure. */
-struct rule {
- struct symbol *lhs; /* Left-hand side of the rule */
- const char *lhsalias; /* Alias for the LHS (NULL if none) */
- int lhsStart; /* True if left-hand side is the start symbol */
- int ruleline; /* Line number for the rule */
- int nrhs; /* Number of RHS symbols */
- struct symbol **rhs; /* The RHS symbols */
- const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
- int line; /* Line number at which code begins */
- const char *code; /* The code executed when this rule is reduced */
- struct symbol *precsym; /* Precedence symbol for this rule */
- int index; /* An index number for this rule */
- Boolean canReduce; /* True if this rule is ever reduced */
- struct rule *nextlhs; /* Next rule with the same LHS */
- struct rule *next; /* Next rule in the global list */
-};
-
-/* A configuration is a production rule of the grammar together with
-** a mark (dot) showing how much of that rule has been processed so far.
-** Configurations also contain a follow-set which is a list of terminal
-** symbols which are allowed to immediately follow the end of the rule.
-** Every configuration is recorded as an instance of the following: */
-enum cfgstatus {
- COMPLETE,
- INCOMPLETE
-};
-struct config {
- struct rule *rp; /* The rule upon which the configuration is based */
- int dot; /* The parse point */
- char *fws; /* Follow-set for this configuration only */
- struct plink *fplp; /* Follow-set forward propagation links */
- struct plink *bplp; /* Follow-set backwards propagation links */
- struct state *stp; /* Pointer to state which contains this */
- enum cfgstatus status; /* used during followset and shift computations */
- struct config *next; /* Next configuration in the state */
- struct config *bp; /* The next basis configuration */
-};
-
-enum e_action {
- SHIFT,
- ACCEPT,
- REDUCE,
- ERROR,
- SSCONFLICT, /* A shift/shift conflict */
- SRCONFLICT, /* Was a reduce, but part of a conflict */
- RRCONFLICT, /* Was a reduce, but part of a conflict */
- SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
- RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
- NOT_USED, /* Deleted by compression */
- SHIFTREDUCE /* Shift first, then reduce */
-};
-
-/* Every shift or reduce operation is stored as one of the following */
-struct action {
- struct symbol *sp; /* The look-ahead symbol */
- enum e_action type;
- union {
- struct state *stp; /* The new state, if a shift */
- struct rule *rp; /* The rule, if a reduce */
- } x;
- struct action *next; /* Next action for this state */
- struct action *collide; /* Next action with the same hash */
-};
-
-/* Each state of the generated parser's finite state machine
-** is encoded as an instance of the following structure. */
-struct state {
- struct config *bp; /* The basis configurations for this state */
- struct config *cfp; /* All configurations in this set */
- int statenum; /* Sequential number for this state */
- struct action *ap; /* Array of actions for this state */
- int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
- int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
- int iDfltReduce; /* Default action is to REDUCE by this rule */
- struct rule *pDfltReduce;/* The default REDUCE rule. */
- int autoReduce; /* True if this is an auto-reduce state */
-};
-#define NO_OFFSET (-2147483647)
-
-/* A followset propagation link indicates that the contents of one
-** configuration followset should be propagated to another whenever
-** the first changes. */
-struct plink {
- struct config *cfp; /* The configuration to which linked */
- struct plink *next; /* The next propagate link */
-};
-
-/* The state vector for the entire parser generator is recorded as
-** follows. (LEMON uses no global variables and makes little use of
-** static variables. Fields in the following structure can be thought
-** of as begin global variables in the program.) */
-struct lemon {
- struct state **sorted; /* Table of states sorted by state number */
- struct rule *rule; /* List of all rules */
- int nstate; /* Number of states */
- int nxstate; /* nstate with tail degenerate states removed */
- int nrule; /* Number of rules */
- int nsymbol; /* Number of terminal and nonterminal symbols */
- int nterminal; /* Number of terminal symbols */
- struct symbol **symbols; /* Sorted array of pointers to symbols */
- int errorcnt; /* Number of errors */
- struct symbol *errsym; /* The error symbol */
- struct symbol *wildcard; /* Token that matches anything */
- char *name; /* Name of the generated parser */
- char *arg; /* Declaration of the 3th argument to parser */
- char *tokentype; /* Type of terminal symbols in the parser stack */
- char *vartype; /* The default type of non-terminal symbols */
- char *start; /* Name of the start symbol for the grammar */
- char *stacksize; /* Size of the parser stack */
- char *include; /* Code to put at the start of the C file */
- char *error; /* Code to execute when an error is seen */
- char *overflow; /* Code to execute on a stack overflow */
- char *failure; /* Code to execute on parser failure */
- char *accept; /* Code to execute when the parser excepts */
- char *extracode; /* Code appended to the generated file */
- char *tokendest; /* Code to execute to destroy token data */
- char *vardest; /* Code for the default non-terminal destructor */
- char *filename; /* Name of the input file */
- char *outname; /* Name of the current output file */
- char *tokenprefix; /* A prefix added to token names in the .h file */
- int nconflict; /* Number of parsing conflicts */
- int nactiontab; /* Number of entries in the yy_action[] table */
- int tablesize; /* Total table size of all tables in bytes */
- int basisflag; /* Print only basis configurations */
- int has_fallback; /* True if any %fallback is seen in the grammar */
- int nolinenosflag; /* True if #line statements should not be printed */
- char *argv0; /* Name of the program */
-};
-
-#define MemoryCheck(X) if((X)==0){ \
- extern void memory_error(); \
- memory_error(); \
-}
-
-/**************** From the file "table.h" *********************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-/* Routines for handling a strings */
-
-const char *Strsafe(const char *);
-
-void Strsafe_init(void);
-int Strsafe_insert(const char *);
-const char *Strsafe_find(const char *);
-
-/* Routines for handling symbols of the grammar */
-
-struct symbol *Symbol_new(const char *);
-int Symbolcmpp(const void *, const void *);
-void Symbol_init(void);
-int Symbol_insert(struct symbol *, const char *);
-struct symbol *Symbol_find(const char *);
-struct symbol *Symbol_Nth(int);
-int Symbol_count(void);
-struct symbol **Symbol_arrayof(void);
-
-/* Routines to manage the state table */
-
-int Configcmp(const char *, const char *);
-struct state *State_new(void);
-void State_init(void);
-int State_insert(struct state *, struct config *);
-struct state *State_find(struct config *);
-struct state **State_arrayof(/* */);
-
-/* Routines used for efficiency in Configlist_add */
-
-void Configtable_init(void);
-int Configtable_insert(struct config *);
-struct config *Configtable_find(struct config *);
-void Configtable_clear(int(*)(struct config *));
-
-/****************** From the file "action.c" *******************************/
-/*
-** Routines processing parser actions in the LEMON parser generator.
-*/
-
-/* Allocate a new parser action */
-static struct action *Action_new(void){
- static struct action *freelist = 0;
- struct action *newaction;
-
- if( freelist==0 ){
- int i;
- int amt = 100;
- freelist = (struct action *)calloc(amt, sizeof(struct action));
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new parser action.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- newaction = freelist;
- freelist = freelist->next;
- return newaction;
-}
-
-/* Compare two actions for sorting purposes. Return negative, zero, or
-** positive if the first action is less than, equal to, or greater than
-** the first
-*/
-static int actioncmp(
- struct action *ap1,
- struct action *ap2
-){
- int rc;
- rc = ap1->sp->index - ap2->sp->index;
- if( rc==0 ){
- rc = (int)ap1->type - (int)ap2->type;
- }
- if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
- rc = ap1->x.rp->index - ap2->x.rp->index;
- }
- if( rc==0 ){
- rc = (int) (ap2 - ap1);
- }
- return rc;
-}
-
-/* Sort parser actions */
-static struct action *Action_sort(
- struct action *ap
-){
- ap = (struct action *)msort((char *)ap,(char **)&ap->next,
- (int(*)(const char*,const char*))actioncmp);
- return ap;
-}
-
-void Action_add(
- struct action **app,
- enum e_action type,
- struct symbol *sp,
- char *arg
-){
- struct action *newaction;
- newaction = Action_new();
- newaction->next = *app;
- *app = newaction;
- newaction->type = type;
- newaction->sp = sp;
- if( type==SHIFT ){
- newaction->x.stp = (struct state *)arg;
- }else{
- newaction->x.rp = (struct rule *)arg;
- }
-}
-/********************** New code to implement the "acttab" module ***********/
-/*
-** This module implements routines use to construct the yy_action[] table.
-*/
-
-/*
-** The state of the yy_action table under construction is an instance of
-** the following structure.
-**
-** The yy_action table maps the pair (state_number, lookahead) into an
-** action_number. The table is an array of integers pairs. The state_number
-** determines an initial offset into the yy_action array. The lookahead
-** value is then added to this initial offset to get an index X into the
-** yy_action array. If the aAction[X].lookahead equals the value of the
-** of the lookahead input, then the value of the action_number output is
-** aAction[X].action. If the lookaheads do not match then the
-** default action for the state_number is returned.
-**
-** All actions associated with a single state_number are first entered
-** into aLookahead[] using multiple calls to acttab_action(). Then the
-** actions for that single state_number are placed into the aAction[]
-** array with a single call to acttab_insert(). The acttab_insert() call
-** also resets the aLookahead[] array in preparation for the next
-** state number.
-*/
-struct lookahead_action {
- int lookahead; /* Value of the lookahead token */
- int action; /* Action to take on the given lookahead */
-};
-typedef struct acttab acttab;
-struct acttab {
- int nAction; /* Number of used slots in aAction[] */
- int nActionAlloc; /* Slots allocated for aAction[] */
- struct lookahead_action
- *aAction, /* The yy_action[] table under construction */
- *aLookahead; /* A single new transaction set */
- int mnLookahead; /* Minimum aLookahead[].lookahead */
- int mnAction; /* Action associated with mnLookahead */
- int mxLookahead; /* Maximum aLookahead[].lookahead */
- int nLookahead; /* Used slots in aLookahead[] */
- int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
-};
-
-/* Return the number of entries in the yy_action table */
-#define acttab_size(X) ((X)->nAction)
-
-/* The value for the N-th entry in yy_action */
-#define acttab_yyaction(X,N) ((X)->aAction[N].action)
-
-/* The value for the N-th entry in yy_lookahead */
-#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
-
-/* Free all memory associated with the given acttab */
-void acttab_free(acttab *p){
- free( p->aAction );
- free( p->aLookahead );
- free( p );
-}
-
-/* Allocate a new acttab structure */
-acttab *acttab_alloc(void){
- acttab *p = (acttab *) calloc( 1, sizeof(*p) );
- if( p==0 ){
- fprintf(stderr,"Unable to allocate memory for a new acttab.");
- exit(1);
- }
- memset(p, 0, sizeof(*p));
- return p;
-}
-
-/* Add a new action to the current transaction set.
-**
-** This routine is called once for each lookahead for a particular
-** state.
-*/
-void acttab_action(acttab *p, int lookahead, int action){
- if( p->nLookahead>=p->nLookaheadAlloc ){
- p->nLookaheadAlloc += 25;
- p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
- sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
- if( p->aLookahead==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- }
- if( p->nLookahead==0 ){
- p->mxLookahead = lookahead;
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }else{
- if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
- if( p->mnLookahead>lookahead ){
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }
- }
- p->aLookahead[p->nLookahead].lookahead = lookahead;
- p->aLookahead[p->nLookahead].action = action;
- p->nLookahead++;
-}
-
-/*
-** Add the transaction set built up with prior calls to acttab_action()
-** into the current action table. Then reset the transaction set back
-** to an empty set in preparation for a new round of acttab_action() calls.
-**
-** Return the offset into the action table of the new transaction.
-*/
-int acttab_insert(acttab *p){
- int i, j, k, n;
- assert( p->nLookahead>0 );
-
- /* Make sure we have enough space to hold the expanded action table
- ** in the worst case. The worst case occurs if the transaction set
- ** must be appended to the current action table
- */
- n = p->mxLookahead + 1;
- if( p->nAction + n >= p->nActionAlloc ){
- int oldAlloc = p->nActionAlloc;
- p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
- p->aAction = (struct lookahead_action *) realloc( p->aAction,
- sizeof(p->aAction[0])*p->nActionAlloc);
- if( p->aAction==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=oldAlloc; i<p->nActionAlloc; i++){
- p->aAction[i].lookahead = -1;
- p->aAction[i].action = -1;
- }
- }
-
- /* Scan the existing action table looking for an offset that is a
- ** duplicate of the current transaction set. Fall out of the loop
- ** if and when the duplicate is found.
- **
- ** i is the index in p->aAction[] where p->mnLookahead is inserted.
- */
- for(i=p->nAction-1; i>=0; i--){
- if( p->aAction[i].lookahead==p->mnLookahead ){
- /* All lookaheads and actions in the aLookahead[] transaction
- ** must match against the candidate aAction[i] entry. */
- if( p->aAction[i].action!=p->mnAction ) continue;
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 || k>=p->nAction ) break;
- if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
- if( p->aLookahead[j].action!=p->aAction[k].action ) break;
- }
- if( j<p->nLookahead ) continue;
-
- /* No possible lookahead value that is not in the aLookahead[]
- ** transaction is allowed to match aAction[i] */
- n = 0;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead<0 ) continue;
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
- }
- if( n==p->nLookahead ){
- break; /* An exact match is found at offset i */
- }
- }
- }
-
- /* If no existing offsets exactly match the current transaction, find an
- ** an empty offset in the aAction[] table in which we can add the
- ** aLookahead[] transaction.
- */
- if( i<0 ){
- /* Look for holes in the aAction[] table that fit the current
- ** aLookahead[] transaction. Leave i set to the offset of the hole.
- ** If no holes are found, i is left at p->nAction, which means the
- ** transaction will be appended. */
- for(i=0; i<p->nActionAlloc - p->mxLookahead; i++){
- if( p->aAction[i].lookahead<0 ){
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 ) break;
- if( p->aAction[k].lookahead>=0 ) break;
- }
- if( j<p->nLookahead ) continue;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
- }
- if( j==p->nAction ){
- break; /* Fits in empty slots */
- }
- }
- }
- }
- /* Insert transaction set at index i. */
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- p->aAction[k] = p->aLookahead[j];
- if( k>=p->nAction ) p->nAction = k+1;
- }
- p->nLookahead = 0;
-
- /* Return the offset that is added to the lookahead in order to get the
- ** index into yy_action of the action */
- return i - p->mnLookahead;
-}
-
-/********************** From the file "build.c" *****************************/
-/*
-** Routines to construction the finite state machine for the LEMON
-** parser generator.
-*/
-
-/* Find a precedence symbol of every rule in the grammar.
-**
-** Those rules which have a precedence symbol coded in the input
-** grammar using the "[symbol]" construct will already have the
-** rp->precsym field filled. Other rules take as their precedence
-** symbol the first RHS symbol with a defined precedence. If there
-** are not RHS symbols with a defined precedence, the precedence
-** symbol field is left blank.
-*/
-void FindRulePrecedences(struct lemon *xp)
-{
- struct rule *rp;
- for(rp=xp->rule; rp; rp=rp->next){
- if( rp->precsym==0 ){
- int i, j;
- for(i=0; i<rp->nrhs && rp->precsym==0; i++){
- struct symbol *sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- for(j=0; j<sp->nsubsym; j++){
- if( sp->subsym[j]->prec>=0 ){
- rp->precsym = sp->subsym[j];
- break;
- }
- }
- }else if( sp->prec>=0 ){
- rp->precsym = rp->rhs[i];
- }
- }
- }
- }
- return;
-}
-
-/* Find all nonterminals which will generate the empty string.
-** Then go back and compute the first sets of every nonterminal.
-** The first set is the set of all terminal symbols which can begin
-** a string generated by that nonterminal.
-*/
-void FindFirstSets(struct lemon *lemp)
-{
- int i, j;
- struct rule *rp;
- int progress;
-
- for(i=0; i<lemp->nsymbol; i++){
- lemp->symbols[i]->lambda = LEMON_FALSE;
- }
- for(i=lemp->nterminal; i<lemp->nsymbol; i++){
- lemp->symbols[i]->firstset = SetNew();
- }
-
- /* First compute all lambdas */
- do{
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->lhs->lambda ) continue;
- for(i=0; i<rp->nrhs; i++){
- struct symbol *sp = rp->rhs[i];
- assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
- if( sp->lambda==LEMON_FALSE ) break;
- }
- if( i==rp->nrhs ){
- rp->lhs->lambda = LEMON_TRUE;
- progress = 1;
- }
- }
- }while( progress );
-
- /* Now compute all first sets */
- do{
- struct symbol *s1, *s2;
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- s1 = rp->lhs;
- for(i=0; i<rp->nrhs; i++){
- s2 = rp->rhs[i];
- if( s2->type==TERMINAL ){
- progress += SetAdd(s1->firstset,s2->index);
- break;
- }else if( s2->type==MULTITERMINAL ){
- for(j=0; j<s2->nsubsym; j++){
- progress += SetAdd(s1->firstset,s2->subsym[j]->index);
- }
- break;
- }else if( s1==s2 ){
- if( s1->lambda==LEMON_FALSE ) break;
- }else{
- progress += SetUnion(s1->firstset,s2->firstset);
- if( s2->lambda==LEMON_FALSE ) break;
- }
- }
- }
- }while( progress );
- return;
-}
-
-/* Compute all LR(0) states for the grammar. Links
-** are added to between some states so that the LR(1) follow sets
-** can be computed later.
-*/
-PRIVATE struct state *getstate(struct lemon *); /* forward reference */
-void FindStates(struct lemon *lemp)
-{
- struct symbol *sp;
- struct rule *rp;
-
- Configlist_init();
-
- /* Find the start symbol */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ){
- ErrorMsg(lemp->filename,0,
-"The specified start symbol \"%s\" is not \
-in a nonterminal of the grammar. \"%s\" will be used as the start \
-symbol instead.",lemp->start,lemp->rule->lhs->name);
- lemp->errorcnt++;
- sp = lemp->rule->lhs;
- }
- }else{
- sp = lemp->rule->lhs;
- }
-
- /* Make sure the start symbol doesn't occur on the right-hand side of
- ** any rule. Report an error if it does. (YACC would generate a new
- ** start symbol in this case.) */
- for(rp=lemp->rule; rp; rp=rp->next){
- int i;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */
- ErrorMsg(lemp->filename,0,
-"The start symbol \"%s\" occurs on the \
-right-hand side of a rule. This will result in a parser which \
-does not work properly.",sp->name);
- lemp->errorcnt++;
- }
- }
- }
-
- /* The basis configuration set for the first state
- ** is all rules which have the start symbol as their
- ** left-hand side */
- for(rp=sp->rule; rp; rp=rp->nextlhs){
- struct config *newcfp;
- rp->lhsStart = 1;
- newcfp = Configlist_addbasis(rp,0);
- SetAdd(newcfp->fws,0);
- }
-
- /* Compute the first state. All other states will be
- ** computed automatically during the computation of the first one.
- ** The returned pointer to the first state is not used. */
- (void)getstate(lemp);
- return;
-}
-
-/* Return a pointer to a state which is described by the configuration
-** list which has been built from calls to Configlist_add.
-*/
-PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */
-PRIVATE struct state *getstate(struct lemon *lemp)
-{
- struct config *cfp, *bp;
- struct state *stp;
-
- /* Extract the sorted basis of the new state. The basis was constructed
- ** by prior calls to "Configlist_addbasis()". */
- Configlist_sortbasis();
- bp = Configlist_basis();
-
- /* Get a state with the same basis */
- stp = State_find(bp);
- if( stp ){
- /* A state with the same basis already exists! Copy all the follow-set
- ** propagation links from the state under construction into the
- ** preexisting state, then return a pointer to the preexisting state */
- struct config *x, *y;
- for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
- Plink_copy(&y->bplp,x->bplp);
- Plink_delete(x->fplp);
- x->fplp = x->bplp = 0;
- }
- cfp = Configlist_return();
- Configlist_eat(cfp);
- }else{
- /* This really is a new state. Construct all the details */
- Configlist_closure(lemp); /* Compute the configuration closure */
- Configlist_sort(); /* Sort the configuration closure */
- cfp = Configlist_return(); /* Get a pointer to the config list */
- stp = State_new(); /* A new state structure */
- MemoryCheck(stp);
- stp->bp = bp; /* Remember the configuration basis */
- stp->cfp = cfp; /* Remember the configuration closure */
- stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
- stp->ap = 0; /* No actions, yet. */
- State_insert(stp,stp->bp); /* Add to the state table */
- buildshifts(lemp,stp); /* Recursively compute successor states */
- }
- return stp;
-}
-
-/*
-** Return true if two symbols are the same.
-*/
-int same_symbol(struct symbol *a, struct symbol *b)
-{
- int i;
- if( a==b ) return 1;
- if( a->type!=MULTITERMINAL ) return 0;
- if( b->type!=MULTITERMINAL ) return 0;
- if( a->nsubsym!=b->nsubsym ) return 0;
- for(i=0; i<a->nsubsym; i++){
- if( a->subsym[i]!=b->subsym[i] ) return 0;
- }
- return 1;
-}
-
-/* Construct all successor states to the given state. A "successor"
-** state is any state which can be reached by a shift action.
-*/
-PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
-{
- struct config *cfp; /* For looping thru the config closure of "stp" */
- struct config *bcfp; /* For the inner loop on config closure of "stp" */
- struct config *newcfg; /* */
- struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
- struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
- struct state *newstp; /* A pointer to a successor state */
-
- /* Each configuration becomes complete after it contibutes to a successor
- ** state. Initially, all configurations are incomplete */
- for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
-
- /* Loop through all configurations of the state "stp" */
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
- if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
- Configlist_reset(); /* Reset the new config set */
- sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
-
- /* For every configuration in the state "stp" which has the symbol "sp"
- ** following its dot, add the same configuration to the basis set under
- ** construction but with the dot shifted one symbol to the right. */
- for(bcfp=cfp; bcfp; bcfp=bcfp->next){
- if( bcfp->status==COMPLETE ) continue; /* Already used */
- if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
- bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
- if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */
- bcfp->status = COMPLETE; /* Mark this config as used */
- newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
- Plink_add(&newcfg->bplp,bcfp);
- }
-
- /* Get a pointer to the state described by the basis configuration set
- ** constructed in the preceding loop */
- newstp = getstate(lemp);
-
- /* The state "newstp" is reached from the state "stp" by a shift action
- ** on the symbol "sp" */
- if( sp->type==MULTITERMINAL ){
- int i;
- for(i=0; i<sp->nsubsym; i++){
- Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
- }
- }else{
- Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
- }
- }
-}
-
-/*
-** Construct the propagation links
-*/
-void FindLinks(struct lemon *lemp)
-{
- int i;
- struct config *cfp, *other;
- struct state *stp;
- struct plink *plp;
-
- /* Housekeeping detail:
- ** Add to every propagate link a pointer back to the state to
- ** which the link is attached. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- cfp->stp = stp;
- }
- }
-
- /* Convert all backlinks into forward links. Only the forward
- ** links are used in the follow-set computation. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- for(plp=cfp->bplp; plp; plp=plp->next){
- other = plp->cfp;
- Plink_add(&other->fplp,cfp);
- }
- }
- }
-}
-
-/* Compute all followsets.
-**
-** A followset is the set of all symbols which can come immediately
-** after a configuration.
-*/
-void FindFollowSets(struct lemon *lemp)
-{
- int i;
- struct config *cfp;
- struct plink *plp;
- int progress;
- int change;
-
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- cfp->status = INCOMPLETE;
- }
- }
-
- do{
- progress = 0;
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue;
- for(plp=cfp->fplp; plp; plp=plp->next){
- change = SetUnion(plp->cfp->fws,cfp->fws);
- if( change ){
- plp->cfp->status = INCOMPLETE;
- progress = 1;
- }
- }
- cfp->status = COMPLETE;
- }
- }
- }while( progress );
-}
-
-static int resolve_conflict(struct action *,struct action *);
-
-/* Compute the reduce actions, and resolve conflicts.
-*/
-void FindActions(struct lemon *lemp)
-{
- int i,j;
- struct config *cfp;
- struct state *stp;
- struct symbol *sp;
- struct rule *rp;
-
- /* Add all of the reduce actions
- ** A reduce action is added for each element of the followset of
- ** a configuration which has its dot at the extreme right.
- */
- for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
- if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
- for(j=0; j<lemp->nterminal; j++){
- if( SetFind(cfp->fws,j) ){
- /* Add a reduce action to the state "stp" which will reduce by the
- ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
- Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
- }
- }
- }
- }
- }
-
- /* Add the accepting token */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ) sp = lemp->rule->lhs;
- }else{
- sp = lemp->rule->lhs;
- }
- /* Add to the first state (which is always the starting state of the
- ** finite state machine) an action to ACCEPT if the lookahead is the
- ** start nonterminal. */
- Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
-
- /* Resolve conflicts */
- for(i=0; i<lemp->nstate; i++){
- struct action *ap, *nap;
- stp = lemp->sorted[i];
- /* assert( stp->ap ); */
- stp->ap = Action_sort(stp->ap);
- for(ap=stp->ap; ap && ap->next; ap=ap->next){
- for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
- /* The two actions "ap" and "nap" have the same lookahead.
- ** Figure out which one should be used */
- lemp->nconflict += resolve_conflict(ap,nap);
- }
- }
- }
-
- /* Report an error for each rule that can never be reduced. */
- for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
- for(i=0; i<lemp->nstate; i++){
- struct action *ap;
- for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
- if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
- }
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->canReduce ) continue;
- ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
- lemp->errorcnt++;
- }
-}
-
-/* Resolve a conflict between the two given actions. If the
-** conflict can't be resolved, return non-zero.
-**
-** NO LONGER TRUE:
-** To resolve a conflict, first look to see if either action
-** is on an error rule. In that case, take the action which
-** is not associated with the error rule. If neither or both
-** actions are associated with an error rule, then try to
-** use precedence to resolve the conflict.
-**
-** If either action is a SHIFT, then it must be apx. This
-** function won't work if apx->type==REDUCE and apy->type==SHIFT.
-*/
-static int resolve_conflict(
- struct action *apx,
- struct action *apy
-){
- struct symbol *spx, *spy;
- int errcnt = 0;
- assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
- if( apx->type==SHIFT && apy->type==SHIFT ){
- apy->type = SSCONFLICT;
- errcnt++;
- }
- if( apx->type==SHIFT && apy->type==REDUCE ){
- spx = apx->sp;
- spy = apy->x.rp->precsym;
- if( spy==0 || spx->prec<0 || spy->prec<0 ){
- /* Not enough precedence information. */
- apy->type = SRCONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){ /* higher precedence wins */
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = SH_RESOLVED;
- }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
- apy->type = RD_RESOLVED; /* associativity */
- }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
- apx->type = SH_RESOLVED;
- }else{
- assert( spx->prec==spy->prec && spx->assoc==NONE );
- apx->type = ERROR;
- }
- }else if( apx->type==REDUCE && apy->type==REDUCE ){
- spx = apx->x.rp->precsym;
- spy = apy->x.rp->precsym;
- if( spx==0 || spy==0 || spx->prec<0 ||
- spy->prec<0 || spx->prec==spy->prec ){
- apy->type = RRCONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = RD_RESOLVED;
- }
- }else{
- assert(
- apx->type==SH_RESOLVED ||
- apx->type==RD_RESOLVED ||
- apx->type==SSCONFLICT ||
- apx->type==SRCONFLICT ||
- apx->type==RRCONFLICT ||
- apy->type==SH_RESOLVED ||
- apy->type==RD_RESOLVED ||
- apy->type==SSCONFLICT ||
- apy->type==SRCONFLICT ||
- apy->type==RRCONFLICT
- );
- /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
- ** REDUCEs on the list. If we reach this point it must be because
- ** the parser conflict had already been resolved. */
- }
- return errcnt;
-}
-/********************* From the file "configlist.c" *************************/
-/*
-** Routines to processing a configuration list and building a state
-** in the LEMON parser generator.
-*/
-
-static struct config *freelist = 0; /* List of free configurations */
-static struct config *current = 0; /* Top of list of configurations */
-static struct config **currentend = 0; /* Last on list of configs */
-static struct config *basis = 0; /* Top of list of basis configs */
-static struct config **basisend = 0; /* End of list of basis configs */
-
-/* Return a pointer to a new configuration */
-PRIVATE struct config *newconfig(){
- struct config *newcfg;
- if( freelist==0 ){
- int i;
- int amt = 3;
- freelist = (struct config *)calloc( amt, sizeof(struct config) );
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new configuration.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- newcfg = freelist;
- freelist = freelist->next;
- return newcfg;
-}
-
-/* The configuration "old" is no longer used */
-PRIVATE void deleteconfig(struct config *old)
-{
- old->next = freelist;
- freelist = old;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_init(){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_init();
- return;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_reset(){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_clear(0);
- return;
-}
-
-/* Add another configuration to the configuration list */
-struct config *Configlist_add(
- struct rule *rp, /* The rule */
- int dot /* Index into the RHS of the rule where the dot goes */
-){
- struct config *cfp, model;
-
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Add a basis configuration to the configuration list */
-struct config *Configlist_addbasis(struct rule *rp, int dot)
-{
- struct config *cfp, model;
-
- assert( basisend!=0 );
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- *basisend = cfp;
- basisend = &cfp->bp;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Compute the closure of the configuration list */
-void Configlist_closure(struct lemon *lemp)
-{
- struct config *cfp, *newcfp;
- struct rule *rp, *newrp;
- struct symbol *sp, *xsp;
- int i, dot;
-
- assert( currentend!=0 );
- for(cfp=current; cfp; cfp=cfp->next){
- rp = cfp->rp;
- dot = cfp->dot;
- if( dot>=rp->nrhs ) continue;
- sp = rp->rhs[dot];
- if( sp->type==NONTERMINAL ){
- if( sp->rule==0 && sp!=lemp->errsym ){
- ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
- sp->name);
- lemp->errorcnt++;
- }
- for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
- newcfp = Configlist_add(newrp,0);
- for(i=dot+1; i<rp->nrhs; i++){
- xsp = rp->rhs[i];
- if( xsp->type==TERMINAL ){
- SetAdd(newcfp->fws,xsp->index);
- break;
- }else if( xsp->type==MULTITERMINAL ){
- int k;
- for(k=0; k<xsp->nsubsym; k++){
- SetAdd(newcfp->fws, xsp->subsym[k]->index);
- }
- break;
- }else{
- SetUnion(newcfp->fws,xsp->firstset);
- if( xsp->lambda==LEMON_FALSE ) break;
- }
- }
- if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
- }
- }
- }
- return;
-}
-
-/* Sort the configuration list */
-void Configlist_sort(){
- current = (struct config*)msort((char*)current,(char**)&(current->next),
- Configcmp);
- currentend = 0;
- return;
-}
-
-/* Sort the basis configuration list */
-void Configlist_sortbasis(){
- basis = (struct config*)msort((char*)current,(char**)&(current->bp),
- Configcmp);
- basisend = 0;
- return;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_return(){
- struct config *old;
- old = current;
- current = 0;
- currentend = 0;
- return old;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_basis(){
- struct config *old;
- old = basis;
- basis = 0;
- basisend = 0;
- return old;
-}
-
-/* Free all elements of the given configuration list */
-void Configlist_eat(struct config *cfp)
-{
- struct config *nextcfp;
- for(; cfp; cfp=nextcfp){
- nextcfp = cfp->next;
- assert( cfp->fplp==0 );
- assert( cfp->bplp==0 );
- if( cfp->fws ) SetFree(cfp->fws);
- deleteconfig(cfp);
- }
- return;
-}
-/***************** From the file "error.c" *********************************/
-/*
-** Code for printing error message.
-*/
-
-void ErrorMsg(const char *filename, int lineno, const char *format, ...){
- va_list ap;
- fprintf(stderr, "%s:%d: ", filename, lineno);
- va_start(ap, format);
- vfprintf(stderr,format,ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-/**************** From the file "main.c" ************************************/
-/*
-** Main program file for the LEMON parser generator.
-*/
-
-/* Report an out-of-memory condition and abort. This function
-** is used mostly by the "MemoryCheck" macro in struct.h
-*/
-void memory_error(){
- fprintf(stderr,"Out of memory. Aborting...\n");
- exit(1);
-}
-
-static int nDefine = 0; /* Number of -D options on the command line */
-static char **azDefine = 0; /* Name of the -D macros */
-
-/* This routine is called with the argument to each -D command-line option.
-** Add the macro defined to the azDefine array.
-*/
-static void handle_D_option(char *z){
- char **paz;
- nDefine++;
- azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
- if( azDefine==0 ){
- fprintf(stderr,"out of memory\n");
- exit(1);
- }
- paz = &azDefine[nDefine-1];
- *paz = (char *) malloc( lemonStrlen(z)+1 );
- if( *paz==0 ){
- fprintf(stderr,"out of memory\n");
- exit(1);
- }
- lemon_strcpy(*paz, z);
- for(z=*paz; *z && *z!='='; z++){}
- *z = 0;
-}
-
-static char *user_templatename = NULL;
-static void handle_T_option(char *z){
- user_templatename = (char *) malloc( lemonStrlen(z)+1 );
- if( user_templatename==0 ){
- memory_error();
- }
- lemon_strcpy(user_templatename, z);
-}
-
-/* forward reference */
-static const char *minimum_size_type(int lwr, int upr, int *pnByte);
-
-/* Print a single line of the "Parser Stats" output
-*/
-static void stats_line(const char *zLabel, int iValue){
- int nLabel = lemonStrlen(zLabel);
- printf(" %s%.*s %5d\n", zLabel,
- 35-nLabel, "................................",
- iValue);
-}
-
-/* The main program. Parse the command line and do it... */
-int main(int argc, char **argv)
-{
- static int version = 0;
- static int rpflag = 0;
- static int basisflag = 0;
- static int compress = 0;
- static int quiet = 0;
- static int statistics = 0;
- static int mhflag = 0;
- static int nolinenosflag = 0;
- static int noResort = 0;
- static struct s_options options[] = {
- {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
- {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
- {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
- {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
- {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
- {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
- {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
- {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
- {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"},
- {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
- "Show conflicts resolved by precedence rules"},
- {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
- {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
- {OPT_FLAG, "s", (char*)&statistics,
- "Print parser stats to standard output."},
- {OPT_FLAG, "x", (char*)&version, "Print the version number."},
- {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
- {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"},
- {OPT_FLAG,0,0,0}
- };
- int i;
- int exitcode;
- struct lemon lem;
-
- OptInit(argv,options,stderr);
- if( version ){
- printf("Lemon version 1.0\n");
- exit(0);
- }
- if( OptNArgs()!=1 ){
- fprintf(stderr,"Exactly one filename argument is required.\n");
- exit(1);
- }
- memset(&lem, 0, sizeof(lem));
- lem.errorcnt = 0;
-
- /* Initialize the machine */
- Strsafe_init();
- Symbol_init();
- State_init();
- lem.argv0 = argv[0];
- lem.filename = OptArg(0);
- lem.basisflag = basisflag;
- lem.nolinenosflag = nolinenosflag;
- Symbol_new("$");
- lem.errsym = Symbol_new("error");
- lem.errsym->useCnt = 0;
-
- /* Parse the input file */
- Parse(&lem);
- if( lem.errorcnt ) exit(lem.errorcnt);
- if( lem.nrule==0 ){
- fprintf(stderr,"Empty grammar.\n");
- exit(1);
- }
-
- /* Count and index the symbols of the grammar */
- Symbol_new("{default}");
- lem.nsymbol = Symbol_count();
- lem.symbols = Symbol_arrayof();
- for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
- qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
- for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
- while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; }
- assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 );
- lem.nsymbol = i - 1;
- for(i=1; isupper(lem.symbols[i]->name[0]); i++);
- lem.nterminal = i;
-
- /* Generate a reprint of the grammar, if requested on the command line */
- if( rpflag ){
- Reprint(&lem);
- }else{
- /* Initialize the size for all follow and first sets */
- SetSize(lem.nterminal+1);
-
- /* Find the precedence for every production rule (that has one) */
- FindRulePrecedences(&lem);
-
- /* Compute the lambda-nonterminals and the first-sets for every
- ** nonterminal */
- FindFirstSets(&lem);
-
- /* Compute all LR(0) states. Also record follow-set propagation
- ** links so that the follow-set can be computed later */
- lem.nstate = 0;
- FindStates(&lem);
- lem.sorted = State_arrayof();
-
- /* Tie up loose ends on the propagation links */
- FindLinks(&lem);
-
- /* Compute the follow set of every reducible configuration */
- FindFollowSets(&lem);
-
- /* Compute the action tables */
- FindActions(&lem);
-
- /* Compress the action tables */
- if( compress==0 ) CompressTables(&lem);
-
- /* Reorder and renumber the states so that states with fewer choices
- ** occur at the end. This is an optimization that helps make the
- ** generated parser tables smaller. */
- if( noResort==0 ) ResortStates(&lem);
-
- /* Generate a report of the parser generated. (the "y.output" file) */
- if( !quiet ) ReportOutput(&lem);
-
- /* Generate the source code for the parser */
- ReportTable(&lem, mhflag);
-
- /* Produce a header file for use by the scanner. (This step is
- ** omitted if the "-m" option is used because makeheaders will
- ** generate the file for us.) */
- if( !mhflag ) ReportHeader(&lem);
- }
- if( statistics ){
- printf("Parser statistics:\n");
- stats_line("terminal symbols", lem.nterminal);
- stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
- stats_line("total symbols", lem.nsymbol);
- stats_line("rules", lem.nrule);
- stats_line("states", lem.nxstate);
- stats_line("conflicts", lem.nconflict);
- stats_line("action table entries", lem.nactiontab);
- stats_line("total table size (bytes)", lem.tablesize);
- }
- if( lem.nconflict > 0 ){
- fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
- }
-
- /* return 0 on success, 1 on failure. */
- exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
- exit(exitcode);
- return (exitcode);
-}
-/******************** From the file "msort.c" *******************************/
-/*
-** A generic merge-sort program.
-**
-** USAGE:
-** Let "ptr" be a pointer to some structure which is at the head of
-** a null-terminated list. Then to sort the list call:
-**
-** ptr = msort(ptr,&(ptr->next),cmpfnc);
-**
-** In the above, "cmpfnc" is a pointer to a function which compares
-** two instances of the structure and returns an integer, as in
-** strcmp. The second argument is a pointer to the pointer to the
-** second element of the linked list. This address is used to compute
-** the offset to the "next" field within the structure. The offset to
-** the "next" field must be constant for all structures in the list.
-**
-** The function returns a new pointer which is the head of the list
-** after sorting.
-**
-** ALGORITHM:
-** Merge-sort.
-*/
-
-/*
-** Return a pointer to the next structure in the linked list.
-*/
-#define NEXT(A) (*(char**)(((char*)A)+offset))
-
-/*
-** Inputs:
-** a: A sorted, null-terminated linked list. (May be null).
-** b: A sorted, null-terminated linked list. (May be null).
-** cmp: A pointer to the comparison function.
-** offset: Offset in the structure to the "next" field.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** of both a and b.
-**
-** Side effects:
-** The "next" pointers for elements in the lists a and b are
-** changed.
-*/
-static char *merge(
- char *a,
- char *b,
- int (*cmp)(const char*,const char*),
- int offset
-){
- char *ptr, *head;
-
- if( a==0 ){
- head = b;
- }else if( b==0 ){
- head = a;
- }else{
- if( (*cmp)(a,b)<=0 ){
- ptr = a;
- a = NEXT(a);
- }else{
- ptr = b;
- b = NEXT(b);
- }
- head = ptr;
- while( a && b ){
- if( (*cmp)(a,b)<=0 ){
- NEXT(ptr) = a;
- ptr = a;
- a = NEXT(a);
- }else{
- NEXT(ptr) = b;
- ptr = b;
- b = NEXT(b);
- }
- }
- if( a ) NEXT(ptr) = a;
- else NEXT(ptr) = b;
- }
- return head;
-}
-
-/*
-** Inputs:
-** list: Pointer to a singly-linked list of structures.
-** next: Pointer to pointer to the second element of the list.
-** cmp: A comparison function.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** orginally in list.
-**
-** Side effects:
-** The "next" pointers for elements in list are changed.
-*/
-#define LISTSIZE 30
-static char *msort(
- char *list,
- char **next,
- int (*cmp)(const char*,const char*)
-){
- unsigned long offset;
- char *ep;
- char *set[LISTSIZE];
- int i;
- offset = (unsigned long)((char*)next - (char*)list);
- for(i=0; i<LISTSIZE; i++) set[i] = 0;
- while( list ){
- ep = list;
- list = NEXT(list);
- NEXT(ep) = 0;
- for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
- ep = merge(ep,set[i],cmp,offset);
- set[i] = 0;
- }
- set[i] = ep;
- }
- ep = 0;
- for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
- return ep;
-}
-/************************ From the file "option.c" **************************/
-static char **argv;
-static struct s_options *op;
-static FILE *errstream;
-
-#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
-
-/*
-** Print the command line with a carrot pointing to the k-th character
-** of the n-th field.
-*/
-static void errline(int n, int k, FILE *err)
-{
- int spcnt, i;
- if( argv[0] ) fprintf(err,"%s",argv[0]);
- spcnt = lemonStrlen(argv[0]) + 1;
- for(i=1; i<n && argv[i]; i++){
- fprintf(err," %s",argv[i]);
- spcnt += lemonStrlen(argv[i])+1;
- }
- spcnt += k;
- for(; argv[i]; i++) fprintf(err," %s",argv[i]);
- if( spcnt<20 ){
- fprintf(err,"\n%*s^-- here\n",spcnt,"");
- }else{
- fprintf(err,"\n%*shere --^\n",spcnt-7,"");
- }
-}
-
-/*
-** Return the index of the N-th non-switch argument. Return -1
-** if N is out of range.
-*/
-static int argindex(int n)
-{
- int i;
- int dashdash = 0;
- if( argv!=0 && *argv!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ){
- if( n==0 ) return i;
- n--;
- }
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return -1;
-}
-
-static char emsg[] = "Command line syntax error: ";
-
-/*
-** Process a flag command line argument.
-*/
-static int handleflags(int i, FILE *err)
-{
- int v;
- int errcnt = 0;
- int j;
- for(j=0; op[j].label; j++){
- if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
- }
- v = argv[i][0]=='-' ? 1 : 0;
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }else if( op[j].arg==0 ){
- /* Ignore this option */
- }else if( op[j].type==OPT_FLAG ){
- *((int*)op[j].arg) = v;
- }else if( op[j].type==OPT_FFLAG ){
- (*(void(*)(int))(op[j].arg))(v);
- }else if( op[j].type==OPT_FSTR ){
- (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
- }else{
- if( err ){
- fprintf(err,"%smissing argument on switch.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }
- return errcnt;
-}
-
-/*
-** Process a command line switch which has an argument.
-*/
-static int handleswitch(int i, FILE *err)
-{
- int lv = 0;
- double dv = 0.0;
- char *sv = 0, *end;
- char *cp;
- int j;
- int errcnt = 0;
- cp = strchr(argv[i],'=');
- assert( cp!=0 );
- *cp = 0;
- for(j=0; op[j].label; j++){
- if( strcmp(argv[i],op[j].label)==0 ) break;
- }
- *cp = '=';
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- }else{
- cp++;
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- if( err ){
- fprintf(err,"%soption requires an argument.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- break;
- case OPT_DBL:
- case OPT_FDBL:
- dv = strtod(cp,&end);
- if( *end ){
- if( err ){
- fprintf(err,
- "%sillegal character in floating-point argument.\n",emsg);
- errline(i,(int)((char*)end-(char*)argv[i]),err);
- }
- errcnt++;
- }
- break;
- case OPT_INT:
- case OPT_FINT:
- lv = strtol(cp,&end,0);
- if( *end ){
- if( err ){
- fprintf(err,"%sillegal character in integer argument.\n",emsg);
- errline(i,(int)((char*)end-(char*)argv[i]),err);
- }
- errcnt++;
- }
- break;
- case OPT_STR:
- case OPT_FSTR:
- sv = cp;
- break;
- }
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_DBL:
- *(double*)(op[j].arg) = dv;
- break;
- case OPT_FDBL:
- (*(void(*)(double))(op[j].arg))(dv);
- break;
- case OPT_INT:
- *(int*)(op[j].arg) = lv;
- break;
- case OPT_FINT:
- (*(void(*)(int))(op[j].arg))((int)lv);
- break;
- case OPT_STR:
- *(char**)(op[j].arg) = sv;
- break;
- case OPT_FSTR:
- (*(void(*)(char *))(op[j].arg))(sv);
- break;
- }
- }
- return errcnt;
-}
-
-int OptInit(char **a, struct s_options *o, FILE *err)
-{
- int errcnt = 0;
- argv = a;
- op = o;
- errstream = err;
- if( argv && *argv && op ){
- int i;
- for(i=1; argv[i]; i++){
- if( argv[i][0]=='+' || argv[i][0]=='-' ){
- errcnt += handleflags(i,err);
- }else if( strchr(argv[i],'=') ){
- errcnt += handleswitch(i,err);
- }
- }
- }
- if( errcnt>0 ){
- fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
- OptPrint();
- exit(1);
- }
- return 0;
-}
-
-int OptNArgs(){
- int cnt = 0;
- int dashdash = 0;
- int i;
- if( argv!=0 && argv[0]!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ) cnt++;
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return cnt;
-}
-
-char *OptArg(int n)
-{
- int i;
- i = argindex(n);
- return i>=0 ? argv[i] : 0;
-}
-
-void OptErr(int n)
-{
- int i;
- i = argindex(n);
- if( i>=0 ) errline(i,0,errstream);
-}
-
-void OptPrint(){
- int i;
- int max, len;
- max = 0;
- for(i=0; op[i].label; i++){
- len = lemonStrlen(op[i].label) + 1;
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_INT:
- case OPT_FINT:
- len += 9; /* length of "<integer>" */
- break;
- case OPT_DBL:
- case OPT_FDBL:
- len += 6; /* length of "<real>" */
- break;
- case OPT_STR:
- case OPT_FSTR:
- len += 8; /* length of "<string>" */
- break;
- }
- if( len>max ) max = len;
- }
- for(i=0; op[i].label; i++){
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
- break;
- case OPT_INT:
- case OPT_FINT:
- fprintf(errstream," -%s<integer>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
- break;
- case OPT_DBL:
- case OPT_FDBL:
- fprintf(errstream," -%s<real>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
- break;
- case OPT_STR:
- case OPT_FSTR:
- fprintf(errstream," -%s<string>%*s %s\n",op[i].label,
- (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
- break;
- }
- }
-}
-/*********************** From the file "parse.c" ****************************/
-/*
-** Input file parser for the LEMON parser generator.
-*/
-
-/* The state of the parser */
-enum e_state {
- INITIALIZE,
- WAITING_FOR_DECL_OR_RULE,
- WAITING_FOR_DECL_KEYWORD,
- WAITING_FOR_DECL_ARG,
- WAITING_FOR_PRECEDENCE_SYMBOL,
- WAITING_FOR_ARROW,
- IN_RHS,
- LHS_ALIAS_1,
- LHS_ALIAS_2,
- LHS_ALIAS_3,
- RHS_ALIAS_1,
- RHS_ALIAS_2,
- PRECEDENCE_MARK_1,
- PRECEDENCE_MARK_2,
- RESYNC_AFTER_RULE_ERROR,
- RESYNC_AFTER_DECL_ERROR,
- WAITING_FOR_DESTRUCTOR_SYMBOL,
- WAITING_FOR_DATATYPE_SYMBOL,
- WAITING_FOR_FALLBACK_ID,
- WAITING_FOR_WILDCARD_ID,
- WAITING_FOR_CLASS_ID,
- WAITING_FOR_CLASS_TOKEN
-};
-struct pstate {
- char *filename; /* Name of the input file */
- int tokenlineno; /* Linenumber at which current token starts */
- int errorcnt; /* Number of errors so far */
- char *tokenstart; /* Text of current token */
- struct lemon *gp; /* Global state vector */
- enum e_state state; /* The state of the parser */
- struct symbol *fallback; /* The fallback token */
- struct symbol *tkclass; /* Token class symbol */
- struct symbol *lhs; /* Left-hand side of current rule */
- const char *lhsalias; /* Alias for the LHS */
- int nrhs; /* Number of right-hand side symbols seen */
- struct symbol *rhs[MAXRHS]; /* RHS symbols */
- const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
- struct rule *prevrule; /* Previous rule parsed */
- const char *declkeyword; /* Keyword of a declaration */
- char **declargslot; /* Where the declaration argument should be put */
- int insertLineMacro; /* Add #line before declaration insert */
- int *decllinenoslot; /* Where to write declaration line number */
- enum e_assoc declassoc; /* Assign this association to decl arguments */
- int preccounter; /* Assign this precedence to decl arguments */
- struct rule *firstrule; /* Pointer to first rule in the grammar */
- struct rule *lastrule; /* Pointer to the most recently parsed rule */
-};
-
-/* Parse a single token */
-static void parseonetoken(struct pstate *psp)
-{
- const char *x;
- x = Strsafe(psp->tokenstart); /* Save the token permanently */
-#if 0
- printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
- x,psp->state);
-#endif
- switch( psp->state ){
- case INITIALIZE:
- psp->prevrule = 0;
- psp->preccounter = 0;
- psp->firstrule = psp->lastrule = 0;
- psp->gp->nrule = 0;
- /* Fall thru to next case */
- case WAITING_FOR_DECL_OR_RULE:
- if( x[0]=='%' ){
- psp->state = WAITING_FOR_DECL_KEYWORD;
- }else if( islower(x[0]) ){
- psp->lhs = Symbol_new(x);
- psp->nrhs = 0;
- psp->lhsalias = 0;
- psp->state = WAITING_FOR_ARROW;
- }else if( x[0]=='{' ){
- if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"There is no prior rule upon which to attach the code \
-fragment which begins on this line.");
- psp->errorcnt++;
- }else if( psp->prevrule->code!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Code fragment beginning on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->line = psp->tokenlineno;
- psp->prevrule->code = &x[1];
- }
- }else if( x[0]=='[' ){
- psp->state = PRECEDENCE_MARK_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Token \"%s\" should be either \"%%\" or a nonterminal name.",
- x);
- psp->errorcnt++;
- }
- break;
- case PRECEDENCE_MARK_1:
- if( !isupper(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "The precedence symbol must be a terminal.");
- psp->errorcnt++;
- }else if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "There is no prior rule to assign precedence \"[%s]\".",x);
- psp->errorcnt++;
- }else if( psp->prevrule->precsym!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Precedence mark on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->precsym = Symbol_new(x);
- }
- psp->state = PRECEDENCE_MARK_2;
- break;
- case PRECEDENCE_MARK_2:
- if( x[0]!=']' ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"]\" on precedence mark.");
- psp->errorcnt++;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- break;
- case WAITING_FOR_ARROW:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else if( x[0]=='(' ){
- psp->state = LHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Expected to see a \":\" following the LHS symbol \"%s\".",
- psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_1:
- if( isalpha(x[0]) ){
- psp->lhsalias = x;
- psp->state = LHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the LHS \"%s\"\n",
- x,psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = LHS_ALIAS_3;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_3:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"->\" following: \"%s(%s)\".",
- psp->lhs->name,psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case IN_RHS:
- if( x[0]=='.' ){
- struct rule *rp;
- rp = (struct rule *)calloc( sizeof(struct rule) +
- sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
- if( rp==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't allocate enough memory for this rule.");
- psp->errorcnt++;
- psp->prevrule = 0;
- }else{
- int i;
- rp->ruleline = psp->tokenlineno;
- rp->rhs = (struct symbol**)&rp[1];
- rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]);
- for(i=0; i<psp->nrhs; i++){
- rp->rhs[i] = psp->rhs[i];
- rp->rhsalias[i] = psp->alias[i];
- }
- rp->lhs = psp->lhs;
- rp->lhsalias = psp->lhsalias;
- rp->nrhs = psp->nrhs;
- rp->code = 0;
- rp->precsym = 0;
- rp->index = psp->gp->nrule++;
- rp->nextlhs = rp->lhs->rule;
- rp->lhs->rule = rp;
- rp->next = 0;
- if( psp->firstrule==0 ){
- psp->firstrule = psp->lastrule = rp;
- }else{
- psp->lastrule->next = rp;
- psp->lastrule = rp;
- }
- psp->prevrule = rp;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( isalpha(x[0]) ){
- if( psp->nrhs>=MAXRHS ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Too many symbols on RHS of rule beginning at \"%s\".",
- x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }else{
- psp->rhs[psp->nrhs] = Symbol_new(x);
- psp->alias[psp->nrhs] = 0;
- psp->nrhs++;
- }
- }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
- struct symbol *msp = psp->rhs[psp->nrhs-1];
- if( msp->type!=MULTITERMINAL ){
- struct symbol *origsp = msp;
- msp = (struct symbol *) calloc(1,sizeof(*msp));
- memset(msp, 0, sizeof(*msp));
- msp->type = MULTITERMINAL;
- msp->nsubsym = 1;
- msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
- msp->subsym[0] = origsp;
- msp->name = origsp->name;
- psp->rhs[psp->nrhs-1] = msp;
- }
- msp->nsubsym++;
- msp->subsym = (struct symbol **) realloc(msp->subsym,
- sizeof(struct symbol*)*msp->nsubsym);
- msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
- if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Cannot form a compound containing a non-terminal");
- psp->errorcnt++;
- }
- }else if( x[0]=='(' && psp->nrhs>0 ){
- psp->state = RHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal character on RHS of rule: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_1:
- if( isalpha(x[0]) ){
- psp->alias[psp->nrhs-1] = x;
- psp->state = RHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
- x,psp->rhs[psp->nrhs-1]->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case WAITING_FOR_DECL_KEYWORD:
- if( isalpha(x[0]) ){
- psp->declkeyword = x;
- psp->declargslot = 0;
- psp->decllinenoslot = 0;
- psp->insertLineMacro = 1;
- psp->state = WAITING_FOR_DECL_ARG;
- if( strcmp(x,"name")==0 ){
- psp->declargslot = &(psp->gp->name);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"include")==0 ){
- psp->declargslot = &(psp->gp->include);
- }else if( strcmp(x,"code")==0 ){
- psp->declargslot = &(psp->gp->extracode);
- }else if( strcmp(x,"token_destructor")==0 ){
- psp->declargslot = &psp->gp->tokendest;
- }else if( strcmp(x,"default_destructor")==0 ){
- psp->declargslot = &psp->gp->vardest;
- }else if( strcmp(x,"token_prefix")==0 ){
- psp->declargslot = &psp->gp->tokenprefix;
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"syntax_error")==0 ){
- psp->declargslot = &(psp->gp->error);
- }else if( strcmp(x,"parse_accept")==0 ){
- psp->declargslot = &(psp->gp->accept);
- }else if( strcmp(x,"parse_failure")==0 ){
- psp->declargslot = &(psp->gp->failure);
- }else if( strcmp(x,"stack_overflow")==0 ){
- psp->declargslot = &(psp->gp->overflow);
- }else if( strcmp(x,"extra_argument")==0 ){
- psp->declargslot = &(psp->gp->arg);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"token_type")==0 ){
- psp->declargslot = &(psp->gp->tokentype);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"default_type")==0 ){
- psp->declargslot = &(psp->gp->vartype);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"stack_size")==0 ){
- psp->declargslot = &(psp->gp->stacksize);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"start_symbol")==0 ){
- psp->declargslot = &(psp->gp->start);
- psp->insertLineMacro = 0;
- }else if( strcmp(x,"left")==0 ){
- psp->preccounter++;
- psp->declassoc = LEFT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"right")==0 ){
- psp->preccounter++;
- psp->declassoc = RIGHT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"nonassoc")==0 ){
- psp->preccounter++;
- psp->declassoc = NONE;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"destructor")==0 ){
- psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
- }else if( strcmp(x,"type")==0 ){
- psp->state = WAITING_FOR_DATATYPE_SYMBOL;
- }else if( strcmp(x,"fallback")==0 ){
- psp->fallback = 0;
- psp->state = WAITING_FOR_FALLBACK_ID;
- }else if( strcmp(x,"wildcard")==0 ){
- psp->state = WAITING_FOR_WILDCARD_ID;
- }else if( strcmp(x,"token_class")==0 ){
- psp->state = WAITING_FOR_CLASS_ID;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Unknown declaration keyword: \"%%%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal declaration keyword: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_DESTRUCTOR_SYMBOL:
- if( !isalpha(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %%destructor keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_new(x);
- psp->declargslot = &sp->destructor;
- psp->decllinenoslot = &sp->destLineno;
- psp->insertLineMacro = 1;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- break;
- case WAITING_FOR_DATATYPE_SYMBOL:
- if( !isalpha(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %%type keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_find(x);
- if((sp) && (sp->datatype)){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol %%type \"%s\" already defined", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- if (!sp){
- sp = Symbol_new(x);
- }
- psp->declargslot = &sp->datatype;
- psp->insertLineMacro = 0;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- }
- break;
- case WAITING_FOR_PRECEDENCE_SYMBOL:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( isupper(x[0]) ){
- struct symbol *sp;
- sp = Symbol_new(x);
- if( sp->prec>=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol \"%s\" has already be given a precedence.",x);
- psp->errorcnt++;
- }else{
- sp->prec = psp->preccounter;
- sp->assoc = psp->declassoc;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't assign a precedence to \"%s\".",x);
- psp->errorcnt++;
- }
- break;
- case WAITING_FOR_DECL_ARG:
- if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){
- const char *zOld, *zNew;
- char *zBuf, *z;
- int nOld, n, nLine = 0, nNew, nBack;
- int addLineMacro;
- char zLine[50];
- zNew = x;
- if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
- nNew = lemonStrlen(zNew);
- if( *psp->declargslot ){
- zOld = *psp->declargslot;
- }else{
- zOld = "";
- }
- nOld = lemonStrlen(zOld);
- n = nOld + nNew + 20;
- addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
- (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
- if( addLineMacro ){
- for(z=psp->filename, nBack=0; *z; z++){
- if( *z=='\\' ) nBack++;
- }
- lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
- nLine = lemonStrlen(zLine);
- n += nLine + lemonStrlen(psp->filename) + nBack;
- }
- *psp->declargslot = (char *) realloc(*psp->declargslot, n);
- zBuf = *psp->declargslot + nOld;
- if( addLineMacro ){
- if( nOld && zBuf[-1]!='\n' ){
- *(zBuf++) = '\n';
- }
- memcpy(zBuf, zLine, nLine);
- zBuf += nLine;
- *(zBuf++) = '"';
- for(z=psp->filename; *z; z++){
- if( *z=='\\' ){
- *(zBuf++) = '\\';
- }
- *(zBuf++) = *z;
- }
- *(zBuf++) = '"';
- *(zBuf++) = '\n';
- }
- if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){
- psp->decllinenoslot[0] = psp->tokenlineno;
- }
- memcpy(zBuf, zNew, nNew);
- zBuf += nNew;
- *zBuf = 0;
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal argument to %%%s: %s",psp->declkeyword,x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_FALLBACK_ID:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !isupper(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%fallback argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- struct symbol *sp = Symbol_new(x);
- if( psp->fallback==0 ){
- psp->fallback = sp;
- }else if( sp->fallback ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "More than one fallback assigned to token %s", x);
- psp->errorcnt++;
- }else{
- sp->fallback = psp->fallback;
- psp->gp->has_fallback = 1;
- }
- }
- break;
- case WAITING_FOR_WILDCARD_ID:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !isupper(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%wildcard argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- struct symbol *sp = Symbol_new(x);
- if( psp->gp->wildcard==0 ){
- psp->gp->wildcard = sp;
- }else{
- ErrorMsg(psp->filename, psp->tokenlineno,
- "Extra wildcard to token: %s", x);
- psp->errorcnt++;
- }
- }
- break;
- case WAITING_FOR_CLASS_ID:
- if( !islower(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token_class must be followed by an identifier: ", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else if( Symbol_find(x) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "Symbol \"%s\" already used", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- psp->tkclass = Symbol_new(x);
- psp->tkclass->type = MULTITERMINAL;
- psp->state = WAITING_FOR_CLASS_TOKEN;
- }
- break;
- case WAITING_FOR_CLASS_TOKEN:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){
- struct symbol *msp = psp->tkclass;
- msp->nsubsym++;
- msp->subsym = (struct symbol **) realloc(msp->subsym,
- sizeof(struct symbol*)*msp->nsubsym);
- if( !isupper(x[0]) ) x++;
- msp->subsym[msp->nsubsym-1] = Symbol_new(x);
- }else{
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token_class argument \"%s\" should be a token", x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case RESYNC_AFTER_RULE_ERROR:
-/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
-** break; */
- case RESYNC_AFTER_DECL_ERROR:
- if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
- if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
- break;
- }
-}
-
-/* Run the preprocessor over the input file text. The global variables
-** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
-** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
-** comments them out. Text in between is also commented out as appropriate.
-*/
-static void preprocess_input(char *z){
- int i, j, k, n;
- int exclude = 0;
- int start = 0;
- int lineno = 1;
- int start_lineno = 1;
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) lineno++;
- if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
- if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){
- if( exclude ){
- exclude--;
- if( exclude==0 ){
- for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
- }
- }
- for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
- }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6]))
- || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){
- if( exclude ){
- exclude++;
- }else{
- for(j=i+7; isspace(z[j]); j++){}
- for(n=0; z[j+n] && !isspace(z[j+n]); n++){}
- exclude = 1;
- for(k=0; k<nDefine; k++){
- if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
- exclude = 0;
- break;
- }
- }
- if( z[i+3]=='n' ) exclude = !exclude;
- if( exclude ){
- start = i;
- start_lineno = lineno;
- }
- }
- for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
- }
- }
- if( exclude ){
- fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
- exit(1);
- }
-}
-
-/* In spite of its name, this function is really a scanner. It read
-** in the entire input file (all at once) then tokenizes it. Each
-** token is passed to the function "parseonetoken" which builds all
-** the appropriate data structures in the global state vector "gp".
-*/
-void Parse(struct lemon *gp)
-{
- struct pstate ps;
- FILE *fp;
- char *filebuf;
- unsigned int filesize;
- int lineno;
- int c;
- char *cp, *nextcp;
- int startline = 0;
-
- memset(&ps, '\0', sizeof(ps));
- ps.gp = gp;
- ps.filename = gp->filename;
- ps.errorcnt = 0;
- ps.state = INITIALIZE;
-
- /* Begin by reading the input file */
- fp = fopen(ps.filename,"rb");
- if( fp==0 ){
- ErrorMsg(ps.filename,0,"Can't open this file for reading.");
- gp->errorcnt++;
- return;
- }
- fseek(fp,0,2);
- filesize = ftell(fp);
- rewind(fp);
- filebuf = (char *)malloc( filesize+1 );
- if( filesize>100000000 || filebuf==0 ){
- ErrorMsg(ps.filename,0,"Input file too large.");
- gp->errorcnt++;
- fclose(fp);
- return;
- }
- if( fread(filebuf,1,filesize,fp)!=filesize ){
- ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
- filesize);
- free(filebuf);
- gp->errorcnt++;
- fclose(fp);
- return;
- }
- fclose(fp);
- filebuf[filesize] = 0;
-
- /* Make an initial pass through the file to handle %ifdef and %ifndef */
- preprocess_input(filebuf);
-
- /* Now scan the text of the input file */
- lineno = 1;
- for(cp=filebuf; (c= *cp)!=0; ){
- if( c=='\n' ) lineno++; /* Keep track of the line number */
- if( isspace(c) ){ cp++; continue; } /* Skip all white space */
- if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
- cp+=2;
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- continue;
- }
- if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
- cp+=2;
- while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c ) cp++;
- continue;
- }
- ps.tokenstart = cp; /* Mark the beginning of the token */
- ps.tokenlineno = lineno; /* Linenumber on which token begins */
- if( c=='\"' ){ /* String literals */
- cp++;
- while( (c= *cp)!=0 && c!='\"' ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c==0 ){
- ErrorMsg(ps.filename,startline,
-"String starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( c=='{' ){ /* A block of C code */
- int level;
- cp++;
- for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
- if( c=='\n' ) lineno++;
- else if( c=='{' ) level++;
- else if( c=='}' ) level--;
- else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
- int prevc;
- cp = &cp[2];
- prevc = 0;
- while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
- if( c=='\n' ) lineno++;
- prevc = c;
- cp++;
- }
- }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
- cp = &cp[2];
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- if( c ) lineno++;
- }else if( c=='\'' || c=='\"' ){ /* String a character literals */
- int startchar, prevc;
- startchar = c;
- prevc = 0;
- for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
- if( c=='\n' ) lineno++;
- if( prevc=='\\' ) prevc = 0;
- else prevc = c;
- }
- }
- }
- if( c==0 ){
- ErrorMsg(ps.filename,ps.tokenlineno,
-"C code starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( isalnum(c) ){ /* Identifiers */
- while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
- nextcp = cp;
- }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
- cp += 3;
- nextcp = cp;
- }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){
- cp += 2;
- while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
- nextcp = cp;
- }else{ /* All other (one character) operators */
- cp++;
- nextcp = cp;
- }
- c = *cp;
- *cp = 0; /* Null terminate the token */
- parseonetoken(&ps); /* Parse the token */
- *cp = (char)c; /* Restore the buffer */
- cp = nextcp;
- }
- free(filebuf); /* Release the buffer after parsing */
- gp->rule = ps.firstrule;
- gp->errorcnt = ps.errorcnt;
-}
-/*************************** From the file "plink.c" *********************/
-/*
-** Routines processing configuration follow-set propagation links
-** in the LEMON parser generator.
-*/
-static struct plink *plink_freelist = 0;
-
-/* Allocate a new plink */
-struct plink *Plink_new(){
- struct plink *newlink;
-
- if( plink_freelist==0 ){
- int i;
- int amt = 100;
- plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
- if( plink_freelist==0 ){
- fprintf(stderr,
- "Unable to allocate memory for a new follow-set propagation link.\n");
- exit(1);
- }
- for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
- plink_freelist[amt-1].next = 0;
- }
- newlink = plink_freelist;
- plink_freelist = plink_freelist->next;
- return newlink;
-}
-
-/* Add a plink to a plink list */
-void Plink_add(struct plink **plpp, struct config *cfp)
-{
- struct plink *newlink;
- newlink = Plink_new();
- newlink->next = *plpp;
- *plpp = newlink;
- newlink->cfp = cfp;
-}
-
-/* Transfer every plink on the list "from" to the list "to" */
-void Plink_copy(struct plink **to, struct plink *from)
-{
- struct plink *nextpl;
- while( from ){
- nextpl = from->next;
- from->next = *to;
- *to = from;
- from = nextpl;
- }
-}
-
-/* Delete every plink on the list */
-void Plink_delete(struct plink *plp)
-{
- struct plink *nextpl;
-
- while( plp ){
- nextpl = plp->next;
- plp->next = plink_freelist;
- plink_freelist = plp;
- plp = nextpl;
- }
-}
-/*********************** From the file "report.c" **************************/
-/*
-** Procedures for generating reports and tables in the LEMON parser generator.
-*/
-
-/* Generate a filename with the given suffix. Space to hold the
-** name comes from malloc() and must be freed by the calling
-** function.
-*/
-PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
-{
- char *name;
- char *cp;
-
- name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
- if( name==0 ){
- fprintf(stderr,"Can't allocate space for a filename.\n");
- exit(1);
- }
- lemon_strcpy(name,lemp->filename);
- cp = strrchr(name,'.');
- if( cp ) *cp = 0;
- lemon_strcat(name,suffix);
- return name;
-}
-
-/* Open a file with a name based on the name of the input file,
-** but with a different (specified) suffix, and return a pointer
-** to the stream */
-PRIVATE FILE *file_open(
- struct lemon *lemp,
- const char *suffix,
- const char *mode
-){
- FILE *fp;
-
- if( lemp->outname ) free(lemp->outname);
- lemp->outname = file_makename(lemp, suffix);
- fp = fopen(lemp->outname,mode);
- if( fp==0 && *mode=='w' ){
- fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
- lemp->errorcnt++;
- return 0;
- }
- return fp;
-}
-
-/* Duplicate the input file without comments and without actions
-** on rules */
-void Reprint(struct lemon *lemp)
-{
- struct rule *rp;
- struct symbol *sp;
- int i, j, maxlen, len, ncolumns, skip;
- printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
- maxlen = 10;
- for(i=0; i<lemp->nsymbol; i++){
- sp = lemp->symbols[i];
- len = lemonStrlen(sp->name);
- if( len>maxlen ) maxlen = len;
- }
- ncolumns = 76/(maxlen+5);
- if( ncolumns<1 ) ncolumns = 1;
- skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
- for(i=0; i<skip; i++){
- printf("//");
- for(j=i; j<lemp->nsymbol; j+=skip){
- sp = lemp->symbols[j];
- assert( sp->index==j );
- printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
- }
- printf("\n");
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- printf("%s",rp->lhs->name);
- /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
- printf(" ::=");
- for(i=0; i<rp->nrhs; i++){
- sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- printf(" %s", sp->subsym[0]->name);
- for(j=1; j<sp->nsubsym; j++){
- printf("|%s", sp->subsym[j]->name);
- }
- }else{
- printf(" %s", sp->name);
- }
- /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
- }
- printf(".");
- if( rp->precsym ) printf(" [%s]",rp->precsym->name);
- /* if( rp->code ) printf("\n %s",rp->code); */
- printf("\n");
- }
-}
-
-/* Print a single rule.
-*/
-void RulePrint(FILE *fp, struct rule *rp, int iCursor){
- struct symbol *sp;
- int i, j;
- fprintf(fp,"%s ::=",rp->lhs->name);
- for(i=0; i<=rp->nrhs; i++){
- if( i==iCursor ) fprintf(fp," *");
- if( i==rp->nrhs ) break;
- sp = rp->rhs[i];
- if( sp->type==MULTITERMINAL ){
- fprintf(fp," %s", sp->subsym[0]->name);
- for(j=1; j<sp->nsubsym; j++){
- fprintf(fp,"|%s",sp->subsym[j]->name);
- }
- }else{
- fprintf(fp," %s", sp->name);
- }
- }
-}
-
-/* Print the rule for a configuration.
-*/
-void ConfigPrint(FILE *fp, struct config *cfp){
- RulePrint(fp, cfp->rp, cfp->dot);
-}
-
-/* #define TEST */
-#if 0
-/* Print a set */
-PRIVATE void SetPrint(out,set,lemp)
-FILE *out;
-char *set;
-struct lemon *lemp;
-{
- int i;
- char *spacer;
- spacer = "";
- fprintf(out,"%12s[","");
- for(i=0; i<lemp->nterminal; i++){
- if( SetFind(set,i) ){
- fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
- spacer = " ";
- }
- }
- fprintf(out,"]\n");
-}
-
-/* Print a plink chain */
-PRIVATE void PlinkPrint(out,plp,tag)
-FILE *out;
-struct plink *plp;
-char *tag;
-{
- while( plp ){
- fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
- ConfigPrint(out,plp->cfp);
- fprintf(out,"\n");
- plp = plp->next;
- }
-}
-#endif
-
-/* Print an action to the given file descriptor. Return FALSE if
-** nothing was actually printed.
-*/
-int PrintAction(
- struct action *ap, /* The action to print */
- FILE *fp, /* Print the action here */
- int indent /* Indent by this amount */
-){
- int result = 1;
- switch( ap->type ){
- case SHIFT: {
- struct state *stp = ap->x.stp;
- fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum);
- break;
- }
- case REDUCE: {
- struct rule *rp = ap->x.rp;
- fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index);
- RulePrint(fp, rp, -1);
- break;
- }
- case SHIFTREDUCE: {
- struct rule *rp = ap->x.rp;
- fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index);
- RulePrint(fp, rp, -1);
- break;
- }
- case ACCEPT:
- fprintf(fp,"%*s accept",indent,ap->sp->name);
- break;
- case ERROR:
- fprintf(fp,"%*s error",indent,ap->sp->name);
- break;
- case SRCONFLICT:
- case RRCONFLICT:
- fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
- indent,ap->sp->name,ap->x.rp->index);
- break;
- case SSCONFLICT:
- fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
- indent,ap->sp->name,ap->x.stp->statenum);
- break;
- case SH_RESOLVED:
- if( showPrecedenceConflict ){
- fprintf(fp,"%*s shift %-7d -- dropped by precedence",
- indent,ap->sp->name,ap->x.stp->statenum);
- }else{
- result = 0;
- }
- break;
- case RD_RESOLVED:
- if( showPrecedenceConflict ){
- fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
- indent,ap->sp->name,ap->x.rp->index);
- }else{
- result = 0;
- }
- break;
- case NOT_USED:
- result = 0;
- break;
- }
- return result;
-}
-
-/* Generate the "*.out" log file */
-void ReportOutput(struct lemon *lemp)
-{
- int i;
- struct state *stp;
- struct config *cfp;
- struct action *ap;
- FILE *fp;
-
- fp = file_open(lemp,".out","wb");
- if( fp==0 ) return;
- for(i=0; i<lemp->nxstate; i++){
- stp = lemp->sorted[i];
- fprintf(fp,"State %d:\n",stp->statenum);
- if( lemp->basisflag ) cfp=stp->bp;
- else cfp=stp->cfp;
- while( cfp ){
- char buf[20];
- if( cfp->dot==cfp->rp->nrhs ){
- lemon_sprintf(buf,"(%d)",cfp->rp->index);
- fprintf(fp," %5s ",buf);
- }else{
- fprintf(fp," ");
- }
- ConfigPrint(fp,cfp);
- fprintf(fp,"\n");
-#if 0
- SetPrint(fp,cfp->fws,lemp);
- PlinkPrint(fp,cfp->fplp,"To ");
- PlinkPrint(fp,cfp->bplp,"From");
-#endif
- if( lemp->basisflag ) cfp=cfp->bp;
- else cfp=cfp->next;
- }
- fprintf(fp,"\n");
- for(ap=stp->ap; ap; ap=ap->next){
- if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
- }
- fprintf(fp,"\n");
- }
- fprintf(fp, "----------------------------------------------------\n");
- fprintf(fp, "Symbols:\n");
- for(i=0; i<lemp->nsymbol; i++){
- int j;
- struct symbol *sp;
-
- sp = lemp->symbols[i];
- fprintf(fp, " %3d: %s", i, sp->name);
- if( sp->type==NONTERMINAL ){
- fprintf(fp, ":");
- if( sp->lambda ){
- fprintf(fp, " <lambda>");
- }
- for(j=0; j<lemp->nterminal; j++){
- if( sp->firstset && SetFind(sp->firstset, j) ){
- fprintf(fp, " %s", lemp->symbols[j]->name);
- }
- }
- }
- fprintf(fp, "\n");
- }
- fclose(fp);
- return;
-}
-
-/* Search for the file "name" which is in the same directory as
-** the exacutable */
-PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
-{
- const char *pathlist;
- char *pathbufptr;
- char *pathbuf;
- char *path,*cp;
- char c;
-
-#ifdef __WIN32__
- cp = strrchr(argv0,'\\');
-#else
- cp = strrchr(argv0,'/');
-#endif
- if( cp ){
- c = *cp;
- *cp = 0;
- path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
- if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
- *cp = c;
- }else{
- pathlist = getenv("PATH");
- if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
- pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
- path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
- if( (pathbuf != 0) && (path!=0) ){
- pathbufptr = pathbuf;
- lemon_strcpy(pathbuf, pathlist);
- while( *pathbuf ){
- cp = strchr(pathbuf,':');
- if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
- c = *cp;
- *cp = 0;
- lemon_sprintf(path,"%s/%s",pathbuf,name);
- *cp = c;
- if( c==0 ) pathbuf[0] = 0;
- else pathbuf = &cp[1];
- if( access(path,modemask)==0 ) break;
- }
- free(pathbufptr);
- }
- }
- return path;
-}
-
-/* Given an action, compute the integer value for that action
-** which is to be put in the action table of the generated machine.
-** Return negative if no action should be generated.
-*/
-PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
-{
- int act;
- switch( ap->type ){
- case SHIFT: act = ap->x.stp->statenum; break;
- case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break;
- case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break;
- case ERROR: act = lemp->nstate + lemp->nrule*2; break;
- case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break;
- default: act = -1; break;
- }
- return act;
-}
-
-#define LINESIZE 1000
-/* The next cluster of routines are for reading the template file
-** and writing the results to the generated parser */
-/* The first function transfers data from "in" to "out" until
-** a line is seen which begins with "%%". The line number is
-** tracked.
-**
-** if name!=0, then any word that begin with "Parse" is changed to
-** begin with *name instead.
-*/
-PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
-{
- int i, iStart;
- char line[LINESIZE];
- while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
- (*lineno)++;
- iStart = 0;
- if( name ){
- for(i=0; line[i]; i++){
- if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
- && (i==0 || !isalpha(line[i-1]))
- ){
- if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
- fprintf(out,"%s",name);
- i += 4;
- iStart = i+1;
- }
- }
- }
- fprintf(out,"%s",&line[iStart]);
- }
-}
-
-/* The next function finds the template file and opens it, returning
-** a pointer to the opened file. */
-PRIVATE FILE *tplt_open(struct lemon *lemp)
-{
- static char templatename[] = "lempar.c";
- char buf[1000];
- FILE *in;
- char *tpltname;
- char *cp;
-
- /* first, see if user specified a template filename on the command line. */
- if (user_templatename != 0) {
- if( access(user_templatename,004)==-1 ){
- fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
- user_templatename);
- lemp->errorcnt++;
- return 0;
- }
- in = fopen(user_templatename,"rb");
- if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",
- user_templatename);
- lemp->errorcnt++;
- return 0;
- }
- return in;
- }
-
- cp = strrchr(lemp->filename,'.');
- if( cp ){
- lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
- }else{
- lemon_sprintf(buf,"%s.lt",lemp->filename);
- }
- if( access(buf,004)==0 ){
- tpltname = buf;
- }else if( access(templatename,004)==0 ){
- tpltname = templatename;
- }else{
- tpltname = pathsearch(lemp->argv0,templatename,0);
- }
- if( tpltname==0 ){
- fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
- templatename);
- lemp->errorcnt++;
- return 0;
- }
- in = fopen(tpltname,"rb");
- if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
- lemp->errorcnt++;
- return 0;
- }
- return in;
-}
-
-/* Print a #line directive line to the output file. */
-PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
-{
- fprintf(out,"#line %d \"",lineno);
- while( *filename ){
- if( *filename == '\\' ) putc('\\',out);
- putc(*filename,out);
- filename++;
- }
- fprintf(out,"\"\n");
-}
-
-/* Print a string to the file and keep the linenumber up to date */
-PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
-{
- if( str==0 ) return;
- while( *str ){
- putc(*str,out);
- if( *str=='\n' ) (*lineno)++;
- str++;
- }
- if( str[-1]!='\n' ){
- putc('\n',out);
- (*lineno)++;
- }
- if (!lemp->nolinenosflag) {
- (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
- }
- return;
-}
-
-/*
-** The following routine emits code for the destructor for the
-** symbol sp
-*/
-void emit_destructor_code(
- FILE *out,
- struct symbol *sp,
- struct lemon *lemp,
- int *lineno
-){
- char *cp = 0;
-
- if( sp->type==TERMINAL ){
- cp = lemp->tokendest;
- if( cp==0 ) return;
- fprintf(out,"{\n"); (*lineno)++;
- }else if( sp->destructor ){
- cp = sp->destructor;
- fprintf(out,"{\n"); (*lineno)++;
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,sp->destLineno,lemp->filename);
- }
- }else if( lemp->vardest ){
- cp = lemp->vardest;
- if( cp==0 ) return;
- fprintf(out,"{\n"); (*lineno)++;
- }else{
- assert( 0 ); /* Cannot happen */
- }
- for(; *cp; cp++){
- if( *cp=='$' && cp[1]=='$' ){
- fprintf(out,"(yypminor->yy%d)",sp->dtnum);
- cp++;
- continue;
- }
- if( *cp=='\n' ) (*lineno)++;
- fputc(*cp,out);
- }
- fprintf(out,"\n"); (*lineno)++;
- if (!lemp->nolinenosflag) {
- (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
- }
- fprintf(out,"}\n"); (*lineno)++;
- return;
-}
-
-/*
-** Return TRUE (non-zero) if the given symbol has a destructor.
-*/
-int has_destructor(struct symbol *sp, struct lemon *lemp)
-{
- int ret;
- if( sp->type==TERMINAL ){
- ret = lemp->tokendest!=0;
- }else{
- ret = lemp->vardest!=0 || sp->destructor!=0;
- }
- return ret;
-}
-
-/*
-** Append text to a dynamically allocated string. If zText is 0 then
-** reset the string to be empty again. Always return the complete text
-** of the string (which is overwritten with each call).
-**
-** n bytes of zText are stored. If n==0 then all of zText up to the first
-** \000 terminator is stored. zText can contain up to two instances of
-** %d. The values of p1 and p2 are written into the first and second
-** %d.
-**
-** If n==-1, then the previous character is overwritten.
-*/
-PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
- static char empty[1] = { 0 };
- static char *z = 0;
- static int alloced = 0;
- static int used = 0;
- int c;
- char zInt[40];
- if( zText==0 ){
- used = 0;
- return z;
- }
- if( n<=0 ){
- if( n<0 ){
- used += n;
- assert( used>=0 );
- }
- n = lemonStrlen(zText);
- }
- if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
- alloced = n + sizeof(zInt)*2 + used + 200;
- z = (char *) realloc(z, alloced);
- }
- if( z==0 ) return empty;
- while( n-- > 0 ){
- c = *(zText++);
- if( c=='%' && n>0 && zText[0]=='d' ){
- lemon_sprintf(zInt, "%d", p1);
- p1 = p2;
- lemon_strcpy(&z[used], zInt);
- used += lemonStrlen(&z[used]);
- zText++;
- n--;
- }else{
- z[used++] = (char)c;
- }
- }
- z[used] = 0;
- return z;
-}
-
-/*
-** zCode is a string that is the action associated with a rule. Expand
-** the symbols in this string so that the refer to elements of the parser
-** stack.
-*/
-PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
- char *cp, *xp;
- int i;
- char lhsused = 0; /* True if the LHS element has been used */
- char used[MAXRHS]; /* True for each RHS element which is used */
-
- for(i=0; i<rp->nrhs; i++) used[i] = 0;
- lhsused = 0;
-
- if( rp->code==0 ){
- static char newlinestr[2] = { '\n', '\0' };
- rp->code = newlinestr;
- rp->line = rp->ruleline;
- }
-
- append_str(0,0,0,0);
-
- /* This const cast is wrong but harmless, if we're careful. */
- for(cp=(char *)rp->code; *cp; cp++){
- if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
- char saved;
- for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
- saved = *xp;
- *xp = 0;
- if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
- append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0);
- cp = xp;
- lhsused = 1;
- }else{
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
- if( cp!=rp->code && cp[-1]=='@' ){
- /* If the argument is of the form @X then substituted
- ** the token number of X, not the value of X */
- append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
- }else{
- struct symbol *sp = rp->rhs[i];
- int dtnum;
- if( sp->type==MULTITERMINAL ){
- dtnum = sp->subsym[0]->dtnum;
- }else{
- dtnum = sp->dtnum;
- }
- append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
- }
- cp = xp;
- used[i] = 1;
- break;
- }
- }
- }
- *xp = saved;
- }
- append_str(cp, 1, 0, 0);
- } /* End loop */
-
- /* Check to make sure the LHS has been used */
- if( rp->lhsalias && !lhsused ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label \"%s\" for \"%s(%s)\" is never used.",
- rp->lhsalias,rp->lhs->name,rp->lhsalias);
- lemp->errorcnt++;
- }
-
- /* Generate destructor code for RHS symbols which are not used in the
- ** reduce code */
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] && !used[i] ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label %s for \"%s(%s)\" is never used.",
- rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
- lemp->errorcnt++;
- }else if( rp->rhsalias[i]==0 ){
- if( has_destructor(rp->rhs[i],lemp) ){
- append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
- rp->rhs[i]->index,i-rp->nrhs+1);
- }else{
- /* No destructor defined for this term */
- }
- }
- }
- if( rp->code ){
- cp = append_str(0,0,0,0);
- rp->code = Strsafe(cp?cp:"");
- }
-}
-
-/*
-** Generate code which executes when the rule "rp" is reduced. Write
-** the code to "out". Make sure lineno stays up-to-date.
-*/
-PRIVATE void emit_code(
- FILE *out,
- struct rule *rp,
- struct lemon *lemp,
- int *lineno
-){
- const char *cp;
-
- /* Generate code to do the reduce action */
- if( rp->code ){
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,rp->line,lemp->filename);
- }
- fprintf(out,"{%s",rp->code);
- for(cp=rp->code; *cp; cp++){
- if( *cp=='\n' ) (*lineno)++;
- } /* End loop */
- fprintf(out,"}\n"); (*lineno)++;
- if( !lemp->nolinenosflag ){
- (*lineno)++;
- tplt_linedir(out,*lineno,lemp->outname);
- }
- } /* End if( rp->code ) */
-
- return;
-}
-
-/*
-** Print the definition of the union used for the parser's data stack.
-** This union contains fields for every possible data type for tokens
-** and nonterminals. In the process of computing and printing this
-** union, also set the ".dtnum" field of every terminal and nonterminal
-** symbol.
-*/
-void print_stack_union(
- FILE *out, /* The output stream */
- struct lemon *lemp, /* The main info structure for this parser */
- int *plineno, /* Pointer to the line number */
- int mhflag /* True if generating makeheaders output */
-){
- int lineno = *plineno; /* The line number of the output */
- char **types; /* A hash table of datatypes */
- int arraysize; /* Size of the "types" array */
- int maxdtlength; /* Maximum length of any ".datatype" field. */
- char *stddt; /* Standardized name for a datatype */
- int i,j; /* Loop counters */
- unsigned hash; /* For hashing the name of a type */
- const char *name; /* Name of the parser */
-
- /* Allocate and initialize types[] and allocate stddt[] */
- arraysize = lemp->nsymbol * 2;
- types = (char**)calloc( arraysize, sizeof(char*) );
- if( types==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
- for(i=0; i<arraysize; i++) types[i] = 0;
- maxdtlength = 0;
- if( lemp->vartype ){
- maxdtlength = lemonStrlen(lemp->vartype);
- }
- for(i=0; i<lemp->nsymbol; i++){
- int len;
- struct symbol *sp = lemp->symbols[i];
- if( sp->datatype==0 ) continue;
- len = lemonStrlen(sp->datatype);
- if( len>maxdtlength ) maxdtlength = len;
- }
- stddt = (char*)malloc( maxdtlength*2 + 1 );
- if( stddt==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
-
- /* Build a hash table of datatypes. The ".dtnum" field of each symbol
- ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
- ** used for terminal symbols. If there is no %default_type defined then
- ** 0 is also used as the .dtnum value for nonterminals which do not specify
- ** a datatype using the %type directive.
- */
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- char *cp;
- if( sp==lemp->errsym ){
- sp->dtnum = arraysize+1;
- continue;
- }
- if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
- sp->dtnum = 0;
- continue;
- }
- cp = sp->datatype;
- if( cp==0 ) cp = lemp->vartype;
- j = 0;
- while( isspace(*cp) ) cp++;
- while( *cp ) stddt[j++] = *cp++;
- while( j>0 && isspace(stddt[j-1]) ) j--;
- stddt[j] = 0;
- if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){
- sp->dtnum = 0;
- continue;
- }
- hash = 0;
- for(j=0; stddt[j]; j++){
- hash = hash*53 + stddt[j];
- }
- hash = (hash & 0x7fffffff)%arraysize;
- while( types[hash] ){
- if( strcmp(types[hash],stddt)==0 ){
- sp->dtnum = hash + 1;
- break;
- }
- hash++;
- if( hash>=(unsigned)arraysize ) hash = 0;
- }
- if( types[hash]==0 ){
- sp->dtnum = hash + 1;
- types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
- if( types[hash]==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
- lemon_strcpy(types[hash],stddt);
- }
- }
-
- /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
- name = lemp->name ? lemp->name : "Parse";
- lineno = *plineno;
- if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
- fprintf(out,"#define %sTOKENTYPE %s\n",name,
- lemp->tokentype?lemp->tokentype:"void*"); lineno++;
- if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
- fprintf(out,"typedef union {\n"); lineno++;
- fprintf(out," int yyinit;\n"); lineno++;
- fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
- for(i=0; i<arraysize; i++){
- if( types[i]==0 ) continue;
- fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
- free(types[i]);
- }
- if( lemp->errsym->useCnt ){
- fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
- }
- free(stddt);
- free(types);
- fprintf(out,"} YYMINORTYPE;\n"); lineno++;
- *plineno = lineno;
-}
-
-/*
-** Return the name of a C datatype able to represent values between
-** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof
-** for that type (1, 2, or 4) into *pnByte.
-*/
-static const char *minimum_size_type(int lwr, int upr, int *pnByte){
- const char *zType = "int";
- int nByte = 4;
- if( lwr>=0 ){
- if( upr<=255 ){
- zType = "unsigned char";
- nByte = 1;
- }else if( upr<65535 ){
- zType = "unsigned short int";
- nByte = 2;
- }else{
- zType = "unsigned int";
- nByte = 4;
- }
- }else if( lwr>=-127 && upr<=127 ){
- zType = "signed char";
- nByte = 1;
- }else if( lwr>=-32767 && upr<32767 ){
- zType = "short";
- nByte = 2;
- }
- if( pnByte ) *pnByte = nByte;
- return zType;
-}
-
-/*
-** Each state contains a set of token transaction and a set of
-** nonterminal transactions. Each of these sets makes an instance
-** of the following structure. An array of these structures is used
-** to order the creation of entries in the yy_action[] table.
-*/
-struct axset {
- struct state *stp; /* A pointer to a state */
- int isTkn; /* True to use tokens. False for non-terminals */
- int nAction; /* Number of actions */
- int iOrder; /* Original order of action sets */
-};
-
-/*
-** Compare to axset structures for sorting purposes
-*/
-static int axset_compare(const void *a, const void *b){
- struct axset *p1 = (struct axset*)a;
- struct axset *p2 = (struct axset*)b;
- int c;
- c = p2->nAction - p1->nAction;
- if( c==0 ){
- c = p1->iOrder - p2->iOrder;
- }
- assert( c!=0 || p1==p2 );
- return c;
-}
-
-/*
-** Write text on "out" that describes the rule "rp".
-*/
-static void writeRuleText(FILE *out, struct rule *rp){
- int j;
- fprintf(out,"%s ::=", rp->lhs->name);
- for(j=0; j<rp->nrhs; j++){
- struct symbol *sp = rp->rhs[j];
- if( sp->type!=MULTITERMINAL ){
- fprintf(out," %s", sp->name);
- }else{
- int k;
- fprintf(out," %s", sp->subsym[0]->name);
- for(k=1; k<sp->nsubsym; k++){
- fprintf(out,"|%s",sp->subsym[k]->name);
- }
- }
- }
-}
-
-
-/* Generate C source code for the parser */
-void ReportTable(
- struct lemon *lemp,
- int mhflag /* Output in makeheaders format if true */
-){
- FILE *out, *in;
- char line[LINESIZE];
- int lineno;
- struct state *stp;
- struct action *ap;
- struct rule *rp;
- struct acttab *pActtab;
- int i, j, n, sz;
- int szActionType; /* sizeof(YYACTIONTYPE) */
- int szCodeType; /* sizeof(YYCODETYPE) */
- const char *name;
- int mnTknOfst, mxTknOfst;
- int mnNtOfst, mxNtOfst;
- struct axset *ax;
-
- in = tplt_open(lemp);
- if( in==0 ) return;
- out = file_open(lemp,".c","wb");
- if( out==0 ){
- fclose(in);
- return;
- }
- lineno = 1;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the include code, if any */
- tplt_print(out,lemp,lemp->include,&lineno);
- if( mhflag ){
- char *incName = file_makename(lemp, ".h");
- fprintf(out,"#include \"%s\"\n", incName); lineno++;
- free(incName);
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate #defines for all tokens */
- if( mhflag ){
- const char *prefix;
- fprintf(out,"#if INTERFACE\n"); lineno++;
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- lineno++;
- }
- fprintf(out,"#endif\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the defines */
- fprintf(out,"#define YYCODETYPE %s\n",
- minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
- fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
- fprintf(out,"#define YYACTIONTYPE %s\n",
- minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++;
- if( lemp->wildcard ){
- fprintf(out,"#define YYWILDCARD %d\n",
- lemp->wildcard->index); lineno++;
- }
- print_stack_union(out,lemp,&lineno,mhflag);
- fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
- if( lemp->stacksize ){
- fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
- }else{
- fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
- }
- fprintf(out, "#endif\n"); lineno++;
- if( mhflag ){
- fprintf(out,"#if INTERFACE\n"); lineno++;
- }
- name = lemp->name ? lemp->name : "Parse";
- if( lemp->arg && lemp->arg[0] ){
- i = lemonStrlen(lemp->arg);
- while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
- while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
- fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
- name,lemp->arg,&lemp->arg[i]); lineno++;
- fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
- name,&lemp->arg[i],&lemp->arg[i]); lineno++;
- }else{
- fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
- fprintf(out,"#define %sARG_STORE\n",name); lineno++;
- }
- if( mhflag ){
- fprintf(out,"#endif\n"); lineno++;
- }
- if( lemp->errsym->useCnt ){
- fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
- fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
- }
- if( lemp->has_fallback ){
- fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
- }
-
- /* Compute the action table, but do not output it yet. The action
- ** table must be computed before generating the YYNSTATE macro because
- ** we need to know how many states can be eliminated.
- */
- ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
- if( ax==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=0; i<lemp->nxstate; i++){
- stp = lemp->sorted[i];
- ax[i*2].stp = stp;
- ax[i*2].isTkn = 1;
- ax[i*2].nAction = stp->nTknAct;
- ax[i*2+1].stp = stp;
- ax[i*2+1].isTkn = 0;
- ax[i*2+1].nAction = stp->nNtAct;
- }
- mxTknOfst = mnTknOfst = 0;
- mxNtOfst = mnNtOfst = 0;
- /* In an effort to minimize the action table size, use the heuristic
- ** of placing the largest action sets first */
- for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
- qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
- pActtab = acttab_alloc();
- for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
- stp = ax[i].stp;
- if( ax[i].isTkn ){
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index>=lemp->nterminal ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iTknOfst = acttab_insert(pActtab);
- if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
- if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
- }else{
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index<lemp->nterminal ) continue;
- if( ap->sp->index==lemp->nsymbol ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iNtOfst = acttab_insert(pActtab);
- if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
- if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
- }
-#if 0 /* Uncomment for a trace of how the yy_action[] table fills out */
- { int jj, nn;
- for(jj=nn=0; jj<pActtab->nAction; jj++){
- if( pActtab->aAction[jj].action<0 ) nn++;
- }
- printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n",
- i, stp->statenum, ax[i].isTkn ? "Token" : "Var ",
- ax[i].nAction, pActtab->nAction, nn);
- }
-#endif
- }
- free(ax);
-
- /* Finish rendering the constants now that the action table has
- ** been computed */
- fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
- fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
- fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
- fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++;
- i = lemp->nstate + lemp->nrule;
- fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
- fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++;
- i = lemp->nstate + lemp->nrule*2;
- fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
- fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++;
- fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++;
- fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Now output the action table and its associates:
- **
- ** yy_action[] A single table containing all actions.
- ** yy_lookahead[] A table containing the lookahead for each entry in
- ** yy_action. Used to detect hash collisions.
- ** yy_shift_ofst[] For each state, the offset into yy_action for
- ** shifting terminals.
- ** yy_reduce_ofst[] For each state, the offset into yy_action for
- ** shifting non-terminals after a reduce.
- ** yy_default[] Default action for each state.
- */
-
- /* Output the yy_action table */
- lemp->nactiontab = n = acttab_size(pActtab);
- lemp->tablesize += n*szActionType;
- fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
- fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
- for(i=j=0; i<n; i++){
- int action = acttab_yyaction(pActtab, i);
- if( action<0 ) action = lemp->nstate + lemp->nrule + 2;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", action);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_lookahead table */
- lemp->tablesize += n*szCodeType;
- fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
- for(i=j=0; i<n; i++){
- int la = acttab_yylookahead(pActtab, i);
- if( la<0 ) la = lemp->nsymbol;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", la);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_shift_ofst[] table */
- fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
- n = lemp->nxstate;
- while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
- fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
- fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
- fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
- fprintf(out, "static const %s yy_shift_ofst[] = {\n",
- minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++;
- lemp->tablesize += n*sz;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iTknOfst;
- if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_reduce_ofst[] table */
- fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
- n = lemp->nxstate;
- while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
- fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
- fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
- fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
- fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
- minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
- lemp->tablesize += n*sz;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iNtOfst;
- if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the default action table */
- fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
- n = lemp->nxstate;
- lemp->tablesize += n*szActionType;
- for(i=j=0; i<n; i++){
- stp = lemp->sorted[i];
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of fallback tokens.
- */
- if( lemp->has_fallback ){
- int mx = lemp->nterminal - 1;
- while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
- lemp->tablesize += (mx+1)*szCodeType;
- for(i=0; i<=mx; i++){
- struct symbol *p = lemp->symbols[i];
- if( p->fallback==0 ){
- fprintf(out, " 0, /* %10s => nothing */\n", p->name);
- }else{
- fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
- p->name, p->fallback->name);
- }
- lineno++;
- }
- }
- tplt_xfer(lemp->name, in, out, &lineno);
-
- /* Generate a table containing the symbolic name of every symbol
- */
- for(i=0; i<lemp->nsymbol; i++){
- lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
- fprintf(out," %-15s",line);
- if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
- }
- if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate a table containing a text string that describes every
- ** rule in the rule set of the grammar. This information is used
- ** when tracing REDUCE actions.
- */
- for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
- assert( rp->index==i );
- fprintf(out," /* %3d */ \"", i);
- writeRuleText(out, rp);
- fprintf(out,"\",\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes every time a symbol is popped from
- ** the stack while processing errors or while destroying the parser.
- ** (In other words, generate the %destructor actions)
- */
- if( lemp->tokendest ){
- int once = 1;
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type!=TERMINAL ) continue;
- if( once ){
- fprintf(out, " /* TERMINAL Destructor */\n"); lineno++;
- once = 0;
- }
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
- }
- for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
- if( i<lemp->nsymbol ){
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- }
- if( lemp->vardest ){
- struct symbol *dflt_sp = 0;
- int once = 1;
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL ||
- sp->index<=0 || sp->destructor!=0 ) continue;
- if( once ){
- fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++;
- once = 0;
- }
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
- dflt_sp = sp;
- }
- if( dflt_sp!=0 ){
- emit_destructor_code(out,dflt_sp,lemp,&lineno);
- }
- fprintf(out," break;\n"); lineno++;
- }
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
- fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
-
- /* Combine duplicate destructors into a single case */
- for(j=i+1; j<lemp->nsymbol; j++){
- struct symbol *sp2 = lemp->symbols[j];
- if( sp2 && sp2->type!=TERMINAL && sp2->destructor
- && sp2->dtnum==sp->dtnum
- && strcmp(sp->destructor,sp2->destructor)==0 ){
- fprintf(out," case %d: /* %s */\n",
- sp2->index, sp2->name); lineno++;
- sp2->destructor = 0;
- }
- }
-
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes whenever the parser stack overflows */
- tplt_print(out,lemp,lemp->overflow,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of rule information
- **
- ** Note: This code depends on the fact that rules are number
- ** sequentually beginning with 0.
- */
- for(rp=lemp->rule; rp; rp=rp->next){
- fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which execution during each REDUCE action */
- for(rp=lemp->rule; rp; rp=rp->next){
- translate_code(lemp, rp);
- }
- /* First output rules other than the default: rule */
- for(rp=lemp->rule; rp; rp=rp->next){
- struct rule *rp2; /* Other rules with the same action */
- if( rp->code==0 ) continue;
- if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */
- fprintf(out," case %d: /* ", rp->index);
- writeRuleText(out, rp);
- fprintf(out, " */\n"); lineno++;
- for(rp2=rp->next; rp2; rp2=rp2->next){
- if( rp2->code==rp->code ){
- fprintf(out," case %d: /* ", rp2->index);
- writeRuleText(out, rp2);
- fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++;
- rp2->code = 0;
- }
- }
- emit_code(out,rp,lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- rp->code = 0;
- }
- /* Finally, output the default: rule. We choose as the default: all
- ** empty actions. */
- fprintf(out," default:\n"); lineno++;
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->code==0 ) continue;
- assert( rp->code[0]=='\n' && rp->code[1]==0 );
- fprintf(out," /* (%d) ", rp->index);
- writeRuleText(out, rp);
- fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++;
- }
- fprintf(out," break;\n"); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes if a parse fails */
- tplt_print(out,lemp,lemp->failure,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when a syntax error occurs */
- tplt_print(out,lemp,lemp->error,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when the parser accepts its input */
- tplt_print(out,lemp,lemp->accept,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Append any addition code the user desires */
- tplt_print(out,lemp,lemp->extracode,&lineno);
-
- fclose(in);
- fclose(out);
- return;
-}
-
-/* Generate a header file for the parser */
-void ReportHeader(struct lemon *lemp)
-{
- FILE *out, *in;
- const char *prefix;
- char line[LINESIZE];
- char pattern[LINESIZE];
- int i;
-
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- in = file_open(lemp,".h","rb");
- if( in ){
- int nextChar;
- for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
- lemon_sprintf(pattern,"#define %s%-30s %3d\n",
- prefix,lemp->symbols[i]->name,i);
- if( strcmp(line,pattern) ) break;
- }
- nextChar = fgetc(in);
- fclose(in);
- if( i==lemp->nterminal && nextChar==EOF ){
- /* No change in the file. Don't rewrite it. */
- return;
- }
- }
- out = file_open(lemp,".h","wb");
- if( out ){
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i);
- }
- fclose(out);
- }
- return;
-}
-
-/* Reduce the size of the action tables, if possible, by making use
-** of defaults.
-**
-** In this version, we take the most frequent REDUCE action and make
-** it the default. Except, there is no default if the wildcard token
-** is a possible look-ahead.
-*/
-void CompressTables(struct lemon *lemp)
-{
- struct state *stp;
- struct action *ap, *ap2;
- struct rule *rp, *rp2, *rbest;
- int nbest, n;
- int i;
- int usesWildcard;
-
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- nbest = 0;
- rbest = 0;
- usesWildcard = 0;
-
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
- usesWildcard = 1;
- }
- if( ap->type!=REDUCE ) continue;
- rp = ap->x.rp;
- if( rp->lhsStart ) continue;
- if( rp==rbest ) continue;
- n = 1;
- for(ap2=ap->next; ap2; ap2=ap2->next){
- if( ap2->type!=REDUCE ) continue;
- rp2 = ap2->x.rp;
- if( rp2==rbest ) continue;
- if( rp2==rp ) n++;
- }
- if( n>nbest ){
- nbest = n;
- rbest = rp;
- }
- }
-
- /* Do not make a default if the number of rules to default
- ** is not at least 1 or if the wildcard token is a possible
- ** lookahead.
- */
- if( nbest<1 || usesWildcard ) continue;
-
-
- /* Combine matching REDUCE actions into a single default */
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) break;
- }
- assert( ap );
- ap->sp = Symbol_new("{default}");
- for(ap=ap->next; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
- }
- stp->ap = Action_sort(stp->ap);
-
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==SHIFT ) break;
- if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
- }
- if( ap==0 ){
- stp->autoReduce = 1;
- stp->pDfltReduce = rbest;
- }
- }
-
- /* Make a second pass over all states and actions. Convert
- ** every action that is a SHIFT to an autoReduce state into
- ** a SHIFTREDUCE action.
- */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(ap=stp->ap; ap; ap=ap->next){
- struct state *pNextState;
- if( ap->type!=SHIFT ) continue;
- pNextState = ap->x.stp;
- if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
- ap->type = SHIFTREDUCE;
- ap->x.rp = pNextState->pDfltReduce;
- }
- }
- }
-}
-
-
-/*
-** Compare two states for sorting purposes. The smaller state is the
-** one with the most non-terminal actions. If they have the same number
-** of non-terminal actions, then the smaller is the one with the most
-** token actions.
-*/
-static int stateResortCompare(const void *a, const void *b){
- const struct state *pA = *(const struct state**)a;
- const struct state *pB = *(const struct state**)b;
- int n;
-
- n = pB->nNtAct - pA->nNtAct;
- if( n==0 ){
- n = pB->nTknAct - pA->nTknAct;
- if( n==0 ){
- n = pB->statenum - pA->statenum;
- }
- }
- assert( n!=0 );
- return n;
-}
-
-
-/*
-** Renumber and resort states so that states with fewer choices
-** occur at the end. Except, keep state 0 as the first state.
-*/
-void ResortStates(struct lemon *lemp)
-{
- int i;
- struct state *stp;
- struct action *ap;
-
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- stp->nTknAct = stp->nNtAct = 0;
- stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */
- stp->iTknOfst = NO_OFFSET;
- stp->iNtOfst = NO_OFFSET;
- for(ap=stp->ap; ap; ap=ap->next){
- int iAction = compute_action(lemp,ap);
- if( iAction>=0 ){
- if( ap->sp->index<lemp->nterminal ){
- stp->nTknAct++;
- }else if( ap->sp->index<lemp->nsymbol ){
- stp->nNtAct++;
- }else{
- assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
- stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule;
- }
- }
- }
- }
- qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
- stateResortCompare);
- for(i=0; i<lemp->nstate; i++){
- lemp->sorted[i]->statenum = i;
- }
- lemp->nxstate = lemp->nstate;
- while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
- lemp->nxstate--;
- }
-}
-
-
-/***************** From the file "set.c" ************************************/
-/*
-** Set manipulation routines for the LEMON parser generator.
-*/
-
-static int size = 0;
-
-/* Set the set size */
-void SetSize(int n)
-{
- size = n+1;
-}
-
-/* Allocate a new set */
-char *SetNew(){
- char *s;
- s = (char*)calloc( size, 1);
- if( s==0 ){
- extern void memory_error();
- memory_error();
- }
- return s;
-}
-
-/* Deallocate a set */
-void SetFree(char *s)
-{
- free(s);
-}
-
-/* Add a new element to the set. Return TRUE if the element was added
-** and FALSE if it was already there. */
-int SetAdd(char *s, int e)
-{
- int rv;
- assert( e>=0 && e<size );
- rv = s[e];
- s[e] = 1;
- return !rv;
-}
-
-/* Add every element of s2 to s1. Return TRUE if s1 changes. */
-int SetUnion(char *s1, char *s2)
-{
- int i, progress;
- progress = 0;
- for(i=0; i<size; i++){
- if( s2[i]==0 ) continue;
- if( s1[i]==0 ){
- progress = 1;
- s1[i] = 1;
- }
- }
- return progress;
-}
-/********************** From the file "table.c" ****************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-
-PRIVATE unsigned strhash(const char *x)
-{
- unsigned h = 0;
- while( *x ) h = h*13 + *(x++);
- return h;
-}
-
-/* Works like strdup, sort of. Save a string in malloced memory, but
-** keep strings in a table so that the same string is not in more
-** than one place.
-*/
-const char *Strsafe(const char *y)
-{
- const char *z;
- char *cpy;
-
- if( y==0 ) return 0;
- z = Strsafe_find(y);
- if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
- lemon_strcpy(cpy,y);
- z = cpy;
- Strsafe_insert(z);
- }
- MemoryCheck(z);
- return z;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x1".
-*/
-struct s_x1 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x1node *tbl; /* The data stored here */
- struct s_x1node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x1".
-*/
-typedef struct s_x1node {
- const char *data; /* The data */
- struct s_x1node *next; /* Next entry with the same hash */
- struct s_x1node **from; /* Previous link */
-} x1node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x1 *x1a;
-
-/* Allocate a new associative array */
-void Strsafe_init(){
- if( x1a ) return;
- x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
- if( x1a ){
- x1a->size = 1024;
- x1a->count = 0;
- x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
- if( x1a->tbl==0 ){
- free(x1a);
- x1a = 0;
- }else{
- int i;
- x1a->ht = (x1node**)&(x1a->tbl[1024]);
- for(i=0; i<1024; i++) x1a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Strsafe_insert(const char *data)
-{
- x1node *np;
- unsigned h;
- unsigned ph;
-
- if( x1a==0 ) return 0;
- ph = strhash(data);
- h = ph & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x1a->count>=x1a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x1 array;
- array.size = arrSize = x1a->size*2;
- array.count = x1a->count;
- array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x1node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x1a->count; i++){
- x1node *oldnp, *newnp;
- oldnp = &(x1a->tbl[i]);
- h = strhash(oldnp->data) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x1a->tbl);
- *x1a = array;
- }
- /* Insert the new data */
- h = ph & (x1a->size-1);
- np = &(x1a->tbl[x1a->count++]);
- np->data = data;
- if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
- np->next = x1a->ht[h];
- x1a->ht[h] = np;
- np->from = &(x1a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-const char *Strsafe_find(const char *key)
-{
- unsigned h;
- x1node *np;
-
- if( x1a==0 ) return 0;
- h = strhash(key) & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return a pointer to the (terminal or nonterminal) symbol "x".
-** Create a new symbol if this is the first time "x" has been seen.
-*/
-struct symbol *Symbol_new(const char *x)
-{
- struct symbol *sp;
-
- sp = Symbol_find(x);
- if( sp==0 ){
- sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
- MemoryCheck(sp);
- sp->name = Strsafe(x);
- sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
- sp->rule = 0;
- sp->fallback = 0;
- sp->prec = -1;
- sp->assoc = UNK;
- sp->firstset = 0;
- sp->lambda = LEMON_FALSE;
- sp->destructor = 0;
- sp->destLineno = 0;
- sp->datatype = 0;
- sp->useCnt = 0;
- Symbol_insert(sp,sp->name);
- }
- sp->useCnt++;
- return sp;
-}
-
-/* Compare two symbols for sorting purposes. Return negative,
-** zero, or positive if a is less then, equal to, or greater
-** than b.
-**
-** Symbols that begin with upper case letters (terminals or tokens)
-** must sort before symbols that begin with lower case letters
-** (non-terminals). And MULTITERMINAL symbols (created using the
-** %token_class directive) must sort at the very end. Other than
-** that, the order does not matter.
-**
-** We find experimentally that leaving the symbols in their original
-** order (the order they appeared in the grammar file) gives the
-** smallest parser tables in SQLite.
-*/
-int Symbolcmpp(const void *_a, const void *_b)
-{
- const struct symbol *a = *(const struct symbol **) _a;
- const struct symbol *b = *(const struct symbol **) _b;
- int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
- int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
- return i1==i2 ? a->index - b->index : i1 - i2;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x2".
-*/
-struct s_x2 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x2node *tbl; /* The data stored here */
- struct s_x2node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x2".
-*/
-typedef struct s_x2node {
- struct symbol *data; /* The data */
- const char *key; /* The key */
- struct s_x2node *next; /* Next entry with the same hash */
- struct s_x2node **from; /* Previous link */
-} x2node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x2 *x2a;
-
-/* Allocate a new associative array */
-void Symbol_init(){
- if( x2a ) return;
- x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
- if( x2a ){
- x2a->size = 128;
- x2a->count = 0;
- x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
- if( x2a->tbl==0 ){
- free(x2a);
- x2a = 0;
- }else{
- int i;
- x2a->ht = (x2node**)&(x2a->tbl[128]);
- for(i=0; i<128; i++) x2a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Symbol_insert(struct symbol *data, const char *key)
-{
- x2node *np;
- unsigned h;
- unsigned ph;
-
- if( x2a==0 ) return 0;
- ph = strhash(key);
- h = ph & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x2a->count>=x2a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x2 array;
- array.size = arrSize = x2a->size*2;
- array.count = x2a->count;
- array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x2node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x2a->count; i++){
- x2node *oldnp, *newnp;
- oldnp = &(x2a->tbl[i]);
- h = strhash(oldnp->key) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x2a->tbl);
- *x2a = array;
- }
- /* Insert the new data */
- h = ph & (x2a->size-1);
- np = &(x2a->tbl[x2a->count++]);
- np->key = key;
- np->data = data;
- if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
- np->next = x2a->ht[h];
- x2a->ht[h] = np;
- np->from = &(x2a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct symbol *Symbol_find(const char *key)
-{
- unsigned h;
- x2node *np;
-
- if( x2a==0 ) return 0;
- h = strhash(key) & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return the n-th data. Return NULL if n is out of range. */
-struct symbol *Symbol_Nth(int n)
-{
- struct symbol *data;
- if( x2a && n>0 && n<=x2a->count ){
- data = x2a->tbl[n-1].data;
- }else{
- data = 0;
- }
- return data;
-}
-
-/* Return the size of the array */
-int Symbol_count()
-{
- return x2a ? x2a->count : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct symbol **Symbol_arrayof()
-{
- struct symbol **array;
- int i,arrSize;
- if( x2a==0 ) return 0;
- arrSize = x2a->count;
- array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
- if( array ){
- for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
- }
- return array;
-}
-
-/* Compare two configurations */
-int Configcmp(const char *_a,const char *_b)
-{
- const struct config *a = (struct config *) _a;
- const struct config *b = (struct config *) _b;
- int x;
- x = a->rp->index - b->rp->index;
- if( x==0 ) x = a->dot - b->dot;
- return x;
-}
-
-/* Compare two states */
-PRIVATE int statecmp(struct config *a, struct config *b)
-{
- int rc;
- for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
- rc = a->rp->index - b->rp->index;
- if( rc==0 ) rc = a->dot - b->dot;
- }
- if( rc==0 ){
- if( a ) rc = 1;
- if( b ) rc = -1;
- }
- return rc;
-}
-
-/* Hash a state */
-PRIVATE unsigned statehash(struct config *a)
-{
- unsigned h=0;
- while( a ){
- h = h*571 + a->rp->index*37 + a->dot;
- a = a->bp;
- }
- return h;
-}
-
-/* Allocate a new state structure */
-struct state *State_new()
-{
- struct state *newstate;
- newstate = (struct state *)calloc(1, sizeof(struct state) );
- MemoryCheck(newstate);
- return newstate;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x3".
-*/
-struct s_x3 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x3node *tbl; /* The data stored here */
- struct s_x3node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x3".
-*/
-typedef struct s_x3node {
- struct state *data; /* The data */
- struct config *key; /* The key */
- struct s_x3node *next; /* Next entry with the same hash */
- struct s_x3node **from; /* Previous link */
-} x3node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x3 *x3a;
-
-/* Allocate a new associative array */
-void State_init(){
- if( x3a ) return;
- x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
- if( x3a ){
- x3a->size = 128;
- x3a->count = 0;
- x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
- if( x3a->tbl==0 ){
- free(x3a);
- x3a = 0;
- }else{
- int i;
- x3a->ht = (x3node**)&(x3a->tbl[128]);
- for(i=0; i<128; i++) x3a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int State_insert(struct state *data, struct config *key)
-{
- x3node *np;
- unsigned h;
- unsigned ph;
-
- if( x3a==0 ) return 0;
- ph = statehash(key);
- h = ph & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x3a->count>=x3a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x3 array;
- array.size = arrSize = x3a->size*2;
- array.count = x3a->count;
- array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x3node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x3a->count; i++){
- x3node *oldnp, *newnp;
- oldnp = &(x3a->tbl[i]);
- h = statehash(oldnp->key) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x3a->tbl);
- *x3a = array;
- }
- /* Insert the new data */
- h = ph & (x3a->size-1);
- np = &(x3a->tbl[x3a->count++]);
- np->key = key;
- np->data = data;
- if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
- np->next = x3a->ht[h];
- x3a->ht[h] = np;
- np->from = &(x3a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct state *State_find(struct config *key)
-{
- unsigned h;
- x3node *np;
-
- if( x3a==0 ) return 0;
- h = statehash(key) & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct state **State_arrayof()
-{
- struct state **array;
- int i,arrSize;
- if( x3a==0 ) return 0;
- arrSize = x3a->count;
- array = (struct state **)calloc(arrSize, sizeof(struct state *));
- if( array ){
- for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
- }
- return array;
-}
-
-/* Hash a configuration */
-PRIVATE unsigned confighash(struct config *a)
-{
- unsigned h=0;
- h = h*571 + a->rp->index*37 + a->dot;
- return h;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x4".
-*/
-struct s_x4 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x4node *tbl; /* The data stored here */
- struct s_x4node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x4".
-*/
-typedef struct s_x4node {
- struct config *data; /* The data */
- struct s_x4node *next; /* Next entry with the same hash */
- struct s_x4node **from; /* Previous link */
-} x4node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x4 *x4a;
-
-/* Allocate a new associative array */
-void Configtable_init(){
- if( x4a ) return;
- x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
- if( x4a ){
- x4a->size = 64;
- x4a->count = 0;
- x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
- if( x4a->tbl==0 ){
- free(x4a);
- x4a = 0;
- }else{
- int i;
- x4a->ht = (x4node**)&(x4a->tbl[64]);
- for(i=0; i<64; i++) x4a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Configtable_insert(struct config *data)
-{
- x4node *np;
- unsigned h;
- unsigned ph;
-
- if( x4a==0 ) return 0;
- ph = confighash(data);
- h = ph & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp((const char *) np->data,(const char *) data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x4a->count>=x4a->size ){
- /* Need to make the hash table bigger */
- int i,arrSize;
- struct s_x4 array;
- array.size = arrSize = x4a->size*2;
- array.count = x4a->count;
- array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x4node**)&(array.tbl[arrSize]);
- for(i=0; i<arrSize; i++) array.ht[i] = 0;
- for(i=0; i<x4a->count; i++){
- x4node *oldnp, *newnp;
- oldnp = &(x4a->tbl[i]);
- h = confighash(oldnp->data) & (arrSize-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x4a->tbl);
- *x4a = array;
- }
- /* Insert the new data */
- h = ph & (x4a->size-1);
- np = &(x4a->tbl[x4a->count++]);
- np->data = data;
- if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
- np->next = x4a->ht[h];
- x4a->ht[h] = np;
- np->from = &(x4a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct config *Configtable_find(struct config *key)
-{
- int h;
- x4node *np;
-
- if( x4a==0 ) return 0;
- h = confighash(key) & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp((const char *) np->data,(const char *) key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Remove all data from the table. Pass each data to the function "f"
-** as it is removed. ("f" may be null to avoid this step.) */
-void Configtable_clear(int(*f)(struct config *))
-{
- int i;
- if( x4a==0 || x4a->count==0 ) return;
- if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
- for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
- x4a->count = 0;
- return;
-}
diff --git a/lib/libsqlite3/tool/lempar.c b/lib/libsqlite3/tool/lempar.c
deleted file mode 100644
index cdf4ca5a1a5..00000000000
--- a/lib/libsqlite3/tool/lempar.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/* Driver template for the LEMON parser generator.
-** The author disclaims copyright to this source code.
-*/
-/* First off, code is included that follows the "include" declaration
-** in the input grammar file. */
-#include <stdio.h>
-%%
-/* Next is all token values, in a form suitable for use by makeheaders.
-** This section will be null unless lemon is run with the -m switch.
-*/
-/*
-** These constants (all generated automatically by the parser generator)
-** specify the various kinds of tokens (terminals) that the parser
-** understands.
-**
-** Each symbol here is a terminal symbol in the grammar.
-*/
-%%
-/* Make sure the INTERFACE macro is defined.
-*/
-#ifndef INTERFACE
-# define INTERFACE 1
-#endif
-/* The next thing included is series of defines which control
-** various aspects of the generated parser.
-** YYCODETYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 terminals
-** and nonterminals. "int" is used otherwise.
-** YYNOCODE is a number of type YYCODETYPE which corresponds
-** to no legal terminal or nonterminal number. This
-** number is used to fill in empty slots of the hash
-** table.
-** YYFALLBACK If defined, this indicates that one or more tokens
-** have fall-back values which should be used if the
-** original value of the token will not parse.
-** YYACTIONTYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 rules and
-** states combined. "int" is used otherwise.
-** ParseTOKENTYPE is the data type used for minor tokens given
-** directly to the parser from the tokenizer.
-** YYMINORTYPE is the data type used for all minor tokens.
-** This is typically a union of many types, one of
-** which is ParseTOKENTYPE. The entry in the union
-** for base tokens is called "yy0".
-** YYSTACKDEPTH is the maximum depth of the parser's stack. If
-** zero the stack is dynamically sized using realloc()
-** ParseARG_SDECL A static variable declaration for the %extra_argument
-** ParseARG_PDECL A parameter declaration for the %extra_argument
-** ParseARG_STORE Code to store %extra_argument into yypParser
-** ParseARG_FETCH Code to extract %extra_argument from yypParser
-** YYERRORSYMBOL is the code number of the error symbol. If not
-** defined, then do no error processing.
-** YYNSTATE the combined number of states.
-** YYNRULE the number of rules in the grammar
-** YY_MAX_SHIFT Maximum value for shift actions
-** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
-** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
-** YY_MIN_REDUCE Maximum value for reduce actions
-** YY_ERROR_ACTION The yy_action[] code for syntax error
-** YY_ACCEPT_ACTION The yy_action[] code for accept
-** YY_NO_ACTION The yy_action[] code for no-op
-*/
-%%
-
-/* The yyzerominor constant is used to initialize instances of
-** YYMINORTYPE objects to zero. */
-static const YYMINORTYPE yyzerominor = { 0 };
-
-/* Define the yytestcase() macro to be a no-op if is not already defined
-** otherwise.
-**
-** Applications can choose to define yytestcase() in the %include section
-** to a macro that can assist in verifying code coverage. For production
-** code the yytestcase() macro should be turned off. But it is useful
-** for testing.
-*/
-#ifndef yytestcase
-# define yytestcase(X)
-#endif
-
-
-/* Next are the tables used to determine what action to take based on the
-** current state and lookahead token. These tables are used to implement
-** functions that take a state number and lookahead value and return an
-** action integer.
-**
-** Suppose the action integer is N. Then the action is determined as
-** follows
-**
-** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
-** token onto the stack and goto state N.
-**
-** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
-** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
-**
-** 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.
-**
-** N == YY_NO_ACTION No such action. Denotes unused
-** slots in the yy_action[] table.
-**
-** The action table is constructed as a single large table named yy_action[].
-** Given state S and lookahead X, the action is computed as
-**
-** yy_action[ yy_shift_ofst[S] + X ]
-**
-** If the index value yy_shift_ofst[S]+X is out of range or if the value
-** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
-** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
-** and that yy_default[S] should be used instead.
-**
-** The formula above is for computing the action when the lookahead is
-** a terminal symbol. If the lookahead is a non-terminal (as occurs after
-** a reduce action) then the yy_reduce_ofst[] array is used in place of
-** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
-** YY_SHIFT_USE_DFLT.
-**
-** The following are the tables generated in this section:
-**
-** yy_action[] A single table containing all actions.
-** yy_lookahead[] A table containing the lookahead for each entry in
-** yy_action. Used to detect hash collisions.
-** yy_shift_ofst[] For each state, the offset into yy_action for
-** shifting terminals.
-** yy_reduce_ofst[] For each state, the offset into yy_action for
-** shifting non-terminals after a reduce.
-** yy_default[] Default action for each state.
-*/
-%%
-
-/* The next table maps tokens into fallback tokens. If a construct
-** like the following:
-**
-** %fallback ID X Y Z.
-**
-** appears in the grammar, then ID becomes a fallback token for X, Y,
-** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
-** but it does not parse, the type of the token is changed to ID and
-** the parse is retried before an error is thrown.
-*/
-#ifdef YYFALLBACK
-static const YYCODETYPE yyFallback[] = {
-%%
-};
-#endif /* YYFALLBACK */
-
-/* The following structure represents a single element of the
-** parser's stack. Information stored includes:
-**
-** + The state number for the parser at this level of the stack.
-**
-** + The value of the token stored at this level of the stack.
-** (In other words, the "major" token.)
-**
-** + The semantic value stored at this level of the stack. This is
-** the information used by the action routines in the grammar.
-** It is sometimes called the "minor" token.
-**
-** After the "shift" half of a SHIFTREDUCE action, the stateno field
-** actually contains the reduce action for the second half of the
-** SHIFTREDUCE.
-*/
-struct yyStackEntry {
- YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
- YYCODETYPE major; /* The major token value. This is the code
- ** number for the token at this stack level */
- YYMINORTYPE minor; /* The user-supplied minor token value. This
- ** is the value of the token */
-};
-typedef struct yyStackEntry yyStackEntry;
-
-/* The state of the parser is completely contained in an instance of
-** the following structure */
-struct yyParser {
- int yyidx; /* Index of top element in stack */
-#ifdef YYTRACKMAXSTACKDEPTH
- int yyidxMax; /* Maximum value of yyidx */
-#endif
- int yyerrcnt; /* Shifts left before out of the error */
- ParseARG_SDECL /* A place to hold %extra_argument */
-#if YYSTACKDEPTH<=0
- int yystksz; /* Current side of the stack */
- yyStackEntry *yystack; /* The parser's stack */
-#else
- yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
-#endif
-};
-typedef struct yyParser yyParser;
-
-#ifndef NDEBUG
-#include <stdio.h>
-static FILE *yyTraceFILE = 0;
-static char *yyTracePrompt = 0;
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/*
-** Turn parser tracing on by giving a stream to which to write the trace
-** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
-**
-** Inputs:
-** <ul>
-** <li> A FILE* to which trace output should be written.
-** If NULL, then tracing is turned off.
-** <li> A prefix string written at the beginning of every
-** line of trace output. If NULL, then tracing is
-** turned off.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
- yyTraceFILE = TraceFILE;
- yyTracePrompt = zTracePrompt;
- if( yyTraceFILE==0 ) yyTracePrompt = 0;
- else if( yyTracePrompt==0 ) yyTraceFILE = 0;
-}
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing shifts, the names of all terminals and nonterminals
-** are required. The following table supplies these names */
-static const char *const yyTokenName[] = {
-%%
-};
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing reduce actions, the names of all rules are required.
-*/
-static const char *const yyRuleName[] = {
-%%
-};
-#endif /* NDEBUG */
-
-
-#if YYSTACKDEPTH<=0
-/*
-** Try to increase the size of the parser stack.
-*/
-static void yyGrowStack(yyParser *p){
- int newSize;
- yyStackEntry *pNew;
-
- newSize = p->yystksz*2 + 100;
- pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
- if( pNew ){
- p->yystack = pNew;
- p->yystksz = newSize;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
- yyTracePrompt, p->yystksz);
- }
-#endif
- }
-}
-#endif
-
-/*
-** This function allocates a new parser.
-** The only argument is a pointer to a function which works like
-** malloc.
-**
-** Inputs:
-** A pointer to the function used to allocate memory.
-**
-** Outputs:
-** A pointer to a parser. This pointer is used in subsequent calls
-** to Parse and ParseFree.
-*/
-void *ParseAlloc(void *(*mallocProc)(size_t)){
- yyParser *pParser;
- pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
- if( pParser ){
- pParser->yyidx = -1;
-#ifdef YYTRACKMAXSTACKDEPTH
- pParser->yyidxMax = 0;
-#endif
-#if YYSTACKDEPTH<=0
- pParser->yystack = NULL;
- pParser->yystksz = 0;
- yyGrowStack(pParser);
-#endif
- }
- return pParser;
-}
-
-/* The following function deletes the value associated with a
-** symbol. The symbol can be either a terminal or nonterminal.
-** "yymajor" is the symbol code, and "yypminor" is a pointer to
-** the value.
-*/
-static void yy_destructor(
- yyParser *yypParser, /* The parser */
- YYCODETYPE yymajor, /* Type code for object to destroy */
- YYMINORTYPE *yypminor /* The object to be destroyed */
-){
- ParseARG_FETCH;
- switch( yymajor ){
- /* Here is inserted the actions which take place when a
- ** terminal or non-terminal is destroyed. This can happen
- ** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
- ** being destroyed before it is finished parsing.
- **
- ** Note: during a reduce, the only symbols destroyed are those
- ** which appear on the RHS of the rule, but which are not used
- ** inside the C code.
- */
-%%
- default: break; /* If no destructor action specified: do nothing */
- }
-}
-
-/*
-** Pop the parser's stack once.
-**
-** If there is a destructor routine associated with the token which
-** is popped from the stack, then call it.
-**
-** Return the major token number for the symbol popped.
-*/
-static int yy_pop_parser_stack(yyParser *pParser){
- YYCODETYPE yymajor;
- yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
-
- if( pParser->yyidx<0 ) return 0;
-#ifndef NDEBUG
- if( yyTraceFILE && pParser->yyidx>=0 ){
- fprintf(yyTraceFILE,"%sPopping %s\n",
- yyTracePrompt,
- yyTokenName[yytos->major]);
- }
-#endif
- yymajor = yytos->major;
- yy_destructor(pParser, yymajor, &yytos->minor);
- pParser->yyidx--;
- return yymajor;
-}
-
-/*
-** Deallocate and destroy a parser. Destructors are all called for
-** all stack elements before shutting the parser down.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser. This should be a pointer
-** obtained from ParseAlloc.
-** <li> A pointer to a function used to reclaim memory obtained
-** from malloc.
-** </ul>
-*/
-void ParseFree(
- void *p, /* The parser to be deleted */
- void (*freeProc)(void*) /* Function used to reclaim memory */
-){
- yyParser *pParser = (yyParser*)p;
- if( pParser==0 ) return;
- while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
-#if YYSTACKDEPTH<=0
- free(pParser->yystack);
-#endif
- (*freeProc)((void*)pParser);
-}
-
-/*
-** Return the peak depth of the stack for a parser.
-*/
-#ifdef YYTRACKMAXSTACKDEPTH
-int ParseStackPeak(void *p){
- yyParser *pParser = (yyParser*)p;
- return pParser->yyidxMax;
-}
-#endif
-
-/*
-** Find the appropriate action for a parser given the terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_shift_action(
- yyParser *pParser, /* The parser */
- YYCODETYPE iLookAhead /* The look-ahead token */
-){
- int i;
- int stateno = pParser->yystack[pParser->yyidx].stateno;
-
- if( stateno>=YY_MIN_REDUCE ) return stateno;
- assert( stateno <= YY_SHIFT_COUNT );
- 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<sizeof(yyFallback)/sizeof(yyFallback[0])
- && (iFallback = yyFallback[iLookAhead])!=0 ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
- }
-#endif
- return yy_find_shift_action(pParser, iFallback);
- }
-#endif
-#ifdef YYWILDCARD
- {
- int j = i - iLookAhead + YYWILDCARD;
- if(
-#if YY_SHIFT_MIN+YYWILDCARD<0
- j>=0 &&
-#endif
-#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
- j<YY_ACTTAB_COUNT &&
-#endif
- yy_lookahead[j]==YYWILDCARD
- ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
- }
-#endif /* NDEBUG */
- return yy_action[j];
- }
- }
-#endif /* YYWILDCARD */
- }
- return yy_default[stateno];
- }else{
- return yy_action[i];
- }
-}
-
-/*
-** Find the appropriate action for a parser given the non-terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_reduce_action(
- int stateno, /* Current state number */
- YYCODETYPE iLookAhead /* The look-ahead token */
-){
- int i;
-#ifdef YYERRORSYMBOL
- if( stateno>YY_REDUCE_COUNT ){
- return yy_default[stateno];
- }
-#else
- assert( stateno<=YY_REDUCE_COUNT );
-#endif
- i = yy_reduce_ofst[stateno];
- assert( i!=YY_REDUCE_USE_DFLT );
- assert( iLookAhead!=YYNOCODE );
- i += iLookAhead;
-#ifdef YYERRORSYMBOL
- if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
- return yy_default[stateno];
- }
-#else
- assert( i>=0 && i<YY_ACTTAB_COUNT );
- assert( yy_lookahead[i]==iLookAhead );
-#endif
- return yy_action[i];
-}
-
-/*
-** The following routine is called if the stack overflows.
-*/
-static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
- ParseARG_FETCH;
- yypParser->yyidx--;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will execute if the parser
- ** stack every overflows */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
-}
-
-/*
-** Print tracing information for a SHIFT action
-*/
-#ifndef NDEBUG
-static void yyTraceShift(yyParser *yypParser, int yyNewState){
- if( yyTraceFILE ){
- int i;
- if( yyNewState<YYNSTATE ){
- fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
- fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
- for(i=1; i<=yypParser->yyidx; i++)
- fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
- fprintf(yyTraceFILE,"\n");
- }else{
- fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
- }
- }
-}
-#else
-# define yyTraceShift(X,Y)
-#endif
-
-/*
-** Perform a shift action. Return the number of errors.
-*/
-static void yy_shift(
- yyParser *yypParser, /* The parser to be shifted */
- int yyNewState, /* The new state to shift in */
- int yyMajor, /* The major token to shift in */
- YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
-){
- yyStackEntry *yytos;
- yypParser->yyidx++;
-#ifdef YYTRACKMAXSTACKDEPTH
- if( yypParser->yyidx>yypParser->yyidxMax ){
- yypParser->yyidxMax = yypParser->yyidx;
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yyidx>=YYSTACKDEPTH ){
- yyStackOverflow(yypParser, yypMinor);
- return;
- }
-#else
- if( yypParser->yyidx>=yypParser->yystksz ){
- yyGrowStack(yypParser);
- if( yypParser->yyidx>=yypParser->yystksz ){
- yyStackOverflow(yypParser, yypMinor);
- return;
- }
- }
-#endif
- yytos = &yypParser->yystack[yypParser->yyidx];
- yytos->stateno = (YYACTIONTYPE)yyNewState;
- yytos->major = (YYCODETYPE)yyMajor;
- yytos->minor = *yypMinor;
- yyTraceShift(yypParser, yyNewState);
-}
-
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- unsigned char nrhs; /* Number of right-hand side symbols in the rule */
-} yyRuleInfo[] = {
-%%
-};
-
-static void yy_accept(yyParser*); /* Forward Declaration */
-
-/*
-** Perform a reduce action and the shift that must immediately
-** follow the reduce.
-*/
-static void yy_reduce(
- yyParser *yypParser, /* The parser */
- int yyruleno /* Number of the rule by which to reduce */
-){
- int yygoto; /* The next state */
- int yyact; /* The next action */
- YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
- yyStackEntry *yymsp; /* The top of the parser's stack */
- int yysize; /* Amount to pop the stack */
- ParseARG_FETCH;
- yymsp = &yypParser->yystack[yypParser->yyidx];
-#ifndef NDEBUG
- if( yyTraceFILE && yyruleno>=0
- && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
- yysize = yyRuleInfo[yyruleno].nrhs;
- fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
- yyRuleName[yyruleno], yymsp[-yysize].stateno);
- }
-#endif /* NDEBUG */
-
- /* Silence complaints from purify about yygotominor being uninitialized
- ** in some cases when it is copied into the stack after the following
- ** switch. yygotominor is uninitialized when a rule reduces that does
- ** not set the value of its left-hand side nonterminal. Leaving the
- ** value of the nonterminal uninitialized is utterly harmless as long
- ** as the value is never used. So really the only thing this code
- ** accomplishes is to quieten purify.
- **
- ** 2007-01-16: The wireshark project (www.wireshark.org) reports that
- ** without this code, their parser segfaults. I'm not sure what there
- ** parser is doing to make this happen. This is the second bug report
- ** from wireshark this week. Clearly they are stressing Lemon in ways
- ** that it has not been previously stressed... (SQLite ticket #2172)
- */
- /*memset(&yygotominor, 0, sizeof(yygotominor));*/
- yygotominor = yyzerominor;
-
-
- switch( yyruleno ){
- /* Beginning here are the reduction cases. A typical example
- ** follows:
- ** case 0:
- ** #line <lineno> <grammarfile>
- ** { ... } // User supplied code
- ** #line <lineno> <thisfile>
- ** break;
- */
-%%
- };
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
- yypParser->yyidx -= yysize;
- yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
- if( yyact <= YY_MAX_SHIFTREDUCE ){
- if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
- /* If the reduce action popped at least
- ** one element off the stack, then we can push the new element back
- ** onto the stack here, and skip the stack overflow test in yy_shift().
- ** That gives a significant speed improvement. */
- if( yysize ){
- yypParser->yyidx++;
- yymsp -= yysize-1;
- yymsp->stateno = (YYACTIONTYPE)yyact;
- yymsp->major = (YYCODETYPE)yygoto;
- yymsp->minor = yygotominor;
- yyTraceShift(yypParser, yyact);
- }else{
- yy_shift(yypParser,yyact,yygoto,&yygotominor);
- }
- }else{
- assert( yyact == YY_ACCEPT_ACTION );
- yy_accept(yypParser);
- }
-}
-
-/*
-** The following code executes when the parse fails
-*/
-#ifndef YYNOERRORRECOVERY
-static void yy_parse_failed(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser fails */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-#endif /* YYNOERRORRECOVERY */
-
-/*
-** The following code executes when a syntax error first occurs.
-*/
-static void yy_syntax_error(
- yyParser *yypParser, /* The parser */
- int yymajor, /* The major type of the error token */
- YYMINORTYPE yyminor /* The minor type of the error token */
-){
- ParseARG_FETCH;
-#define TOKEN (yyminor.yy0)
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/*
-** The following is executed when the parser accepts
-*/
-static void yy_accept(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser accepts */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/* The main parser program.
-** The first argument is a pointer to a structure obtained from
-** "ParseAlloc" which describes the current state of the parser.
-** The second argument is the major token number. The third is
-** the minor token. The fourth optional argument is whatever the
-** user wants (and specified in the grammar) and is available for
-** use by the action routines.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser (an opaque structure.)
-** <li> The major token number.
-** <li> The minor token number.
-** <li> An option argument of a grammar-specified type.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void Parse(
- void *yyp, /* The parser */
- int yymajor, /* The major token code number */
- ParseTOKENTYPE yyminor /* The value for the token */
- ParseARG_PDECL /* Optional %extra_argument parameter */
-){
- YYMINORTYPE yyminorunion;
- int yyact; /* The parser action. */
- int yyendofinput; /* True if we are at the end of input */
-#ifdef YYERRORSYMBOL
- int yyerrorhit = 0; /* True if yymajor has invoked an error */
-#endif
- yyParser *yypParser; /* The parser */
-
- /* (re)initialize the parser, if necessary */
- yypParser = (yyParser*)yyp;
- if( yypParser->yyidx<0 ){
-#if YYSTACKDEPTH<=0
- if( yypParser->yystksz <=0 ){
- /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
- yyminorunion = yyzerominor;
- yyStackOverflow(yypParser, &yyminorunion);
- return;
- }
-#endif
- yypParser->yyidx = 0;
- yypParser->yyerrcnt = -1;
- yypParser->yystack[0].stateno = 0;
- yypParser->yystack[0].major = 0;
- }
- yyminorunion.yy0 = yyminor;
- yyendofinput = (yymajor==0);
- ParseARG_STORE;
-
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
-
- do{
- yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
- if( yyact <= YY_MAX_SHIFTREDUCE ){
- if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
- yy_shift(yypParser,yyact,yymajor,&yyminorunion);
- yypParser->yyerrcnt--;
- yymajor = YYNOCODE;
- }else if( yyact <= YY_MAX_REDUCE ){
- yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
- }else{
- assert( yyact == YY_ERROR_ACTION );
-#ifdef YYERRORSYMBOL
- int yymx;
-#endif
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
- }
-#endif
-#ifdef YYERRORSYMBOL
- /* A syntax error has occurred.
- ** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
- **
- ** This is what we do if the grammar does define ERROR:
- **
- ** * Call the %syntax_error function.
- **
- ** * Begin popping the stack until we enter a state where
- ** it is legal to shift the error symbol, then shift
- ** the error symbol.
- **
- ** * Set the error count to three.
- **
- ** * Begin accepting and shifting new tokens. No new error
- ** processing will occur until three tokens have been
- ** shifted successfully.
- **
- */
- if( yypParser->yyerrcnt<0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yymx = yypParser->yystack[yypParser->yyidx].major;
- if( yymx==YYERRORSYMBOL || yyerrorhit ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sDiscard input token %s\n",
- yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
- yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
- yymajor = YYNOCODE;
- }else{
- while(
- yypParser->yyidx >= 0 &&
- yymx != YYERRORSYMBOL &&
- (yyact = yy_find_reduce_action(
- yypParser->yystack[yypParser->yyidx].stateno,
- YYERRORSYMBOL)) >= YY_MIN_REDUCE
- ){
- yy_pop_parser_stack(yypParser);
- }
- if( yypParser->yyidx < 0 || yymajor==0 ){
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- yy_parse_failed(yypParser);
- yymajor = YYNOCODE;
- }else if( yymx!=YYERRORSYMBOL ){
- YYMINORTYPE u2;
- u2.YYERRSYMDT = 0;
- yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
- }
- }
- yypParser->yyerrcnt = 3;
- yyerrorhit = 1;
-#elif defined(YYNOERRORRECOVERY)
- /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
- ** do any kind of error recovery. Instead, simply invoke the syntax
- ** error routine and continue going as if nothing had happened.
- **
- ** Applications can set this macro (for example inside %include) if
- ** they intend to abandon the parse upon the first syntax error seen.
- */
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- yymajor = YYNOCODE;
-
-#else /* YYERRORSYMBOL is not defined */
- /* This is what we do if the grammar does not define ERROR:
- **
- ** * Report an error message, and throw away the input token.
- **
- ** * If the input token is $, then fail the parse.
- **
- ** As before, subsequent error messages are suppressed until
- ** three input tokens have been successfully shifted.
- */
- if( yypParser->yyerrcnt<=0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yypParser->yyerrcnt = 3;
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- if( yyendofinput ){
- yy_parse_failed(yypParser);
- }
- yymajor = YYNOCODE;
-#endif
- }
- }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
- }
-#endif
- return;
-}
diff --git a/lib/libsqlite3/tool/loadfts.c b/lib/libsqlite3/tool/loadfts.c
deleted file mode 100644
index 0000797b887..00000000000
--- a/lib/libsqlite3/tool/loadfts.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-** 2014-07-28
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements a utility program that will load many disk
-** files (all files under a given directory) into a FTS table. This is
-** used for performance testing of FTS3, FTS4, and FTS5.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include "sqlite3.h"
-
-/*
-** Implementation of the "readtext(X)" SQL function. The entire content
-** of the file named X is read and returned as a TEXT value. It is assumed
-** the file contains UTF-8 text. NULL is returned if the file does not
-** exist or is unreadable.
-*/
-static void readfileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zName;
- FILE *in;
- long nIn;
- void *pBuf;
-
- zName = (const char*)sqlite3_value_text(argv[0]);
- if( zName==0 ) return;
- in = fopen(zName, "rb");
- if( in==0 ) return;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_text(context, pBuf, nIn, sqlite3_free);
- }else{
- sqlite3_free(pBuf);
- }
- fclose(in);
-}
-
-/*
-** Print usage text for this program and exit.
-*/
-static void showHelp(const char *zArgv0){
- printf("\n"
-"Usage: %s SWITCHES... DB\n"
-"\n"
-" This program opens the database named on the command line and attempts to\n"
-" create an FTS table named \"fts\" with a single column. If successful, it\n"
-" recursively traverses the directory named by the -dir option and inserts\n"
-" the contents of each file into the fts table. All files are assumed to\n"
-" contain UTF-8 text.\n"
-"\n"
-"Switches are:\n"
-" -fts [345] FTS version to use (default=5)\n"
-" -idx [01] Create a mapping from filename to rowid (default=0)\n"
-" -dir <path> Root of directory tree to load data from (default=.)\n"
-" -trans <integer> Number of inserts per transaction (default=1)\n"
-, zArgv0
-);
- exit(1);
-}
-
-/*
-** Exit with a message based on the argument and the current value of errno.
-*/
-static void error_out(const char *zText){
- fprintf(stderr, "%s: %s\n", zText, strerror(errno));
- exit(-1);
-}
-
-/*
-** Exit with a message based on the first argument and the error message
-** currently stored in database handle db.
-*/
-static void sqlite_error_out(const char *zText, sqlite3 *db){
- fprintf(stderr, "%s: %s\n", zText, sqlite3_errmsg(db));
- exit(-1);
-}
-
-/*
-** Context object for visit_file().
-*/
-typedef struct VisitContext VisitContext;
-struct VisitContext {
- int nRowPerTrans;
- sqlite3 *db; /* Database handle */
- sqlite3_stmt *pInsert; /* INSERT INTO fts VALUES(readtext(:1)) */
-};
-
-/*
-** Callback used with traverse(). The first argument points to an object
-** of type VisitContext. This function inserts the contents of the text
-** file zPath into the FTS table.
-*/
-void visit_file(void *pCtx, const char *zPath){
- int rc;
- VisitContext *p = (VisitContext*)pCtx;
- /* printf("%s\n", zPath); */
- sqlite3_bind_text(p->pInsert, 1, zPath, -1, SQLITE_STATIC);
- sqlite3_step(p->pInsert);
- rc = sqlite3_reset(p->pInsert);
- if( rc!=SQLITE_OK ){
- sqlite_error_out("insert", p->db);
- }else if( p->nRowPerTrans>0
- && (sqlite3_last_insert_rowid(p->db) % p->nRowPerTrans)==0
- ){
- sqlite3_exec(p->db, "COMMIT ; BEGIN", 0, 0, 0);
- }
-}
-
-/*
-** Recursively traverse directory zDir. For each file that is not a
-** directory, invoke the supplied callback with its path.
-*/
-static void traverse(
- const char *zDir, /* Directory to traverse */
- void *pCtx, /* First argument passed to callback */
- void (*xCallback)(void*, const char *zPath)
-){
- DIR *d;
- struct dirent *e;
-
- d = opendir(zDir);
- if( d==0 ) error_out("opendir()");
-
- for(e=readdir(d); e; e=readdir(d)){
- if( strcmp(e->d_name, ".")==0 || strcmp(e->d_name, "..")==0 ) continue;
- char *zPath = sqlite3_mprintf("%s/%s", zDir, e->d_name);
- if (e->d_type & DT_DIR) {
- traverse(zPath, pCtx, xCallback);
- }else{
- xCallback(pCtx, zPath);
- }
- sqlite3_free(zPath);
- }
-
- closedir(d);
-}
-
-int main(int argc, char **argv){
- int iFts = 5; /* Value of -fts option */
- int bMap = 0; /* True to create mapping table */
- const char *zDir = "."; /* Directory to scan */
- int i;
- int rc;
- int nRowPerTrans = 0;
- sqlite3 *db;
- char *zSql;
- VisitContext sCtx;
-
- int nCmd = 0;
- char **aCmd = 0;
-
- if( argc % 2 ) showHelp(argv[0]);
-
- for(i=1; i<(argc-1); i+=2){
- char *zOpt = argv[i];
- char *zArg = argv[i+1];
- if( strcmp(zOpt, "-fts")==0 ){
- iFts = atoi(zArg);
- if( iFts!=3 && iFts!=4 && iFts!= 5) showHelp(argv[0]);
- }
- else if( strcmp(zOpt, "-trans")==0 ){
- nRowPerTrans = atoi(zArg);
- }
- else if( strcmp(zOpt, "-idx")==0 ){
- bMap = atoi(zArg);
- if( bMap!=0 && bMap!=1 ) showHelp(argv[0]);
- }
- else if( strcmp(zOpt, "-dir")==0 ){
- zDir = zArg;
- }
- else if( strcmp(zOpt, "-special")==0 ){
- nCmd++;
- aCmd = sqlite3_realloc(aCmd, sizeof(char*) * nCmd);
- aCmd[nCmd-1] = zArg;
- }
- else{
- showHelp(argv[0]);
- }
- }
-
- /* Open the database file */
- rc = sqlite3_open(argv[argc-1], &db);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_open()", db);
-
- rc = sqlite3_create_function(db, "readtext", 1, SQLITE_UTF8, 0,
- readfileFunc, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_create_function()", db);
-
- /* Create the FTS table */
- zSql = sqlite3_mprintf("CREATE VIRTUAL TABLE fts USING fts%d(content)", iFts);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_exec(1)", db);
- sqlite3_free(zSql);
-
- for(i=0; i<nCmd; i++){
- zSql = sqlite3_mprintf("INSERT INTO fts(fts) VALUES(%Q)", aCmd[i]);
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_exec(1)", db);
- sqlite3_free(zSql);
- }
-
- /* Compile the INSERT statement to write data to the FTS table. */
- memset(&sCtx, 0, sizeof(VisitContext));
- sCtx.db = db;
- sCtx.nRowPerTrans = nRowPerTrans;
- rc = sqlite3_prepare_v2(db,
- "INSERT INTO fts VALUES(readtext(?))", -1, &sCtx.pInsert, 0
- );
- if( rc!=SQLITE_OK ) sqlite_error_out("sqlite3_prepare_v2(1)", db);
-
- /* Load all files in the directory hierarchy into the FTS table. */
- if( sCtx.nRowPerTrans>0 ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
- traverse(zDir, (void*)&sCtx, visit_file);
- if( sCtx.nRowPerTrans>0 ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
-
- /* Clean up and exit. */
- sqlite3_finalize(sCtx.pInsert);
- sqlite3_close(db);
- sqlite3_free(aCmd);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/logest.c b/lib/libsqlite3/tool/logest.c
deleted file mode 100644
index 347fa68a4f4..00000000000
--- a/lib/libsqlite3/tool/logest.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-** 2013-06-10
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains a simple command-line utility for converting from
-** integers and LogEst values and back again and for doing simple
-** arithmetic operations (multiple and add) on LogEst values.
-**
-** Usage:
-**
-** ./LogEst ARGS
-**
-** See the showHelp() routine for a description of valid arguments.
-** Examples:
-**
-** To convert 123 from LogEst to integer:
-**
-** ./LogEst ^123
-**
-** To convert 123456 from integer to LogEst:
-**
-** ./LogEst 123456
-**
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include "sqlite3.h"
-
-typedef short int LogEst; /* 10 times log2() */
-
-LogEst logEstMultiply(LogEst a, LogEst b){ return a+b; }
-LogEst logEstAdd(LogEst a, LogEst b){
- static const unsigned char x[] = {
- 10, 10, /* 0,1 */
- 9, 9, /* 2,3 */
- 8, 8, /* 4,5 */
- 7, 7, 7, /* 6,7,8 */
- 6, 6, 6, /* 9,10,11 */
- 5, 5, 5, /* 12-14 */
- 4, 4, 4, 4, /* 15-18 */
- 3, 3, 3, 3, 3, 3, /* 19-24 */
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
- };
- if( a<b ){ LogEst t = a; a = b; b = t; }
- if( a>b+49 ) return a;
- if( a>b+31 ) return a+1;
- return a+x[a-b];
-}
-LogEst logEstFromInteger(sqlite3_uint64 x){
- static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
- LogEst y = 40;
- if( x<8 ){
- if( x<2 ) return 0;
- while( x<8 ){ y -= 10; x <<= 1; }
- }else{
- while( x>255 ){ y += 40; x >>= 4; }
- while( x>15 ){ y += 10; x >>= 1; }
- }
- return a[x&7] + y - 10;
-}
-static sqlite3_uint64 logEstToInt(LogEst x){
- sqlite3_uint64 n;
- if( x<10 ) return 1;
- n = x%10;
- x /= 10;
- if( n>=5 ) n -= 2;
- else if( n>=1 ) n -= 1;
- if( x>=3 ) return (n+8)<<(x-3);
- return (n+8)>>(3-x);
-}
-static LogEst logEstFromDouble(double x){
- sqlite3_uint64 a;
- LogEst e;
- assert( sizeof(x)==8 && sizeof(a)==8 );
- if( x<=0.0 ) return -32768;
- if( x<0.01 ) return -logEstFromDouble(1.0/x);
- if( x<1.0 ) return logEstFromDouble(100.0*x) - 66;
- if( x<1024.0 ) return logEstFromInteger((sqlite3_uint64)(1024.0*x)) - 100;
- if( x<=2000000000.0 ) return logEstFromInteger((sqlite3_uint64)x);
- memcpy(&a, &x, 8);
- e = (a>>52) - 1022;
- return e*10;
-}
-
-int isInteger(const char *z){
- while( z[0]>='0' && z[0]<='9' ) z++;
- return z[0]==0;
-}
-
-int isFloat(const char *z){
- char c;
- while( ((c=z[0])>='0' && c<='9') || c=='.' || c=='E' || c=='e'
- || c=='+' || c=='-' ) z++;
- return z[0]==0;
-}
-
-static void showHelp(const char *zArgv0){
- printf("Usage: %s ARGS...\n", zArgv0);
- printf("Arguments:\n"
- " NUM Convert NUM from integer to LogEst and push onto the stack\n"
- " ^NUM Interpret NUM as a LogEst and push onto stack\n"
- " x Multiple the top two elements of the stack\n"
- " + Add the top two elements of the stack\n"
- " dup Dupliate the top element on the stack\n"
- " inv Take the reciprocal of the top of stack. N = 1/N.\n"
- " log Find the LogEst of the number on top of stack\n"
- " nlogn Compute NlogN where N is the top of stack\n"
- );
- exit(1);
-}
-
-int main(int argc, char **argv){
- int i;
- int n = 0;
- LogEst a[100];
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( strcmp(z,"+")==0 ){
- if( n>=2 ){
- a[n-2] = logEstAdd(a[n-2],a[n-1]);
- n--;
- }
- }else if( strcmp(z,"x")==0 ){
- if( n>=2 ){
- a[n-2] = logEstMultiply(a[n-2],a[n-1]);
- n--;
- }
- }else if( strcmp(z,"dup")==0 ){
- if( n>0 ){
- a[n] = a[n-1];
- n++;
- }
- }else if( strcmp(z,"log")==0 ){
- if( n>0 ) a[n-1] = logEstFromInteger(a[n-1]) - 33;
- }else if( strcmp(z,"nlogn")==0 ){
- if( n>0 ) a[n-1] += logEstFromInteger(a[n-1]) - 33;
- }else if( strcmp(z,"inv")==0 ){
- if( n>0 ) a[n-1] = -a[n-1];
- }else if( z[0]=='^' ){
- a[n++] = atoi(z+1);
- }else if( isInteger(z) ){
- a[n++] = logEstFromInteger(atoi(z));
- }else if( isFloat(z) && z[0]!='-' ){
- a[n++] = logEstFromDouble(atof(z));
- }else{
- showHelp(argv[0]);
- }
- }
- for(i=n-1; i>=0; i--){
- if( a[i]<-40 ){
- printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
- }else if( a[i]<10 ){
- printf("%5d (%f)\n", a[i], logEstToInt(a[i]+100)/1024.0);
- }else{
- sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024;
- printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100);
- }
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/mkautoconfamal.sh b/lib/libsqlite3/tool/mkautoconfamal.sh
deleted file mode 100644
index 0c2668c8b7e..00000000000
--- a/lib/libsqlite3/tool/mkautoconfamal.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/sh
-# This script is used to build the amalgamation autoconf package.
-# It assumes the following:
-#
-# 1. The files "sqlite3.c", "sqlite3.h" and "sqlite3ext.h"
-# are available in the current directory.
-#
-# 2. Variable $TOP is set to the full path of the root directory
-# of the SQLite source tree.
-#
-# 3. There is nothing of value in the ./mkpkg_tmp_dir directory.
-# This is important, as the script executes "rm -rf ./mkpkg_tmp_dir".
-#
-
-
-# Bail out of the script if any command returns a non-zero exit
-# status. Or if the script tries to use an unset variable. These
-# may fail for old /bin/sh interpreters.
-#
-set -e
-set -u
-
-TMPSPACE=./mkpkg_tmp_dir
-VERSION=`cat $TOP/VERSION`
-
-# Set global variable $ARTIFACT to the "3xxyyzz" string incorporated
-# into artifact filenames. And $VERSION2 to the "3.x.y[.z]" form.
-xx=`echo $VERSION|sed 's/3\.\([0-9]*\)\..*/\1/'`
-yy=`echo $VERSION|sed 's/3\.[^.]*\.\([0-9]*\).*/\1/'`
-zz=0
-set +e
- zz=`echo $VERSION|sed 's/3\.[^.]*\.[^.]*\.\([0-9]*\).*/\1/'|grep -v '\.'`
-set -e
-ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz`
-
-rm -rf $TMPSPACE
-cp -R $TOP/autoconf $TMPSPACE
-
-cp sqlite3.c $TMPSPACE
-cp sqlite3.h $TMPSPACE
-cp sqlite3ext.h $TMPSPACE
-cp $TOP/sqlite3.1 $TMPSPACE
-cp $TOP/sqlite3.pc.in $TMPSPACE
-cp $TOP/src/shell.c $TMPSPACE
-
-chmod 755 $TMPSPACE/install-sh
-chmod 755 $TMPSPACE/missing
-chmod 755 $TMPSPACE/depcomp
-chmod 755 $TMPSPACE/config.sub
-chmod 755 $TMPSPACE/config.guess
-
-cat $TMPSPACE/configure.ac |
-sed "s/AC_INIT(sqlite, .*, http:\/\/www.sqlite.org)/AC_INIT(sqlite, $VERSION, http:\/\/www.sqlite.org)/" > $TMPSPACE/tmp
-mv $TMPSPACE/tmp $TMPSPACE/configure.ac
-
-cd $TMPSPACE
-aclocal
-autoconf
-automake
-
-mkdir -p tea/generic
-echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c
-echo "# include <sqlite3.h>" >> tea/generic/tclsqlite3.c
-echo "#else" >> tea/generic/tclsqlite3.c
-echo "#include \"sqlite3.c\"" >> tea/generic/tclsqlite3.c
-echo "#endif" >> tea/generic/tclsqlite3.c
-cat $TOP/src/tclsqlite.c >> tea/generic/tclsqlite3.c
-
-cat tea/configure.ac |
- sed "s/AC_INIT(\[sqlite\], .*)/AC_INIT([sqlite], [$VERSION])/" > tmp
-mv tmp tea/configure.ac
-
-cd tea
-autoconf
-rm -rf autom4te.cache
-
-cd ../
-./configure && make dist
-tar -xzf sqlite-$VERSION.tar.gz
-mv sqlite-$VERSION sqlite-autoconf-$ARTIFACT
-tar -czf sqlite-autoconf-$ARTIFACT.tar.gz sqlite-autoconf-$ARTIFACT
-mv sqlite-autoconf-$ARTIFACT.tar.gz ..
diff --git a/lib/libsqlite3/tool/mkkeywordhash.c b/lib/libsqlite3/tool/mkkeywordhash.c
deleted file mode 100644
index 721611f5a36..00000000000
--- a/lib/libsqlite3/tool/mkkeywordhash.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
-** Compile and run this standalone program in order to generate code that
-** implements a function that will translate alphabetic identifiers into
-** parser token codes.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/*
-** A header comment placed at the beginning of generated code.
-*/
-static const char zHdr[] =
- "/***** This file contains automatically generated code ******\n"
- "**\n"
- "** The code in this file has been automatically generated by\n"
- "**\n"
- "** sqlite/tool/mkkeywordhash.c\n"
- "**\n"
- "** The code in this file implements a function that determines whether\n"
- "** or not a given identifier is really an SQL keyword. The same thing\n"
- "** might be implemented more directly using a hand-written hash table.\n"
- "** But by using this automatically generated code, the size of the code\n"
- "** is substantially reduced. This is important for embedded applications\n"
- "** on platforms with limited memory.\n"
- "*/\n"
-;
-
-/*
-** All the keywords of the SQL language are stored in a hash
-** table composed of instances of the following structure.
-*/
-typedef struct Keyword Keyword;
-struct Keyword {
- char *zName; /* The keyword name */
- char *zTokenType; /* Token value for this keyword */
- int mask; /* Code this keyword if non-zero */
- int id; /* Unique ID for this record */
- int hash; /* Hash on the keyword */
- int offset; /* Offset to start of name string */
- int len; /* Length of this keyword, not counting final \000 */
- int prefix; /* Number of characters in prefix */
- int longestSuffix; /* Longest suffix that is a prefix on another word */
- int iNext; /* Index in aKeywordTable[] of next with same hash */
- int substrId; /* Id to another keyword this keyword is embedded in */
- int substrOffset; /* Offset into substrId for start of this keyword */
- char zOrigName[20]; /* Original keyword name before processing */
-};
-
-/*
-** Define masks used to determine which keywords are allowed
-*/
-#ifdef SQLITE_OMIT_ALTERTABLE
-# define ALTER 0
-#else
-# define ALTER 0x00000001
-#endif
-#define ALWAYS 0x00000002
-#ifdef SQLITE_OMIT_ANALYZE
-# define ANALYZE 0
-#else
-# define ANALYZE 0x00000004
-#endif
-#ifdef SQLITE_OMIT_ATTACH
-# define ATTACH 0
-#else
-# define ATTACH 0x00000008
-#endif
-#ifdef SQLITE_OMIT_AUTOINCREMENT
-# define AUTOINCR 0
-#else
-# define AUTOINCR 0x00000010
-#endif
-#ifdef SQLITE_OMIT_CAST
-# define CAST 0
-#else
-# define CAST 0x00000020
-#endif
-#ifdef SQLITE_OMIT_COMPOUND_SELECT
-# define COMPOUND 0
-#else
-# define COMPOUND 0x00000040
-#endif
-#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
-# define CONFLICT 0
-#else
-# define CONFLICT 0x00000080
-#endif
-#ifdef SQLITE_OMIT_EXPLAIN
-# define EXPLAIN 0
-#else
-# define EXPLAIN 0x00000100
-#endif
-#ifdef SQLITE_OMIT_FOREIGN_KEY
-# define FKEY 0
-#else
-# define FKEY 0x00000200
-#endif
-#ifdef SQLITE_OMIT_PRAGMA
-# define PRAGMA 0
-#else
-# define PRAGMA 0x00000400
-#endif
-#ifdef SQLITE_OMIT_REINDEX
-# define REINDEX 0
-#else
-# define REINDEX 0x00000800
-#endif
-#ifdef SQLITE_OMIT_SUBQUERY
-# define SUBQUERY 0
-#else
-# define SUBQUERY 0x00001000
-#endif
-#ifdef SQLITE_OMIT_TRIGGER
-# define TRIGGER 0
-#else
-# define TRIGGER 0x00002000
-#endif
-#if defined(SQLITE_OMIT_AUTOVACUUM) && \
- (defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH))
-# define VACUUM 0
-#else
-# define VACUUM 0x00004000
-#endif
-#ifdef SQLITE_OMIT_VIEW
-# define VIEW 0
-#else
-# define VIEW 0x00008000
-#endif
-#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define VTAB 0
-#else
-# define VTAB 0x00010000
-#endif
-#ifdef SQLITE_OMIT_AUTOVACUUM
-# define AUTOVACUUM 0
-#else
-# define AUTOVACUUM 0x00020000
-#endif
-#ifdef SQLITE_OMIT_CTE
-# define CTE 0
-#else
-# define CTE 0x00040000
-#endif
-
-/*
-** These are the keywords
-*/
-static Keyword aKeywordTable[] = {
- { "ABORT", "TK_ABORT", CONFLICT|TRIGGER },
- { "ACTION", "TK_ACTION", FKEY },
- { "ADD", "TK_ADD", ALTER },
- { "AFTER", "TK_AFTER", TRIGGER },
- { "ALL", "TK_ALL", ALWAYS },
- { "ALTER", "TK_ALTER", ALTER },
- { "ANALYZE", "TK_ANALYZE", ANALYZE },
- { "AND", "TK_AND", ALWAYS },
- { "AS", "TK_AS", ALWAYS },
- { "ASC", "TK_ASC", ALWAYS },
- { "ATTACH", "TK_ATTACH", ATTACH },
- { "AUTOINCREMENT", "TK_AUTOINCR", AUTOINCR },
- { "BEFORE", "TK_BEFORE", TRIGGER },
- { "BEGIN", "TK_BEGIN", ALWAYS },
- { "BETWEEN", "TK_BETWEEN", ALWAYS },
- { "BY", "TK_BY", ALWAYS },
- { "CASCADE", "TK_CASCADE", FKEY },
- { "CASE", "TK_CASE", ALWAYS },
- { "CAST", "TK_CAST", CAST },
- { "CHECK", "TK_CHECK", ALWAYS },
- { "COLLATE", "TK_COLLATE", ALWAYS },
- { "COLUMN", "TK_COLUMNKW", ALTER },
- { "COMMIT", "TK_COMMIT", ALWAYS },
- { "CONFLICT", "TK_CONFLICT", CONFLICT },
- { "CONSTRAINT", "TK_CONSTRAINT", ALWAYS },
- { "CREATE", "TK_CREATE", ALWAYS },
- { "CROSS", "TK_JOIN_KW", ALWAYS },
- { "CURRENT_DATE", "TK_CTIME_KW", ALWAYS },
- { "CURRENT_TIME", "TK_CTIME_KW", ALWAYS },
- { "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS },
- { "DATABASE", "TK_DATABASE", ATTACH },
- { "DEFAULT", "TK_DEFAULT", ALWAYS },
- { "DEFERRED", "TK_DEFERRED", ALWAYS },
- { "DEFERRABLE", "TK_DEFERRABLE", FKEY },
- { "DELETE", "TK_DELETE", ALWAYS },
- { "DESC", "TK_DESC", ALWAYS },
- { "DETACH", "TK_DETACH", ATTACH },
- { "DISTINCT", "TK_DISTINCT", ALWAYS },
- { "DROP", "TK_DROP", ALWAYS },
- { "END", "TK_END", ALWAYS },
- { "EACH", "TK_EACH", TRIGGER },
- { "ELSE", "TK_ELSE", ALWAYS },
- { "ESCAPE", "TK_ESCAPE", ALWAYS },
- { "EXCEPT", "TK_EXCEPT", COMPOUND },
- { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
- { "EXISTS", "TK_EXISTS", ALWAYS },
- { "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
- { "FAIL", "TK_FAIL", CONFLICT|TRIGGER },
- { "FOR", "TK_FOR", TRIGGER },
- { "FOREIGN", "TK_FOREIGN", FKEY },
- { "FROM", "TK_FROM", ALWAYS },
- { "FULL", "TK_JOIN_KW", ALWAYS },
- { "GLOB", "TK_LIKE_KW", ALWAYS },
- { "GROUP", "TK_GROUP", ALWAYS },
- { "HAVING", "TK_HAVING", ALWAYS },
- { "IF", "TK_IF", ALWAYS },
- { "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER },
- { "IMMEDIATE", "TK_IMMEDIATE", ALWAYS },
- { "IN", "TK_IN", ALWAYS },
- { "INDEX", "TK_INDEX", ALWAYS },
- { "INDEXED", "TK_INDEXED", ALWAYS },
- { "INITIALLY", "TK_INITIALLY", FKEY },
- { "INNER", "TK_JOIN_KW", ALWAYS },
- { "INSERT", "TK_INSERT", ALWAYS },
- { "INSTEAD", "TK_INSTEAD", TRIGGER },
- { "INTERSECT", "TK_INTERSECT", COMPOUND },
- { "INTO", "TK_INTO", ALWAYS },
- { "IS", "TK_IS", ALWAYS },
- { "ISNULL", "TK_ISNULL", ALWAYS },
- { "JOIN", "TK_JOIN", ALWAYS },
- { "KEY", "TK_KEY", ALWAYS },
- { "LEFT", "TK_JOIN_KW", ALWAYS },
- { "LIKE", "TK_LIKE_KW", ALWAYS },
- { "LIMIT", "TK_LIMIT", ALWAYS },
- { "MATCH", "TK_MATCH", ALWAYS },
- { "NATURAL", "TK_JOIN_KW", ALWAYS },
- { "NO", "TK_NO", FKEY },
- { "NOT", "TK_NOT", ALWAYS },
- { "NOTNULL", "TK_NOTNULL", ALWAYS },
- { "NULL", "TK_NULL", ALWAYS },
- { "OF", "TK_OF", ALWAYS },
- { "OFFSET", "TK_OFFSET", ALWAYS },
- { "ON", "TK_ON", ALWAYS },
- { "OR", "TK_OR", ALWAYS },
- { "ORDER", "TK_ORDER", ALWAYS },
- { "OUTER", "TK_JOIN_KW", ALWAYS },
- { "PLAN", "TK_PLAN", EXPLAIN },
- { "PRAGMA", "TK_PRAGMA", PRAGMA },
- { "PRIMARY", "TK_PRIMARY", ALWAYS },
- { "QUERY", "TK_QUERY", EXPLAIN },
- { "RAISE", "TK_RAISE", TRIGGER },
- { "RECURSIVE", "TK_RECURSIVE", CTE },
- { "REFERENCES", "TK_REFERENCES", FKEY },
- { "REGEXP", "TK_LIKE_KW", ALWAYS },
- { "REINDEX", "TK_REINDEX", REINDEX },
- { "RELEASE", "TK_RELEASE", ALWAYS },
- { "RENAME", "TK_RENAME", ALTER },
- { "REPLACE", "TK_REPLACE", CONFLICT },
- { "RESTRICT", "TK_RESTRICT", FKEY },
- { "RIGHT", "TK_JOIN_KW", ALWAYS },
- { "ROLLBACK", "TK_ROLLBACK", ALWAYS },
- { "ROW", "TK_ROW", TRIGGER },
- { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS },
- { "SELECT", "TK_SELECT", ALWAYS },
- { "SET", "TK_SET", ALWAYS },
- { "TABLE", "TK_TABLE", ALWAYS },
- { "TEMP", "TK_TEMP", ALWAYS },
- { "TEMPORARY", "TK_TEMP", ALWAYS },
- { "THEN", "TK_THEN", ALWAYS },
- { "TO", "TK_TO", ALWAYS },
- { "TRANSACTION", "TK_TRANSACTION", ALWAYS },
- { "TRIGGER", "TK_TRIGGER", TRIGGER },
- { "UNION", "TK_UNION", COMPOUND },
- { "UNIQUE", "TK_UNIQUE", ALWAYS },
- { "UPDATE", "TK_UPDATE", ALWAYS },
- { "USING", "TK_USING", ALWAYS },
- { "VACUUM", "TK_VACUUM", VACUUM },
- { "VALUES", "TK_VALUES", ALWAYS },
- { "VIEW", "TK_VIEW", VIEW },
- { "VIRTUAL", "TK_VIRTUAL", VTAB },
- { "WITH", "TK_WITH", CTE },
- { "WITHOUT", "TK_WITHOUT", ALWAYS },
- { "WHEN", "TK_WHEN", ALWAYS },
- { "WHERE", "TK_WHERE", ALWAYS },
-};
-
-/* Number of keywords */
-static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]));
-
-/* An array to map all upper-case characters into their corresponding
-** lower-case character.
-*/
-const unsigned char sqlite3UpperToLower[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
- 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
- 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
- 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
- 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
- 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
- 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
- 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
-};
-#define UpperToLower sqlite3UpperToLower
-
-/*
-** Comparision function for two Keyword records
-*/
-static int keywordCompare1(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pA->len - pB->len;
- if( n==0 ){
- n = strcmp(pA->zName, pB->zName);
- }
- assert( n!=0 );
- return n;
-}
-static int keywordCompare2(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pB->longestSuffix - pA->longestSuffix;
- if( n==0 ){
- n = strcmp(pA->zName, pB->zName);
- }
- assert( n!=0 );
- return n;
-}
-static int keywordCompare3(const void *a, const void *b){
- const Keyword *pA = (Keyword*)a;
- const Keyword *pB = (Keyword*)b;
- int n = pA->offset - pB->offset;
- if( n==0 ) n = pB->id - pA->id;
- assert( n!=0 );
- return n;
-}
-
-/*
-** Return a KeywordTable entry with the given id
-*/
-static Keyword *findById(int id){
- int i;
- for(i=0; i<nKeyword; i++){
- if( aKeywordTable[i].id==id ) break;
- }
- return &aKeywordTable[i];
-}
-
-/*
-** This routine does the work. The generated code is printed on standard
-** output.
-*/
-int main(int argc, char **argv){
- int i, j, k, h;
- int bestSize, bestCount;
- int count;
- int nChar;
- int totalLen = 0;
- int aHash[1000]; /* 1000 is much bigger than nKeyword */
- char zText[2000];
-
- /* Remove entries from the list of keywords that have mask==0 */
- for(i=j=0; i<nKeyword; i++){
- if( aKeywordTable[i].mask==0 ) continue;
- if( j<i ){
- aKeywordTable[j] = aKeywordTable[i];
- }
- j++;
- }
- nKeyword = j;
-
- /* Fill in the lengths of strings and hashes for all entries. */
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- p->len = (int)strlen(p->zName);
- assert( p->len<sizeof(p->zOrigName) );
- memcpy(p->zOrigName, p->zName, p->len+1);
- totalLen += p->len;
- p->hash = (UpperToLower[(int)p->zName[0]]*4) ^
- (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len;
- p->id = i+1;
- }
-
- /* Sort the table from shortest to longest keyword */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare1);
-
- /* Look for short keywords embedded in longer keywords */
- for(i=nKeyword-2; i>=0; i--){
- Keyword *p = &aKeywordTable[i];
- for(j=nKeyword-1; j>i && p->substrId==0; j--){
- Keyword *pOther = &aKeywordTable[j];
- if( pOther->substrId ) continue;
- if( pOther->len<=p->len ) continue;
- for(k=0; k<=pOther->len-p->len; k++){
- if( memcmp(p->zName, &pOther->zName[k], p->len)==0 ){
- p->substrId = pOther->id;
- p->substrOffset = k;
- break;
- }
- }
- }
- }
-
- /* Compute the longestSuffix value for every word */
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ) continue;
- for(j=0; j<nKeyword; j++){
- Keyword *pOther;
- if( j==i ) continue;
- pOther = &aKeywordTable[j];
- if( pOther->substrId ) continue;
- for(k=p->longestSuffix+1; k<p->len && k<pOther->len; k++){
- if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){
- p->longestSuffix = k;
- }
- }
- }
- }
-
- /* Sort the table into reverse order by length */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare2);
-
- /* Fill in the offset for all entries */
- nChar = 0;
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->offset>0 || p->substrId ) continue;
- p->offset = nChar;
- nChar += p->len;
- for(k=p->len-1; k>=1; k--){
- for(j=i+1; j<nKeyword; j++){
- Keyword *pOther = &aKeywordTable[j];
- if( pOther->offset>0 || pOther->substrId ) continue;
- if( pOther->len<=k ) continue;
- if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){
- p = pOther;
- p->offset = nChar - k;
- nChar = p->offset + p->len;
- p->zName += k;
- p->len -= k;
- p->prefix = k;
- j = i;
- k = p->len;
- }
- }
- }
- }
- for(i=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ){
- p->offset = findById(p->substrId)->offset + p->substrOffset;
- }
- }
-
- /* Sort the table by offset */
- qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare3);
-
- /* Figure out how big to make the hash table in order to minimize the
- ** number of collisions */
- bestSize = nKeyword;
- bestCount = nKeyword*nKeyword;
- for(i=nKeyword/2; i<=2*nKeyword; i++){
- for(j=0; j<i; j++) aHash[j] = 0;
- for(j=0; j<nKeyword; j++){
- h = aKeywordTable[j].hash % i;
- aHash[h] *= 2;
- aHash[h]++;
- }
- for(j=count=0; j<i; j++) count += aHash[j];
- if( count<bestCount ){
- bestCount = count;
- bestSize = i;
- }
- }
-
- /* Compute the hash */
- for(i=0; i<bestSize; i++) aHash[i] = 0;
- for(i=0; i<nKeyword; i++){
- h = aKeywordTable[i].hash % bestSize;
- aKeywordTable[i].iNext = aHash[h];
- aHash[h] = i+1;
- }
-
- /* Begin generating code */
- printf("%s", zHdr);
- printf("/* Hash score: %d */\n", bestCount);
- printf("static int keywordCode(const char *z, int n){\n");
- printf(" /* zText[] encodes %d bytes of keywords in %d bytes */\n",
- totalLen + nKeyword, nChar+1 );
- for(i=j=k=0; i<nKeyword; i++){
- Keyword *p = &aKeywordTable[i];
- if( p->substrId ) continue;
- memcpy(&zText[k], p->zName, p->len);
- k += p->len;
- if( j+p->len>70 ){
- printf("%*s */\n", 74-j, "");
- j = 0;
- }
- if( j==0 ){
- printf(" /* ");
- j = 8;
- }
- printf("%s", p->zName);
- j += p->len;
- }
- if( j>0 ){
- printf("%*s */\n", 74-j, "");
- }
- printf(" static const char zText[%d] = {\n", nChar);
- zText[nChar] = 0;
- for(i=j=0; i<k; i++){
- if( j==0 ){
- printf(" ");
- }
- if( zText[i]==0 ){
- printf("0");
- }else{
- printf("'%c',", zText[i]);
- }
- j += 4;
- if( j>68 ){
- printf("\n");
- j = 0;
- }
- }
- if( j>0 ) printf("\n");
- printf(" };\n");
-
- printf(" static const unsigned char aHash[%d] = {\n", bestSize);
- for(i=j=0; i<bestSize; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aHash[i]);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s };\n", j==0 ? "" : "\n");
-
- printf(" static const unsigned char aNext[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].iNext);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s };\n", j==0 ? "" : "\n");
-
- printf(" static const unsigned char aLen[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].len+aKeywordTable[i].prefix);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s };\n", j==0 ? "" : "\n");
-
- printf(" static const unsigned short int aOffset[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- if( j==0 ) printf(" ");
- printf(" %3d,", aKeywordTable[i].offset);
- j++;
- if( j>12 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s };\n", j==0 ? "" : "\n");
-
- printf(" static const unsigned char aCode[%d] = {\n", nKeyword);
- for(i=j=0; i<nKeyword; i++){
- char *zToken = aKeywordTable[i].zTokenType;
- if( j==0 ) printf(" ");
- printf("%s,%*s", zToken, (int)(14-strlen(zToken)), "");
- j++;
- if( j>=5 ){
- printf("\n");
- j = 0;
- }
- }
- printf("%s };\n", j==0 ? "" : "\n");
-
- printf(" int h, i;\n");
- printf(" if( n<2 ) return TK_ID;\n");
- printf(" h = ((charMap(z[0])*4) ^\n"
- " (charMap(z[n-1])*3) ^\n"
- " n) %% %d;\n", bestSize);
- printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n");
- printf(" if( aLen[i]==n &&"
- " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n");
- for(i=0; i<nKeyword; i++){
- printf(" testcase( i==%d ); /* %s */\n",
- i, aKeywordTable[i].zOrigName);
- }
- printf(" return aCode[i];\n");
- printf(" }\n");
- printf(" }\n");
- printf(" return TK_ID;\n");
- printf("}\n");
- printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n");
- printf(" return keywordCode((char*)z, n);\n");
- printf("}\n");
- printf("#define SQLITE_N_KEYWORD %d\n", nKeyword);
-
- return 0;
-}
diff --git a/lib/libsqlite3/tool/mkopts.tcl b/lib/libsqlite3/tool/mkopts.tcl
deleted file mode 100644
index e3ddcb9eeb3..00000000000
--- a/lib/libsqlite3/tool/mkopts.tcl
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script is used to generate the array of strings and the enum
-# that appear at the beginning of the C code implementation of a
-# a TCL command and that define the available subcommands for that
-# TCL command.
-
-set prefix {}
-while {![eof stdin]} {
- set line [gets stdin]
- if {$line==""} continue
- regsub -all "\[ \t\n,\]+" [string trim $line] { } line
- foreach token [split $line { }] {
- if {![regexp {(([a-zA-Z]+)_)?([_a-zA-Z]+)} $token all px p2 name]} continue
- lappend namelist [string tolower $name]
- if {$px!=""} {set prefix $p2}
- }
-}
-
-puts " static const char *${prefix}_strs\[\] = \173"
-set col 0
-proc put_item x {
- global col
- if {$col==0} {puts -nonewline " "}
- if {$col<2} {
- puts -nonewline [format " %-21s" $x]
- incr col
- } else {
- puts $x
- set col 0
- }
-}
-proc finalize {} {
- global col
- if {$col>0} {puts {}}
- set col 0
-}
-
-foreach name [lsort $namelist] {
- put_item \"$name\",
-}
-put_item 0
-finalize
-puts " \175;"
-puts " enum ${prefix}_enum \173"
-foreach name [lsort $namelist] {
- regsub -all {@} $name {} name
- put_item ${prefix}_[string toupper $name],
-}
-finalize
-puts " \175;"
diff --git a/lib/libsqlite3/tool/mkpragmatab.tcl b/lib/libsqlite3/tool/mkpragmatab.tcl
deleted file mode 100644
index bbdf9da754a..00000000000
--- a/lib/libsqlite3/tool/mkpragmatab.tcl
+++ /dev/null
@@ -1,471 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script to generate the pragma name lookup table C code.
-#
-# To add new pragmas, first add the name and other relevant attributes
-# of the pragma to the "pragma_def" object below. Then run this script
-# to generate the ../src/pragma.h header file that contains macros and
-# the lookup table needed for pragma name lookup in the pragma.c module.
-# Then add the extra "case PragTyp_XXXXX:" and subsequent code for the
-# new pragma in ../src/pragma.c.
-#
-
-set pragma_def {
- NAME: full_column_names
- TYPE: FLAG
- ARG: SQLITE_FullColNames
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: short_column_names
- TYPE: FLAG
- ARG: SQLITE_ShortColNames
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: count_changes
- TYPE: FLAG
- ARG: SQLITE_CountRows
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: empty_result_callbacks
- TYPE: FLAG
- ARG: SQLITE_NullCallback
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: legacy_file_format
- TYPE: FLAG
- ARG: SQLITE_LegacyFileFmt
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: fullfsync
- TYPE: FLAG
- ARG: SQLITE_FullFSync
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: checkpoint_fullfsync
- TYPE: FLAG
- ARG: SQLITE_CkptFullFSync
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: cache_spill
- TYPE: FLAG
- ARG: SQLITE_CacheSpill
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: reverse_unordered_selects
- TYPE: FLAG
- ARG: SQLITE_ReverseOrder
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: query_only
- TYPE: FLAG
- ARG: SQLITE_QueryOnly
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: automatic_index
- TYPE: FLAG
- ARG: SQLITE_AutoIndex
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
-
- NAME: sql_trace
- TYPE: FLAG
- ARG: SQLITE_SqlTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_listing
- TYPE: FLAG
- ARG: SQLITE_VdbeListing
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_trace
- TYPE: FLAG
- ARG: SQLITE_VdbeTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_addoptrace
- TYPE: FLAG
- ARG: SQLITE_VdbeAddopTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_debug
- TYPE: FLAG
- ARG: SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: vdbe_eqp
- TYPE: FLAG
- ARG: SQLITE_VdbeEQP
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: defined(SQLITE_DEBUG)
-
- NAME: ignore_check_constraints
- TYPE: FLAG
- ARG: SQLITE_IgnoreChecks
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_CHECK)
-
- NAME: writable_schema
- TYPE: FLAG
- ARG: SQLITE_WriteSchema|SQLITE_RecoveryMode
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: read_uncommitted
- TYPE: FLAG
- ARG: SQLITE_ReadUncommitted
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: recursive_triggers
- TYPE: FLAG
- ARG: SQLITE_RecTriggers
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-
- NAME: foreign_keys
- TYPE: FLAG
- ARG: SQLITE_ForeignKeys
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: defer_foreign_keys
- TYPE: FLAG
- ARG: SQLITE_DeferFKs
- IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: cell_size_check
- TYPE: FLAG
- ARG: SQLITE_CellSizeCk
-
- NAME: default_cache_size
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
-
- NAME: page_size
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: secure_delete
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: page_count
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: max_page_count
- TYPE: PAGE_COUNT
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: locking_mode
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: journal_mode
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: journal_size_limit
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: cache_size
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: mmap_size
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: auto_vacuum
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_AUTOVACUUM)
-
- NAME: incremental_vacuum
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_AUTOVACUUM)
-
- NAME: temp_store
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: temp_store_directory
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: data_store_directory
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
-
- NAME: lock_proxy_file
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
-
- NAME: synchronous
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-
- NAME: table_info
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: stats
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: index_info
- TYPE: INDEX_INFO
- ARG: 0
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: index_xinfo
- TYPE: INDEX_INFO
- ARG: 1
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: index_list
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: database_list
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: collation_list
- IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-
- NAME: foreign_key_list
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
-
- NAME: foreign_key_check
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-
- NAME: parser_trace
- IF: defined(SQLITE_DEBUG)
-
- NAME: case_sensitive_like
-
- NAME: integrity_check
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
-
- NAME: quick_check
- TYPE: INTEGRITY_CHECK
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
-
- NAME: encoding
- IF: !defined(SQLITE_OMIT_UTF16)
-
- NAME: schema_version
- TYPE: HEADER_VALUE
- ARG: BTREE_SCHEMA_VERSION
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: user_version
- TYPE: HEADER_VALUE
- ARG: BTREE_USER_VERSION
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: data_version
- TYPE: HEADER_VALUE
- ARG: BTREE_DATA_VERSION
- FLAG: ReadOnly
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: freelist_count
- TYPE: HEADER_VALUE
- ARG: BTREE_FREE_PAGE_COUNT
- FLAG: ReadOnly
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: application_id
- TYPE: HEADER_VALUE
- ARG: BTREE_APPLICATION_ID
- IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-
- NAME: compile_options
- IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
-
- NAME: wal_checkpoint
- FLAG: NeedSchema
- IF: !defined(SQLITE_OMIT_WAL)
-
- NAME: wal_autocheckpoint
- IF: !defined(SQLITE_OMIT_WAL)
-
- NAME: shrink_memory
-
- NAME: busy_timeout
-
- NAME: lock_status
- IF: defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
-
- NAME: key
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: rekey
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: hexkey
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: hexrekey
- TYPE: HEXKEY
- IF: defined(SQLITE_HAS_CODEC)
-
- NAME: activate_extensions
- IF: defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-
- NAME: soft_heap_limit
-
- NAME: threads
-}
-
-# Open the output file
-#
-set destfile "[file dir [file dir [file normal $argv0]]]/src/pragma.h"
-puts "Overwriting $destfile with new pragma table..."
-set fd [open $destfile wb]
-puts $fd {/* DO NOT EDIT!
-** This file is automatically generated by the script at
-** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
-** that script and rerun it.
-*/}
-
-# Parse the PRAGMA table above.
-#
-set name {}
-set type {}
-set if {}
-set flags {}
-set arg 0
-proc record_one {} {
- global name type if arg allbyname typebyif flags
- if {$name==""} return
- set allbyname($name) [list $type $arg $if $flags]
- set name {}
- set type {}
- set if {}
- set flags {}
- set arg 0
-}
-foreach line [split $pragma_def \n] {
- set line [string trim $line]
- if {$line==""} continue
- foreach {id val} [split $line :] break
- set val [string trim $val]
- if {$id=="NAME"} {
- record_one
- set name $val
- set type [string toupper $val]
- } elseif {$id=="TYPE"} {
- set type $val
- } elseif {$id=="ARG"} {
- set arg $val
- } elseif {$id=="IF"} {
- lappend if $val
- } elseif {$id=="FLAG"} {
- foreach term [split $val] {
- lappend flags $term
- set allflags($term) 1
- }
- } else {
- error "bad pragma_def line: $line"
- }
-}
-record_one
-set allnames [lsort [array names allbyname]]
-
-# Generate #defines for all pragma type names. Group the pragmas that are
-# omit in default builds (defined(SQLITE_DEBUG) and defined(SQLITE_HAS_CODEC))
-# at the end.
-#
-set pnum 0
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set if [lindex $allbyname($name) 2]
- if {[regexp SQLITE_DEBUG $if] || [regexp SQLITE_HAS_CODEC $if]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set if [lindex $allbyname($name) 2]
- if {[regexp SQLITE_DEBUG $if]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-foreach name $allnames {
- set type [lindex $allbyname($name) 0]
- if {[info exists seentype($type)]} continue
- set seentype($type) 1
- puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum]
- incr pnum
-}
-
-# Generate #defines for flags
-#
-set fv 1
-foreach f [lsort [array names allflags]] {
- puts $fd [format {#define PragFlag_%-20s 0x%02x} $f $fv]
- set fv [expr {$fv*2}]
-}
-
-# Generate the lookup table
-#
-puts $fd "static const struct sPragmaNames \173"
-puts $fd " const char *const zName; /* Name of pragma */"
-puts $fd " u8 ePragTyp; /* PragTyp_XXX value */"
-puts $fd " u8 mPragFlag; /* Zero or more PragFlag_XXX values */"
-puts $fd " u32 iArg; /* Extra argument */"
-puts $fd "\175 aPragmaNames\[\] = \173"
-
-set current_if {}
-set spacer [format { %26s } {}]
-foreach name $allnames {
- foreach {type arg if flag} $allbyname($name) break
- if {$if!=$current_if} {
- if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#endif"
- }
- }
- set current_if $if
- if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#if $this_if"
- }
- }
- }
- set typex [format PragTyp_%-23s $type,]
- if {$flag==""} {
- set flagx "0"
- } else {
- set flagx PragFlag_[join $flag {|PragFlag_}]
- }
- puts $fd " \173 /* zName: */ \"$name\","
- puts $fd " /* ePragTyp: */ PragTyp_$type,"
- puts $fd " /* ePragFlag: */ $flagx,"
- puts $fd " /* iArg: */ $arg \175,"
-}
-if {$current_if!=""} {
- foreach this_if $current_if {
- puts $fd "#endif"
- }
-}
-puts $fd "\175;"
-
-# count the number of pragmas, for information purposes
-#
-set allcnt 0
-set dfltcnt 0
-foreach name $allnames {
- incr allcnt
- set if [lindex $allbyname($name) 2]
- if {[regexp {^defined} $if] || [regexp {[^!]defined} $if]} continue
- incr dfltcnt
-}
-puts $fd "/* Number of pragmas: $dfltcnt on by default, $allcnt total. */"
diff --git a/lib/libsqlite3/tool/mkspeedsql.tcl b/lib/libsqlite3/tool/mkspeedsql.tcl
deleted file mode 100644
index 65f8d3f0574..00000000000
--- a/lib/libsqlite3/tool/mkspeedsql.tcl
+++ /dev/null
@@ -1,237 +0,0 @@
-# 2008 October 9
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#*************************************************************************
-# This file generates SQL text used for performance testing.
-#
-# $Id: mkspeedsql.tcl,v 1.1.1.1 2012/04/14 13:13:17 espie Exp $
-#
-
-# Set a uniform random seed
-expr srand(0)
-
-# The number_name procedure below converts its argment (an integer)
-# into a string which is the English-language name for that number.
-#
-# Example:
-#
-# puts [number_name 123] -> "one hundred twenty three"
-#
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-# Create a database schema.
-#
-puts {
- PRAGMA page_size=1024;
- PRAGMA cache_size=8192;
- PRAGMA locking_mode=EXCLUSIVE;
- CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
- CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT);
- CREATE INDEX i2a ON t2(a);
- CREATE INDEX i2b ON t2(b);
- SELECT name FROM sqlite_master ORDER BY 1;
-}
-
-
-# 50000 INSERTs on an unindexed table
-#
-set t1c_list {}
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- set x [number_name $r]
- lappend t1c_list $x
- puts "INSERT INTO t1 VALUES($i,$r,'$x');"
-}
-puts {COMMIT;}
-
-# 50000 INSERTs on an indexed table
-#
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');"
-}
-puts {COMMIT;}
-
-
-# 50 SELECTs on an integer comparison. There is no index so
-# a full table scan is required.
-#
-for {set i 0} {$i<50} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
-}
-
-# 50 SELECTs on an LIKE comparison. There is no index so a full
-# table scan is required.
-#
-for {set i 0} {$i<50} {incr i} {
- puts "SELECT count(*), avg(b) FROM t1 WHERE c LIKE '%[number_name $i]%';"
-}
-
-# Create indices
-#
-puts {BEGIN;}
-puts {
- CREATE INDEX i1a ON t1(a);
- CREATE INDEX i1b ON t1(b);
- CREATE INDEX i1c ON t1(c);
-}
-puts {COMMIT;}
-
-# 5000 SELECTs on an integer comparison where the integer is
-# indexed.
-#
-set sql {}
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts "SELECT count(*), avg(b) FROM t1 WHERE b>=$lwr AND b<$upr;"
-}
-
-# 100000 random SELECTs against rowid.
-#
-for {set i 1} {$i<=100000} {incr i} {
- set id [expr {int(rand()*50000)+1}]
- puts "SELECT c FROM t1 WHERE rowid=$id;"
-}
-
-# 100000 random SELECTs against a unique indexed column.
-#
-for {set i 1} {$i<=100000} {incr i} {
- set id [expr {int(rand()*50000)+1}]
- puts "SELECT c FROM t1 WHERE a=$id;"
-}
-
-# 50000 random SELECTs against an indexed column text column
-#
-set nt1c [llength $t1c_list]
-for {set i 0} {$i<50000} {incr i} {
- set r [expr {int(rand()*$nt1c)}]
- set c [lindex $t1c_list $i]
- puts "SELECT c FROM t1 WHERE c='$c';"
-}
-
-
-# Vacuum
-puts {VACUUM;}
-
-# 5000 updates of ranges where the field being compared is indexed.
-#
-puts {BEGIN;}
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*2}]
- set upr [expr {($i+1)*2}]
- puts "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;"
-}
-puts {COMMIT;}
-
-# 50000 single-row updates. An index is used to find the row quickly.
-#
-puts {BEGIN;}
-for {set i 0} {$i<50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "UPDATE t1 SET b=$r WHERE a=$i;"
-}
-puts {COMMIT;}
-
-# 1 big text update that touches every row in the table.
-#
-puts {
- UPDATE t1 SET c=a;
-}
-
-# Many individual text updates. Each row in the table is
-# touched through an index.
-#
-puts {BEGIN;}
-for {set i 1} {$i<=50000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts "UPDATE t1 SET c='[number_name $r]' WHERE a=$i;"
-}
-puts {COMMIT;}
-
-# Delete all content in a table.
-#
-puts {DELETE FROM t1;}
-
-# Copy one table into another
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Delete all content in a table, one row at a time.
-#
-puts {DELETE FROM t1 WHERE 1;}
-
-# Refill the table yet again
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Drop the table and recreate it without its indices.
-#
-puts {BEGIN;}
-puts {
- DROP TABLE t1;
- CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
-}
-puts {COMMIT;}
-
-# Refill the table yet again. This copy should be faster because
-# there are no indices to deal with.
-#
-puts {INSERT INTO t1 SELECT * FROM t2;}
-
-# Select 20000 rows from the table at random.
-#
-puts {
- SELECT rowid FROM t1 ORDER BY random() LIMIT 20000;
-}
-
-# Delete 20000 random rows from the table.
-#
-puts {
- DELETE FROM t1 WHERE rowid IN
- (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000);
-}
-puts {SELECT count(*) FROM t1;}
-
-# Delete 20000 more rows at random from the table.
-#
-puts {
- DELETE FROM t1 WHERE rowid IN
- (SELECT rowid FROM t1 ORDER BY random() LIMIT 20000);
-}
-puts {SELECT count(*) FROM t1;}
diff --git a/lib/libsqlite3/tool/mksqlite3c-noext.tcl b/lib/libsqlite3/tool/mksqlite3c-noext.tcl
deleted file mode 100644
index 601b8cce8c3..00000000000
--- a/lib/libsqlite3/tool/mksqlite3c-noext.tcl
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c-noext.tcl
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Extract the version number
-# from in this file. The version number is needed to generate the header
-# comment of the amalgamation.
-#
-if {[lsearch $argv --nostatic]>=0} {
- set addstatic 0
-} else {
- set addstatic 1
-}
-if {[lsearch $argv --linemacros]>=0} {
- set linemacros 1
-} else {
- set linemacros 0
-}
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3.c w]
-# Force the output to use unix line endings, even on Windows.
-fconfigure $out -translation lf
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. 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
-** of 5% or more are commonly seen when SQLite is compiled as a single
-** translation unit.
-**
-** 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 "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
-** if you want a wrapper to interface SQLite with your choice of programming
-** language. The code for the "sqlite3" command-line shell is also in a
-** separate file. This file contains only code for the core SQLite library.
-*/
-#define SQLITE_CORE 1
-#define SQLITE_AMALGAMATION 1}]
-if {$addstatic} {
- puts $out \
-{#ifndef SQLITE_PRIVATE
-# define SQLITE_PRIVATE static
-#endif}
-}
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- mutex.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- pcache.h
- pragma.h
- sqlite3ext.h
- sqlite3.h
- sqliteicu.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
- vxworks.h
- wal.h
- whereInt.h
-} {
- set available_hdr($hdr) 1
-}
-set available_hdr(sqliteInt.h) 0
-
-# These headers should be copied into the amalgamation without modifying any
-# of their function declarations or definitions.
-set varonly_hdr(sqlite3.h) 1
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them appropriately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
- set ln 0
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- if {$linemacros} {puts $out "#line 1 \"$filename\""}
- set in [open $filename r]
- set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
- set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
- if {[file extension $filename]==".h"} {
- set declpattern " *$declpattern"
- }
- set declpattern ^$declpattern\$
- while {![eof $in]} {
- set line [gets $in]
- incr ln
- if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
- set available_hdr($hdr) 0
- }
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
- set seen_hdr($hdr) 1
- }
- puts $out $line
- } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
- # This include file must be kept because there was a "keep"
- # directive inside of a line comment.
- puts $out $line
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {!$linemacros && [regexp {^#line} $line]} {
- # Skip #line directives.
- } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
- # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
- # functions if this header file does not need it.
- if {![info exists varonly_hdr($tail)]
- && [regexp $declpattern $line all rettype funcname rest]} {
- regsub {^SQLITE_API } $line {} line
- # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
- # so that linkage can be modified at compile-time.
- if {[regexp {^sqlite3_} $funcname]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_STDCALL
- }
- append line " " $funcname $rest
- puts $out $line
- } else {
- puts $out "SQLITE_PRIVATE $line"
- }
- } elseif {[regexp $varpattern $line all varname]} {
- # Add the SQLITE_PRIVATE before variable declarations or
- # definitions for internal use
- regsub {^SQLITE_API } $line {} line
- if {![regexp {^sqlite3_} $varname]} {
- regsub {^extern } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- if {[regexp {const char sqlite3_version\[\];} $line]} {
- set line {const char sqlite3_version[] = SQLITE_VERSION;}
- }
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out "SQLITE_API $line"
- }
- } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
- regsub {^SQLITE_API } $line {} line
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out $line
- } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
- regsub {^SQLITE_API } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- puts $out $line
- }
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- sqliteInt.h
-
- global.c
- ctime.c
- status.c
- date.c
- os.c
-
- fault.c
- mem0.c
- mem1.c
- mem2.c
- mem3.c
- mem5.c
- mutex.c
- mutex_noop.c
- mutex_unix.c
- mutex_w32.c
- malloc.c
- printf.c
- random.c
- threads.c
- utf.c
- util.c
- hash.c
- opcodes.c
-
- os_unix.c
- os_win.c
-
- bitvec.c
- pcache.c
- pcache1.c
- rowset.c
- pager.c
- wal.c
-
- btmutex.c
- btree.c
- backup.c
-
- vdbemem.c
- vdbeaux.c
- vdbeapi.c
- vdbetrace.c
- vdbe.c
- vdbeblob.c
- vdbesort.c
- journal.c
- memjournal.c
-
- walker.c
- resolve.c
- expr.c
- alter.c
- analyze.c
- attach.c
- auth.c
- build.c
- callback.c
- delete.c
- func.c
- fkey.c
- insert.c
- legacy.c
- loadext.c
- pragma.c
- prepare.c
- select.c
- table.c
- trigger.c
- update.c
- vacuum.c
- vtab.c
- where.c
-
- parse.c
-
- tokenize.c
- complete.c
-
- main.c
- notify.c
-} {
- copy_file tsrc/$file
-}
-
-close $out
diff --git a/lib/libsqlite3/tool/mksqlite3c.tcl b/lib/libsqlite3/tool/mksqlite3c.tcl
deleted file mode 100644
index 23241e27a6e..00000000000
--- a/lib/libsqlite3/tool/mksqlite3c.tcl
+++ /dev/null
@@ -1,388 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c.tcl --srcdir $SRC
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Extract the version number
-# from in this file. The version number is needed to generate the header
-# comment of the amalgamation.
-#
-set addstatic 1
-set linemacros 0
-for {set i 0} {$i<[llength $argv]} {incr i} {
- set x [lindex $argv $i]
- if {[regexp {^-+nostatic$} $x]} {
- set addstatic 0
- } elseif {[regexp {^-+linemacros} $x]} {
- set linemacros 1
- } else {
- error "unknown command-line option: $x"
- }
-}
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3.c w]
-# Force the output to use unix line endings, even on Windows.
-fconfigure $out -translation lf
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. 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
-** of 5% or more are commonly seen when SQLite is compiled as a single
-** translation unit.
-**
-** 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 "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
-** if you want a wrapper to interface SQLite with your choice of programming
-** language. The code for the "sqlite3" command-line shell is also in a
-** separate file. This file contains only code for the core SQLite library.
-*/
-#define SQLITE_CORE 1
-#define SQLITE_AMALGAMATION 1}]
-if {$addstatic} {
- puts $out \
-{#ifndef SQLITE_PRIVATE
-# define SQLITE_PRIVATE static
-#endif}
-}
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- fts3.h
- fts3Int.h
- fts3_hash.h
- fts3_tokenizer.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- mutex.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- pcache.h
- pragma.h
- rtree.h
- sqlite3.h
- sqlite3ext.h
- sqlite3rbu.h
- sqliteicu.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
- vxworks.h
- wal.h
- whereInt.h
-} {
- set available_hdr($hdr) 1
-}
-set available_hdr(sqliteInt.h) 0
-
-# These headers should be copied into the amalgamation without modifying any
-# of their function declarations or definitions.
-set varonly_hdr(sqlite3.h) 1
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them appropriately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
- set ln 0
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- if {$linemacros} {puts $out "#line 1 \"$filename\""}
- set in [open $filename r]
- set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
- set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
- if {[file extension $filename]==".h"} {
- set declpattern " *$declpattern"
- }
- set declpattern ^$declpattern\$
- while {![eof $in]} {
- set line [gets $in]
- incr ln
- if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
- set available_hdr($hdr) 0
- }
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
- set seen_hdr($hdr) 1
- }
- puts $out $line
- } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
- # This include file must be kept because there was a "keep"
- # directive inside of a line comment.
- puts $out $line
- } else {
- # Comment out the entire line, replacing any nested comment
- # begin/end markers with the harmless substring "**".
- puts $out "/* [string map [list /* ** */ **] $line] */"
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {!$linemacros && [regexp {^#line} $line]} {
- # Skip #line directives.
- } elseif {$addstatic
- && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
- # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
- # functions if this header file does not need it.
- if {![info exists varonly_hdr($tail)]
- && [regexp $declpattern $line all rettype funcname rest]} {
- regsub {^SQLITE_API } $line {} line
- # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
- # so that linkage can be modified at compile-time.
- if {[regexp {^sqlite3(_|rbu_)} $funcname]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_STDCALL
- }
- append line " " $funcname $rest
- puts $out $line
- } else {
- puts $out "SQLITE_PRIVATE $line"
- }
- } elseif {[regexp $varpattern $line all varname]} {
- # Add the SQLITE_PRIVATE before variable declarations or
- # definitions for internal use
- regsub {^SQLITE_API } $line {} line
- if {![regexp {^sqlite3_} $varname]} {
- regsub {^extern } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- if {[regexp {const char sqlite3_version\[\];} $line]} {
- set line {const char sqlite3_version[] = SQLITE_VERSION;}
- }
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out "SQLITE_API $line"
- }
- } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
- regsub {^SQLITE_API } $line {} line
- regsub {^SQLITE_EXTERN } $line {} line
- puts $out $line
- } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
- regsub {^SQLITE_API } $line {} line
- puts $out "SQLITE_PRIVATE $line"
- } else {
- puts $out $line
- }
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- sqliteInt.h
-
- global.c
- ctime.c
- status.c
- date.c
- os.c
-
- fault.c
- mem0.c
- mem1.c
- mem2.c
- mem3.c
- mem5.c
- mutex.c
- mutex_noop.c
- mutex_unix.c
- mutex_w32.c
- malloc.c
- printf.c
- treeview.c
- random.c
- threads.c
- utf.c
- util.c
- hash.c
- opcodes.c
-
- os_unix.c
- os_win.c
-
- bitvec.c
- pcache.c
- pcache1.c
- rowset.c
- pager.c
- wal.c
-
- btmutex.c
- btree.c
- backup.c
-
- vdbemem.c
- vdbeaux.c
- vdbeapi.c
- vdbetrace.c
- vdbe.c
- vdbeblob.c
- vdbesort.c
- journal.c
- memjournal.c
-
- walker.c
- resolve.c
- expr.c
- alter.c
- analyze.c
- attach.c
- auth.c
- build.c
- callback.c
- delete.c
- func.c
- fkey.c
- insert.c
- legacy.c
- loadext.c
- pragma.c
- prepare.c
- select.c
- table.c
- trigger.c
- update.c
- vacuum.c
- vtab.c
- wherecode.c
- whereexpr.c
- where.c
-
- parse.c
-
- tokenize.c
- complete.c
-
- main.c
- notify.c
-
- fts3.c
- fts3_aux.c
- fts3_expr.c
- fts3_hash.c
- fts3_porter.c
- fts3_tokenizer.c
- fts3_tokenizer1.c
- fts3_tokenize_vtab.c
- fts3_write.c
- fts3_snippet.c
- fts3_unicode.c
- fts3_unicode2.c
-
- rtree.c
- icu.c
- fts3_icu.c
- sqlite3rbu.c
- dbstat.c
- json1.c
- fts5.c
-} {
- copy_file tsrc/$file
-}
-
-close $out
diff --git a/lib/libsqlite3/tool/mksqlite3h.tcl b/lib/libsqlite3/tool/mksqlite3h.tcl
deleted file mode 100644
index 3f59aef4675..00000000000
--- a/lib/libsqlite3/tool/mksqlite3h.tcl
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script constructs the "sqlite3.h" header file from the following
-# sources:
-#
-# 1) The src/sqlite.h.in source file. This is the template for sqlite3.h.
-# 2) The VERSION file containing the current SQLite version number.
-# 3) The manifest file from the fossil SCM. This gives use the date.
-# 4) The manifest.uuid file from the fossil SCM. This gives the SHA1 hash.
-#
-# Run this script by specifying the root directory of the source tree
-# on the command-line.
-#
-# This script performs processing on src/sqlite.h.in. It:
-#
-# 1) Adds SQLITE_EXTERN in front of the declaration of global variables,
-# 2) Adds SQLITE_API in front of the declaration of API functions,
-# 3) Replaces the string --VERS-- with the current library version,
-# formatted as a string (e.g. "3.6.17"), and
-# 4) Replaces the string --VERSION-NUMBER-- with current library version,
-# formatted as an integer (e.g. "3006017").
-# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
-# hash of the fossil-scm manifest for the source tree.
-#
-# This script outputs to stdout.
-#
-# Example usage:
-#
-# tclsh mksqlite3h.tcl ../sqlite >sqlite3.h
-#
-
-
-# Get the source tree root directory from the command-line
-#
-set TOP [lindex $argv 0]
-
-# Get the SQLite version number (ex: 3.6.18) from the $TOP/VERSION file.
-#
-set in [open $TOP/VERSION]
-set zVersion [string trim [read $in]]
-close $in
-set nVersion [eval format "%d%03d%03d" [split $zVersion .]]
-
-# Get the fossil-scm version number from $TOP/manifest.uuid.
-#
-set in [open $TOP/manifest.uuid]
-set zUuid [string trim [read $in]]
-close $in
-
-# Get the fossil-scm check-in date from the "D" card of $TOP/manifest.
-#
-set in [open $TOP/manifest]
-set zDate {}
-while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^D (2[-0-9T:]+)} $line all date]} {
- set zDate [string map {T { }} $date]
- break
- }
-}
-close $in
-
-# Set up patterns for recognizing API declarations.
-#
-set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)}
-set declpattern {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
-
-# Force the output to use unix line endings, even on Windows.
-fconfigure stdout -translation lf
-
-set filelist [subst {
- $TOP/src/sqlite.h.in
- $TOP/ext/rtree/sqlite3rtree.h
- $TOP/ext/fts5/fts5.h
-}]
-
-# These are the functions that accept a variable number of arguments. They
-# always need to use the "cdecl" calling convention even when another calling
-# convention (e.g. "stcall") is being used for the rest of the library.
-set cdecllist {
- sqlite3_config
- sqlite3_db_config
- sqlite3_log
- sqlite3_mprintf
- sqlite3_snprintf
- sqlite3_test_control
- sqlite3_vtab_config
-}
-
-# Process the source files.
-#
-foreach file $filelist {
- set in [open $file]
- while {![eof $in]} {
-
- set line [gets $in]
-
- # File sqlite3rtree.h contains a line "#include <sqlite3.h>". Omit this
- # line when copying sqlite3rtree.h into sqlite3.h.
- #
- if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue
-
- regsub -- --VERS-- $line $zVersion line
- regsub -- --VERSION-NUMBER-- $line $nVersion line
- regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line
-
- if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
- set line "SQLITE_API $line"
- } else {
- if {[regexp $declpattern $line all rettype funcname rest]} {
- set line SQLITE_API
- append line " " [string trim $rettype]
- if {[string index $rettype end] ne "*"} {
- append line " "
- }
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_STDCALL
- }
- append line " " $funcname $rest
- }
- }
- puts $line
- }
- close $in
-}
diff --git a/lib/libsqlite3/tool/mksqlite3internalh.tcl b/lib/libsqlite3/tool/mksqlite3internalh.tcl
deleted file mode 100644
index 8db593fe756..00000000000
--- a/lib/libsqlite3/tool/mksqlite3internalh.tcl
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/tclsh
-#
-# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
-# interface are omitted.) first do
-#
-# make target_source
-#
-# The make target above moves all of the source code files into
-# a subdirectory named "tsrc". (This script expects to find the files
-# there and will not work if they are not found.) There are a few
-# generated C code files that are also added to the tsrc directory.
-# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
-# "keywordhash.h" files is generated by a program named "mkkeywordhash".
-#
-# After the "tsrc" directory has been created and populated, run
-# this script:
-#
-# tclsh mksqlite3c.tcl
-#
-# The amalgamated SQLite code will be written into sqlite3.c
-#
-
-# Begin by reading the "sqlite3.h" header file. Count the number of lines
-# in this file and extract the version number. That information will be
-# needed in order to generate the header of the amalgamation.
-#
-set in [open tsrc/sqlite3.h]
-set cnt 0
-set VERSION ?????
-while {![eof $in]} {
- set line [gets $in]
- if {$line=="" && [eof $in]} break
- incr cnt
- regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
-}
-close $in
-
-# Open the output file and write a header comment at the beginning
-# of the file.
-#
-set out [open sqlite3internal.h w]
-set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
-puts $out [subst \
-{/******************************************************************************
-** This file is an amalgamation of many private header files from SQLite
-** version $VERSION.
-*/}]
-
-# These are the header files used by SQLite. The first time any of these
-# files are seen in a #include statement in the C code, include the complete
-# text of the file in-line. The file only needs to be included once.
-#
-foreach hdr {
- btree.h
- btreeInt.h
- hash.h
- hwtime.h
- keywordhash.h
- msvc.h
- opcodes.h
- os_common.h
- os_setup.h
- os_win.h
- os.h
- pager.h
- parse.h
- sqlite3ext.h
- sqlite3.h
- sqliteInt.h
- sqliteLimit.h
- vdbe.h
- vdbeInt.h
-} {
- set available_hdr($hdr) 1
-}
-
-# 78 stars used for comment formatting.
-set s78 \
-{*****************************************************************************}
-
-# Insert a comment into the code
-#
-proc section_comment {text} {
- global out s78
- set n [string length $text]
- set nstar [expr {60 - $n}]
- set stars [string range $s78 0 $nstar]
- puts $out "/************** $text $stars/"
-}
-
-# Read the source file named $filename and write it into the
-# sqlite3.c output file. If any #include statements are seen,
-# process them approprately.
-#
-proc copy_file {filename} {
- global seen_hdr available_hdr out
- set tail [file tail $filename]
- section_comment "Begin file $tail"
- set in [open $filename r]
- while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
- if {[info exists available_hdr($hdr)]} {
- if {$available_hdr($hdr)} {
- section_comment "Include $hdr in the middle of $tail"
- copy_file tsrc/$hdr
- section_comment "Continuing where we left off in $tail"
- }
- } elseif {![info exists seen_hdr($hdr)]} {
- set seen_hdr($hdr) 1
- puts $out $line
- }
- } elseif {[regexp {^#ifdef __cplusplus} $line]} {
- puts $out "#if 0"
- } elseif {[regexp {^#line} $line]} {
- # Skip #line directives.
- } else {
- puts $out $line
- }
- }
- close $in
- section_comment "End of $tail"
-}
-
-
-# Process the source files. Process files containing commonly
-# used subroutines first in order to help the compiler find
-# inlining opportunities.
-#
-foreach file {
- sqliteInt.h
- sqlite3.h
- btree.h
- hash.h
- os.h
- pager.h
- parse.h
- sqlite3ext.h
- vdbe.h
-} {
- if {$available_hdr($file)} {
- copy_file tsrc/$file
- }
-}
-
-close $out
diff --git a/lib/libsqlite3/tool/mkvsix.tcl b/lib/libsqlite3/tool/mkvsix.tcl
deleted file mode 100644
index b7c5983dbe2..00000000000
--- a/lib/libsqlite3/tool/mkvsix.tcl
+++ /dev/null
@@ -1,840 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script is used to generate a VSIX (Visual Studio Extension) file for
-# SQLite usable by Visual Studio.
-#
-# PREREQUISITES
-#
-# 1. Tcl 8.4 and later are supported, earlier versions have not been tested.
-#
-# 2. The "sqlite3.h" file is assumed to exist in the parent directory of the
-# directory containing this script. The [optional] second command line
-# argument to this script may be used to specify an alternate location.
-# This script also assumes that the "sqlite3.h" file corresponds with the
-# version of the binaries to be packaged. This assumption is not verified
-# by this script.
-#
-# 3. The temporary directory specified in the TEMP or TMP environment variables
-# must refer to an existing directory writable by the current user.
-#
-# 4. The "zip" and "unzip" command line tools must be located either in a
-# directory contained in the PATH environment variable or specified as the
-# exact file names to execute in the "ZipTool" and "UnZipTool" environment
-# variables, respectively.
-#
-# 5. The template VSIX file (which is basically a zip file) must be located in
-# a "win" directory inside the directory containing this script. It should
-# not contain any executable binaries. It should only contain dynamic
-# textual content files to be processed using [subst] and/or static content
-# files to be copied verbatim.
-#
-# 6. The executable and other compiled binary files to be packaged into the
-# final VSIX file (e.g. DLLs, LIBs, and PDBs) must be located in a single
-# directory tree. The top-level directory of the tree must be specified as
-# the first command line argument to this script. The second level
-# sub-directory names must match those of the build configuration (e.g.
-# "Debug" or "Retail"). The third level sub-directory names must match
-# those of the platform (e.g. "x86", "x64", and "ARM"). For example, the
-# binary files to be packaged would need to be organized as follows when
-# packaging the "Debug" and "Retail" build configurations for the "x86" and
-# "x64" platforms (in this example, "C:\temp" is the top-level directory as
-# specified in the first command line argument):
-#
-# C:\Temp\Debug\x86\sqlite3.lib
-# C:\Temp\Debug\x86\sqlite3.dll
-# C:\Temp\Debug\x86\sqlite3.pdb
-# C:\Temp\Debug\x64\sqlite3.lib
-# C:\Temp\Debug\x64\sqlite3.dll
-# C:\Temp\Debug\x64\sqlite3.pdb
-# C:\Temp\Retail\x86\sqlite3.lib
-# C:\Temp\Retail\x86\sqlite3.dll
-# C:\Temp\Retail\x86\sqlite3.pdb
-# C:\Temp\Retail\x64\sqlite3.lib
-# C:\Temp\Retail\x64\sqlite3.dll
-# C:\Temp\Retail\x64\sqlite3.pdb
-#
-# The above directory tree organization is performed automatically if the
-# "tool\build-all-msvc.bat" batch script is used to build the binary files
-# to be packaged.
-#
-# USAGE
-#
-# The first argument to this script is required and must be the name of the
-# top-level directory containing the directories and files organized into a
-# tree as described in item 6 of the PREREQUISITES section, above. The second
-# argument is optional and if present must contain the name of the directory
-# containing the root of the source tree for SQLite. The third argument is
-# optional and if present must contain the flavor the VSIX package to build.
-# Currently, the only supported package flavors are "WinRT", "WinRT81", "WP80",
-# "WP81", and "Win32". The fourth argument is optional and if present must be
-# a string containing a list of platforms to include in the VSIX package. The
-# platform list is "platform1,platform2,platform3". The fifth argument is
-# optional and if present must contain the version of Visual Studio required by
-# the package. Currently, the only supported versions are "2012" and "2013".
-# The package flavors "WinRT81" and "WP81" are only supported when the Visual
-# Studio version is "2013". Typically, when on Windows, this script is
-# executed using commands similar to the following from a normal Windows
-# command prompt:
-#
-# CD /D C:\dev\sqlite\core
-# tclsh85 tool\mkvsix.tcl C:\Temp
-#
-# In the example above, "C:\dev\sqlite\core" represents the root of the source
-# tree for SQLite and "C:\Temp" represents the top-level directory containing
-# the executable and other compiled binary files, organized into a directory
-# tree as described in item 6 of the PREREQUISITES section, above.
-#
-# This script should work on non-Windows platforms as well, provided that all
-# the requirements listed in the PREREQUISITES section are met.
-#
-# NOTES
-#
-# The temporary directory is used as a staging area for the final VSIX file.
-# The template VSIX file is extracted, its contents processed, and then the
-# resulting files are packaged into the final VSIX file.
-#
-package require Tcl 8.4
-
-proc fail { {error ""} {usage false} } {
- if {[string length $error] > 0} then {
- puts stdout $error
- if {!$usage} then {exit 1}
- }
-
- puts stdout "usage:\
-[file tail [info nameofexecutable]]\
-[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
-\[packageFlavor\] \[platformNames\] \[vsVersion\]"
-
- exit 1
-}
-
-proc getEnvironmentVariable { name } {
- #
- # NOTE: Returns the value of the specified environment variable or an empty
- # string for environment variables that do not exist in the current
- # process environment.
- #
- return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
-}
-
-proc getTemporaryPath {} {
- #
- # NOTE: Returns the normalized path to the first temporary directory found
- # in the typical set of environment variables used for that purpose
- # or an empty string to signal a failure to locate such a directory.
- #
- set names [list]
-
- foreach name [list TEMP TMP] {
- lappend names [string toupper $name] [string tolower $name] \
- [string totitle $name]
- }
-
- foreach name $names {
- set value [getEnvironmentVariable $name]
-
- if {[string length $value] > 0} then {
- return [file normalize $value]
- }
- }
-
- return ""
-}
-
-proc appendArgs { args } {
- #
- # NOTE: Returns all passed arguments joined together as a single string with
- # no intervening spaces between arguments.
- #
- eval append result $args
-}
-
-proc readFile { fileName } {
- #
- # NOTE: Reads and returns the entire contents of the specified file, which
- # may contain binary data.
- #
- set file_id [open $fileName RDONLY]
- fconfigure $file_id -encoding binary -translation binary
- set result [read $file_id]
- close $file_id
- return $result
-}
-
-proc writeFile { fileName data } {
- #
- # NOTE: Writes the entire contents of the specified file, which may contain
- # binary data.
- #
- set file_id [open $fileName {WRONLY CREAT TRUNC}]
- fconfigure $file_id -encoding binary -translation binary
- puts -nonewline $file_id $data
- close $file_id
- return ""
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getMinVsVersionXmlChunk { vsVersion } {
- switch -exact $vsVersion {
- 2012 {
- return [appendArgs \
- "\r\n " {MinVSVersion="11.0"}]
- }
- 2013 {
- return [appendArgs \
- "\r\n " {MinVSVersion="12.0"}]
- }
- 2015 {
- return [appendArgs \
- "\r\n " {MinVSVersion="14.0"}]
- }
- default {
- return ""
- }
- }
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
- #
- # NOTE: Only Visual Studio 2013 and later support this attribute within the
- # SDK manifest.
- #
- if {![string equal $vsVersion 2013] && \
- ![string equal $vsVersion 2015]} then {
- return ""
- }
-
- switch -exact $packageFlavor {
- WinRT {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.0"}]
- }
- WinRT81 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.1"}]
- }
- WP80 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.0"}]
- }
- WP81 {
- return [appendArgs \
- "\r\n " {MaxPlatformVersion="8.1"}]
- }
- default {
- return ""
- }
- }
-}
-
-#
-# TODO: Modify this procedure when a new version of Visual Studio is released.
-#
-proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
- #
- # NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX
- # package SDK manifests; however, it appears that Windows Phone 8.1
- # does.
- #
- if {[string equal $packageFlavor WP80]} then {
- return ""
- }
-
- set appliesTo [expr {[string equal $packageFlavor Win32] ? \
- "VisualC" : "WindowsAppContainer"}]
-
- switch -exact $vsVersion {
- 2012 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
- }
- 2013 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
- }
- 2015 {
- return [appendArgs \
- "\r\n " AppliesTo=\" $appliesTo \" \
- "\r\n " {DependsOn="Microsoft.VCLibs, version=14.0"}]
- }
- default {
- return ""
- }
- }
-}
-
-proc replaceFileNameTokens { fileName name buildName platformName } {
- #
- # NOTE: Returns the specified file name containing the platform name instead
- # of platform placeholder tokens.
- #
- return [string map [list <build> $buildName <platform> $platformName \
- <name> $name] $fileName]
-}
-
-proc substFile { fileName } {
- #
- # NOTE: Performs all Tcl command, variable, and backslash substitutions in
- # the specified file and then rewrites the contents of that same file
- # with the substituted data.
- #
- return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
-}
-
-#
-# NOTE: This is the entry point for this script.
-#
-set script [file normalize [info script]]
-
-if {[string length $script] == 0} then {
- fail "script file currently being evaluated is unknown" true
-}
-
-set path [file dirname $script]
-set rootName [file rootname [file tail $script]]
-
-###############################################################################
-
-#
-# NOTE: Process and verify all the command line arguments.
-#
-set argc [llength $argv]
-if {$argc < 1 || $argc > 5} then {fail}
-
-set binaryDirectory [lindex $argv 0]
-
-if {[string length $binaryDirectory] == 0} then {
- fail "invalid binary directory"
-}
-
-if {![file exists $binaryDirectory] || \
- ![file isdirectory $binaryDirectory]} then {
- fail "binary directory does not exist"
-}
-
-if {$argc >= 2} then {
- set sourceDirectory [lindex $argv 1]
-} else {
- #
- # NOTE: Assume that the source directory is the parent directory of the one
- # that contains this script file.
- #
- set sourceDirectory [file dirname $path]
-}
-
-if {[string length $sourceDirectory] == 0} then {
- fail "invalid source directory"
-}
-
-if {![file exists $sourceDirectory] || \
- ![file isdirectory $sourceDirectory]} then {
- fail "source directory does not exist"
-}
-
-if {$argc >= 3} then {
- set packageFlavor [lindex $argv 2]
-} else {
- #
- # NOTE: Assume the package flavor is WinRT.
- #
- set packageFlavor WinRT
-}
-
-if {[string length $packageFlavor] == 0} then {
- fail "invalid package flavor"
-}
-
-if {$argc >= 4} then {
- set platformNames [list]
-
- foreach platformName [split [lindex $argv 3] ", "] {
- set platformName [string trim $platformName]
-
- if {[string length $platformName] > 0} then {
- lappend platformNames $platformName
- }
- }
-}
-
-if {$argc >= 5} then {
- set vsVersion [lindex $argv 4]
-} else {
- set vsVersion 2012
-}
-
-if {[string length $vsVersion] == 0} then {
- fail "invalid Visual Studio version"
-}
-
-if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013] && \
- ![string equal $vsVersion 2015]} then {
- fail [appendArgs \
- "unsupported Visual Studio version, must be one of: " \
- [list 2012 2013 2015]]
-}
-
-set shortNames(WinRT,2012) SQLite.WinRT
-set shortNames(WinRT,2013) SQLite.WinRT.2013
-set shortNames(WinRT81,2013) SQLite.WinRT81
-set shortNames(WP80,2012) SQLite.WP80
-set shortNames(WP80,2013) SQLite.WP80.2013
-set shortNames(WP81,2013) SQLite.WP81
-set shortNames(Win32,2012) SQLite.Win32
-set shortNames(Win32,2013) SQLite.Win32.2013
-set shortNames(UAP,2015) SQLite.UAP.2015
-
-set displayNames(WinRT,2012) "SQLite for Windows Runtime"
-set displayNames(WinRT,2013) "SQLite for Windows Runtime"
-set displayNames(WinRT81,2013) "SQLite for Windows Runtime (Windows 8.1)"
-set displayNames(WP80,2012) "SQLite for Windows Phone"
-set displayNames(WP80,2013) "SQLite for Windows Phone"
-set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
-set displayNames(Win32,2012) "SQLite for Windows"
-set displayNames(Win32,2013) "SQLite for Windows"
-set displayNames(UAP,2015) "SQLite for Universal App Platform"
-
-if {[string equal $packageFlavor WinRT]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WinRT81]} then {
- if {$vsVersion ne "2013"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2013"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.1
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WP80]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier "Windows Phone"
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor WP81]} then {
- if {$vsVersion ne "2013"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2013"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier WindowsPhoneApp
- set targetPlatformVersion v8.1
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor UAP]} then {
- if {$vsVersion ne "2015"} then {
- fail [appendArgs \
- "unsupported combination, package flavor " $packageFlavor \
- " is only supported with Visual Studio 2015"]
- }
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier UAP
- set targetPlatformVersion v0.8.0.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath "\\..\\$targetPlatformIdentifier"
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} elseif {[string equal $packageFlavor Win32]} then {
- set shortName $shortNames($packageFlavor,$vsVersion)
- set displayName $displayNames($packageFlavor,$vsVersion)
- set targetPlatformIdentifier Windows
- set targetPlatformVersion v8.0
- set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
- set maxPlatformVersion \
- [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
- set extraSdkPath ""
- set extraFileListAttributes \
- [getExtraFileListXmlChunk $packageFlavor $vsVersion]
-} else {
- fail [appendArgs \
- "unsupported package flavor, must be one of: " \
- [list WinRT WinRT81 WP80 WP81 UAP Win32]]
-}
-
-###############################################################################
-
-#
-# NOTE: Evaluate the user-specific customizations file, if it exists.
-#
-set userFile [file join $path [appendArgs \
- $rootName . $tcl_platform(user) .tcl]]
-
-if {[file exists $userFile] && \
- [file isfile $userFile]} then {
- source $userFile
-}
-
-###############################################################################
-
-set templateFile [file join $path win sqlite.vsix]
-
-if {![file exists $templateFile] || \
- ![file isfile $templateFile]} then {
- fail [appendArgs "template file \"" $templateFile "\" does not exist"]
-}
-
-set currentDirectory [pwd]
-set outputFile [file join $currentDirectory [appendArgs sqlite- \
- $packageFlavor -output.vsix]]
-
-if {[file exists $outputFile]} then {
- fail [appendArgs "output file \"" $outputFile "\" already exists"]
-}
-
-###############################################################################
-
-#
-# NOTE: Make sure that a valid temporary directory exists.
-#
-set temporaryDirectory [getTemporaryPath]
-
-if {[string length $temporaryDirectory] == 0 || \
- ![file exists $temporaryDirectory] || \
- ![file isdirectory $temporaryDirectory]} then {
- fail "cannot locate a usable temporary directory"
-}
-
-#
-# NOTE: Setup the staging directory to have a unique name inside of the
-# configured temporary directory.
-#
-set stagingDirectory [file normalize [file join $temporaryDirectory \
- [appendArgs $rootName . [pid]]]]
-
-###############################################################################
-
-#
-# NOTE: Configure the external zipping tool. First, see if it has already
-# been pre-configured. If not, try to query it from the environment.
-# Finally, fallback on the default of simply "zip", which will then
-# be assumed to exist somewhere along the PATH.
-#
-if {![info exists zip]} then {
- if {[info exists env(ZipTool)]} then {
- set zip $env(ZipTool)
- }
- if {![info exists zip] || ![file exists $zip]} then {
- set zip zip
- }
-}
-
-#
-# NOTE: Configure the external unzipping tool. First, see if it has already
-# been pre-configured. If not, try to query it from the environment.
-# Finally, fallback on the default of simply "unzip", which will then
-# be assumed to exist somewhere along the PATH.
-#
-if {![info exists unzip]} then {
- if {[info exists env(UnZipTool)]} then {
- set unzip $env(UnZipTool)
- }
- if {![info exists unzip] || ![file exists $unzip]} then {
- set unzip unzip
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file
-# in the source directory. This script assumes that the header file has
-# already been generated by the build process.
-#
-set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$}
-set data [readFile [file join $sourceDirectory sqlite3.h]]
-
-if {![regexp -line -- $pattern $data dummy version]} then {
- fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \
- [file join $sourceDirectory sqlite3.h] \"]
-}
-
-###############################################################################
-
-#
-# NOTE: Setup all the master file list data. This includes the source file
-# names, the destination file names, and the file processing flags. The
-# possible file processing flags are:
-#
-# "buildNeutral" -- This flag indicates the file location and content do
-# not depend on the build configuration.
-#
-# "platformNeutral" -- This flag indicates the file location and content
-# do not depend on the build platform.
-#
-# "subst" -- This flag indicates that the file contains dynamic textual
-# content that needs to be processed using [subst] prior to
-# packaging the file into the final VSIX package. The primary
-# use of this flag is to insert the name of the VSIX package,
-# some package flavor-specific value, or the SQLite version
-# into a file.
-#
-# "noDebug" -- This flag indicates that the file should be skipped when
-# processing the debug build.
-#
-# "noRetail" -- This flag indicates that the file should be skipped when
-# processing the retail build.
-#
-# "move" -- This flag indicates that the file should be moved from the
-# source to the destination instead of being copied.
-#
-# This file metadata may be overridden, either in whole or in part, via
-# the user-specific customizations file.
-#
-if {![info exists fileNames(source)]} then {
- set fileNames(source) [list "" "" \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.props] \
- [file join $sourceDirectory sqlite3.h] \
- [file join $binaryDirectory <build> <platform> sqlite3.lib] \
- [file join $binaryDirectory <build> <platform> sqlite3.dll]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(source) \
- [file join $binaryDirectory <build> <platform> sqlite3.pdb]
- }
-}
-
-if {![info exists fileNames(destination)]} then {
- set fileNames(destination) [list \
- [file join $stagingDirectory extension.vsixmanifest] \
- [file join $stagingDirectory SDKManifest.xml] \
- [file join $stagingDirectory DesignTime <build> <platform> <name>.props] \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \
- [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \
- [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(destination) \
- [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb]
- }
-}
-
-if {![info exists fileNames(flags)]} then {
- set fileNames(flags) [list \
- [list buildNeutral platformNeutral subst] \
- [list buildNeutral platformNeutral subst] \
- [list buildNeutral platformNeutral subst move] \
- [list buildNeutral platformNeutral] \
- [list] [list] [list noRetail]]
-
- if {![info exists no(symbols)]} then {
- lappend fileNames(flags) [list noRetail]
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Setup the list of builds supported by this script. These may be
-# overridden via the user-specific customizations file.
-#
-if {![info exists buildNames]} then {
- set buildNames [list Debug Retail]
-}
-
-###############################################################################
-
-#
-# NOTE: Setup the list of platforms supported by this script. These may be
-# overridden via the command line or the user-specific customizations
-# file.
-#
-if {![info exists platformNames] || [llength $platformNames] == 0} then {
- set platformNames [list x86 x64 ARM]
-}
-
-###############################################################################
-
-#
-# NOTE: Make sure the staging directory exists, creating it if necessary.
-#
-file mkdir $stagingDirectory
-
-#
-# NOTE: Build the Tcl command used to extract the template VSIX package to
-# the staging directory.
-#
-set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory]
-
-#
-# NOTE: Extract the template VSIX package to the staging directory.
-#
-eval $extractCommand
-
-###############################################################################
-
-#
-# NOTE: Process each file in the master file list. There are actually three
-# parallel lists that contain the source file names, the destination file
-# names, and the file processing flags. If the "buildNeutral" flag is
-# present, the file location and content do not depend on the build
-# configuration and "CommonConfiguration" will be used in place of the
-# build configuration name. If the "platformNeutral" flag is present,
-# the file location and content do not depend on the build platform and
-# "neutral" will be used in place of the build platform name. If the
-# "subst" flag is present, the file is assumed to be a text file that may
-# contain Tcl variable, command, and backslash replacements, to be
-# dynamically replaced during processing using the Tcl [subst] command.
-# If the "noDebug" flag is present, the file will be skipped when
-# processing for the debug build. If the "noRetail" flag is present, the
-# file will be skipped when processing for the retail build. If the
-# "move" flag is present, the source file will be deleted after it is
-# copied to the destination file. If the source file name is an empty
-# string, the destination file name will be assumed to already exist in
-# the staging directory and will not be copied; however, Tcl variable,
-# command, and backslash replacements may still be performed on the
-# destination file prior to the final VSIX package being built if the
-# "subst" flag is present.
-#
-foreach sourceFileName $fileNames(source) \
- destinationFileName $fileNames(destination) \
- fileFlags $fileNames(flags) {
- #
- # NOTE: Process the file flags into separate boolean variables that may be
- # used within the loop.
- #
- set isBuildNeutral [expr {[lsearch $fileFlags buildNeutral] != -1}]
- set isPlatformNeutral [expr {[lsearch $fileFlags platformNeutral] != -1}]
- set isMove [expr {[lsearch $fileFlags move] != -1}]
- set useSubst [expr {[lsearch $fileFlags subst] != -1}]
-
- #
- # NOTE: If the current file is build-neutral, then only one build will
- # be processed for it, namely "CommonConfiguration"; otherwise, each
- # supported build will be processed for it individually.
- #
- foreach buildName \
- [expr {$isBuildNeutral ? [list CommonConfiguration] : $buildNames}] {
- #
- # NOTE: Should the current file be skipped for this build?
- #
- if {[lsearch $fileFlags no${buildName}] != -1} then {
- continue
- }
-
- #
- # NOTE: If the current file is platform-neutral, then only one platform
- # will be processed for it, namely "neutral"; otherwise, each
- # supported platform will be processed for it individually.
- #
- foreach platformName \
- [expr {$isPlatformNeutral ? [list neutral] : $platformNames}] {
- #
- # NOTE: Use the actual platform name in the destination file name.
- #
- set newDestinationFileName [replaceFileNameTokens $destinationFileName \
- $shortName $buildName $platformName]
-
- #
- # NOTE: Does the source file need to be copied to the destination file?
- #
- if {[string length $sourceFileName] > 0} then {
- #
- # NOTE: First, make sure the destination directory exists.
- #
- file mkdir [file dirname $newDestinationFileName]
-
- #
- # NOTE: Then, copy the source file to the destination file verbatim.
- #
- set newSourceFileName [replaceFileNameTokens $sourceFileName \
- $shortName $buildName $platformName]
-
- file copy $newSourceFileName $newDestinationFileName
-
- #
- # NOTE: If this is a move instead of a copy, delete the source file
- # now.
- #
- if {$isMove} then {
- file delete $newSourceFileName
- }
- }
-
- #
- # NOTE: Does the destination file contain dynamic replacements that must
- # be processed now?
- #
- if {$useSubst} then {
- #
- # NOTE: Perform any dynamic replacements contained in the destination
- # file and then re-write it in-place.
- #
- substFile $newDestinationFileName
- }
- }
- }
-}
-
-###############################################################################
-
-#
-# NOTE: Change the current directory to the staging directory so that the
-# external archive building tool can pickup the necessary files using
-# relative paths.
-#
-cd $stagingDirectory
-
-#
-# NOTE: Build the Tcl command used to archive the final VSIX package in the
-# output directory.
-#
-set archiveCommand [list exec -- $zip -r $outputFile *]
-
-#
-# NOTE: Build the final VSIX package archive in the output directory.
-#
-eval $archiveCommand
-
-#
-# NOTE: Change back to the previously saved current directory.
-#
-cd $currentDirectory
-
-#
-# NOTE: Cleanup the temporary staging directory.
-#
-file delete -force $stagingDirectory
-
-###############################################################################
-
-#
-# NOTE: Success, emit the fully qualified path of the generated VSIX file.
-#
-puts stdout $outputFile
diff --git a/lib/libsqlite3/tool/offsets.c b/lib/libsqlite3/tool/offsets.c
deleted file mode 100644
index 8e098e71cb9..00000000000
--- a/lib/libsqlite3/tool/offsets.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
-** This program searches an SQLite database file for the lengths and
-** offsets for all TEXT or BLOB entries for a particular column of a
-** particular table. The rowid, size and offset for the column are
-** written to standard output. There are three arguments, which are the
-** name of the database file, the table, and the column.
-*/
-#include "sqlite3.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-typedef unsigned char u8;
-typedef struct GState GState;
-
-#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
-
-/*
-** Global state information for this program.
-*/
-struct GState {
- char *zErr; /* Error message text */
- FILE *f; /* Open database file */
- int szPg; /* Page size for the database file */
- int iRoot; /* Root page of the table */
- int iCol; /* Column number for the column */
- int pgno; /* Current page number */
- u8 *aPage; /* Current page content */
- u8 *aStack[20]; /* Page stack */
- int aPgno[20]; /* Page number stack */
- int nStack; /* Depth of stack */
- int bTrace; /* True for tracing output */
-};
-
-/*
-** Write an error.
-*/
-static void ofstError(GState *p, const char *zFormat, ...){
- va_list ap;
- sqlite3_free(p->zErr);
- va_start(ap, zFormat);
- p->zErr = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
-}
-
-/*
-** Write a trace message
-*/
-static void ofstTrace(GState *p, const char *zFormat, ...){
- va_list ap;
- if( p->bTrace ){
- va_start(ap, zFormat);
- vprintf(zFormat, ap);
- va_end(ap);
- }
-}
-
-/*
-** Find the root page of the table and the column number of the column.
-*/
-static void ofstRootAndColumn(
- GState *p, /* Global state */
- const char *zFile, /* Name of the database file */
- const char *zTable, /* Name of the table */
- const char *zColumn /* Name of the column */
-){
- sqlite3 *db = 0;
- sqlite3_stmt *pStmt = 0;
- char *zSql = 0;
- int rc;
- if( p->zErr ) return;
- rc = sqlite3_open(zFile, &db);
- if( rc ){
- ofstError(p, "cannot open database file \"%s\"", zFile);
- goto rootAndColumn_exit;
- }
- zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master WHERE name=%Q",
- zTable);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- ofstError(p, "cannot find table [%s]\n", zTable);
- sqlite3_finalize(pStmt);
- goto rootAndColumn_exit;
- }
- p->iRoot = sqlite3_column_int(pStmt , 0);
- sqlite3_finalize(pStmt);
-
- p->iCol = -1;
- zSql = sqlite3_mprintf("PRAGMA table_info(%Q)", zTable);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s}", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zCol = sqlite3_column_text(pStmt, 1);
- if( strlen(zCol)==strlen(zColumn)
- && sqlite3_strnicmp(zCol, zColumn, strlen(zCol))==0
- ){
- p->iCol = sqlite3_column_int(pStmt, 0);
- break;
- }
- }
- sqlite3_finalize(pStmt);
- if( p->iCol<0 ){
- ofstError(p, "no such column: %s.%s", zTable, zColumn);
- goto rootAndColumn_exit;
- }
-
- zSql = sqlite3_mprintf("PRAGMA page_size");
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
- sqlite3_free(zSql);
- if( p->zErr ) goto rootAndColumn_exit;
- if( sqlite3_step(pStmt)!=SQLITE_ROW ){
- ofstError(p, "cannot find page size");
- }else{
- p->szPg = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
-
-rootAndColumn_exit:
- sqlite3_close(db);
- return;
-}
-
-/*
-** Pop a page from the stack
-*/
-static void ofstPopPage(GState *p){
- if( p->nStack<=0 ) return;
- p->nStack--;
- sqlite3_free(p->aStack[p->nStack]);
- p->pgno = p->aPgno[p->nStack-1];
- p->aPage = p->aStack[p->nStack-1];
-}
-
-
-/*
-** Push a new page onto the stack.
-*/
-static void ofstPushPage(GState *p, int pgno){
- u8 *pPage;
- size_t got;
- if( p->zErr ) return;
- if( p->nStack >= ArraySize(p->aStack) ){
- ofstError(p, "page stack overflow");
- return;
- }
- p->aPgno[p->nStack] = pgno;
- p->aStack[p->nStack] = pPage = sqlite3_malloc( p->szPg );
- if( pPage==0 ){
- fprintf(stderr, "out of memory\n");
- exit(1);
- }
- p->nStack++;
- p->aPage = pPage;
- p->pgno = pgno;
- fseek(p->f, (pgno-1)*p->szPg, SEEK_SET);
- got = fread(pPage, 1, p->szPg, p->f);
- if( got!=p->szPg ){
- ofstError(p, "unable to read page %d", pgno);
- ofstPopPage(p);
- }
-}
-
-/* Read a two-byte integer at the given offset into the current page */
-static int ofst2byte(GState *p, int ofst){
- int x = p->aPage[ofst];
- return (x<<8) + p->aPage[ofst+1];
-}
-
-/* Read a four-byte integer at the given offset into the current page */
-static int ofst4byte(GState *p, int ofst){
- int x = p->aPage[ofst];
- x = (x<<8) + p->aPage[ofst+1];
- x = (x<<8) + p->aPage[ofst+2];
- x = (x<<8) + p->aPage[ofst+3];
- return x;
-}
-
-/* Read a variable-length integer. Update the offset */
-static sqlite3_int64 ofstVarint(GState *p, int *pOfst){
- sqlite3_int64 x = 0;
- u8 *a = &p->aPage[*pOfst];
- int n = 0;
- while( n<8 && (a[0] & 0x80)!=0 ){
- x = (x<<7) + (a[0] & 0x7f);
- n++;
- a++;
- }
- if( n==8 ){
- x = (x<<8) + a[0];
- }else{
- x = (x<<7) + a[0];
- }
- *pOfst += (n+1);
- return x;
-}
-
-/* Return the absolute offset into a file for the given offset
-** into the current page */
-static int ofstInFile(GState *p, int ofst){
- return p->szPg*(p->pgno-1) + ofst;
-}
-
-/* Return the size (in bytes) of the data corresponding to the
-** given serial code */
-static int ofstSerialSize(int scode){
- if( scode<5 ) return scode;
- if( scode==5 ) return 6;
- if( scode<8 ) return 8;
- if( scode<12 ) return 0;
- return (scode-12)/2;
-}
-
-/* Forward reference */
-static void ofstWalkPage(GState*, int);
-
-/* Walk an interior btree page */
-static void ofstWalkInteriorPage(GState *p){
- int nCell;
- int i;
- int ofst;
- int iChild;
-
- nCell = ofst2byte(p, 3);
- for(i=0; i<nCell; i++){
- ofst = ofst2byte(p, 12+i*2);
- iChild = ofst4byte(p, ofst);
- ofstWalkPage(p, iChild);
- if( p->zErr ) return;
- }
- ofstWalkPage(p, ofst4byte(p, 8));
-}
-
-/* Walk a leaf btree page */
-static void ofstWalkLeafPage(GState *p){
- int nCell;
- int i;
- int ofst;
- int nPayload;
- sqlite3_int64 rowid;
- int nHdr;
- int j;
- int scode;
- int sz;
- int dataOfst;
- char zMsg[200];
-
- nCell = ofst2byte(p, 3);
- for(i=0; i<nCell; i++){
- ofst = ofst2byte(p, 8+i*2);
- nPayload = ofstVarint(p, &ofst);
- rowid = ofstVarint(p, &ofst);
- if( nPayload > p->szPg-35 ){
- sqlite3_snprintf(sizeof(zMsg), zMsg,
- "# overflow rowid %lld", rowid);
- printf("%s\n", zMsg);
- continue;
- }
- dataOfst = ofst;
- nHdr = ofstVarint(p, &ofst);
- dataOfst += nHdr;
- for(j=0; j<p->iCol; j++){
- scode = ofstVarint(p, &ofst);
- dataOfst += ofstSerialSize(scode);
- }
- scode = ofstVarint(p, &ofst);
- sz = ofstSerialSize(scode);
- sqlite3_snprintf(sizeof(zMsg), zMsg,
- "rowid %12lld size %5d offset %8d",
- rowid, sz, ofstInFile(p, dataOfst));
- printf("%s\n", zMsg);
- }
-}
-
-/*
-** Output results from a single page.
-*/
-static void ofstWalkPage(GState *p, int pgno){
- if( p->zErr ) return;
- ofstPushPage(p, pgno);
- if( p->zErr ) return;
- if( p->aPage[0]==5 ){
- ofstWalkInteriorPage(p);
- }else if( p->aPage[0]==13 ){
- ofstWalkLeafPage(p);
- }else{
- ofstError(p, "page %d has a faulty type byte: %d", pgno, p->aPage[0]);
- }
- ofstPopPage(p);
-}
-
-int main(int argc, char **argv){
- GState g;
- memset(&g, 0, sizeof(g));
- if( argc>2 && strcmp(argv[1],"--trace")==0 ){
- g.bTrace = 1;
- argc--;
- argv++;
- }
- if( argc!=4 ){
- fprintf(stderr, "Usage: %s DATABASE TABLE COLUMN\n", *argv);
- exit(1);
- }
- ofstRootAndColumn(&g, argv[1], argv[2], argv[3]);
- if( g.zErr ){
- fprintf(stderr, "%s\n", g.zErr);
- exit(1);
- }
- ofstTrace(&g, "# szPg = %d\n", g.szPg);
- ofstTrace(&g, "# iRoot = %d\n", g.iRoot);
- ofstTrace(&g, "# iCol = %d\n", g.iCol);
- g.f = fopen(argv[1], "rb");
- if( g.f==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
- exit(1);
- }
- ofstWalkPage(&g, g.iRoot);
- if( g.zErr ){
- fprintf(stderr, "%s\n", g.zErr);
- exit(1);
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/omittest.tcl b/lib/libsqlite3/tool/omittest.tcl
deleted file mode 100644
index d03c5b49e70..00000000000
--- a/lib/libsqlite3/tool/omittest.tcl
+++ /dev/null
@@ -1,299 +0,0 @@
-
-set rcsid {$Id: omittest.tcl,v 1.1.1.3 2014/03/24 01:37:45 jturner Exp $}
-
-# Documentation for this script. This may be output to stderr
-# if the script is invoked incorrectly.
-set ::USAGE_MESSAGE {
-This Tcl script is used to test the various compile time options
-available for omitting code (the SQLITE_OMIT_xxx options). It
-should be invoked as follows:
-
- <script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run?
-
-The default value for ::MAKEFILE is "../Makefile.linux.gcc".
-
-If -skip_run option is given then only the compile part is attempted.
-
-This script builds the testfixture program and runs the SQLite test suite
-once with each SQLITE_OMIT_ option defined and then once with all options
-defined together. Each run is performed in a seperate directory created
-as a sub-directory of the current directory by the script. The output
-of the build is saved in <sub-directory>/build.log. The output of the
-test-suite is saved in <sub-directory>/test.log.
-
-Almost any SQLite makefile (except those generated by configure - see below)
-should work. The following properties are required:
-
- * The makefile should support the "testfixture" target.
- * The makefile should support the "test" target.
- * The makefile should support the variable "OPTS" as a way to pass
- options from the make command line to lemon and the C compiler.
-
-More precisely, the following two invocations must be supported:
-
- $::MAKEBIN -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1"
- $::MAKEBIN -f $::MAKEFILE test
-
-Makefiles generated by the sqlite configure program cannot be used as
-they do not respect the OPTS variable.
-}
-
-
-# Build a testfixture executable and run quick.test using it. The first
-# parameter is the name of the directory to create and use to run the
-# test in. The second parameter is a list of OMIT symbols to define
-# when doing so. For example:
-#
-# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW}
-#
-#
-proc run_quick_test {dir omit_symbol_list} {
- # Compile the value of the OPTS Makefile variable.
- set opts ""
- if {$::tcl_platform(platform)=="windows"} {
- append opts "OPTS += -DSQLITE_OS_WIN=1\n"
- set target "testfixture.exe"
- } else {
- append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
- }
- foreach sym $omit_symbol_list {
- append opts "OPTS += -D${sym}=1\n"
- }
-
- # Create the directory and do the build. If an error occurs return
- # early without attempting to run the test suite.
- file mkdir $dir
- puts -nonewline "Building $dir..."
- flush stdout
- catch {
- file copy -force ./config.h $dir
- file copy -force ./libtool $dir
- }
- set fd [open $::MAKEFILE]
- set mkfile [read $fd]
- close $fd
- regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
- set fd [open $dir/makefile w]
- puts $fd $mkfile
- close $fd
-
- set rc [catch {
- exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
- }]
- if {$rc} {
- puts "No good. See $dir/build.log."
- return
- } else {
- puts "Ok"
- }
-
- # Create an empty file "$dir/sqlite3". This is to trick the makefile out
- # of trying to build the sqlite shell. The sqlite shell won't build
- # with some of the OMIT options (i.e OMIT_COMPLETE).
- set sqlite3_dummy $dir/sqlite3
- if {$::tcl_platform(platform)=="windows"} {
- append sqlite3_dummy ".exe"
- }
- if {![file exists $sqlite3_dummy]} {
- set wr [open $sqlite3_dummy w]
- puts $wr "dummy"
- close $wr
- }
-
- if {$::SKIP_RUN} {
- puts "Skip testing $dir."
- } else {
- # Run the test suite.
- puts -nonewline "Testing $dir..."
- flush stdout
- set rc [catch {
- exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
- }]
- if {$rc} {
- puts "No good. See $dir/test.log."
- } else {
- puts "Ok"
- }
- }
-}
-
-
-# This proc processes the command line options passed to this script.
-# Currently the only option supported is "-makefile", default
-# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
-# option.
-#
-proc process_options {argv} {
- set ::MAKEBIN make ;# Default value
- if {$::tcl_platform(platform)=="windows"} {
- set ::MAKEFILE ./Makefile ;# Default value on Windows
- } else {
- set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
- }
- set ::SKIP_RUN 0 ;# Default to attempt test
- set ::TARGET testfixture ;# Default thing to build
-
- for {set i 0} {$i < [llength $argv]} {incr i} {
- switch -- [lindex $argv $i] {
- -makefile {
- incr i
- set ::MAKEFILE [lindex $argv $i]
- }
-
- -nmake {
- set ::MAKEBIN nmake
- set ::MAKEFILE ./Makefile.msc
- }
-
- -target {
- incr i
- set ::TARGET [lindex $argv $i]
- }
-
- -skip_run {
- set ::SKIP_RUN 1
- }
-
- default {
- if {[info exists ::SYMBOL]} {
- puts stderr [string trim $::USAGE_MESSAGE]
- exit -1
- }
- set ::SYMBOL [lindex $argv $i]
- }
- }
- set ::MAKEFILE [file normalize $::MAKEFILE]
- }
-}
-
-# Main routine.
-#
-
-proc main {argv} {
- # List of SQLITE_OMIT_XXX symbols supported by SQLite.
- set ::OMIT_SYMBOLS [list \
- SQLITE_OMIT_ALTERTABLE \
- SQLITE_OMIT_ANALYZE \
- SQLITE_OMIT_ATTACH \
- SQLITE_OMIT_AUTHORIZATION \
- SQLITE_OMIT_AUTOINCREMENT \
- SQLITE_OMIT_AUTOINIT \
- SQLITE_OMIT_AUTOMATIC_INDEX \
- SQLITE_OMIT_AUTORESET \
- SQLITE_OMIT_AUTOVACUUM \
- SQLITE_OMIT_BETWEEN_OPTIMIZATION \
- SQLITE_OMIT_BLOB_LITERAL \
- SQLITE_OMIT_BTREECOUNT \
- SQLITE_OMIT_BUILTIN_TEST \
- SQLITE_OMIT_CAST \
- SQLITE_OMIT_CHECK \
- SQLITE_OMIT_COMPILEOPTION_DIAGS \
- SQLITE_OMIT_COMPLETE \
- SQLITE_OMIT_COMPOUND_SELECT \
- SQLITE_OMIT_CTE \
- SQLITE_OMIT_DATETIME_FUNCS \
- SQLITE_OMIT_DECLTYPE \
- SQLITE_OMIT_DEPRECATED \
- SQLITE_OMIT_EXPLAIN \
- SQLITE_OMIT_FLAG_PRAGMAS \
- SQLITE_OMIT_FLOATING_POINT \
- SQLITE_OMIT_FOREIGN_KEY \
- SQLITE_OMIT_GET_TABLE \
- SQLITE_OMIT_INCRBLOB \
- SQLITE_OMIT_INTEGRITY_CHECK \
- SQLITE_OMIT_LIKE_OPTIMIZATION \
- SQLITE_OMIT_LOAD_EXTENSION \
- SQLITE_OMIT_LOCALTIME \
- SQLITE_OMIT_LOOKASIDE \
- SQLITE_OMIT_MEMORYDB \
- SQLITE_OMIT_OR_OPTIMIZATION \
- SQLITE_OMIT_PAGER_PRAGMAS \
- SQLITE_OMIT_PRAGMA \
- SQLITE_OMIT_PROGRESS_CALLBACK \
- SQLITE_OMIT_QUICKBALANCE \
- SQLITE_OMIT_REINDEX \
- SQLITE_OMIT_SCHEMA_PRAGMAS \
- SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
- SQLITE_OMIT_SHARED_CACHE \
- SQLITE_OMIT_SUBQUERY \
- SQLITE_OMIT_TCL_VARIABLE \
- SQLITE_OMIT_TEMPDB \
- SQLITE_OMIT_TRACE \
- SQLITE_OMIT_TRIGGER \
- SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
- SQLITE_OMIT_UNIQUE_ENFORCEMENT \
- SQLITE_OMIT_UTF16 \
- SQLITE_OMIT_VACUUM \
- SQLITE_OMIT_VIEW \
- SQLITE_OMIT_VIRTUALTABLE \
- SQLITE_OMIT_WAL \
- SQLITE_OMIT_WSD \
- SQLITE_OMIT_XFER_OPT \
- ]
-
- set ::ENABLE_SYMBOLS [list \
- SQLITE_DISABLE_DIRSYNC \
- SQLITE_DISABLE_LFS \
- SQLITE_ENABLE_ATOMIC_WRITE \
- SQLITE_ENABLE_COLUMN_METADATA \
- SQLITE_ENABLE_EXPENSIVE_ASSERT \
- SQLITE_ENABLE_FTS3 \
- SQLITE_ENABLE_FTS3_PARENTHESIS \
- SQLITE_ENABLE_FTS4 \
- SQLITE_ENABLE_IOTRACE \
- SQLITE_ENABLE_LOAD_EXTENSION \
- SQLITE_ENABLE_LOCKING_STYLE \
- SQLITE_ENABLE_MEMORY_MANAGEMENT \
- SQLITE_ENABLE_MEMSYS3 \
- SQLITE_ENABLE_MEMSYS5 \
- SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
- SQLITE_ENABLE_RTREE \
- SQLITE_ENABLE_STAT3 \
- SQLITE_ENABLE_UNLOCK_NOTIFY \
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
- ]
-
- # Process any command line options.
- process_options $argv
-
- if {[info exists ::SYMBOL] } {
- set sym $::SYMBOL
-
- if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
- puts stderr "No such symbol: $sym"
- exit -1
- }
-
- set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
- run_quick_test $dirname $sym
- } else {
- # First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT
- # and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
- # and the latter is currently incompatible with the test suite (this should
- # be fixed, but it will be a lot of work).
- set allsyms [list]
- foreach s $::OMIT_SYMBOLS {
- if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
- lappend allsyms $s
- }
- }
- run_quick_test test_OMIT_EVERYTHING $allsyms
-
- # Now try one quick.test with each of the OMIT symbols defined. Included
- # are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
- # know they will fail. It's good to be reminded of this from time to time.
- foreach sym $::OMIT_SYMBOLS {
- set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
- run_quick_test $dirname $sym
- }
-
- # Try the ENABLE/DISABLE symbols one at a time.
- # We don't do them all at once since some are conflicting.
- foreach sym $::ENABLE_SYMBOLS {
- set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
- run_quick_test $dirname $sym
- }
- }
-}
-
-main $argv
diff --git a/lib/libsqlite3/tool/opcodeDoc.awk b/lib/libsqlite3/tool/opcodeDoc.awk
deleted file mode 100644
index 492010624fd..00000000000
--- a/lib/libsqlite3/tool/opcodeDoc.awk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Extract opcode documentation for sqliteVdbe.c and generate HTML
-#
-BEGIN {
- print "<html><body bgcolor=white>"
- print "<h1>SQLite Virtual Database Engine Opcodes</h1>"
- print "<table>"
-}
-/ Opcode: /,/\*\// {
- if( $2=="Opcode:" ){
- printf "<tr><td>%s&nbsp;%s&nbsp;%s&nbsp;%s</td>\n<td>\n", $3, $4, $5, $6
- }else if( $1=="*/" ){
- printf "</td></tr>\n"
- }else if( NF>1 ){
- sub(/^ *\*\* /,"")
- gsub(/</,"&lt;")
- gsub(/&/,"&amp;")
- print
- }
-}
-END {
- print "</table></body></html>"
-}
diff --git a/lib/libsqlite3/tool/pagesig.c b/lib/libsqlite3/tool/pagesig.c
deleted file mode 100644
index 540c9d72266..00000000000
--- a/lib/libsqlite3/tool/pagesig.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-** 2013-10-01
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** Compute hash signatures for every page of a database file. This utility
-** program is useful for analyzing the output logs generated by the
-** ext/misc/vfslog.c extension.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-/*
-** Compute signature for a block of content.
-**
-** For blocks of 16 or fewer bytes, the signature is just a hex dump of
-** the entire block.
-**
-** For blocks of more than 16 bytes, the signature is a hex dump of the
-** first 8 bytes followed by a 64-bit has of the entire block.
-*/
-static void vlogSignature(unsigned char *p, int n, char *zCksum){
- unsigned int s0 = 0, s1 = 0;
- unsigned int *pI;
- int i;
- if( n<=16 ){
- for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]);
- }else{
- pI = (unsigned int*)p;
- for(i=0; i<n-7; i+=8){
- s0 += pI[0] + s1;
- s1 += pI[1] + s0;
- pI += 2;
- }
- for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]);
- sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
- }
-}
-
-/*
-** Open a file. Find its page size. Read each page, and compute and
-** display the page signature.
-*/
-static void computeSigs(const char *zFilename){
- FILE *in = fopen(zFilename, "rb");
- unsigned pgsz;
- size_t got;
- unsigned n;
- unsigned char aBuf[50];
- unsigned char aPage[65536];
-
- if( in==0 ){
- fprintf(stderr, "cannot open \"%s\"\n", zFilename);
- return;
- }
- got = fread(aBuf, 1, sizeof(aBuf), in);
- if( got!=sizeof(aBuf) ){
- goto endComputeSigs;
- }
- pgsz = aBuf[16]*256 + aBuf[17];
- if( pgsz==1 ) pgsz = 65536;
- if( (pgsz & (pgsz-1))!=0 ){
- fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]);
- goto endComputeSigs;
- }
- rewind(in);
- for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){
- vlogSignature(aPage, pgsz, aBuf);
- printf("%4d: %s\n", n, aBuf);
- }
-
-endComputeSigs:
- fclose(in);
-}
-
-/*
-** Find page signatures for all named files.
-*/
-int main(int argc, char **argv){
- int i;
- for(i=1; i<argc; i++) computeSigs(argv[i]);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/restore_jrnl.tcl b/lib/libsqlite3/tool/restore_jrnl.tcl
deleted file mode 100644
index 05af4f9a2a8..00000000000
--- a/lib/libsqlite3/tool/restore_jrnl.tcl
+++ /dev/null
@@ -1,233 +0,0 @@
-# 2010 January 7
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements utility functions for SQLite library.
-#
-# This file attempts to restore the header of a journal.
-# This may be useful for rolling-back the last committed
-# transaction from a recovered journal.
-#
-
-package require sqlite3
-
-set parm_error 0
-set fix_chksums 0
-set dump_pages 0
-set db_name ""
-
-for {set i 0} {$i<$argc} {incr i} {
- if {[lindex $argv $i] == "-fix_chksums"} {
- set fix_chksums -1
- } elseif {[lindex $argv $i] == "-dump_pages"} {
- set dump_pages -1
- } elseif {$db_name == ""} {
- set db_name [lindex $argv $i]
- set jrnl_name $db_name-journal
- } else {
- set parm_error -1
- }
-}
-if {$parm_error || $db_name == ""} {
- puts "USAGE: restore_jrnl.tcl \[-fix_chksums\] \[-dump_pages\] db_name"
- puts "Example: restore_jrnl.tcl foo.sqlite"
- return
-}
-
-# is there a way to determine this?
-set sectsz 512
-
-# Copy file $from into $to
-#
-proc copy_file {from to} {
- file copy -force $from $to
-}
-
-# Execute some SQL
-#
-proc catchsql {sql} {
- set rc [catch {uplevel [list db eval $sql]} msg]
- list $rc $msg
-}
-
-# Perform a test
-#
-proc do_test {name cmd expected} {
- puts -nonewline "$name ..."
- set res [uplevel $cmd]
- if {$res eq $expected} {
- puts Ok
- } else {
- puts Error
- puts " Got: $res"
- puts " Expected: $expected"
- }
-}
-
-# Calc checksum nonce from journal page data.
-#
-proc calc_nonce {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set nonce [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
- for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
- set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
- set nonce [expr $nonce-$byte]
- }
- return $nonce
-}
-
-# Calc checksum from journal page data.
-#
-proc calc_chksum {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
- global nonce
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set chksum $nonce
- for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
- set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
- set chksum [expr $chksum+$byte]
- }
- return $chksum
-}
-
-# Print journal page data in hex dump form
-#
-proc dump_jrnl_page {jrnl_pgno} {
- global sectsz
- global db_pgsz
- global jrnl_name
-
- # print a header block for the page
- puts [string repeat "-" 79]
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
- set db_pgno [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset] 4]]
- set chksum [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
- set nonce [calc_nonce $jrnl_pgno]
- puts [ format {jrnl_pg_offset: %08x (%d) jrnl_pgno: %d db_pgno: %d} \
- $jrnl_pg_offset $jrnl_pg_offset \
- $jrnl_pgno $db_pgno]
- puts [ format {nonce: %08x chksum: %08x} \
- $nonce $chksum]
-
- # now hex dump the data
- # This is derived from the Tcler's WIKI
- set fid [open $jrnl_name r]
- fconfigure $fid -translation binary -encoding binary
- seek $fid [expr $jrnl_pg_offset+4]
- set data [read $fid $db_pgsz]
- close $fid
- for {set addr 0} {$addr<$db_pgsz} {set addr [expr $addr+16]} {
- # get 16 bytes of data
- set s [string range $data $addr [expr $addr+16]]
-
- # Convert the data to hex and to characters.
- binary scan $s H*@0a* hex ascii
-
- # Replace non-printing characters in the data.
- regsub -all -- {[^[:graph:] ]} $ascii {.} ascii
-
- # Split the 16 bytes into two 8-byte chunks
- regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2
-
- # Convert the hex to pairs of hex digits
- regsub -all -- {..} $hex1 {& } hex1
- regsub -all -- {..} $hex2 {& } hex2
-
- # Print the hex and ascii data
- puts [ format {%08x %-24s %-24s %-16s} \
- $addr $hex1 $hex2 $ascii ]
- }
-}
-
-# Setup for the tests. Make a backup copy of the files.
-#
-if [file exist $db_name.org] {
- puts "ERROR: during back-up: $db_name.org exists already."
- return;
-}
-if [file exist $jrnl_name.org] {
- puts "ERROR: during back-up: $jrnl_name.org exists already."
- return
-}
-copy_file $db_name $db_name.org
-copy_file $jrnl_name $jrnl_name.org
-
-set db_fsize [file size $db_name]
-set db_pgsz [hexio_get_int [hexio_read $db_name 16 2]]
-set db_npage [expr {$db_fsize / $db_pgsz}]
-
-set jrnl_fsize [file size $jrnl_name]
-set jrnl_npage [expr {($jrnl_fsize - $sectsz) / (4 + $db_pgsz + 4)}]
-
-# calculate checksum nonce for first page
-set nonce [calc_nonce 0]
-
-# verify all the pages in the journal use the same nonce
-for {set i 1} {$i<$jrnl_npage} {incr i} {
- set tnonce [calc_nonce $i]
- if {$tnonce != $nonce} {
- puts "WARNING: different nonces: 0=$nonce $i=$tnonce"
- if {$fix_chksums } {
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
- set tchksum [calc_chksum $i]
- hexio_write $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] [format %08x $tchksum]
- puts "INFO: fixing chksum: $i=$tchksum"
- }
- }
-}
-
-# verify all the page numbers in the journal
-for {set i 0} {$i<$jrnl_npage} {incr i} {
- set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
- set db_pgno [hexio_get_int [hexio_read $jrnl_name $jrnl_pg_offset 4]]
- if {$db_pgno < 1} {
- puts "WARNING: page number < 1: $i=$db_pgno"
- }
- if {$db_pgno >= $db_npage} {
- puts "WARNING: page number >= $db_npage: $i=$db_pgno"
- }
-}
-
-# dump page data
-if {$dump_pages} {
- for {set i 0} {$i<$jrnl_npage} {incr i} {
- dump_jrnl_page $i
- }
-}
-
-# write the 8 byte magic string
-hexio_write $jrnl_name 0 d9d505f920a163d7
-
-# write -1 for number of records
-hexio_write $jrnl_name 8 ffffffff
-
-# write 00 for checksum nonce
-hexio_write $jrnl_name 12 [format %08x $nonce]
-
-# write page count
-hexio_write $jrnl_name 16 [format %08x $db_npage]
-
-# write sector size
-hexio_write $jrnl_name 20 [format %08x $sectsz]
-
-# write page size
-hexio_write $jrnl_name 24 [format %08x $db_pgsz]
-
-# check the integrity of the database with the patched journal
-sqlite3 db $db_name
-do_test restore_jrnl-1.0 {
- catchsql {PRAGMA integrity_check}
-} {0 ok}
-db close
-
diff --git a/lib/libsqlite3/tool/rollback-test.c b/lib/libsqlite3/tool/rollback-test.c
deleted file mode 100644
index 915d9d203da..00000000000
--- a/lib/libsqlite3/tool/rollback-test.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-** This program is used to generate and verify databases with hot journals.
-** Use this program to generate a hot journal on one machine and verify
-** that it rolls back correctly on another machine with a different
-** architecture.
-**
-** Usage:
-**
-** rollback-test new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE
-** rollback-test check DATABASE
-** rollback-test crash [-wal] [-rollback] DATABASE
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sqlite3.h"
-
-static void usage(char *argv0){
- fprintf(stderr,
- "Usage: %s new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE\n"
- " %s check DATABASE\n"
- " %s crash [-wal] DATABASE\n",
- argv0, argv0, argv0
- );
- exit(1);
-}
-
-static sqlite3 *openDb(const char *zFilename){
- int rc;
- sqlite3 *db;
- rc = sqlite3_open(zFilename, &db);
- if( rc ){
- fprintf(stderr, "Cannot open \"%s\": %s\n",
- zFilename, sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- return db;
-}
-
-static int nReply = 0;
-static char zReply[1000];
-
-static int execCallback(void *NotUsed, int nArg, char **azArg, char **azCol){
- int i, n;
- char *z;
- for(i=0; i<nArg; i++){
- z = azArg[i];
- if( z==0 ) z = "NULL";
- if( nReply>0 && nReply<sizeof(zReply)-1 ) zReply[nReply++] = ' ';
- n = strlen(z);
- if( nReply+n>=sizeof(zReply)-1 ) n = sizeof(zReply) - nReply - 1;
- memcpy(&zReply[nReply], z, n);
- nReply += n;
- zReply[nReply] = 0;
- }
- return 0;
-}
-
-static void runSql(sqlite3 *db, const char *zSql){
- char *zErr = 0;
- int rc;
- nReply = 0;
- rc = sqlite3_exec(db, zSql, execCallback, 0, &zErr);
- if( zErr ){
- fprintf(stderr, "SQL error: %s\n", zErr);
- exit(1);
- }
- if( rc ){
- fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
- exit(1);
- }
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int i;
-
- if( argc<3 ) usage(argv[0]);
- if( strcmp(argv[1], "new")==0 ){
- db = openDb(argv[argc-1]);
- for(i=2; i<argc-1; i++){
- if( strcmp(argv[i],"-utf8")==0 ){
- runSql(db, "PRAGMA encoding=UTF8");
- }else if( strcmp(argv[i], "-utf16le")==0 ){
- runSql(db, "PRAGMA encoding=UTF16LE");
- }else if( strcmp(argv[i], "-utf16be")==0 ){
- runSql(db, "PRAGMA encoding=UTF16BE");
- }else if( strncmp(argv[i], "-pagesize=", 10)==0 ){
- int szPg = atoi(&argv[i][10]);
- char zBuf[100];
- sprintf(zBuf, "PRAGMA pagesize=%d", szPg);
- runSql(db, zBuf);
- }else{
- fprintf(stderr, "unknown option %s\n", argv[i]);
- usage(argv[0]);
- }
- }
- runSql(db,
- "BEGIN;"
- "CREATE TABLE t1(x INTEGER PRIMARY KEY, y);"
- "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');"
- "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');"
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 4 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 8 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 16 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 32 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 64 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 128 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 256 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 512 */
- "INSERT INTO t1(y) SELECT y FROM t1;" /* 1024 */
- "UPDATE t1 SET y=(y || x);"
- "CREATE INDEX t1y ON t1(y);"
- "COMMIT;"
- );
- sqlite3_close(db);
- }else if( strcmp(argv[1], "check")==0 ){
- db = openDb(argv[argc-1]);
- runSql(db, "PRAGMA integrity_check");
- if( strcmp(zReply, "ok")!=0 ){
- fprintf(stderr, "Integrity check: %s\n", zReply);
- exit(1);
- }
- runSql(db,
- "SELECT count(*) FROM t1 WHERE y<>('abcdefghijklmnopqrstuvwxyz' || x)"
- );
- if( strcmp(zReply, "0")!=0 ){
- fprintf(stderr, "Wrong content\n");
- exit(1);
- }
- printf("Ok\n");
- }else if( strcmp(argv[1], "crash")==0 ){
- db = openDb(argv[argc-1]);
- for(i=2; i<argc-1; i++){
- if( strcmp(argv[i],"-wal")==0 ){
- runSql(db, "PRAGMA journal_mode=WAL");
- }else if( strcmp(argv[i], "-rollback")==0 ){
- runSql(db, "PRAGMA journal_mode=DELETE");
- }else{
- fprintf(stderr, "unknown option %s\n", argv[i]);
- usage(argv[0]);
- }
- }
- runSql(db,
- "PRAGMA cache_size=10;"
- "BEGIN;"
- "UPDATE t1 SET y=(y || -x)"
- );
- exit(0);
- }else{
- usage(argv[0]);
- }
- return 0;
-}
diff --git a/lib/libsqlite3/tool/showdb.c b/lib/libsqlite3/tool/showdb.c
deleted file mode 100644
index 892cacd5520..00000000000
--- a/lib/libsqlite3/tool/showdb.c
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
-** A utility for printing all or part of an SQLite database file.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-
-static struct GlobalData {
- int pagesize; /* Size of a database page */
- int dbfd; /* File descriptor for reading the DB */
- int mxPage; /* Last page number */
- int perLine; /* HEX elements to print per line */
- int bRaw; /* True to access db file via OS APIs */
- sqlite3_file *pFd; /* File descriptor for non-raw mode */
- sqlite3 *pDb; /* Database handle that owns pFd */
-} g = {1024, -1, 0, 16, 0, 0, 0};
-
-
-typedef long long int i64; /* Datatype for 64-bit integers */
-
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-/*
-** Extract a big-endian 32-bit integer
-*/
-static unsigned int decodeInt32(const unsigned char *z){
- return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
-}
-
-/* Report an out-of-memory error and die.
-*/
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Open a database connection.
-*/
-static sqlite3 *openDatabase(const char *zPrg, const char *zName){
- sqlite3 *db = 0;
- int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
- int rc = sqlite3_open_v2(zName, &db, flags, 0);
- if( rc!=SQLITE_OK ){
- const char *zErr = sqlite3_errmsg(db);
- fprintf(stderr, "%s: can't open %s (%s)\n", zPrg, zName, zErr);
- sqlite3_close(db);
- exit(1);
- }
- return db;
-}
-
-/**************************************************************************
-** Beginning of low-level file access functions.
-**
-** All low-level access to the database file read by this program is
-** performed using the following four functions:
-**
-** fileOpen() - open the db file
-** fileClose() - close the db file
-** fileRead() - read raw data from the db file
-** fileGetsize() - return the size of the db file in bytes
-*/
-
-/*
-** Open the database file.
-*/
-static void fileOpen(const char *zPrg, const char *zName){
- assert( g.dbfd<0 );
- if( g.bRaw==0 ){
- int rc;
- void *pArg = (void *)(&g.pFd);
- g.pDb = openDatabase(zPrg, zName);
- rc = sqlite3_file_control(g.pDb, "main", SQLITE_FCNTL_FILE_POINTER, pArg);
- if( rc!=SQLITE_OK ){
- fprintf(stderr,
- "%s: failed to obtain fd for %s (SQLite too old?)\n", zPrg, zName
- );
- exit(1);
- }
- }else{
- g.dbfd = open(zName, O_RDONLY);
- if( g.dbfd<0 ){
- fprintf(stderr,"%s: can't open %s\n", zPrg, zName);
- exit(1);
- }
- }
-}
-
-/*
-** Close the database file opened by fileOpen()
-*/
-static void fileClose(){
- if( g.bRaw==0 ){
- sqlite3_close(g.pDb);
- g.pDb = 0;
- g.pFd = 0;
- }else{
- close(g.dbfd);
- g.dbfd = -1;
- }
-}
-
-/*
-** Read content from the file.
-**
-** Space to hold the content is obtained from sqlite3_malloc() and needs
-** to be freed by the caller.
-*/
-static unsigned char *fileRead(sqlite3_int64 ofst, int nByte){
- unsigned char *aData;
- int got;
- aData = sqlite3_malloc(nByte+32);
- if( aData==0 ) out_of_memory();
- memset(aData, 0, nByte+32);
- if( g.bRaw==0 ){
- int rc = g.pFd->pMethods->xRead(g.pFd, (void*)aData, nByte, ofst);
- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
- fprintf(stderr, "error in xRead() - %d\n", rc);
- exit(1);
- }
- }else{
- lseek(g.dbfd, ofst, SEEK_SET);
- got = read(g.dbfd, aData, nByte);
- if( got>0 && got<nByte ) memset(aData+got, 0, nByte-got);
- }
- return aData;
-}
-
-/*
-** Return the size of the file in byte.
-*/
-static sqlite3_int64 fileGetsize(void){
- sqlite3_int64 res = 0;
- if( g.bRaw==0 ){
- int rc = g.pFd->pMethods->xFileSize(g.pFd, &res);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "error in xFileSize() - %d\n", rc);
- exit(1);
- }
- }else{
- struct stat sbuf;
- fstat(g.dbfd, &sbuf);
- res = (sqlite3_int64)(sbuf.st_size);
- }
- return res;
-}
-
-/*
-** End of low-level file access functions.
-**************************************************************************/
-
-/*
-** Print a range of bytes as hex and as ascii.
-*/
-static unsigned char *print_byte_range(
- int ofst, /* First byte in the range of bytes to print */
- int nByte, /* Number of bytes to print */
- int printOfst /* Add this amount to the index on the left column */
-){
- unsigned char *aData;
- int i, j;
- const char *zOfstFmt;
-
- if( ((printOfst+nByte)&~0xfff)==0 ){
- zOfstFmt = " %03x: ";
- }else if( ((printOfst+nByte)&~0xffff)==0 ){
- zOfstFmt = " %04x: ";
- }else if( ((printOfst+nByte)&~0xfffff)==0 ){
- zOfstFmt = " %05x: ";
- }else if( ((printOfst+nByte)&~0xffffff)==0 ){
- zOfstFmt = " %06x: ";
- }else{
- zOfstFmt = " %08x: ";
- }
-
- aData = fileRead(ofst, nByte);
- for(i=0; i<nByte; i += g.perLine){
- fprintf(stdout, zOfstFmt, i+printOfst);
- for(j=0; j<g.perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%02x ", aData[i+j]);
- }
- }
- for(j=0; j<g.perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- fprintf(stdout,"\n");
- }
- return aData;
-}
-
-/*
-** Print an entire page of content as hex
-*/
-static void print_page(int iPg){
- int iStart;
- unsigned char *aData;
- iStart = (iPg-1)*g.pagesize;
- fprintf(stdout, "Page %d: (offsets 0x%x..0x%x)\n",
- iPg, iStart, iStart+g.pagesize-1);
- aData = print_byte_range(iStart, g.pagesize, 0);
- sqlite3_free(aData);
-}
-
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static void print_decode_line(
- unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- const char *zMsg /* Message to append */
-){
- int i, j;
- int val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- sprintf(&zBuf[i], " %9d", val);
- printf("%s %s\n", zBuf, zMsg);
-}
-
-/*
-** Decode the database header.
-*/
-static void print_db_header(void){
- unsigned char *aData;
- aData = print_byte_range(0, 100, 0);
- printf("Decoded:\n");
- print_decode_line(aData, 16, 2, "Database page size");
- print_decode_line(aData, 18, 1, "File format write version");
- print_decode_line(aData, 19, 1, "File format read version");
- print_decode_line(aData, 20, 1, "Reserved space at end of page");
- print_decode_line(aData, 24, 4, "File change counter");
- print_decode_line(aData, 28, 4, "Size of database in pages");
- print_decode_line(aData, 32, 4, "Page number of first freelist page");
- print_decode_line(aData, 36, 4, "Number of freelist pages");
- print_decode_line(aData, 40, 4, "Schema cookie");
- print_decode_line(aData, 44, 4, "Schema format version");
- print_decode_line(aData, 48, 4, "Default page cache size");
- print_decode_line(aData, 52, 4, "Largest auto-vac root page");
- print_decode_line(aData, 56, 4, "Text encoding");
- print_decode_line(aData, 60, 4, "User version");
- print_decode_line(aData, 64, 4, "Incremental-vacuum mode");
- print_decode_line(aData, 68, 4, "Application ID");
- print_decode_line(aData, 72, 4, "meta[8]");
- print_decode_line(aData, 76, 4, "meta[9]");
- print_decode_line(aData, 80, 4, "meta[10]");
- print_decode_line(aData, 84, 4, "meta[11]");
- print_decode_line(aData, 88, 4, "meta[12]");
- print_decode_line(aData, 92, 4, "Change counter for version number");
- print_decode_line(aData, 96, 4, "SQLite version number");
-}
-
-/*
-** Describe cell content.
-*/
-static i64 describeContent(
- unsigned char *a, /* Cell content */
- i64 nLocal, /* Bytes in a[] */
- char *zDesc /* Write description here */
-){
- i64 nDesc = 0;
- int n, j;
- i64 i, x, v;
- const unsigned char *pData;
- const unsigned char *pLimit;
- char sep = ' ';
-
- pLimit = &a[nLocal];
- n = decodeVarint(a, &x);
- pData = &a[x];
- a += n;
- i = x - n;
- while( i>0 && pData<=pLimit ){
- n = decodeVarint(a, &x);
- a += n;
- i -= n;
- nLocal -= n;
- zDesc[0] = sep;
- sep = ',';
- nDesc++;
- zDesc++;
- if( x==0 ){
- sprintf(zDesc, "*"); /* NULL is a "*" */
- }else if( x>=1 && x<=6 ){
- v = (signed char)pData[0];
- pData++;
- switch( x ){
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 4: v = (v<<8) + pData[0]; pData++;
- case 3: v = (v<<8) + pData[0]; pData++;
- case 2: v = (v<<8) + pData[0]; pData++;
- }
- sprintf(zDesc, "%lld", v);
- }else if( x==7 ){
- sprintf(zDesc, "real");
- pData += 8;
- }else if( x==8 ){
- sprintf(zDesc, "0");
- }else if( x==9 ){
- sprintf(zDesc, "1");
- }else if( x>=12 ){
- i64 size = (x-12)/2;
- if( (x&1)==0 ){
- sprintf(zDesc, "blob(%lld)", size);
- }else{
- sprintf(zDesc, "txt(%lld)", size);
- }
- pData += size;
- }
- j = (int)strlen(zDesc);
- zDesc += j;
- nDesc += j;
- }
- return nDesc;
-}
-
-/*
-** Compute the local payload size given the total payload size and
-** the page size.
-*/
-static i64 localPayload(i64 nPayload, char cType){
- i64 maxLocal;
- i64 minLocal;
- i64 surplus;
- i64 nLocal;
- if( cType==13 ){
- /* Table leaf */
- maxLocal = g.pagesize-35;
- minLocal = (g.pagesize-12)*32/255-23;
- }else{
- maxLocal = (g.pagesize-12)*64/255-23;
- minLocal = (g.pagesize-12)*32/255-23;
- }
- if( nPayload>maxLocal ){
- surplus = minLocal + (nPayload-minLocal)%(g.pagesize-4);
- if( surplus<=maxLocal ){
- nLocal = surplus;
- }else{
- nLocal = minLocal;
- }
- }else{
- nLocal = nPayload;
- }
- return nLocal;
-}
-
-
-/*
-** Create a description for a single cell.
-**
-** The return value is the local cell size.
-*/
-static i64 describeCell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int showCellContent, /* Show cell content if true */
- char **pzDesc /* Store description here */
-){
- int i;
- i64 nDesc = 0;
- int n = 0;
- int leftChild;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- static char zDesc[1000];
- i = 0;
- if( cType<=5 ){
- leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
- a += 4;
- n += 4;
- sprintf(zDesc, "lx: %d ", leftChild);
- nDesc = strlen(zDesc);
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
- nDesc += strlen(&zDesc[nDesc]);
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "r: %lld ", rowid);
- nDesc += strlen(&zDesc[nDesc]);
- }
- if( nLocal<nPayload ){
- int ovfl;
- unsigned char *b = &a[nLocal];
- ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
- sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
- nDesc += strlen(&zDesc[nDesc]);
- n += 4;
- }
- if( showCellContent && cType!=5 ){
- nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
- }
- *pzDesc = zDesc;
- return nLocal+n;
-}
-
-/* Print an offset followed by nByte bytes. Add extra white-space
-** at the end so that subsequent text is aligned.
-*/
-static void printBytes(
- unsigned char *aData, /* Content being decoded */
- unsigned char *aStart, /* Start of content to be printed */
- int nByte /* Number of bytes to print */
-){
- int j;
- printf(" %03x: ", (int)(aStart-aData));
- for(j=0; j<9; j++){
- if( j>=nByte ){
- printf(" ");
- }else{
- printf("%02x ", aStart[j]);
- }
- }
-}
-
-
-/*
-** Write a full decode on stdout for the cell at a[ofst].
-** Assume the page contains a header of size szPgHdr bytes.
-*/
-static void decodeCell(
- unsigned char *a, /* Page content (without the page-1 header) */
- unsigned pgno, /* Page number */
- int iCell, /* Cell index */
- int szPgHdr, /* Size of the page header. 0 or 100 */
- int ofst /* Cell begins at a[ofst] */
-){
- int i, j = 0;
- int leftChild;
- i64 k;
- i64 nPayload;
- i64 rowid;
- i64 nHdr;
- i64 iType;
- i64 nLocal;
- unsigned char *x = a + ofst;
- unsigned char *end;
- unsigned char cType = a[0];
- int nCol = 0;
- int szCol[2000];
- int ofstCol[2000];
- int typeCol[2000];
-
- printf("Cell[%d]:\n", iCell);
- if( cType<=5 ){
- leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3];
- printBytes(a, x, 4);
- printf("left child page:: %d\n", leftChild);
- x += 4;
- }
- if( cType!=5 ){
- i = decodeVarint(x, &nPayload);
- printBytes(a, x, i);
- nLocal = localPayload(nPayload, cType);
- if( nLocal==nPayload ){
- printf("payload-size: %lld\n", nPayload);
- }else{
- printf("payload-size: %lld (%lld local, %lld overflow)\n",
- nPayload, nLocal, nPayload-nLocal);
- }
- x += i;
- }else{
- nPayload = nLocal = 0;
- }
- end = x + nLocal;
- if( cType==5 || cType==13 ){
- i = decodeVarint(x, &rowid);
- printBytes(a, x, i);
- printf("rowid: %lld\n", rowid);
- x += i;
- }
- if( nLocal>0 ){
- i = decodeVarint(x, &nHdr);
- printBytes(a, x, i);
- printf("record-header-size: %d\n", (int)nHdr);
- j = i;
- nCol = 0;
- k = nHdr;
- while( x+j<end && j<nHdr ){
- const char *zTypeName;
- int sz = 0;
- char zNm[30];
- i = decodeVarint(x+j, &iType);
- printBytes(a, x+j, i);
- printf("typecode[%d]: %d - ", nCol, (int)iType);
- switch( iType ){
- case 0: zTypeName = "NULL"; sz = 0; break;
- case 1: zTypeName = "int8"; sz = 1; break;
- case 2: zTypeName = "int16"; sz = 2; break;
- case 3: zTypeName = "int24"; sz = 3; break;
- case 4: zTypeName = "int32"; sz = 4; break;
- case 5: zTypeName = "int48"; sz = 6; break;
- case 6: zTypeName = "int64"; sz = 8; break;
- case 7: zTypeName = "double"; sz = 8; break;
- case 8: zTypeName = "zero"; sz = 0; break;
- case 9: zTypeName = "one"; sz = 0; break;
- case 10:
- case 11: zTypeName = "error"; sz = 0; break;
- default: {
- sz = (int)(iType-12)/2;
- sprintf(zNm, (iType&1)==0 ? "blob(%d)" : "text(%d)", sz);
- zTypeName = zNm;
- break;
- }
- }
- printf("%s\n", zTypeName);
- szCol[nCol] = sz;
- ofstCol[nCol] = (int)k;
- typeCol[nCol] = (int)iType;
- k += sz;
- nCol++;
- j += i;
- }
- for(i=0; i<nCol && ofstCol[i]+szCol[i]<=nLocal; i++){
- int s = ofstCol[i];
- i64 v;
- const unsigned char *pData;
- if( szCol[i]==0 ) continue;
- printBytes(a, x+s, szCol[i]);
- printf("data[%d]: ", i);
- pData = x+s;
- if( typeCol[i]<=7 ){
- v = (signed char)pData[0];
- for(k=1; k<szCol[i]; k++){
- v = (v<<8) + pData[k];
- }
- if( typeCol[i]==7 ){
- double r;
- memcpy(&r, &v, sizeof(r));
- printf("%#g\n", r);
- }else{
- printf("%lld\n", v);
- }
- }else{
- int ii, jj;
- char zConst[32];
- if( (typeCol[i]&1)==0 ){
- zConst[0] = 'x';
- zConst[1] = '\'';
- for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){
- sprintf(zConst+ii, "%02x", pData[jj]);
- }
- }else{
- zConst[0] = '\'';
- for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){
- zConst[ii] = isprint(pData[jj]) ? pData[jj] : '.';
- }
- zConst[ii] = 0;
- }
- if( jj<szCol[i] ){
- memcpy(zConst+ii, "...'", 5);
- }else{
- memcpy(zConst+ii, "'", 2);
- }
- printf("%s\n", zConst);
- }
- j = ofstCol[i] + szCol[i];
- }
- }
- if( j<nLocal ){
- printBytes(a, x+j, 0);
- printf("... %lld bytes of content ...\n", nLocal-j);
- }
- if( nLocal<nPayload ){
- printBytes(a, x+nLocal, 4);
- printf("overflow-page: %d\n", decodeInt32(x+nLocal));
- }
-}
-
-
-/*
-** Decode a btree page
-*/
-static void decode_btree_page(
- unsigned char *a, /* Page content */
- int pgno, /* Page number */
- int hdrSize, /* Size of the page header. 0 or 100 */
- char *zArgs /* Flags to control formatting */
-){
- const char *zType = "unknown";
- int nCell;
- int i, j;
- int iCellPtr;
- int showCellContent = 0;
- int showMap = 0;
- int cellToDecode = -2;
- char *zMap = 0;
- switch( a[0] ){
- case 2: zType = "index interior node"; break;
- case 5: zType = "table interior node"; break;
- case 10: zType = "index leaf"; break;
- case 13: zType = "table leaf"; break;
- }
- while( zArgs[0] ){
- switch( zArgs[0] ){
- case 'c': showCellContent = 1; break;
- case 'm': showMap = 1; break;
- case 'd': {
- if( !isdigit(zArgs[1]) ){
- cellToDecode = -1;
- }else{
- cellToDecode = 0;
- while( isdigit(zArgs[1]) ){
- zArgs++;
- cellToDecode = cellToDecode*10 + zArgs[0] - '0';
- }
- }
- break;
- }
- }
- zArgs++;
- }
- nCell = a[3]*256 + a[4];
- iCellPtr = (a[0]==2 || a[0]==5) ? 12 : 8;
- if( cellToDecode>=nCell ){
- printf("Page %d has only %d cells\n", pgno, nCell);
- return;
- }
- printf("Header on btree page %d:\n", pgno);
- print_decode_line(a, 0, 1, zType);
- print_decode_line(a, 1, 2, "Offset to first freeblock");
- print_decode_line(a, 3, 2, "Number of cells on this page");
- print_decode_line(a, 5, 2, "Offset to cell content area");
- print_decode_line(a, 7, 1, "Fragmented byte count");
- if( a[0]==2 || a[0]==5 ){
- print_decode_line(a, 8, 4, "Right child");
- }
- if( cellToDecode==(-2) && nCell>0 ){
- printf(" key: lx=left-child n=payload-size r=rowid\n");
- }
- if( showMap ){
- zMap = sqlite3_malloc(g.pagesize);
- memset(zMap, '.', g.pagesize);
- memset(zMap, '1', hdrSize);
- memset(&zMap[hdrSize], 'H', iCellPtr);
- memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
- }
- for(i=0; i<nCell; i++){
- int cofst = iCellPtr + i*2;
- char *zDesc;
- i64 n;
-
- cofst = a[cofst]*256 + a[cofst+1];
- n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
- if( showMap ){
- char zBuf[30];
- memset(&zMap[cofst], '*', (size_t)n);
- zMap[cofst] = '[';
- zMap[cofst+n-1] = ']';
- sprintf(zBuf, "%d", i);
- j = (int)strlen(zBuf);
- if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
- }
- if( cellToDecode==(-2) ){
- printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
- }else if( cellToDecode==(-1) || cellToDecode==i ){
- decodeCell(a, pgno, i, hdrSize, cofst-hdrSize);
- }
- }
- if( showMap ){
- printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n");
- for(i=0; i<g.pagesize; i+=64){
- printf(" %03x: %.64s\n", i, &zMap[i]);
- }
- sqlite3_free(zMap);
- }
-}
-
-/*
-** Decode a freelist trunk page.
-*/
-static void decode_trunk_page(
- int pgno, /* The page number */
- int detail, /* Show leaf pages if true */
- int recursive /* Follow the trunk change if true */
-){
- int n, i;
- unsigned char *a;
- while( pgno>0 ){
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- printf("Decode of freelist trunk page %d:\n", pgno);
- print_decode_line(a, 0, 4, "Next freelist trunk page");
- print_decode_line(a, 4, 4, "Number of entries on this page");
- if( detail ){
- n = (int)decodeInt32(&a[4]);
- for(i=0; i<n; i++){
- unsigned int x = decodeInt32(&a[8+4*i]);
- char zIdx[10];
- sprintf(zIdx, "[%d]", i);
- printf(" %5s %7u", zIdx, x);
- if( i%5==4 ) printf("\n");
- }
- if( i%5!=0 ) printf("\n");
- }
- if( !recursive ){
- pgno = 0;
- }else{
- pgno = (int)decodeInt32(&a[0]);
- }
- sqlite3_free(a);
- }
-}
-
-/*
-** A short text comment on the use of each page.
-*/
-static char **zPageUse;
-
-/*
-** Add a comment on the use of a page.
-*/
-static void page_usage_msg(int pgno, const char *zFormat, ...){
- va_list ap;
- char *zMsg;
-
- va_start(ap, zFormat);
- zMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( pgno<=0 || pgno>g.mxPage ){
- printf("ERROR: page %d out of range 1..%d: %s\n",
- pgno, g.mxPage, zMsg);
- sqlite3_free(zMsg);
- return;
- }
- if( zPageUse[pgno]!=0 ){
- printf("ERROR: page %d used multiple times:\n", pgno);
- printf("ERROR: previous: %s\n", zPageUse[pgno]);
- printf("ERROR: current: %s\n", zMsg);
- sqlite3_free(zPageUse[pgno]);
- }
- zPageUse[pgno] = zMsg;
-}
-
-/*
-** Find overflow pages of a cell and describe their usage.
-*/
-static void page_usage_cell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int pgno, /* page containing the cell */
- int cellno /* Index of the cell on the page */
-){
- int i;
- int n = 0;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- i = 0;
- if( cType<=5 ){
- a += 4;
- n += 4;
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- }
- if( nLocal<nPayload ){
- int ovfl = decodeInt32(a+nLocal);
- int cnt = 0;
- while( ovfl && (cnt++)<g.mxPage ){
- page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
- cnt, cellno, pgno);
- a = fileRead((ovfl-1)*g.pagesize, 4);
- ovfl = decodeInt32(a);
- sqlite3_free(a);
- }
- }
-}
-
-
-/*
-** Describe the usages of a b-tree page
-*/
-static void page_usage_btree(
- int pgno, /* Page to describe */
- int parent, /* Parent of this page. 0 for root pages */
- int idx, /* Which child of the parent */
- const char *zName /* Name of the table */
-){
- unsigned char *a;
- const char *zType = "corrupt node";
- int nCell;
- int i;
- int hdr = pgno==1 ? 100 : 0;
-
- if( pgno<=0 || pgno>g.mxPage ) return;
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- switch( a[hdr] ){
- case 2: zType = "interior node of index"; break;
- case 5: zType = "interior node of table"; break;
- case 10: zType = "leaf of index"; break;
- case 13: zType = "leaf of table"; break;
- }
- if( parent ){
- page_usage_msg(pgno, "%s [%s], child %d of page %d",
- zType, zName, idx, parent);
- }else{
- page_usage_msg(pgno, "root %s [%s]", zType, zName);
- }
- nCell = a[hdr+3]*256 + a[hdr+4];
- if( a[hdr]==2 || a[hdr]==5 ){
- int cellstart = hdr+12;
- unsigned int child;
- for(i=0; i<nCell; i++){
- int ofst;
-
- ofst = cellstart + i*2;
- ofst = a[ofst]*256 + a[ofst+1];
- child = decodeInt32(a+ofst);
- page_usage_btree(child, pgno, i, zName);
- }
- child = decodeInt32(a+cellstart-4);
- page_usage_btree(child, pgno, i, zName);
- }
- if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){
- int cellstart = hdr + 8 + 4*(a[hdr]<=5);
- for(i=0; i<nCell; i++){
- int ofst;
- ofst = cellstart + i*2;
- ofst = a[ofst]*256 + a[ofst+1];
- page_usage_cell(a[hdr], a+ofst, pgno, i);
- }
- }
- sqlite3_free(a);
-}
-
-/*
-** Determine page usage by the freelist
-*/
-static void page_usage_freelist(int pgno){
- unsigned char *a;
- int cnt = 0;
- int i;
- int n;
- int iNext;
- int parent = 1;
-
- while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
- page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
- a = fileRead((pgno-1)*g.pagesize, g.pagesize);
- iNext = decodeInt32(a);
- n = decodeInt32(a+4);
- for(i=0; i<n; i++){
- int child = decodeInt32(a + (i*4+8));
- page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
- i, pgno);
- }
- sqlite3_free(a);
- parent = pgno;
- pgno = iNext;
- }
-}
-
-/*
-** Determine pages used as PTRMAP pages
-*/
-static void page_usage_ptrmap(unsigned char *a){
- if( a[55] ){
- int usable = g.pagesize - a[20];
- int pgno = 2;
- int perPage = usable/5;
- while( pgno<=g.mxPage ){
- page_usage_msg(pgno, "PTRMAP page covering %d..%d",
- pgno+1, pgno+perPage);
- pgno += perPage + 1;
- }
- }
-}
-
-/*
-** Try to figure out how every page in the database file is being used.
-*/
-static void page_usage_report(const char *zPrg, const char *zDbName){
- int i, j;
- int rc;
- sqlite3 *db;
- sqlite3_stmt *pStmt;
- unsigned char *a;
- char zQuery[200];
-
- /* Avoid the pathological case */
- if( g.mxPage<1 ){
- printf("empty database\n");
- return;
- }
-
- /* Open the database file */
- db = openDatabase(zPrg, zDbName);
-
- /* Set up global variables zPageUse[] and g.mxPage to record page
- ** usages */
- zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(g.mxPage+1) );
- if( zPageUse==0 ) out_of_memory();
- memset(zPageUse, 0, sizeof(zPageUse[0])*(g.mxPage+1));
-
- /* Discover the usage of each page */
- a = fileRead(0, 100);
- page_usage_freelist(decodeInt32(a+32));
- page_usage_ptrmap(a);
- sqlite3_free(a);
- page_usage_btree(1, 0, 0, "sqlite_master");
- sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
- for(j=0; j<2; j++){
- sqlite3_snprintf(sizeof(zQuery), zQuery,
- "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
- " ORDER BY rowid %s", j?"DESC":"");
- rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- int pgno = sqlite3_column_int(pStmt, 2);
- page_usage_btree(pgno, 0, 0, (const char*)sqlite3_column_text(pStmt,1));
- }
- }else{
- printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
- }
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) break;
- }
- sqlite3_close(db);
-
- /* Print the report and free memory used */
- for(i=1; i<=g.mxPage; i++){
- printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
- sqlite3_free(zPageUse[i]);
- }
- sqlite3_free(zPageUse);
- zPageUse = 0;
-}
-
-/*
-** Try to figure out how every page in the database file is being used.
-*/
-static void ptrmap_coverage_report(const char *zDbName){
- int pgno;
- unsigned char *aHdr;
- unsigned char *a;
- int usable;
- int perPage;
- int i;
-
- /* Avoid the pathological case */
- if( g.mxPage<1 ){
- printf("empty database\n");
- return;
- }
-
- /* Make sure PTRMAPs are used in this database */
- aHdr = fileRead(0, 100);
- if( aHdr[55]==0 ){
- printf("database does not use PTRMAP pages\n");
- return;
- }
- usable = g.pagesize - aHdr[20];
- perPage = usable/5;
- sqlite3_free(aHdr);
- printf("%5d: root of sqlite_master\n", 1);
- for(pgno=2; pgno<=g.mxPage; pgno += perPage+1){
- printf("%5d: PTRMAP page covering %d..%d\n", pgno,
- pgno+1, pgno+perPage);
- a = fileRead((pgno-1)*g.pagesize, usable);
- for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
- const char *zType = "???";
- unsigned int iFrom = decodeInt32(&a[i+1]);
- switch( a[i] ){
- case 1: zType = "b-tree root page"; break;
- case 2: zType = "freelist page"; break;
- case 3: zType = "first page of overflow"; break;
- case 4: zType = "later page of overflow"; break;
- case 5: zType = "b-tree non-root page"; break;
- }
- printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
- }
- sqlite3_free(a);
- }
-}
-
-/*
-** Print a usage comment
-*/
-static void usage(const char *argv0){
- fprintf(stderr, "Usage %s ?--uri? FILENAME ?args...?\n\n", argv0);
- fprintf(stderr,
- "switches:\n"
- " --raw Read db file directly, bypassing SQLite VFS\n"
- "args:\n"
- " dbheader Show database header\n"
- " pgidx Index of how each page is used\n"
- " ptrmap Show all PTRMAP page content\n"
- " NNN..MMM Show hex of pages NNN through MMM\n"
- " NNN..end Show hex of pages NNN through end of file\n"
- " NNNb Decode btree page NNN\n"
- " NNNbc Decode btree page NNN and show content\n"
- " NNNbm Decode btree page NNN and show a layout map\n"
- " NNNbdCCC Decode cell CCC on btree page NNN\n"
- " NNNt Decode freelist trunk page NNN\n"
- " NNNtd Show leaf freelist pages on the decode\n"
- " NNNtr Recursively decode freelist starting at NNN\n"
- );
-}
-
-int main(int argc, char **argv){
- sqlite3_int64 szFile;
- unsigned char *zPgSz;
- const char *zPrg = argv[0]; /* Name of this executable */
- char **azArg = argv;
- int nArg = argc;
-
- /* Check for the "--uri" or "-uri" switch. */
- if( nArg>1 ){
- if( sqlite3_stricmp("-raw", azArg[1])==0
- || sqlite3_stricmp("--raw", azArg[1])==0
- ){
- g.bRaw = 1;
- azArg++;
- nArg--;
- }
- }
-
- if( nArg<2 ){
- usage(zPrg);
- exit(1);
- }
-
- fileOpen(zPrg, azArg[1]);
- szFile = fileGetsize();
-
- zPgSz = fileRead(16, 2);
- g.pagesize = zPgSz[0]*256 + zPgSz[1]*65536;
- if( g.pagesize==0 ) g.pagesize = 1024;
- sqlite3_free(zPgSz);
-
- printf("Pagesize: %d\n", g.pagesize);
- g.mxPage = (szFile+g.pagesize-1)/g.pagesize;
-
- printf("Available pages: 1..%d\n", g.mxPage);
- if( nArg==2 ){
- int i;
- for(i=1; i<=g.mxPage; i++) print_page(i);
- }else{
- int i;
- for(i=2; i<nArg; i++){
- int iStart, iEnd;
- char *zLeft;
- if( strcmp(azArg[i], "dbheader")==0 ){
- print_db_header();
- continue;
- }
- if( strcmp(azArg[i], "pgidx")==0 ){
- page_usage_report(zPrg, azArg[1]);
- continue;
- }
- if( strcmp(azArg[i], "ptrmap")==0 ){
- ptrmap_coverage_report(azArg[1]);
- continue;
- }
- if( strcmp(azArg[i], "help")==0 ){
- usage(zPrg);
- continue;
- }
- if( !isdigit(azArg[i][0]) ){
- fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]);
- continue;
- }
- iStart = strtol(azArg[i], &zLeft, 0);
- if( zLeft && strcmp(zLeft,"..end")==0 ){
- iEnd = g.mxPage;
- }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
- iEnd = strtol(&zLeft[2], 0, 0);
- }else if( zLeft && zLeft[0]=='b' ){
- int ofst, nByte, hdrSize;
- unsigned char *a;
- if( iStart==1 ){
- ofst = hdrSize = 100;
- nByte = g.pagesize-100;
- }else{
- hdrSize = 0;
- ofst = (iStart-1)*g.pagesize;
- nByte = g.pagesize;
- }
- a = fileRead(ofst, nByte);
- decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
- sqlite3_free(a);
- continue;
- }else if( zLeft && zLeft[0]=='t' ){
- int detail = 0;
- int recursive = 0;
- int i;
- for(i=1; zLeft[i]; i++){
- if( zLeft[i]=='r' ) recursive = 1;
- if( zLeft[i]=='d' ) detail = 1;
- }
- decode_trunk_page(iStart, detail, recursive);
- continue;
- }else{
- iEnd = iStart;
- }
- if( iStart<1 || iEnd<iStart || iEnd>g.mxPage ){
- fprintf(stderr,
- "Page argument should be LOWER?..UPPER?. Range 1 to %d\n",
- g.mxPage);
- exit(1);
- }
- while( iStart<=iEnd ){
- print_page(iStart);
- iStart++;
- }
- }
- }
- fileClose();
- return 0;
-}
diff --git a/lib/libsqlite3/tool/showjournal.c b/lib/libsqlite3/tool/showjournal.c
deleted file mode 100644
index 19220f5196a..00000000000
--- a/lib/libsqlite3/tool/showjournal.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-** A utility for printing an SQLite database journal.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
-** state information
-*/
-static int pageSize = 1024;
-static int sectorSize = 512;
-static FILE *db = 0;
-static int fileSize = 0;
-static unsigned cksumNonce = 0;
-
-/* Report a memory allocation error */
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Read N bytes of memory starting at iOfst into space obtained
-** from malloc().
-*/
-static unsigned char *read_content(int N, int iOfst){
- int got;
- unsigned char *pBuf = malloc(N);
- if( pBuf==0 ) out_of_memory();
- fseek(db, iOfst, SEEK_SET);
- got = fread(pBuf, 1, N, db);
- if( got<0 ){
- fprintf(stderr, "I/O error reading %d bytes from %d\n", N, iOfst);
- memset(pBuf, 0, N);
- }else if( got<N ){
- fprintf(stderr, "Short read: got only %d of %d bytes from %d\n",
- got, N, iOfst);
- memset(&pBuf[got], 0, N-got);
- }
- return pBuf;
-}
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static unsigned print_decode_line(
- const unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- const char *zMsg /* Message to append */
-){
- int i, j;
- unsigned val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %05x: %02x", ofst, aData[ofst]);
- i = strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += strlen(&zBuf[i]);
- }
- sprintf(&zBuf[i], " %10u", val);
- printf("%s %s\n", zBuf, zMsg);
- return val;
-}
-
-/*
-** Read and print a journal header. Store key information (page size, etc)
-** in global variables.
-*/
-static unsigned decode_journal_header(int iOfst){
- unsigned char *pHdr = read_content(64, iOfst);
- unsigned nPage;
- printf("Header at offset %d:\n", iOfst);
- print_decode_line(pHdr, 0, 4, "Header part 1 (3654616569)");
- print_decode_line(pHdr, 4, 4, "Header part 2 (547447767)");
- nPage =
- print_decode_line(pHdr, 8, 4, "page count");
- cksumNonce =
- print_decode_line(pHdr, 12, 4, "chksum nonce");
- print_decode_line(pHdr, 16, 4, "initial database size in pages");
- sectorSize =
- print_decode_line(pHdr, 20, 4, "sector size");
- pageSize =
- print_decode_line(pHdr, 24, 4, "page size");
- print_decode_line(pHdr, 28, 4, "zero");
- print_decode_line(pHdr, 32, 4, "zero");
- print_decode_line(pHdr, 36, 4, "zero");
- print_decode_line(pHdr, 40, 4, "zero");
- free(pHdr);
- return nPage;
-}
-
-static void print_page(int iOfst){
- unsigned char *aData;
- char zTitle[50];
- aData = read_content(pageSize+8, iOfst);
- sprintf(zTitle, "page number for page at offset %d", iOfst);
- print_decode_line(aData-iOfst, iOfst, 4, zTitle);
- free(aData);
-}
-
-int main(int argc, char **argv){
- int nPage, cnt;
- int iOfst;
- if( argc!=2 ){
- fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
- exit(1);
- }
- db = fopen(argv[1], "rb");
- if( db==0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- fseek(db, 0, SEEK_END);
- fileSize = ftell(db);
- printf("journal file size: %d bytes\n", fileSize);
- fseek(db, 0, SEEK_SET);
- iOfst = 0;
- while( iOfst<fileSize ){
- cnt = nPage = (int)decode_journal_header(iOfst);
- if( cnt==0 ){
- cnt = (fileSize - sectorSize)/(pageSize+8);
- }
- iOfst += sectorSize;
- while( cnt && iOfst<fileSize ){
- print_page(iOfst);
- iOfst += pageSize+8;
- }
- iOfst = (iOfst/sectorSize + 1)*sectorSize;
- }
- fclose(db);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/showlocks.c b/lib/libsqlite3/tool/showlocks.c
deleted file mode 100644
index 752c535cc37..00000000000
--- a/lib/libsqlite3/tool/showlocks.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-** This file implements a simple command-line utility that shows all of the
-** Posix Advisory Locks on a file.
-**
-** Usage:
-**
-** showlocks FILENAME
-**
-** To compile: gcc -o showlocks showlocks.c
-*/
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* This utility only looks for locks in the first 2 billion bytes */
-#define MX_LCK 2147483647
-
-/*
-** Print all locks on the inode of "fd" that occur in between
-** lwr and upr, inclusive.
-*/
-static int showLocksInRange(int fd, off_t lwr, off_t upr){
- int cnt = 0;
- struct flock x;
-
- x.l_type = F_WRLCK;
- x.l_whence = SEEK_SET;
- x.l_start = lwr;
- x.l_len = upr-lwr;
- fcntl(fd, F_GETLK, &x);
- if( x.l_type==F_UNLCK ) return 0;
- printf("start: %-12d len: %-5d pid: %-5d type: %s\n",
- (int)x.l_start, (int)x.l_len,
- x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK");
- cnt++;
- if( x.l_start>lwr ){
- cnt += showLocksInRange(fd, lwr, x.l_start-1);
- }
- if( x.l_start+x.l_len<upr ){
- cnt += showLocksInRange(fd, x.l_start+x.l_len+1, upr);
- }
- return cnt;
-}
-
-int main(int argc, char **argv){
- int fd;
- int cnt;
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
- return 1;
- }
- fd = open(argv[1], O_RDWR, 0);
- if( fd<0 ){
- fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
- return 1;
- }
- cnt = showLocksInRange(fd, 0, MX_LCK);
- if( cnt==0 ) printf("no locks\n");
- close(fd);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/showstat4.c b/lib/libsqlite3/tool/showstat4.c
deleted file mode 100644
index 215962919ed..00000000000
--- a/lib/libsqlite3/tool/showstat4.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-** This utility program decodes and displays the content of the
-** sqlite_stat4 table in the database file named on the command
-** line.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "sqlite3.h"
-
-typedef sqlite3_int64 i64; /* 64-bit signed integer type */
-
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-
-
-int main(int argc, char **argv){
- sqlite3 *db;
- sqlite3_stmt *pStmt;
- char *zIdx = 0;
- int rc, j, x, y, mxHdr;
- const unsigned char *aSample;
- int nSample;
- i64 iVal;
- const char *zSep;
- int iRow = 0;
-
- if( argc!=2 ){
- fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]);
- exit(1);
- }
- rc = sqlite3_open(argv[1], &db);
- if( rc!=SQLITE_OK || db==0 ){
- fprintf(stderr, "Cannot open database file [%s]\n", argv[1]);
- exit(1);
- }
- rc = sqlite3_prepare_v2(db,
- "SELECT tbl||'.'||idx, nEq, nLT, nDLt, sample "
- "FROM sqlite_stat4 ORDER BY 1", -1,
- &pStmt, 0);
- if( rc!=SQLITE_OK || pStmt==0 ){
- fprintf(stderr, "%s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){
- if( zIdx ) printf("\n**************************************"
- "**************\n\n");
- sqlite3_free(zIdx);
- zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0));
- iRow = 0;
- }
- printf("%s sample %d ------------------------------------\n", zIdx, ++iRow);
- printf(" nEq = %s\n", sqlite3_column_text(pStmt,1));
- printf(" nLt = %s\n", sqlite3_column_text(pStmt,2));
- printf(" nDLt = %s\n", sqlite3_column_text(pStmt,3));
- printf(" sample = x'");
- aSample = sqlite3_column_blob(pStmt,4);
- nSample = sqlite3_column_bytes(pStmt,4);
- for(j=0; j<nSample; j++) printf("%02x", aSample[j]);
- printf("'\n ");
- zSep = " ";
- x = decodeVarint(aSample, &iVal);
- if( iVal<x || iVal>nSample ){
- printf(" <error>\n");
- continue;
- }
- y = mxHdr = (int)iVal;
- while( x<mxHdr ){
- int sz;
- i64 v;
- x += decodeVarint(aSample+x, &iVal);
- if( x>mxHdr ) break;
- if( iVal<0 ) break;
- switch( iVal ){
- case 0: sz = 0; break;
- case 1: sz = 1; break;
- case 2: sz = 2; break;
- case 3: sz = 3; break;
- case 4: sz = 4; break;
- case 5: sz = 6; break;
- case 6: sz = 8; break;
- case 7: sz = 8; break;
- case 8: sz = 0; break;
- case 9: sz = 0; break;
- case 10:
- case 11: sz = 0; break;
- default: sz = (int)(iVal-12)/2; break;
- }
- if( y+sz>nSample ) break;
- if( iVal==0 ){
- printf("%sNULL", zSep);
- }else if( iVal==8 || iVal==9 ){
- printf("%s%d", zSep, ((int)iVal)-8);
- }else if( iVal<=7 ){
- v = (signed char)aSample[y];
- for(j=1; j<sz; j++){
- v = (v<<8) + aSample[y+j];
- }
- if( iVal==7 ){
- double r;
- memcpy(&r, &v, sizeof(r));
- printf("%s%#g", zSep, r);
- }else{
- printf("%s%lld", zSep, v);
- }
- }else if( (iVal&1)==0 ){
- printf("%sx'", zSep);
- for(j=0; j<sz; j++){
- printf("%02x", aSample[y+j]);
- }
- printf("'");
- }else{
- printf("%s\"", zSep);
- for(j=0; j<sz; j++){
- char c = (char)aSample[y+j];
- if( isprint(c) ){
- if( c=='"' || c=='\\' ) putchar('\\');
- putchar(c);
- }else if( c=='\n' ){
- printf("\\n");
- }else if( c=='\t' ){
- printf("\\t");
- }else if( c=='\r' ){
- printf("\\r");
- }else{
- printf("\\%03o", c);
- }
- }
- printf("\"");
- }
- zSep = ",";
- y += sz;
- }
- printf("\n");
- }
- sqlite3_free(zIdx);
- sqlite3_finalize(pStmt);
- sqlite3_close(db);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/showwal.c b/lib/libsqlite3/tool/showwal.c
deleted file mode 100644
index 35810c66a96..00000000000
--- a/lib/libsqlite3/tool/showwal.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
-** A utility for printing content from a write-ahead log file.
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if !defined(_MSC_VER)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-
-static int pagesize = 1024; /* Size of a database page */
-static int fd = -1; /* File descriptor for reading the WAL file */
-static int mxFrame = 0; /* Last frame */
-static int perLine = 16; /* HEX elements to print per line */
-
-typedef long long int i64; /* Datatype for 64-bit integers */
-
-/* Information for computing the checksum */
-typedef struct Cksum Cksum;
-struct Cksum {
- int bSwap; /* True to do byte swapping on 32-bit words */
- unsigned s0, s1; /* Current checksum value */
-};
-
-/*
-** extract a 32-bit big-endian integer
-*/
-static unsigned int getInt32(const unsigned char *a){
- unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
- return x;
-}
-
-/*
-** Swap bytes on a 32-bit unsigned integer
-*/
-static unsigned int swab32(unsigned int x){
- return (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)
- + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24);
-}
-
-/* Extend the checksum. Reinitialize the checksum if bInit is true.
-*/
-static void extendCksum(
- Cksum *pCksum,
- unsigned char *aData,
- unsigned int nByte,
- int bInit
-){
- unsigned int *a32;
- if( bInit ){
- int a = 0;
- *((char*)&a) = 1;
- if( a==1 ){
- /* Host is little-endian */
- pCksum->bSwap = getInt32(aData)!=0x377f0682;
- }else{
- /* Host is big-endian */
- pCksum->bSwap = getInt32(aData)!=0x377f0683;
- }
- pCksum->s0 = 0;
- pCksum->s1 = 0;
- }
- a32 = (unsigned int*)aData;
- while( nByte>0 ){
- unsigned int x0 = a32[0];
- unsigned int x1 = a32[1];
- if( pCksum->bSwap ){
- x0 = swab32(x0);
- x1 = swab32(x1);
- }
- pCksum->s0 += x0 + pCksum->s1;
- pCksum->s1 += x1 + pCksum->s0;
- nByte -= 8;
- a32 += 2;
- }
-}
-
-/*
-** Convert the var-int format into i64. Return the number of bytes
-** in the var-int. Write the var-int value into *pVal.
-*/
-static int decodeVarint(const unsigned char *z, i64 *pVal){
- i64 v = 0;
- int i;
- for(i=0; i<8; i++){
- v = (v<<7) + (z[i]&0x7f);
- if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
- }
- v = (v<<8) + (z[i]&0xff);
- *pVal = v;
- return 9;
-}
-
-/* Report an out-of-memory error and die.
-*/
-static void out_of_memory(void){
- fprintf(stderr,"Out of memory...\n");
- exit(1);
-}
-
-/*
-** Read content from the file.
-**
-** Space to hold the content is obtained from malloc() and needs to be
-** freed by the caller.
-*/
-static unsigned char *getContent(int ofst, int nByte){
- unsigned char *aData;
- aData = malloc(nByte);
- if( aData==0 ) out_of_memory();
- lseek(fd, ofst, SEEK_SET);
- read(fd, aData, nByte);
- return aData;
-}
-
-/*
-** Print a range of bytes as hex and as ascii.
-*/
-static void print_byte_range(
- int ofst, /* First byte in the range of bytes to print */
- int nByte, /* Number of bytes to print */
- unsigned char *aData, /* Content to print */
- int printOfst /* Add this amount to the index on the left column */
-){
- int i, j;
- const char *zOfstFmt;
-
- if( ((printOfst+nByte)&~0xfff)==0 ){
- zOfstFmt = " %03x: ";
- }else if( ((printOfst+nByte)&~0xffff)==0 ){
- zOfstFmt = " %04x: ";
- }else if( ((printOfst+nByte)&~0xfffff)==0 ){
- zOfstFmt = " %05x: ";
- }else if( ((printOfst+nByte)&~0xffffff)==0 ){
- zOfstFmt = " %06x: ";
- }else{
- zOfstFmt = " %08x: ";
- }
-
- for(i=0; i<nByte; i += perLine){
- fprintf(stdout, zOfstFmt, i+printOfst);
- for(j=0; j<perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%02x ", aData[i+j]);
- }
- }
- for(j=0; j<perLine; j++){
- if( i+j>nByte ){
- fprintf(stdout, " ");
- }else{
- fprintf(stdout,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
- }
- }
- fprintf(stdout,"\n");
- }
-}
-
-/* Print a line of decode output showing a 4-byte integer.
-*/
-static void print_decode_line(
- unsigned char *aData, /* Content being decoded */
- int ofst, int nByte, /* Start and size of decode */
- int asHex, /* If true, output value as hex */
- const char *zMsg /* Message to append */
-){
- int i, j;
- int val = aData[ofst];
- char zBuf[100];
- sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
- i = (int)strlen(zBuf);
- for(j=1; j<4; j++){
- if( j>=nByte ){
- sprintf(&zBuf[i], " ");
- }else{
- sprintf(&zBuf[i], " %02x", aData[ofst+j]);
- val = val*256 + aData[ofst+j];
- }
- i += (int)strlen(&zBuf[i]);
- }
- if( asHex ){
- sprintf(&zBuf[i], " 0x%08x", val);
- }else{
- sprintf(&zBuf[i], " %9d", val);
- }
- printf("%s %s\n", zBuf, zMsg);
-}
-
-/*
-** Print an entire page of content as hex
-*/
-static void print_frame(int iFrame){
- int iStart;
- unsigned char *aData;
- iStart = 32 + (iFrame-1)*(pagesize+24);
- fprintf(stdout, "Frame %d: (offsets 0x%x..0x%x)\n",
- iFrame, iStart, iStart+pagesize+24);
- aData = getContent(iStart, pagesize+24);
- print_decode_line(aData, 0, 4, 0, "Page number");
- print_decode_line(aData, 4, 4, 0, "DB size, or 0 for non-commit");
- print_decode_line(aData, 8, 4, 1, "Salt-1");
- print_decode_line(aData,12, 4, 1, "Salt-2");
- print_decode_line(aData,16, 4, 1, "Checksum-1");
- print_decode_line(aData,20, 4, 1, "Checksum-2");
- print_byte_range(iStart+24, pagesize, aData+24, 0);
- free(aData);
-}
-
-/*
-** Summarize a single frame on a single line.
-*/
-static void print_oneline_frame(int iFrame, Cksum *pCksum){
- int iStart;
- unsigned char *aData;
- unsigned int s0, s1;
- iStart = 32 + (iFrame-1)*(pagesize+24);
- aData = getContent(iStart, 24);
- extendCksum(pCksum, aData, 8, 0);
- extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0);
- s0 = getInt32(aData+16);
- s1 = getInt32(aData+20);
- fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n",
- iFrame,
- getInt32(aData),
- getInt32(aData+4),
- getInt32(aData+8),
- getInt32(aData+12),
- s0,
- s1,
- (s0==pCksum->s0 && s1==pCksum->s1) ? "" : "cksum-fail"
- );
-
- /* Reset the checksum so that a single frame checksum failure will not
- ** cause all subsequent frames to also show a failure. */
- pCksum->s0 = s0;
- pCksum->s1 = s1;
- free(aData);
-}
-
-/*
-** Decode the WAL header.
-*/
-static void print_wal_header(Cksum *pCksum){
- unsigned char *aData;
- aData = getContent(0, 32);
- if( pCksum ){
- extendCksum(pCksum, aData, 24, 1);
- printf("Checksum byte order: %s\n", pCksum->bSwap ? "swapped" : "native");
- }
- printf("WAL Header:\n");
- print_decode_line(aData, 0, 4,1,"Magic. 0x377f0682 (le) or 0x377f0683 (be)");
- print_decode_line(aData, 4, 4, 0, "File format");
- print_decode_line(aData, 8, 4, 0, "Database page size");
- print_decode_line(aData, 12,4, 0, "Checkpoint sequence number");
- print_decode_line(aData, 16,4, 1, "Salt-1");
- print_decode_line(aData, 20,4, 1, "Salt-2");
- print_decode_line(aData, 24,4, 1, "Checksum-1");
- print_decode_line(aData, 28,4, 1, "Checksum-2");
- if( pCksum ){
- if( pCksum->s0!=getInt32(aData+24) ){
- printf("**** cksum-1 mismatch: 0x%08x\n", pCksum->s0);
- }
- if( pCksum->s1!=getInt32(aData+28) ){
- printf("**** cksum-2 mismatch: 0x%08x\n", pCksum->s1);
- }
- }
- free(aData);
-}
-/*
-** Describe cell content.
-*/
-static i64 describeContent(
- unsigned char *a, /* Cell content */
- i64 nLocal, /* Bytes in a[] */
- char *zDesc /* Write description here */
-){
- int nDesc = 0;
- int n, j;
- i64 i, x, v;
- const unsigned char *pData;
- const unsigned char *pLimit;
- char sep = ' ';
-
- pLimit = &a[nLocal];
- n = decodeVarint(a, &x);
- pData = &a[x];
- a += n;
- i = x - n;
- while( i>0 && pData<=pLimit ){
- n = decodeVarint(a, &x);
- a += n;
- i -= n;
- nLocal -= n;
- zDesc[0] = sep;
- sep = ',';
- nDesc++;
- zDesc++;
- if( x==0 ){
- sprintf(zDesc, "*"); /* NULL is a "*" */
- }else if( x>=1 && x<=6 ){
- v = (signed char)pData[0];
- pData++;
- switch( x ){
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 4: v = (v<<8) + pData[0]; pData++;
- case 3: v = (v<<8) + pData[0]; pData++;
- case 2: v = (v<<8) + pData[0]; pData++;
- }
- sprintf(zDesc, "%lld", v);
- }else if( x==7 ){
- sprintf(zDesc, "real");
- pData += 8;
- }else if( x==8 ){
- sprintf(zDesc, "0");
- }else if( x==9 ){
- sprintf(zDesc, "1");
- }else if( x>=12 ){
- i64 size = (x-12)/2;
- if( (x&1)==0 ){
- sprintf(zDesc, "blob(%lld)", size);
- }else{
- sprintf(zDesc, "txt(%lld)", size);
- }
- pData += size;
- }
- j = (int)strlen(zDesc);
- zDesc += j;
- nDesc += j;
- }
- return nDesc;
-}
-
-/*
-** Compute the local payload size given the total payload size and
-** the page size.
-*/
-static i64 localPayload(i64 nPayload, char cType){
- i64 maxLocal;
- i64 minLocal;
- i64 surplus;
- i64 nLocal;
- if( cType==13 ){
- /* Table leaf */
- maxLocal = pagesize-35;
- minLocal = (pagesize-12)*32/255-23;
- }else{
- maxLocal = (pagesize-12)*64/255-23;
- minLocal = (pagesize-12)*32/255-23;
- }
- if( nPayload>maxLocal ){
- surplus = minLocal + (nPayload-minLocal)%(pagesize-4);
- if( surplus<=maxLocal ){
- nLocal = surplus;
- }else{
- nLocal = minLocal;
- }
- }else{
- nLocal = nPayload;
- }
- return nLocal;
-}
-
-/*
-** Create a description for a single cell.
-**
-** The return value is the local cell size.
-*/
-static i64 describeCell(
- unsigned char cType, /* Page type */
- unsigned char *a, /* Cell content */
- int showCellContent, /* Show cell content if true */
- char **pzDesc /* Store description here */
-){
- int i;
- i64 nDesc = 0;
- int n = 0;
- int leftChild;
- i64 nPayload;
- i64 rowid;
- i64 nLocal;
- static char zDesc[1000];
- i = 0;
- if( cType<=5 ){
- leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
- a += 4;
- n += 4;
- sprintf(zDesc, "lx: %d ", leftChild);
- nDesc = strlen(zDesc);
- }
- if( cType!=5 ){
- i = decodeVarint(a, &nPayload);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
- nDesc += strlen(&zDesc[nDesc]);
- nLocal = localPayload(nPayload, cType);
- }else{
- nPayload = nLocal = 0;
- }
- if( cType==5 || cType==13 ){
- i = decodeVarint(a, &rowid);
- a += i;
- n += i;
- sprintf(&zDesc[nDesc], "r: %lld ", rowid);
- nDesc += strlen(&zDesc[nDesc]);
- }
- if( nLocal<nPayload ){
- int ovfl;
- unsigned char *b = &a[nLocal];
- ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
- sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
- nDesc += strlen(&zDesc[nDesc]);
- n += 4;
- }
- if( showCellContent && cType!=5 ){
- nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
- }
- *pzDesc = zDesc;
- return nLocal+n;
-}
-
-/*
-** Decode a btree page
-*/
-static void decode_btree_page(
- unsigned char *a, /* Content of the btree page to be decoded */
- int pgno, /* Page number */
- int hdrSize, /* Size of the page1-header in bytes */
- const char *zArgs /* Flags to control formatting */
-){
- const char *zType = "unknown";
- int nCell;
- int i, j;
- int iCellPtr;
- int showCellContent = 0;
- int showMap = 0;
- char *zMap = 0;
- switch( a[0] ){
- case 2: zType = "index interior node"; break;
- case 5: zType = "table interior node"; break;
- case 10: zType = "index leaf"; break;
- case 13: zType = "table leaf"; break;
- }
- while( zArgs[0] ){
- switch( zArgs[0] ){
- case 'c': showCellContent = 1; break;
- case 'm': showMap = 1; break;
- }
- zArgs++;
- }
- printf("Decode of btree page %d:\n", pgno);
- print_decode_line(a, 0, 1, 0, zType);
- print_decode_line(a, 1, 2, 0, "Offset to first freeblock");
- print_decode_line(a, 3, 2, 0, "Number of cells on this page");
- nCell = a[3]*256 + a[4];
- print_decode_line(a, 5, 2, 0, "Offset to cell content area");
- print_decode_line(a, 7, 1, 0, "Fragmented byte count");
- if( a[0]==2 || a[0]==5 ){
- print_decode_line(a, 8, 4, 0, "Right child");
- iCellPtr = 12;
- }else{
- iCellPtr = 8;
- }
- if( nCell>0 ){
- printf(" key: lx=left-child n=payload-size r=rowid\n");
- }
- if( showMap ){
- zMap = malloc(pagesize);
- memset(zMap, '.', pagesize);
- memset(zMap, '1', hdrSize);
- memset(&zMap[hdrSize], 'H', iCellPtr);
- memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
- }
- for(i=0; i<nCell; i++){
- int cofst = iCellPtr + i*2;
- char *zDesc;
- i64 n;
-
- cofst = a[cofst]*256 + a[cofst+1];
- n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
- if( showMap ){
- char zBuf[30];
- memset(&zMap[cofst], '*', (size_t)n);
- zMap[cofst] = '[';
- zMap[cofst+n-1] = ']';
- sprintf(zBuf, "%d", i);
- j = (int)strlen(zBuf);
- if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
- }
- printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
- }
- if( showMap ){
- for(i=0; i<pagesize; i+=64){
- printf(" %03x: %.64s\n", i, &zMap[i]);
- }
- free(zMap);
- }
-}
-
-int main(int argc, char **argv){
- struct stat sbuf;
- unsigned char zPgSz[4];
- if( argc<2 ){
- fprintf(stderr,"Usage: %s FILENAME ?PAGE? ...\n", argv[0]);
- exit(1);
- }
- fd = open(argv[1], O_RDONLY);
- if( fd<0 ){
- fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
- exit(1);
- }
- zPgSz[0] = 0;
- zPgSz[1] = 0;
- lseek(fd, 8, SEEK_SET);
- read(fd, zPgSz, 4);
- pagesize = zPgSz[1]*65536 + zPgSz[2]*256 + zPgSz[3];
- if( pagesize==0 ) pagesize = 1024;
- printf("Pagesize: %d\n", pagesize);
- fstat(fd, &sbuf);
- if( sbuf.st_size<32 ){
- printf("file too small to be a WAL\n");
- return 0;
- }
- mxFrame = (sbuf.st_size - 32)/(pagesize + 24);
- printf("Available pages: 1..%d\n", mxFrame);
- if( argc==2 ){
- int i;
- Cksum x;
- print_wal_header(&x);
- for(i=1; i<=mxFrame; i++){
- print_oneline_frame(i, &x);
- }
- }else{
- int i;
- for(i=2; i<argc; i++){
- int iStart, iEnd;
- char *zLeft;
- if( strcmp(argv[i], "header")==0 ){
- print_wal_header(0);
- continue;
- }
- if( !isdigit(argv[i][0]) ){
- fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
- continue;
- }
- iStart = strtol(argv[i], &zLeft, 0);
- if( zLeft && strcmp(zLeft,"..end")==0 ){
- iEnd = mxFrame;
- }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
- iEnd = strtol(&zLeft[2], 0, 0);
- }else if( zLeft && zLeft[0]=='b' ){
- int ofst, nByte, hdrSize;
- unsigned char *a;
- if( iStart==1 ){
- hdrSize = 100;
- ofst = hdrSize = 100;
- nByte = pagesize-100;
- }else{
- hdrSize = 0;
- ofst = (iStart-1)*pagesize;
- nByte = pagesize;
- }
- ofst = 32 + hdrSize + (iStart-1)*(pagesize+24) + 24;
- a = getContent(ofst, nByte);
- decode_btree_page(a, iStart, hdrSize, zLeft+1);
- free(a);
- continue;
- }else{
- iEnd = iStart;
- }
- if( iStart<1 || iEnd<iStart || iEnd>mxFrame ){
- fprintf(stderr,
- "Page argument should be LOWER?..UPPER?. Range 1 to %d\n",
- mxFrame);
- exit(1);
- }
- while( iStart<=iEnd ){
- print_frame(iStart);
- iStart++;
- }
- }
- }
- close(fd);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/soak1.tcl b/lib/libsqlite3/tool/soak1.tcl
deleted file mode 100644
index 846f905935c..00000000000
--- a/lib/libsqlite3/tool/soak1.tcl
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Usage:
-#
-# tclsh soak1.tcl local-makefile.mk ?target? ?scenario?
-#
-# This generates many variations on local-makefile.mk (by modifing
-# the OPT = lines) and runs them will fulltest, one by one. The
-# constructed makefiles are named "soak1.mk".
-#
-# If ?target? is provided, that is the makefile target that is run.
-# The default is "fulltest"
-#
-# If ?scenario? is provided, it is the name of a single scenario to
-# be run. All other scenarios are skipped.
-#
-set localmake [lindex $argv 0]
-set target [lindex $argv 1]
-set scene [lindex $argv 2]
-if {$target==""} {set target fulltest}
-if {$scene==""} {set scene all}
-
-set in [open $localmake]
-set maketxt [read $in]
-close $in
-regsub -all {\\\n} $maketxt {} maketxt
-#set makefilename "soak1-[expr {int(rand()*1000000000)}].mk"
-set makefilename "soak1.mk"
-
-# Generate a makefile
-#
-proc generate_makefile {pattern} {
- global makefilename maketxt
- set out [open $makefilename w]
- set seen_opt 0
- foreach line [split $maketxt \n] {
- if {[regexp {^ *#? *OPTS[ =+]} $line]} {
- if {!$seen_opt} {
- puts $out "OPTS += -DSQLITE_NO_SYNC=1"
- foreach x $pattern {
- puts $out "OPTS += -D$x"
- }
- set seen_opt 1
- }
- } else {
- puts $out $line
- }
- }
- close $out
-}
-
-# Run a test
-#
-proc scenario {id title pattern} {
- global makefilename target scene
- if {$scene!="all" && $scene!=$id && $scene!=$title} return
- puts "**************** $title ***************"
- generate_makefile $pattern
- exec make -f $makefilename clean >@stdout 2>@stdout
- exec make -f $makefilename $target >@stdout 2>@stdout
-}
-
-###############################################################################
-# Add new scenarios here
-#
-scenario 0 {Default} {}
-scenario 1 {Debug} {
- SQLITE_DEBUG=1
- SQLITE_MEMDEBUG=1
-}
-scenario 2 {Everything} {
- SQLITE_DEBUG=1
- SQLITE_MEMDEBUG=1
- SQLITE_ENABLE_MEMORY_MANAGEMENT=1
- SQLITE_ENABLE_COLUMN_METADATA=1
- SQLITE_ENABLE_LOAD_EXTENSION=1 HAVE_DLOPEN=1
- SQLITE_ENABLE_MEMORY_MANAGEMENT=1
-}
-scenario 3 {Customer-1} {
- SQLITE_DEBUG=1 SQLITE_MEMDEBUG=1
- SQLITE_THREADSAFE=1 SQLITE_OS_UNIX=1
- SQLITE_DISABLE_LFS=1
- SQLITE_DEFAULT_AUTOVACUUM=1
- SQLITE_DEFAULT_PAGE_SIZE=1024
- SQLITE_MAX_PAGE_SIZE=4096
- SQLITE_DEFAULT_CACHE_SIZE=64
- SQLITE_DEFAULT_TEMP_CACHE_SIZE=32
- SQLITE_TEMP_STORE=3
- SQLITE_OMIT_PROGRESS_CALLBACK=1
- SQLITE_OMIT_LOAD_EXTENSION=1
- SQLITE_OMIT_VIRTUALTABLE=1
- SQLITE_ENABLE_IOTRACE=1
-}
-scenario 4 {Small-Cache} {
- SQLITE_DEBUG=1 SQLITE_MEMDEBUG=1
- SQLITE_THREADSAFE=1 SQLITE_OS_UNIX=1
- SQLITE_DEFAULT_AUTOVACUUM=1
- SQLITE_DEFAULT_PAGE_SIZE=1024
- SQLITE_MAX_PAGE_SIZE=2048
- SQLITE_DEFAULT_CACHE_SIZE=13
- SQLITE_DEFAULT_TEMP_CACHE_SIZE=11
- SQLITE_TEMP_STORE=1
-}
diff --git a/lib/libsqlite3/tool/space_used.tcl b/lib/libsqlite3/tool/space_used.tcl
deleted file mode 100644
index 2044aa38c5e..00000000000
--- a/lib/libsqlite3/tool/space_used.tcl
+++ /dev/null
@@ -1,111 +0,0 @@
-# Run this TCL script using "testfixture" in order get a report that shows
-# how much disk space is used by a particular data to actually store data
-# versus how much space is unused.
-#
-
-# Get the name of the database to analyze
-#
-if {[llength $argv]!=1} {
- puts stderr "Usage: $argv0 database-name"
- exit 1
-}
-set file_to_analyze [lindex $argv 0]
-
-# Open the database
-#
-sqlite db [lindex $argv 0]
-set DB [btree_open [lindex $argv 0]]
-
-# Output the schema for the generated report
-#
-puts \
-{BEGIN;
-CREATE TABLE space_used(
- name clob, -- Name of a table or index in the database file
- is_index boolean, -- TRUE if it is an index, false for a table
- payload int, -- Total amount of data stored in this table or index
- pri_pages int, -- Number of primary pages used
- ovfl_pages int, -- Number of overflow pages used
- pri_unused int, -- Number of unused bytes on primary pages
- ovfl_unused int -- Number of unused bytes on overflow pages
-);}
-
-# This query will be used to find the root page number for every index and
-# table in the database.
-#
-set sql {
- SELECT name, type, rootpage FROM sqlite_master
- UNION ALL
- SELECT 'sqlite_master', 'table', 2
- ORDER BY 1
-}
-
-# Initialize variables used for summary statistics.
-#
-set total_size 0
-set total_primary 0
-set total_overflow 0
-set total_unused_primary 0
-set total_unused_ovfl 0
-
-# Analyze every table in the database, one at a time.
-#
-foreach {name type rootpage} [db eval $sql] {
- set cursor [btree_cursor $DB $rootpage 0]
- set go [btree_first $cursor]
- set size 0
- catch {unset pg_used}
- set unused_ovfl 0
- set n_overflow 0
- while {$go==0} {
- set payload [btree_payload_size $cursor]
- incr size $payload
- set stat [btree_cursor_dump $cursor]
- set pgno [lindex $stat 0]
- set freebytes [lindex $stat 4]
- set pg_used($pgno) $freebytes
- if {$payload>238} {
- set n [expr {($payload-238+1019)/1020}]
- incr n_overflow $n
- incr unused_ovfl [expr {$n*1020+238-$payload}]
- }
- set go [btree_next $cursor]
- }
- btree_close_cursor $cursor
- set n_primary [llength [array names pg_used]]
- set unused_primary 0
- foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
- regsub -all ' $name '' name
- puts -nonewline "INSERT INTO space_used VALUES('$name'"
- puts -nonewline ",[expr {$type=="index"}]"
- puts ",$size,$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
- incr total_size $size
- incr total_primary $n_primary
- incr total_overflow $n_overflow
- incr total_unused_primary $unused_primary
- incr total_unused_ovfl $unused_ovfl
-}
-
-# Output summary statistics:
-#
-puts "-- Total payload size: $total_size"
-puts "-- Total pages used: $total_primary primary and $total_overflow overflow"
-set file_pgcnt [expr {[file size [lindex $argv 0]]/1024}]
-puts -nonewline "-- Total unused bytes on primary pages: $total_unused_primary"
-if {$total_primary>0} {
- set upp [expr {$total_unused_primary/$total_primary}]
- puts " (avg $upp bytes/page)"
-} else {
- puts ""
-}
-puts -nonewline "-- Total unused bytes on overflow pages: $total_unused_ovfl"
-if {$total_overflow>0} {
- set upp [expr {$total_unused_ovfl/$total_overflow}]
- puts " (avg $upp bytes/page)"
-} else {
- puts ""
-}
-set n_free [expr {$file_pgcnt-$total_primary-$total_overflow}]
-if {$n_free>0} {incr n_free -1}
-puts "-- Total pages on freelist: $n_free"
-puts "COMMIT;"
diff --git a/lib/libsqlite3/tool/spaceanal.tcl b/lib/libsqlite3/tool/spaceanal.tcl
deleted file mode 100644
index 38d954162e4..00000000000
--- a/lib/libsqlite3/tool/spaceanal.tcl
+++ /dev/null
@@ -1,805 +0,0 @@
-# Run this TCL script using "testfixture" in order get a report that shows
-# how much disk space is used by a particular data to actually store data
-# versus how much space is unused.
-#
-
-if {[catch {
-
-# Argument $tname is the name of a table within the database opened by
-# database handle [db]. Return true if it is a WITHOUT ROWID table, or
-# false otherwise.
-#
-proc is_without_rowid {tname} {
- set t [string map {' ''} $tname]
- db eval "PRAGMA index_list = '$t'" o {
- if {$o(origin) == "pk"} {
- set n $o(name)
- if {0==[db one { SELECT count(*) FROM sqlite_master WHERE name=$n }]} {
- return 1
- }
- }
- }
- return 0
-}
-
-# Get the name of the database to analyze
-#
-proc usage {} {
- set argv0 [file rootname [file tail [info nameofexecutable]]]
- puts stderr "Usage: $argv0 ?--pageinfo? ?--stats? database-filename"
- puts stderr {
-Analyze the SQLite3 database file specified by the "database-filename"
-argument and output a report detailing size and storage efficiency
-information for the database and its constituent tables and indexes.
-
-Options:
-
- --stats Output SQL text that creates a new database containing
- statistics about the database that was analyzed
-
- --pageinfo Show how each page of the database-file is used
-}
- exit 1
-}
-set file_to_analyze {}
-set flags(-pageinfo) 0
-set flags(-stats) 0
-append argv {}
-foreach arg $argv {
- if {[regexp {^-+pageinfo$} $arg]} {
- set flags(-pageinfo) 1
- } elseif {[regexp {^-+stats$} $arg]} {
- set flags(-stats) 1
- } elseif {[regexp {^-} $arg]} {
- puts stderr "Unknown option: $arg"
- usage
- } elseif {$file_to_analyze!=""} {
- usage
- } else {
- set file_to_analyze $arg
- }
-}
-if {$file_to_analyze==""} usage
-set root_filename $file_to_analyze
-regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
-if {![file exists $root_filename]} {
- puts stderr "No such file: $root_filename"
- exit 1
-}
-if {![file readable $root_filename]} {
- puts stderr "File is not readable: $root_filename"
- exit 1
-}
-set true_file_size [file size $root_filename]
-if {$true_file_size<512} {
- puts stderr "Empty or malformed database: $root_filename"
- exit 1
-}
-
-# Compute the total file size assuming test_multiplexor is being used.
-# Assume that SQLITE_ENABLE_8_3_NAMES might be enabled
-#
-set extension [file extension $root_filename]
-set pattern $root_filename
-append pattern {[0-3][0-9][0-9]}
-foreach f [glob -nocomplain $pattern] {
- incr true_file_size [file size $f]
- set extension {}
-}
-if {[string length $extension]>=2 && [string length $extension]<=4} {
- set pattern [file rootname $root_filename]
- append pattern {.[0-3][0-9][0-9]}
- foreach f [glob -nocomplain $pattern] {
- incr true_file_size [file size $f]
- }
-}
-
-# Open the database
-#
-if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} {
- puts stderr "error trying to open $file_to_analyze: $msg"
- exit 1
-}
-
-db eval {SELECT count(*) FROM sqlite_master}
-set pageSize [expr {wide([db one {PRAGMA page_size}])}]
-
-if {$flags(-pageinfo)} {
- db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
- db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {
- puts "$pageno $name $path"
- }
- exit 0
-}
-if {$flags(-stats)} {
- db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
- puts "BEGIN;"
- puts "CREATE TABLE stats("
- puts " name STRING, /* Name of table or index */"
- puts " path INTEGER, /* Path to page from root */"
- puts " pageno INTEGER, /* Page number */"
- puts " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */"
- puts " ncell INTEGER, /* Cells on page (0 for overflow) */"
- puts " payload INTEGER, /* Bytes of payload on this page */"
- puts " unused INTEGER, /* Bytes of unused space on this page */"
- puts " mx_payload INTEGER, /* Largest payload size of all cells */"
- puts " pgoffset INTEGER, /* Offset of page in file */"
- puts " pgsize INTEGER /* Size of the page */"
- puts ");"
- db eval {SELECT quote(name) || ',' ||
- quote(path) || ',' ||
- quote(pageno) || ',' ||
- quote(pagetype) || ',' ||
- quote(ncell) || ',' ||
- quote(payload) || ',' ||
- quote(unused) || ',' ||
- quote(mx_payload) || ',' ||
- quote(pgoffset) || ',' ||
- quote(pgsize) AS x FROM stat} {
- puts "INSERT INTO stats VALUES($x);"
- }
- puts "COMMIT;"
- exit 0
-}
-
-# In-memory database for collecting statistics. This script loops through
-# the tables and indices in the database being analyzed, adding a row for each
-# to an in-memory database (for which the schema is shown below). It then
-# queries the in-memory db to produce the space-analysis report.
-#
-sqlite3 mem :memory:
-set tabledef {CREATE TABLE space_used(
- name clob, -- Name of a table or index in the database file
- tblname clob, -- Name of associated table
- is_index boolean, -- TRUE if it is an index, false for a table
- nentry int, -- Number of entries in the BTree
- leaf_entries int, -- Number of leaf entries
- depth int, -- Depth of the b-tree
- payload int, -- Total amount of data stored in this table or index
- ovfl_payload int, -- Total amount of data stored on overflow pages
- ovfl_cnt int, -- Number of entries that use overflow
- mx_payload int, -- Maximum payload size
- int_pages int, -- Number of interior pages used
- leaf_pages int, -- Number of leaf pages used
- ovfl_pages int, -- Number of overflow pages used
- int_unused int, -- Number of unused bytes on interior pages
- leaf_unused int, -- Number of unused bytes on primary pages
- ovfl_unused int, -- Number of unused bytes on overflow pages
- gap_cnt int, -- Number of gaps in the page layout
- compressed_size int -- Total bytes stored on disk
-);}
-mem eval $tabledef
-
-# Create a temporary "dbstat" virtual table.
-#
-db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
-db eval {CREATE TEMP TABLE dbstat AS SELECT * FROM temp.stat
- ORDER BY name, path}
-db eval {DROP TABLE temp.stat}
-
-set isCompressed 0
-set compressOverhead 0
-set depth 0
-set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 }
-foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
-
- set is_index [expr {$name!=$tblname}]
- set idx_btree [expr {$is_index || [is_without_rowid $name]}]
- db eval {
- SELECT
- sum(ncell) AS nentry,
- sum((pagetype=='leaf')*ncell) AS leaf_entries,
- sum(payload) AS payload,
- sum((pagetype=='overflow') * payload) AS ovfl_payload,
- sum(path LIKE '%+000000') AS ovfl_cnt,
- max(mx_payload) AS mx_payload,
- sum(pagetype=='internal') AS int_pages,
- sum(pagetype=='leaf') AS leaf_pages,
- sum(pagetype=='overflow') AS ovfl_pages,
- sum((pagetype=='internal') * unused) AS int_unused,
- sum((pagetype=='leaf') * unused) AS leaf_unused,
- sum((pagetype=='overflow') * unused) AS ovfl_unused,
- sum(pgsize) AS compressed_size,
- max((length(CASE WHEN path LIKE '%+%' THEN '' ELSE path END)+3)/4)
- AS depth
- FROM temp.dbstat WHERE name = $name
- } break
-
- set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
- set storage [expr {$total_pages*$pageSize}]
- if {!$isCompressed && $storage>$compressed_size} {
- set isCompressed 1
- set compressOverhead 14
- }
-
- # Column 'gap_cnt' is set to the number of non-contiguous entries in the
- # list of pages visited if the b-tree structure is traversed in a top-down
- # fashion (each node visited before its child-tree is passed). Any overflow
- # chains present are traversed from start to finish before any child-tree
- # is.
- #
- set gap_cnt 0
- set prev 0
- db eval {
- SELECT pageno, pagetype FROM temp.dbstat
- WHERE name=$name
- ORDER BY pageno
- } {
- if {$prev>0 && $pagetype=="leaf" && $pageno!=$prev+1} {
- incr gap_cnt
- }
- set prev $pageno
- }
- mem eval {
- INSERT INTO space_used VALUES(
- $name,
- $tblname,
- $is_index,
- $nentry,
- $leaf_entries,
- $depth,
- $payload,
- $ovfl_payload,
- $ovfl_cnt,
- $mx_payload,
- $int_pages,
- $leaf_pages,
- $ovfl_pages,
- $int_unused,
- $leaf_unused,
- $ovfl_unused,
- $gap_cnt,
- $compressed_size
- );
- }
-}
-
-proc integerify {real} {
- if {[string is double -strict $real]} {
- return [expr {wide($real)}]
- } else {
- return 0
- }
-}
-mem function int integerify
-
-# Quote a string for use in an SQL query. Examples:
-#
-# [quote {hello world}] == {'hello world'}
-# [quote {hello world's}] == {'hello world''s'}
-#
-proc quote {txt} {
- return [string map {' ''} $txt]
-}
-
-# Output a title line
-#
-proc titleline {title} {
- if {$title==""} {
- puts [string repeat * 79]
- } else {
- set len [string length $title]
- set stars [string repeat * [expr 79-$len-5]]
- puts "*** $title $stars"
- }
-}
-
-# Generate a single line of output in the statistics section of the
-# report.
-#
-proc statline {title value {extra {}}} {
- set len [string length $title]
- set dots [string repeat . [expr 50-$len]]
- set len [string length $value]
- set sp2 [string range { } $len end]
- if {$extra ne ""} {
- set extra " $extra"
- }
- puts "$title$dots $value$sp2$extra"
-}
-
-# Generate a formatted percentage value for $num/$denom
-#
-proc percent {num denom {of {}}} {
- if {$denom==0.0} {return ""}
- set v [expr {$num*100.0/$denom}]
- set of {}
- if {$v==100.0 || $v<0.001 || ($v>1.0 && $v<99.0)} {
- return [format {%5.1f%% %s} $v $of]
- } elseif {$v<0.1 || $v>99.9} {
- return [format {%7.3f%% %s} $v $of]
- } else {
- return [format {%6.2f%% %s} $v $of]
- }
-}
-
-proc divide {num denom} {
- if {$denom==0} {return 0.0}
- return [format %.2f [expr double($num)/double($denom)]]
-}
-
-# Generate a subreport that covers some subset of the database.
-# the $where clause determines which subset to analyze.
-#
-proc subreport {title where showFrag} {
- global pageSize file_pgcnt compressOverhead
-
- # Query the in-memory database for the sum of various statistics
- # for the subset of tables/indices identified by the WHERE clause in
- # $where. Note that even if the WHERE clause matches no rows, the
- # following query returns exactly one row (because it is an aggregate).
- #
- # The results of the query are stored directly by SQLite into local
- # variables (i.e. $nentry, $nleaf etc.).
- #
- mem eval "
- SELECT
- int(sum(nentry)) AS nentry,
- int(sum(leaf_entries)) AS nleaf,
- int(sum(payload)) AS payload,
- int(sum(ovfl_payload)) AS ovfl_payload,
- max(mx_payload) AS mx_payload,
- int(sum(ovfl_cnt)) as ovfl_cnt,
- int(sum(leaf_pages)) AS leaf_pages,
- int(sum(int_pages)) AS int_pages,
- int(sum(ovfl_pages)) AS ovfl_pages,
- int(sum(leaf_unused)) AS leaf_unused,
- int(sum(int_unused)) AS int_unused,
- int(sum(ovfl_unused)) AS ovfl_unused,
- int(sum(gap_cnt)) AS gap_cnt,
- int(sum(compressed_size)) AS compressed_size,
- int(max(depth)) AS depth,
- count(*) AS cnt
- FROM space_used WHERE $where" {} {}
-
- # Output the sub-report title, nicely decorated with * characters.
- #
- puts ""
- titleline $title
- puts ""
-
- # Calculate statistics and store the results in TCL variables, as follows:
- #
- # total_pages: Database pages consumed.
- # total_pages_percent: Pages consumed as a percentage of the file.
- # storage: Bytes consumed.
- # payload_percent: Payload bytes used as a percentage of $storage.
- # total_unused: Unused bytes on pages.
- # avg_payload: Average payload per btree entry.
- # avg_fanout: Average fanout for internal pages.
- # avg_unused: Average unused bytes per btree entry.
- # ovfl_cnt_percent: Percentage of btree entries that use overflow pages.
- #
- set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
- set total_pages_percent [percent $total_pages $file_pgcnt]
- set storage [expr {$total_pages*$pageSize}]
- set payload_percent [percent $payload $storage {of storage consumed}]
- set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
- set avg_payload [divide $payload $nleaf]
- set avg_unused [divide $total_unused $nleaf]
- if {$int_pages>0} {
- # TODO: Is this formula correct?
- set nTab [mem eval "
- SELECT count(*) FROM (
- SELECT DISTINCT tblname FROM space_used WHERE $where AND is_index=0
- )
- "]
- set avg_fanout [mem eval "
- SELECT (sum(leaf_pages+int_pages)-$nTab)/sum(int_pages) FROM space_used
- WHERE $where
- "]
- set avg_fanout [format %.2f $avg_fanout]
- }
- set ovfl_cnt_percent [percent $ovfl_cnt $nleaf {of all entries}]
-
- # Print out the sub-report statistics.
- #
- statline {Percentage of total database} $total_pages_percent
- statline {Number of entries} $nleaf
- statline {Bytes of storage consumed} $storage
- if {$compressed_size!=$storage} {
- set compressed_size [expr {$compressed_size+$compressOverhead*$total_pages}]
- set pct [expr {$compressed_size*100.0/$storage}]
- set pct [format {%5.1f%%} $pct]
- statline {Bytes used after compression} $compressed_size $pct
- }
- statline {Bytes of payload} $payload $payload_percent
- if {$cnt==1} {statline {B-tree depth} $depth}
- statline {Average payload per entry} $avg_payload
- statline {Average unused bytes per entry} $avg_unused
- if {[info exists avg_fanout]} {
- statline {Average fanout} $avg_fanout
- }
- if {$showFrag && $total_pages>1} {
- set fragmentation [percent $gap_cnt [expr {$total_pages-1}]]
- statline {Non-sequential pages} $gap_cnt $fragmentation
- }
- statline {Maximum payload per entry} $mx_payload
- statline {Entries that use overflow} $ovfl_cnt $ovfl_cnt_percent
- if {$int_pages>0} {
- statline {Index pages used} $int_pages
- }
- statline {Primary pages used} $leaf_pages
- statline {Overflow pages used} $ovfl_pages
- statline {Total pages used} $total_pages
- if {$int_unused>0} {
- set int_unused_percent [
- percent $int_unused [expr {$int_pages*$pageSize}] {of index space}]
- statline "Unused bytes on index pages" $int_unused $int_unused_percent
- }
- statline "Unused bytes on primary pages" $leaf_unused [
- percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}]
- statline "Unused bytes on overflow pages" $ovfl_unused [
- percent $ovfl_unused [expr {$ovfl_pages*$pageSize}] {of overflow space}]
- statline "Unused bytes on all pages" $total_unused [
- percent $total_unused $storage {of all space}]
- return 1
-}
-
-# Calculate the overhead in pages caused by auto-vacuum.
-#
-# This procedure calculates and returns the number of pages used by the
-# auto-vacuum 'pointer-map'. If the database does not support auto-vacuum,
-# then 0 is returned. The two arguments are the size of the database file in
-# pages and the page size used by the database (in bytes).
-proc autovacuum_overhead {filePages pageSize} {
-
- # Set $autovacuum to non-zero for databases that support auto-vacuum.
- set autovacuum [db one {PRAGMA auto_vacuum}]
-
- # If the database is not an auto-vacuum database or the file consists
- # of one page only then there is no overhead for auto-vacuum. Return zero.
- if {0==$autovacuum || $filePages==1} {
- return 0
- }
-
- # The number of entries on each pointer map page. The layout of the
- # database file is one pointer-map page, followed by $ptrsPerPage other
- # pages, followed by a pointer-map page etc. The first pointer-map page
- # is the second page of the file overall.
- set ptrsPerPage [expr double($pageSize/5)]
-
- # Return the number of pointer map pages in the database.
- return [expr wide(ceil( ($filePages-1.0)/($ptrsPerPage+1.0) ))]
-}
-
-
-# Calculate the summary statistics for the database and store the results
-# in TCL variables. They are output below. Variables are as follows:
-#
-# pageSize: Size of each page in bytes.
-# file_bytes: File size in bytes.
-# file_pgcnt: Number of pages in the file.
-# file_pgcnt2: Number of pages in the file (calculated).
-# av_pgcnt: Pages consumed by the auto-vacuum pointer-map.
-# av_percent: Percentage of the file consumed by auto-vacuum pointer-map.
-# inuse_pgcnt: Data pages in the file.
-# inuse_percent: Percentage of pages used to store data.
-# free_pgcnt: Free pages calculated as (<total pages> - <in-use pages>)
-# free_pgcnt2: Free pages in the file according to the file header.
-# free_percent: Percentage of file consumed by free pages (calculated).
-# free_percent2: Percentage of file consumed by free pages (header).
-# ntable: Number of tables in the db.
-# nindex: Number of indices in the db.
-# nautoindex: Number of indices created automatically.
-# nmanindex: Number of indices created manually.
-# user_payload: Number of bytes of payload in table btrees
-# (not including sqlite_master)
-# user_percent: $user_payload as a percentage of total file size.
-
-### The following, setting $file_bytes based on the actual size of the file
-### on disk, causes this tool to choke on zipvfs databases. So set it based
-### on the return of [PRAGMA page_count] instead.
-if 0 {
- set file_bytes [file size $file_to_analyze]
- set file_pgcnt [expr {$file_bytes/$pageSize}]
-}
-set file_pgcnt [db one {PRAGMA page_count}]
-set file_bytes [expr {$file_pgcnt * $pageSize}]
-
-set av_pgcnt [autovacuum_overhead $file_pgcnt $pageSize]
-set av_percent [percent $av_pgcnt $file_pgcnt]
-
-set sql {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}
-set inuse_pgcnt [expr wide([mem eval $sql])]
-set inuse_percent [percent $inuse_pgcnt $file_pgcnt]
-
-set free_pgcnt [expr {$file_pgcnt-$inuse_pgcnt-$av_pgcnt}]
-set free_percent [percent $free_pgcnt $file_pgcnt]
-set free_pgcnt2 [db one {PRAGMA freelist_count}]
-set free_percent2 [percent $free_pgcnt2 $file_pgcnt]
-
-set file_pgcnt2 [expr {$inuse_pgcnt+$free_pgcnt2+$av_pgcnt}]
-
-set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
-set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
-set sql {SELECT count(*) FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
-set nautoindex [db eval $sql]
-set nmanindex [expr {$nindex-$nautoindex}]
-
-# set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
-set user_payload [mem one {SELECT int(sum(payload)) FROM space_used
- WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
-set user_percent [percent $user_payload $file_bytes]
-
-# Output the summary statistics calculated above.
-#
-puts "/** Disk-Space Utilization Report For $root_filename"
-puts ""
-statline {Page size in bytes} $pageSize
-statline {Pages in the whole file (measured)} $file_pgcnt
-statline {Pages in the whole file (calculated)} $file_pgcnt2
-statline {Pages that store data} $inuse_pgcnt $inuse_percent
-statline {Pages on the freelist (per header)} $free_pgcnt2 $free_percent2
-statline {Pages on the freelist (calculated)} $free_pgcnt $free_percent
-statline {Pages of auto-vacuum overhead} $av_pgcnt $av_percent
-statline {Number of tables in the database} $ntable
-statline {Number of indices} $nindex
-statline {Number of defined indices} $nmanindex
-statline {Number of implied indices} $nautoindex
-if {$isCompressed} {
- statline {Size of uncompressed content in bytes} $file_bytes
- set efficiency [percent $true_file_size $file_bytes]
- statline {Size of compressed file on disk} $true_file_size $efficiency
-} else {
- statline {Size of the file in bytes} $file_bytes
-}
-statline {Bytes of user payload stored} $user_payload $user_percent
-
-# Output table rankings
-#
-puts ""
-titleline "Page counts for all tables with their indices"
-puts ""
-mem eval {SELECT tblname, count(*) AS cnt,
- int(sum(int_pages+leaf_pages+ovfl_pages)) AS size
- FROM space_used GROUP BY tblname ORDER BY size+0 DESC, tblname} {} {
- statline [string toupper $tblname] $size [percent $size $file_pgcnt]
-}
-puts ""
-titleline "Page counts for all tables and indices separately"
-puts ""
-mem eval {
- SELECT
- upper(name) AS nm,
- int(int_pages+leaf_pages+ovfl_pages) AS size
- FROM space_used
- ORDER BY size+0 DESC, name} {} {
- statline $nm $size [percent $size $file_pgcnt]
-}
-if {$isCompressed} {
- puts ""
- titleline "Bytes of disk space used after compression"
- puts ""
- set csum 0
- mem eval {SELECT tblname,
- int(sum(compressed_size)) +
- $compressOverhead*sum(int_pages+leaf_pages+ovfl_pages)
- AS csize
- FROM space_used GROUP BY tblname ORDER BY csize+0 DESC, tblname} {} {
- incr csum $csize
- statline [string toupper $tblname] $csize [percent $csize $true_file_size]
- }
- set overhead [expr {$true_file_size - $csum}]
- if {$overhead>0} {
- statline {Header and free space} $overhead [percent $overhead $true_file_size]
- }
-}
-
-# Output subreports
-#
-if {$nindex>0} {
- subreport {All tables and indices} 1 0
-}
-subreport {All tables} {NOT is_index} 0
-if {$nindex>0} {
- subreport {All indices} {is_index} 0
-}
-foreach tbl [mem eval {SELECT DISTINCT tblname name FROM space_used
- ORDER BY name}] {
- set qn [quote $tbl]
- set name [string toupper $tbl]
- set n [mem eval {SELECT count(*) FROM space_used WHERE tblname=$tbl}]
- if {$n>1} {
- set idxlist [mem eval "SELECT name FROM space_used
- WHERE tblname='$qn' AND is_index
- ORDER BY 1"]
- subreport "Table $name and all its indices" "tblname='$qn'" 0
- subreport "Table $name w/o any indices" "name='$qn'" 1
- if {[llength $idxlist]>1} {
- subreport "Indices of table $name" "tblname='$qn' AND is_index" 0
- }
- foreach idx $idxlist {
- set qidx [quote $idx]
- subreport "Index [string toupper $idx] of table $name" "name='$qidx'" 1
- }
- } else {
- subreport "Table $name" "name='$qn'" 1
- }
-}
-
-# Output instructions on what the numbers above mean.
-#
-puts ""
-titleline Definitions
-puts {
-Page size in bytes
-
- The number of bytes in a single page of the database file.
- Usually 1024.
-
-Number of pages in the whole file
-}
-puts " The number of $pageSize-byte pages that go into forming the complete
- database"
-puts {
-Pages that store data
-
- The number of pages that store data, either as primary B*Tree pages or
- as overflow pages. The number at the right is the data pages divided by
- the total number of pages in the file.
-
-Pages on the freelist
-
- The number of pages that are not currently in use but are reserved for
- future use. The percentage at the right is the number of freelist pages
- divided by the total number of pages in the file.
-
-Pages of auto-vacuum overhead
-
- The number of pages that store data used by the database to facilitate
- auto-vacuum. This is zero for databases that do not support auto-vacuum.
-
-Number of tables in the database
-
- The number of tables in the database, including the SQLITE_MASTER table
- used to store schema information.
-
-Number of indices
-
- The total number of indices in the database.
-
-Number of defined indices
-
- The number of indices created using an explicit CREATE INDEX statement.
-
-Number of implied indices
-
- The number of indices used to implement PRIMARY KEY or UNIQUE constraints
- on tables.
-
-Size of the file in bytes
-
- The total amount of disk space used by the entire database files.
-
-Bytes of user payload stored
-
- The total number of bytes of user payload stored in the database. The
- schema information in the SQLITE_MASTER table is not counted when
- computing this number. The percentage at the right shows the payload
- divided by the total file size.
-
-Percentage of total database
-
- The amount of the complete database file that is devoted to storing
- information described by this category.
-
-Number of entries
-
- The total number of B-Tree key/value pairs stored under this category.
-
-Bytes of storage consumed
-
- The total amount of disk space required to store all B-Tree entries
- under this category. The is the total number of pages used times
- the pages size.
-
-Bytes of payload
-
- The amount of payload stored under this category. Payload is the data
- part of table entries and the key part of index entries. The percentage
- at the right is the bytes of payload divided by the bytes of storage
- consumed.
-
-Average payload per entry
-
- The average amount of payload on each entry. This is just the bytes of
- payload divided by the number of entries.
-
-Average unused bytes per entry
-
- The average amount of free space remaining on all pages under this
- category on a per-entry basis. This is the number of unused bytes on
- all pages divided by the number of entries.
-
-Non-sequential pages
-
- The number of pages in the table or index that are out of sequence.
- Many filesystems are optimized for sequential file access so a small
- number of non-sequential pages might result in faster queries,
- especially for larger database files that do not fit in the disk cache.
- Note that after running VACUUM, the root page of each table or index is
- at the beginning of the database file and all other pages are in a
- separate part of the database file, resulting in a single non-
- sequential page.
-
-Maximum payload per entry
-
- The largest payload size of any entry.
-
-Entries that use overflow
-
- The number of entries that user one or more overflow pages.
-
-Total pages used
-
- This is the number of pages used to hold all information in the current
- category. This is the sum of index, primary, and overflow pages.
-
-Index pages used
-
- This is the number of pages in a table B-tree that hold only key (rowid)
- information and no data.
-
-Primary pages used
-
- This is the number of B-tree pages that hold both key and data.
-
-Overflow pages used
-
- The total number of overflow pages used for this category.
-
-Unused bytes on index pages
-
- The total number of bytes of unused space on all index pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on index pages.
-
-Unused bytes on primary pages
-
- The total number of bytes of unused space on all primary pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on primary pages.
-
-Unused bytes on overflow pages
-
- The total number of bytes of unused space on all overflow pages. The
- percentage at the right is the number of unused bytes divided by the
- total number of bytes on overflow pages.
-
-Unused bytes on all pages
-
- The total number of bytes of unused space on all primary and overflow
- pages. The percentage at the right is the number of unused bytes
- divided by the total number of bytes.
-}
-
-# Output a dump of the in-memory database. This can be used for more
-# complex offline analysis.
-#
-titleline {}
-puts "The entire text of this report can be sourced into any SQL database"
-puts "engine for further analysis. All of the text above is an SQL comment."
-puts "The data used to generate this report follows:"
-puts "*/"
-puts "BEGIN;"
-puts $tabledef
-unset -nocomplain x
-mem eval {SELECT * FROM space_used} x {
- puts -nonewline "INSERT INTO space_used VALUES"
- set sep (
- foreach col $x(*) {
- set v $x($col)
- if {$v=="" || ![string is double $v]} {set v '[quote $v]'}
- puts -nonewline $sep$v
- set sep ,
- }
- puts ");"
-}
-puts "COMMIT;"
-
-} err]} {
- puts "ERROR: $err"
- puts $errorInfo
- exit 1
-}
diff --git a/lib/libsqlite3/tool/speedtest.tcl b/lib/libsqlite3/tool/speedtest.tcl
deleted file mode 100644
index ef39dc5461d..00000000000
--- a/lib/libsqlite3/tool/speedtest.tcl
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script using TCLSH to do a speed comparison between
-# various versions of SQLite and PostgreSQL and MySQL
-#
-
-# Run a test
-#
-set cnt 1
-proc runtest {title} {
- global cnt
- set sqlfile test$cnt.sql
- puts "<h2>Test $cnt: $title</h2>"
- incr cnt
- set fd [open $sqlfile r]
- set sql [string trim [read $fd [file size $sqlfile]]]
- close $fd
- set sx [split $sql \n]
- set n [llength $sx]
- if {$n>8} {
- set sql {}
- for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n}
- append sql "<i>... [expr {$n-6}] lines omitted</i><br>\n"
- for {set i [expr {$n-3}]} {$i<$n} {incr i} {
- append sql [lindex $sx $i]<br>\n
- }
- } else {
- regsub -all \n [string trim $sql] <br> sql
- }
- puts "<blockquote>"
- puts "$sql"
- puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>"
- set format {<tr><td>%s</td><td align="right">&nbsp;&nbsp;&nbsp;%.3f</td></tr>}
- set delay 1000
-# exec sync; after $delay;
-# set t [time "exec psql drh <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format PostgreSQL: $t]
- exec sync; after $delay;
- set t [time "exec mysql -f drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format MySQL: $t]
-# set t [time "exec ./sqlite232 s232.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.3.2:} $t]
-# set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (cache=100):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite248 s2k.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.8:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite248 sns.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.8 (nosync):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite2412 s2kb.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.12:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite2412 snsb.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4.12 (nosync):} $t]
-# set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (test):} $t]
- puts "</table>"
-}
-
-# Initialize the environment
-#
-expr srand(1)
-catch {exec /bin/sh -c {rm -f s*.db}}
-set fd [open clear.sql w]
-puts $fd {
- drop table t1;
- drop table t2;
-}
-close $fd
-catch {exec psql drh <clear.sql}
-catch {exec mysql drh <clear.sql}
-set fd [open 2kinit.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=on;
-}
-close $fd
-exec ./sqlite248 s2k.db <2kinit.sql
-exec ./sqlite2412 s2kb.db <2kinit.sql
-set fd [open nosync-init.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=off;
-}
-close $fd
-exec ./sqlite248 sns.db <nosync-init.sql
-exec ./sqlite2412 snsb.db <nosync-init.sql
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=1000} {incr i} {
- set r [expr {int(rand()*100000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-close $fd
-runtest {1000 INSERTs}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 0} {$i<100} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+10)*100}]
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;"
-}
-close $fd
-runtest {100 SELECTs without an index}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 1} {$i<=100} {incr i} {
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%[number_name $i]%';"
-}
-close $fd
-runtest {100 SELECTs on a string comparison}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {CREATE INDEX i2a ON t2(a);}
-puts $fd {CREATE INDEX i2b ON t2(b);}
-close $fd
-runtest {Creating an index}
-
-
-
-set fd [open test$cnt.sql w]
-for {set i 0} {$i<5000} {incr i} {
- set lwr [expr {$i*100}]
- set upr [expr {($i+1)*100}]
- puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;"
-}
-close $fd
-runtest {5000 SELECTs with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 0} {$i<1000} {incr i} {
- set lwr [expr {$i*10}]
- set upr [expr {($i+1)*10}]
- puts $fd "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {1000 UPDATEs without an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "UPDATE t2 SET b=$r WHERE a=$i;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 UPDATEs with an index}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "UPDATE t2 SET c='[number_name $r]' WHERE a=$i;"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 text UPDATEs with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "INSERT INTO t1 SELECT * FROM t2;"
-puts $fd "INSERT INTO t2 SELECT * FROM t1;"
-puts $fd "COMMIT;"
-close $fd
-runtest {INSERTs from a SELECT}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DELETE FROM t2 WHERE c LIKE '%fifty%';}
-close $fd
-runtest {DELETE without an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DELETE FROM t2 WHERE a>10 AND a<20000;}
-close $fd
-runtest {DELETE with an index}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {INSERT INTO t2 SELECT * FROM t1;}
-close $fd
-runtest {A big INSERT after a big DELETE}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {BEGIN;}
-puts $fd {DELETE FROM t1;}
-for {set i 1} {$i<=3000} {incr i} {
- set r [expr {int(rand()*100000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd {COMMIT;}
-close $fd
-runtest {A big DELETE followed by many small INSERTs}
-
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DROP TABLE t1;}
-puts $fd {DROP TABLE t2;}
-close $fd
-runtest {DROP TABLE}
diff --git a/lib/libsqlite3/tool/speedtest16.c b/lib/libsqlite3/tool/speedtest16.c
deleted file mode 100644
index e81f1a6dba0..00000000000
--- a/lib/libsqlite3/tool/speedtest16.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line.
-** It converts each SQL statement into UTF16 and submits it to SQLite
-** for evaluation. A new UTF16 database is created at the beginning of
-** the program. All statements are timed using the high-resolution timer
-** built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest16.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out database.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "sqlite3.h"
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-/*
-** Convert a zero-terminated ASCII string into a zero-terminated
-** UTF-16le string. Memory to hold the returned string comes
-** from malloc() and should be freed by the caller.
-*/
-static void *asciiToUtf16le(const char *z){
- int n = strlen(z);
- char *z16;
- int i, j;
-
- z16 = malloc( n*2 + 2 );
- for(i=j=0; i<=n; i++){
- z16[j++] = z[i];
- z16[j++] = 0;
- }
- return (void*)z16;
-}
-
-/*
-** Timers
-*/
-static sqlite_uint64 prepTime = 0;
-static sqlite_uint64 runTime = 0;
-static sqlite_uint64 finalizeTime = 0;
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3 *db, const char *zSql){
- void *utf16;
- sqlite3_stmt *pStmt;
- const void *stmtTail;
- sqlite_uint64 iStart, iElapse;
- int rc;
-
- printf("****************************************************************\n");
- printf("SQL statement: [%s]\n", zSql);
- utf16 = asciiToUtf16le(zSql);
- iStart = sqlite3Hwtime();
- rc = sqlite3_prepare16_v2(db, utf16, -1, &pStmt, &stmtTail);
- iElapse = sqlite3Hwtime() - iStart;
- prepTime += iElapse;
- printf("sqlite3_prepare16_v2() returns %d in %llu cycles\n", rc, iElapse);
- if( rc==SQLITE_OK ){
- int nRow = 0;
- iStart = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iElapse = sqlite3Hwtime() - iStart;
- runTime += iElapse;
- printf("sqlite3_step() returns %d after %d rows in %llu cycles\n",
- rc, nRow, iElapse);
- iStart = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iElapse = sqlite3Hwtime() - iStart;
- finalizeTime += iElapse;
- printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse);
- }
- free(utf16);
-}
-
-int main(int argc, char **argv){
- void *utf16;
- sqlite3 *db;
- int rc;
- int nSql;
- char *zSql;
- int i, j;
- FILE *in;
- sqlite_uint64 iStart, iElapse;
- sqlite_uint64 iSetup = 0;
- int nStmt = 0;
- int nByte = 0;
-
- if( argc!=3 ){
- fprintf(stderr, "Usage: %s FILENAME SQL-SCRIPT\n"
- "Runs SQL-SCRIPT as UTF16 against a UTF16 database\n",
- argv[0]);
- exit(1);
- }
- in = fopen(argv[2], "r");
- fseek(in, 0L, SEEK_END);
- nSql = ftell(in);
- zSql = malloc( nSql+1 );
- fseek(in, 0L, SEEK_SET);
- nSql = fread(zSql, 1, nSql, in);
- zSql[nSql] = 0;
-
- printf("SQLite version: %d\n", sqlite3_libversion_number());
- unlink(argv[1]);
- utf16 = asciiToUtf16le(argv[1]);
- iStart = sqlite3Hwtime();
- rc = sqlite3_open16(utf16, &db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup = iElapse;
- printf("sqlite3_open16() returns %d in %llu cycles\n", rc, iElapse);
- free(utf16);
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && isspace(zSql[i]) ){ i++; }
- if( i<j ){
- nStmt++;
- nByte += j-i;
- prepareAndRun(db, &zSql[i]);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
- iStart = sqlite3Hwtime();
- sqlite3_close(db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup += iElapse;
- printf("sqlite3_close() returns in %llu cycles\n", iElapse);
- printf("\n");
- printf("Statements run: %15d\n", nStmt);
- printf("Bytes of SQL text: %15d\n", nByte);
- printf("Total prepare time: %15llu cycles\n", prepTime);
- printf("Total run time: %15llu cycles\n", runTime);
- printf("Total finalize time: %15llu cycles\n", finalizeTime);
- printf("Open/Close time: %15llu cycles\n", iSetup);
- printf("Total Time: %15llu cycles\n",
- prepTime + runTime + finalizeTime + iSetup);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/speedtest2.tcl b/lib/libsqlite3/tool/speedtest2.tcl
deleted file mode 100644
index 4fd632d4c7c..00000000000
--- a/lib/libsqlite3/tool/speedtest2.tcl
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Run this script using TCLSH to do a speed comparison between
-# various versions of SQLite and PostgreSQL and MySQL
-#
-
-# Run a test
-#
-set cnt 1
-proc runtest {title} {
- global cnt
- set sqlfile test$cnt.sql
- puts "<h2>Test $cnt: $title</h2>"
- incr cnt
- set fd [open $sqlfile r]
- set sql [string trim [read $fd [file size $sqlfile]]]
- close $fd
- set sx [split $sql \n]
- set n [llength $sx]
- if {$n>8} {
- set sql {}
- for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]<br>\n}
- append sql "<i>... [expr {$n-6}] lines omitted</i><br>\n"
- for {set i [expr {$n-3}]} {$i<$n} {incr i} {
- append sql [lindex $sx $i]<br>\n
- }
- } else {
- regsub -all \n [string trim $sql] <br> sql
- }
- puts "<blockquote>"
- puts "$sql"
- puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>"
- set format {<tr><td>%s</td><td align="right">&nbsp;&nbsp;&nbsp;%.3f</td></tr>}
- set delay 1000
- exec sync; after $delay;
- set t [time "exec psql drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format PostgreSQL: $t]
- exec sync; after $delay;
- set t [time "exec mysql -f drh <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format MySQL: $t]
-# set t [time "exec ./sqlite232 s232.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.3.2:} $t]
-# set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (cache=100):} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4:} $t]
- exec sync; after $delay;
- set t [time "exec ./sqlite240 sns.db <$sqlfile" 1]
- set t [expr {[lindex $t 0]/1000000.0}]
- puts [format $format {SQLite 2.4 (nosync):} $t]
-# set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1]
-# set t [expr {[lindex $t 0]/1000000.0}]
-# puts [format $format {SQLite 2.4 (test):} $t]
- puts "</table>"
-}
-
-# Initialize the environment
-#
-expr srand(1)
-catch {exec /bin/sh -c {rm -f s*.db}}
-set fd [open clear.sql w]
-puts $fd {
- drop table t1;
- drop table t2;
-}
-close $fd
-catch {exec psql drh <clear.sql}
-catch {exec mysql drh <clear.sql}
-set fd [open 2kinit.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=on;
-}
-close $fd
-exec ./sqlite240 s2k.db <2kinit.sql
-exec ./sqlite-t1 st1.db <2kinit.sql
-set fd [open nosync-init.sql w]
-puts $fd {
- PRAGMA default_cache_size=2000;
- PRAGMA default_synchronous=off;
-}
-close $fd
-exec ./sqlite240 sns.db <nosync-init.sql
-set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
-set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
-proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
-}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "BEGIN;"
-for {set i 1} {$i<=25000} {incr i} {
- set r [expr {int(rand()*500000)}]
- puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');"
-}
-puts $fd "COMMIT;"
-close $fd
-runtest {25000 INSERTs in a transaction}
-
-
-set fd [open test$cnt.sql w]
-puts $fd "DELETE FROM t1;"
-close $fd
-runtest {DELETE everything}
-
-
-set fd [open test$cnt.sql w]
-puts $fd {DROP TABLE t1;}
-close $fd
-runtest {DROP TABLE}
diff --git a/lib/libsqlite3/tool/speedtest8.c b/lib/libsqlite3/tool/speedtest8.c
deleted file mode 100644
index 051fc898196..00000000000
--- a/lib/libsqlite3/tool/speedtest8.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line
-** and submits that text to SQLite for evaluation. A new database
-** is created at the beginning of the program. All statements are
-** timed using the high-resolution timer built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest8.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out test.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <time.h>
-
-#if defined(_MSC_VER)
-#include <windows.h>
-#else
-#include <unistd.h>
-#include <sys/times.h>
-#include <sched.h>
-#endif
-
-#include "sqlite3.h"
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-#include "hwtime.h"
-
-/*
-** Timers
-*/
-static sqlite_uint64 prepTime = 0;
-static sqlite_uint64 runTime = 0;
-static sqlite_uint64 finalizeTime = 0;
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3 *db, const char *zSql, int bQuiet){
- sqlite3_stmt *pStmt;
- const char *stmtTail;
- sqlite_uint64 iStart, iElapse;
- int rc;
-
- if (!bQuiet){
- printf("***************************************************************\n");
- }
- if (!bQuiet) printf("SQL statement: [%s]\n", zSql);
- iStart = sqlite3Hwtime();
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail);
- iElapse = sqlite3Hwtime() - iStart;
- prepTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_prepare_v2() returns %d in %llu cycles\n", rc, iElapse);
- }
- if( rc==SQLITE_OK ){
- int nRow = 0;
- iStart = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iElapse = sqlite3Hwtime() - iStart;
- runTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_step() returns %d after %d rows in %llu cycles\n",
- rc, nRow, iElapse);
- }
- iStart = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iElapse = sqlite3Hwtime() - iStart;
- finalizeTime += iElapse;
- if (!bQuiet){
- printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse);
- }
- }
-}
-
-int main(int argc, char **argv){
- sqlite3 *db;
- int rc;
- int nSql;
- char *zSql;
- int i, j;
- FILE *in;
- sqlite_uint64 iStart, iElapse;
- sqlite_uint64 iSetup = 0;
- int nStmt = 0;
- int nByte = 0;
- const char *zArgv0 = argv[0];
- int bQuiet = 0;
-#if !defined(_MSC_VER)
- struct tms tmsStart, tmsEnd;
- clock_t clkStart, clkEnd;
-#endif
-
-#ifdef HAVE_OSINST
- extern sqlite3_vfs *sqlite3_instvfs_binarylog(char *, char *, char *);
- extern void sqlite3_instvfs_destroy(sqlite3_vfs *);
- sqlite3_vfs *pVfs = 0;
-#endif
-
- while (argc>3)
- {
-#ifdef HAVE_OSINST
- if( argc>4 && (strcmp(argv[1], "-log")==0) ){
- pVfs = sqlite3_instvfs_binarylog("oslog", 0, argv[2]);
- sqlite3_vfs_register(pVfs, 1);
- argv += 2;
- argc -= 2;
- continue;
- }
-#endif
-
- /*
- ** Increasing the priority slightly above normal can help with
- ** repeatability of testing. Note that with Cygwin, -5 equates
- ** to "High", +5 equates to "Low", and anything in between
- ** equates to "Normal".
- */
- if( argc>4 && (strcmp(argv[1], "-priority")==0) ){
-#if defined(_MSC_VER)
- int new_priority = atoi(argv[2]);
- if(!SetPriorityClass(GetCurrentProcess(),
- (new_priority<=-5) ? HIGH_PRIORITY_CLASS :
- (new_priority<=0) ? ABOVE_NORMAL_PRIORITY_CLASS :
- (new_priority==0) ? NORMAL_PRIORITY_CLASS :
- (new_priority<5) ? BELOW_NORMAL_PRIORITY_CLASS :
- IDLE_PRIORITY_CLASS)){
- printf ("error setting priority\n");
- exit(2);
- }
-#else
- struct sched_param myParam;
- sched_getparam(0, &myParam);
- printf ("Current process priority is %d.\n", (int)myParam.sched_priority);
- myParam.sched_priority = atoi(argv[2]);
- printf ("Setting process priority to %d.\n", (int)myParam.sched_priority);
- if (sched_setparam (0, &myParam) != 0){
- printf ("error setting priority\n");
- exit(2);
- }
-#endif
- argv += 2;
- argc -= 2;
- continue;
- }
-
- if( argc>3 && strcmp(argv[1], "-quiet")==0 ){
- bQuiet = -1;
- argv++;
- argc--;
- continue;
- }
-
- break;
- }
-
- if( argc!=3 ){
- fprintf(stderr, "Usage: %s [options] FILENAME SQL-SCRIPT\n"
- "Runs SQL-SCRIPT against a UTF8 database\n"
- "\toptions:\n"
-#ifdef HAVE_OSINST
- "\t-log <log>\n"
-#endif
- "\t-priority <value> : set priority of task\n"
- "\t-quiet : only display summary results\n",
- zArgv0);
- exit(1);
- }
-
- in = fopen(argv[2], "r");
- fseek(in, 0L, SEEK_END);
- nSql = ftell(in);
- zSql = malloc( nSql+1 );
- fseek(in, 0L, SEEK_SET);
- nSql = fread(zSql, 1, nSql, in);
- zSql[nSql] = 0;
-
- printf("SQLite version: %d\n", sqlite3_libversion_number());
- unlink(argv[1]);
-#if !defined(_MSC_VER)
- clkStart = times(&tmsStart);
-#endif
- iStart = sqlite3Hwtime();
- rc = sqlite3_open(argv[1], &db);
- iElapse = sqlite3Hwtime() - iStart;
- iSetup = iElapse;
- if (!bQuiet) printf("sqlite3_open() returns %d in %llu cycles\n", rc, iElapse);
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && isspace(zSql[i]) ){ i++; }
- if( i<j ){
- int n = j - i;
- if( n>=6 && memcmp(&zSql[i], ".crash",6)==0 ) exit(1);
- nStmt++;
- nByte += n;
- prepareAndRun(db, &zSql[i], bQuiet);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
- iStart = sqlite3Hwtime();
- sqlite3_close(db);
- iElapse = sqlite3Hwtime() - iStart;
-#if !defined(_MSC_VER)
- clkEnd = times(&tmsEnd);
-#endif
- iSetup += iElapse;
- if (!bQuiet) printf("sqlite3_close() returns in %llu cycles\n", iElapse);
-
- printf("\n");
- printf("Statements run: %15d stmts\n", nStmt);
- printf("Bytes of SQL text: %15d bytes\n", nByte);
- printf("Total prepare time: %15llu cycles\n", prepTime);
- printf("Total run time: %15llu cycles\n", runTime);
- printf("Total finalize time: %15llu cycles\n", finalizeTime);
- printf("Open/Close time: %15llu cycles\n", iSetup);
- printf("Total time: %15llu cycles\n",
- prepTime + runTime + finalizeTime + iSetup);
-
-#if !defined(_MSC_VER)
- printf("\n");
- printf("Total user CPU time: %15.3g secs\n", (tmsEnd.tms_utime - tmsStart.tms_utime)/(double)CLOCKS_PER_SEC );
- printf("Total system CPU time: %15.3g secs\n", (tmsEnd.tms_stime - tmsStart.tms_stime)/(double)CLOCKS_PER_SEC );
- printf("Total real time: %15.3g secs\n", (clkEnd -clkStart)/(double)CLOCKS_PER_SEC );
-#endif
-
-#ifdef HAVE_OSINST
- if( pVfs ){
- sqlite3_instvfs_destroy(pVfs);
- printf("vfs log written to %s\n", argv[0]);
- }
-#endif
-
- return 0;
-}
diff --git a/lib/libsqlite3/tool/speedtest8inst1.c b/lib/libsqlite3/tool/speedtest8inst1.c
deleted file mode 100644
index f0cb544c81e..00000000000
--- a/lib/libsqlite3/tool/speedtest8inst1.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
-** Performance test for SQLite.
-**
-** This program reads ASCII text from a file named on the command-line
-** and submits that text to SQLite for evaluation. A new database
-** is created at the beginning of the program. All statements are
-** timed using the high-resolution timer built into Intel-class processors.
-**
-** To compile this program, first compile the SQLite library separately
-** will full optimizations. For example:
-**
-** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
-**
-** Then link against this program. But to do optimize this program
-** because that defeats the hi-res timer.
-**
-** gcc speedtest8.c sqlite3.o -ldl -I../src
-**
-** Then run this program with a single argument which is the name of
-** a file containing SQL script that you want to test:
-**
-** ./a.out test.db test.sql
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include "sqlite3.h"
-
-#include "test_osinst.c"
-
-/*
-** Prepare and run a single statement of SQL.
-*/
-static void prepareAndRun(sqlite3_vfs *pInstVfs, sqlite3 *db, const char *zSql){
- sqlite3_stmt *pStmt;
- const char *stmtTail;
- int rc;
- char zMessage[1024];
- zMessage[1023] = '\0';
-
- sqlite3_uint64 iTime;
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_prepare_v2: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
-
- iTime = sqlite3Hwtime();
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail);
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs,BINARYLOG_PREPARE_V2,iTime,rc,zSql);
-
- if( rc==SQLITE_OK ){
- int nRow = 0;
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_step loop: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
- iTime = sqlite3Hwtime();
- while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_STEP, iTime, rc, zSql);
-
- sqlite3_snprintf(1023, zMessage, "sqlite3_finalize: %s", zSql);
- sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
- iTime = sqlite3Hwtime();
- rc = sqlite3_finalize(pStmt);
- iTime = sqlite3Hwtime() - iTime;
- sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_FINALIZE, iTime, rc, zSql);
- }
-}
-
-static int stringcompare(const char *zLeft, const char *zRight){
- int ii;
- for(ii=0; zLeft[ii] && zRight[ii]; ii++){
- if( zLeft[ii]!=zRight[ii] ) return 0;
- }
- return( zLeft[ii]==zRight[ii] );
-}
-
-static char *readScriptFile(const char *zFile, int *pnScript){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- sqlite3_file *p;
- int rc;
- sqlite3_int64 nByte;
- char *zData = 0;
- int flags = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_DB;
-
- p = (sqlite3_file *)malloc(pVfs->szOsFile);
- rc = pVfs->xOpen(pVfs, zFile, p, flags, &flags);
- if( rc!=SQLITE_OK ){
- goto error_out;
- }
-
- rc = p->pMethods->xFileSize(p, &nByte);
- if( rc!=SQLITE_OK ){
- goto close_out;
- }
-
- zData = (char *)malloc(nByte+1);
- rc = p->pMethods->xRead(p, zData, nByte, 0);
- if( rc!=SQLITE_OK ){
- goto close_out;
- }
- zData[nByte] = '\0';
-
- p->pMethods->xClose(p);
- free(p);
- *pnScript = nByte;
- return zData;
-
-close_out:
- p->pMethods->xClose(p);
-
-error_out:
- free(p);
- free(zData);
- return 0;
-}
-
-int main(int argc, char **argv){
-
- const char zUsageMsg[] =
- "Usage: %s options...\n"
- " where available options are:\n"
- "\n"
- " -db DATABASE-FILE (database file to operate on)\n"
- " -script SCRIPT-FILE (script file to read sql from)\n"
- " -log LOG-FILE (log file to create)\n"
- " -logdata (log all data to log file)\n"
- "\n"
- " Options -db, -script and -log are compulsory\n"
- "\n"
- ;
-
- const char *zDb = 0;
- const char *zScript = 0;
- const char *zLog = 0;
- int logdata = 0;
-
- int ii;
- int i, j;
- int rc;
-
- sqlite3_vfs *pInstVfs; /* Instrumentation VFS */
-
- char *zSql = 0;
- int nSql;
-
- sqlite3 *db;
-
- for(ii=1; ii<argc; ii++){
- if( stringcompare("-db", argv[ii]) && (ii+1)<argc ){
- zDb = argv[++ii];
- }
-
- else if( stringcompare("-script", argv[ii]) && (ii+1)<argc ){
- zScript = argv[++ii];
- }
-
- else if( stringcompare("-log", argv[ii]) && (ii+1)<argc ){
- zLog = argv[++ii];
- }
-
- else if( stringcompare("-logdata", argv[ii]) ){
- logdata = 1;
- }
-
- else {
- goto usage;
- }
- }
- if( !zDb || !zScript || !zLog ) goto usage;
-
- zSql = readScriptFile(zScript, &nSql);
- if( !zSql ){
- fprintf(stderr, "Failed to read script file\n");
- return -1;
- }
-
- pInstVfs = sqlite3_instvfs_binarylog("logging", 0, zLog, logdata);
-
- rc = sqlite3_open_v2(
- zDb, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "logging"
- );
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "Failed to open db: %s\n", sqlite3_errmsg(db));
- return -2;
- }
-
- for(i=j=0; j<nSql; j++){
- if( zSql[j]==';' ){
- int isComplete;
- char c = zSql[j+1];
- zSql[j+1] = 0;
- isComplete = sqlite3_complete(&zSql[i]);
- zSql[j+1] = c;
- if( isComplete ){
- zSql[j] = 0;
- while( i<j && isspace(zSql[i]) ){ i++; }
- if( i<j ){
- prepareAndRun(pInstVfs, db, &zSql[i]);
- }
- zSql[j] = ';';
- i = j+1;
- }
- }
- }
-
- sqlite3_instvfs_destroy(pInstVfs);
- return 0;
-
-usage:
- fprintf(stderr, zUsageMsg, argv[0]);
- return -3;
-}
diff --git a/lib/libsqlite3/tool/split-sqlite3c.tcl b/lib/libsqlite3/tool/split-sqlite3c.tcl
deleted file mode 100644
index 287b752828f..00000000000
--- a/lib/libsqlite3/tool/split-sqlite3c.tcl
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/tclsh
-#
-# This script splits the sqlite3.c amalgamated source code files into
-# several smaller files such that no single files is more than a fixed
-# number of lines in length (32k or 64k). Each of the split out files
-# is #include-ed by the master file.
-#
-# Splitting files up this way allows them to be used with older compilers
-# that cannot handle really long source files.
-#
-set MAX 32768 ;# Maximum number of lines per file.
-
-set BEGIN {^/\*+ Begin file ([a-zA-Z0-9_.]+) \*+/}
-set END {^/\*+ End of %s \*+/}
-
-set in [open sqlite3.c]
-set out1 [open sqlite3-all.c w]
-
-# Copy the header from sqlite3.c into sqlite3-all.c
-#
-while {[gets $in line]} {
- if {[regexp $BEGIN $line]} break
- puts $out1 $line
-}
-
-# Gather the complete content of a file into memory. Store the
-# content in $bufout. Store the number of lines is $nout
-#
-proc gather_one_file {firstline bufout nout} {
- regexp $::BEGIN $firstline all filename
- set end [format $::END $filename]
- upvar $bufout buf $nout n
- set buf $firstline\n
- global in
- set n 0
- while {[gets $in line]>=0} {
- incr n
- append buf $line\n
- if {[regexp $end $line]} break
- }
-}
-
-# Write a big chunk of text in to an auxiliary file "sqlite3-NNN.c".
-# Also add an appropriate #include to sqlite3-all.c
-#
-set filecnt 0
-proc write_one_file {content} {
- global filecnt
- incr filecnt
- set out [open sqlite3-$filecnt.c w]
- puts -nonewline $out $content
- close $out
- puts $::out1 "#include \"sqlite3-$filecnt.c\""
-}
-
-# Continue reading input. Store chunks in separate files and add
-# the #includes to the main sqlite3-all.c file as necessary to reference
-# the extra chunks.
-#
-set all {}
-set N 0
-while {[regexp $BEGIN $line]} {
- set buf {}
- set n 0
- gather_one_file $line buf n
- if {$n+$N>=$MAX} {
- write_one_file $all
- set all {}
- set N 0
- }
- append all $buf
- incr N $n
- while {[gets $in line]>=0} {
- if {[regexp $BEGIN $line]} break
- puts $out1 $line
- }
-}
-if {$N>0} {
- write_one_file $all
-}
-close $out1
-close $in
diff --git a/lib/libsqlite3/tool/sqldiff.c b/lib/libsqlite3/tool/sqldiff.c
deleted file mode 100644
index 9f0b705c40a..00000000000
--- a/lib/libsqlite3/tool/sqldiff.c
+++ /dev/null
@@ -1,1857 +0,0 @@
-/*
-** 2015-04-06
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This is a utility program that computes the differences in content
-** between two SQLite databases.
-**
-** To compile, simply link against SQLite.
-**
-** See the showHelp() routine below for a brief description of how to
-** run the utility.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <assert.h>
-#include "sqlite3.h"
-
-/*
-** All global variables are gathered into the "g" singleton.
-*/
-struct GlobalVars {
- const char *zArgv0; /* Name of program */
- int bSchemaOnly; /* Only show schema differences */
- int bSchemaPK; /* Use the schema-defined PK, not the true PK */
- unsigned fDebug; /* Debug flags */
- sqlite3 *db; /* The database connection */
-} g;
-
-/*
-** Allowed values for g.fDebug
-*/
-#define DEBUG_COLUMN_NAMES 0x000001
-#define DEBUG_DIFF_SQL 0x000002
-
-/*
-** Dynamic string object
-*/
-typedef struct Str Str;
-struct Str {
- char *z; /* Text of the string */
- int nAlloc; /* Bytes allocated in z[] */
- int nUsed; /* Bytes actually used in z[] */
-};
-
-/*
-** Initialize a Str object
-*/
-static void strInit(Str *p){
- p->z = 0;
- p->nAlloc = 0;
- p->nUsed = 0;
-}
-
-/*
-** Print an error resulting from faulting command-line arguments and
-** abort the program.
-*/
-static void cmdlineError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0);
- exit(1);
-}
-
-/*
-** Print an error message for an error that occurs at runtime, then
-** abort the program.
-*/
-static void runtimeError(const char *zFormat, ...){
- va_list ap;
- fprintf(stderr, "%s: ", g.zArgv0);
- va_start(ap, zFormat);
- vfprintf(stderr, zFormat, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-/*
-** Free all memory held by a Str object
-*/
-static void strFree(Str *p){
- sqlite3_free(p->z);
- strInit(p);
-}
-
-/*
-** Add formatted text to the end of a Str object
-*/
-static void strPrintf(Str *p, const char *zFormat, ...){
- int nNew;
- for(;;){
- if( p->z ){
- va_list ap;
- va_start(ap, zFormat);
- sqlite3_vsnprintf(p->nAlloc-p->nUsed, p->z+p->nUsed, zFormat, ap);
- va_end(ap);
- nNew = (int)strlen(p->z + p->nUsed);
- }else{
- nNew = p->nAlloc;
- }
- if( p->nUsed+nNew < p->nAlloc-1 ){
- p->nUsed += nNew;
- break;
- }
- p->nAlloc = p->nAlloc*2 + 1000;
- p->z = sqlite3_realloc(p->z, p->nAlloc);
- if( p->z==0 ) runtimeError("out of memory");
- }
-}
-
-
-
-/* Safely quote an SQL identifier. Use the minimum amount of transformation
-** necessary to allow the string to be used with %s.
-**
-** Space to hold the returned string is obtained from sqlite3_malloc(). The
-** caller is responsible for ensuring this space is freed when no longer
-** needed.
-*/
-static char *safeId(const char *zId){
- /* All SQLite keywords, in alphabetical order */
- static const char *azKeywords[] = {
- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
- "WITH", "WITHOUT",
- };
- int lwr, upr, mid, c, i, x;
- for(i=x=0; (c = zId[i])!=0; i++){
- if( !isalpha(c) && c!='_' ){
- if( i>0 && isdigit(c) ){
- x++;
- }else{
- return sqlite3_mprintf("\"%w\"", zId);
- }
- }
- }
- if( x ) return sqlite3_mprintf("%s", zId);
- lwr = 0;
- upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
- while( lwr<=upr ){
- mid = (lwr+upr)/2;
- c = sqlite3_stricmp(azKeywords[mid], zId);
- if( c==0 ) return sqlite3_mprintf("\"%w\"", zId);
- if( c<0 ){
- lwr = mid+1;
- }else{
- upr = mid-1;
- }
- }
- return sqlite3_mprintf("%s", zId);
-}
-
-/*
-** Prepare a new SQL statement. Print an error and abort if anything
-** goes wrong.
-*/
-static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){
- char *zSql;
- int rc;
- sqlite3_stmt *pStmt;
-
- zSql = sqlite3_vmprintf(zFormat, ap);
- if( zSql==0 ) runtimeError("out of memory");
- rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
- if( rc ){
- runtimeError("SQL statement error: %s\n\"%s\"", sqlite3_errmsg(g.db),
- zSql);
- }
- sqlite3_free(zSql);
- return pStmt;
-}
-static sqlite3_stmt *db_prepare(const char *zFormat, ...){
- va_list ap;
- sqlite3_stmt *pStmt;
- va_start(ap, zFormat);
- pStmt = db_vprepare(zFormat, ap);
- va_end(ap);
- return pStmt;
-}
-
-/*
-** Free a list of strings
-*/
-static void namelistFree(char **az){
- if( az ){
- int i;
- for(i=0; az[i]; i++) sqlite3_free(az[i]);
- sqlite3_free(az);
- }
-}
-
-/*
-** Return a list of column names for the table zDb.zTab. Space to
-** hold the list is obtained from sqlite3_malloc() and should released
-** using namelistFree() when no longer needed.
-**
-** Primary key columns are listed first, followed by data columns.
-** The number of columns in the primary key is returned in *pnPkey.
-**
-** Normally, the "primary key" in the previous sentence is the true
-** primary key - the rowid or INTEGER PRIMARY KEY for ordinary tables
-** or the declared PRIMARY KEY for WITHOUT ROWID tables. However, if
-** the g.bSchemaPK flag is set, then the schema-defined PRIMARY KEY is
-** used in all cases. In that case, entries that have NULL values in
-** any of their primary key fields will be excluded from the analysis.
-**
-** If the primary key for a table is the rowid but rowid is inaccessible,
-** then this routine returns a NULL pointer.
-**
-** Examples:
-** CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c));
-** *pnPKey = 1;
-** az = { "rowid", "a", "b", "c", 0 } // Normal case
-** az = { "c", "a", "b", 0 } // g.bSchemaPK==1
-**
-** CREATE TABLE t2(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(b));
-** *pnPKey = 1;
-** az = { "b", "a", "c", 0 }
-**
-** CREATE TABLE t3(x,y,z,PRIMARY KEY(y,z));
-** *pnPKey = 1 // Normal case
-** az = { "rowid", "x", "y", "z", 0 } // Normal case
-** *pnPKey = 2 // g.bSchemaPK==1
-** az = { "y", "x", "z", 0 } // g.bSchemaPK==1
-**
-** CREATE TABLE t4(x,y,z,PRIMARY KEY(y,z)) WITHOUT ROWID;
-** *pnPKey = 2
-** az = { "y", "z", "x", 0 }
-**
-** CREATE TABLE t5(rowid,_rowid_,oid);
-** az = 0 // The rowid is not accessible
-*/
-static char **columnNames(
- const char *zDb, /* Database ("main" or "aux") to query */
- const char *zTab, /* Name of table to return details of */
- int *pnPKey, /* OUT: Number of PK columns */
- int *pbRowid /* OUT: True if PK is an implicit rowid */
-){
- char **az = 0; /* List of column names to be returned */
- int naz = 0; /* Number of entries in az[] */
- sqlite3_stmt *pStmt; /* SQL statement being run */
- char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */
- int truePk = 0; /* PRAGMA table_info indentifies the PK to use */
- int nPK = 0; /* Number of PRIMARY KEY columns */
- int i, j; /* Loop counters */
-
- if( g.bSchemaPK==0 ){
- /* Normal case: Figure out what the true primary key is for the table.
- ** * For WITHOUT ROWID tables, the true primary key is the same as
- ** the schema PRIMARY KEY, which is guaranteed to be present.
- ** * For rowid tables with an INTEGER PRIMARY KEY, the true primary
- ** key is the INTEGER PRIMARY KEY.
- ** * For all other rowid tables, the rowid is the true primary key.
- */
- pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){
- zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- break;
- }
- }
- sqlite3_finalize(pStmt);
- if( zPkIdxName ){
- int nKey = 0;
- int nCol = 0;
- truePk = 0;
- pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- nCol++;
- if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; }
- if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1;
- }
- if( nCol==nKey ) truePk = 1;
- if( truePk ){
- nPK = nKey;
- }else{
- nPK = 1;
- }
- sqlite3_finalize(pStmt);
- sqlite3_free(zPkIdxName);
- }else{
- truePk = 1;
- nPK = 1;
- }
- pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab);
- }else{
- /* The g.bSchemaPK==1 case: Use whatever primary key is declared
- ** in the schema. The "rowid" will still be used as the primary key
- ** if the table definition does not contain a PRIMARY KEY.
- */
- nPK = 0;
- pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_int(pStmt,5)>0 ) nPK++;
- }
- sqlite3_reset(pStmt);
- if( nPK==0 ) nPK = 1;
- truePk = 1;
- }
- *pnPKey = nPK;
- naz = nPK;
- az = sqlite3_malloc( sizeof(char*)*(nPK+1) );
- if( az==0 ) runtimeError("out of memory");
- memset(az, 0, sizeof(char*)*(nPK+1));
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iPKey;
- if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){
- az[iPKey-1] = safeId((char*)sqlite3_column_text(pStmt,1));
- }else{
- az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
- if( az==0 ) runtimeError("out of memory");
- az[naz++] = safeId((char*)sqlite3_column_text(pStmt,1));
- }
- }
- sqlite3_finalize(pStmt);
- if( az ) az[naz] = 0;
-
- /* If it is non-NULL, set *pbRowid to indicate whether or not the PK of
- ** this table is an implicit rowid (*pbRowid==1) or not (*pbRowid==0). */
- if( pbRowid ) *pbRowid = (az[0]==0);
-
- /* If this table has an implicit rowid for a PK, figure out how to refer
- ** to it. There are three options - "rowid", "_rowid_" and "oid". Any
- ** of these will work, unless the table has an explicit column of the
- ** same name. */
- if( az[0]==0 ){
- const char *azRowid[] = { "rowid", "_rowid_", "oid" };
- for(i=0; i<sizeof(azRowid)/sizeof(azRowid[0]); i++){
- for(j=1; j<naz; j++){
- if( sqlite3_stricmp(az[j], azRowid[i])==0 ) break;
- }
- if( j>=naz ){
- az[0] = sqlite3_mprintf("%s", azRowid[i]);
- break;
- }
- }
- if( az[0]==0 ){
- for(i=1; i<naz; i++) sqlite3_free(az[i]);
- sqlite3_free(az);
- az = 0;
- }
- }
- return az;
-}
-
-/*
-** Print the sqlite3_value X as an SQL literal.
-*/
-static void printQuoted(FILE *out, sqlite3_value *X){
- switch( sqlite3_value_type(X) ){
- case SQLITE_FLOAT: {
- double r1;
- char zBuf[50];
- r1 = sqlite3_value_double(X);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
- fprintf(out, "%s", zBuf);
- break;
- }
- case SQLITE_INTEGER: {
- fprintf(out, "%lld", sqlite3_value_int64(X));
- break;
- }
- case SQLITE_BLOB: {
- const unsigned char *zBlob = sqlite3_value_blob(X);
- int nBlob = sqlite3_value_bytes(X);
- if( zBlob ){
- int i;
- fprintf(out, "x'");
- for(i=0; i<nBlob; i++){
- fprintf(out, "%02x", zBlob[i]);
- }
- fprintf(out, "'");
- }else{
- fprintf(out, "NULL");
- }
- break;
- }
- case SQLITE_TEXT: {
- const unsigned char *zArg = sqlite3_value_text(X);
- int i, j;
-
- if( zArg==0 ){
- fprintf(out, "NULL");
- }else{
- fprintf(out, "'");
- for(i=j=0; zArg[i]; i++){
- if( zArg[i]=='\'' ){
- fprintf(out, "%.*s'", i-j+1, &zArg[j]);
- j = i+1;
- }
- }
- fprintf(out, "%s'", &zArg[j]);
- }
- break;
- }
- case SQLITE_NULL: {
- fprintf(out, "NULL");
- break;
- }
- }
-}
-
-/*
-** Output SQL that will recreate the aux.zTab table.
-*/
-static void dump_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of the table */
- char **az = 0; /* List of columns */
- int nPk; /* Number of true primary key columns */
- int nCol; /* Number of data columns */
- int i; /* Loop counter */
- sqlite3_stmt *pStmt; /* SQL statement */
- const char *zSep; /* Separator string */
- Str ins; /* Beginning of the INSERT statement */
-
- pStmt = db_prepare("SELECT sql FROM aux.sqlite_master WHERE name=%Q", zTab);
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
- if( !g.bSchemaOnly ){
- az = columnNames("aux", zTab, &nPk, 0);
- strInit(&ins);
- if( az==0 ){
- pStmt = db_prepare("SELECT * FROM aux.%s", zId);
- strPrintf(&ins,"INSERT INTO %s VALUES", zId);
- }else{
- Str sql;
- strInit(&sql);
- zSep = "SELECT";
- for(i=0; az[i]; i++){
- strPrintf(&sql, "%s %s", zSep, az[i]);
- zSep = ",";
- }
- strPrintf(&sql," FROM aux.%s", zId);
- zSep = " ORDER BY";
- for(i=1; i<=nPk; i++){
- strPrintf(&sql, "%s %d", zSep, i);
- zSep = ",";
- }
- pStmt = db_prepare("%s", sql.z);
- strFree(&sql);
- strPrintf(&ins, "INSERT INTO %s", zId);
- zSep = "(";
- for(i=0; az[i]; i++){
- strPrintf(&ins, "%s%s", zSep, az[i]);
- zSep = ",";
- }
- strPrintf(&ins,") VALUES");
- namelistFree(az);
- }
- nCol = sqlite3_column_count(pStmt);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s",ins.z);
- zSep = "(";
- for(i=0; i<nCol; i++){
- fprintf(out, "%s",zSep);
- printQuoted(out, sqlite3_column_value(pStmt,i));
- zSep = ",";
- }
- fprintf(out, ");\n");
- }
- sqlite3_finalize(pStmt);
- strFree(&ins);
- } /* endif !g.bSchemaOnly */
- pStmt = db_prepare("SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q AND sql IS NOT NULL",
- zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
-}
-
-
-/*
-** Compute all differences for a single table.
-*/
-static void diff_one_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of table (translated for us in SQL) */
- char **az = 0; /* Columns in main */
- char **az2 = 0; /* Columns in aux */
- int nPk; /* Primary key columns in main */
- int nPk2; /* Primary key columns in aux */
- int n = 0; /* Number of columns in main */
- int n2; /* Number of columns in aux */
- int nQ; /* Number of output columns in the diff query */
- int i; /* Loop counter */
- const char *zSep; /* Separator string */
- Str sql; /* Comparison query */
- sqlite3_stmt *pStmt; /* Query statement to do the diff */
-
- strInit(&sql);
- if( g.fDebug==DEBUG_COLUMN_NAMES ){
- /* Simply run columnNames() on all tables of the origin
- ** database and show the results. This is used for testing
- ** and debugging of the columnNames() function.
- */
- az = columnNames("aux",zTab, &nPk, 0);
- if( az==0 ){
- printf("Rowid not accessible for %s\n", zId);
- }else{
- printf("%s:", zId);
- for(i=0; az[i]; i++){
- printf(" %s", az[i]);
- if( i+1==nPk ) printf(" *");
- }
- printf("\n");
- }
- goto end_diff_one_table;
- }
-
-
- if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
- if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from second database. */
- fprintf(out, "DROP TABLE %s;\n", zId);
- }
- goto end_diff_one_table;
- }
-
- if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from source */
- dump_table(zTab, out);
- goto end_diff_one_table;
- }
-
- az = columnNames("main", zTab, &nPk, 0);
- az2 = columnNames("aux", zTab, &nPk2, 0);
- if( az && az2 ){
- for(n=0; az[n]; n++){
- if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
- }
- }
- if( az==0
- || az2==0
- || nPk!=nPk2
- || az[n]
- ){
- /* Schema mismatch */
- fprintf(out, "DROP TABLE %s;\n", zId);
- dump_table(zTab, out);
- goto end_diff_one_table;
- }
-
- /* Build the comparison query */
- for(n2=n; az[n2]; n2++){}
- nQ = nPk2+1+2*(n2-nPk2);
- if( n2>nPk2 ){
- zSep = "SELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sB.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 1%s -- changed row\n", nPk==n ? "" : ",");
- while( az[i] ){
- strPrintf(&sql, " A.%s IS NOT B.%s, B.%s%s\n",
- az[i], az[i], az[i], i==n2-1 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- zSep = "\n AND (";
- while( az[i] ){
- strPrintf(&sql, "%sA.%s IS NOT B.%s%s\n",
- zSep, az[i], az[i], i==n2-1 ? ")" : "");
- zSep = " OR ";
- i++;
- }
- strPrintf(&sql, " UNION ALL\n");
- }
- zSep = "SELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sA.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 2%s -- deleted row\n", nPk==n ? "" : ",");
- while( az[i] ){
- strPrintf(&sql, " NULL, NULL%s\n", i==n2-1 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- zSep = " UNION ALL\nSELECT ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%sB.%s", zSep, az[i]);
- zSep = ", ";
- }
- strPrintf(&sql, ", 3%s -- inserted row\n", nPk==n ? "" : ",");
- while( az2[i] ){
- strPrintf(&sql, " 1, B.%s%s\n", az[i], i==n2-1 ? "" : ",");
- i++;
- }
- strPrintf(&sql, " FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n ORDER BY");
- zSep = " ";
- for(i=1; i<=nPk; i++){
- strPrintf(&sql, "%s%d", zSep, i);
- zSep = ", ";
- }
- strPrintf(&sql, ";\n");
-
- if( g.fDebug & DEBUG_DIFF_SQL ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_diff_one_table;
- }
-
- /* Drop indexes that are missing in the destination */
- pStmt = db_prepare(
- "SELECT name FROM main.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL"
- " AND sql NOT IN (SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL)",
- zTab, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- char *z = safeId((const char*)sqlite3_column_text(pStmt,0));
- fprintf(out, "DROP INDEX %s;\n", z);
- sqlite3_free(z);
- }
- sqlite3_finalize(pStmt);
-
- /* Run the query and output differences */
- if( !g.bSchemaOnly ){
- pStmt = db_prepare(sql.z);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iType = sqlite3_column_int(pStmt, nPk);
- if( iType==1 || iType==2 ){
- if( iType==1 ){ /* Change the content of a row */
- fprintf(out, "UPDATE %s", zId);
- zSep = " SET";
- for(i=nPk+1; i<nQ; i+=2){
- if( sqlite3_column_int(pStmt,i)==0 ) continue;
- fprintf(out, "%s %s=", zSep, az2[(i+nPk-1)/2]);
- zSep = ",";
- printQuoted(out, sqlite3_column_value(pStmt,i+1));
- }
- }else{ /* Delete a row */
- fprintf(out, "DELETE FROM %s", zId);
- }
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- fprintf(out, "%s %s=", zSep, az2[i]);
- printQuoted(out, sqlite3_column_value(pStmt,i));
- zSep = ",";
- }
- fprintf(out, ";\n");
- }else{ /* Insert a row */
- fprintf(out, "INSERT INTO %s(%s", zId, az2[0]);
- for(i=1; az2[i]; i++) fprintf(out, ",%s", az2[i]);
- fprintf(out, ") VALUES");
- zSep = "(";
- for(i=0; i<nPk2; i++){
- fprintf(out, "%s", zSep);
- zSep = ",";
- printQuoted(out, sqlite3_column_value(pStmt,i));
- }
- for(i=nPk2+2; i<nQ; i+=2){
- fprintf(out, ",");
- printQuoted(out, sqlite3_column_value(pStmt,i));
- }
- fprintf(out, ");\n");
- }
- }
- sqlite3_finalize(pStmt);
- } /* endif !g.bSchemaOnly */
-
- /* Create indexes that are missing in the source */
- pStmt = db_prepare(
- "SELECT sql FROM aux.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL"
- " AND sql NOT IN (SELECT sql FROM main.sqlite_master"
- " WHERE type='index' AND tbl_name=%Q"
- " AND sql IS NOT NULL)",
- zTab, zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
- }
- sqlite3_finalize(pStmt);
-
-end_diff_one_table:
- strFree(&sql);
- sqlite3_free(zId);
- namelistFree(az);
- namelistFree(az2);
- return;
-}
-
-/*
-** Check that table zTab exists and has the same schema in both the "main"
-** and "aux" databases currently opened by the global db handle. If they
-** do not, output an error message on stderr and exit(1). Otherwise, if
-** the schemas do match, return control to the caller.
-*/
-static void checkSchemasMatch(const char *zTab){
- sqlite3_stmt *pStmt = db_prepare(
- "SELECT A.sql=B.sql FROM main.sqlite_master A, aux.sqlite_master B"
- " WHERE A.name=%Q AND B.name=%Q", zTab, zTab
- );
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_int(pStmt,0)==0 ){
- runtimeError("schema changes for table %s", safeId(zTab));
- }
- }else{
- runtimeError("table %s missing from one or both databases", safeId(zTab));
- }
- sqlite3_finalize(pStmt);
-}
-
-/**************************************************************************
-** The following code is copied from fossil. It is used to generate the
-** fossil delta blobs sometimes used in RBU update records.
-*/
-
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned char u8;
-
-/*
-** The width of a hash window in bytes. The algorithm only works if this
-** is a power of 2.
-*/
-#define NHASH 16
-
-/*
-** The current state of the rolling hash.
-**
-** z[] holds the values that have been hashed. z[] is a circular buffer.
-** z[i] is the first entry and z[(i+NHASH-1)%NHASH] is the last entry of
-** the window.
-**
-** Hash.a is the sum of all elements of hash.z[]. Hash.b is a weighted
-** sum. Hash.b is z[i]*NHASH + z[i+1]*(NHASH-1) + ... + z[i+NHASH-1]*1.
-** (Each index for z[] should be module NHASH, of course. The %NHASH operator
-** is omitted in the prior expression for brevity.)
-*/
-typedef struct hash hash;
-struct hash {
- u16 a, b; /* Hash values */
- u16 i; /* Start of the hash window */
- char z[NHASH]; /* The values that have been hashed */
-};
-
-/*
-** Initialize the rolling hash using the first NHASH characters of z[]
-*/
-static void hash_init(hash *pHash, const char *z){
- u16 a, b, i;
- a = b = 0;
- for(i=0; i<NHASH; i++){
- a += z[i];
- b += (NHASH-i)*z[i];
- pHash->z[i] = z[i];
- }
- pHash->a = a & 0xffff;
- pHash->b = b & 0xffff;
- pHash->i = 0;
-}
-
-/*
-** Advance the rolling hash by a single character "c"
-*/
-static void hash_next(hash *pHash, int c){
- u16 old = pHash->z[pHash->i];
- pHash->z[pHash->i] = (char)c;
- pHash->i = (pHash->i+1)&(NHASH-1);
- pHash->a = pHash->a - old + (char)c;
- pHash->b = pHash->b - NHASH*old + pHash->a;
-}
-
-/*
-** Return a 32-bit hash value
-*/
-static u32 hash_32bit(hash *pHash){
- return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
-}
-
-/*
-** Write an base-64 integer into the given buffer.
-*/
-static void putInt(unsigned int v, char **pz){
- static const char zDigits[] =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
- /* 123456789 123456789 123456789 123456789 123456789 123456789 123 */
- int i, j;
- char zBuf[20];
- if( v==0 ){
- *(*pz)++ = '0';
- return;
- }
- for(i=0; v>0; i++, v>>=6){
- zBuf[i] = zDigits[v&0x3f];
- }
- for(j=i-1; j>=0; j--){
- *(*pz)++ = zBuf[j];
- }
-}
-
-/*
-** Return the number digits in the base-64 representation of a positive integer
-*/
-static int digit_count(int v){
- unsigned int i, x;
- for(i=1, x=64; (unsigned int)v>=x; i++, x <<= 6){}
- return i;
-}
-
-/*
-** Compute a 32-bit checksum on the N-byte buffer. Return the result.
-*/
-static unsigned int checksum(const char *zIn, size_t N){
- const unsigned char *z = (const unsigned char *)zIn;
- unsigned sum0 = 0;
- unsigned sum1 = 0;
- unsigned sum2 = 0;
- unsigned sum3 = 0;
- while(N >= 16){
- sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
- sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
- sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
- sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
- z += 16;
- N -= 16;
- }
- while(N >= 4){
- sum0 += z[0];
- sum1 += z[1];
- sum2 += z[2];
- sum3 += z[3];
- z += 4;
- N -= 4;
- }
- sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
- switch(N){
- case 3: sum3 += (z[2] << 8);
- case 2: sum3 += (z[1] << 16);
- case 1: sum3 += (z[0] << 24);
- default: ;
- }
- return sum3;
-}
-
-/*
-** Create a new delta.
-**
-** The delta is written into a preallocated buffer, zDelta, which
-** should be at least 60 bytes longer than the target file, zOut.
-** The delta string will be NUL-terminated, but it might also contain
-** embedded NUL characters if either the zSrc or zOut files are
-** binary. This function returns the length of the delta string
-** in bytes, excluding the final NUL terminator character.
-**
-** Output Format:
-**
-** The delta begins with a base64 number followed by a newline. This
-** number is the number of bytes in the TARGET file. Thus, given a
-** delta file z, a program can compute the size of the output file
-** simply by reading the first line and decoding the base-64 number
-** found there. The delta_output_size() routine does exactly this.
-**
-** After the initial size number, the delta consists of a series of
-** literal text segments and commands to copy from the SOURCE file.
-** A copy command looks like this:
-**
-** NNN@MMM,
-**
-** where NNN is the number of bytes to be copied and MMM is the offset
-** into the source file of the first byte (both base-64). If NNN is 0
-** it means copy the rest of the input file. Literal text is like this:
-**
-** NNN:TTTTT
-**
-** where NNN is the number of bytes of text (base-64) and TTTTT is the text.
-**
-** The last term is of the form
-**
-** NNN;
-**
-** In this case, NNN is a 32-bit bigendian checksum of the output file
-** that can be used to verify that the delta applied correctly. All
-** numbers are in base-64.
-**
-** Pure text files generate a pure text delta. Binary files generate a
-** delta that may contain some binary data.
-**
-** Algorithm:
-**
-** The encoder first builds a hash table to help it find matching
-** patterns in the source file. 16-byte chunks of the source file
-** sampled at evenly spaced intervals are used to populate the hash
-** table.
-**
-** Next we begin scanning the target file using a sliding 16-byte
-** window. The hash of the 16-byte window in the target is used to
-** search for a matching section in the source file. When a match
-** is found, a copy command is added to the delta. An effort is
-** made to extend the matching section to regions that come before
-** and after the 16-byte hash window. A copy command is only issued
-** if the result would use less space that just quoting the text
-** literally. Literal text is added to the delta for sections that
-** do not match or which can not be encoded efficiently using copy
-** commands.
-*/
-static int rbuDeltaCreate(
- const char *zSrc, /* The source or pattern file */
- unsigned int lenSrc, /* Length of the source file */
- const char *zOut, /* The target file */
- unsigned int lenOut, /* Length of the target file */
- char *zDelta /* Write the delta into this buffer */
-){
- unsigned int i, base;
- char *zOrigDelta = zDelta;
- hash h;
- int nHash; /* Number of hash table entries */
- int *landmark; /* Primary hash table */
- int *collide; /* Collision chain */
- int lastRead = -1; /* Last byte of zSrc read by a COPY command */
-
- /* Add the target file size to the beginning of the delta
- */
- putInt(lenOut, &zDelta);
- *(zDelta++) = '\n';
-
- /* If the source file is very small, it means that we have no
- ** chance of ever doing a copy command. Just output a single
- ** literal segment for the entire target and exit.
- */
- if( lenSrc<=NHASH ){
- putInt(lenOut, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, zOut, lenOut);
- zDelta += lenOut;
- putInt(checksum(zOut, lenOut), &zDelta);
- *(zDelta++) = ';';
- return zDelta - zOrigDelta;
- }
-
- /* Compute the hash table used to locate matching sections in the
- ** source file.
- */
- nHash = lenSrc/NHASH;
- collide = sqlite3_malloc( nHash*2*sizeof(int) );
- landmark = &collide[nHash];
- memset(landmark, -1, nHash*sizeof(int));
- memset(collide, -1, nHash*sizeof(int));
- for(i=0; i<lenSrc-NHASH; i+=NHASH){
- int hv;
- hash_init(&h, &zSrc[i]);
- hv = hash_32bit(&h) % nHash;
- collide[i/NHASH] = landmark[hv];
- landmark[hv] = i/NHASH;
- }
-
- /* Begin scanning the target file and generating copy commands and
- ** literal sections of the delta.
- */
- base = 0; /* We have already generated everything before zOut[base] */
- while( base+NHASH<lenOut ){
- int iSrc, iBlock;
- int bestCnt, bestOfst=0, bestLitsz=0;
- hash_init(&h, &zOut[base]);
- i = 0; /* Trying to match a landmark against zOut[base+i] */
- bestCnt = 0;
- while( 1 ){
- int hv;
- int limit = 250;
-
- hv = hash_32bit(&h) % nHash;
- iBlock = landmark[hv];
- while( iBlock>=0 && (limit--)>0 ){
- /*
- ** The hash window has identified a potential match against
- ** landmark block iBlock. But we need to investigate further.
- **
- ** Look for a region in zOut that matches zSrc. Anchor the search
- ** at zSrc[iSrc] and zOut[base+i]. Do not include anything prior to
- ** zOut[base] or after zOut[outLen] nor anything after zSrc[srcLen].
- **
- ** Set cnt equal to the length of the match and set ofst so that
- ** zSrc[ofst] is the first element of the match. litsz is the number
- ** of characters between zOut[base] and the beginning of the match.
- ** sz will be the overhead (in bytes) needed to encode the copy
- ** command. Only generate copy command if the overhead of the
- ** copy command is less than the amount of literal text to be copied.
- */
- int cnt, ofst, litsz;
- int j, k, x, y;
- int sz;
-
- /* Beginning at iSrc, match forwards as far as we can. j counts
- ** the number of characters that match */
- iSrc = iBlock*NHASH;
- for(
- j=0, x=iSrc, y=base+i;
- (unsigned int)x<lenSrc && (unsigned int)y<lenOut;
- j++, x++, y++
- ){
- if( zSrc[x]!=zOut[y] ) break;
- }
- j--;
-
- /* Beginning at iSrc-1, match backwards as far as we can. k counts
- ** the number of characters that match */
- for(k=1; k<iSrc && (unsigned int)k<=i; k++){
- if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
- }
- k--;
-
- /* Compute the offset and size of the matching region */
- ofst = iSrc-k;
- cnt = j+k+1;
- litsz = i-k; /* Number of bytes of literal text before the copy */
- /* sz will hold the number of bytes needed to encode the "insert"
- ** command and the copy command, not counting the "insert" text */
- sz = digit_count(i-k)+digit_count(cnt)+digit_count(ofst)+3;
- if( cnt>=sz && cnt>bestCnt ){
- /* Remember this match only if it is the best so far and it
- ** does not increase the file size */
- bestCnt = cnt;
- bestOfst = iSrc-k;
- bestLitsz = litsz;
- }
-
- /* Check the next matching block */
- iBlock = collide[iBlock];
- }
-
- /* We have a copy command that does not cause the delta to be larger
- ** than a literal insert. So add the copy command to the delta.
- */
- if( bestCnt>0 ){
- if( bestLitsz>0 ){
- /* Add an insert command before the copy */
- putInt(bestLitsz,&zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], bestLitsz);
- zDelta += bestLitsz;
- base += bestLitsz;
- }
- base += bestCnt;
- putInt(bestCnt, &zDelta);
- *(zDelta++) = '@';
- putInt(bestOfst, &zDelta);
- *(zDelta++) = ',';
- if( bestOfst + bestCnt -1 > lastRead ){
- lastRead = bestOfst + bestCnt - 1;
- }
- bestCnt = 0;
- break;
- }
-
- /* If we reach this point, it means no match is found so far */
- if( base+i+NHASH>=lenOut ){
- /* We have reached the end of the file and have not found any
- ** matches. Do an "insert" for everything that does not match */
- putInt(lenOut-base, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], lenOut-base);
- zDelta += lenOut-base;
- base = lenOut;
- break;
- }
-
- /* Advance the hash by one character. Keep looking for a match */
- hash_next(&h, zOut[base+i+NHASH]);
- i++;
- }
- }
- /* Output a final "insert" record to get all the text at the end of
- ** the file that does not match anything in the source file.
- */
- if( base<lenOut ){
- putInt(lenOut-base, &zDelta);
- *(zDelta++) = ':';
- memcpy(zDelta, &zOut[base], lenOut-base);
- zDelta += lenOut-base;
- }
- /* Output the final checksum record. */
- putInt(checksum(zOut, lenOut), &zDelta);
- *(zDelta++) = ';';
- sqlite3_free(collide);
- return zDelta - zOrigDelta;
-}
-
-/*
-** End of code copied from fossil.
-**************************************************************************/
-
-static void strPrintfArray(
- Str *pStr, /* String object to append to */
- const char *zSep, /* Separator string */
- const char *zFmt, /* Format for each entry */
- char **az, int n /* Array of strings & its size (or -1) */
-){
- int i;
- for(i=0; az[i] && (i<n || n<0); i++){
- if( i!=0 ) strPrintf(pStr, "%s", zSep);
- strPrintf(pStr, zFmt, az[i], az[i], az[i]);
- }
-}
-
-static void getRbudiffQuery(
- const char *zTab,
- char **azCol,
- int nPK,
- int bOtaRowid,
- Str *pSql
-){
- int i;
-
- /* First the newly inserted rows: **/
- strPrintf(pSql, "SELECT ");
- strPrintfArray(pSql, ", ", "%s", azCol, -1);
- strPrintf(pSql, ", 0, "); /* Set ota_control to 0 for an insert */
- strPrintfArray(pSql, ", ", "NULL", azCol, -1);
- strPrintf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
- strPrintf(pSql, " SELECT 1 FROM ", zTab);
- strPrintf(pSql, " main.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n)");
-
- /* Deleted rows: */
- strPrintf(pSql, "\nUNION ALL\nSELECT ");
- strPrintfArray(pSql, ", ", "%s", azCol, nPK);
- if( azCol[nPK] ){
- strPrintf(pSql, ", ");
- strPrintfArray(pSql, ", ", "NULL", &azCol[nPK], -1);
- }
- strPrintf(pSql, ", 1, "); /* Set ota_control to 1 for a delete */
- strPrintfArray(pSql, ", ", "NULL", azCol, -1);
- strPrintf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
- strPrintf(pSql, " SELECT 1 FROM ", zTab);
- strPrintf(pSql, " aux.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) ");
-
- /* Updated rows. If all table columns are part of the primary key, there
- ** can be no updates. In this case this part of the compound SELECT can
- ** be omitted altogether. */
- if( azCol[nPK] ){
- strPrintf(pSql, "\nUNION ALL\nSELECT ");
- strPrintfArray(pSql, ", ", "n.%s", azCol, nPK);
- strPrintf(pSql, ",\n");
- strPrintfArray(pSql, " ,\n",
- " CASE WHEN n.%s IS o.%s THEN NULL ELSE n.%s END", &azCol[nPK], -1
- );
-
- if( bOtaRowid==0 ){
- strPrintf(pSql, ", '");
- strPrintfArray(pSql, "", ".", azCol, nPK);
- strPrintf(pSql, "' ||\n");
- }else{
- strPrintf(pSql, ",\n");
- }
- strPrintfArray(pSql, " ||\n",
- " CASE WHEN n.%s IS o.%s THEN '.' ELSE 'x' END", &azCol[nPK], -1
- );
- strPrintf(pSql, "\nAS ota_control, ");
- strPrintfArray(pSql, ", ", "NULL", azCol, nPK);
- strPrintf(pSql, ",\n");
- strPrintfArray(pSql, " ,\n",
- " CASE WHEN n.%s IS o.%s THEN NULL ELSE o.%s END", &azCol[nPK], -1
- );
-
- strPrintf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ", zTab, zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
- strPrintf(pSql, " AND ota_control LIKE '%%x%%'");
- }
-
- /* Now add an ORDER BY clause to sort everything by PK. */
- strPrintf(pSql, "\nORDER BY ");
- for(i=1; i<=nPK; i++) strPrintf(pSql, "%s%d", ((i>1)?", ":""), i);
-}
-
-static void rbudiff_one_table(const char *zTab, FILE *out){
- int bOtaRowid; /* True to use an ota_rowid column */
- int nPK; /* Number of primary key columns in table */
- char **azCol; /* NULL terminated array of col names */
- int i;
- int nCol;
- Str ct = {0, 0, 0}; /* The "CREATE TABLE data_xxx" statement */
- Str sql = {0, 0, 0}; /* Query to find differences */
- Str insert = {0, 0, 0}; /* First part of output INSERT statement */
- sqlite3_stmt *pStmt = 0;
-
- /* --rbu mode must use real primary keys. */
- g.bSchemaPK = 1;
-
- /* Check that the schemas of the two tables match. Exit early otherwise. */
- checkSchemasMatch(zTab);
-
- /* Grab the column names and PK details for the table(s). If no usable PK
- ** columns are found, bail out early. */
- azCol = columnNames("main", zTab, &nPK, &bOtaRowid);
- if( azCol==0 ){
- runtimeError("table %s has no usable PK columns", zTab);
- }
- for(nCol=0; azCol[nCol]; nCol++);
-
- /* Build and output the CREATE TABLE statement for the data_xxx table */
- strPrintf(&ct, "CREATE TABLE IF NOT EXISTS 'data_%q'(", zTab);
- if( bOtaRowid ) strPrintf(&ct, "rbu_rowid, ");
- strPrintfArray(&ct, ", ", "%s", &azCol[bOtaRowid], -1);
- strPrintf(&ct, ", rbu_control);");
-
- /* Get the SQL for the query to retrieve data from the two databases */
- getRbudiffQuery(zTab, azCol, nPK, bOtaRowid, &sql);
-
- /* Build the first part of the INSERT statement output for each row
- ** in the data_xxx table. */
- strPrintf(&insert, "INSERT INTO 'data_%q' (", zTab);
- if( bOtaRowid ) strPrintf(&insert, "rbu_rowid, ");
- strPrintfArray(&insert, ", ", "%s", &azCol[bOtaRowid], -1);
- strPrintf(&insert, ", rbu_control) VALUES(");
-
- pStmt = db_prepare("%s", sql.z);
-
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
-
- /* If this is the first row output, print out the CREATE TABLE
- ** statement first. And then set ct.z to NULL so that it is not
- ** printed again. */
- if( ct.z ){
- fprintf(out, "%s\n", ct.z);
- strFree(&ct);
- }
-
- /* Output the first part of the INSERT statement */
- fprintf(out, "%s", insert.z);
-
- if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){
- for(i=0; i<=nCol; i++){
- if( i>0 ) fprintf(out, ", ");
- printQuoted(out, sqlite3_column_value(pStmt, i));
- }
- }else{
- char *zOtaControl;
- int nOtaControl = sqlite3_column_bytes(pStmt, nCol);
-
- zOtaControl = (char*)sqlite3_malloc(nOtaControl);
- memcpy(zOtaControl, sqlite3_column_text(pStmt, nCol), nOtaControl+1);
-
- for(i=0; i<nCol; i++){
- int bDone = 0;
- if( i>=nPK
- && sqlite3_column_type(pStmt, i)==SQLITE_BLOB
- && sqlite3_column_type(pStmt, nCol+1+i)==SQLITE_BLOB
- ){
- const char *aSrc = sqlite3_column_blob(pStmt, nCol+1+i);
- int nSrc = sqlite3_column_bytes(pStmt, nCol+1+i);
- const char *aFinal = sqlite3_column_blob(pStmt, i);
- int nFinal = sqlite3_column_bytes(pStmt, i);
- char *aDelta;
- int nDelta;
-
- aDelta = sqlite3_malloc(nFinal + 60);
- nDelta = rbuDeltaCreate(aSrc, nSrc, aFinal, nFinal, aDelta);
- if( nDelta<nFinal ){
- int j;
- fprintf(out, "x'");
- for(j=0; j<nDelta; j++) fprintf(out, "%02x", (u8)aDelta[j]);
- fprintf(out, "'");
- zOtaControl[i-bOtaRowid] = 'f';
- bDone = 1;
- }
- sqlite3_free(aDelta);
- }
-
- if( bDone==0 ){
- printQuoted(out, sqlite3_column_value(pStmt, i));
- }
- fprintf(out, ", ");
- }
- fprintf(out, "'%s'", zOtaControl);
- sqlite3_free(zOtaControl);
- }
-
- /* And the closing bracket of the insert statement */
- fprintf(out, ");\n");
- }
-
- sqlite3_finalize(pStmt);
-
- strFree(&ct);
- strFree(&sql);
- strFree(&insert);
-}
-
-/*
-** Display a summary of differences between two versions of the same
-** table table.
-**
-** * Number of rows changed
-** * Number of rows added
-** * Number of rows deleted
-** * Number of identical rows
-*/
-static void summarize_one_table(const char *zTab, FILE *out){
- char *zId = safeId(zTab); /* Name of table (translated for us in SQL) */
- char **az = 0; /* Columns in main */
- char **az2 = 0; /* Columns in aux */
- int nPk; /* Primary key columns in main */
- int nPk2; /* Primary key columns in aux */
- int n = 0; /* Number of columns in main */
- int n2; /* Number of columns in aux */
- int i; /* Loop counter */
- const char *zSep; /* Separator string */
- Str sql; /* Comparison query */
- sqlite3_stmt *pStmt; /* Query statement to do the diff */
- sqlite3_int64 nUpdate; /* Number of updated rows */
- sqlite3_int64 nUnchanged; /* Number of unmodified rows */
- sqlite3_int64 nDelete; /* Number of deleted rows */
- sqlite3_int64 nInsert; /* Number of inserted rows */
-
- strInit(&sql);
- if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
- if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from second database. */
- fprintf(out, "%s: missing from second database\n", zTab);
- }
- goto end_summarize_one_table;
- }
-
- if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
- /* Table missing from source */
- fprintf(out, "%s: missing from first database\n", zTab);
- goto end_summarize_one_table;
- }
-
- az = columnNames("main", zTab, &nPk, 0);
- az2 = columnNames("aux", zTab, &nPk2, 0);
- if( az && az2 ){
- for(n=0; az[n]; n++){
- if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
- }
- }
- if( az==0
- || az2==0
- || nPk!=nPk2
- || az[n]
- ){
- /* Schema mismatch */
- fprintf(out, "%s: incompatible schema\n", zTab);
- goto end_summarize_one_table;
- }
-
- /* Build the comparison query */
- for(n2=n; az[n2]; n2++){}
- strPrintf(&sql, "SELECT 1, count(*)");
- if( n2==nPk2 ){
- strPrintf(&sql, ", 0\n");
- }else{
- zSep = ", sum(";
- for(i=nPk; az[i]; i++){
- strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, az[i], az[i]);
- zSep = " OR ";
- }
- strPrintf(&sql, ")\n");
- }
- strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, " UNION ALL\n");
- strPrintf(&sql, "SELECT 2, count(*), 0\n");
- strPrintf(&sql, " FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B ", zId);
- zSep = "WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- strPrintf(&sql, " UNION ALL\n");
- strPrintf(&sql, "SELECT 3, count(*), 0\n");
- strPrintf(&sql, " FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A ", zId);
- zSep = "WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n ORDER BY 1;\n");
-
- if( (g.fDebug & DEBUG_DIFF_SQL)!=0 ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_summarize_one_table;
- }
-
- /* Run the query and output difference summary */
- pStmt = db_prepare(sql.z);
- nUpdate = 0;
- nInsert = 0;
- nDelete = 0;
- nUnchanged = 0;
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- switch( sqlite3_column_int(pStmt,0) ){
- case 1:
- nUpdate = sqlite3_column_int64(pStmt,2);
- nUnchanged = sqlite3_column_int64(pStmt,1) - nUpdate;
- break;
- case 2:
- nDelete = sqlite3_column_int64(pStmt,1);
- break;
- case 3:
- nInsert = sqlite3_column_int64(pStmt,1);
- break;
- }
- }
- sqlite3_finalize(pStmt);
- fprintf(out, "%s: %lld changes, %lld inserts, %lld deletes, %lld unchanged\n",
- zTab, nUpdate, nInsert, nDelete, nUnchanged);
-
-end_summarize_one_table:
- strFree(&sql);
- sqlite3_free(zId);
- namelistFree(az);
- namelistFree(az2);
- return;
-}
-
-/*
-** Write a 64-bit signed integer as a varint onto out
-*/
-static void putsVarint(FILE *out, sqlite3_uint64 v){
- int i, n;
- unsigned char p[12];
- if( v & (((sqlite3_uint64)0xff000000)<<32) ){
- p[8] = (unsigned char)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- fwrite(p, 8, 1, out);
- }else{
- n = 9;
- do{
- p[n--] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- p[9] &= 0x7f;
- fwrite(p+n+1, 9-n, 1, out);
- }
-}
-
-/*
-** Write an SQLite value onto out.
-*/
-static void putValue(FILE *out, sqlite3_value *pVal){
- int iDType = sqlite3_value_type(pVal);
- sqlite3_int64 iX;
- double rX;
- sqlite3_uint64 uX;
- int j;
-
- putc(iDType, out);
- switch( iDType ){
- case SQLITE_INTEGER:
- iX = sqlite3_value_int64(pVal);
- memcpy(&uX, &iX, 8);
- for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
- break;
- case SQLITE_FLOAT:
- rX = sqlite3_value_double(pVal);
- memcpy(&uX, &rX, 8);
- for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
- break;
- case SQLITE_TEXT:
- iX = sqlite3_value_bytes(pVal);
- putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out);
- break;
- case SQLITE_BLOB:
- iX = sqlite3_value_bytes(pVal);
- putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out);
- break;
- case SQLITE_NULL:
- break;
- }
-}
-
-/*
-** Generate a CHANGESET for all differences from main.zTab to aux.zTab.
-*/
-static void changeset_one_table(const char *zTab, FILE *out){
- sqlite3_stmt *pStmt; /* SQL statment */
- char *zId = safeId(zTab); /* Escaped name of the table */
- char **azCol = 0; /* List of escaped column names */
- int nCol = 0; /* Number of columns */
- int *aiFlg = 0; /* 0 if column is not part of PK */
- int *aiPk = 0; /* Column numbers for each PK column */
- int nPk = 0; /* Number of PRIMARY KEY columns */
- Str sql; /* SQL for the diff query */
- int i, k; /* Loop counters */
- const char *zSep; /* List separator */
-
- /* Check that the schemas of the two tables match. Exit early otherwise. */
- checkSchemasMatch(zTab);
-
- pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- nCol++;
- azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol);
- if( azCol==0 ) runtimeError("out of memory");
- aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol);
- if( aiFlg==0 ) runtimeError("out of memory");
- azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1));
- aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5);
- if( i>0 ){
- if( i>nPk ){
- nPk = i;
- aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk);
- if( aiPk==0 ) runtimeError("out of memory");
- }
- aiPk[i-1] = nCol-1;
- }
- }
- sqlite3_finalize(pStmt);
- if( nPk==0 ) goto end_changeset_one_table;
- strInit(&sql);
- if( nCol>nPk ){
- strPrintf(&sql, "SELECT %d", SQLITE_UPDATE);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n A.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n A.%s IS NOT B.%s, A.%s, B.%s",
- azCol[i], azCol[i], azCol[i], azCol[i]);
- }
- }
- strPrintf(&sql,"\n FROM main.%s A, aux.%s B\n", zId, zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- zSep = "\n AND (";
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ) continue;
- strPrintf(&sql, "%sA.%s IS NOT B.%s", zSep, azCol[i], azCol[i]);
- zSep = " OR\n ";
- }
- strPrintf(&sql,")\n UNION ALL\n");
- }
- strPrintf(&sql, "SELECT %d", SQLITE_DELETE);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n A.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n 1, A.%s, NULL", azCol[i]);
- }
- }
- strPrintf(&sql, "\n FROM main.%s A\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n UNION ALL\n");
- strPrintf(&sql, "SELECT %d", SQLITE_INSERT);
- for(i=0; i<nCol; i++){
- if( aiFlg[i] ){
- strPrintf(&sql, ",\n B.%s", azCol[i]);
- }else{
- strPrintf(&sql, ",\n 1, NULL, B.%s", azCol[i]);
- }
- }
- strPrintf(&sql, "\n FROM aux.%s B\n", zId);
- strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId);
- zSep = " WHERE";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s A.%s=B.%s", zSep, azCol[aiPk[i]], azCol[aiPk[i]]);
- zSep = " AND";
- }
- strPrintf(&sql, ")\n");
- strPrintf(&sql, " ORDER BY");
- zSep = " ";
- for(i=0; i<nPk; i++){
- strPrintf(&sql, "%s %d", zSep, aiPk[i]+2);
- zSep = ",";
- }
- strPrintf(&sql, ";\n");
-
- if( g.fDebug & DEBUG_DIFF_SQL ){
- printf("SQL for %s:\n%s\n", zId, sql.z);
- goto end_changeset_one_table;
- }
-
- putc('T', out);
- putsVarint(out, (sqlite3_uint64)nCol);
- for(i=0; i<nCol; i++) putc(aiFlg[i]!=0, out);
- fwrite(zTab, 1, strlen(zTab), out);
- putc(0, out);
-
- pStmt = db_prepare("%s", sql.z);
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int iType = sqlite3_column_int(pStmt,0);
- putc(iType, out);
- putc(0, out);
- switch( sqlite3_column_int(pStmt,0) ){
- case SQLITE_UPDATE: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+1));
- k += 3;
- }else{
- putc(0, out);
- k += 3;
- }
- }
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putc(0, out);
- k++;
- }else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+2));
- k += 3;
- }else{
- putc(0, out);
- k += 3;
- }
- }
- break;
- }
- case SQLITE_INSERT: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else{
- putValue(out, sqlite3_column_value(pStmt,k+2));
- k += 3;
- }
- }
- break;
- }
- case SQLITE_DELETE: {
- for(k=1, i=0; i<nCol; i++){
- if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
- k++;
- }else{
- putValue(out, sqlite3_column_value(pStmt,k+1));
- k += 3;
- }
- }
- break;
- }
- }
- }
- sqlite3_finalize(pStmt);
-
-end_changeset_one_table:
- while( nCol>0 ) sqlite3_free(azCol[--nCol]);
- sqlite3_free(azCol);
- sqlite3_free(aiPk);
- sqlite3_free(zId);
-}
-
-/*
-** Print sketchy documentation for this utility program
-*/
-static void showHelp(void){
- printf("Usage: %s [options] DB1 DB2\n", g.zArgv0);
- printf(
-"Output SQL text that would transform DB1 into DB2.\n"
-"Options:\n"
-" --changeset FILE Write a CHANGESET into FILE\n"
-" -L|--lib LIBRARY Load an SQLite extension library\n"
-" --primarykey Use schema-defined PRIMARY KEYs\n"
-" --rbu Output SQL to create/populate RBU table(s)\n"
-" --schema Show only differences in the schema\n"
-" --summary Show only a summary of the differences\n"
-" --table TAB Show only differences in table TAB\n"
- );
-}
-
-int main(int argc, char **argv){
- const char *zDb1 = 0;
- const char *zDb2 = 0;
- int i;
- int rc;
- char *zErrMsg = 0;
- char *zSql;
- sqlite3_stmt *pStmt;
- char *zTab = 0;
- FILE *out = stdout;
- void (*xDiff)(const char*,FILE*) = diff_one_table;
- int nExt = 0;
- char **azExt = 0;
-
- g.zArgv0 = argv[0];
- sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"changeset")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- out = fopen(argv[++i], "wb");
- if( out==0 ) cmdlineError("cannot open: %s", argv[i]);
- xDiff = changeset_one_table;
- }else
- if( strcmp(z,"debug")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- g.fDebug = strtol(argv[++i], 0, 0);
- }else
- if( strcmp(z,"help")==0 ){
- showHelp();
- return 0;
- }else
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- if( strcmp(z,"lib")==0 || strcmp(z,"L")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- azExt = realloc(azExt, sizeof(azExt[0])*(nExt+1));
- if( azExt==0 ) cmdlineError("out of memory");
- azExt[nExt++] = argv[++i];
- }else
-#endif
- if( strcmp(z,"primarykey")==0 ){
- g.bSchemaPK = 1;
- }else
- if( strcmp(z,"rbu")==0 ){
- xDiff = rbudiff_one_table;
- }else
- if( strcmp(z,"schema")==0 ){
- g.bSchemaOnly = 1;
- }else
- if( strcmp(z,"summary")==0 ){
- xDiff = summarize_one_table;
- }else
- if( strcmp(z,"table")==0 ){
- if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
- zTab = argv[++i];
- }else
- {
- cmdlineError("unknown option: %s", argv[i]);
- }
- }else if( zDb1==0 ){
- zDb1 = argv[i];
- }else if( zDb2==0 ){
- zDb2 = argv[i];
- }else{
- cmdlineError("unknown argument: %s", argv[i]);
- }
- }
- if( zDb2==0 ){
- cmdlineError("two database arguments required");
- }
- rc = sqlite3_open(zDb1, &g.db);
- if( rc ){
- cmdlineError("cannot open database file \"%s\"", zDb1);
- }
- rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1);
- }
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- sqlite3_enable_load_extension(g.db, 1);
- for(i=0; i<nExt; i++){
- rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
- }
- }
-#endif
- free(azExt);
- zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
- rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("cannot attach database \"%s\"", zDb2);
- }
- rc = sqlite3_exec(g.db, "SELECT * FROM aux.sqlite_master", 0, 0, &zErrMsg);
- if( rc || zErrMsg ){
- cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb2);
- }
-
- if( zTab ){
- xDiff(zTab, out);
- }else{
- /* Handle tables one by one */
- pStmt = db_prepare(
- "SELECT name FROM main.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " UNION\n"
- "SELECT name FROM aux.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " ORDER BY name"
- );
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- xDiff((const char*)sqlite3_column_text(pStmt,0), out);
- }
- sqlite3_finalize(pStmt);
- }
-
- /* TBD: Handle trigger differences */
- /* TBD: Handle view differences */
- sqlite3_close(g.db);
- return 0;
-}
diff --git a/lib/libsqlite3/tool/stack_usage.tcl b/lib/libsqlite3/tool/stack_usage.tcl
deleted file mode 100644
index b3574f026e0..00000000000
--- a/lib/libsqlite3/tool/stack_usage.tcl
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/tclsh
-#
-# Parse the output of
-#
-# objdump -d sqlite3.o
-#
-# for x64 and generate a report showing:
-#
-# (1) Stack used by each function
-# (2) Recursion paths and their aggregate stack depth
-#
-set getStack 0
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {^[0-9a-f]+ <([^>]+)>:\s*$} $line all procname]} {
- set curfunc $procname
- set root($curfunc) 1
- set calls($curfunc) {}
- set calledby($curfunc) {}
- set recursive($curfunc) {}
- set stkdepth($curfunc) 0
- set getStack 1
- continue
- }
- if {[regexp {callq? +[0-9a-z]+ <([^>]+)>} $line all other]} {
- set key [list $curfunc $other]
- set callpair($key) 1
- unset -nocomplain root($curfunc)
- continue
- }
- if {[regexp {sub +\$(0x[0-9a-z]+),%[er]sp} $line all xdepth]} {
- if {$getStack} {
- scan $xdepth %x depth
- set stkdepth($curfunc) $depth
- set getStack 0
- }
- continue
- }
-}
-
-puts "****************** Stack Usage By Function ********************"
-set sdlist {}
-foreach f [array names stkdepth] {
- lappend sdlist [list $stkdepth($f) $f]
-}
-foreach sd [lsort -integer -decr -index 0 $sdlist] {
- foreach {depth fname} $sd break
- puts [format {%6d %s} $depth $fname]
-}
-
-puts "****************** Stack Usage By Recursion *******************"
-foreach key [array names callpair] {
- foreach {from to} $key break
- lappend calls($from) $to
- # lappend calledby($to) $from
-}
-proc all_descendents {root} {
- global calls recursive
- set todo($root) $root
- set go 1
- while {$go} {
- set go 0
- foreach f [array names todo] {
- set path $todo($f)
- unset todo($f)
- if {![info exists calls($f)]} continue
- foreach x $calls($f) {
- if {$x==$root} {
- lappend recursive($root) [concat $path $root]
- } elseif {![info exists d($x)]} {
- set go 1
- set todo($x) [concat $path $x]
- set d($x) 1
- }
- }
- }
- }
- return [array names d]
-}
-set pathlist {}
-foreach f [array names recursive] {
- all_descendents $f
- foreach m $recursive($f) {
- set depth 0
- foreach b [lrange $m 0 end-1] {
- set depth [expr {$depth+$stkdepth($b)}]
- }
- lappend pathlist [list $depth $m]
- }
-}
-foreach path [lsort -integer -decr -index 0 $pathlist] {
- foreach {depth m} $path break
- set first [lindex $m 0]
- puts [format {%6d %s %d} $depth $first $stkdepth($first)]
- foreach b [lrange $m 1 end] {
- puts " $b $stkdepth($b)"
- }
-}
diff --git a/lib/libsqlite3/tool/symbols-mingw.sh b/lib/libsqlite3/tool/symbols-mingw.sh
deleted file mode 100644
index bf93eec7c6b..00000000000
--- a/lib/libsqlite3/tool/symbols-mingw.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-#
-# Run this script in a directory that contains a valid SQLite makefile in
-# order to verify that unintentionally exported symbols.
-#
-make sqlite3.c
-
-echo '****** Exported symbols from a build including RTREE && FTS4 ******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep " [TD] "
-
-echo '****** Surplus symbols from a build including RTREE & FTS4 ******'
-nm sqlite3.o | grep " [TD] " | grep -v " .*sqlite3_"
-
-echo '****** Dependencies of the core. No extensions. No OS interface *******'
-gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-nm sqlite3.o | grep " U "
-
-echo '****** Dependencies including RTREE & FTS4 *******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep " U "
diff --git a/lib/libsqlite3/tool/symbols.sh b/lib/libsqlite3/tool/symbols.sh
deleted file mode 100644
index befffce5c4c..00000000000
--- a/lib/libsqlite3/tool/symbols.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-#
-# Run this script in a directory that contains a valid SQLite makefile in
-# order to verify that unintentionally exported symbols.
-#
-make sqlite3.c
-
-echo '****** Exported symbols from a build including RTREE, FTS4 & ICU ******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_ENABLE_ICU \
- sqlite3.c
-nm sqlite3.o | grep ' [TD] ' | sort -k 3
-
-echo '****** Surplus symbols from a build including RTREE, FTS4 & ICU ******'
-nm sqlite3.o | grep ' [TD] ' | grep -v ' .*sqlite3_'
-
-echo '****** Dependencies of the core. No extensions. No OS interface *******'
-gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-nm sqlite3.o | grep ' U ' | sort -k 3
-
-echo '****** Dependencies including RTREE & FTS4 *******'
-gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
- -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
- -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
- sqlite3.c
-nm sqlite3.o | grep ' U ' | sort -k 3
diff --git a/lib/libsqlite3/tool/tostr.awk b/lib/libsqlite3/tool/tostr.awk
deleted file mode 100644
index 83c6cc1a50a..00000000000
--- a/lib/libsqlite3/tool/tostr.awk
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/awk
-#
-# Convert input text into a C string
-#
-{
- gsub(/\\/,"\\\\");
- gsub(/\"/,"\\\"");
- print "\"" $0 "\\n\"";
-}
diff --git a/lib/libsqlite3/tool/varint.c b/lib/libsqlite3/tool/varint.c
deleted file mode 100644
index f4a51118b4d..00000000000
--- a/lib/libsqlite3/tool/varint.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** A utility program to translate SQLite varints into decimal and decimal
-** integers into varints.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 i64;
- typedef unsigned __int64 u64;
-#else
- typedef long long int i64;
- typedef unsigned long long int u64;
-#endif
-
-static int hexValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-static char toHex(unsigned char c){
- return "0123456789abcdef"[c&0xf];
-}
-
-static int putVarint(unsigned char *p, u64 v){
- int i, j, n;
- unsigned char buf[10];
- if( v & (((u64)0xff000000)<<32) ){
- p[8] = (unsigned char)v;
- v >>= 8;
- for(i=7; i>=0; i--){
- p[i] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }
- return 9;
- }
- n = 0;
- do{
- buf[n++] = (unsigned char)((v & 0x7f) | 0x80);
- v >>= 7;
- }while( v!=0 );
- buf[0] &= 0x7f;
- for(i=0, j=n-1; j>=0; j--, i++){
- p[i] = buf[j];
- }
- return n;
-}
-
-
-int main(int argc, char **argv){
- int i;
- u64 x;
- u64 uX = 0;
- i64 iX;
- int n;
- unsigned char zHex[20];
-
- if( argc==1 ){
- fprintf(stderr,
- "Usage:\n"
- " %s HH HH HH ... Convert varint to decimal\n"
- " %s DDDDD Convert decimal to varint\n"
- " Add '+' or '-' before DDDDD to disambiguate.\n",
- argv[0], argv[0]);
- exit(1);
- }
- if( argc>2
- || (strlen(argv[1])==2 && hexValue(argv[1][0])>=0 && hexValue(argv[1][1])>=0)
- ){
- /* Hex to decimal */
- for(i=1; i<argc && i<9; i++){
- if( strlen(argv[i])!=2 ){
- fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
- exit(1);
- }
- x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
- uX = (uX<<7) + (x&0x7f);
- if( (x&0x80)==0 ) break;
- }
- if( i==9 && i<argc ){
- if( strlen(argv[i])!=2 ){
- fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
- exit(1);
- }
- x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
- uX = (uX<<8) + x;
- }
- i++;
- if( i<argc ){
- fprintf(stderr, "Extra arguments: %s...\n", argv[i]);
- exit(1);
- }
- }else{
- char *z = argv[1];
- int sign = 1;
- if( z[0]=='+' ) z++;
- else if( z[0]=='-' ){ z++; sign = -1; }
- uX = 0;
- while( z[0] ){
- if( z[0]<'0' || z[0]>'9' ){
- fprintf(stderr, "Not a decimal number: %s", argv[1]);
- exit(1);
- }
- uX = uX*10 + z[0] - '0';
- z++;
- }
- if( sign<0 ){
- memcpy(&iX, &uX, 8);
- iX = -iX;
- memcpy(&uX, &iX, 8);
- }
- }
- n = putVarint(zHex, uX);
- printf("%lld =", (i64)uX);
- for(i=0; i<n; i++){
- printf(" %c%c", toHex(zHex[i]>>4), toHex(zHex[i]&0x0f));
- }
- printf("\n");
- return 0;
-}
diff --git a/lib/libsqlite3/tool/vdbe-compress.tcl b/lib/libsqlite3/tool/vdbe-compress.tcl
deleted file mode 100644
index 9477f4afe62..00000000000
--- a/lib/libsqlite3/tool/vdbe-compress.tcl
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/tcl
-#
-# This script makes modifications to the vdbe.c source file which reduce
-# the amount of stack space required by the sqlite3VdbeExec() routine.
-#
-# The modifications performed by this script are optional. The vdbe.c
-# source file will compile correctly with and without the modifications
-# performed by this script. And all routines within vdbe.c will compute
-# the same result. The modifications made by this script merely help
-# the C compiler to generate code for sqlite3VdbeExec() that uses less
-# stack space.
-#
-# Script usage:
-#
-# mv vdbe.c vdbe.c.template
-# tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c
-#
-# Modifications made:
-#
-# All modifications are within the sqlite3VdbeExec() function. The
-# modifications seek to reduce the amount of stack space allocated by
-# this routine by moving local variable declarations out of individual
-# opcode implementations and into a single large union. The union contains
-# a separate structure for each opcode and that structure contains the
-# local variables used by that opcode. In this way, the total amount
-# of stack space required by sqlite3VdbeExec() is reduced from the
-# sum of all local variables to the maximum of the local variable space
-# required for any single opcode.
-#
-# In order to be recognized by this script, local variables must appear
-# on the first line after the open curly-brace that begins a new opcode
-# implementation. Local variables must not have initializers, though they
-# may be commented.
-#
-# The union definition is inserted in place of a special marker comment
-# in the preamble to the sqlite3VdbeExec() implementation.
-#
-#############################################################################
-#
-set beforeUnion {} ;# C code before union
-set unionDef {} ;# C code of the union
-set afterUnion {} ;# C code after the union
-set sCtr 0 ;# Context counter
-
-# If the SQLITE_SMALL_STACK compile-time option is missing, then
-# this transformation becomes a no-op.
-#
-if {![regexp {SQLITE_SMALL_STACK} $argv]} {
- while {![eof stdin]} {
- puts [gets stdin]
- }
- exit
-}
-
-# Read program text up to the spot where the union should be
-# inserted.
-#
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {INSERT STACK UNION HERE} $line]} break
- append beforeUnion $line\n
-}
-
-# Process the remaining text. Build up the union definition as we go.
-#
-set vlist {}
-set seenDecl 0
-set namechars {abcdefghijklmnopqrstuvwxyz}
-set nnc [string length $namechars]
-while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
- append afterUnion $line\n
- set vlist {}
- while {![eof stdin]} {
- set line [gets stdin]
- if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \
- all constKeyword vname notused1]} {
- if {!$seenDecl} {
- set sname {}
- append sname [string index $namechars [expr {$sCtr/$nnc}]]
- append sname [string index $namechars [expr {$sCtr%$nnc}]]
- incr sCtr
- append unionDef " struct ${operator}_stack_vars \173\n"
- append afterUnion \
- "#if 0 /* local variables moved into u.$sname */\n"
- set seenDecl 1
- }
- append unionDef " $line\n"
- append afterUnion $line\n
- lappend vlist $vname
- } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} {
- append unionDef "$line\n"
- append afterUnion $line\n
- } else {
- break
- }
- }
- if {$seenDecl} {
- append unionDef " \175 $sname;\n"
- append afterUnion "#endif /* local variables moved into u.$sname */\n"
- }
- set seenDecl 0
- }
- if {[regexp "^\175" $line]} {
- append afterUnion $line\n
- set vlist {}
- } elseif {[llength $vlist]>0} {
- append line " "
- foreach v $vlist {
- regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
- regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
-
- # The expressions above fail to catch instance of variable "abc" in
- # expressions like (32>abc). The following expression makes those
- # substitutions.
- regsub -all "(\[^-\])>${v}(\\W)" $line "\\1>u.$sname.$v\\2" line
- }
- append afterUnion [string trimright $line]\n
- } elseif {$line=="" && [eof stdin]} {
- # no-op
- } else {
- append afterUnion $line\n
- }
-}
-
-# Output the resulting text.
-#
-puts -nonewline $beforeUnion
-puts " /********************************************************************"
-puts " ** Automatically generated code"
-puts " **"
-puts " ** The following union is automatically generated by the"
-puts " ** vdbe-compress.tcl script. The purpose of this union is to"
-puts " ** reduce the amount of stack space required by this function."
-puts " ** See comments in the vdbe-compress.tcl script for details."
-puts " */"
-puts " union vdbeExecUnion \173"
-puts -nonewline $unionDef
-puts " \175 u;"
-puts " /* End automatically generated code"
-puts " ********************************************************************/"
-puts -nonewline $afterUnion
diff --git a/lib/libsqlite3/tool/vdbe_profile.tcl b/lib/libsqlite3/tool/vdbe_profile.tcl
deleted file mode 100644
index fb1f955391a..00000000000
--- a/lib/libsqlite3/tool/vdbe_profile.tcl
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/tclsh
-#
-# Run this script in the same directory as the "vdbe_profile.out" file.
-# This script summarizes the results contained in that file.
-#
-if {![file readable vdbe_profile.out]} {
- error "run this script in the same directory as the vdbe_profile.out file"
-}
-set in [open vdbe_profile.out r]
-set stmt {}
-set allstmt {}
-while {![eof $in]} {
- set line [gets $in]
- if {$line==""} continue
- if {[regexp {^---- } $line]} {
- set stmt [lindex $line 1]
- if {[info exists cnt($stmt)]} {
- incr cnt($stmt)
- set firsttime 0
- } else {
- set cnt($stmt) 1
- set sql($stmt) {}
- set firsttime 1
- lappend allstmt $stmt
- }
- continue;
- }
- if {[regexp {^-- } $line]} {
- if {$firsttime} {
- append sql($stmt) [string range $line 3 end]\n
- }
- continue
- }
- if {![regexp {^ *\d+ *\d+ *\d+ *\d+ ([A-Z].*)} $line all detail]} continue
- set c [lindex $line 0]
- set t [lindex $line 1]
- set addr [lindex $line 3]
- set op [lindex $line 4]
- if {[info exists opcnt($op)]} {
- incr opcnt($op) $c
- incr opcycle($op) $t
- } else {
- set opcnt($op) $c
- set opcycle($op) $t
- }
- if {[info exists stat($stmt,$addr)]} {
- foreach {cx tx detail} $stat($stmt,$addr) break
- incr cx $c
- incr tx $t
- set stat($stmt,$addr) [list $cx $tx $detail]
- } else {
- set stat($stmt,$addr) [list $c $t $detail]
- }
-}
-close $in
-
-foreach stmt $allstmt {
- puts "********************************************************************"
- puts [string trim $sql($stmt)]
- puts "Execution count: $cnt($stmt)"
- for {set i 0} {[info exists stat($stmt,$i)]} {incr i} {
- foreach {cx tx detail} $stat($stmt,$i) break
- if {$cx==0} {
- set ax 0
- } else {
- set ax [expr {$tx/$cx}]
- }
- puts [format {%8d %12d %12d %4d %s} $cx $tx $ax $i $detail]
- }
-}
-puts "********************************************************************"
-puts "OPCODES:"
-foreach op [lsort [array names opcnt]] {
- set cx $opcnt($op)
- set tx $opcycle($op)
- if {$cx==0} {
- set ax 0
- } else {
- set ax [expr {$tx/$cx}]
- }
- puts [format {%8d %12d %12d %s} $cx $tx $ax $op]
-}
diff --git a/lib/libsqlite3/tool/warnings-clang.sh b/lib/libsqlite3/tool/warnings-clang.sh
deleted file mode 100644
index 7a0aa4bce7f..00000000000
--- a/lib/libsqlite3/tool/warnings-clang.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#/bin/sh
-#
-# Run this script in a directory with a working makefile to check for
-# compiler warnings in SQLite.
-#
-rm -f sqlite3.c
-make sqlite3.c
-echo '************* FTS4 and RTREE ****************'
-scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_DEBUG -DSQLITE_ENABLE_STAT3 sqlite3.c 2>&1 | grep -v 'ANALYZE:'
-echo '********** ENABLE_STAT3. THREADSAFE=0 *******'
-scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
- -DSQLITE_DEBUG \
- sqlite3.c ../sqlite/src/shell.c -ldl 2>&1 | grep -v 'ANALYZE:'
diff --git a/lib/libsqlite3/tool/warnings.sh b/lib/libsqlite3/tool/warnings.sh
deleted file mode 100644
index d69cbaf5dbc..00000000000
--- a/lib/libsqlite3/tool/warnings.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#/bin/sh
-#
-# Run this script in a directory with a working makefile to check for
-# compiler warnings in SQLite.
-#
-rm -f sqlite3.c
-make sqlite3.c
-echo '********** No optimizations. Includes FTS4 and RTREE *********'
-gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- sqlite3.c
-echo '********** Android configuration ******************************'
-gcc -c \
- -DHAVE_USLEEP=1 \
- -DSQLITE_HAVE_ISNAN \
- -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
- -DSQLITE_THREADSAFE=2 \
- -DSQLITE_TEMP_STORE=3 \
- -DSQLITE_POWERSAFE_OVERWRITE=1 \
- -DSQLITE_DEFAULT_FILE_FORMAT=4 \
- -DSQLITE_DEFAULT_AUTOVACUUM=1 \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
- -DSQLITE_ENABLE_FTS3 \
- -DSQLITE_ENABLE_FTS3_BACKWARDS \
- -DSQLITE_ENABLE_FTS4 \
- -DSQLITE_OMIT_BUILTIN_TEST \
- -DSQLITE_OMIT_COMPILEOPTION_DIAGS \
- -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
- -DSQLITE_ENABLE_ICU \
- -DUSE_PREAD64 \
- -Wshadow -Wall -Wextra \
- -Os sqlite3.c shell.c
-echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
-gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
- -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
- sqlite3.c
-echo '********** Optimized -O3. Includes FTS4 and RTREE ************'
-gcc -O3 -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
- sqlite3.c
diff --git a/lib/libsqlite3/tool/win/sqlite.vsix b/lib/libsqlite3/tool/win/sqlite.vsix
deleted file mode 100644
index 1450011266b..00000000000
--- a/lib/libsqlite3/tool/win/sqlite.vsix
+++ /dev/null
Binary files differ