Fossil SCM

Merge trunk into branch "loongarch"

js 2024-07-21 16:22 UTC loongarch merge
Commit 116262e4a6af99f39c66544789adff6113651aa3b93631fe6056138f73691fd8
132 files changed +1 -1 +24 -19 +10 +1 -2 +8 -8 +3 -3 +5 -4 +1 -1 +1 -1 +1 -1 +3 -3 +2 -2 +2 -2 +1 -1 +1 -1 +1 -1 +16 -2 +4 -4 +1 -1 +16 -5 +2 -2 +1 -1 +4 -4 +81 -68 +4 -4 +1 -1 +4 -4 +1 -1 +4 -4 +1 -1 +4 -4 +1 -1 +4 -4 +1 -1 +36 -11 +33 -2 +2 -2 +1 -1 +2 -6 +6 -6 +1 -1 +3 -3 +2 -2 +1 -1 +1 -1 +3 -3 +5 -5 +13 -12 +16 -16 +2 -2 +17 -3 +2 -18 +4 -4 +1 -9 +1 -9 +1 -9 +3 -3 +11 -11 +100 -100 +3 -24 +2590 -1030 +97 -23 +6 -5 +384 -385 +423 -157 +2876 -1845 +78 -25 +4 -2 +1 -1 +18 +2 -8 +13 -6 +3 -3 +41 -14 +223 -86 +142 -20 +13 -1 +2 -1 +1 -1 +5 -4 +2 +1 -1 +79 -1 +2 -2 +1 -1 +396 -53 +18 -9 +62 -14 +33 +13 -1 +4 -1 -6 +9 -26 +44 -14 +1 +73 -18 +10 -3 +5 +2 -1 +47 -13 +69 +9 +5 -2 +8 -3 +50 -25 +7 +64 -24 +9 -6 +56 -1 +11 -1 +1 -2 +1 -1 +16 -15 +1 +47 -47 +1 +2 +53 -14 +104 +1 -1 +3 -3 +3 -3 +64 -68 +14 -2 +4 -4 +1 +1 +23 +16 +9 -7
~ VERSION ~ compat/zlib/CMakeLists.txt ~ compat/zlib/ChangeLog ~ compat/zlib/FAQ ~ compat/zlib/Makefile.in ~ compat/zlib/README ~ compat/zlib/configure ~ compat/zlib/contrib/delphi/ZLib.pas ~ compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs ~ compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs ~ compat/zlib/contrib/infback9/inftree9.c ~ compat/zlib/contrib/infback9/inftree9.h ~ compat/zlib/contrib/iostream3/zfstream.h ~ compat/zlib/contrib/minizip/Makefile ~ compat/zlib/contrib/minizip/configure.ac ~ compat/zlib/contrib/minizip/ioapi.h ~ compat/zlib/contrib/minizip/miniunz.c ~ compat/zlib/contrib/minizip/unzip.c ~ compat/zlib/contrib/minizip/unzip.h ~ compat/zlib/contrib/minizip/zip.c ~ compat/zlib/contrib/minizip/zip.h ~ compat/zlib/contrib/pascal/zlibpas.pas ~ compat/zlib/contrib/puff/puff.c ~ compat/zlib/contrib/vstudio/readme.txt ~ compat/zlib/contrib/vstudio/vc10/zlib.rc ~ compat/zlib/contrib/vstudio/vc10/zlibvc.def ~ compat/zlib/contrib/vstudio/vc11/zlib.rc ~ compat/zlib/contrib/vstudio/vc11/zlibvc.def ~ compat/zlib/contrib/vstudio/vc12/zlib.rc ~ compat/zlib/contrib/vstudio/vc12/zlibvc.def ~ compat/zlib/contrib/vstudio/vc14/zlib.rc ~ compat/zlib/contrib/vstudio/vc14/zlibvc.def ~ compat/zlib/contrib/vstudio/vc9/zlib.rc ~ compat/zlib/contrib/vstudio/vc9/zlibvc.def ~ compat/zlib/deflate.c ~ compat/zlib/deflate.h ~ compat/zlib/examples/gzlog.c ~ compat/zlib/examples/zran.c ~ compat/zlib/gzguts.h ~ compat/zlib/gzlib.c ~ compat/zlib/inflate.c ~ compat/zlib/inftrees.c ~ compat/zlib/inftrees.h ~ compat/zlib/old/visual-basic.txt ~ compat/zlib/os400/README400 ~ compat/zlib/os400/zlib.inc ~ compat/zlib/qnx/package.qpg ~ compat/zlib/test/example.c ~ compat/zlib/test/minigzip.c ~ compat/zlib/treebuild.xml ~ compat/zlib/trees.c ~ compat/zlib/win32/DLL_FAQ.txt ~ compat/zlib/win32/README-WIN32.txt ~ compat/zlib/zconf.h ~ compat/zlib/zconf.h.cmakein ~ compat/zlib/zconf.h.in ~ compat/zlib/zlib.3 ~ compat/zlib/zlib.3.pdf ~ compat/zlib/zlib.h ~ compat/zlib/zlib.map ~ compat/zlib/zutil.h ~ extsrc/linenoise.c ~ extsrc/linenoise.h ~ extsrc/pikchr.c ~ extsrc/pikchr.js ~ extsrc/pikchr.wasm ~ extsrc/shell.c ~ extsrc/sqlite3.c ~ extsrc/sqlite3.h ~ src/add.c ~ src/alerts.c ~ src/bisect.c ~ src/branch.c ~ src/browse.c ~ src/bundle.c ~ src/cgi.c ~ src/chat.c ~ src/checkin.c ~ src/clone.c ~ src/db.c ~ src/descendants.c ~ src/dispatch.c ~ src/doc.c ~ src/export.c ~ src/file.c ~ src/fossil.dom.js ~ src/fossil.fetch.js ~ src/fossil.page.chat.js ~ src/graph.c ~ src/http.c ~ src/http_ssl.c ~ src/import.c ~ src/info.c ~ src/json_branch.c ~ src/login.c ~ src/main.c ~ src/main.mk ~ src/merge.c ~ src/path.c ~ src/rebuild.c ~ src/regexp.c ~ src/search.c ~ src/security_audit.c ~ src/setup.c ~ src/stash.c ~ src/style.c ~ src/style.chat.css ~ src/style.uvlist.css ~ src/tag.c ~ src/timeline.c ~ src/unversioned.c ~ src/wiki.c ~ test/amend.test ~ test/merge5.test ~ test/stash.test ~ test/tester.tcl ~ test/utf.test ~ win/Makefile.mingw ~ win/Makefile.msc ~ www/changes.wiki ~ www/colordiff.md ~ www/embeddeddoc.wiki ~ www/faq.tcl ~ www/faq.wiki ~ www/gitusers.md ~ www/hints.wiki ~ www/index.wiki ~ www/mkindex.tcl ~ www/permutedindex.html ~ www/server/any/cgi.md ~ www/ssl.wiki ~ www/unvers.wiki
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-2.24
1
+2.25
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.24
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.25
2
--- compat/zlib/CMakeLists.txt
+++ compat/zlib/CMakeLists.txt
@@ -1,11 +1,13 @@
11
cmake_minimum_required(VERSION 2.4.4...3.15.0)
22
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
33
44
project(zlib C)
55
6
-set(VERSION "1.3")
6
+set(VERSION "1.3.1")
7
+
8
+option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)
79
810
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
911
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
1012
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
1113
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
@@ -146,11 +148,13 @@
146148
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
147149
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
148150
endif(MINGW)
149151
150152
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
153
+target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
151154
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
155
+target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
152156
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
153157
set_target_properties(zlib PROPERTIES SOVERSION 1)
154158
155159
if(NOT CYGWIN)
156160
# This property causes shared libraries on Linux to have the full version
@@ -164,11 +168,11 @@
164168
endif()
165169
166170
if(UNIX)
167171
# On unix-like platforms the library is almost always called libz
168172
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
169
- if(NOT APPLE)
173
+ if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX))
170174
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
171175
endif()
172176
elseif(BUILD_SHARED_LIBS AND WIN32)
173177
# Creates zlib1.dll when building shared library version
174178
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
@@ -191,23 +195,24 @@
191195
endif()
192196
193197
#============================================================================
194198
# Example binaries
195199
#============================================================================
196
-
197
-add_executable(example test/example.c)
198
-target_link_libraries(example zlib)
199
-add_test(example example)
200
-
201
-add_executable(minigzip test/minigzip.c)
202
-target_link_libraries(minigzip zlib)
203
-
204
-if(HAVE_OFF64_T)
205
- add_executable(example64 test/example.c)
206
- target_link_libraries(example64 zlib)
207
- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
208
- add_test(example64 example64)
209
-
210
- add_executable(minigzip64 test/minigzip.c)
211
- target_link_libraries(minigzip64 zlib)
212
- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
200
+if(ZLIB_BUILD_EXAMPLES)
201
+ add_executable(example test/example.c)
202
+ target_link_libraries(example zlib)
203
+ add_test(example example)
204
+
205
+ add_executable(minigzip test/minigzip.c)
206
+ target_link_libraries(minigzip zlib)
207
+
208
+ if(HAVE_OFF64_T)
209
+ add_executable(example64 test/example.c)
210
+ target_link_libraries(example64 zlib)
211
+ set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
212
+ add_test(example64 example64)
213
+
214
+ add_executable(minigzip64 test/minigzip.c)
215
+ target_link_libraries(minigzip64 zlib)
216
+ set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
217
+ endif()
213218
endif()
214219
--- compat/zlib/CMakeLists.txt
+++ compat/zlib/CMakeLists.txt
@@ -1,11 +1,13 @@
1 cmake_minimum_required(VERSION 2.4.4...3.15.0)
2 set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
3
4 project(zlib C)
5
6 set(VERSION "1.3")
 
 
7
8 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
9 set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
10 set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
11 set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
@@ -146,11 +148,13 @@
146 -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
147 set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
148 endif(MINGW)
149
150 add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
 
151 add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
 
152 set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
153 set_target_properties(zlib PROPERTIES SOVERSION 1)
154
155 if(NOT CYGWIN)
156 # This property causes shared libraries on Linux to have the full version
@@ -164,11 +168,11 @@
164 endif()
165
166 if(UNIX)
167 # On unix-like platforms the library is almost always called libz
168 set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
169 if(NOT APPLE)
170 set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
171 endif()
172 elseif(BUILD_SHARED_LIBS AND WIN32)
173 # Creates zlib1.dll when building shared library version
174 set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
@@ -191,23 +195,24 @@
191 endif()
192
193 #============================================================================
194 # Example binaries
195 #============================================================================
196
197 add_executable(example test/example.c)
198 target_link_libraries(example zlib)
199 add_test(example example)
200
201 add_executable(minigzip test/minigzip.c)
202 target_link_libraries(minigzip zlib)
203
204 if(HAVE_OFF64_T)
205 add_executable(example64 test/example.c)
206 target_link_libraries(example64 zlib)
207 set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
208 add_test(example64 example64)
209
210 add_executable(minigzip64 test/minigzip.c)
211 target_link_libraries(minigzip64 zlib)
212 set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
 
213 endif()
214
--- compat/zlib/CMakeLists.txt
+++ compat/zlib/CMakeLists.txt
@@ -1,11 +1,13 @@
1 cmake_minimum_required(VERSION 2.4.4...3.15.0)
2 set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
3
4 project(zlib C)
5
6 set(VERSION "1.3.1")
7
8 option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)
9
10 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
11 set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
12 set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
13 set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
@@ -146,11 +148,13 @@
148 -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
149 set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
150 endif(MINGW)
151
152 add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
153 target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
154 add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
155 target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
156 set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
157 set_target_properties(zlib PROPERTIES SOVERSION 1)
158
159 if(NOT CYGWIN)
160 # This property causes shared libraries on Linux to have the full version
@@ -164,11 +168,11 @@
168 endif()
169
170 if(UNIX)
171 # On unix-like platforms the library is almost always called libz
172 set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
173 if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX))
174 set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
175 endif()
176 elseif(BUILD_SHARED_LIBS AND WIN32)
177 # Creates zlib1.dll when building shared library version
178 set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
@@ -191,23 +195,24 @@
195 endif()
196
197 #============================================================================
198 # Example binaries
199 #============================================================================
200 if(ZLIB_BUILD_EXAMPLES)
201 add_executable(example test/example.c)
202 target_link_libraries(example zlib)
203 add_test(example example)
204
205 add_executable(minigzip test/minigzip.c)
206 target_link_libraries(minigzip zlib)
207
208 if(HAVE_OFF64_T)
209 add_executable(example64 test/example.c)
210 target_link_libraries(example64 zlib)
211 set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
212 add_test(example64 example64)
213
214 add_executable(minigzip64 test/minigzip.c)
215 target_link_libraries(minigzip64 zlib)
216 set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
217 endif()
218 endif()
219
--- compat/zlib/ChangeLog
+++ compat/zlib/ChangeLog
@@ -1,8 +1,18 @@
11
22
ChangeLog file for zlib
33
4
+Changes in 1.3.1 (22 Jan 2024)
5
+- Reject overflows of zip header fields in minizip
6
+- Fix bug in inflateSync() for data held in bit buffer
7
+- Add LIT_MEM define to use more memory for a small deflate speedup
8
+- Fix decision on the emission of Zip64 end records in minizip
9
+- Add bounds checking to ERR_MSG() macro, used by zError()
10
+- Neutralize zip file traversal attacks in miniunz
11
+- Fix a bug in ZLIB_DEBUG compiles in check_match()
12
+- Various portability and appearance improvements
13
+
414
Changes in 1.3 (18 Aug 2023)
515
- Remove K&R function definitions and zlib2ansi
616
- Fix bug in deflateBound() for level 0 and memLevel 9
717
- Fix bug when gzungetc() is used immediately after gzopen()
818
- Fix bug when using gzflush() with a very small buffer
919
--- compat/zlib/ChangeLog
+++ compat/zlib/ChangeLog
@@ -1,8 +1,18 @@
1
2 ChangeLog file for zlib
3
 
 
 
 
 
 
 
 
 
 
4 Changes in 1.3 (18 Aug 2023)
5 - Remove K&R function definitions and zlib2ansi
6 - Fix bug in deflateBound() for level 0 and memLevel 9
7 - Fix bug when gzungetc() is used immediately after gzopen()
8 - Fix bug when using gzflush() with a very small buffer
9
--- compat/zlib/ChangeLog
+++ compat/zlib/ChangeLog
@@ -1,8 +1,18 @@
1
2 ChangeLog file for zlib
3
4 Changes in 1.3.1 (22 Jan 2024)
5 - Reject overflows of zip header fields in minizip
6 - Fix bug in inflateSync() for data held in bit buffer
7 - Add LIT_MEM define to use more memory for a small deflate speedup
8 - Fix decision on the emission of Zip64 end records in minizip
9 - Add bounds checking to ERR_MSG() macro, used by zError()
10 - Neutralize zip file traversal attacks in miniunz
11 - Fix a bug in ZLIB_DEBUG compiles in check_match()
12 - Various portability and appearance improvements
13
14 Changes in 1.3 (18 Aug 2023)
15 - Remove K&R function definitions and zlib2ansi
16 - Fix bug in deflateBound() for level 0 and memLevel 9
17 - Fix bug when gzungetc() is used immediately after gzopen()
18 - Fix bug when using gzflush() with a very small buffer
19
+1 -2
--- compat/zlib/FAQ
+++ compat/zlib/FAQ
@@ -12,12 +12,11 @@
1212
Yes. zlib doesn't handle dates.
1313
1414
2. Where can I get a Windows DLL version?
1515
1616
The zlib sources can be compiled without change to produce a DLL. See the
17
- file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
18
- precompiled DLL are found in the zlib web site at http://zlib.net/ .
17
+ file win32/DLL_FAQ.txt in the zlib distribution.
1918
2019
3. Where can I get a Visual Basic interface to zlib?
2120
2221
See
2322
* http://marknelson.us/1997/01/01/zlib-engine/
2423
--- compat/zlib/FAQ
+++ compat/zlib/FAQ
@@ -12,12 +12,11 @@
12 Yes. zlib doesn't handle dates.
13
14 2. Where can I get a Windows DLL version?
15
16 The zlib sources can be compiled without change to produce a DLL. See the
17 file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
18 precompiled DLL are found in the zlib web site at http://zlib.net/ .
19
20 3. Where can I get a Visual Basic interface to zlib?
21
22 See
23 * http://marknelson.us/1997/01/01/zlib-engine/
24
--- compat/zlib/FAQ
+++ compat/zlib/FAQ
@@ -12,12 +12,11 @@
12 Yes. zlib doesn't handle dates.
13
14 2. Where can I get a Windows DLL version?
15
16 The zlib sources can be compiled without change to produce a DLL. See the
17 file win32/DLL_FAQ.txt in the zlib distribution.
 
18
19 3. Where can I get a Visual Basic interface to zlib?
20
21 See
22 * http://marknelson.us/1997/01/01/zlib-engine/
23
--- compat/zlib/Makefile.in
+++ compat/zlib/Makefile.in
@@ -1,7 +1,7 @@
11
# Makefile for zlib
2
-# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
2
+# Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
33
# For conditions of distribution and use, see copyright notice in zlib.h
44
55
# To compile and test, type:
66
# ./configure; make test
77
# Normally configure builds both a static and a shared library.
@@ -20,17 +20,17 @@
2020
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
2121
# -Wstrict-prototypes -Wmissing-prototypes
2222
2323
SFLAGS=-O
2424
LDFLAGS=
25
-TEST_LDFLAGS=$(LDFLAGS) -L. libz.a
25
+TEST_LIBS=-L. libz.a
2626
LDSHARED=$(CC)
2727
CPP=$(CC) -E
2828
2929
STATICLIB=libz.a
3030
SHAREDLIB=libz.so
31
-SHAREDLIBV=libz.so.1.3
31
+SHAREDLIBV=libz.so.1.3.1
3232
SHAREDLIBM=libz.so.1
3333
LIBS=$(STATICLIB) $(SHAREDLIBV)
3434
3535
AR=ar
3636
ARFLAGS=rc
@@ -280,26 +280,26 @@
280280
ln -s $@ $(SHAREDLIB)
281281
ln -s $@ $(SHAREDLIBM)
282282
-@rmdir objs
283283
284284
example$(EXE): example.o $(STATICLIB)
285
- $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
285
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS)
286286
287287
minigzip$(EXE): minigzip.o $(STATICLIB)
288
- $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
288
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS)
289289
290290
examplesh$(EXE): example.o $(SHAREDLIBV)
291291
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)
292292
293293
minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
294294
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)
295295
296296
example64$(EXE): example64.o $(STATICLIB)
297
- $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
297
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS)
298298
299299
minigzip64$(EXE): minigzip64.o $(STATICLIB)
300
- $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
300
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS)
301301
302302
install-libs: $(LIBS)
303303
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
304304
-@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
305305
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
@@ -358,11 +358,11 @@
358358
359359
zconf: $(SRCDIR)zconf.h.in
360360
cp -p $(SRCDIR)zconf.h.in zconf.h
361361
362362
minizip-test: static
363
- cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
363
+ cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
364364
365365
minizip-clean:
366366
cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; }
367367
368368
mostlyclean: clean
369369
--- compat/zlib/Makefile.in
+++ compat/zlib/Makefile.in
@@ -1,7 +1,7 @@
1 # Makefile for zlib
2 # Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
3 # For conditions of distribution and use, see copyright notice in zlib.h
4
5 # To compile and test, type:
6 # ./configure; make test
7 # Normally configure builds both a static and a shared library.
@@ -20,17 +20,17 @@
20 #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
21 # -Wstrict-prototypes -Wmissing-prototypes
22
23 SFLAGS=-O
24 LDFLAGS=
25 TEST_LDFLAGS=$(LDFLAGS) -L. libz.a
26 LDSHARED=$(CC)
27 CPP=$(CC) -E
28
29 STATICLIB=libz.a
30 SHAREDLIB=libz.so
31 SHAREDLIBV=libz.so.1.3
32 SHAREDLIBM=libz.so.1
33 LIBS=$(STATICLIB) $(SHAREDLIBV)
34
35 AR=ar
36 ARFLAGS=rc
@@ -280,26 +280,26 @@
280 ln -s $@ $(SHAREDLIB)
281 ln -s $@ $(SHAREDLIBM)
282 -@rmdir objs
283
284 example$(EXE): example.o $(STATICLIB)
285 $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
286
287 minigzip$(EXE): minigzip.o $(STATICLIB)
288 $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
289
290 examplesh$(EXE): example.o $(SHAREDLIBV)
291 $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)
292
293 minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
294 $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)
295
296 example64$(EXE): example64.o $(STATICLIB)
297 $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
298
299 minigzip64$(EXE): minigzip64.o $(STATICLIB)
300 $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
301
302 install-libs: $(LIBS)
303 -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
304 -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
305 -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
@@ -358,11 +358,11 @@
358
359 zconf: $(SRCDIR)zconf.h.in
360 cp -p $(SRCDIR)zconf.h.in zconf.h
361
362 minizip-test: static
363 cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
364
365 minizip-clean:
366 cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; }
367
368 mostlyclean: clean
369
--- compat/zlib/Makefile.in
+++ compat/zlib/Makefile.in
@@ -1,7 +1,7 @@
1 # Makefile for zlib
2 # Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
3 # For conditions of distribution and use, see copyright notice in zlib.h
4
5 # To compile and test, type:
6 # ./configure; make test
7 # Normally configure builds both a static and a shared library.
@@ -20,17 +20,17 @@
20 #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
21 # -Wstrict-prototypes -Wmissing-prototypes
22
23 SFLAGS=-O
24 LDFLAGS=
25 TEST_LIBS=-L. libz.a
26 LDSHARED=$(CC)
27 CPP=$(CC) -E
28
29 STATICLIB=libz.a
30 SHAREDLIB=libz.so
31 SHAREDLIBV=libz.so.1.3.1
32 SHAREDLIBM=libz.so.1
33 LIBS=$(STATICLIB) $(SHAREDLIBV)
34
35 AR=ar
36 ARFLAGS=rc
@@ -280,26 +280,26 @@
280 ln -s $@ $(SHAREDLIB)
281 ln -s $@ $(SHAREDLIBM)
282 -@rmdir objs
283
284 example$(EXE): example.o $(STATICLIB)
285 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS)
286
287 minigzip$(EXE): minigzip.o $(STATICLIB)
288 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS)
289
290 examplesh$(EXE): example.o $(SHAREDLIBV)
291 $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)
292
293 minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
294 $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)
295
296 example64$(EXE): example64.o $(STATICLIB)
297 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS)
298
299 minigzip64$(EXE): minigzip64.o $(STATICLIB)
300 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS)
301
302 install-libs: $(LIBS)
303 -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
304 -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
305 -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
@@ -358,11 +358,11 @@
358
359 zconf: $(SRCDIR)zconf.h.in
360 cp -p $(SRCDIR)zconf.h.in zconf.h
361
362 minizip-test: static
363 cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
364
365 minizip-clean:
366 cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; }
367
368 mostlyclean: clean
369
--- compat/zlib/README
+++ compat/zlib/README
@@ -1,8 +1,8 @@
11
ZLIB DATA COMPRESSION LIBRARY
22
3
-zlib 1.3 is a general purpose data compression library. All the code is
3
+zlib 1.3.1 is a general purpose data compression library. All the code is
44
thread safe. The data format used by the zlib library is described by RFCs
55
(Request for Comments) 1950 to 1952 in the files
66
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
77
rfc1952 (gzip format).
88
@@ -29,11 +29,11 @@
2929
3030
Mark Nelson <[email protected]> wrote an article about zlib for the Jan. 1997
3131
issue of Dr. Dobb's Journal; a copy of the article is available at
3232
https://marknelson.us/posts/1997/01/01/zlib-engine.html .
3333
34
-The changes made in version 1.3 are documented in the file ChangeLog.
34
+The changes made in version 1.3.1 are documented in the file ChangeLog.
3535
3636
Unsupported third party contributions are provided in directory contrib/ .
3737
3838
zlib is available in Java using the java.util.zip package. Follow the API
3939
Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .
@@ -81,11 +81,11 @@
8181
people who reported problems and suggested various improvements in zlib; they
8282
are too numerous to cite here.
8383
8484
Copyright notice:
8585
86
- (C) 1995-2023 Jean-loup Gailly and Mark Adler
86
+ (C) 1995-2024 Jean-loup Gailly and Mark Adler
8787
8888
This software is provided 'as-is', without any express or implied
8989
warranty. In no event will the authors be held liable for any damages
9090
arising from the use of this software.
9191
9292
--- compat/zlib/README
+++ compat/zlib/README
@@ -1,8 +1,8 @@
1 ZLIB DATA COMPRESSION LIBRARY
2
3 zlib 1.3 is a general purpose data compression library. All the code is
4 thread safe. The data format used by the zlib library is described by RFCs
5 (Request for Comments) 1950 to 1952 in the files
6 http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
7 rfc1952 (gzip format).
8
@@ -29,11 +29,11 @@
29
30 Mark Nelson <[email protected]> wrote an article about zlib for the Jan. 1997
31 issue of Dr. Dobb's Journal; a copy of the article is available at
32 https://marknelson.us/posts/1997/01/01/zlib-engine.html .
33
34 The changes made in version 1.3 are documented in the file ChangeLog.
35
36 Unsupported third party contributions are provided in directory contrib/ .
37
38 zlib is available in Java using the java.util.zip package. Follow the API
39 Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .
@@ -81,11 +81,11 @@
81 people who reported problems and suggested various improvements in zlib; they
82 are too numerous to cite here.
83
84 Copyright notice:
85
86 (C) 1995-2023 Jean-loup Gailly and Mark Adler
87
88 This software is provided 'as-is', without any express or implied
89 warranty. In no event will the authors be held liable for any damages
90 arising from the use of this software.
91
92
--- compat/zlib/README
+++ compat/zlib/README
@@ -1,8 +1,8 @@
1 ZLIB DATA COMPRESSION LIBRARY
2
3 zlib 1.3.1 is a general purpose data compression library. All the code is
4 thread safe. The data format used by the zlib library is described by RFCs
5 (Request for Comments) 1950 to 1952 in the files
6 http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
7 rfc1952 (gzip format).
8
@@ -29,11 +29,11 @@
29
30 Mark Nelson <[email protected]> wrote an article about zlib for the Jan. 1997
31 issue of Dr. Dobb's Journal; a copy of the article is available at
32 https://marknelson.us/posts/1997/01/01/zlib-engine.html .
33
34 The changes made in version 1.3.1 are documented in the file ChangeLog.
35
36 Unsupported third party contributions are provided in directory contrib/ .
37
38 zlib is available in Java using the java.util.zip package. Follow the API
39 Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .
@@ -81,11 +81,11 @@
81 people who reported problems and suggested various improvements in zlib; they
82 are too numerous to cite here.
83
84 Copyright notice:
85
86 (C) 1995-2024 Jean-loup Gailly and Mark Adler
87
88 This software is provided 'as-is', without any express or implied
89 warranty. In no event will the authors be held liable for any damages
90 arising from the use of this software.
91
92
--- compat/zlib/configure
+++ compat/zlib/configure
@@ -23,11 +23,11 @@
2323
if test $SRCDIR = "."; then
2424
ZINC=""
2525
ZINCOUT="-I."
2626
SRCDIR=""
2727
else
28
- ZINC='-include zconf.h'
28
+ ZINC='-I. -include zconf.h'
2929
ZINCOUT='-I. -I$(SRCDIR)'
3030
SRCDIR="$SRCDIR/"
3131
fi
3232
3333
# set command prefix for cross-compilation
@@ -42,11 +42,12 @@
4242
# destination name for static library
4343
STATICLIB=libz.a
4444
4545
# extract zlib version numbers from zlib.h
4646
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
47
-VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
47
+VER3=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\(\\.[0-9]\{1,\}\)\{1,2\}\).*/\1/p'`
48
+VER1=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\)\\..*/\1/p'`
4849
4950
# establish commands for library building
5051
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
5152
AR=${AR-"${CROSS_PREFIX}ar"}
5253
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
@@ -261,11 +262,11 @@
261262
Darwin* | darwin* | *-darwin*)
262263
shared_ext='.dylib'
263264
SHAREDLIB=libz$shared_ext
264265
SHAREDLIBV=libz.$VER$shared_ext
265266
SHAREDLIBM=libz.$VER1$shared_ext
266
- LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"}
267
+ LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
267268
if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then
268269
AR="${CROSS_PREFIX}libtool"
269270
elif libtool -V 2>&1 | grep Apple > /dev/null; then
270271
AR="libtool"
271272
else
@@ -439,11 +440,11 @@
439440
int hello() {return getchar();}
440441
EOF
441442
if test $shared -eq 1; then
442443
echo Checking for shared library support... | tee -a configure.log
443444
# we must test in two steps (cc then ld), required at least on SunOS 4.x
444
- if try $CC -w -c $SFLAGS $test.c &&
445
+ if try $CC -c $SFLAGS $test.c &&
445446
try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
446447
echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
447448
elif test -z "$old_cc" -a -z "$old_cflags"; then
448449
echo No shared library support. | tee -a configure.log
449450
shared=0;
450451
--- compat/zlib/configure
+++ compat/zlib/configure
@@ -23,11 +23,11 @@
23 if test $SRCDIR = "."; then
24 ZINC=""
25 ZINCOUT="-I."
26 SRCDIR=""
27 else
28 ZINC='-include zconf.h'
29 ZINCOUT='-I. -I$(SRCDIR)'
30 SRCDIR="$SRCDIR/"
31 fi
32
33 # set command prefix for cross-compilation
@@ -42,11 +42,12 @@
42 # destination name for static library
43 STATICLIB=libz.a
44
45 # extract zlib version numbers from zlib.h
46 VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
47 VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
 
48
49 # establish commands for library building
50 if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
51 AR=${AR-"${CROSS_PREFIX}ar"}
52 test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
@@ -261,11 +262,11 @@
261 Darwin* | darwin* | *-darwin*)
262 shared_ext='.dylib'
263 SHAREDLIB=libz$shared_ext
264 SHAREDLIBV=libz.$VER$shared_ext
265 SHAREDLIBM=libz.$VER1$shared_ext
266 LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"}
267 if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then
268 AR="${CROSS_PREFIX}libtool"
269 elif libtool -V 2>&1 | grep Apple > /dev/null; then
270 AR="libtool"
271 else
@@ -439,11 +440,11 @@
439 int hello() {return getchar();}
440 EOF
441 if test $shared -eq 1; then
442 echo Checking for shared library support... | tee -a configure.log
443 # we must test in two steps (cc then ld), required at least on SunOS 4.x
444 if try $CC -w -c $SFLAGS $test.c &&
445 try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
446 echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
447 elif test -z "$old_cc" -a -z "$old_cflags"; then
448 echo No shared library support. | tee -a configure.log
449 shared=0;
450
--- compat/zlib/configure
+++ compat/zlib/configure
@@ -23,11 +23,11 @@
23 if test $SRCDIR = "."; then
24 ZINC=""
25 ZINCOUT="-I."
26 SRCDIR=""
27 else
28 ZINC='-I. -include zconf.h'
29 ZINCOUT='-I. -I$(SRCDIR)'
30 SRCDIR="$SRCDIR/"
31 fi
32
33 # set command prefix for cross-compilation
@@ -42,11 +42,12 @@
42 # destination name for static library
43 STATICLIB=libz.a
44
45 # extract zlib version numbers from zlib.h
46 VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
47 VER3=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\(\\.[0-9]\{1,\}\)\{1,2\}\).*/\1/p'`
48 VER1=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\)\\..*/\1/p'`
49
50 # establish commands for library building
51 if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
52 AR=${AR-"${CROSS_PREFIX}ar"}
53 test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
@@ -261,11 +262,11 @@
262 Darwin* | darwin* | *-darwin*)
263 shared_ext='.dylib'
264 SHAREDLIB=libz$shared_ext
265 SHAREDLIBV=libz.$VER$shared_ext
266 SHAREDLIBM=libz.$VER1$shared_ext
267 LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
268 if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then
269 AR="${CROSS_PREFIX}libtool"
270 elif libtool -V 2>&1 | grep Apple > /dev/null; then
271 AR="libtool"
272 else
@@ -439,11 +440,11 @@
440 int hello() {return getchar();}
441 EOF
442 if test $shared -eq 1; then
443 echo Checking for shared library support... | tee -a configure.log
444 # we must test in two steps (cc then ld), required at least on SunOS 4.x
445 if try $CC -c $SFLAGS $test.c &&
446 try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
447 echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
448 elif test -z "$old_cc" -a -z "$old_cflags"; then
449 echo No shared library support. | tee -a configure.log
450 shared=0;
451
--- compat/zlib/contrib/delphi/ZLib.pas
+++ compat/zlib/contrib/delphi/ZLib.pas
@@ -150,11 +150,11 @@
150150
BufSize = number of bytes in OutBuf }
151151
procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152152
const OutBuf: Pointer; BufSize: Integer);
153153
154154
const
155
- zlib_version = '1.3.0';
155
+ zlib_version = '1.3.1';
156156
157157
type
158158
EZlibError = class(Exception);
159159
ECompressionError = class(EZlibError);
160160
EDecompressionError = class(EZlibError);
161161
--- compat/zlib/contrib/delphi/ZLib.pas
+++ compat/zlib/contrib/delphi/ZLib.pas
@@ -150,11 +150,11 @@
150 BufSize = number of bytes in OutBuf }
151 procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152 const OutBuf: Pointer; BufSize: Integer);
153
154 const
155 zlib_version = '1.3.0';
156
157 type
158 EZlibError = class(Exception);
159 ECompressionError = class(EZlibError);
160 EDecompressionError = class(EZlibError);
161
--- compat/zlib/contrib/delphi/ZLib.pas
+++ compat/zlib/contrib/delphi/ZLib.pas
@@ -150,11 +150,11 @@
150 BufSize = number of bytes in OutBuf }
151 procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152 const OutBuf: Pointer; BufSize: Integer);
153
154 const
155 zlib_version = '1.3.1';
156
157 type
158 EZlibError = class(Exception);
159 ECompressionError = class(EZlibError);
160 EDecompressionError = class(EZlibError);
161
--- compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
@@ -32,11 +32,11 @@
3232
{
3333
_current = 0;
3434
}
3535
3636
/// <summary>
37
- /// Initializes a new instance of the checksum generator basewith a specified value
37
+ /// Initializes a new instance of the checksum generator base with a specified value
3838
/// </summary>
3939
/// <param name="initialValue">The value to set the current checksum to</param>
4040
public ChecksumGeneratorBase(uint initialValue)
4141
{
4242
_current = initialValue;
4343
--- compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
@@ -32,11 +32,11 @@
32 {
33 _current = 0;
34 }
35
36 /// <summary>
37 /// Initializes a new instance of the checksum generator basewith a specified value
38 /// </summary>
39 /// <param name="initialValue">The value to set the current checksum to</param>
40 public ChecksumGeneratorBase(uint initialValue)
41 {
42 _current = initialValue;
43
--- compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
@@ -32,11 +32,11 @@
32 {
33 _current = 0;
34 }
35
36 /// <summary>
37 /// Initializes a new instance of the checksum generator base with a specified value
38 /// </summary>
39 /// <param name="initialValue">The value to set the current checksum to</param>
40 public ChecksumGeneratorBase(uint initialValue)
41 {
42 _current = initialValue;
43
--- compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
@@ -154,11 +154,11 @@
154154
#region Info tests
155155
[Test]
156156
public void Info_Version()
157157
{
158158
Info info = new Info();
159
- Assert.AreEqual("1.3.0", Info.Version);
159
+ Assert.AreEqual("1.3.1", Info.Version);
160160
Assert.AreEqual(32, info.SizeOfUInt);
161161
Assert.AreEqual(32, info.SizeOfULong);
162162
Assert.AreEqual(32, info.SizeOfPointer);
163163
Assert.AreEqual(32, info.SizeOfOffset);
164164
}
165165
--- compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
@@ -154,11 +154,11 @@
154 #region Info tests
155 [Test]
156 public void Info_Version()
157 {
158 Info info = new Info();
159 Assert.AreEqual("1.3.0", Info.Version);
160 Assert.AreEqual(32, info.SizeOfUInt);
161 Assert.AreEqual(32, info.SizeOfULong);
162 Assert.AreEqual(32, info.SizeOfPointer);
163 Assert.AreEqual(32, info.SizeOfOffset);
164 }
165
--- compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
+++ compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
@@ -154,11 +154,11 @@
154 #region Info tests
155 [Test]
156 public void Info_Version()
157 {
158 Info info = new Info();
159 Assert.AreEqual("1.3.1", Info.Version);
160 Assert.AreEqual(32, info.SizeOfUInt);
161 Assert.AreEqual(32, info.SizeOfULong);
162 Assert.AreEqual(32, info.SizeOfPointer);
163 Assert.AreEqual(32, info.SizeOfOffset);
164 }
165
--- compat/zlib/contrib/infback9/inftree9.c
+++ compat/zlib/contrib/infback9/inftree9.c
@@ -1,17 +1,17 @@
11
/* inftree9.c -- generate Huffman trees for efficient decoding
2
- * Copyright (C) 1995-2023 Mark Adler
2
+ * Copyright (C) 1995-2024 Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
#include "zutil.h"
77
#include "inftree9.h"
88
99
#define MAXBITS 15
1010
1111
const char inflate9_copyright[] =
12
- " inflate9 1.3 Copyright 1995-2023 Mark Adler ";
12
+ " inflate9 1.3.1 Copyright 1995-2024 Mark Adler ";
1313
/*
1414
If you use the zlib library in a product, an acknowledgment is welcome
1515
in the documentation of your product. If for some reason you cannot
1616
include such an acknowledgment, I would appreciate that you keep this
1717
copyright string in the executable of your product.
@@ -57,11 +57,11 @@
5757
19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
5858
131, 163, 195, 227, 3, 0, 0};
5959
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
6060
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
6161
130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
62
- 133, 133, 133, 133, 144, 198, 203};
62
+ 133, 133, 133, 133, 144, 203, 77};
6363
static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
6464
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
6565
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
6666
4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153};
6767
static const unsigned short dext[32] = { /* Distance codes 0..31 extra */
6868
--- compat/zlib/contrib/infback9/inftree9.c
+++ compat/zlib/contrib/infback9/inftree9.c
@@ -1,17 +1,17 @@
1 /* inftree9.c -- generate Huffman trees for efficient decoding
2 * Copyright (C) 1995-2023 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "zutil.h"
7 #include "inftree9.h"
8
9 #define MAXBITS 15
10
11 const char inflate9_copyright[] =
12 " inflate9 1.3 Copyright 1995-2023 Mark Adler ";
13 /*
14 If you use the zlib library in a product, an acknowledgment is welcome
15 in the documentation of your product. If for some reason you cannot
16 include such an acknowledgment, I would appreciate that you keep this
17 copyright string in the executable of your product.
@@ -57,11 +57,11 @@
57 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
58 131, 163, 195, 227, 3, 0, 0};
59 static const unsigned short lext[31] = { /* Length codes 257..285 extra */
60 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
61 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
62 133, 133, 133, 133, 144, 198, 203};
63 static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
64 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
65 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
66 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153};
67 static const unsigned short dext[32] = { /* Distance codes 0..31 extra */
68
--- compat/zlib/contrib/infback9/inftree9.c
+++ compat/zlib/contrib/infback9/inftree9.c
@@ -1,17 +1,17 @@
1 /* inftree9.c -- generate Huffman trees for efficient decoding
2 * Copyright (C) 1995-2024 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "zutil.h"
7 #include "inftree9.h"
8
9 #define MAXBITS 15
10
11 const char inflate9_copyright[] =
12 " inflate9 1.3.1 Copyright 1995-2024 Mark Adler ";
13 /*
14 If you use the zlib library in a product, an acknowledgment is welcome
15 in the documentation of your product. If for some reason you cannot
16 include such an acknowledgment, I would appreciate that you keep this
17 copyright string in the executable of your product.
@@ -57,11 +57,11 @@
57 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
58 131, 163, 195, 227, 3, 0, 0};
59 static const unsigned short lext[31] = { /* Length codes 257..285 extra */
60 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
61 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
62 133, 133, 133, 133, 144, 203, 77};
63 static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
64 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
65 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
66 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153};
67 static const unsigned short dext[32] = { /* Distance codes 0..31 extra */
68
--- compat/zlib/contrib/infback9/inftree9.h
+++ compat/zlib/contrib/infback9/inftree9.h
@@ -39,12 +39,12 @@
3939
1446, which is the sum of 852 for literal/length codes and 594 for distance
4040
codes. These values were found by exhaustive searches using the program
4141
examples/enough.c found in the zlib distribution. The arguments to that
4242
program are the number of symbols, the initial root table size, and the
4343
maximum bit length of a code. "enough 286 9 15" for literal/length codes
44
- returns returns 852, and "enough 32 6 15" for distance codes returns 594.
45
- The initial root table size (9 or 6) is found in the fifth argument of the
44
+ returns 852, and "enough 32 6 15" for distance codes returns 594. The
45
+ initial root table size (9 or 6) is found in the fifth argument of the
4646
inflate_table() calls in infback9.c. If the root table size is changed,
4747
then these maximum sizes would be need to be recalculated and updated. */
4848
#define ENOUGH_LENS 852
4949
#define ENOUGH_DISTS 594
5050
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
5151
--- compat/zlib/contrib/infback9/inftree9.h
+++ compat/zlib/contrib/infback9/inftree9.h
@@ -39,12 +39,12 @@
39 1446, which is the sum of 852 for literal/length codes and 594 for distance
40 codes. These values were found by exhaustive searches using the program
41 examples/enough.c found in the zlib distribution. The arguments to that
42 program are the number of symbols, the initial root table size, and the
43 maximum bit length of a code. "enough 286 9 15" for literal/length codes
44 returns returns 852, and "enough 32 6 15" for distance codes returns 594.
45 The initial root table size (9 or 6) is found in the fifth argument of the
46 inflate_table() calls in infback9.c. If the root table size is changed,
47 then these maximum sizes would be need to be recalculated and updated. */
48 #define ENOUGH_LENS 852
49 #define ENOUGH_DISTS 594
50 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
51
--- compat/zlib/contrib/infback9/inftree9.h
+++ compat/zlib/contrib/infback9/inftree9.h
@@ -39,12 +39,12 @@
39 1446, which is the sum of 852 for literal/length codes and 594 for distance
40 codes. These values were found by exhaustive searches using the program
41 examples/enough.c found in the zlib distribution. The arguments to that
42 program are the number of symbols, the initial root table size, and the
43 maximum bit length of a code. "enough 286 9 15" for literal/length codes
44 returns 852, and "enough 32 6 15" for distance codes returns 594. The
45 initial root table size (9 or 6) is found in the fifth argument of the
46 inflate_table() calls in infback9.c. If the root table size is changed,
47 then these maximum sizes would be need to be recalculated and updated. */
48 #define ENOUGH_LENS 852
49 #define ENOUGH_DISTS 594
50 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
51
--- compat/zlib/contrib/iostream3/zfstream.h
+++ compat/zlib/contrib/iostream3/zfstream.h
@@ -411,11 +411,11 @@
411411
*/
412412
template<typename T1, typename T2>
413413
class gzomanip2
414414
{
415415
public:
416
- // Allows insertor to peek at internals
416
+ // Allows inserter to peek at internals
417417
template <typename Ta, typename Tb>
418418
friend gzofstream&
419419
operator<<(gzofstream&,
420420
const gzomanip2<Ta,Tb>&);
421421
@@ -450,11 +450,11 @@
450450
T1 v1,
451451
T2 v2)
452452
: func(f), val1(v1), val2(v2)
453453
{ }
454454
455
-// Insertor applies underlying manipulator function to stream
455
+// Inserter applies underlying manipulator function to stream
456456
template<typename T1, typename T2>
457457
inline gzofstream&
458458
operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
459459
{ return (*m.func)(s, m.val1, m.val2); }
460460
461461
--- compat/zlib/contrib/iostream3/zfstream.h
+++ compat/zlib/contrib/iostream3/zfstream.h
@@ -411,11 +411,11 @@
411 */
412 template<typename T1, typename T2>
413 class gzomanip2
414 {
415 public:
416 // Allows insertor to peek at internals
417 template <typename Ta, typename Tb>
418 friend gzofstream&
419 operator<<(gzofstream&,
420 const gzomanip2<Ta,Tb>&);
421
@@ -450,11 +450,11 @@
450 T1 v1,
451 T2 v2)
452 : func(f), val1(v1), val2(v2)
453 { }
454
455 // Insertor applies underlying manipulator function to stream
456 template<typename T1, typename T2>
457 inline gzofstream&
458 operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
459 { return (*m.func)(s, m.val1, m.val2); }
460
461
--- compat/zlib/contrib/iostream3/zfstream.h
+++ compat/zlib/contrib/iostream3/zfstream.h
@@ -411,11 +411,11 @@
411 */
412 template<typename T1, typename T2>
413 class gzomanip2
414 {
415 public:
416 // Allows inserter to peek at internals
417 template <typename Ta, typename Tb>
418 friend gzofstream&
419 operator<<(gzofstream&,
420 const gzomanip2<Ta,Tb>&);
421
@@ -450,11 +450,11 @@
450 T1 v1,
451 T2 v2)
452 : func(f), val1(v1), val2(v2)
453 { }
454
455 // Inserter applies underlying manipulator function to stream
456 template<typename T1, typename T2>
457 inline gzofstream&
458 operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
459 { return (*m.func)(s, m.val1, m.val2); }
460
461
--- compat/zlib/contrib/minizip/Makefile
+++ compat/zlib/contrib/minizip/Makefile
@@ -1,6 +1,6 @@
1
-CC=cc
1
+CC?=cc
22
CFLAGS := $(CFLAGS) -O -I../..
33
44
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
55
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
66
77
--- compat/zlib/contrib/minizip/Makefile
+++ compat/zlib/contrib/minizip/Makefile
@@ -1,6 +1,6 @@
1 CC=cc
2 CFLAGS := $(CFLAGS) -O -I../..
3
4 UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
5 ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
6
7
--- compat/zlib/contrib/minizip/Makefile
+++ compat/zlib/contrib/minizip/Makefile
@@ -1,6 +1,6 @@
1 CC?=cc
2 CFLAGS := $(CFLAGS) -O -I../..
3
4 UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
5 ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
6
7
--- compat/zlib/contrib/minizip/configure.ac
+++ compat/zlib/contrib/minizip/configure.ac
@@ -1,9 +1,9 @@
11
# -*- Autoconf -*-
22
# Process this file with autoconf to produce a configure script.
33
4
-AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
4
+AC_INIT([minizip], [1.3.1], [bugzilla.redhat.com])
55
AC_CONFIG_SRCDIR([minizip.c])
66
AM_INIT_AUTOMAKE([foreign])
77
LT_INIT
88
99
AC_MSG_CHECKING([whether to build example programs])
1010
--- compat/zlib/contrib/minizip/configure.ac
+++ compat/zlib/contrib/minizip/configure.ac
@@ -1,9 +1,9 @@
1 # -*- Autoconf -*-
2 # Process this file with autoconf to produce a configure script.
3
4 AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
5 AC_CONFIG_SRCDIR([minizip.c])
6 AM_INIT_AUTOMAKE([foreign])
7 LT_INIT
8
9 AC_MSG_CHECKING([whether to build example programs])
10
--- compat/zlib/contrib/minizip/configure.ac
+++ compat/zlib/contrib/minizip/configure.ac
@@ -1,9 +1,9 @@
1 # -*- Autoconf -*-
2 # Process this file with autoconf to produce a configure script.
3
4 AC_INIT([minizip], [1.3.1], [bugzilla.redhat.com])
5 AC_CONFIG_SRCDIR([minizip.c])
6 AM_INIT_AUTOMAKE([foreign])
7 LT_INIT
8
9 AC_MSG_CHECKING([whether to build example programs])
10
--- compat/zlib/contrib/minizip/ioapi.h
+++ compat/zlib/contrib/minizip/ioapi.h
@@ -142,11 +142,11 @@
142142
143143
typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
144144
typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
145145
146146
147
-/* here is the "old" 32 bits structure structure */
147
+/* here is the "old" 32 bits structure */
148148
typedef struct zlib_filefunc_def_s
149149
{
150150
open_file_func zopen_file;
151151
read_file_func zread_file;
152152
write_file_func zwrite_file;
153153
--- compat/zlib/contrib/minizip/ioapi.h
+++ compat/zlib/contrib/minizip/ioapi.h
@@ -142,11 +142,11 @@
142
143 typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
144 typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
145
146
147 /* here is the "old" 32 bits structure structure */
148 typedef struct zlib_filefunc_def_s
149 {
150 open_file_func zopen_file;
151 read_file_func zread_file;
152 write_file_func zwrite_file;
153
--- compat/zlib/contrib/minizip/ioapi.h
+++ compat/zlib/contrib/minizip/ioapi.h
@@ -142,11 +142,11 @@
142
143 typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
144 typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
145
146
147 /* here is the "old" 32 bits structure */
148 typedef struct zlib_filefunc_def_s
149 {
150 open_file_func zopen_file;
151 read_file_func zread_file;
152 write_file_func zwrite_file;
153
--- compat/zlib/contrib/minizip/miniunz.c
+++ compat/zlib/contrib/minizip/miniunz.c
@@ -77,11 +77,11 @@
7777
*/
7878
7979
8080
/* change_file_date : change the date/time of a file
8181
filename : the filename of the file where date/time must be modified
82
- dosdate : the new date at the MSDos format (4 bytes)
82
+ dosdate : the new date at the MSDOS format (4 bytes)
8383
tmu_date : the SAME new date at the tm_unz format */
8484
static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
8585
#ifdef _WIN32
8686
HANDLE hFile;
8787
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
@@ -184,11 +184,11 @@
184184
free(buffer);
185185
return 1;
186186
}
187187
188188
static void do_banner(void) {
189
- printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
189
+ printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
190190
printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
191191
}
192192
193193
static void do_help(void) {
194194
printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
@@ -353,10 +353,24 @@
353353
354354
if ((*popt_extract_without_path)==0)
355355
write_filename = filename_inzip;
356356
else
357357
write_filename = filename_withoutpath;
358
+
359
+ if (write_filename[0]!='\0')
360
+ {
361
+ const char* relative_check = write_filename;
362
+ while (relative_check[1]!='\0')
363
+ {
364
+ if (relative_check[0]=='.' && relative_check[1]=='.')
365
+ write_filename = relative_check;
366
+ relative_check++;
367
+ }
368
+ }
369
+
370
+ while (write_filename[0]=='/' || write_filename[0]=='.')
371
+ write_filename++;
358372
359373
err = unzOpenCurrentFilePassword(uf,password);
360374
if (err!=UNZ_OK)
361375
{
362376
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
363377
--- compat/zlib/contrib/minizip/miniunz.c
+++ compat/zlib/contrib/minizip/miniunz.c
@@ -77,11 +77,11 @@
77 */
78
79
80 /* change_file_date : change the date/time of a file
81 filename : the filename of the file where date/time must be modified
82 dosdate : the new date at the MSDos format (4 bytes)
83 tmu_date : the SAME new date at the tm_unz format */
84 static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
85 #ifdef _WIN32
86 HANDLE hFile;
87 FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
@@ -184,11 +184,11 @@
184 free(buffer);
185 return 1;
186 }
187
188 static void do_banner(void) {
189 printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
190 printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
191 }
192
193 static void do_help(void) {
194 printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
@@ -353,10 +353,24 @@
353
354 if ((*popt_extract_without_path)==0)
355 write_filename = filename_inzip;
356 else
357 write_filename = filename_withoutpath;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
359 err = unzOpenCurrentFilePassword(uf,password);
360 if (err!=UNZ_OK)
361 {
362 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
363
--- compat/zlib/contrib/minizip/miniunz.c
+++ compat/zlib/contrib/minizip/miniunz.c
@@ -77,11 +77,11 @@
77 */
78
79
80 /* change_file_date : change the date/time of a file
81 filename : the filename of the file where date/time must be modified
82 dosdate : the new date at the MSDOS format (4 bytes)
83 tmu_date : the SAME new date at the tm_unz format */
84 static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
85 #ifdef _WIN32
86 HANDLE hFile;
87 FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
@@ -184,11 +184,11 @@
184 free(buffer);
185 return 1;
186 }
187
188 static void do_banner(void) {
189 printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
190 printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
191 }
192
193 static void do_help(void) {
194 printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
@@ -353,10 +353,24 @@
353
354 if ((*popt_extract_without_path)==0)
355 write_filename = filename_inzip;
356 else
357 write_filename = filename_withoutpath;
358
359 if (write_filename[0]!='\0')
360 {
361 const char* relative_check = write_filename;
362 while (relative_check[1]!='\0')
363 {
364 if (relative_check[0]=='.' && relative_check[1]=='.')
365 write_filename = relative_check;
366 relative_check++;
367 }
368 }
369
370 while (write_filename[0]=='/' || write_filename[0]=='.')
371 write_filename++;
372
373 err = unzOpenCurrentFilePassword(uf,password);
374 if (err!=UNZ_OK)
375 {
376 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
377
--- compat/zlib/contrib/minizip/unzip.c
+++ compat/zlib/contrib/minizip/unzip.c
@@ -115,11 +115,11 @@
115115
116116
117117
const char unz_copyright[] =
118118
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
119119
120
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
120
+/* unz_file_info64_internal contain internal info about a file in zipfile*/
121121
typedef struct unz_file_info64_internal_s
122122
{
123123
ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
124124
} unz_file_info64_internal;
125125
@@ -448,11 +448,11 @@
448448
449449
/* the signature, already checked */
450450
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
451451
return CENTRALDIRINVALID;
452452
453
- /* number of the disk with the start of the zip64 end of central directory */
453
+ /* number of the disk with the start of the zip64 end of central directory */
454454
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
455455
return CENTRALDIRINVALID;
456456
if (uL != 0)
457457
return CENTRALDIRINVALID;
458458
@@ -495,13 +495,13 @@
495495
unz64_s us;
496496
unz64_s *s;
497497
ZPOS64_T central_pos;
498498
uLong uL;
499499
500
- uLong number_disk; /* number of the current dist, used for
500
+ uLong number_disk; /* number of the current disk, used for
501501
spanning ZIP, unsupported, always 0*/
502
- uLong number_disk_with_CD; /* number the the disk with central dir, used
502
+ uLong number_disk_with_CD; /* number the disk with central dir, used
503503
for spanning ZIP, unsupported, always 0*/
504504
ZPOS64_T number_entry_CD; /* total number of entries in
505505
the central dir
506506
(same than number_entry on nospan) */
507507
508508
--- compat/zlib/contrib/minizip/unzip.c
+++ compat/zlib/contrib/minizip/unzip.c
@@ -115,11 +115,11 @@
115
116
117 const char unz_copyright[] =
118 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
119
120 /* unz_file_info_interntal contain internal info about a file in zipfile*/
121 typedef struct unz_file_info64_internal_s
122 {
123 ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
124 } unz_file_info64_internal;
125
@@ -448,11 +448,11 @@
448
449 /* the signature, already checked */
450 if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
451 return CENTRALDIRINVALID;
452
453 /* number of the disk with the start of the zip64 end of central directory */
454 if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
455 return CENTRALDIRINVALID;
456 if (uL != 0)
457 return CENTRALDIRINVALID;
458
@@ -495,13 +495,13 @@
495 unz64_s us;
496 unz64_s *s;
497 ZPOS64_T central_pos;
498 uLong uL;
499
500 uLong number_disk; /* number of the current dist, used for
501 spanning ZIP, unsupported, always 0*/
502 uLong number_disk_with_CD; /* number the the disk with central dir, used
503 for spanning ZIP, unsupported, always 0*/
504 ZPOS64_T number_entry_CD; /* total number of entries in
505 the central dir
506 (same than number_entry on nospan) */
507
508
--- compat/zlib/contrib/minizip/unzip.c
+++ compat/zlib/contrib/minizip/unzip.c
@@ -115,11 +115,11 @@
115
116
117 const char unz_copyright[] =
118 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
119
120 /* unz_file_info64_internal contain internal info about a file in zipfile*/
121 typedef struct unz_file_info64_internal_s
122 {
123 ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
124 } unz_file_info64_internal;
125
@@ -448,11 +448,11 @@
448
449 /* the signature, already checked */
450 if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
451 return CENTRALDIRINVALID;
452
453 /* number of the disk with the start of the zip64 end of central directory */
454 if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
455 return CENTRALDIRINVALID;
456 if (uL != 0)
457 return CENTRALDIRINVALID;
458
@@ -495,13 +495,13 @@
495 unz64_s us;
496 unz64_s *s;
497 ZPOS64_T central_pos;
498 uLong uL;
499
500 uLong number_disk; /* number of the current disk, used for
501 spanning ZIP, unsupported, always 0*/
502 uLong number_disk_with_CD; /* number the disk with central dir, used
503 for spanning ZIP, unsupported, always 0*/
504 ZPOS64_T number_entry_CD; /* total number of entries in
505 the central dir
506 (same than number_entry on nospan) */
507
508
--- compat/zlib/contrib/minizip/unzip.h
+++ compat/zlib/contrib/minizip/unzip.h
@@ -304,11 +304,11 @@
304304
uLong commentBufferSize);
305305
/*
306306
Get Info about the current file
307307
if pfile_info!=NULL, the *pfile_info structure will contain some info about
308308
the current file
309
- if szFileName!=NULL, the filemane string will be copied in szFileName
309
+ if szFileName!=NULL, the filename string will be copied in szFileName
310310
(fileNameBufferSize is the size of the buffer)
311311
if extraField!=NULL, the extra field information will be copied in extraField
312312
(extraFieldBufferSize is the size of the buffer).
313313
This is the Central-header version of the extra field
314314
if szComment!=NULL, the comment string of the file will be copied in szComment
315315
--- compat/zlib/contrib/minizip/unzip.h
+++ compat/zlib/contrib/minizip/unzip.h
@@ -304,11 +304,11 @@
304 uLong commentBufferSize);
305 /*
306 Get Info about the current file
307 if pfile_info!=NULL, the *pfile_info structure will contain some info about
308 the current file
309 if szFileName!=NULL, the filemane string will be copied in szFileName
310 (fileNameBufferSize is the size of the buffer)
311 if extraField!=NULL, the extra field information will be copied in extraField
312 (extraFieldBufferSize is the size of the buffer).
313 This is the Central-header version of the extra field
314 if szComment!=NULL, the comment string of the file will be copied in szComment
315
--- compat/zlib/contrib/minizip/unzip.h
+++ compat/zlib/contrib/minizip/unzip.h
@@ -304,11 +304,11 @@
304 uLong commentBufferSize);
305 /*
306 Get Info about the current file
307 if pfile_info!=NULL, the *pfile_info structure will contain some info about
308 the current file
309 if szFileName!=NULL, the filename string will be copied in szFileName
310 (fileNameBufferSize is the size of the buffer)
311 if extraField!=NULL, the extra field information will be copied in extraField
312 (extraFieldBufferSize is the size of the buffer).
313 This is the Central-header version of the extra field
314 if szComment!=NULL, the comment string of the file will be copied in szComment
315
--- compat/zlib/contrib/minizip/zip.c
+++ compat/zlib/contrib/minizip/zip.c
@@ -573,11 +573,11 @@
573573
574574
/* the signature, already checked */
575575
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
576576
return 0;
577577
578
- /* number of the disk with the start of the zip64 end of central directory */
578
+ /* number of the disk with the start of the zip64 end of central directory */
579579
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
580580
return 0;
581581
if (uL != 0)
582582
return 0;
583583
@@ -612,13 +612,13 @@
612612
ZPOS64_T size_central_dir; /* size of the central directory */
613613
ZPOS64_T offset_central_dir; /* offset of start of central directory */
614614
ZPOS64_T central_pos;
615615
uLong uL;
616616
617
- uLong number_disk; /* number of the current dist, used for
617
+ uLong number_disk; /* number of the current disk, used for
618618
spanning ZIP, unsupported, always 0*/
619
- uLong number_disk_with_CD; /* number the the disk with central dir, used
619
+ uLong number_disk_with_CD; /* number of the disk with central dir, used
620620
for spanning ZIP, unsupported, always 0*/
621621
ZPOS64_T number_entry;
622622
ZPOS64_T number_entry_CD; /* total number of entries in
623623
the central dir
624624
(same than number_entry on nospan) */
@@ -1040,10 +1040,21 @@
10401040
return ZIP_PARAMERROR;
10411041
#else
10421042
if ((method!=0) && (method!=Z_DEFLATED))
10431043
return ZIP_PARAMERROR;
10441044
#endif
1045
+
1046
+ // The filename and comment length must fit in 16 bits.
1047
+ if ((filename!=NULL) && (strlen(filename)>0xffff))
1048
+ return ZIP_PARAMERROR;
1049
+ if ((comment!=NULL) && (strlen(comment)>0xffff))
1050
+ return ZIP_PARAMERROR;
1051
+ // The extra field length must fit in 16 bits. If the member also requires
1052
+ // a Zip64 extra block, that will also need to fit within that 16-bit
1053
+ // length, but that will be checked for later.
1054
+ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
1055
+ return ZIP_PARAMERROR;
10451056
10461057
zi = (zip64_internal*)file;
10471058
10481059
if (zi->in_opened_file_inzip == 1)
10491060
{
@@ -1595,11 +1606,11 @@
15951606
{
15961607
char* p = NULL;
15971608
15981609
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
15991610
{
1600
- // we can not write more data to the buffer that we have room for.
1611
+ // we cannot write more data to the buffer that we have room for.
16011612
return ZIP_BADZIPFILE;
16021613
}
16031614
16041615
p = zi->ci.central_header + zi->ci.size_centralheader;
16051616
@@ -1859,11 +1870,11 @@
18591870
}
18601871
}
18611872
free_linkedlist(&(zi->central_dir));
18621873
18631874
pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
1864
- if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
1875
+ if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
18651876
{
18661877
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
18671878
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
18681879
18691880
Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
18701881
--- compat/zlib/contrib/minizip/zip.c
+++ compat/zlib/contrib/minizip/zip.c
@@ -573,11 +573,11 @@
573
574 /* the signature, already checked */
575 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
576 return 0;
577
578 /* number of the disk with the start of the zip64 end of central directory */
579 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
580 return 0;
581 if (uL != 0)
582 return 0;
583
@@ -612,13 +612,13 @@
612 ZPOS64_T size_central_dir; /* size of the central directory */
613 ZPOS64_T offset_central_dir; /* offset of start of central directory */
614 ZPOS64_T central_pos;
615 uLong uL;
616
617 uLong number_disk; /* number of the current dist, used for
618 spanning ZIP, unsupported, always 0*/
619 uLong number_disk_with_CD; /* number the the disk with central dir, used
620 for spanning ZIP, unsupported, always 0*/
621 ZPOS64_T number_entry;
622 ZPOS64_T number_entry_CD; /* total number of entries in
623 the central dir
624 (same than number_entry on nospan) */
@@ -1040,10 +1040,21 @@
1040 return ZIP_PARAMERROR;
1041 #else
1042 if ((method!=0) && (method!=Z_DEFLATED))
1043 return ZIP_PARAMERROR;
1044 #endif
 
 
 
 
 
 
 
 
 
 
 
1045
1046 zi = (zip64_internal*)file;
1047
1048 if (zi->in_opened_file_inzip == 1)
1049 {
@@ -1595,11 +1606,11 @@
1595 {
1596 char* p = NULL;
1597
1598 if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1599 {
1600 // we can not write more data to the buffer that we have room for.
1601 return ZIP_BADZIPFILE;
1602 }
1603
1604 p = zi->ci.central_header + zi->ci.size_centralheader;
1605
@@ -1859,11 +1870,11 @@
1859 }
1860 }
1861 free_linkedlist(&(zi->central_dir));
1862
1863 pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
1864 if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
1865 {
1866 ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
1867 Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
1868
1869 Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
1870
--- compat/zlib/contrib/minizip/zip.c
+++ compat/zlib/contrib/minizip/zip.c
@@ -573,11 +573,11 @@
573
574 /* the signature, already checked */
575 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
576 return 0;
577
578 /* number of the disk with the start of the zip64 end of central directory */
579 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
580 return 0;
581 if (uL != 0)
582 return 0;
583
@@ -612,13 +612,13 @@
612 ZPOS64_T size_central_dir; /* size of the central directory */
613 ZPOS64_T offset_central_dir; /* offset of start of central directory */
614 ZPOS64_T central_pos;
615 uLong uL;
616
617 uLong number_disk; /* number of the current disk, used for
618 spanning ZIP, unsupported, always 0*/
619 uLong number_disk_with_CD; /* number of the disk with central dir, used
620 for spanning ZIP, unsupported, always 0*/
621 ZPOS64_T number_entry;
622 ZPOS64_T number_entry_CD; /* total number of entries in
623 the central dir
624 (same than number_entry on nospan) */
@@ -1040,10 +1040,21 @@
1040 return ZIP_PARAMERROR;
1041 #else
1042 if ((method!=0) && (method!=Z_DEFLATED))
1043 return ZIP_PARAMERROR;
1044 #endif
1045
1046 // The filename and comment length must fit in 16 bits.
1047 if ((filename!=NULL) && (strlen(filename)>0xffff))
1048 return ZIP_PARAMERROR;
1049 if ((comment!=NULL) && (strlen(comment)>0xffff))
1050 return ZIP_PARAMERROR;
1051 // The extra field length must fit in 16 bits. If the member also requires
1052 // a Zip64 extra block, that will also need to fit within that 16-bit
1053 // length, but that will be checked for later.
1054 if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
1055 return ZIP_PARAMERROR;
1056
1057 zi = (zip64_internal*)file;
1058
1059 if (zi->in_opened_file_inzip == 1)
1060 {
@@ -1595,11 +1606,11 @@
1606 {
1607 char* p = NULL;
1608
1609 if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1610 {
1611 // we cannot write more data to the buffer that we have room for.
1612 return ZIP_BADZIPFILE;
1613 }
1614
1615 p = zi->ci.central_header + zi->ci.size_centralheader;
1616
@@ -1859,11 +1870,11 @@
1870 }
1871 }
1872 free_linkedlist(&(zi->central_dir));
1873
1874 pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
1875 if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
1876 {
1877 ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
1878 Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
1879
1880 Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
1881
--- compat/zlib/contrib/minizip/zip.h
+++ compat/zlib/contrib/minizip/zip.h
@@ -175,13 +175,13 @@
175175
/*
176176
Open a file in the ZIP for writing.
177177
filename : the filename in zip (if NULL, '-' without quote will be used
178178
*zipfi contain supplemental information
179179
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
180
- contains the extrafield data the the local header
180
+ contains the extrafield data for the local header
181181
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
182
- contains the extrafield data the the local header
182
+ contains the extrafield data for the global header
183183
if comment != NULL, comment contain the comment string
184184
method contain the compression method (0 for store, Z_DEFLATED for deflate)
185185
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
186186
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
187187
this MUST be '1' if the uncompressed size is >= 0xffffffff.
188188
--- compat/zlib/contrib/minizip/zip.h
+++ compat/zlib/contrib/minizip/zip.h
@@ -175,13 +175,13 @@
175 /*
176 Open a file in the ZIP for writing.
177 filename : the filename in zip (if NULL, '-' without quote will be used
178 *zipfi contain supplemental information
179 if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
180 contains the extrafield data the the local header
181 if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
182 contains the extrafield data the the local header
183 if comment != NULL, comment contain the comment string
184 method contain the compression method (0 for store, Z_DEFLATED for deflate)
185 level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
186 zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
187 this MUST be '1' if the uncompressed size is >= 0xffffffff.
188
--- compat/zlib/contrib/minizip/zip.h
+++ compat/zlib/contrib/minizip/zip.h
@@ -175,13 +175,13 @@
175 /*
176 Open a file in the ZIP for writing.
177 filename : the filename in zip (if NULL, '-' without quote will be used
178 *zipfi contain supplemental information
179 if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
180 contains the extrafield data for the local header
181 if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
182 contains the extrafield data for the global header
183 if comment != NULL, comment contain the comment string
184 method contain the compression method (0 for store, Z_DEFLATED for deflate)
185 level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
186 zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
187 this MUST be '1' if the uncompressed size is >= 0xffffffff.
188
--- compat/zlib/contrib/pascal/zlibpas.pas
+++ compat/zlib/contrib/pascal/zlibpas.pas
@@ -8,11 +8,11 @@
88
unit zlibpas;
99
1010
interface
1111
1212
const
13
- ZLIB_VERSION = '1.3.0';
13
+ ZLIB_VERSION = '1.3.1';
1414
ZLIB_VERNUM = $12a0;
1515
1616
type
1717
alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
1818
cdecl;
1919
--- compat/zlib/contrib/pascal/zlibpas.pas
+++ compat/zlib/contrib/pascal/zlibpas.pas
@@ -8,11 +8,11 @@
8 unit zlibpas;
9
10 interface
11
12 const
13 ZLIB_VERSION = '1.3.0';
14 ZLIB_VERNUM = $12a0;
15
16 type
17 alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
18 cdecl;
19
--- compat/zlib/contrib/pascal/zlibpas.pas
+++ compat/zlib/contrib/pascal/zlibpas.pas
@@ -8,11 +8,11 @@
8 unit zlibpas;
9
10 interface
11
12 const
13 ZLIB_VERSION = '1.3.1';
14 ZLIB_VERNUM = $12a0;
15
16 type
17 alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
18 cdecl;
19
--- compat/zlib/contrib/puff/puff.c
+++ compat/zlib/contrib/puff/puff.c
@@ -591,14 +591,14 @@
591591
*
592592
* - The code lengths are stored in order for the symbols, so lengths are
593593
* provided for each of the literal/length symbols, and for each of the
594594
* distance symbols.
595595
*
596
- * - If a symbol is not used in the block, this is represented by a zero as
597
- * as the code length. This does not mean a zero-length code, but rather
598
- * that no code should be created for this symbol. There is no way in the
599
- * deflate format to represent a zero-length code.
596
+ * - If a symbol is not used in the block, this is represented by a zero as the
597
+ * code length. This does not mean a zero-length code, but rather that no
598
+ * code should be created for this symbol. There is no way in the deflate
599
+ * format to represent a zero-length code.
600600
*
601601
* - The maximum number of bits in a code is 15, so the possible lengths for
602602
* any code are 1..15.
603603
*
604604
* - The fact that a length of zero is not permitted for a code has an
605605
--- compat/zlib/contrib/puff/puff.c
+++ compat/zlib/contrib/puff/puff.c
@@ -591,14 +591,14 @@
591 *
592 * - The code lengths are stored in order for the symbols, so lengths are
593 * provided for each of the literal/length symbols, and for each of the
594 * distance symbols.
595 *
596 * - If a symbol is not used in the block, this is represented by a zero as
597 * as the code length. This does not mean a zero-length code, but rather
598 * that no code should be created for this symbol. There is no way in the
599 * deflate format to represent a zero-length code.
600 *
601 * - The maximum number of bits in a code is 15, so the possible lengths for
602 * any code are 1..15.
603 *
604 * - The fact that a length of zero is not permitted for a code has an
605
--- compat/zlib/contrib/puff/puff.c
+++ compat/zlib/contrib/puff/puff.c
@@ -591,14 +591,14 @@
591 *
592 * - The code lengths are stored in order for the symbols, so lengths are
593 * provided for each of the literal/length symbols, and for each of the
594 * distance symbols.
595 *
596 * - If a symbol is not used in the block, this is represented by a zero as the
597 * code length. This does not mean a zero-length code, but rather that no
598 * code should be created for this symbol. There is no way in the deflate
599 * format to represent a zero-length code.
600 *
601 * - The maximum number of bits in a code is 15, so the possible lengths for
602 * any code are 1..15.
603 *
604 * - The fact that a length of zero is not permitted for a code has an
605
--- compat/zlib/contrib/vstudio/readme.txt
+++ compat/zlib/contrib/vstudio/readme.txt
@@ -1,75 +1,81 @@
1
-Building instructions for the DLL versions of Zlib 1.3.0
2
-========================================================
3
-
4
-This directory contains projects that build zlib and minizip using
5
-Microsoft Visual C++ 9.0/10.0.
6
-
7
-You don't need to build these projects yourself. You can download the
8
-binaries from:
9
- http://www.winimage.com/zLibDll
10
-
11
-More information can be found at this site.
12
-
13
-
14
-
15
-
16
-
17
-Build instructions for Visual Studio 2008 (32 bits or 64 bits)
---------------------------------------------------------------
18
-- Decompress current zlib, including all contrib/* files
19
-- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
20
-- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
21
-
22
-Build instructions for Visual Studio 2010 (32 bits or 64 bits)
---------------------------------------------------------------
23
-- Decompress current zlib, including all contrib/* files
24
-- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
25
-
26
-Build instructions for Visual Studio 2012 (32 bits or 64 bits)
---------------------------------------------------------------
27
-- Decompress current zlib, including all contrib/* files
28
-- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
29
-
30
-Build instructions for Visual Studio 2013 (32 bits or 64 bits)
---------------------------------------------------------------
31
-- Decompress current zlib, including all contrib/* files
32
-- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
33
-
34
-Build instructions for Visual Studio 2015 (32 bits or 64 bits)
---------------------------------------------------------------
35
-- Decompress current zlib, including all contrib/* files
36
-- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
37
-
38
-
39
-Important
----------
40
-- To use zlibwapi.dll in your application, you must define the
41
- macro ZLIB_WINAPI when compiling your application's source files.
42
-
43
-
44
-Additional notes
-----------------
45
-- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
46
- by Gilles Vollant from the zlib 1.1.x sources, and distributed at
47
- http://www.winimage.com/zLibDll
48
- It uses the WINAPI calling convention for the exported functions, and
49
- includes the minizip functionality. If your application needs that
50
- particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
51
-
52
-- The new DLL was renamed because there exist several incompatible
53
- versions of zlib.dll on the Internet.
54
-
55
-- There is also an official DLL build of zlib, named zlib1.dll. This one
56
- is exporting the functions using the CDECL convention. See the file
57
- win32\DLL_FAQ.txt found in this zlib distribution.
58
-
59
-- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
60
- has a slightly different effect. To avoid compatibility problems, do
61
- not define it here.
62
-
63
-
64
-Gilles Vollant
65
-[email protected]
66
-
67
-Visual Studio 2013 and 2015 Projects from Sean Hunt
68
-[email protected]
1
+Building instructions for the DLL versions of Zlib 1.3.1
2
+========================================================
3
+
4
+This directory contains projects that build zlib and minizip using
5
+Microsoft Visual C++ 9.0/10.0.
6
+
7
+You don't need to build these projects yourself. You can download the
8
+binaries from:
9
+ http://www.winimage.com/zLibDll
10
+
11
+More information can be found at this site.
12
+
13
+
14
+
15
+
16
+
17
+Build instructions for Visual Studio 2008 (32 bits or 64 bits)
18
+--------------------------------------------------------------
19
+- Decompress current zlib, including all contrib/* files
20
+- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
21
+- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
22
+
23
+Build instructions for Visual Studio 2010 (32 bits or 64 bits)
24
+--------------------------------------------------------------
25
+- Decompress current zlib, including all contrib/* files
26
+- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
27
+
28
+Build instructions for Visual Studio 2012 (32 bits or 64 bits)
29
+--------------------------------------------------------------
30
+- Decompress current zlib, including all contrib/* files
31
+- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
32
+
33
+Build instructions for Visual Studio 2013 (32 bits or 64 bits)
34
+--------------------------------------------------------------
35
+- Decompress current zlib, including all contrib/* files
36
+- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
37
+
38
+Build instructions for Visual Studio 2015 (32 bits or 64 bits)
39
+--------------------------------------------------------------
40
+- Decompress current zlib, including all contrib/* files
41
+- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
42
+
43
+Build instructions for Visual Studio 2022 (64 bits)
44
+--------------------------------------------------------------
45
+- Decompress current zlib, including all contrib/* files
46
+- Open contrib\vstudio\vc143\zlibvc.sln with Microsoft Visual C++ 2022
47
+
48
+
49
+
50
+Important
51
+---------
52
+- To use zlibwapi.dll in your application, you must define the
53
+ macro ZLIB_WINAPI when compiling your application's source files.
54
+
55
+
56
+Additional notes
57
+----------------
58
+- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
59
+ by Gilles Vollant from the zlib 1.1.x sources, and distributed at
60
+ http://www.winimage.com/zLibDll
61
+ It uses the WINAPI calling convention for the exported functions, and
62
+ includes the minizip functionality. If your application needs that
63
+ particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
64
+
65
+- The new DLL was renamed because there exist several incompatible
66
+ versions of zlib.dll on the Internet.
67
+
68
+- There is also an official DLL build of zlib, named zlib1.dll. This one
69
+ is exporting the functions using the CDECL convention. See the file
70
+ win32\DLL_FAQ.txt found in this zlib distribution.
71
+
72
+- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
73
+ has a slightly different effect. To avoid compatibility problems, do
74
+ not define it here.
75
+
76
+
77
+Gilles Vollant
78
+[email protected]
79
+
80
+Visual Studio 2013, 2015, and 2022 Projects from Sean Hunt
81
+[email protected]
6982
--- compat/zlib/contrib/vstudio/readme.txt
+++ compat/zlib/contrib/vstudio/readme.txt
@@ -1,75 +1,81 @@
1 Building instructions for the DLL versions of Zlib 1.3.0
2 ========================================================
3
4 This directory contains projects that build zlib and minizip using
5 Microsoft Visual C++ 9.0/10.0.
6
7 You don't need to build these projects yourself. You can download the
8 binaries from:
9 http://www.winimage.com/zLibDll
10
11 More information can be found at this site.
12
13
14
15
16
17 Build instructions for Visual Studio 2008 (32 bits or 64 bits)
---------------------------------------------------------------
18 - Decompress current zlib, including all contrib/* files
19 - Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
20 - Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
21
22 Build instructions for Visual Studio 2010 (32 bits or 64 bits)
---------------------------------------------------------------
23 - Decompress current zlib, including all contrib/* files
24 - Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
25
26 Build instructions for Visual Studio 2012 (32 bits or 64 bits)
---------------------------------------------------------------
27 - Decompress current zlib, including all contrib/* files
28 - Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
29
30 Build instructions for Visual Studio 2013 (32 bits or 64 bits)
---------------------------------------------------------------
31 - Decompress current zlib, including all contrib/* files
32 - Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
33
34 Build instructions for Visual Studio 2015 (32 bits or 64 bits)
---------------------------------------------------------------
35 - Decompress current zlib, including all contrib/* files
36 - Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
37
38
39 Important
----------
40 - To use zlibwapi.dll in your application, you must define the
41 macro ZLIB_WINAPI when compiling your application's source files.
42
43
44 Additional notes
-----------------
45 - This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
46 by Gilles Vollant from the zlib 1.1.x sources, and distributed at
47 http://www.winimage.com/zLibDll
48 It uses the WINAPI calling convention for the exported functions, and
49 includes the minizip functionality. If your application needs that
50 particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
51
52 - The new DLL was renamed because there exist several incompatible
53 versions of zlib.dll on the Internet.
54
55 - There is also an official DLL build of zlib, named zlib1.dll. This one
56 is exporting the functions using the CDECL convention. See the file
57 win32\DLL_FAQ.txt found in this zlib distribution.
58
59 - There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
60 has a slightly different effect. To avoid compatibility problems, do
61 not define it here.
62
63
64 Gilles Vollant
65 [email protected]
66
67 Visual Studio 2013 and 2015 Projects from Sean Hunt
68 [email protected]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
--- compat/zlib/contrib/vstudio/readme.txt
+++ compat/zlib/contrib/vstudio/readme.txt
@@ -1,75 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
---------------------------------------------------------------
 
 
 
 
 
---------------------------------------------------------------
 
 
 
 
---------------------------------------------------------------
 
 
 
 
---------------------------------------------------------------
 
 
 
 
---------------------------------------------------------------
 
 
 
 
 
----------
 
 
 
 
 
-----------------
1 Building instructions for the DLL versions of Zlib 1.3.1
2 ========================================================
3
4 This directory contains projects that build zlib and minizip using
5 Microsoft Visual C++ 9.0/10.0.
6
7 You don't need to build these projects yourself. You can download the
8 binaries from:
9 http://www.winimage.com/zLibDll
10
11 More information can be found at this site.
12
13
14
15
16
17 Build instructions for Visual Studio 2008 (32 bits or 64 bits)
18 --------------------------------------------------------------
19 - Decompress current zlib, including all contrib/* files
20 - Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
21 - Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
22
23 Build instructions for Visual Studio 2010 (32 bits or 64 bits)
24 --------------------------------------------------------------
25 - Decompress current zlib, including all contrib/* files
26 - Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
27
28 Build instructions for Visual Studio 2012 (32 bits or 64 bits)
29 --------------------------------------------------------------
30 - Decompress current zlib, including all contrib/* files
31 - Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
32
33 Build instructions for Visual Studio 2013 (32 bits or 64 bits)
34 --------------------------------------------------------------
35 - Decompress current zlib, including all contrib/* files
36 - Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
37
38 Build instructions for Visual Studio 2015 (32 bits or 64 bits)
39 --------------------------------------------------------------
40 - Decompress current zlib, including all contrib/* files
41 - Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
42
43 Build instructions for Visual Studio 2022 (64 bits)
44 --------------------------------------------------------------
45 - Decompress current zlib, including all contrib/* files
46 - Open contrib\vstudio\vc143\zlibvc.sln with Microsoft Visual C++ 2022
47
48
49
50 Important
51 ---------
52 - To use zlibwapi.dll in your application, you must define the
53 macro ZLIB_WINAPI when compiling your application's source files.
54
55
56 Additional notes
57 ----------------
58 - This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
59 by Gilles Vollant from the zlib 1.1.x sources, and distributed at
60 http://www.winimage.com/zLibDll
61 It uses the WINAPI calling convention for the exported functions, and
62 includes the minizip functionality. If your application needs that
63 particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
64
65 - The new DLL was renamed because there exist several incompatible
66 versions of zlib.dll on the Internet.
67
68 - There is also an official DLL build of zlib, named zlib1.dll. This one
69 is exporting the functions using the CDECL convention. See the file
70 win32\DLL_FAQ.txt found in this zlib distribution.
71
72 - There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
73 has a slightly different effect. To avoid compatibility problems, do
74 not define it here.
75
76
77 Gilles Vollant
78 [email protected]
79
80 Visual Studio 2013, 2015, and 2022 Projects from Sean Hunt
81 [email protected]
82
--- compat/zlib/contrib/vstudio/vc10/zlib.rc
+++ compat/zlib/contrib/vstudio/vc10/zlib.rc
@@ -1,11 +1,11 @@
11
#include <windows.h>
22
33
#define IDR_VERSION1 1
44
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5
- FILEVERSION 1, 3, 0, 0
6
- PRODUCTVERSION 1, 3, 0, 0
5
+ FILEVERSION 1, 3, 1, 0
6
+ PRODUCTVERSION 1, 3, 1, 0
77
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
88
FILEFLAGS 0
99
FILEOS VOS_DOS_WINDOWS32
1010
FILETYPE VFT_DLL
1111
FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
1515
BLOCK "040904E4"
1616
//language ID = U.S. English, char set = Windows, Multilingual
1717
1818
BEGIN
1919
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20
- VALUE "FileVersion", "1.3.0\0"
20
+ VALUE "FileVersion", "1.3.1\0"
2121
VALUE "InternalName", "zlib\0"
2222
VALUE "OriginalFilename", "zlibwapi.dll\0"
2323
VALUE "ProductName", "ZLib.DLL\0"
2424
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
25
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
2626
END
2727
END
2828
BLOCK "VarFileInfo"
2929
BEGIN
3030
VALUE "Translation", 0x0409, 1252
3131
END
3232
END
3333
--- compat/zlib/contrib/vstudio/vc10/zlib.rc
+++ compat/zlib/contrib/vstudio/vc10/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 0, 0
6 PRODUCTVERSION 1, 3, 0, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.0\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc10/zlib.rc
+++ compat/zlib/contrib/vstudio/vc10/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 1, 0
6 PRODUCTVERSION 1, 3, 1, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.1\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc10/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc10/zlibvc.def
@@ -1,9 +1,9 @@
11
LIBRARY
22
; zlib data compression and ZIP file I/O library
33
4
-VERSION 1.3
4
+VERSION 1.3.1
55
66
EXPORTS
77
adler32 @1
88
compress @2
99
crc32 @3
1010
--- compat/zlib/contrib/vstudio/vc10/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc10/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc10/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc10/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3.1
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc11/zlib.rc
+++ compat/zlib/contrib/vstudio/vc11/zlib.rc
@@ -1,11 +1,11 @@
11
#include <windows.h>
22
33
#define IDR_VERSION1 1
44
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5
- FILEVERSION 1, 3, 0, 0
6
- PRODUCTVERSION 1, 3, 0, 0
5
+ FILEVERSION 1, 3, 1, 0
6
+ PRODUCTVERSION 1, 3, 1, 0
77
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
88
FILEFLAGS 0
99
FILEOS VOS_DOS_WINDOWS32
1010
FILETYPE VFT_DLL
1111
FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
1515
BLOCK "040904E4"
1616
//language ID = U.S. English, char set = Windows, Multilingual
1717
1818
BEGIN
1919
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20
- VALUE "FileVersion", "1.3.0\0"
20
+ VALUE "FileVersion", "1.3.1\0"
2121
VALUE "InternalName", "zlib\0"
2222
VALUE "OriginalFilename", "zlibwapi.dll\0"
2323
VALUE "ProductName", "ZLib.DLL\0"
2424
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
25
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
2626
END
2727
END
2828
BLOCK "VarFileInfo"
2929
BEGIN
3030
VALUE "Translation", 0x0409, 1252
3131
END
3232
END
3333
--- compat/zlib/contrib/vstudio/vc11/zlib.rc
+++ compat/zlib/contrib/vstudio/vc11/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 0, 0
6 PRODUCTVERSION 1, 3, 0, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.0\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc11/zlib.rc
+++ compat/zlib/contrib/vstudio/vc11/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 1, 0
6 PRODUCTVERSION 1, 3, 1, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.1\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc11/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc11/zlibvc.def
@@ -1,9 +1,9 @@
11
LIBRARY
22
; zlib data compression and ZIP file I/O library
33
4
-VERSION 1.3
4
+VERSION 1.3.1
55
66
EXPORTS
77
adler32 @1
88
compress @2
99
crc32 @3
1010
--- compat/zlib/contrib/vstudio/vc11/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc11/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc11/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc11/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3.1
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc12/zlib.rc
+++ compat/zlib/contrib/vstudio/vc12/zlib.rc
@@ -1,11 +1,11 @@
11
#include <windows.h>
22
33
#define IDR_VERSION1 1
44
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5
- FILEVERSION 1, 3, 0, 0
6
- PRODUCTVERSION 1, 3, 0, 0
5
+ FILEVERSION 1, 3, 1, 0
6
+ PRODUCTVERSION 1, 3, 1, 0
77
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
88
FILEFLAGS 0
99
FILEOS VOS_DOS_WINDOWS32
1010
FILETYPE VFT_DLL
1111
FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
1515
BLOCK "040904E4"
1616
//language ID = U.S. English, char set = Windows, Multilingual
1717
1818
BEGIN
1919
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20
- VALUE "FileVersion", "1.3.0\0"
20
+ VALUE "FileVersion", "1.3.1\0"
2121
VALUE "InternalName", "zlib\0"
2222
VALUE "OriginalFilename", "zlibwapi.dll\0"
2323
VALUE "ProductName", "ZLib.DLL\0"
2424
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
25
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
2626
END
2727
END
2828
BLOCK "VarFileInfo"
2929
BEGIN
3030
VALUE "Translation", 0x0409, 1252
3131
END
3232
END
3333
--- compat/zlib/contrib/vstudio/vc12/zlib.rc
+++ compat/zlib/contrib/vstudio/vc12/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 0, 0
6 PRODUCTVERSION 1, 3, 0, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.0\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc12/zlib.rc
+++ compat/zlib/contrib/vstudio/vc12/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 1, 0
6 PRODUCTVERSION 1, 3, 1, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.1\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc12/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc12/zlibvc.def
@@ -1,9 +1,9 @@
11
LIBRARY
22
; zlib data compression and ZIP file I/O library
33
4
-VERSION 1.3
4
+VERSION 1.3.1
55
66
EXPORTS
77
adler32 @1
88
compress @2
99
crc32 @3
1010
--- compat/zlib/contrib/vstudio/vc12/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc12/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc12/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc12/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3.1
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc14/zlib.rc
+++ compat/zlib/contrib/vstudio/vc14/zlib.rc
@@ -1,11 +1,11 @@
11
#include <windows.h>
22
33
#define IDR_VERSION1 1
44
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5
- FILEVERSION 1, 3, 0, 0
6
- PRODUCTVERSION 1, 3, 0, 0
5
+ FILEVERSION 1, 3, 1, 0
6
+ PRODUCTVERSION 1, 3, 1, 0
77
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
88
FILEFLAGS 0
99
FILEOS VOS_DOS_WINDOWS32
1010
FILETYPE VFT_DLL
1111
FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
1515
BLOCK "040904E4"
1616
//language ID = U.S. English, char set = Windows, Multilingual
1717
1818
BEGIN
1919
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20
- VALUE "FileVersion", "1.3.0\0"
20
+ VALUE "FileVersion", "1.3.1\0"
2121
VALUE "InternalName", "zlib\0"
2222
VALUE "OriginalFilename", "zlibwapi.dll\0"
2323
VALUE "ProductName", "ZLib.DLL\0"
2424
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
25
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
2626
END
2727
END
2828
BLOCK "VarFileInfo"
2929
BEGIN
3030
VALUE "Translation", 0x0409, 1252
3131
END
3232
END
3333
--- compat/zlib/contrib/vstudio/vc14/zlib.rc
+++ compat/zlib/contrib/vstudio/vc14/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 0, 0
6 PRODUCTVERSION 1, 3, 0, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.0\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc14/zlib.rc
+++ compat/zlib/contrib/vstudio/vc14/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 1, 0
6 PRODUCTVERSION 1, 3, 1, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.1\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc14/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc14/zlibvc.def
@@ -1,9 +1,9 @@
11
LIBRARY
22
; zlib data compression and ZIP file I/O library
33
4
-VERSION 1.3
4
+VERSION 1.3.1
55
66
EXPORTS
77
adler32 @1
88
compress @2
99
crc32 @3
1010
--- compat/zlib/contrib/vstudio/vc14/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc14/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc14/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc14/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3.1
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc9/zlib.rc
+++ compat/zlib/contrib/vstudio/vc9/zlib.rc
@@ -1,11 +1,11 @@
11
#include <windows.h>
22
33
#define IDR_VERSION1 1
44
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5
- FILEVERSION 1, 3, 0, 0
6
- PRODUCTVERSION 1, 3, 0, 0
5
+ FILEVERSION 1, 3, 1, 0
6
+ PRODUCTVERSION 1, 3, 1, 0
77
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
88
FILEFLAGS 0
99
FILEOS VOS_DOS_WINDOWS32
1010
FILETYPE VFT_DLL
1111
FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
1515
BLOCK "040904E4"
1616
//language ID = U.S. English, char set = Windows, Multilingual
1717
1818
BEGIN
1919
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20
- VALUE "FileVersion", "1.3.0\0"
20
+ VALUE "FileVersion", "1.3.1\0"
2121
VALUE "InternalName", "zlib\0"
2222
VALUE "OriginalFilename", "zlibwapi.dll\0"
2323
VALUE "ProductName", "ZLib.DLL\0"
2424
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
25
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
2626
END
2727
END
2828
BLOCK "VarFileInfo"
2929
BEGIN
3030
VALUE "Translation", 0x0409, 1252
3131
END
3232
END
3333
--- compat/zlib/contrib/vstudio/vc9/zlib.rc
+++ compat/zlib/contrib/vstudio/vc9/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 0, 0
6 PRODUCTVERSION 1, 3, 0, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.0\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc9/zlib.rc
+++ compat/zlib/contrib/vstudio/vc9/zlib.rc
@@ -1,11 +1,11 @@
1 #include <windows.h>
2
3 #define IDR_VERSION1 1
4 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
5 FILEVERSION 1, 3, 1, 0
6 PRODUCTVERSION 1, 3, 1, 0
7 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
8 FILEFLAGS 0
9 FILEOS VOS_DOS_WINDOWS32
10 FILETYPE VFT_DLL
11 FILESUBTYPE 0 // not used
@@ -15,18 +15,18 @@
15 BLOCK "040904E4"
16 //language ID = U.S. English, char set = Windows, Multilingual
17
18 BEGIN
19 VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
20 VALUE "FileVersion", "1.3.1\0"
21 VALUE "InternalName", "zlib\0"
22 VALUE "OriginalFilename", "zlibwapi.dll\0"
23 VALUE "ProductName", "ZLib.DLL\0"
24 VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
25 VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
26 END
27 END
28 BLOCK "VarFileInfo"
29 BEGIN
30 VALUE "Translation", 0x0409, 1252
31 END
32 END
33
--- compat/zlib/contrib/vstudio/vc9/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc9/zlibvc.def
@@ -1,9 +1,9 @@
11
LIBRARY
22
; zlib data compression and ZIP file I/O library
33
4
-VERSION 1.3
4
+VERSION 1.3.1
55
66
EXPORTS
77
adler32 @1
88
compress @2
99
crc32 @3
1010
--- compat/zlib/contrib/vstudio/vc9/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc9/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/contrib/vstudio/vc9/zlibvc.def
+++ compat/zlib/contrib/vstudio/vc9/zlibvc.def
@@ -1,9 +1,9 @@
1 LIBRARY
2 ; zlib data compression and ZIP file I/O library
3
4 VERSION 1.3.1
5
6 EXPORTS
7 adler32 @1
8 compress @2
9 crc32 @3
10
--- compat/zlib/deflate.c
+++ compat/zlib/deflate.c
@@ -1,7 +1,7 @@
11
/* deflate.c -- compress data using the deflation algorithm
2
- * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/*
77
* ALGORITHM
@@ -50,11 +50,11 @@
5050
/* @(#) $Id$ */
5151
5252
#include "deflate.h"
5353
5454
const char deflate_copyright[] =
55
- " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
55
+ " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
5656
/*
5757
If you use the zlib library in a product, an acknowledgment is welcome
5858
in the documentation of your product. If for some reason you cannot
5959
include such an acknowledgment, I would appreciate that you keep this
6060
copyright string in the executable of your product.
@@ -491,22 +491,28 @@
491491
* Therefore its average symbol length is assured to be less than 31. So
492492
* the compressed data for a dynamic block also cannot overwrite the
493493
* symbols from which it is being constructed.
494494
*/
495495
496
- s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
496
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
497497
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
498498
499499
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
500500
s->pending_buf == Z_NULL) {
501501
s->status = FINISH_STATE;
502502
strm->msg = ERR_MSG(Z_MEM_ERROR);
503503
deflateEnd (strm);
504504
return Z_MEM_ERROR;
505505
}
506
+#ifdef LIT_MEM
507
+ s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
508
+ s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
509
+ s->sym_end = s->lit_bufsize - 1;
510
+#else
506511
s->sym_buf = s->pending_buf + s->lit_bufsize;
507512
s->sym_end = (s->lit_bufsize - 1) * 3;
513
+#endif
508514
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
509515
* on 16 bit machines and because stored blocks are restricted to
510516
* 64K-1 bytes.
511517
*/
512518
@@ -718,13 +724,19 @@
718724
deflate_state *s;
719725
int put;
720726
721727
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
722728
s = strm->state;
729
+#ifdef LIT_MEM
730
+ if (bits < 0 || bits > 16 ||
731
+ (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
732
+ return Z_BUF_ERROR;
733
+#else
723734
if (bits < 0 || bits > 16 ||
724735
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
725736
return Z_BUF_ERROR;
737
+#endif
726738
do {
727739
put = Buf_size - s->bi_valid;
728740
if (put > bits)
729741
put = bits;
730742
s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
@@ -1292,11 +1304,11 @@
12921304
ds->strm = dest;
12931305
12941306
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
12951307
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
12961308
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
1297
- ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
1309
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
12981310
12991311
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
13001312
ds->pending_buf == Z_NULL) {
13011313
deflateEnd (dest);
13021314
return Z_MEM_ERROR;
@@ -1303,14 +1315,19 @@
13031315
}
13041316
/* following zmemcpy do not work for 16-bit MSDOS */
13051317
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
13061318
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
13071319
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
1308
- zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
1320
+ zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
13091321
13101322
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
1323
+#ifdef LIT_MEM
1324
+ ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
1325
+ ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
1326
+#else
13111327
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
1328
+#endif
13121329
13131330
ds->l_desc.dyn_tree = ds->dyn_ltree;
13141331
ds->d_desc.dyn_tree = ds->dyn_dtree;
13151332
ds->bl_desc.dyn_tree = ds->bl_tree;
13161333
@@ -1537,17 +1554,25 @@
15371554
/* ===========================================================================
15381555
* Check that the match at match_start is indeed a match.
15391556
*/
15401557
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
15411558
/* check that the match is indeed a match */
1542
- if (zmemcmp(s->window + match,
1543
- s->window + start, length) != EQUAL) {
1544
- fprintf(stderr, " start %u, match %u, length %d\n",
1545
- start, match, length);
1559
+ Bytef *back = s->window + (int)match, *here = s->window + start;
1560
+ IPos len = length;
1561
+ if (match == (IPos)-1) {
1562
+ /* match starts one byte before the current window -- just compare the
1563
+ subsequent length-1 bytes */
1564
+ back++;
1565
+ here++;
1566
+ len--;
1567
+ }
1568
+ if (zmemcmp(back, here, len) != EQUAL) {
1569
+ fprintf(stderr, " start %u, match %d, length %d\n",
1570
+ start, (int)match, length);
15461571
do {
1547
- fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
1548
- } while (--length != 0);
1572
+ fprintf(stderr, "(%02x %02x)", *back++, *here++);
1573
+ } while (--len != 0);
15491574
z_error("invalid match");
15501575
}
15511576
if (z_verbose > 1) {
15521577
fprintf(stderr,"\\[%d,%d]", start - match, length);
15531578
do { putc(s->window[start++], stderr); } while (--length != 0);
15541579
--- compat/zlib/deflate.c
+++ compat/zlib/deflate.c
@@ -1,7 +1,7 @@
1 /* deflate.c -- compress data using the deflation algorithm
2 * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /*
7 * ALGORITHM
@@ -50,11 +50,11 @@
50 /* @(#) $Id$ */
51
52 #include "deflate.h"
53
54 const char deflate_copyright[] =
55 " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
56 /*
57 If you use the zlib library in a product, an acknowledgment is welcome
58 in the documentation of your product. If for some reason you cannot
59 include such an acknowledgment, I would appreciate that you keep this
60 copyright string in the executable of your product.
@@ -491,22 +491,28 @@
491 * Therefore its average symbol length is assured to be less than 31. So
492 * the compressed data for a dynamic block also cannot overwrite the
493 * symbols from which it is being constructed.
494 */
495
496 s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
497 s->pending_buf_size = (ulg)s->lit_bufsize * 4;
498
499 if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
500 s->pending_buf == Z_NULL) {
501 s->status = FINISH_STATE;
502 strm->msg = ERR_MSG(Z_MEM_ERROR);
503 deflateEnd (strm);
504 return Z_MEM_ERROR;
505 }
 
 
 
 
 
506 s->sym_buf = s->pending_buf + s->lit_bufsize;
507 s->sym_end = (s->lit_bufsize - 1) * 3;
 
508 /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
509 * on 16 bit machines and because stored blocks are restricted to
510 * 64K-1 bytes.
511 */
512
@@ -718,13 +724,19 @@
718 deflate_state *s;
719 int put;
720
721 if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
722 s = strm->state;
 
 
 
 
 
723 if (bits < 0 || bits > 16 ||
724 s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
725 return Z_BUF_ERROR;
 
726 do {
727 put = Buf_size - s->bi_valid;
728 if (put > bits)
729 put = bits;
730 s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
@@ -1292,11 +1304,11 @@
1292 ds->strm = dest;
1293
1294 ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
1295 ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
1296 ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
1297 ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
1298
1299 if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
1300 ds->pending_buf == Z_NULL) {
1301 deflateEnd (dest);
1302 return Z_MEM_ERROR;
@@ -1303,14 +1315,19 @@
1303 }
1304 /* following zmemcpy do not work for 16-bit MSDOS */
1305 zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
1306 zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
1307 zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
1308 zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
1309
1310 ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
 
 
 
 
1311 ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
 
1312
1313 ds->l_desc.dyn_tree = ds->dyn_ltree;
1314 ds->d_desc.dyn_tree = ds->dyn_dtree;
1315 ds->bl_desc.dyn_tree = ds->bl_tree;
1316
@@ -1537,17 +1554,25 @@
1537 /* ===========================================================================
1538 * Check that the match at match_start is indeed a match.
1539 */
1540 local void check_match(deflate_state *s, IPos start, IPos match, int length) {
1541 /* check that the match is indeed a match */
1542 if (zmemcmp(s->window + match,
1543 s->window + start, length) != EQUAL) {
1544 fprintf(stderr, " start %u, match %u, length %d\n",
1545 start, match, length);
 
 
 
 
 
 
 
 
1546 do {
1547 fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
1548 } while (--length != 0);
1549 z_error("invalid match");
1550 }
1551 if (z_verbose > 1) {
1552 fprintf(stderr,"\\[%d,%d]", start - match, length);
1553 do { putc(s->window[start++], stderr); } while (--length != 0);
1554
--- compat/zlib/deflate.c
+++ compat/zlib/deflate.c
@@ -1,7 +1,7 @@
1 /* deflate.c -- compress data using the deflation algorithm
2 * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /*
7 * ALGORITHM
@@ -50,11 +50,11 @@
50 /* @(#) $Id$ */
51
52 #include "deflate.h"
53
54 const char deflate_copyright[] =
55 " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
56 /*
57 If you use the zlib library in a product, an acknowledgment is welcome
58 in the documentation of your product. If for some reason you cannot
59 include such an acknowledgment, I would appreciate that you keep this
60 copyright string in the executable of your product.
@@ -491,22 +491,28 @@
491 * Therefore its average symbol length is assured to be less than 31. So
492 * the compressed data for a dynamic block also cannot overwrite the
493 * symbols from which it is being constructed.
494 */
495
496 s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
497 s->pending_buf_size = (ulg)s->lit_bufsize * 4;
498
499 if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
500 s->pending_buf == Z_NULL) {
501 s->status = FINISH_STATE;
502 strm->msg = ERR_MSG(Z_MEM_ERROR);
503 deflateEnd (strm);
504 return Z_MEM_ERROR;
505 }
506 #ifdef LIT_MEM
507 s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
508 s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
509 s->sym_end = s->lit_bufsize - 1;
510 #else
511 s->sym_buf = s->pending_buf + s->lit_bufsize;
512 s->sym_end = (s->lit_bufsize - 1) * 3;
513 #endif
514 /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
515 * on 16 bit machines and because stored blocks are restricted to
516 * 64K-1 bytes.
517 */
518
@@ -718,13 +724,19 @@
724 deflate_state *s;
725 int put;
726
727 if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
728 s = strm->state;
729 #ifdef LIT_MEM
730 if (bits < 0 || bits > 16 ||
731 (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
732 return Z_BUF_ERROR;
733 #else
734 if (bits < 0 || bits > 16 ||
735 s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
736 return Z_BUF_ERROR;
737 #endif
738 do {
739 put = Buf_size - s->bi_valid;
740 if (put > bits)
741 put = bits;
742 s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
@@ -1292,11 +1304,11 @@
1304 ds->strm = dest;
1305
1306 ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
1307 ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
1308 ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
1309 ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
1310
1311 if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
1312 ds->pending_buf == Z_NULL) {
1313 deflateEnd (dest);
1314 return Z_MEM_ERROR;
@@ -1303,14 +1315,19 @@
1315 }
1316 /* following zmemcpy do not work for 16-bit MSDOS */
1317 zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
1318 zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
1319 zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
1320 zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
1321
1322 ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
1323 #ifdef LIT_MEM
1324 ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
1325 ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
1326 #else
1327 ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
1328 #endif
1329
1330 ds->l_desc.dyn_tree = ds->dyn_ltree;
1331 ds->d_desc.dyn_tree = ds->dyn_dtree;
1332 ds->bl_desc.dyn_tree = ds->bl_tree;
1333
@@ -1537,17 +1554,25 @@
1554 /* ===========================================================================
1555 * Check that the match at match_start is indeed a match.
1556 */
1557 local void check_match(deflate_state *s, IPos start, IPos match, int length) {
1558 /* check that the match is indeed a match */
1559 Bytef *back = s->window + (int)match, *here = s->window + start;
1560 IPos len = length;
1561 if (match == (IPos)-1) {
1562 /* match starts one byte before the current window -- just compare the
1563 subsequent length-1 bytes */
1564 back++;
1565 here++;
1566 len--;
1567 }
1568 if (zmemcmp(back, here, len) != EQUAL) {
1569 fprintf(stderr, " start %u, match %d, length %d\n",
1570 start, (int)match, length);
1571 do {
1572 fprintf(stderr, "(%02x %02x)", *back++, *here++);
1573 } while (--len != 0);
1574 z_error("invalid match");
1575 }
1576 if (z_verbose > 1) {
1577 fprintf(stderr,"\\[%d,%d]", start - match, length);
1578 do { putc(s->window[start++], stderr); } while (--length != 0);
1579
--- compat/zlib/deflate.h
+++ compat/zlib/deflate.h
@@ -1,7 +1,7 @@
11
/* deflate.h -- internal compression state
2
- * Copyright (C) 1995-2018 Jean-loup Gailly
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/* WARNING: this file should *not* be used by applications. It is
77
part of the implementation of the compression library and is
@@ -20,10 +20,14 @@
2020
the crc code when it is not needed. For shared libraries, gzip encoding
2121
should be left enabled. */
2222
#ifndef NO_GZIP
2323
# define GZIP
2424
#endif
25
+
26
+/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
27
+ the cost of a larger memory footprint */
28
+/* #define LIT_MEM */
2529
2630
/* ===========================================================================
2731
* Internal compression state.
2832
*/
2933
@@ -215,11 +219,18 @@
215219
216220
uch depth[2*L_CODES+1];
217221
/* Depth of each subtree used as tie breaker for trees of equal frequency
218222
*/
219223
224
+#ifdef LIT_MEM
225
+# define LIT_BUFS 5
226
+ ushf *d_buf; /* buffer for distances */
227
+ uchf *l_buf; /* buffer for literals/lengths */
228
+#else
229
+# define LIT_BUFS 4
220230
uchf *sym_buf; /* buffer for distances and literals/lengths */
231
+#endif
221232
222233
uInt lit_bufsize;
223234
/* Size of match buffer for literals/lengths. There are 4 reasons for
224235
* limiting lit_bufsize to 64K:
225236
* - frequencies can be kept in 16 bit counters
@@ -237,11 +248,11 @@
237248
* fast adaptation but have of course the overhead of transmitting
238249
* trees more frequently.
239250
* - I can't count above 4
240251
*/
241252
242
- uInt sym_next; /* running index in sym_buf */
253
+ uInt sym_next; /* running index in symbol buffer */
243254
uInt sym_end; /* symbol table full when sym_next reaches this */
244255
245256
ulg opt_len; /* bit length of current block with optimal trees */
246257
ulg static_len; /* bit length of current block with static trees */
247258
uInt matches; /* number of string matches in current block */
@@ -316,10 +327,29 @@
316327
#else
317328
extern const uch ZLIB_INTERNAL _length_code[];
318329
extern const uch ZLIB_INTERNAL _dist_code[];
319330
#endif
320331
332
+#ifdef LIT_MEM
333
+# define _tr_tally_lit(s, c, flush) \
334
+ { uch cc = (c); \
335
+ s->d_buf[s->sym_next] = 0; \
336
+ s->l_buf[s->sym_next++] = cc; \
337
+ s->dyn_ltree[cc].Freq++; \
338
+ flush = (s->sym_next == s->sym_end); \
339
+ }
340
+# define _tr_tally_dist(s, distance, length, flush) \
341
+ { uch len = (uch)(length); \
342
+ ush dist = (ush)(distance); \
343
+ s->d_buf[s->sym_next] = dist; \
344
+ s->l_buf[s->sym_next++] = len; \
345
+ dist--; \
346
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
347
+ s->dyn_dtree[d_code(dist)].Freq++; \
348
+ flush = (s->sym_next == s->sym_end); \
349
+ }
350
+#else
321351
# define _tr_tally_lit(s, c, flush) \
322352
{ uch cc = (c); \
323353
s->sym_buf[s->sym_next++] = 0; \
324354
s->sym_buf[s->sym_next++] = 0; \
325355
s->sym_buf[s->sym_next++] = cc; \
@@ -335,12 +365,13 @@
335365
dist--; \
336366
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
337367
s->dyn_dtree[d_code(dist)].Freq++; \
338368
flush = (s->sym_next == s->sym_end); \
339369
}
370
+#endif
340371
#else
341372
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
342373
# define _tr_tally_dist(s, distance, length, flush) \
343374
flush = _tr_tally(s, distance, length)
344375
#endif
345376
346377
#endif /* DEFLATE_H */
347378
--- compat/zlib/deflate.h
+++ compat/zlib/deflate.h
@@ -1,7 +1,7 @@
1 /* deflate.h -- internal compression state
2 * Copyright (C) 1995-2018 Jean-loup Gailly
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* WARNING: this file should *not* be used by applications. It is
7 part of the implementation of the compression library and is
@@ -20,10 +20,14 @@
20 the crc code when it is not needed. For shared libraries, gzip encoding
21 should be left enabled. */
22 #ifndef NO_GZIP
23 # define GZIP
24 #endif
 
 
 
 
25
26 /* ===========================================================================
27 * Internal compression state.
28 */
29
@@ -215,11 +219,18 @@
215
216 uch depth[2*L_CODES+1];
217 /* Depth of each subtree used as tie breaker for trees of equal frequency
218 */
219
 
 
 
 
 
 
220 uchf *sym_buf; /* buffer for distances and literals/lengths */
 
221
222 uInt lit_bufsize;
223 /* Size of match buffer for literals/lengths. There are 4 reasons for
224 * limiting lit_bufsize to 64K:
225 * - frequencies can be kept in 16 bit counters
@@ -237,11 +248,11 @@
237 * fast adaptation but have of course the overhead of transmitting
238 * trees more frequently.
239 * - I can't count above 4
240 */
241
242 uInt sym_next; /* running index in sym_buf */
243 uInt sym_end; /* symbol table full when sym_next reaches this */
244
245 ulg opt_len; /* bit length of current block with optimal trees */
246 ulg static_len; /* bit length of current block with static trees */
247 uInt matches; /* number of string matches in current block */
@@ -316,10 +327,29 @@
316 #else
317 extern const uch ZLIB_INTERNAL _length_code[];
318 extern const uch ZLIB_INTERNAL _dist_code[];
319 #endif
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321 # define _tr_tally_lit(s, c, flush) \
322 { uch cc = (c); \
323 s->sym_buf[s->sym_next++] = 0; \
324 s->sym_buf[s->sym_next++] = 0; \
325 s->sym_buf[s->sym_next++] = cc; \
@@ -335,12 +365,13 @@
335 dist--; \
336 s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
337 s->dyn_dtree[d_code(dist)].Freq++; \
338 flush = (s->sym_next == s->sym_end); \
339 }
 
340 #else
341 # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
342 # define _tr_tally_dist(s, distance, length, flush) \
343 flush = _tr_tally(s, distance, length)
344 #endif
345
346 #endif /* DEFLATE_H */
347
--- compat/zlib/deflate.h
+++ compat/zlib/deflate.h
@@ -1,7 +1,7 @@
1 /* deflate.h -- internal compression state
2 * Copyright (C) 1995-2024 Jean-loup Gailly
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* WARNING: this file should *not* be used by applications. It is
7 part of the implementation of the compression library and is
@@ -20,10 +20,14 @@
20 the crc code when it is not needed. For shared libraries, gzip encoding
21 should be left enabled. */
22 #ifndef NO_GZIP
23 # define GZIP
24 #endif
25
26 /* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
27 the cost of a larger memory footprint */
28 /* #define LIT_MEM */
29
30 /* ===========================================================================
31 * Internal compression state.
32 */
33
@@ -215,11 +219,18 @@
219
220 uch depth[2*L_CODES+1];
221 /* Depth of each subtree used as tie breaker for trees of equal frequency
222 */
223
224 #ifdef LIT_MEM
225 # define LIT_BUFS 5
226 ushf *d_buf; /* buffer for distances */
227 uchf *l_buf; /* buffer for literals/lengths */
228 #else
229 # define LIT_BUFS 4
230 uchf *sym_buf; /* buffer for distances and literals/lengths */
231 #endif
232
233 uInt lit_bufsize;
234 /* Size of match buffer for literals/lengths. There are 4 reasons for
235 * limiting lit_bufsize to 64K:
236 * - frequencies can be kept in 16 bit counters
@@ -237,11 +248,11 @@
248 * fast adaptation but have of course the overhead of transmitting
249 * trees more frequently.
250 * - I can't count above 4
251 */
252
253 uInt sym_next; /* running index in symbol buffer */
254 uInt sym_end; /* symbol table full when sym_next reaches this */
255
256 ulg opt_len; /* bit length of current block with optimal trees */
257 ulg static_len; /* bit length of current block with static trees */
258 uInt matches; /* number of string matches in current block */
@@ -316,10 +327,29 @@
327 #else
328 extern const uch ZLIB_INTERNAL _length_code[];
329 extern const uch ZLIB_INTERNAL _dist_code[];
330 #endif
331
332 #ifdef LIT_MEM
333 # define _tr_tally_lit(s, c, flush) \
334 { uch cc = (c); \
335 s->d_buf[s->sym_next] = 0; \
336 s->l_buf[s->sym_next++] = cc; \
337 s->dyn_ltree[cc].Freq++; \
338 flush = (s->sym_next == s->sym_end); \
339 }
340 # define _tr_tally_dist(s, distance, length, flush) \
341 { uch len = (uch)(length); \
342 ush dist = (ush)(distance); \
343 s->d_buf[s->sym_next] = dist; \
344 s->l_buf[s->sym_next++] = len; \
345 dist--; \
346 s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
347 s->dyn_dtree[d_code(dist)].Freq++; \
348 flush = (s->sym_next == s->sym_end); \
349 }
350 #else
351 # define _tr_tally_lit(s, c, flush) \
352 { uch cc = (c); \
353 s->sym_buf[s->sym_next++] = 0; \
354 s->sym_buf[s->sym_next++] = 0; \
355 s->sym_buf[s->sym_next++] = cc; \
@@ -335,12 +365,13 @@
365 dist--; \
366 s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
367 s->dyn_dtree[d_code(dist)].Freq++; \
368 flush = (s->sym_next == s->sym_end); \
369 }
370 #endif
371 #else
372 # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
373 # define _tr_tally_dist(s, distance, length, flush) \
374 flush = _tr_tally(s, distance, length)
375 #endif
376
377 #endif /* DEFLATE_H */
378
--- compat/zlib/examples/gzlog.c
+++ compat/zlib/examples/gzlog.c
@@ -210,12 +210,12 @@
210210
Recovery procedure:
211211
- If not a replace recovery, read in the foo.add file, and provide that data
212212
to the appropriate recovery below. If there is no foo.add file, provide
213213
a zero data length to the recovery. In that case, the append recovery
214214
restores the foo.gz to the previous compressed + uncompressed data state.
215
- For the the compress recovery, a missing foo.add file results in foo.gz
216
- being restored to the previous compressed-only data state.
215
+ For the compress recovery, a missing foo.add file results in foo.gz being
216
+ restored to the previous compressed-only data state.
217217
- Append recovery:
218218
- Pick up append at + step above
219219
- Compress recovery:
220220
- Pick up compress at * step above
221221
- Replace recovery:
222222
--- compat/zlib/examples/gzlog.c
+++ compat/zlib/examples/gzlog.c
@@ -210,12 +210,12 @@
210 Recovery procedure:
211 - If not a replace recovery, read in the foo.add file, and provide that data
212 to the appropriate recovery below. If there is no foo.add file, provide
213 a zero data length to the recovery. In that case, the append recovery
214 restores the foo.gz to the previous compressed + uncompressed data state.
215 For the the compress recovery, a missing foo.add file results in foo.gz
216 being restored to the previous compressed-only data state.
217 - Append recovery:
218 - Pick up append at + step above
219 - Compress recovery:
220 - Pick up compress at * step above
221 - Replace recovery:
222
--- compat/zlib/examples/gzlog.c
+++ compat/zlib/examples/gzlog.c
@@ -210,12 +210,12 @@
210 Recovery procedure:
211 - If not a replace recovery, read in the foo.add file, and provide that data
212 to the appropriate recovery below. If there is no foo.add file, provide
213 a zero data length to the recovery. In that case, the append recovery
214 restores the foo.gz to the previous compressed + uncompressed data state.
215 For the compress recovery, a missing foo.add file results in foo.gz being
216 restored to the previous compressed-only data state.
217 - Append recovery:
218 - Pick up append at + step above
219 - Compress recovery:
220 - Pick up compress at * step above
221 - Replace recovery:
222
--- compat/zlib/examples/zran.c
+++ compat/zlib/examples/zran.c
@@ -265,11 +265,11 @@
265265
k = 8; // now at a byte boundary
266266
*++in = value;
267267
}
268268
}
269269
270
-// Insert enough bits in the form of empty deflate blocks in front of the the
270
+// Insert enough bits in the form of empty deflate blocks in front of the
271271
// low bits bits of value, in order to bring the sequence to a byte boundary.
272272
// Then feed that to inflate(). This does what inflatePrime() does, except that
273273
// a negative value of bits is not supported. bits must be in 0..16. If the
274274
// arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return
275275
// value from inflate() is returned.
276276
--- compat/zlib/examples/zran.c
+++ compat/zlib/examples/zran.c
@@ -265,11 +265,11 @@
265 k = 8; // now at a byte boundary
266 *++in = value;
267 }
268 }
269
270 // Insert enough bits in the form of empty deflate blocks in front of the the
271 // low bits bits of value, in order to bring the sequence to a byte boundary.
272 // Then feed that to inflate(). This does what inflatePrime() does, except that
273 // a negative value of bits is not supported. bits must be in 0..16. If the
274 // arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return
275 // value from inflate() is returned.
276
--- compat/zlib/examples/zran.c
+++ compat/zlib/examples/zran.c
@@ -265,11 +265,11 @@
265 k = 8; // now at a byte boundary
266 *++in = value;
267 }
268 }
269
270 // Insert enough bits in the form of empty deflate blocks in front of the
271 // low bits bits of value, in order to bring the sequence to a byte boundary.
272 // Then feed that to inflate(). This does what inflatePrime() does, except that
273 // a negative value of bits is not supported. bits must be in 0..16. If the
274 // arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return
275 // value from inflate() is returned.
276
--- compat/zlib/gzguts.h
+++ compat/zlib/gzguts.h
@@ -1,7 +1,7 @@
11
/* gzguts.h -- zlib internal header definitions for gz* operations
2
- * Copyright (C) 2004-2019 Mark Adler
2
+ * Copyright (C) 2004-2024 Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
#ifdef _LARGEFILE64_SOURCE
77
# ifndef _LARGEFILE_SOURCE
@@ -208,11 +208,7 @@
208208
#endif
209209
210210
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
211211
value -- needed when comparing unsigned to z_off64_t, which is signed
212212
(possible z_off64_t types off_t, off64_t, and long are all signed) */
213
-#ifdef INT_MAX
214
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
215
-#else
216213
unsigned ZLIB_INTERNAL gz_intmax(void);
217
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
218
-#endif
214
+#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
219215
--- compat/zlib/gzguts.h
+++ compat/zlib/gzguts.h
@@ -1,7 +1,7 @@
1 /* gzguts.h -- zlib internal header definitions for gz* operations
2 * Copyright (C) 2004-2019 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #ifdef _LARGEFILE64_SOURCE
7 # ifndef _LARGEFILE_SOURCE
@@ -208,11 +208,7 @@
208 #endif
209
210 /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
211 value -- needed when comparing unsigned to z_off64_t, which is signed
212 (possible z_off64_t types off_t, off64_t, and long are all signed) */
213 #ifdef INT_MAX
214 # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
215 #else
216 unsigned ZLIB_INTERNAL gz_intmax(void);
217 # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
218 #endif
219
--- compat/zlib/gzguts.h
+++ compat/zlib/gzguts.h
@@ -1,7 +1,7 @@
1 /* gzguts.h -- zlib internal header definitions for gz* operations
2 * Copyright (C) 2004-2024 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #ifdef _LARGEFILE64_SOURCE
7 # ifndef _LARGEFILE_SOURCE
@@ -208,11 +208,7 @@
208 #endif
209
210 /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
211 value -- needed when comparing unsigned to z_off64_t, which is signed
212 (possible z_off64_t types off_t, off64_t, and long are all signed) */
 
 
 
213 unsigned ZLIB_INTERNAL gz_intmax(void);
214 #define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
 
215
--- compat/zlib/gzlib.c
+++ compat/zlib/gzlib.c
@@ -1,7 +1,7 @@
11
/* gzlib.c -- zlib functions common to reading and writing gzip files
2
- * Copyright (C) 2004-2019 Mark Adler
2
+ * Copyright (C) 2004-2024 Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
#include "gzguts.h"
77
@@ -561,22 +561,22 @@
561561
strcat(state->msg, ": ");
562562
strcat(state->msg, msg);
563563
#endif
564564
}
565565
566
-#ifndef INT_MAX
567566
/* portably return maximum value for an int (when limits.h presumed not
568567
available) -- we need to do this to cover cases where 2's complement not
569568
used, since C standard permits 1's complement and sign-bit representations,
570569
otherwise we could just use ((unsigned)-1) >> 1 */
571570
unsigned ZLIB_INTERNAL gz_intmax(void) {
572
- unsigned p, q;
573
-
574
- p = 1;
571
+#ifdef INT_MAX
572
+ return INT_MAX;
573
+#else
574
+ unsigned p = 1, q;
575575
do {
576576
q = p;
577577
p <<= 1;
578578
p++;
579579
} while (p > q);
580580
return q >> 1;
581
-}
582581
#endif
582
+}
583583
--- compat/zlib/gzlib.c
+++ compat/zlib/gzlib.c
@@ -1,7 +1,7 @@
1 /* gzlib.c -- zlib functions common to reading and writing gzip files
2 * Copyright (C) 2004-2019 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "gzguts.h"
7
@@ -561,22 +561,22 @@
561 strcat(state->msg, ": ");
562 strcat(state->msg, msg);
563 #endif
564 }
565
566 #ifndef INT_MAX
567 /* portably return maximum value for an int (when limits.h presumed not
568 available) -- we need to do this to cover cases where 2's complement not
569 used, since C standard permits 1's complement and sign-bit representations,
570 otherwise we could just use ((unsigned)-1) >> 1 */
571 unsigned ZLIB_INTERNAL gz_intmax(void) {
572 unsigned p, q;
573
574 p = 1;
 
575 do {
576 q = p;
577 p <<= 1;
578 p++;
579 } while (p > q);
580 return q >> 1;
581 }
582 #endif
 
583
--- compat/zlib/gzlib.c
+++ compat/zlib/gzlib.c
@@ -1,7 +1,7 @@
1 /* gzlib.c -- zlib functions common to reading and writing gzip files
2 * Copyright (C) 2004-2024 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "gzguts.h"
7
@@ -561,22 +561,22 @@
561 strcat(state->msg, ": ");
562 strcat(state->msg, msg);
563 #endif
564 }
565
 
566 /* portably return maximum value for an int (when limits.h presumed not
567 available) -- we need to do this to cover cases where 2's complement not
568 used, since C standard permits 1's complement and sign-bit representations,
569 otherwise we could just use ((unsigned)-1) >> 1 */
570 unsigned ZLIB_INTERNAL gz_intmax(void) {
571 #ifdef INT_MAX
572 return INT_MAX;
573 #else
574 unsigned p = 1, q;
575 do {
576 q = p;
577 p <<= 1;
578 p++;
579 } while (p > q);
580 return q >> 1;
 
581 #endif
582 }
583
--- compat/zlib/inflate.c
+++ compat/zlib/inflate.c
@@ -1385,11 +1385,11 @@
13851385
if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
13861386
13871387
/* if first time, start search in bit buffer */
13881388
if (state->mode != SYNC) {
13891389
state->mode = SYNC;
1390
- state->hold <<= state->bits & 7;
1390
+ state->hold >>= state->bits & 7;
13911391
state->bits -= state->bits & 7;
13921392
len = 0;
13931393
while (state->bits >= 8) {
13941394
buf[len++] = (unsigned char)(state->hold);
13951395
state->hold >>= 8;
13961396
--- compat/zlib/inflate.c
+++ compat/zlib/inflate.c
@@ -1385,11 +1385,11 @@
1385 if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
1386
1387 /* if first time, start search in bit buffer */
1388 if (state->mode != SYNC) {
1389 state->mode = SYNC;
1390 state->hold <<= state->bits & 7;
1391 state->bits -= state->bits & 7;
1392 len = 0;
1393 while (state->bits >= 8) {
1394 buf[len++] = (unsigned char)(state->hold);
1395 state->hold >>= 8;
1396
--- compat/zlib/inflate.c
+++ compat/zlib/inflate.c
@@ -1385,11 +1385,11 @@
1385 if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
1386
1387 /* if first time, start search in bit buffer */
1388 if (state->mode != SYNC) {
1389 state->mode = SYNC;
1390 state->hold >>= state->bits & 7;
1391 state->bits -= state->bits & 7;
1392 len = 0;
1393 while (state->bits >= 8) {
1394 buf[len++] = (unsigned char)(state->hold);
1395 state->hold >>= 8;
1396
--- compat/zlib/inftrees.c
+++ compat/zlib/inftrees.c
@@ -1,17 +1,17 @@
11
/* inftrees.c -- generate Huffman trees for efficient decoding
2
- * Copyright (C) 1995-2023 Mark Adler
2
+ * Copyright (C) 1995-2024 Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
#include "zutil.h"
77
#include "inftrees.h"
88
99
#define MAXBITS 15
1010
1111
const char inflate_copyright[] =
12
- " inflate 1.3 Copyright 1995-2023 Mark Adler ";
12
+ " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
1313
/*
1414
If you use the zlib library in a product, an acknowledgment is welcome
1515
in the documentation of your product. If for some reason you cannot
1616
include such an acknowledgment, I would appreciate that you keep this
1717
copyright string in the executable of your product.
@@ -55,11 +55,11 @@
5555
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
5656
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
5757
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
5858
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
5959
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
60
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
60
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
6161
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
6262
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
6363
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
6464
8193, 12289, 16385, 24577, 0, 0};
6565
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
6666
--- compat/zlib/inftrees.c
+++ compat/zlib/inftrees.c
@@ -1,17 +1,17 @@
1 /* inftrees.c -- generate Huffman trees for efficient decoding
2 * Copyright (C) 1995-2023 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "zutil.h"
7 #include "inftrees.h"
8
9 #define MAXBITS 15
10
11 const char inflate_copyright[] =
12 " inflate 1.3 Copyright 1995-2023 Mark Adler ";
13 /*
14 If you use the zlib library in a product, an acknowledgment is welcome
15 in the documentation of your product. If for some reason you cannot
16 include such an acknowledgment, I would appreciate that you keep this
17 copyright string in the executable of your product.
@@ -55,11 +55,11 @@
55 static const unsigned short lbase[31] = { /* Length codes 257..285 base */
56 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
57 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
58 static const unsigned short lext[31] = { /* Length codes 257..285 extra */
59 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
60 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
61 static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
62 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
63 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
64 8193, 12289, 16385, 24577, 0, 0};
65 static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
66
--- compat/zlib/inftrees.c
+++ compat/zlib/inftrees.c
@@ -1,17 +1,17 @@
1 /* inftrees.c -- generate Huffman trees for efficient decoding
2 * Copyright (C) 1995-2024 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "zutil.h"
7 #include "inftrees.h"
8
9 #define MAXBITS 15
10
11 const char inflate_copyright[] =
12 " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
13 /*
14 If you use the zlib library in a product, an acknowledgment is welcome
15 in the documentation of your product. If for some reason you cannot
16 include such an acknowledgment, I would appreciate that you keep this
17 copyright string in the executable of your product.
@@ -55,11 +55,11 @@
55 static const unsigned short lbase[31] = { /* Length codes 257..285 base */
56 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
57 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
58 static const unsigned short lext[31] = { /* Length codes 257..285 extra */
59 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
60 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
61 static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
62 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
63 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
64 8193, 12289, 16385, 24577, 0, 0};
65 static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
66
--- compat/zlib/inftrees.h
+++ compat/zlib/inftrees.h
@@ -39,12 +39,12 @@
3939
1444, which is the sum of 852 for literal/length codes and 592 for distance
4040
codes. These values were found by exhaustive searches using the program
4141
examples/enough.c found in the zlib distribution. The arguments to that
4242
program are the number of symbols, the initial root table size, and the
4343
maximum bit length of a code. "enough 286 9 15" for literal/length codes
44
- returns returns 852, and "enough 30 6 15" for distance codes returns 592.
45
- The initial root table size (9 or 6) is found in the fifth argument of the
44
+ returns 852, and "enough 30 6 15" for distance codes returns 592. The
45
+ initial root table size (9 or 6) is found in the fifth argument of the
4646
inflate_table() calls in inflate.c and infback.c. If the root table size is
4747
changed, then these maximum sizes would be need to be recalculated and
4848
updated. */
4949
#define ENOUGH_LENS 852
5050
#define ENOUGH_DISTS 592
5151
--- compat/zlib/inftrees.h
+++ compat/zlib/inftrees.h
@@ -39,12 +39,12 @@
39 1444, which is the sum of 852 for literal/length codes and 592 for distance
40 codes. These values were found by exhaustive searches using the program
41 examples/enough.c found in the zlib distribution. The arguments to that
42 program are the number of symbols, the initial root table size, and the
43 maximum bit length of a code. "enough 286 9 15" for literal/length codes
44 returns returns 852, and "enough 30 6 15" for distance codes returns 592.
45 The initial root table size (9 or 6) is found in the fifth argument of the
46 inflate_table() calls in inflate.c and infback.c. If the root table size is
47 changed, then these maximum sizes would be need to be recalculated and
48 updated. */
49 #define ENOUGH_LENS 852
50 #define ENOUGH_DISTS 592
51
--- compat/zlib/inftrees.h
+++ compat/zlib/inftrees.h
@@ -39,12 +39,12 @@
39 1444, which is the sum of 852 for literal/length codes and 592 for distance
40 codes. These values were found by exhaustive searches using the program
41 examples/enough.c found in the zlib distribution. The arguments to that
42 program are the number of symbols, the initial root table size, and the
43 maximum bit length of a code. "enough 286 9 15" for literal/length codes
44 returns 852, and "enough 30 6 15" for distance codes returns 592. The
45 initial root table size (9 or 6) is found in the fifth argument of the
46 inflate_table() calls in inflate.c and infback.c. If the root table size is
47 changed, then these maximum sizes would be need to be recalculated and
48 updated. */
49 #define ENOUGH_LENS 852
50 #define ENOUGH_DISTS 592
51
--- compat/zlib/old/visual-basic.txt
+++ compat/zlib/old/visual-basic.txt
@@ -113,11 +113,11 @@
113113
SUCCESS Then
114114
lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
115115
ReDim Preserve bytaryCpr(lngCprSiz - 1)
116116
Open strCprPth For Binary Access Write As #1
117117
Put #1, , bytaryCpr()
118
- Put #1, , lngOriSiz 'Add the the original size value to the end
118
+ Put #1, , lngOriSiz 'Add the original size value to the end
119119
(last 4 bytes)
120120
Close #1
121121
Else
122122
MsgBox "Compression error"
123123
End If
124124
--- compat/zlib/old/visual-basic.txt
+++ compat/zlib/old/visual-basic.txt
@@ -113,11 +113,11 @@
113 SUCCESS Then
114 lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
115 ReDim Preserve bytaryCpr(lngCprSiz - 1)
116 Open strCprPth For Binary Access Write As #1
117 Put #1, , bytaryCpr()
118 Put #1, , lngOriSiz 'Add the the original size value to the end
119 (last 4 bytes)
120 Close #1
121 Else
122 MsgBox "Compression error"
123 End If
124
--- compat/zlib/old/visual-basic.txt
+++ compat/zlib/old/visual-basic.txt
@@ -113,11 +113,11 @@
113 SUCCESS Then
114 lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
115 ReDim Preserve bytaryCpr(lngCprSiz - 1)
116 Open strCprPth For Binary Access Write As #1
117 Put #1, , bytaryCpr()
118 Put #1, , lngOriSiz 'Add the original size value to the end
119 (last 4 bytes)
120 Close #1
121 Else
122 MsgBox "Compression error"
123 End If
124
--- compat/zlib/os400/README400
+++ compat/zlib/os400/README400
@@ -1,6 +1,6 @@
1
- ZLIB version 1.3.0 for OS/400 installation instructions
1
+ ZLIB version 1.3.1 for OS/400 installation instructions
22
33
1) Download and unpack the zlib tarball to some IFS directory.
44
(i.e.: /path/to/the/zlib/ifs/source/directory)
55
66
If the installed IFS command supports gzip format, this is straightforward,
77
--- compat/zlib/os400/README400
+++ compat/zlib/os400/README400
@@ -1,6 +1,6 @@
1 ZLIB version 1.3.0 for OS/400 installation instructions
2
3 1) Download and unpack the zlib tarball to some IFS directory.
4 (i.e.: /path/to/the/zlib/ifs/source/directory)
5
6 If the installed IFS command supports gzip format, this is straightforward,
7
--- compat/zlib/os400/README400
+++ compat/zlib/os400/README400
@@ -1,6 +1,6 @@
1 ZLIB version 1.3.1 for OS/400 installation instructions
2
3 1) Download and unpack the zlib tarball to some IFS directory.
4 (i.e.: /path/to/the/zlib/ifs/source/directory)
5
6 If the installed IFS command supports gzip format, this is straightforward,
7
--- compat/zlib/os400/zlib.inc
+++ compat/zlib/os400/zlib.inc
@@ -1,9 +1,9 @@
11
* ZLIB.INC - Interface to the general purpose compression library
22
*
33
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
4
- * Version 1.3.0
4
+ * Version 1.3.1
55
*
66
*
77
* WARNING:
88
* Procedures inflateInit(), inflateInit2(), deflateInit(),
99
* deflateInit2() and inflateBackInit() need to be called with
@@ -20,16 +20,16 @@
2020
* Constants
2121
**************************************************************************
2222
*
2323
* Versioning information.
2424
*
25
- D ZLIB_VERSION C '1.3.0'
25
+ D ZLIB_VERSION C '1.3.1'
2626
D ZLIB_VERNUM C X'12a0'
2727
D ZLIB_VER_MAJOR C 1
2828
D ZLIB_VER_MINOR C 3
2929
D ZLIB_VER_REVISION...
30
- D C 0
30
+ D C 1
3131
D ZLIB_VER_SUBREVISION...
3232
D C 0
3333
*
3434
* Other equates.
3535
*
3636
--- compat/zlib/os400/zlib.inc
+++ compat/zlib/os400/zlib.inc
@@ -1,9 +1,9 @@
1 * ZLIB.INC - Interface to the general purpose compression library
2 *
3 * ILE RPG400 version by Patrick Monnerat, DATASPHERE.
4 * Version 1.3.0
5 *
6 *
7 * WARNING:
8 * Procedures inflateInit(), inflateInit2(), deflateInit(),
9 * deflateInit2() and inflateBackInit() need to be called with
@@ -20,16 +20,16 @@
20 * Constants
21 **************************************************************************
22 *
23 * Versioning information.
24 *
25 D ZLIB_VERSION C '1.3.0'
26 D ZLIB_VERNUM C X'12a0'
27 D ZLIB_VER_MAJOR C 1
28 D ZLIB_VER_MINOR C 3
29 D ZLIB_VER_REVISION...
30 D C 0
31 D ZLIB_VER_SUBREVISION...
32 D C 0
33 *
34 * Other equates.
35 *
36
--- compat/zlib/os400/zlib.inc
+++ compat/zlib/os400/zlib.inc
@@ -1,9 +1,9 @@
1 * ZLIB.INC - Interface to the general purpose compression library
2 *
3 * ILE RPG400 version by Patrick Monnerat, DATASPHERE.
4 * Version 1.3.1
5 *
6 *
7 * WARNING:
8 * Procedures inflateInit(), inflateInit2(), deflateInit(),
9 * deflateInit2() and inflateBackInit() need to be called with
@@ -20,16 +20,16 @@
20 * Constants
21 **************************************************************************
22 *
23 * Versioning information.
24 *
25 D ZLIB_VERSION C '1.3.1'
26 D ZLIB_VERNUM C X'12a0'
27 D ZLIB_VER_MAJOR C 1
28 D ZLIB_VER_MINOR C 3
29 D ZLIB_VER_REVISION...
30 D C 1
31 D ZLIB_VER_SUBREVISION...
32 D C 0
33 *
34 * Other equates.
35 *
36
--- compat/zlib/qnx/package.qpg
+++ compat/zlib/qnx/package.qpg
@@ -23,14 +23,14 @@
2323
2424
<QPG:Values>
2525
<QPG:Files>
2626
<QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
2727
<QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
28
- <QPG:Add file="../libz.so.1.3.0" install="/opt/lib/" user="root:bin" permission="644"/>
29
- <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.3.0"/>
30
- <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.3.0"/>
31
- <QPG:Add file="../libz.so.1.3.0" install="/opt/lib/" component="slib"/>
28
+ <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" user="root:bin" permission="644"/>
29
+ <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.3.1"/>
30
+ <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.3.1"/>
31
+ <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" component="slib"/>
3232
</QPG:Files>
3333
3434
<QPG:PackageFilter>
3535
<QPM:PackageManifest>
3636
<QPM:PackageDescription>
@@ -61,11 +61,11 @@
6161
<QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
6262
<QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
6363
</QPM:ProductDescription>
6464
6565
<QPM:ReleaseDescription>
66
- <QPM:ReleaseVersion>1.3.0</QPM:ReleaseVersion>
66
+ <QPM:ReleaseVersion>1.3.1</QPM:ReleaseVersion>
6767
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
6868
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
6969
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
7070
<QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
7171
<QPM:ExcludeCountries>
7272
--- compat/zlib/qnx/package.qpg
+++ compat/zlib/qnx/package.qpg
@@ -23,14 +23,14 @@
23
24 <QPG:Values>
25 <QPG:Files>
26 <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
27 <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
28 <QPG:Add file="../libz.so.1.3.0" install="/opt/lib/" user="root:bin" permission="644"/>
29 <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.3.0"/>
30 <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.3.0"/>
31 <QPG:Add file="../libz.so.1.3.0" install="/opt/lib/" component="slib"/>
32 </QPG:Files>
33
34 <QPG:PackageFilter>
35 <QPM:PackageManifest>
36 <QPM:PackageDescription>
@@ -61,11 +61,11 @@
61 <QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
62 <QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
63 </QPM:ProductDescription>
64
65 <QPM:ReleaseDescription>
66 <QPM:ReleaseVersion>1.3.0</QPM:ReleaseVersion>
67 <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
68 <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
69 <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
70 <QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
71 <QPM:ExcludeCountries>
72
--- compat/zlib/qnx/package.qpg
+++ compat/zlib/qnx/package.qpg
@@ -23,14 +23,14 @@
23
24 <QPG:Values>
25 <QPG:Files>
26 <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
27 <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
28 <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" user="root:bin" permission="644"/>
29 <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.3.1"/>
30 <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.3.1"/>
31 <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" component="slib"/>
32 </QPG:Files>
33
34 <QPG:PackageFilter>
35 <QPM:PackageManifest>
36 <QPM:PackageDescription>
@@ -61,11 +61,11 @@
61 <QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
62 <QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
63 </QPM:ProductDescription>
64
65 <QPM:ReleaseDescription>
66 <QPM:ReleaseVersion>1.3.1</QPM:ReleaseVersion>
67 <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
68 <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
69 <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
70 <QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
71 <QPM:ExcludeCountries>
72
--- compat/zlib/test/example.c
+++ compat/zlib/test/example.c
@@ -34,16 +34,16 @@
3434
static const char dictionary[] = "hello";
3535
static uLong dictId; /* Adler32 value of the dictionary */
3636
3737
#ifdef Z_SOLO
3838
39
-void *myalloc(void *q, unsigned n, unsigned m) {
39
+static void *myalloc(void *q, unsigned n, unsigned m) {
4040
(void)q;
4141
return calloc(n, m);
4242
}
4343
44
-void myfree(void *q, void *p) {
44
+static void myfree(void *q, void *p) {
4545
(void)q;
4646
free(p);
4747
}
4848
4949
static alloc_func zalloc = myalloc;
@@ -55,11 +55,11 @@
5555
static free_func zfree = (free_func)0;
5656
5757
/* ===========================================================================
5858
* Test compress() and uncompress()
5959
*/
60
-void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
60
+static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
6161
uLong uncomprLen) {
6262
int err;
6363
uLong len = (uLong)strlen(hello)+1;
6464
6565
err = compress(compr, &comprLen, (const Bytef*)hello, len);
@@ -79,11 +79,11 @@
7979
}
8080
8181
/* ===========================================================================
8282
* Test read/write of .gz files
8383
*/
84
-void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
84
+static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
8585
#ifdef NO_GZCOMPRESS
8686
fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
8787
#else
8888
int err;
8989
int len = (int)strlen(hello)+1;
@@ -161,11 +161,11 @@
161161
#endif /* Z_SOLO */
162162
163163
/* ===========================================================================
164164
* Test deflate() with small buffers
165165
*/
166
-void test_deflate(Byte *compr, uLong comprLen) {
166
+static void test_deflate(Byte *compr, uLong comprLen) {
167167
z_stream c_stream; /* compression stream */
168168
int err;
169169
uLong len = (uLong)strlen(hello)+1;
170170
171171
c_stream.zalloc = zalloc;
@@ -196,11 +196,11 @@
196196
}
197197
198198
/* ===========================================================================
199199
* Test inflate() with small buffers
200200
*/
201
-void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
201
+static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
202202
uLong uncomprLen) {
203203
int err;
204204
z_stream d_stream; /* decompression stream */
205205
206206
strcpy((char*)uncompr, "garbage");
@@ -235,11 +235,11 @@
235235
}
236236
237237
/* ===========================================================================
238238
* Test deflate() with large buffers and dynamic change of compression level
239239
*/
240
-void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
240
+static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
241241
uLong uncomprLen) {
242242
z_stream c_stream; /* compression stream */
243243
int err;
244244
245245
c_stream.zalloc = zalloc;
@@ -288,11 +288,11 @@
288288
}
289289
290290
/* ===========================================================================
291291
* Test inflate() with large buffers
292292
*/
293
-void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
293
+static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
294294
uLong uncomprLen) {
295295
int err;
296296
z_stream d_stream; /* decompression stream */
297297
298298
strcpy((char*)uncompr, "garbage");
@@ -327,11 +327,11 @@
327327
}
328328
329329
/* ===========================================================================
330330
* Test deflate() with full flush
331331
*/
332
-void test_flush(Byte *compr, uLong *comprLen) {
332
+static void test_flush(Byte *compr, uLong *comprLen) {
333333
z_stream c_stream; /* compression stream */
334334
int err;
335335
uInt len = (uInt)strlen(hello)+1;
336336
337337
c_stream.zalloc = zalloc;
@@ -362,11 +362,12 @@
362362
}
363363
364364
/* ===========================================================================
365365
* Test inflateSync()
366366
*/
367
-void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) {
367
+static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
368
+ uLong uncomprLen) {
368369
int err;
369370
z_stream d_stream; /* decompression stream */
370371
371372
strcpy((char*)uncompr, "garbage");
372373
@@ -402,11 +403,11 @@
402403
}
403404
404405
/* ===========================================================================
405406
* Test deflate() with preset dictionary
406407
*/
407
-void test_dict_deflate(Byte *compr, uLong comprLen) {
408
+static void test_dict_deflate(Byte *compr, uLong comprLen) {
408409
z_stream c_stream; /* compression stream */
409410
int err;
410411
411412
c_stream.zalloc = zalloc;
412413
c_stream.zfree = zfree;
@@ -436,11 +437,11 @@
436437
}
437438
438439
/* ===========================================================================
439440
* Test inflate() with a preset dictionary
440441
*/
441
-void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
442
+static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
442443
uLong uncomprLen) {
443444
int err;
444445
z_stream d_stream; /* decompression stream */
445446
446447
strcpy((char*)uncompr, "garbage");
447448
--- compat/zlib/test/example.c
+++ compat/zlib/test/example.c
@@ -34,16 +34,16 @@
34 static const char dictionary[] = "hello";
35 static uLong dictId; /* Adler32 value of the dictionary */
36
37 #ifdef Z_SOLO
38
39 void *myalloc(void *q, unsigned n, unsigned m) {
40 (void)q;
41 return calloc(n, m);
42 }
43
44 void myfree(void *q, void *p) {
45 (void)q;
46 free(p);
47 }
48
49 static alloc_func zalloc = myalloc;
@@ -55,11 +55,11 @@
55 static free_func zfree = (free_func)0;
56
57 /* ===========================================================================
58 * Test compress() and uncompress()
59 */
60 void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
61 uLong uncomprLen) {
62 int err;
63 uLong len = (uLong)strlen(hello)+1;
64
65 err = compress(compr, &comprLen, (const Bytef*)hello, len);
@@ -79,11 +79,11 @@
79 }
80
81 /* ===========================================================================
82 * Test read/write of .gz files
83 */
84 void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
85 #ifdef NO_GZCOMPRESS
86 fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
87 #else
88 int err;
89 int len = (int)strlen(hello)+1;
@@ -161,11 +161,11 @@
161 #endif /* Z_SOLO */
162
163 /* ===========================================================================
164 * Test deflate() with small buffers
165 */
166 void test_deflate(Byte *compr, uLong comprLen) {
167 z_stream c_stream; /* compression stream */
168 int err;
169 uLong len = (uLong)strlen(hello)+1;
170
171 c_stream.zalloc = zalloc;
@@ -196,11 +196,11 @@
196 }
197
198 /* ===========================================================================
199 * Test inflate() with small buffers
200 */
201 void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
202 uLong uncomprLen) {
203 int err;
204 z_stream d_stream; /* decompression stream */
205
206 strcpy((char*)uncompr, "garbage");
@@ -235,11 +235,11 @@
235 }
236
237 /* ===========================================================================
238 * Test deflate() with large buffers and dynamic change of compression level
239 */
240 void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
241 uLong uncomprLen) {
242 z_stream c_stream; /* compression stream */
243 int err;
244
245 c_stream.zalloc = zalloc;
@@ -288,11 +288,11 @@
288 }
289
290 /* ===========================================================================
291 * Test inflate() with large buffers
292 */
293 void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
294 uLong uncomprLen) {
295 int err;
296 z_stream d_stream; /* decompression stream */
297
298 strcpy((char*)uncompr, "garbage");
@@ -327,11 +327,11 @@
327 }
328
329 /* ===========================================================================
330 * Test deflate() with full flush
331 */
332 void test_flush(Byte *compr, uLong *comprLen) {
333 z_stream c_stream; /* compression stream */
334 int err;
335 uInt len = (uInt)strlen(hello)+1;
336
337 c_stream.zalloc = zalloc;
@@ -362,11 +362,12 @@
362 }
363
364 /* ===========================================================================
365 * Test inflateSync()
366 */
367 void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) {
 
368 int err;
369 z_stream d_stream; /* decompression stream */
370
371 strcpy((char*)uncompr, "garbage");
372
@@ -402,11 +403,11 @@
402 }
403
404 /* ===========================================================================
405 * Test deflate() with preset dictionary
406 */
407 void test_dict_deflate(Byte *compr, uLong comprLen) {
408 z_stream c_stream; /* compression stream */
409 int err;
410
411 c_stream.zalloc = zalloc;
412 c_stream.zfree = zfree;
@@ -436,11 +437,11 @@
436 }
437
438 /* ===========================================================================
439 * Test inflate() with a preset dictionary
440 */
441 void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
442 uLong uncomprLen) {
443 int err;
444 z_stream d_stream; /* decompression stream */
445
446 strcpy((char*)uncompr, "garbage");
447
--- compat/zlib/test/example.c
+++ compat/zlib/test/example.c
@@ -34,16 +34,16 @@
34 static const char dictionary[] = "hello";
35 static uLong dictId; /* Adler32 value of the dictionary */
36
37 #ifdef Z_SOLO
38
39 static void *myalloc(void *q, unsigned n, unsigned m) {
40 (void)q;
41 return calloc(n, m);
42 }
43
44 static void myfree(void *q, void *p) {
45 (void)q;
46 free(p);
47 }
48
49 static alloc_func zalloc = myalloc;
@@ -55,11 +55,11 @@
55 static free_func zfree = (free_func)0;
56
57 /* ===========================================================================
58 * Test compress() and uncompress()
59 */
60 static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
61 uLong uncomprLen) {
62 int err;
63 uLong len = (uLong)strlen(hello)+1;
64
65 err = compress(compr, &comprLen, (const Bytef*)hello, len);
@@ -79,11 +79,11 @@
79 }
80
81 /* ===========================================================================
82 * Test read/write of .gz files
83 */
84 static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
85 #ifdef NO_GZCOMPRESS
86 fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
87 #else
88 int err;
89 int len = (int)strlen(hello)+1;
@@ -161,11 +161,11 @@
161 #endif /* Z_SOLO */
162
163 /* ===========================================================================
164 * Test deflate() with small buffers
165 */
166 static void test_deflate(Byte *compr, uLong comprLen) {
167 z_stream c_stream; /* compression stream */
168 int err;
169 uLong len = (uLong)strlen(hello)+1;
170
171 c_stream.zalloc = zalloc;
@@ -196,11 +196,11 @@
196 }
197
198 /* ===========================================================================
199 * Test inflate() with small buffers
200 */
201 static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
202 uLong uncomprLen) {
203 int err;
204 z_stream d_stream; /* decompression stream */
205
206 strcpy((char*)uncompr, "garbage");
@@ -235,11 +235,11 @@
235 }
236
237 /* ===========================================================================
238 * Test deflate() with large buffers and dynamic change of compression level
239 */
240 static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
241 uLong uncomprLen) {
242 z_stream c_stream; /* compression stream */
243 int err;
244
245 c_stream.zalloc = zalloc;
@@ -288,11 +288,11 @@
288 }
289
290 /* ===========================================================================
291 * Test inflate() with large buffers
292 */
293 static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
294 uLong uncomprLen) {
295 int err;
296 z_stream d_stream; /* decompression stream */
297
298 strcpy((char*)uncompr, "garbage");
@@ -327,11 +327,11 @@
327 }
328
329 /* ===========================================================================
330 * Test deflate() with full flush
331 */
332 static void test_flush(Byte *compr, uLong *comprLen) {
333 z_stream c_stream; /* compression stream */
334 int err;
335 uInt len = (uInt)strlen(hello)+1;
336
337 c_stream.zalloc = zalloc;
@@ -362,11 +362,12 @@
362 }
363
364 /* ===========================================================================
365 * Test inflateSync()
366 */
367 static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
368 uLong uncomprLen) {
369 int err;
370 z_stream d_stream; /* decompression stream */
371
372 strcpy((char*)uncompr, "garbage");
373
@@ -402,11 +403,11 @@
403 }
404
405 /* ===========================================================================
406 * Test deflate() with preset dictionary
407 */
408 static void test_dict_deflate(Byte *compr, uLong comprLen) {
409 z_stream c_stream; /* compression stream */
410 int err;
411
412 c_stream.zalloc = zalloc;
413 c_stream.zfree = zfree;
@@ -436,11 +437,11 @@
437 }
438
439 /* ===========================================================================
440 * Test inflate() with a preset dictionary
441 */
442 static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
443 uLong uncomprLen) {
444 int err;
445 z_stream d_stream; /* decompression stream */
446
447 strcpy((char*)uncompr, "garbage");
448
--- compat/zlib/test/minigzip.c
+++ compat/zlib/test/minigzip.c
@@ -147,16 +147,16 @@
147147
148148
#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
149149
# include <unistd.h> /* for unlink() */
150150
#endif
151151
152
-void *myalloc(void *q, unsigned n, unsigned m) {
152
+static void *myalloc(void *q, unsigned n, unsigned m) {
153153
(void)q;
154154
return calloc(n, m);
155155
}
156156
157
-void myfree(void *q, void *p) {
157
+static void myfree(void *q, void *p) {
158158
(void)q;
159159
free(p);
160160
}
161161
162162
typedef struct gzFile_s {
@@ -165,11 +165,11 @@
165165
int err;
166166
char *msg;
167167
z_stream strm;
168168
} *gzFile;
169169
170
-gzFile gz_open(const char *path, int fd, const char *mode) {
170
+static gzFile gz_open(const char *path, int fd, const char *mode) {
171171
gzFile gz;
172172
int ret;
173173
174174
gz = malloc(sizeof(struct gzFile_s));
175175
if (gz == NULL)
@@ -199,19 +199,19 @@
199199
gz->err = 0;
200200
gz->msg = "";
201201
return gz;
202202
}
203203
204
-gzFile gzopen(const char *path, const char *mode) {
204
+static gzFile gzopen(const char *path, const char *mode) {
205205
return gz_open(path, -1, mode);
206206
}
207207
208
-gzFile gzdopen(int fd, const char *mode) {
208
+static gzFile gzdopen(int fd, const char *mode) {
209209
return gz_open(NULL, fd, mode);
210210
}
211211
212
-int gzwrite(gzFile gz, const void *buf, unsigned len) {
212
+static int gzwrite(gzFile gz, const void *buf, unsigned len) {
213213
z_stream *strm;
214214
unsigned char out[BUFLEN];
215215
216216
if (gz == NULL || !gz->write)
217217
return 0;
@@ -225,11 +225,11 @@
225225
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
226226
} while (strm->avail_out == 0);
227227
return len;
228228
}
229229
230
-int gzread(gzFile gz, void *buf, unsigned len) {
230
+static int gzread(gzFile gz, void *buf, unsigned len) {
231231
int ret;
232232
unsigned got;
233233
unsigned char in[1];
234234
z_stream *strm;
235235
@@ -256,11 +256,11 @@
256256
inflateReset(strm);
257257
} while (strm->avail_out);
258258
return len - strm->avail_out;
259259
}
260260
261
-int gzclose(gzFile gz) {
261
+static int gzclose(gzFile gz) {
262262
z_stream *strm;
263263
unsigned char out[BUFLEN];
264264
265265
if (gz == NULL)
266266
return Z_STREAM_ERROR;
@@ -281,11 +281,11 @@
281281
fclose(gz->file);
282282
free(gz);
283283
return Z_OK;
284284
}
285285
286
-const char *gzerror(gzFile gz, int *err) {
286
+static const char *gzerror(gzFile gz, int *err) {
287287
*err = gz->err;
288288
return gz->msg;
289289
}
290290
291291
#endif
@@ -293,21 +293,21 @@
293293
static char *prog;
294294
295295
/* ===========================================================================
296296
* Display error message and exit
297297
*/
298
-void error(const char *msg) {
298
+static void error(const char *msg) {
299299
fprintf(stderr, "%s: %s\n", prog, msg);
300300
exit(1);
301301
}
302302
303303
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */
304304
305305
/* Try compressing the input file at once using mmap. Return Z_OK if
306
- * if success, Z_ERRNO otherwise.
306
+ * success, Z_ERRNO otherwise.
307307
*/
308
-int gz_compress_mmap(FILE *in, gzFile out) {
308
+static int gz_compress_mmap(FILE *in, gzFile out) {
309309
int len;
310310
int err;
311311
int ifd = fileno(in);
312312
caddr_t buf; /* mmap'ed buffer for the entire input file */
313313
off_t buf_len; /* length of the input file */
@@ -336,11 +336,11 @@
336336
337337
/* ===========================================================================
338338
* Compress input to output then close both files.
339339
*/
340340
341
-void gz_compress(FILE *in, gzFile out) {
341
+static void gz_compress(FILE *in, gzFile out) {
342342
local char buf[BUFLEN];
343343
int len;
344344
int err;
345345
346346
#ifdef USE_MMAP
@@ -364,11 +364,11 @@
364364
}
365365
366366
/* ===========================================================================
367367
* Uncompress input to output then close both files.
368368
*/
369
-void gz_uncompress(gzFile in, FILE *out) {
369
+static void gz_uncompress(gzFile in, FILE *out) {
370370
local char buf[BUFLEN];
371371
int len;
372372
int err;
373373
374374
for (;;) {
@@ -388,11 +388,11 @@
388388
389389
/* ===========================================================================
390390
* Compress the given file: create a corresponding .gz file and remove the
391391
* original.
392392
*/
393
-void file_compress(char *file, char *mode) {
393
+static void file_compress(char *file, char *mode) {
394394
local char outfile[MAX_NAME_LEN];
395395
FILE *in;
396396
gzFile out;
397397
398398
if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
@@ -424,11 +424,11 @@
424424
425425
426426
/* ===========================================================================
427427
* Uncompress the given file and remove the original.
428428
*/
429
-void file_uncompress(char *file) {
429
+static void file_uncompress(char *file) {
430430
local char buf[MAX_NAME_LEN];
431431
char *infile, *outfile;
432432
FILE *out;
433433
gzFile in;
434434
z_size_t len = strlen(file);
435435
--- compat/zlib/test/minigzip.c
+++ compat/zlib/test/minigzip.c
@@ -147,16 +147,16 @@
147
148 #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
149 # include <unistd.h> /* for unlink() */
150 #endif
151
152 void *myalloc(void *q, unsigned n, unsigned m) {
153 (void)q;
154 return calloc(n, m);
155 }
156
157 void myfree(void *q, void *p) {
158 (void)q;
159 free(p);
160 }
161
162 typedef struct gzFile_s {
@@ -165,11 +165,11 @@
165 int err;
166 char *msg;
167 z_stream strm;
168 } *gzFile;
169
170 gzFile gz_open(const char *path, int fd, const char *mode) {
171 gzFile gz;
172 int ret;
173
174 gz = malloc(sizeof(struct gzFile_s));
175 if (gz == NULL)
@@ -199,19 +199,19 @@
199 gz->err = 0;
200 gz->msg = "";
201 return gz;
202 }
203
204 gzFile gzopen(const char *path, const char *mode) {
205 return gz_open(path, -1, mode);
206 }
207
208 gzFile gzdopen(int fd, const char *mode) {
209 return gz_open(NULL, fd, mode);
210 }
211
212 int gzwrite(gzFile gz, const void *buf, unsigned len) {
213 z_stream *strm;
214 unsigned char out[BUFLEN];
215
216 if (gz == NULL || !gz->write)
217 return 0;
@@ -225,11 +225,11 @@
225 fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
226 } while (strm->avail_out == 0);
227 return len;
228 }
229
230 int gzread(gzFile gz, void *buf, unsigned len) {
231 int ret;
232 unsigned got;
233 unsigned char in[1];
234 z_stream *strm;
235
@@ -256,11 +256,11 @@
256 inflateReset(strm);
257 } while (strm->avail_out);
258 return len - strm->avail_out;
259 }
260
261 int gzclose(gzFile gz) {
262 z_stream *strm;
263 unsigned char out[BUFLEN];
264
265 if (gz == NULL)
266 return Z_STREAM_ERROR;
@@ -281,11 +281,11 @@
281 fclose(gz->file);
282 free(gz);
283 return Z_OK;
284 }
285
286 const char *gzerror(gzFile gz, int *err) {
287 *err = gz->err;
288 return gz->msg;
289 }
290
291 #endif
@@ -293,21 +293,21 @@
293 static char *prog;
294
295 /* ===========================================================================
296 * Display error message and exit
297 */
298 void error(const char *msg) {
299 fprintf(stderr, "%s: %s\n", prog, msg);
300 exit(1);
301 }
302
303 #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */
304
305 /* Try compressing the input file at once using mmap. Return Z_OK if
306 * if success, Z_ERRNO otherwise.
307 */
308 int gz_compress_mmap(FILE *in, gzFile out) {
309 int len;
310 int err;
311 int ifd = fileno(in);
312 caddr_t buf; /* mmap'ed buffer for the entire input file */
313 off_t buf_len; /* length of the input file */
@@ -336,11 +336,11 @@
336
337 /* ===========================================================================
338 * Compress input to output then close both files.
339 */
340
341 void gz_compress(FILE *in, gzFile out) {
342 local char buf[BUFLEN];
343 int len;
344 int err;
345
346 #ifdef USE_MMAP
@@ -364,11 +364,11 @@
364 }
365
366 /* ===========================================================================
367 * Uncompress input to output then close both files.
368 */
369 void gz_uncompress(gzFile in, FILE *out) {
370 local char buf[BUFLEN];
371 int len;
372 int err;
373
374 for (;;) {
@@ -388,11 +388,11 @@
388
389 /* ===========================================================================
390 * Compress the given file: create a corresponding .gz file and remove the
391 * original.
392 */
393 void file_compress(char *file, char *mode) {
394 local char outfile[MAX_NAME_LEN];
395 FILE *in;
396 gzFile out;
397
398 if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
@@ -424,11 +424,11 @@
424
425
426 /* ===========================================================================
427 * Uncompress the given file and remove the original.
428 */
429 void file_uncompress(char *file) {
430 local char buf[MAX_NAME_LEN];
431 char *infile, *outfile;
432 FILE *out;
433 gzFile in;
434 z_size_t len = strlen(file);
435
--- compat/zlib/test/minigzip.c
+++ compat/zlib/test/minigzip.c
@@ -147,16 +147,16 @@
147
148 #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
149 # include <unistd.h> /* for unlink() */
150 #endif
151
152 static void *myalloc(void *q, unsigned n, unsigned m) {
153 (void)q;
154 return calloc(n, m);
155 }
156
157 static void myfree(void *q, void *p) {
158 (void)q;
159 free(p);
160 }
161
162 typedef struct gzFile_s {
@@ -165,11 +165,11 @@
165 int err;
166 char *msg;
167 z_stream strm;
168 } *gzFile;
169
170 static gzFile gz_open(const char *path, int fd, const char *mode) {
171 gzFile gz;
172 int ret;
173
174 gz = malloc(sizeof(struct gzFile_s));
175 if (gz == NULL)
@@ -199,19 +199,19 @@
199 gz->err = 0;
200 gz->msg = "";
201 return gz;
202 }
203
204 static gzFile gzopen(const char *path, const char *mode) {
205 return gz_open(path, -1, mode);
206 }
207
208 static gzFile gzdopen(int fd, const char *mode) {
209 return gz_open(NULL, fd, mode);
210 }
211
212 static int gzwrite(gzFile gz, const void *buf, unsigned len) {
213 z_stream *strm;
214 unsigned char out[BUFLEN];
215
216 if (gz == NULL || !gz->write)
217 return 0;
@@ -225,11 +225,11 @@
225 fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
226 } while (strm->avail_out == 0);
227 return len;
228 }
229
230 static int gzread(gzFile gz, void *buf, unsigned len) {
231 int ret;
232 unsigned got;
233 unsigned char in[1];
234 z_stream *strm;
235
@@ -256,11 +256,11 @@
256 inflateReset(strm);
257 } while (strm->avail_out);
258 return len - strm->avail_out;
259 }
260
261 static int gzclose(gzFile gz) {
262 z_stream *strm;
263 unsigned char out[BUFLEN];
264
265 if (gz == NULL)
266 return Z_STREAM_ERROR;
@@ -281,11 +281,11 @@
281 fclose(gz->file);
282 free(gz);
283 return Z_OK;
284 }
285
286 static const char *gzerror(gzFile gz, int *err) {
287 *err = gz->err;
288 return gz->msg;
289 }
290
291 #endif
@@ -293,21 +293,21 @@
293 static char *prog;
294
295 /* ===========================================================================
296 * Display error message and exit
297 */
298 static void error(const char *msg) {
299 fprintf(stderr, "%s: %s\n", prog, msg);
300 exit(1);
301 }
302
303 #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */
304
305 /* Try compressing the input file at once using mmap. Return Z_OK if
306 * success, Z_ERRNO otherwise.
307 */
308 static int gz_compress_mmap(FILE *in, gzFile out) {
309 int len;
310 int err;
311 int ifd = fileno(in);
312 caddr_t buf; /* mmap'ed buffer for the entire input file */
313 off_t buf_len; /* length of the input file */
@@ -336,11 +336,11 @@
336
337 /* ===========================================================================
338 * Compress input to output then close both files.
339 */
340
341 static void gz_compress(FILE *in, gzFile out) {
342 local char buf[BUFLEN];
343 int len;
344 int err;
345
346 #ifdef USE_MMAP
@@ -364,11 +364,11 @@
364 }
365
366 /* ===========================================================================
367 * Uncompress input to output then close both files.
368 */
369 static void gz_uncompress(gzFile in, FILE *out) {
370 local char buf[BUFLEN];
371 int len;
372 int err;
373
374 for (;;) {
@@ -388,11 +388,11 @@
388
389 /* ===========================================================================
390 * Compress the given file: create a corresponding .gz file and remove the
391 * original.
392 */
393 static void file_compress(char *file, char *mode) {
394 local char outfile[MAX_NAME_LEN];
395 FILE *in;
396 gzFile out;
397
398 if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
@@ -424,11 +424,11 @@
424
425
426 /* ===========================================================================
427 * Uncompress the given file and remove the original.
428 */
429 static void file_uncompress(char *file) {
430 local char buf[MAX_NAME_LEN];
431 char *infile, *outfile;
432 FILE *out;
433 gzFile in;
434 z_size_t len = strlen(file);
435
--- compat/zlib/treebuild.xml
+++ compat/zlib/treebuild.xml
@@ -1,8 +1,8 @@
11
<?xml version="1.0" ?>
2
-<package name="zlib" version="1.3">
3
- <library name="zlib" dlversion="1.3" dlname="z">
2
+<package name="zlib" version="1.3.1">
3
+ <library name="zlib" dlversion="1.3.1" dlname="z">
44
<property name="description"> zip compression library </property>
55
<property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
66
77
<!-- fixme: not implemented yet -->
88
<property name="compiler/c/inline" value="yes" />
99
--- compat/zlib/treebuild.xml
+++ compat/zlib/treebuild.xml
@@ -1,8 +1,8 @@
1 <?xml version="1.0" ?>
2 <package name="zlib" version="1.3">
3 <library name="zlib" dlversion="1.3" dlname="z">
4 <property name="description"> zip compression library </property>
5 <property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
6
7 <!-- fixme: not implemented yet -->
8 <property name="compiler/c/inline" value="yes" />
9
--- compat/zlib/treebuild.xml
+++ compat/zlib/treebuild.xml
@@ -1,8 +1,8 @@
1 <?xml version="1.0" ?>
2 <package name="zlib" version="1.3.1">
3 <library name="zlib" dlversion="1.3.1" dlname="z">
4 <property name="description"> zip compression library </property>
5 <property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
6
7 <!-- fixme: not implemented yet -->
8 <property name="compiler/c/inline" value="yes" />
9
--- compat/zlib/trees.c
+++ compat/zlib/trees.c
@@ -1,7 +1,7 @@
11
/* trees.c -- output deflated data using Huffman coding
2
- * Copyright (C) 1995-2021 Jean-loup Gailly
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly
33
* detect_data_type() function provided freely by Cosmin Truta, 2006
44
* For conditions of distribution and use, see copyright notice in zlib.h
55
*/
66
77
/*
@@ -897,18 +897,23 @@
897897
*/
898898
local void compress_block(deflate_state *s, const ct_data *ltree,
899899
const ct_data *dtree) {
900900
unsigned dist; /* distance of matched string */
901901
int lc; /* match length or unmatched char (if dist == 0) */
902
- unsigned sx = 0; /* running index in sym_buf */
902
+ unsigned sx = 0; /* running index in symbol buffers */
903903
unsigned code; /* the code to send */
904904
int extra; /* number of extra bits to send */
905905
906906
if (s->sym_next != 0) do {
907
+#ifdef LIT_MEM
908
+ dist = s->d_buf[sx];
909
+ lc = s->l_buf[sx++];
910
+#else
907911
dist = s->sym_buf[sx++] & 0xff;
908912
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
909913
lc = s->sym_buf[sx++];
914
+#endif
910915
if (dist == 0) {
911916
send_code(s, lc, ltree); /* send a literal byte */
912917
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
913918
} else {
914919
/* Here, lc is the match length - MIN_MATCH */
@@ -929,12 +934,16 @@
929934
dist -= (unsigned)base_dist[code];
930935
send_bits(s, dist, extra); /* send the extra distance bits */
931936
}
932937
} /* literal or match pair ? */
933938
934
- /* Check that the overlay between pending_buf and sym_buf is ok: */
939
+ /* Check for no overlay of pending_buf on needed symbols */
940
+#ifdef LIT_MEM
941
+ Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
942
+#else
935943
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
944
+#endif
936945
937946
} while (sx < s->sym_next);
938947
939948
send_code(s, END_BLOCK, ltree);
940949
}
@@ -1080,13 +1089,18 @@
10801089
/* ===========================================================================
10811090
* Save the match info and tally the frequency counts. Return true if
10821091
* the current block must be flushed.
10831092
*/
10841093
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
1094
+#ifdef LIT_MEM
1095
+ s->d_buf[s->sym_next] = (ush)dist;
1096
+ s->l_buf[s->sym_next++] = (uch)lc;
1097
+#else
10851098
s->sym_buf[s->sym_next++] = (uch)dist;
10861099
s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
10871100
s->sym_buf[s->sym_next++] = (uch)lc;
1101
+#endif
10881102
if (dist == 0) {
10891103
/* lc is the unmatched char */
10901104
s->dyn_ltree[lc].Freq++;
10911105
} else {
10921106
s->matches++;
10931107
--- compat/zlib/trees.c
+++ compat/zlib/trees.c
@@ -1,7 +1,7 @@
1 /* trees.c -- output deflated data using Huffman coding
2 * Copyright (C) 1995-2021 Jean-loup Gailly
3 * detect_data_type() function provided freely by Cosmin Truta, 2006
4 * For conditions of distribution and use, see copyright notice in zlib.h
5 */
6
7 /*
@@ -897,18 +897,23 @@
897 */
898 local void compress_block(deflate_state *s, const ct_data *ltree,
899 const ct_data *dtree) {
900 unsigned dist; /* distance of matched string */
901 int lc; /* match length or unmatched char (if dist == 0) */
902 unsigned sx = 0; /* running index in sym_buf */
903 unsigned code; /* the code to send */
904 int extra; /* number of extra bits to send */
905
906 if (s->sym_next != 0) do {
 
 
 
 
907 dist = s->sym_buf[sx++] & 0xff;
908 dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
909 lc = s->sym_buf[sx++];
 
910 if (dist == 0) {
911 send_code(s, lc, ltree); /* send a literal byte */
912 Tracecv(isgraph(lc), (stderr," '%c' ", lc));
913 } else {
914 /* Here, lc is the match length - MIN_MATCH */
@@ -929,12 +934,16 @@
929 dist -= (unsigned)base_dist[code];
930 send_bits(s, dist, extra); /* send the extra distance bits */
931 }
932 } /* literal or match pair ? */
933
934 /* Check that the overlay between pending_buf and sym_buf is ok: */
 
 
 
935 Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
 
936
937 } while (sx < s->sym_next);
938
939 send_code(s, END_BLOCK, ltree);
940 }
@@ -1080,13 +1089,18 @@
1080 /* ===========================================================================
1081 * Save the match info and tally the frequency counts. Return true if
1082 * the current block must be flushed.
1083 */
1084 int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
 
 
 
 
1085 s->sym_buf[s->sym_next++] = (uch)dist;
1086 s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
1087 s->sym_buf[s->sym_next++] = (uch)lc;
 
1088 if (dist == 0) {
1089 /* lc is the unmatched char */
1090 s->dyn_ltree[lc].Freq++;
1091 } else {
1092 s->matches++;
1093
--- compat/zlib/trees.c
+++ compat/zlib/trees.c
@@ -1,7 +1,7 @@
1 /* trees.c -- output deflated data using Huffman coding
2 * Copyright (C) 1995-2024 Jean-loup Gailly
3 * detect_data_type() function provided freely by Cosmin Truta, 2006
4 * For conditions of distribution and use, see copyright notice in zlib.h
5 */
6
7 /*
@@ -897,18 +897,23 @@
897 */
898 local void compress_block(deflate_state *s, const ct_data *ltree,
899 const ct_data *dtree) {
900 unsigned dist; /* distance of matched string */
901 int lc; /* match length or unmatched char (if dist == 0) */
902 unsigned sx = 0; /* running index in symbol buffers */
903 unsigned code; /* the code to send */
904 int extra; /* number of extra bits to send */
905
906 if (s->sym_next != 0) do {
907 #ifdef LIT_MEM
908 dist = s->d_buf[sx];
909 lc = s->l_buf[sx++];
910 #else
911 dist = s->sym_buf[sx++] & 0xff;
912 dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
913 lc = s->sym_buf[sx++];
914 #endif
915 if (dist == 0) {
916 send_code(s, lc, ltree); /* send a literal byte */
917 Tracecv(isgraph(lc), (stderr," '%c' ", lc));
918 } else {
919 /* Here, lc is the match length - MIN_MATCH */
@@ -929,12 +934,16 @@
934 dist -= (unsigned)base_dist[code];
935 send_bits(s, dist, extra); /* send the extra distance bits */
936 }
937 } /* literal or match pair ? */
938
939 /* Check for no overlay of pending_buf on needed symbols */
940 #ifdef LIT_MEM
941 Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
942 #else
943 Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
944 #endif
945
946 } while (sx < s->sym_next);
947
948 send_code(s, END_BLOCK, ltree);
949 }
@@ -1080,13 +1089,18 @@
1089 /* ===========================================================================
1090 * Save the match info and tally the frequency counts. Return true if
1091 * the current block must be flushed.
1092 */
1093 int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
1094 #ifdef LIT_MEM
1095 s->d_buf[s->sym_next] = (ush)dist;
1096 s->l_buf[s->sym_next++] = (uch)lc;
1097 #else
1098 s->sym_buf[s->sym_next++] = (uch)dist;
1099 s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
1100 s->sym_buf[s->sym_next++] = (uch)lc;
1101 #endif
1102 if (dist == 0) {
1103 /* lc is the unmatched char */
1104 s->dyn_ltree[lc].Freq++;
1105 } else {
1106 s->matches++;
1107
--- compat/zlib/win32/DLL_FAQ.txt
+++ compat/zlib/win32/DLL_FAQ.txt
@@ -1,25 +1,21 @@
11
22
Frequently Asked Questions about ZLIB1.DLL
33
44
55
This document describes the design, the rationale, and the usage
6
-of the official DLL build of zlib, named ZLIB1.DLL. If you have
6
+of the common DLL build of zlib, named ZLIB1.DLL. If you have
77
general questions about zlib, you should see the file "FAQ" found
88
in the zlib distribution, or at the following location:
99
http://www.gzip.org/zlib/zlib_faq.html
1010
1111
1212
1. What is ZLIB1.DLL, and how can I get it?
1313
14
- - ZLIB1.DLL is the official build of zlib as a DLL.
14
+ - ZLIB1.DLL is the common build of zlib as a DLL.
1515
(Please remark the character '1' in the name.)
1616
17
- Pointers to a precompiled ZLIB1.DLL can be found in the zlib
18
- web site at:
19
- http://www.zlib.net/
20
-
2117
Applications that link to ZLIB1.DLL can rely on the following
2218
specification:
2319
2420
* The exported symbols are exclusively defined in the source
2521
files "zlib.h" and "zlib.def", found in an official zlib
@@ -377,21 +373,9 @@
377373
- No. A legitimate build of ZLIB1.DLL must provide the complete
378374
zlib functionality, as implemented in the official zlib source
379375
code. But you can make your own private DLL build, under a
380376
different file name, as suggested in the previous answer.
381377
382
-
383
-17. I made my own ZLIB1.DLL build. Can I test it for compliance?
384
-
385
- - We prefer that you download the official DLL from the zlib
386
- web site. If you need something peculiar from this DLL, you
387
- can send your suggestion to the zlib mailing list.
388
-
389
- However, in case you do rebuild the DLL yourself, you can run
390
- it with the test programs found in the DLL distribution.
391
- Running these test programs is not a guarantee of compliance,
392
- but a failure can imply a detected problem.
393
-
394378
**
395379
396380
This document is written and maintained by
397381
Cosmin Truta <[email protected]>
398382
--- compat/zlib/win32/DLL_FAQ.txt
+++ compat/zlib/win32/DLL_FAQ.txt
@@ -1,25 +1,21 @@
1
2 Frequently Asked Questions about ZLIB1.DLL
3
4
5 This document describes the design, the rationale, and the usage
6 of the official DLL build of zlib, named ZLIB1.DLL. If you have
7 general questions about zlib, you should see the file "FAQ" found
8 in the zlib distribution, or at the following location:
9 http://www.gzip.org/zlib/zlib_faq.html
10
11
12 1. What is ZLIB1.DLL, and how can I get it?
13
14 - ZLIB1.DLL is the official build of zlib as a DLL.
15 (Please remark the character '1' in the name.)
16
17 Pointers to a precompiled ZLIB1.DLL can be found in the zlib
18 web site at:
19 http://www.zlib.net/
20
21 Applications that link to ZLIB1.DLL can rely on the following
22 specification:
23
24 * The exported symbols are exclusively defined in the source
25 files "zlib.h" and "zlib.def", found in an official zlib
@@ -377,21 +373,9 @@
377 - No. A legitimate build of ZLIB1.DLL must provide the complete
378 zlib functionality, as implemented in the official zlib source
379 code. But you can make your own private DLL build, under a
380 different file name, as suggested in the previous answer.
381
382
383 17. I made my own ZLIB1.DLL build. Can I test it for compliance?
384
385 - We prefer that you download the official DLL from the zlib
386 web site. If you need something peculiar from this DLL, you
387 can send your suggestion to the zlib mailing list.
388
389 However, in case you do rebuild the DLL yourself, you can run
390 it with the test programs found in the DLL distribution.
391 Running these test programs is not a guarantee of compliance,
392 but a failure can imply a detected problem.
393
394 **
395
396 This document is written and maintained by
397 Cosmin Truta <[email protected]>
398
--- compat/zlib/win32/DLL_FAQ.txt
+++ compat/zlib/win32/DLL_FAQ.txt
@@ -1,25 +1,21 @@
1
2 Frequently Asked Questions about ZLIB1.DLL
3
4
5 This document describes the design, the rationale, and the usage
6 of the common DLL build of zlib, named ZLIB1.DLL. If you have
7 general questions about zlib, you should see the file "FAQ" found
8 in the zlib distribution, or at the following location:
9 http://www.gzip.org/zlib/zlib_faq.html
10
11
12 1. What is ZLIB1.DLL, and how can I get it?
13
14 - ZLIB1.DLL is the common build of zlib as a DLL.
15 (Please remark the character '1' in the name.)
16
 
 
 
 
17 Applications that link to ZLIB1.DLL can rely on the following
18 specification:
19
20 * The exported symbols are exclusively defined in the source
21 files "zlib.h" and "zlib.def", found in an official zlib
@@ -377,21 +373,9 @@
373 - No. A legitimate build of ZLIB1.DLL must provide the complete
374 zlib functionality, as implemented in the official zlib source
375 code. But you can make your own private DLL build, under a
376 different file name, as suggested in the previous answer.
377
 
 
 
 
 
 
 
 
 
 
 
 
378 **
379
380 This document is written and maintained by
381 Cosmin Truta <[email protected]>
382
--- compat/zlib/win32/README-WIN32.txt
+++ compat/zlib/win32/README-WIN32.txt
@@ -1,8 +1,8 @@
11
ZLIB DATA COMPRESSION LIBRARY
22
3
-zlib 1.3.0 is a general purpose data compression library. All the code is
3
+zlib 1.3.1 is a general purpose data compression library. All the code is
44
thread safe. The data format used by the zlib library is described by RFCs
55
(Request for Comments) 1950 to 1952 in the files
66
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
77
and rfc1952.txt (gzip format).
88
@@ -14,17 +14,17 @@
1414
Questions about zlib should be sent to <[email protected]>. The zlib home page
1515
is http://zlib.net/ . Before reporting a problem, please check this site to
1616
verify that you have the latest version of zlib; otherwise get the latest
1717
version and check whether the problem still exists or not.
1818
19
-PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
20
-before asking for help.
19
+PLEASE read DLL_FAQ.txt, and the zlib FAQ http://zlib.net/zlib_faq.html before
20
+asking for help.
2121
2222
2323
Manifest:
2424
25
-The package zlib-1.3.0-win32-x86.zip will contain the following files:
25
+The package zlib-1.3.1-win32-x86.zip will contain the following files:
2626
2727
README-WIN32.txt This document
2828
ChangeLog Changes since previous zlib packages
2929
DLL_FAQ.txt Frequently asked questions about zlib1.dll
3030
zlib.3.pdf Documentation of this library in Adobe Acrobat format
3131
--- compat/zlib/win32/README-WIN32.txt
+++ compat/zlib/win32/README-WIN32.txt
@@ -1,8 +1,8 @@
1 ZLIB DATA COMPRESSION LIBRARY
2
3 zlib 1.3.0 is a general purpose data compression library. All the code is
4 thread safe. The data format used by the zlib library is described by RFCs
5 (Request for Comments) 1950 to 1952 in the files
6 http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
7 and rfc1952.txt (gzip format).
8
@@ -14,17 +14,17 @@
14 Questions about zlib should be sent to <[email protected]>. The zlib home page
15 is http://zlib.net/ . Before reporting a problem, please check this site to
16 verify that you have the latest version of zlib; otherwise get the latest
17 version and check whether the problem still exists or not.
18
19 PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
20 before asking for help.
21
22
23 Manifest:
24
25 The package zlib-1.3.0-win32-x86.zip will contain the following files:
26
27 README-WIN32.txt This document
28 ChangeLog Changes since previous zlib packages
29 DLL_FAQ.txt Frequently asked questions about zlib1.dll
30 zlib.3.pdf Documentation of this library in Adobe Acrobat format
31
--- compat/zlib/win32/README-WIN32.txt
+++ compat/zlib/win32/README-WIN32.txt
@@ -1,8 +1,8 @@
1 ZLIB DATA COMPRESSION LIBRARY
2
3 zlib 1.3.1 is a general purpose data compression library. All the code is
4 thread safe. The data format used by the zlib library is described by RFCs
5 (Request for Comments) 1950 to 1952 in the files
6 http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
7 and rfc1952.txt (gzip format).
8
@@ -14,17 +14,17 @@
14 Questions about zlib should be sent to <[email protected]>. The zlib home page
15 is http://zlib.net/ . Before reporting a problem, please check this site to
16 verify that you have the latest version of zlib; otherwise get the latest
17 version and check whether the problem still exists or not.
18
19 PLEASE read DLL_FAQ.txt, and the zlib FAQ http://zlib.net/zlib_faq.html before
20 asking for help.
21
22
23 Manifest:
24
25 The package zlib-1.3.1-win32-x86.zip will contain the following files:
26
27 README-WIN32.txt This document
28 ChangeLog Changes since previous zlib packages
29 DLL_FAQ.txt Frequently asked questions about zlib1.dll
30 zlib.3.pdf Documentation of this library in Adobe Acrobat format
31
--- compat/zlib/zconf.h
+++ compat/zlib/zconf.h
@@ -1,7 +1,7 @@
11
/* zconf.h -- configuration of the zlib compression library
2
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/* @(#) $Id$ */
77
@@ -298,18 +298,10 @@
298298
# else
299299
# define OF(args) ()
300300
# endif
301301
#endif
302302
303
-#ifndef Z_ARG /* function prototypes for stdarg */
304
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
305
-# define Z_ARG(args) args
306
-# else
307
-# define Z_ARG(args) ()
308
-# endif
309
-#endif
310
-
311303
/* The following definitions for FAR are needed only for MSDOS mixed
312304
* model programming (small or medium model with some far allocations).
313305
* This was tested only with MSC; for other MSDOS compilers you may have
314306
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
315307
* just define FAR to be empty.
316308
--- compat/zlib/zconf.h
+++ compat/zlib/zconf.h
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -298,18 +298,10 @@
298 # else
299 # define OF(args) ()
300 # endif
301 #endif
302
303 #ifndef Z_ARG /* function prototypes for stdarg */
304 # if defined(STDC) || defined(Z_HAVE_STDARG_H)
305 # define Z_ARG(args) args
306 # else
307 # define Z_ARG(args) ()
308 # endif
309 #endif
310
311 /* The following definitions for FAR are needed only for MSDOS mixed
312 * model programming (small or medium model with some far allocations).
313 * This was tested only with MSC; for other MSDOS compilers you may have
314 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
315 * just define FAR to be empty.
316
--- compat/zlib/zconf.h
+++ compat/zlib/zconf.h
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -298,18 +298,10 @@
298 # else
299 # define OF(args) ()
300 # endif
301 #endif
302
 
 
 
 
 
 
 
 
303 /* The following definitions for FAR are needed only for MSDOS mixed
304 * model programming (small or medium model with some far allocations).
305 * This was tested only with MSC; for other MSDOS compilers you may have
306 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
307 * just define FAR to be empty.
308
--- compat/zlib/zconf.h.cmakein
+++ compat/zlib/zconf.h.cmakein
@@ -1,7 +1,7 @@
11
/* zconf.h -- configuration of the zlib compression library
2
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/* @(#) $Id$ */
77
@@ -300,18 +300,10 @@
300300
# else
301301
# define OF(args) ()
302302
# endif
303303
#endif
304304
305
-#ifndef Z_ARG /* function prototypes for stdarg */
306
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
307
-# define Z_ARG(args) args
308
-# else
309
-# define Z_ARG(args) ()
310
-# endif
311
-#endif
312
-
313305
/* The following definitions for FAR are needed only for MSDOS mixed
314306
* model programming (small or medium model with some far allocations).
315307
* This was tested only with MSC; for other MSDOS compilers you may have
316308
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
317309
* just define FAR to be empty.
318310
--- compat/zlib/zconf.h.cmakein
+++ compat/zlib/zconf.h.cmakein
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -300,18 +300,10 @@
300 # else
301 # define OF(args) ()
302 # endif
303 #endif
304
305 #ifndef Z_ARG /* function prototypes for stdarg */
306 # if defined(STDC) || defined(Z_HAVE_STDARG_H)
307 # define Z_ARG(args) args
308 # else
309 # define Z_ARG(args) ()
310 # endif
311 #endif
312
313 /* The following definitions for FAR are needed only for MSDOS mixed
314 * model programming (small or medium model with some far allocations).
315 * This was tested only with MSC; for other MSDOS compilers you may have
316 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
317 * just define FAR to be empty.
318
--- compat/zlib/zconf.h.cmakein
+++ compat/zlib/zconf.h.cmakein
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -300,18 +300,10 @@
300 # else
301 # define OF(args) ()
302 # endif
303 #endif
304
 
 
 
 
 
 
 
 
305 /* The following definitions for FAR are needed only for MSDOS mixed
306 * model programming (small or medium model with some far allocations).
307 * This was tested only with MSC; for other MSDOS compilers you may have
308 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
309 * just define FAR to be empty.
310
--- compat/zlib/zconf.h.in
+++ compat/zlib/zconf.h.in
@@ -1,7 +1,7 @@
11
/* zconf.h -- configuration of the zlib compression library
2
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/* @(#) $Id$ */
77
@@ -298,18 +298,10 @@
298298
# else
299299
# define OF(args) ()
300300
# endif
301301
#endif
302302
303
-#ifndef Z_ARG /* function prototypes for stdarg */
304
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
305
-# define Z_ARG(args) args
306
-# else
307
-# define Z_ARG(args) ()
308
-# endif
309
-#endif
310
-
311303
/* The following definitions for FAR are needed only for MSDOS mixed
312304
* model programming (small or medium model with some far allocations).
313305
* This was tested only with MSC; for other MSDOS compilers you may have
314306
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
315307
* just define FAR to be empty.
316308
--- compat/zlib/zconf.h.in
+++ compat/zlib/zconf.h.in
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -298,18 +298,10 @@
298 # else
299 # define OF(args) ()
300 # endif
301 #endif
302
303 #ifndef Z_ARG /* function prototypes for stdarg */
304 # if defined(STDC) || defined(Z_HAVE_STDARG_H)
305 # define Z_ARG(args) args
306 # else
307 # define Z_ARG(args) ()
308 # endif
309 #endif
310
311 /* The following definitions for FAR are needed only for MSDOS mixed
312 * model programming (small or medium model with some far allocations).
313 * This was tested only with MSC; for other MSDOS compilers you may have
314 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
315 * just define FAR to be empty.
316
--- compat/zlib/zconf.h.in
+++ compat/zlib/zconf.h.in
@@ -1,7 +1,7 @@
1 /* zconf.h -- configuration of the zlib compression library
2 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* @(#) $Id$ */
7
@@ -298,18 +298,10 @@
298 # else
299 # define OF(args) ()
300 # endif
301 #endif
302
 
 
 
 
 
 
 
 
303 /* The following definitions for FAR are needed only for MSDOS mixed
304 * model programming (small or medium model with some far allocations).
305 * This was tested only with MSC; for other MSDOS compilers you may have
306 * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
307 * just define FAR to be empty.
308
--- compat/zlib/zlib.3
+++ compat/zlib/zlib.3
@@ -1,6 +1,6 @@
1
-.TH ZLIB 3 "18 Aug 2023"
1
+.TH ZLIB 3 "22 Jan 2024"
22
.SH NAME
33
zlib \- compression/decompression library
44
.SH SYNOPSIS
55
[see
66
.I zlib.h
@@ -103,13 +103,13 @@
103103
.LP
104104
before asking for help.
105105
Send questions and/or comments to [email protected],
106106
or (for the Windows DLL version) to Gilles Vollant ([email protected]).
107107
.SH AUTHORS AND LICENSE
108
-Version 1.3
108
+Version 1.3.1
109109
.LP
110
-Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
110
+Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
111111
.LP
112112
This software is provided 'as-is', without any express or implied
113113
warranty. In no event will the authors be held liable for any damages
114114
arising from the use of this software.
115115
.LP
116116
--- compat/zlib/zlib.3
+++ compat/zlib/zlib.3
@@ -1,6 +1,6 @@
1 .TH ZLIB 3 "18 Aug 2023"
2 .SH NAME
3 zlib \- compression/decompression library
4 .SH SYNOPSIS
5 [see
6 .I zlib.h
@@ -103,13 +103,13 @@
103 .LP
104 before asking for help.
105 Send questions and/or comments to [email protected],
106 or (for the Windows DLL version) to Gilles Vollant ([email protected]).
107 .SH AUTHORS AND LICENSE
108 Version 1.3
109 .LP
110 Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
111 .LP
112 This software is provided 'as-is', without any express or implied
113 warranty. In no event will the authors be held liable for any damages
114 arising from the use of this software.
115 .LP
116
--- compat/zlib/zlib.3
+++ compat/zlib/zlib.3
@@ -1,6 +1,6 @@
1 .TH ZLIB 3 "22 Jan 2024"
2 .SH NAME
3 zlib \- compression/decompression library
4 .SH SYNOPSIS
5 [see
6 .I zlib.h
@@ -103,13 +103,13 @@
103 .LP
104 before asking for help.
105 Send questions and/or comments to [email protected],
106 or (for the Windows DLL version) to Gilles Vollant ([email protected]).
107 .SH AUTHORS AND LICENSE
108 Version 1.3.1
109 .LP
110 Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
111 .LP
112 This software is provided 'as-is', without any express or implied
113 warranty. In no event will the authors be held liable for any damages
114 arising from the use of this software.
115 .LP
116
--- compat/zlib/zlib.3.pdf
+++ compat/zlib/zlib.3.pdf
cannot compute difference between binary files
11
--- compat/zlib/zlib.3.pdf
+++ compat/zlib/zlib.3.pdf
0 annot compute difference between binary files
1
--- compat/zlib/zlib.3.pdf
+++ compat/zlib/zlib.3.pdf
0 annot compute difference between binary files
1
+11 -11
--- compat/zlib/zlib.h
+++ compat/zlib/zlib.h
@@ -1,9 +1,9 @@
11
/* zlib.h -- interface of the 'zlib' general purpose compression library
2
- version 1.3, August 18th, 2023
2
+ version 1.3.1, January 22nd, 2024
33
4
- Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
4
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
55
66
This software is provided 'as-is', without any express or implied
77
warranty. In no event will the authors be held liable for any damages
88
arising from the use of this software.
99
@@ -35,15 +35,15 @@
3535
3636
#ifdef __cplusplus
3737
extern "C" {
3838
#endif
3939
40
-#define ZLIB_VERSION "1.3"
41
-#define ZLIB_VERNUM 0x1300
40
+#define ZLIB_VERSION "1.3.1"
41
+#define ZLIB_VERNUM 0x1310
4242
#define ZLIB_VER_MAJOR 1
4343
#define ZLIB_VER_MINOR 3
44
-#define ZLIB_VER_REVISION 0
44
+#define ZLIB_VER_REVISION 1
4545
#define ZLIB_VER_SUBREVISION 0
4646
4747
/*
4848
The 'zlib' compression library provides in-memory compression and
4949
decompression functions, including integrity checks of the uncompressed data.
@@ -934,14 +934,14 @@
934934
pattern are full flush points.
935935
936936
inflateSync returns Z_OK if a possible full flush point has been found,
937937
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
938938
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
939
- In the success case, the application may save the current current value of
940
- total_in which indicates where valid compressed data was found. In the
941
- error case, the application may repeatedly call inflateSync, providing more
942
- input each time, until success or end of the input data.
939
+ In the success case, the application may save the current value of total_in
940
+ which indicates where valid compressed data was found. In the error case,
941
+ the application may repeatedly call inflateSync, providing more input each
942
+ time, until success or end of the input data.
943943
*/
944944
945945
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
946946
z_streamp source);
947947
/*
@@ -1756,18 +1756,18 @@
17561756
17571757
Combine two CRC-32 check values into one. For two sequences of bytes,
17581758
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
17591759
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
17601760
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
1761
- len2.
1761
+ len2. len2 must be non-negative.
17621762
*/
17631763
17641764
/*
17651765
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
17661766
17671767
Return the operator corresponding to length len2, to be used with
1768
- crc32_combine_op().
1768
+ crc32_combine_op(). len2 must be non-negative.
17691769
*/
17701770
17711771
ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
17721772
/*
17731773
Give the same result as crc32_combine(), using op in place of len2. op is
17741774
--- compat/zlib/zlib.h
+++ compat/zlib/zlib.h
@@ -1,9 +1,9 @@
1 /* zlib.h -- interface of the 'zlib' general purpose compression library
2 version 1.3, August 18th, 2023
3
4 Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
5
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
@@ -35,15 +35,15 @@
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 #define ZLIB_VERSION "1.3"
41 #define ZLIB_VERNUM 0x1300
42 #define ZLIB_VER_MAJOR 1
43 #define ZLIB_VER_MINOR 3
44 #define ZLIB_VER_REVISION 0
45 #define ZLIB_VER_SUBREVISION 0
46
47 /*
48 The 'zlib' compression library provides in-memory compression and
49 decompression functions, including integrity checks of the uncompressed data.
@@ -934,14 +934,14 @@
934 pattern are full flush points.
935
936 inflateSync returns Z_OK if a possible full flush point has been found,
937 Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
938 has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
939 In the success case, the application may save the current current value of
940 total_in which indicates where valid compressed data was found. In the
941 error case, the application may repeatedly call inflateSync, providing more
942 input each time, until success or end of the input data.
943 */
944
945 ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
946 z_streamp source);
947 /*
@@ -1756,18 +1756,18 @@
1756
1757 Combine two CRC-32 check values into one. For two sequences of bytes,
1758 seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
1759 calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
1760 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
1761 len2.
1762 */
1763
1764 /*
1765 ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
1766
1767 Return the operator corresponding to length len2, to be used with
1768 crc32_combine_op().
1769 */
1770
1771 ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
1772 /*
1773 Give the same result as crc32_combine(), using op in place of len2. op is
1774
--- compat/zlib/zlib.h
+++ compat/zlib/zlib.h
@@ -1,9 +1,9 @@
1 /* zlib.h -- interface of the 'zlib' general purpose compression library
2 version 1.3.1, January 22nd, 2024
3
4 Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
5
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
@@ -35,15 +35,15 @@
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 #define ZLIB_VERSION "1.3.1"
41 #define ZLIB_VERNUM 0x1310
42 #define ZLIB_VER_MAJOR 1
43 #define ZLIB_VER_MINOR 3
44 #define ZLIB_VER_REVISION 1
45 #define ZLIB_VER_SUBREVISION 0
46
47 /*
48 The 'zlib' compression library provides in-memory compression and
49 decompression functions, including integrity checks of the uncompressed data.
@@ -934,14 +934,14 @@
934 pattern are full flush points.
935
936 inflateSync returns Z_OK if a possible full flush point has been found,
937 Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
938 has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
939 In the success case, the application may save the current value of total_in
940 which indicates where valid compressed data was found. In the error case,
941 the application may repeatedly call inflateSync, providing more input each
942 time, until success or end of the input data.
943 */
944
945 ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
946 z_streamp source);
947 /*
@@ -1756,18 +1756,18 @@
1756
1757 Combine two CRC-32 check values into one. For two sequences of bytes,
1758 seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
1759 calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
1760 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
1761 len2. len2 must be non-negative.
1762 */
1763
1764 /*
1765 ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
1766
1767 Return the operator corresponding to length len2, to be used with
1768 crc32_combine_op(). len2 must be non-negative.
1769 */
1770
1771 ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
1772 /*
1773 Give the same result as crc32_combine(), using op in place of len2. op is
1774
+100 -100
--- compat/zlib/zlib.map
+++ compat/zlib/zlib.map
@@ -1,100 +1,100 @@
1
-ZLIB_1.2.0 {
2
- global:
3
- compressBound;
4
- deflateBound;
5
- inflateBack;
6
- inflateBackEnd;
7
- inflateBackInit_;
8
- inflateCopy;
9
- local:
10
- deflate_copyright;
11
- inflate_copyright;
12
- inflate_fast;
13
- inflate_table;
14
- zcalloc;
15
- zcfree;
16
- z_errmsg;
17
- gz_error;
18
- gz_intmax;
19
- _*;
20
-};
21
-
22
-ZLIB_1.2.0.2 {
23
- gzclearerr;
24
- gzungetc;
25
- zlibCompileFlags;
26
-} ZLIB_1.2.0;
27
-
28
-ZLIB_1.2.0.8 {
29
- deflatePrime;
30
-} ZLIB_1.2.0.2;
31
-
32
-ZLIB_1.2.2 {
33
- adler32_combine;
34
- crc32_combine;
35
- deflateSetHeader;
36
- inflateGetHeader;
37
-} ZLIB_1.2.0.8;
38
-
39
-ZLIB_1.2.2.3 {
40
- deflateTune;
41
- gzdirect;
42
-} ZLIB_1.2.2;
43
-
44
-ZLIB_1.2.2.4 {
45
- inflatePrime;
46
-} ZLIB_1.2.2.3;
47
-
48
-ZLIB_1.2.3.3 {
49
- adler32_combine64;
50
- crc32_combine64;
51
- gzopen64;
52
- gzseek64;
53
- gztell64;
54
- inflateUndermine;
55
-} ZLIB_1.2.2.4;
56
-
57
-ZLIB_1.2.3.4 {
58
- inflateReset2;
59
- inflateMark;
60
-} ZLIB_1.2.3.3;
61
-
62
-ZLIB_1.2.3.5 {
63
- gzbuffer;
64
- gzoffset;
65
- gzoffset64;
66
- gzclose_r;
67
- gzclose_w;
68
-} ZLIB_1.2.3.4;
69
-
70
-ZLIB_1.2.5.1 {
71
- deflatePending;
72
-} ZLIB_1.2.3.5;
73
-
74
-ZLIB_1.2.5.2 {
75
- deflateResetKeep;
76
- gzgetc_;
77
- inflateResetKeep;
78
-} ZLIB_1.2.5.1;
79
-
80
-ZLIB_1.2.7.1 {
81
- inflateGetDictionary;
82
- gzvprintf;
83
-} ZLIB_1.2.5.2;
84
-
85
-ZLIB_1.2.9 {
86
- inflateCodesUsed;
87
- inflateValidate;
88
- uncompress2;
89
- gzfread;
90
- gzfwrite;
91
- deflateGetDictionary;
92
- adler32_z;
93
- crc32_z;
94
-} ZLIB_1.2.7.1;
95
-
96
-ZLIB_1.2.12 {
97
- crc32_combine_gen;
98
- crc32_combine_gen64;
99
- crc32_combine_op;
100
-} ZLIB_1.2.9;
1
+ZLIB_1.2.0 {
2
+ global:
3
+ compressBound;
4
+ deflateBound;
5
+ inflateBack;
6
+ inflateBackEnd;
7
+ inflateBackInit_;
8
+ inflateCopy;
9
+ local:
10
+ deflate_copyright;
11
+ inflate_copyright;
12
+ inflate_fast;
13
+ inflate_table;
14
+ zcalloc;
15
+ zcfree;
16
+ z_errmsg;
17
+ gz_error;
18
+ gz_intmax;
19
+ _*;
20
+};
21
+
22
+ZLIB_1.2.0.2 {
23
+ gzclearerr;
24
+ gzungetc;
25
+ zlibCompileFlags;
26
+} ZLIB_1.2.0;
27
+
28
+ZLIB_1.2.0.8 {
29
+ deflatePrime;
30
+} ZLIB_1.2.0.2;
31
+
32
+ZLIB_1.2.2 {
33
+ adler32_combine;
34
+ crc32_combine;
35
+ deflateSetHeader;
36
+ inflateGetHeader;
37
+} ZLIB_1.2.0.8;
38
+
39
+ZLIB_1.2.2.3 {
40
+ deflateTune;
41
+ gzdirect;
42
+} ZLIB_1.2.2;
43
+
44
+ZLIB_1.2.2.4 {
45
+ inflatePrime;
46
+} ZLIB_1.2.2.3;
47
+
48
+ZLIB_1.2.3.3 {
49
+ adler32_combine64;
50
+ crc32_combine64;
51
+ gzopen64;
52
+ gzseek64;
53
+ gztell64;
54
+ inflateUndermine;
55
+} ZLIB_1.2.2.4;
56
+
57
+ZLIB_1.2.3.4 {
58
+ inflateReset2;
59
+ inflateMark;
60
+} ZLIB_1.2.3.3;
61
+
62
+ZLIB_1.2.3.5 {
63
+ gzbuffer;
64
+ gzoffset;
65
+ gzoffset64;
66
+ gzclose_r;
67
+ gzclose_w;
68
+} ZLIB_1.2.3.4;
69
+
70
+ZLIB_1.2.5.1 {
71
+ deflatePending;
72
+} ZLIB_1.2.3.5;
73
+
74
+ZLIB_1.2.5.2 {
75
+ deflateResetKeep;
76
+ gzgetc_;
77
+ inflateResetKeep;
78
+} ZLIB_1.2.5.1;
79
+
80
+ZLIB_1.2.7.1 {
81
+ inflateGetDictionary;
82
+ gzvprintf;
83
+} ZLIB_1.2.5.2;
84
+
85
+ZLIB_1.2.9 {
86
+ inflateCodesUsed;
87
+ inflateValidate;
88
+ uncompress2;
89
+ gzfread;
90
+ gzfwrite;
91
+ deflateGetDictionary;
92
+ adler32_z;
93
+ crc32_z;
94
+} ZLIB_1.2.7.1;
95
+
96
+ZLIB_1.2.12 {
97
+ crc32_combine_gen;
98
+ crc32_combine_gen64;
99
+ crc32_combine_op;
100
+} ZLIB_1.2.9;
101101
--- compat/zlib/zlib.map
+++ compat/zlib/zlib.map
@@ -1,100 +1,100 @@
1 ZLIB_1.2.0 {
2 global:
3 compressBound;
4 deflateBound;
5 inflateBack;
6 inflateBackEnd;
7 inflateBackInit_;
8 inflateCopy;
9 local:
10 deflate_copyright;
11 inflate_copyright;
12 inflate_fast;
13 inflate_table;
14 zcalloc;
15 zcfree;
16 z_errmsg;
17 gz_error;
18 gz_intmax;
19 _*;
20 };
21
22 ZLIB_1.2.0.2 {
23 gzclearerr;
24 gzungetc;
25 zlibCompileFlags;
26 } ZLIB_1.2.0;
27
28 ZLIB_1.2.0.8 {
29 deflatePrime;
30 } ZLIB_1.2.0.2;
31
32 ZLIB_1.2.2 {
33 adler32_combine;
34 crc32_combine;
35 deflateSetHeader;
36 inflateGetHeader;
37 } ZLIB_1.2.0.8;
38
39 ZLIB_1.2.2.3 {
40 deflateTune;
41 gzdirect;
42 } ZLIB_1.2.2;
43
44 ZLIB_1.2.2.4 {
45 inflatePrime;
46 } ZLIB_1.2.2.3;
47
48 ZLIB_1.2.3.3 {
49 adler32_combine64;
50 crc32_combine64;
51 gzopen64;
52 gzseek64;
53 gztell64;
54 inflateUndermine;
55 } ZLIB_1.2.2.4;
56
57 ZLIB_1.2.3.4 {
58 inflateReset2;
59 inflateMark;
60 } ZLIB_1.2.3.3;
61
62 ZLIB_1.2.3.5 {
63 gzbuffer;
64 gzoffset;
65 gzoffset64;
66 gzclose_r;
67 gzclose_w;
68 } ZLIB_1.2.3.4;
69
70 ZLIB_1.2.5.1 {
71 deflatePending;
72 } ZLIB_1.2.3.5;
73
74 ZLIB_1.2.5.2 {
75 deflateResetKeep;
76 gzgetc_;
77 inflateResetKeep;
78 } ZLIB_1.2.5.1;
79
80 ZLIB_1.2.7.1 {
81 inflateGetDictionary;
82 gzvprintf;
83 } ZLIB_1.2.5.2;
84
85 ZLIB_1.2.9 {
86 inflateCodesUsed;
87 inflateValidate;
88 uncompress2;
89 gzfread;
90 gzfwrite;
91 deflateGetDictionary;
92 adler32_z;
93 crc32_z;
94 } ZLIB_1.2.7.1;
95
96 ZLIB_1.2.12 {
97 crc32_combine_gen;
98 crc32_combine_gen64;
99 crc32_combine_op;
100 } ZLIB_1.2.9;
101
--- compat/zlib/zlib.map
+++ compat/zlib/zlib.map
@@ -1,100 +1,100 @@
1 ZLIB_1.2.0 {
2 global:
3 compressBound;
4 deflateBound;
5 inflateBack;
6 inflateBackEnd;
7 inflateBackInit_;
8 inflateCopy;
9 local:
10 deflate_copyright;
11 inflate_copyright;
12 inflate_fast;
13 inflate_table;
14 zcalloc;
15 zcfree;
16 z_errmsg;
17 gz_error;
18 gz_intmax;
19 _*;
20 };
21
22 ZLIB_1.2.0.2 {
23 gzclearerr;
24 gzungetc;
25 zlibCompileFlags;
26 } ZLIB_1.2.0;
27
28 ZLIB_1.2.0.8 {
29 deflatePrime;
30 } ZLIB_1.2.0.2;
31
32 ZLIB_1.2.2 {
33 adler32_combine;
34 crc32_combine;
35 deflateSetHeader;
36 inflateGetHeader;
37 } ZLIB_1.2.0.8;
38
39 ZLIB_1.2.2.3 {
40 deflateTune;
41 gzdirect;
42 } ZLIB_1.2.2;
43
44 ZLIB_1.2.2.4 {
45 inflatePrime;
46 } ZLIB_1.2.2.3;
47
48 ZLIB_1.2.3.3 {
49 adler32_combine64;
50 crc32_combine64;
51 gzopen64;
52 gzseek64;
53 gztell64;
54 inflateUndermine;
55 } ZLIB_1.2.2.4;
56
57 ZLIB_1.2.3.4 {
58 inflateReset2;
59 inflateMark;
60 } ZLIB_1.2.3.3;
61
62 ZLIB_1.2.3.5 {
63 gzbuffer;
64 gzoffset;
65 gzoffset64;
66 gzclose_r;
67 gzclose_w;
68 } ZLIB_1.2.3.4;
69
70 ZLIB_1.2.5.1 {
71 deflatePending;
72 } ZLIB_1.2.3.5;
73
74 ZLIB_1.2.5.2 {
75 deflateResetKeep;
76 gzgetc_;
77 inflateResetKeep;
78 } ZLIB_1.2.5.1;
79
80 ZLIB_1.2.7.1 {
81 inflateGetDictionary;
82 gzvprintf;
83 } ZLIB_1.2.5.2;
84
85 ZLIB_1.2.9 {
86 inflateCodesUsed;
87 inflateValidate;
88 uncompress2;
89 gzfread;
90 gzfwrite;
91 deflateGetDictionary;
92 adler32_z;
93 crc32_z;
94 } ZLIB_1.2.7.1;
95
96 ZLIB_1.2.12 {
97 crc32_combine_gen;
98 crc32_combine_gen64;
99 crc32_combine_op;
100 } ZLIB_1.2.9;
101
--- compat/zlib/zutil.h
+++ compat/zlib/zutil.h
@@ -1,7 +1,7 @@
11
/* zutil.h -- internal interface and configuration of the compression library
2
- * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
2
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
33
* For conditions of distribution and use, see copyright notice in zlib.h
44
*/
55
66
/* WARNING: this file should *not* be used by applications. It is
77
part of the implementation of the compression library and is
@@ -54,11 +54,11 @@
5454
#endif
5555
5656
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
5757
/* (size given to avoid silly warnings with Visual C++) */
5858
59
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
59
+#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
6060
6161
#define ERR_RETURN(strm,err) \
6262
return (strm->msg = ERR_MSG(err), (err))
6363
/* To be used only when the state is known to be valid */
6464
@@ -135,21 +135,12 @@
135135
# if defined(M_I86) && !defined(Z_SOLO)
136136
# include <malloc.h>
137137
# endif
138138
#endif
139139
140
-#if defined(MACOS) || defined(TARGET_OS_MAC)
140
+#if defined(MACOS)
141141
# define OS_CODE 7
142
-# ifndef Z_SOLO
143
-# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
144
-# include <unix.h> /* for fdopen */
145
-# else
146
-# ifndef fdopen
147
-# define fdopen(fd,mode) NULL /* No fdopen() */
148
-# endif
149
-# endif
150
-# endif
151142
#endif
152143
153144
#ifdef __acorn
154145
# define OS_CODE 13
155146
#endif
@@ -168,22 +159,10 @@
168159
169160
#ifdef __APPLE__
170161
# define OS_CODE 19
171162
#endif
172163
173
-#if defined(_BEOS_) || defined(RISCOS)
174
-# define fdopen(fd,mode) NULL /* No fdopen() */
175
-#endif
176
-
177
-#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
178
-# if defined(_WIN32_WCE)
179
-# define fdopen(fd,mode) NULL /* No fdopen() */
180
-# else
181
-# define fdopen(fd,type) _fdopen(fd,type)
182
-# endif
183
-#endif
184
-
185164
#if defined(__BORLANDC__) && !defined(MSDOS)
186165
#pragma warn -8004
187166
#pragma warn -8008
188167
#pragma warn -8066
189168
#endif
190169
--- compat/zlib/zutil.h
+++ compat/zlib/zutil.h
@@ -1,7 +1,7 @@
1 /* zutil.h -- internal interface and configuration of the compression library
2 * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* WARNING: this file should *not* be used by applications. It is
7 part of the implementation of the compression library and is
@@ -54,11 +54,11 @@
54 #endif
55
56 extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
57 /* (size given to avoid silly warnings with Visual C++) */
58
59 #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
60
61 #define ERR_RETURN(strm,err) \
62 return (strm->msg = ERR_MSG(err), (err))
63 /* To be used only when the state is known to be valid */
64
@@ -135,21 +135,12 @@
135 # if defined(M_I86) && !defined(Z_SOLO)
136 # include <malloc.h>
137 # endif
138 #endif
139
140 #if defined(MACOS) || defined(TARGET_OS_MAC)
141 # define OS_CODE 7
142 # ifndef Z_SOLO
143 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
144 # include <unix.h> /* for fdopen */
145 # else
146 # ifndef fdopen
147 # define fdopen(fd,mode) NULL /* No fdopen() */
148 # endif
149 # endif
150 # endif
151 #endif
152
153 #ifdef __acorn
154 # define OS_CODE 13
155 #endif
@@ -168,22 +159,10 @@
168
169 #ifdef __APPLE__
170 # define OS_CODE 19
171 #endif
172
173 #if defined(_BEOS_) || defined(RISCOS)
174 # define fdopen(fd,mode) NULL /* No fdopen() */
175 #endif
176
177 #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
178 # if defined(_WIN32_WCE)
179 # define fdopen(fd,mode) NULL /* No fdopen() */
180 # else
181 # define fdopen(fd,type) _fdopen(fd,type)
182 # endif
183 #endif
184
185 #if defined(__BORLANDC__) && !defined(MSDOS)
186 #pragma warn -8004
187 #pragma warn -8008
188 #pragma warn -8066
189 #endif
190
--- compat/zlib/zutil.h
+++ compat/zlib/zutil.h
@@ -1,7 +1,7 @@
1 /* zutil.h -- internal interface and configuration of the compression library
2 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 /* WARNING: this file should *not* be used by applications. It is
7 part of the implementation of the compression library and is
@@ -54,11 +54,11 @@
54 #endif
55
56 extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
57 /* (size given to avoid silly warnings with Visual C++) */
58
59 #define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
60
61 #define ERR_RETURN(strm,err) \
62 return (strm->msg = ERR_MSG(err), (err))
63 /* To be used only when the state is known to be valid */
64
@@ -135,21 +135,12 @@
135 # if defined(M_I86) && !defined(Z_SOLO)
136 # include <malloc.h>
137 # endif
138 #endif
139
140 #if defined(MACOS)
141 # define OS_CODE 7
 
 
 
 
 
 
 
 
 
142 #endif
143
144 #ifdef __acorn
145 # define OS_CODE 13
146 #endif
@@ -168,22 +159,10 @@
159
160 #ifdef __APPLE__
161 # define OS_CODE 19
162 #endif
163
 
 
 
 
 
 
 
 
 
 
 
 
164 #if defined(__BORLANDC__) && !defined(MSDOS)
165 #pragma warn -8004
166 #pragma warn -8008
167 #pragma warn -8066
168 #endif
169
+2590 -1030
--- extsrc/linenoise.c
+++ extsrc/linenoise.c
@@ -1,19 +1,718 @@
1
+#line 1 "utf8.h"
2
+#ifndef UTF8_UTIL_H
3
+#define UTF8_UTIL_H
4
+
5
+#ifdef __cplusplus
6
+extern "C" {
7
+#endif
8
+
9
+/**
10
+ * UTF-8 utility functions
11
+ *
12
+ * (c) 2010-2019 Steve Bennett <[email protected]>
13
+ *
14
+ * See utf8.c for licence details.
15
+ */
16
+
17
+#ifndef USE_UTF8
18
+#include <ctype.h>
19
+
20
+#define MAX_UTF8_LEN 1
21
+
22
+/* No utf-8 support. 1 byte = 1 char */
23
+#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
24
+#define utf8_strwidth(S, B) utf8_strlen((S), (B))
25
+#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
26
+#define utf8_index(C, I) (I)
27
+#define utf8_charlen(C) 1
28
+ #define utf8_width(C) 1
29
+
30
+#else
31
+
32
+#define MAX_UTF8_LEN 4
33
+
34
+/**
35
+ * Converts the given unicode codepoint (0 - 0x1fffff) to utf-8
36
+ * and stores the result at 'p'.
37
+ *
38
+ * Returns the number of utf-8 characters
39
+ */
40
+int utf8_fromunicode(char *p, unsigned uc);
41
+
42
+/**
43
+ * Returns the length of the utf-8 sequence starting with 'c'.
44
+ *
45
+ * Returns 1-4, or -1 if this is not a valid start byte.
46
+ *
47
+ * Note that charlen=4 is not supported by the rest of the API.
48
+ */
49
+int utf8_charlen(int c);
50
+
51
+/**
52
+ * Returns the number of characters in the utf-8
53
+ * string of the given byte length.
54
+ *
55
+ * Any bytes which are not part of an valid utf-8
56
+ * sequence are treated as individual characters.
57
+ *
58
+ * The string *must* be null terminated.
59
+ *
60
+ * Does not support unicode code points > \u1fffff
61
+ */
62
+int utf8_strlen(const char *str, int bytelen);
63
+
64
+/**
65
+ * Calculates the display width of the first 'charlen' characters in 'str'.
66
+ * See utf8_width()
67
+ */
68
+int utf8_strwidth(const char *str, int charlen);
69
+
70
+/**
71
+ * Returns the byte index of the given character in the utf-8 string.
72
+ *
73
+ * The string *must* be null terminated.
74
+ *
75
+ * This will return the byte length of a utf-8 string
76
+ * if given the char length.
77
+ */
78
+int utf8_index(const char *str, int charindex);
79
+
80
+/**
81
+ * Returns the unicode codepoint corresponding to the
82
+ * utf-8 sequence 'str'.
83
+ *
84
+ * Stores the result in *uc and returns the number of bytes
85
+ * consumed.
86
+ *
87
+ * If 'str' is null terminated, then an invalid utf-8 sequence
88
+ * at the end of the string will be returned as individual bytes.
89
+ *
90
+ * If it is not null terminated, the length *must* be checked first.
91
+ *
92
+ * Does not support unicode code points > \u1fffff
93
+ */
94
+int utf8_tounicode(const char *str, int *uc);
95
+
96
+/**
97
+ * Returns the width (in characters) of the given unicode codepoint.
98
+ * This is 1 for normal letters and 0 for combining characters and 2 for wide characters.
99
+ */
100
+int utf8_width(int ch);
101
+
102
+#endif
103
+
104
+#ifdef __cplusplus
105
+}
106
+#endif
107
+
108
+#endif
109
+#line 1 "utf8.c"
110
+/**
111
+ * UTF-8 utility functions
112
+ *
113
+ * (c) 2010-2019 Steve Bennett <[email protected]>
114
+ *
115
+ * All rights reserved.
116
+ *
117
+ * Redistribution and use in source and binary forms, with or without
118
+ * modification, are permitted provided that the following conditions are met:
119
+ *
120
+ * * Redistributions of source code must retain the above copyright notice,
121
+ * this list of conditions and the following disclaimer.
122
+ *
123
+ * * Redistributions in binary form must reproduce the above copyright notice,
124
+ * this list of conditions and the following disclaimer in the documentation
125
+ * and/or other materials provided with the distribution.
126
+ *
127
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
128
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
129
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
130
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
131
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
132
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
133
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
134
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
135
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
136
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
137
+ */
138
+
139
+#include <ctype.h>
140
+#include <stdlib.h>
141
+#include <string.h>
142
+#include <stdio.h>
143
+#ifndef UTF8_UTIL_H
144
+#include "utf8.h"
145
+#endif
146
+
147
+#ifdef USE_UTF8
148
+int utf8_fromunicode(char *p, unsigned uc)
149
+{
150
+ if (uc <= 0x7f) {
151
+ *p = uc;
152
+ return 1;
153
+ }
154
+ else if (uc <= 0x7ff) {
155
+ *p++ = 0xc0 | ((uc & 0x7c0) >> 6);
156
+ *p = 0x80 | (uc & 0x3f);
157
+ return 2;
158
+ }
159
+ else if (uc <= 0xffff) {
160
+ *p++ = 0xe0 | ((uc & 0xf000) >> 12);
161
+ *p++ = 0x80 | ((uc & 0xfc0) >> 6);
162
+ *p = 0x80 | (uc & 0x3f);
163
+ return 3;
164
+ }
165
+ /* Note: We silently truncate to 21 bits here: 0x1fffff */
166
+ else {
167
+ *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
168
+ *p++ = 0x80 | ((uc & 0x3f000) >> 12);
169
+ *p++ = 0x80 | ((uc & 0xfc0) >> 6);
170
+ *p = 0x80 | (uc & 0x3f);
171
+ return 4;
172
+ }
173
+}
174
+
175
+int utf8_charlen(int c)
176
+{
177
+ if ((c & 0x80) == 0) {
178
+ return 1;
179
+ }
180
+ if ((c & 0xe0) == 0xc0) {
181
+ return 2;
182
+ }
183
+ if ((c & 0xf0) == 0xe0) {
184
+ return 3;
185
+ }
186
+ if ((c & 0xf8) == 0xf0) {
187
+ return 4;
188
+ }
189
+ /* Invalid sequence */
190
+ return -1;
191
+}
192
+
193
+int utf8_strlen(const char *str, int bytelen)
194
+{
195
+ int charlen = 0;
196
+ if (bytelen < 0) {
197
+ bytelen = strlen(str);
198
+ }
199
+ while (bytelen > 0) {
200
+ int c;
201
+ int l = utf8_tounicode(str, &c);
202
+ charlen++;
203
+ str += l;
204
+ bytelen -= l;
205
+ }
206
+ return charlen;
207
+}
208
+
209
+int utf8_strwidth(const char *str, int charlen)
210
+{
211
+ int width = 0;
212
+ while (charlen) {
213
+ int c;
214
+ int l = utf8_tounicode(str, &c);
215
+ width += utf8_width(c);
216
+ str += l;
217
+ charlen--;
218
+ }
219
+ return width;
220
+}
221
+
222
+int utf8_index(const char *str, int index)
223
+{
224
+ const char *s = str;
225
+ while (index--) {
226
+ int c;
227
+ s += utf8_tounicode(s, &c);
228
+ }
229
+ return s - str;
230
+}
231
+
232
+int utf8_tounicode(const char *str, int *uc)
233
+{
234
+ unsigned const char *s = (unsigned const char *)str;
235
+
236
+ if (s[0] < 0xc0) {
237
+ *uc = s[0];
238
+ return 1;
239
+ }
240
+ if (s[0] < 0xe0) {
241
+ if ((s[1] & 0xc0) == 0x80) {
242
+ *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80);
243
+ if (*uc >= 0x80) {
244
+ return 2;
245
+ }
246
+ /* Otherwise this is an invalid sequence */
247
+ }
248
+ }
249
+ else if (s[0] < 0xf0) {
250
+ if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) {
251
+ *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80);
252
+ if (*uc >= 0x800) {
253
+ return 3;
254
+ }
255
+ /* Otherwise this is an invalid sequence */
256
+ }
257
+ }
258
+ else if (s[0] < 0xf8) {
259
+ if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80) && ((str[3] & 0xc0) == 0x80)) {
260
+ *uc = ((s[0] & ~0xf0) << 18) | ((s[1] & ~0x80) << 12) | ((s[2] & ~0x80) << 6) | (s[3] & ~0x80);
261
+ if (*uc >= 0x10000) {
262
+ return 4;
263
+ }
264
+ /* Otherwise this is an invalid sequence */
265
+ }
266
+ }
267
+
268
+ /* Invalid sequence, so just return the byte */
269
+ *uc = *s;
270
+ return 1;
271
+}
272
+
273
+struct utf8range {
274
+ int lower; /* lower inclusive */
275
+ int upper; /* upper exclusive */
276
+};
277
+
278
+/* From http://unicode.org/Public/UNIDATA/UnicodeData.txt */
279
+static const struct utf8range unicode_range_combining[] = {
280
+ { 0x0300, 0x0370 }, { 0x0483, 0x048a }, { 0x0591, 0x05d0 }, { 0x0610, 0x061b },
281
+ { 0x064b, 0x0660 }, { 0x0670, 0x0671 }, { 0x06d6, 0x06dd }, { 0x06df, 0x06e5 },
282
+ { 0x06e7, 0x06ee }, { 0x0711, 0x0712 }, { 0x0730, 0x074d }, { 0x07a6, 0x07b1 },
283
+ { 0x07eb, 0x07f4 }, { 0x0816, 0x0830 }, { 0x0859, 0x085e }, { 0x08d4, 0x0904 },
284
+ { 0x093a, 0x0958 }, { 0x0962, 0x0964 }, { 0x0981, 0x0985 }, { 0x09bc, 0x09ce },
285
+ { 0x09d7, 0x09dc }, { 0x09e2, 0x09e6 }, { 0x0a01, 0x0a05 }, { 0x0a3c, 0x0a59 },
286
+ { 0x0a70, 0x0a72 }, { 0x0a75, 0x0a85 }, { 0x0abc, 0x0ad0 }, { 0x0ae2, 0x0ae6 },
287
+ { 0x0afa, 0x0b05 }, { 0x0b3c, 0x0b5c }, { 0x0b62, 0x0b66 }, { 0x0b82, 0x0b83 },
288
+ { 0x0bbe, 0x0bd0 }, { 0x0bd7, 0x0be6 }, { 0x0c00, 0x0c05 }, { 0x0c3e, 0x0c58 },
289
+ { 0x0c62, 0x0c66 }, { 0x0c81, 0x0c85 }, { 0x0cbc, 0x0cde }, { 0x0ce2, 0x0ce6 },
290
+ { 0x0d00, 0x0d05 }, { 0x0d3b, 0x0d4e }, { 0x0d57, 0x0d58 }, { 0x0d62, 0x0d66 },
291
+ { 0x0d82, 0x0d85 }, { 0x0dca, 0x0de6 }, { 0x0df2, 0x0df4 }, { 0x0e31, 0x0e32 },
292
+ { 0x0e34, 0x0e3f }, { 0x0e47, 0x0e4f }, { 0x0eb1, 0x0eb2 }, { 0x0eb4, 0x0ebd },
293
+ { 0x0ec8, 0x0ed0 }, { 0x0f18, 0x0f1a }, { 0x0f35, 0x0f3a }, { 0x0f3e, 0x0f40 },
294
+ { 0x0f71, 0x0f88 }, { 0x0f8d, 0x0fbe }, { 0x0fc6, 0x0fc7 }, { 0x102b, 0x103f },
295
+ { 0x1056, 0x105a }, { 0x105e, 0x1065 }, { 0x1067, 0x106e }, { 0x1071, 0x1075 },
296
+ { 0x1082, 0x1090 }, { 0x109a, 0x109e }, { 0x135d, 0x1360 }, { 0x1712, 0x1720 },
297
+ { 0x1732, 0x1735 }, { 0x1752, 0x1760 }, { 0x1772, 0x1780 }, { 0x17b4, 0x17d4 },
298
+ { 0x17dd, 0x17e0 }, { 0x180b, 0x180e }, { 0x1885, 0x1887 }, { 0x18a9, 0x18aa },
299
+ { 0x1920, 0x1940 }, { 0x1a17, 0x1a1e }, { 0x1a55, 0x1a80 }, { 0x1ab0, 0x1b05 },
300
+ { 0x1b34, 0x1b45 }, { 0x1b6b, 0x1b74 }, { 0x1b80, 0x1b83 }, { 0x1ba1, 0x1bae },
301
+ { 0x1be6, 0x1bfc }, { 0x1c24, 0x1c3b }, { 0x1cd0, 0x1ce9 }, { 0x1ced, 0x1cee },
302
+ { 0x1cf2, 0x1cf5 }, { 0x1cf7, 0x1d00 }, { 0x1dc0, 0x1e00 }, { 0x20d0, 0x2100 },
303
+ { 0x2cef, 0x2cf2 }, { 0x2d7f, 0x2d80 }, { 0x2de0, 0x2e00 }, { 0x302a, 0x3030 },
304
+ { 0x3099, 0x309b }, { 0xa66f, 0xa67e }, { 0xa69e, 0xa6a0 }, { 0xa6f0, 0xa6f2 },
305
+ { 0xa802, 0xa803 }, { 0xa806, 0xa807 }, { 0xa80b, 0xa80c }, { 0xa823, 0xa828 },
306
+ { 0xa880, 0xa882 }, { 0xa8b4, 0xa8ce }, { 0xa8e0, 0xa8f2 }, { 0xa926, 0xa92e },
307
+ { 0xa947, 0xa95f }, { 0xa980, 0xa984 }, { 0xa9b3, 0xa9c1 }, { 0xa9e5, 0xa9e6 },
308
+ { 0xaa29, 0xaa40 }, { 0xaa43, 0xaa44 }, { 0xaa4c, 0xaa50 }, { 0xaa7b, 0xaa7e },
309
+ { 0xaab0, 0xaab5 }, { 0xaab7, 0xaab9 }, { 0xaabe, 0xaac2 }, { 0xaaeb, 0xaaf0 },
310
+ { 0xaaf5, 0xab01 }, { 0xabe3, 0xabf0 }, { 0xfb1e, 0xfb1f }, { 0xfe00, 0xfe10 },
311
+ { 0xfe20, 0xfe30 },
312
+};
313
+
314
+/* From http://unicode.org/Public/UNIDATA/EastAsianWidth.txt */
315
+static const struct utf8range unicode_range_wide[] = {
316
+ { 0x1100, 0x115f }, { 0x231a, 0x231b }, { 0x2329, 0x232a }, { 0x23e9, 0x23ec },
317
+ { 0x23f0, 0x23f0 }, { 0x23f3, 0x23f3 }, { 0x25fd, 0x25fe }, { 0x2614, 0x2615 },
318
+ { 0x2648, 0x2653 }, { 0x267f, 0x267f }, { 0x2693, 0x2693 }, { 0x26a1, 0x26a1 },
319
+ { 0x26aa, 0x26ab }, { 0x26bd, 0x26be }, { 0x26c4, 0x26c5 }, { 0x26ce, 0x26ce },
320
+ { 0x26d4, 0x26d4 }, { 0x26ea, 0x26ea }, { 0x26f2, 0x26f3 }, { 0x26f5, 0x26f5 },
321
+ { 0x26fa, 0x26fa }, { 0x26fd, 0x26fd }, { 0x2705, 0x2705 }, { 0x270a, 0x270b },
322
+ { 0x2728, 0x2728 }, { 0x274c, 0x274c }, { 0x274e, 0x274e }, { 0x2753, 0x2755 },
323
+ { 0x2757, 0x2757 }, { 0x2795, 0x2797 }, { 0x27b0, 0x27b0 }, { 0x27bf, 0x27bf },
324
+ { 0x2b1b, 0x2b1c }, { 0x2b50, 0x2b50 }, { 0x2b55, 0x2b55 }, { 0x2e80, 0x2e99 },
325
+ { 0x2e9b, 0x2ef3 }, { 0x2f00, 0x2fd5 }, { 0x2ff0, 0x2ffb }, { 0x3001, 0x303e },
326
+ { 0x3041, 0x3096 }, { 0x3099, 0x30ff }, { 0x3105, 0x312e }, { 0x3131, 0x318e },
327
+ { 0x3190, 0x31ba }, { 0x31c0, 0x31e3 }, { 0x31f0, 0x321e }, { 0x3220, 0x3247 },
328
+ { 0x3250, 0x32fe }, { 0x3300, 0x4dbf }, { 0x4e00, 0xa48c }, { 0xa490, 0xa4c6 },
329
+ { 0xa960, 0xa97c }, { 0xac00, 0xd7a3 }, { 0xf900, 0xfaff }, { 0xfe10, 0xfe19 },
330
+ { 0xfe30, 0xfe52 }, { 0xfe54, 0xfe66 }, { 0xfe68, 0xfe6b }, { 0x16fe0, 0x16fe1 },
331
+ { 0x17000, 0x187ec }, { 0x18800, 0x18af2 }, { 0x1b000, 0x1b11e }, { 0x1b170, 0x1b2fb },
332
+ { 0x1f004, 0x1f004 }, { 0x1f0cf, 0x1f0cf }, { 0x1f18e, 0x1f18e }, { 0x1f191, 0x1f19a },
333
+ { 0x1f200, 0x1f202 }, { 0x1f210, 0x1f23b }, { 0x1f240, 0x1f248 }, { 0x1f250, 0x1f251 },
334
+ { 0x1f260, 0x1f265 }, { 0x1f300, 0x1f320 }, { 0x1f32d, 0x1f335 }, { 0x1f337, 0x1f37c },
335
+ { 0x1f37e, 0x1f393 }, { 0x1f3a0, 0x1f3ca }, { 0x1f3cf, 0x1f3d3 }, { 0x1f3e0, 0x1f3f0 },
336
+ { 0x1f3f4, 0x1f3f4 }, { 0x1f3f8, 0x1f43e }, { 0x1f440, 0x1f440 }, { 0x1f442, 0x1f4fc },
337
+ { 0x1f4ff, 0x1f53d }, { 0x1f54b, 0x1f54e }, { 0x1f550, 0x1f567 }, { 0x1f57a, 0x1f57a },
338
+ { 0x1f595, 0x1f596 }, { 0x1f5a4, 0x1f5a4 }, { 0x1f5fb, 0x1f64f }, { 0x1f680, 0x1f6c5 },
339
+ { 0x1f6cc, 0x1f6cc }, { 0x1f6d0, 0x1f6d2 }, { 0x1f6eb, 0x1f6ec }, { 0x1f6f4, 0x1f6f8 },
340
+ { 0x1f910, 0x1f93e }, { 0x1f940, 0x1f94c }, { 0x1f950, 0x1f96b }, { 0x1f980, 0x1f997 },
341
+ { 0x1f9c0, 0x1f9c0 }, { 0x1f9d0, 0x1f9e6 }, { 0x20000, 0x2fffd }, { 0x30000, 0x3fffd },
342
+};
343
+
344
+#define ARRAYSIZE(A) sizeof(A) / sizeof(*(A))
345
+
346
+static int cmp_range(const void *key, const void *cm)
347
+{
348
+ const struct utf8range *range = (const struct utf8range *)cm;
349
+ int ch = *(int *)key;
350
+ if (ch < range->lower) {
351
+ return -1;
352
+ }
353
+ if (ch >= range->upper) {
354
+ return 1;
355
+ }
356
+ return 0;
357
+}
358
+
359
+static int utf8_in_range(const struct utf8range *range, int num, int ch)
360
+{
361
+ const struct utf8range *r =
362
+ bsearch(&ch, range, num, sizeof(*range), cmp_range);
363
+
364
+ if (r) {
365
+ return 1;
366
+ }
367
+ return 0;
368
+}
369
+
370
+int utf8_width(int ch)
371
+{
372
+ /* short circuit for common case */
373
+ if (isascii(ch)) {
374
+ return 1;
375
+ }
376
+ if (utf8_in_range(unicode_range_combining, ARRAYSIZE(unicode_range_combining), ch)) {
377
+ return 0;
378
+ }
379
+ if (utf8_in_range(unicode_range_wide, ARRAYSIZE(unicode_range_wide), ch)) {
380
+ return 2;
381
+ }
382
+ return 1;
383
+}
384
+#endif
385
+#line 1 "stringbuf.h"
386
+#ifndef STRINGBUF_H
387
+#define STRINGBUF_H
388
+/**
389
+ * resizable string buffer
390
+ *
391
+ * (c) 2017-2020 Steve Bennett <[email protected]>
392
+ *
393
+ * See utf8.c for licence details.
394
+ */
395
+#ifdef __cplusplus
396
+extern "C" {
397
+#endif
398
+
399
+/** @file
400
+ * A stringbuf is a resizing, null terminated string buffer.
401
+ *
402
+ * The buffer is reallocated as necessary.
403
+ *
404
+ * In general it is *not* OK to call these functions with a NULL pointer
405
+ * unless stated otherwise.
406
+ *
407
+ * If USE_UTF8 is defined, supports utf8.
408
+ */
409
+
410
+/**
411
+ * The stringbuf structure should not be accessed directly.
412
+ * Use the functions below.
413
+ */
414
+typedef struct {
415
+ int remaining; /**< Allocated, but unused space */
416
+ int last; /**< Index of the null terminator (and thus the length of the string) */
417
+#ifdef USE_UTF8
418
+ int chars; /**< Count of characters */
419
+#endif
420
+ char *data; /**< Allocated memory containing the string or NULL for empty */
421
+} stringbuf;
422
+
423
+/**
424
+ * Allocates and returns a new stringbuf with no elements.
425
+ */
426
+stringbuf *sb_alloc(void);
427
+
428
+/**
429
+ * Frees a stringbuf.
430
+ * It is OK to call this with NULL.
431
+ */
432
+void sb_free(stringbuf *sb);
433
+
434
+/**
435
+ * Returns an allocated copy of the stringbuf
436
+ */
437
+stringbuf *sb_copy(stringbuf *sb);
438
+
439
+/**
440
+ * Returns the byte length of the buffer.
441
+ *
442
+ * Returns 0 for both a NULL buffer and an empty buffer.
443
+ */
444
+static inline int sb_len(stringbuf *sb) {
445
+ return sb->last;
446
+}
447
+
448
+/**
449
+ * Returns the utf8 character length of the buffer.
450
+ *
451
+ * Returns 0 for both a NULL buffer and an empty buffer.
452
+ */
453
+static inline int sb_chars(stringbuf *sb) {
454
+#ifdef USE_UTF8
455
+ return sb->chars;
456
+#else
457
+ return sb->last;
458
+#endif
459
+}
460
+
461
+/**
462
+ * Appends a null terminated string to the stringbuf
463
+ */
464
+void sb_append(stringbuf *sb, const char *str);
465
+
466
+/**
467
+ * Like sb_append() except does not require a null terminated string.
468
+ * The length of 'str' is given as 'len'
469
+ *
470
+ * Note that in utf8 mode, characters will *not* be counted correctly
471
+ * if a partial utf8 sequence is added with sb_append_len()
472
+ */
473
+void sb_append_len(stringbuf *sb, const char *str, int len);
474
+
475
+/**
476
+ * Returns a pointer to the null terminated string in the buffer.
477
+ *
478
+ * Note this pointer only remains valid until the next modification to the
479
+ * string buffer.
480
+ *
481
+ * The returned pointer can be used to update the buffer in-place
482
+ * as long as care is taken to not overwrite the end of the buffer.
483
+ */
484
+static inline char *sb_str(const stringbuf *sb)
485
+{
486
+ return sb->data;
487
+}
488
+
489
+/**
490
+ * Inserts the given string *before* (zero-based) byte 'index' in the stringbuf.
491
+ * If index is past the end of the buffer, the string is appended,
492
+ * just like sb_append()
493
+ */
494
+void sb_insert(stringbuf *sb, int index, const char *str);
495
+
496
+/**
497
+ * Delete 'len' bytes in the string at the given index.
498
+ *
499
+ * Any bytes past the end of the buffer are ignored.
500
+ * The buffer remains null terminated.
501
+ *
502
+ * If len is -1, deletes to the end of the buffer.
503
+ */
504
+void sb_delete(stringbuf *sb, int index, int len);
505
+
506
+/**
507
+ * Clear to an empty buffer.
508
+ */
509
+void sb_clear(stringbuf *sb);
510
+
511
+/**
512
+ * Return an allocated copy of buffer and frees 'sb'.
513
+ *
514
+ * If 'sb' is empty, returns an allocated copy of "".
515
+ */
516
+char *sb_to_string(stringbuf *sb);
517
+
518
+#ifdef __cplusplus
519
+}
520
+#endif
521
+
522
+#endif
523
+#line 1 "stringbuf.c"
524
+/**
525
+ * resizable string buffer
526
+ *
527
+ * (c) 2017-2020 Steve Bennett <[email protected]>
528
+ *
529
+ * See utf8.c for licence details.
530
+ */
531
+#include <stdlib.h>
532
+#include <string.h>
533
+#include <stdio.h>
534
+#include <ctype.h>
535
+#include <assert.h>
536
+
537
+#ifndef STRINGBUF_H
538
+#include "stringbuf.h"
539
+#endif
540
+#ifdef USE_UTF8
541
+#ifndef UTF8_UTIL_H
542
+#include "utf8.h"
543
+#endif
544
+#endif
545
+
546
+#define SB_INCREMENT 200
547
+
548
+stringbuf *sb_alloc(void)
549
+{
550
+ stringbuf *sb = (stringbuf *)malloc(sizeof(*sb));
551
+ sb->remaining = 0;
552
+ sb->last = 0;
553
+#ifdef USE_UTF8
554
+ sb->chars = 0;
555
+#endif
556
+ sb->data = NULL;
557
+
558
+ return(sb);
559
+}
560
+
561
+void sb_free(stringbuf *sb)
562
+{
563
+ if (sb) {
564
+ free(sb->data);
565
+ }
566
+ free(sb);
567
+}
568
+
569
+static void sb_realloc(stringbuf *sb, int newlen)
570
+{
571
+ sb->data = (char *)realloc(sb->data, newlen);
572
+ sb->remaining = newlen - sb->last;
573
+}
574
+
575
+void sb_append(stringbuf *sb, const char *str)
576
+{
577
+ sb_append_len(sb, str, strlen(str));
578
+}
579
+
580
+void sb_append_len(stringbuf *sb, const char *str, int len)
581
+{
582
+ if (sb->remaining < len + 1) {
583
+ sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
584
+ }
585
+ memcpy(sb->data + sb->last, str, len);
586
+ sb->data[sb->last + len] = 0;
587
+
588
+ sb->last += len;
589
+ sb->remaining -= len;
590
+#ifdef USE_UTF8
591
+ sb->chars += utf8_strlen(str, len);
592
+#endif
593
+}
594
+
595
+char *sb_to_string(stringbuf *sb)
596
+{
597
+ if (sb->data == NULL) {
598
+ /* Return an allocated empty string, not null */
599
+ return strdup("");
600
+ }
601
+ else {
602
+ /* Just return the data and free the stringbuf structure */
603
+ char *pt = sb->data;
604
+ free(sb);
605
+ return pt;
606
+ }
607
+}
608
+
609
+/* Insert and delete operations */
610
+
611
+/* Moves up all the data at position 'pos' and beyond by 'len' bytes
612
+ * to make room for new data
613
+ *
614
+ * Note: Does *not* update sb->chars
615
+ */
616
+static void sb_insert_space(stringbuf *sb, int pos, int len)
617
+{
618
+ assert(pos <= sb->last);
619
+
620
+ /* Make sure there is enough space */
621
+ if (sb->remaining < len) {
622
+ sb_realloc(sb, sb->last + len + SB_INCREMENT);
623
+ }
624
+ /* Now move it up */
625
+ memmove(sb->data + pos + len, sb->data + pos, sb->last - pos);
626
+ sb->last += len;
627
+ sb->remaining -= len;
628
+ /* And null terminate */
629
+ sb->data[sb->last] = 0;
630
+}
631
+
632
+/**
633
+ * Move down all the data from pos + len, effectively
634
+ * deleting the data at position 'pos' of length 'len'
635
+ */
636
+static void sb_delete_space(stringbuf *sb, int pos, int len)
637
+{
638
+ assert(pos < sb->last);
639
+ assert(pos + len <= sb->last);
640
+
641
+#ifdef USE_UTF8
642
+ sb->chars -= utf8_strlen(sb->data + pos, len);
643
+#endif
644
+
645
+ /* Now move it up */
646
+ memmove(sb->data + pos, sb->data + pos + len, sb->last - pos - len);
647
+ sb->last -= len;
648
+ sb->remaining += len;
649
+ /* And null terminate */
650
+ sb->data[sb->last] = 0;
651
+}
652
+
653
+void sb_insert(stringbuf *sb, int index, const char *str)
654
+{
655
+ if (index >= sb->last) {
656
+ /* Inserting after the end of the list appends. */
657
+ sb_append(sb, str);
658
+ }
659
+ else {
660
+ int len = strlen(str);
661
+
662
+ sb_insert_space(sb, index, len);
663
+ memcpy(sb->data + index, str, len);
664
+#ifdef USE_UTF8
665
+ sb->chars += utf8_strlen(str, len);
666
+#endif
667
+ }
668
+}
669
+
670
+/**
671
+ * Delete the bytes at index 'index' for length 'len'
672
+ * Has no effect if the index is past the end of the list.
673
+ */
674
+void sb_delete(stringbuf *sb, int index, int len)
675
+{
676
+ if (index < sb->last) {
677
+ char *pos = sb->data + index;
678
+ if (len < 0) {
679
+ len = sb->last;
680
+ }
681
+
682
+ sb_delete_space(sb, pos - sb->data, len);
683
+ }
684
+}
685
+
686
+void sb_clear(stringbuf *sb)
687
+{
688
+ if (sb->data) {
689
+ /* Null terminate */
690
+ sb->data[0] = 0;
691
+ sb->last = 0;
692
+#ifdef USE_UTF8
693
+ sb->chars = 0;
694
+#endif
695
+ }
696
+}
697
+#line 1 "linenoise.c"
1698
/* linenoise.c -- guerrilla line editing library against the idea that a
2699
* line editing lib needs to be 20,000 lines of C code.
3700
*
4701
* You can find the latest source code at:
5702
*
6
- * http://github.com/antirez/linenoise
703
+ * http://github.com/msteveb/linenoise
704
+ * (forked from http://github.com/antirez/linenoise)
7705
*
8706
* Does a number of crazy assumptions that happen to be true in 99.9999% of
9707
* the 2010 UNIX computers around.
10708
*
11709
* ------------------------------------------------------------------------
12710
*
13
- * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
14
- * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
711
+ * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
712
+ * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
713
+ * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
15714
*
16715
* All rights reserved.
17716
*
18717
* Redistribution and use in source and binary forms, with or without
19718
* modification, are permitted provided that the following conditions are
@@ -42,211 +741,381 @@
42741
*
43742
* References:
44743
* - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
45744
* - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
46745
*
47
- * Todo list:
48
- * - Filter bogus Ctrl+<char> combinations.
49
- * - Win32 support
50
- *
51746
* Bloat:
52
- * - History search like Ctrl+r in readline?
747
+ * - Completion?
53748
*
749
+ * Unix/termios
750
+ * ------------
54751
* List of escape sequences used by this program, we do everything just
55
- * with three sequences. In order to be so cheap we may have some
752
+ * a few sequences. In order to be so cheap we may have some
56753
* flickering effect with some slow terminal, but the lesser sequences
57754
* the more compatible.
58755
*
59756
* EL (Erase Line)
60
- * Sequence: ESC [ n K
61
- * Effect: if n is 0 or missing, clear from cursor to end of line
62
- * Effect: if n is 1, clear from beginning of line to cursor
63
- * Effect: if n is 2, clear entire line
757
+ * Sequence: ESC [ 0 K
758
+ * Effect: clear from cursor to end of line
64759
*
65760
* CUF (CUrsor Forward)
66761
* Sequence: ESC [ n C
67762
* Effect: moves cursor forward n chars
68763
*
69
- * CUB (CUrsor Backward)
70
- * Sequence: ESC [ n D
71
- * Effect: moves cursor backward n chars
72
- *
73
- * The following is used to get the terminal width if getting
74
- * the width with the TIOCGWINSZ ioctl fails
75
- *
76
- * DSR (Device Status Report)
77
- * Sequence: ESC [ 6 n
78
- * Effect: reports the current cusor position as ESC [ n ; m R
79
- * where n is the row and m is the column
80
- *
81
- * When multi line mode is enabled, we also use an additional escape
82
- * sequence. However multi line editing is disabled by default.
83
- *
84
- * CUU (Cursor Up)
85
- * Sequence: ESC [ n A
86
- * Effect: moves cursor up of n chars.
87
- *
88
- * CUD (Cursor Down)
89
- * Sequence: ESC [ n B
90
- * Effect: moves cursor down of n chars.
91
- *
92
- * When linenoiseClearScreen() is called, two additional escape sequences
93
- * are used in order to clear the screen and position the cursor at home
94
- * position.
95
- *
96
- * CUP (Cursor position)
764
+ * CR (Carriage Return)
765
+ * Sequence: \r
766
+ * Effect: moves cursor to column 1
767
+ *
768
+ * The following are used to clear the screen: ESC [ H ESC [ 2 J
769
+ * This is actually composed of two sequences:
770
+ *
771
+ * cursorhome
97772
* Sequence: ESC [ H
98773
* Effect: moves the cursor to upper left corner
99774
*
100
- * ED (Erase display)
775
+ * ED2 (Clear entire screen)
101776
* Sequence: ESC [ 2 J
102777
* Effect: clear the whole screen
103778
*
779
+ * == For highlighting control characters, we also use the following two ==
780
+ * SO (enter StandOut)
781
+ * Sequence: ESC [ 7 m
782
+ * Effect: Uses some standout mode such as reverse video
783
+ *
784
+ * SE (Standout End)
785
+ * Sequence: ESC [ 0 m
786
+ * Effect: Exit standout mode
787
+ *
788
+ * == Only used if TIOCGWINSZ fails ==
789
+ * DSR/CPR (Report cursor position)
790
+ * Sequence: ESC [ 6 n
791
+ * Effect: reports current cursor position as ESC [ NNN ; MMM R
792
+ *
793
+ * == Only used in multiline mode ==
794
+ * CUU (Cursor Up)
795
+ * Sequence: ESC [ n A
796
+ * Effect: moves cursor up n chars.
797
+ *
798
+ * CUD (Cursor Down)
799
+ * Sequence: ESC [ n B
800
+ * Effect: moves cursor down n chars.
801
+ *
802
+ * win32/console
803
+ * -------------
804
+ * If __MINGW32__ is defined, the win32 console API is used.
805
+ * This could probably be made to work for the msvc compiler too.
806
+ * This support based in part on work by Jon Griffiths.
104807
*/
105808
809
+#ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
810
+#include <windows.h>
811
+#include <fcntl.h>
812
+#define USE_WINCONSOLE
813
+#ifdef __MINGW32__
814
+#define HAVE_UNISTD_H
815
+#endif
816
+#else
106817
#include <termios.h>
818
+#include <sys/ioctl.h>
819
+#include <poll.h>
820
+#define USE_TERMIOS
821
+#define HAVE_UNISTD_H
822
+#endif
823
+
824
+#ifdef HAVE_UNISTD_H
107825
#include <unistd.h>
826
+#endif
108827
#include <stdlib.h>
828
+#include <stdarg.h>
109829
#include <stdio.h>
830
+#include <assert.h>
110831
#include <errno.h>
111832
#include <string.h>
833
+#include <signal.h>
112834
#include <stdlib.h>
113
-#include <ctype.h>
114
-#include <sys/stat.h>
115835
#include <sys/types.h>
116
-#include <sys/ioctl.h>
117
-#include <unistd.h>
836
+
837
+#if defined(_WIN32) && !defined(__MINGW32__)
838
+/* Microsoft headers don't like old POSIX names */
839
+#define strdup _strdup
840
+#define snprintf _snprintf
841
+#endif
842
+
118843
#include "linenoise.h"
844
+#ifndef STRINGBUF_H
845
+#include "stringbuf.h"
846
+#endif
847
+#ifndef UTF8_UTIL_H
848
+#include "utf8.h"
849
+#endif
119850
120851
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
121
-#define LINENOISE_MAX_LINE 4096
122
-static char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
123
-static linenoiseCompletionCallback *completionCallback = NULL;
124
-static linenoiseHintsCallback *hintsCallback = NULL;
125
-static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
126
-
127
-static struct termios orig_termios; /* In order to restore at exit.*/
128
-static int maskmode = 0; /* Show "***" instead of input. For passwords. */
129
-static int rawmode = 0; /* For atexit() function to check if restore is needed*/
130
-static int mlmode = 0; /* Multi line mode. Default is single line. */
131
-static int atexit_registered = 0; /* Register atexit just 1 time. */
852
+
853
+/* ctrl('A') -> 0x01 */
854
+#define ctrl(C) ((C) - '@')
855
+/* meta('a') -> 0xe1 */
856
+#define meta(C) ((C) | 0x80)
857
+
858
+/* Use -ve numbers here to co-exist with normal unicode chars */
859
+enum {
860
+ SPECIAL_NONE,
861
+ /* don't use -1 here since that indicates error */
862
+ SPECIAL_UP = -20,
863
+ SPECIAL_DOWN = -21,
864
+ SPECIAL_LEFT = -22,
865
+ SPECIAL_RIGHT = -23,
866
+ SPECIAL_DELETE = -24,
867
+ SPECIAL_HOME = -25,
868
+ SPECIAL_END = -26,
869
+ SPECIAL_INSERT = -27,
870
+ SPECIAL_PAGE_UP = -28,
871
+ SPECIAL_PAGE_DOWN = -29,
872
+
873
+ /* Some handy names for other special keycodes */
874
+ CHAR_ESCAPE = 27,
875
+ CHAR_DELETE = 127,
876
+};
877
+
132878
static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
133879
static int history_len = 0;
880
+static int history_index = 0;
134881
static char **history = NULL;
135882
136
-/* The linenoiseState structure represents the state during line editing.
137
- * We pass this state to functions implementing specific editing
138
- * functionalities. */
139
-struct linenoiseState {
140
- int ifd; /* Terminal stdin file descriptor. */
141
- int ofd; /* Terminal stdout file descriptor. */
142
- char *buf; /* Edited line buffer. */
143
- size_t buflen; /* Edited line buffer size. */
144
- const char *prompt; /* Prompt to display. */
145
- size_t plen; /* Prompt length. */
146
- size_t pos; /* Current cursor position. */
147
- size_t oldpos; /* Previous refresh cursor position. */
148
- size_t len; /* Current edited line length. */
149
- size_t cols; /* Number of columns in terminal. */
150
- size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
151
- int history_index; /* The history index we are currently editing. */
152
-};
153
-
154
-enum KEY_ACTION{
155
- KEY_NULL = 0, /* NULL */
156
- CTRL_A = 1, /* Ctrl+a */
157
- CTRL_B = 2, /* Ctrl-b */
158
- CTRL_C = 3, /* Ctrl-c */
159
- CTRL_D = 4, /* Ctrl-d */
160
- CTRL_E = 5, /* Ctrl-e */
161
- CTRL_F = 6, /* Ctrl-f */
162
- CTRL_H = 8, /* Ctrl-h */
163
- TAB = 9, /* Tab */
164
- CTRL_K = 11, /* Ctrl+k */
165
- CTRL_L = 12, /* Ctrl+l */
166
- ENTER = 13, /* Enter */
167
- CTRL_N = 14, /* Ctrl-n */
168
- CTRL_P = 16, /* Ctrl-p */
169
- CTRL_T = 20, /* Ctrl-t */
170
- CTRL_U = 21, /* Ctrl+u */
171
- CTRL_W = 23, /* Ctrl+w */
172
- ESC = 27, /* Escape */
173
- BACKSPACE = 127 /* Backspace */
174
-};
175
-
176
-static void linenoiseAtExit(void);
177
-int linenoiseHistoryAdd(const char *line);
178
-static void refreshLine(struct linenoiseState *l);
179
-
180
-/* Debugging macro. */
181
-#if 0
182
-FILE *lndebug_fp = NULL;
183
-#define lndebug(...) \
184
- do { \
185
- if (lndebug_fp == NULL) { \
186
- lndebug_fp = fopen("/tmp/lndebug.txt","a"); \
187
- fprintf(lndebug_fp, \
188
- "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \
189
- (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \
190
- (int)l->maxrows,old_rows); \
191
- } \
192
- fprintf(lndebug_fp, ", " __VA_ARGS__); \
193
- fflush(lndebug_fp); \
194
- } while (0)
195
-#else
196
-#define lndebug(fmt, ...)
197
-#endif
198
-
199
-/* ======================= Low level terminal handling ====================== */
200
-
201
-/* Enable "mask mode". When it is enabled, instead of the input that
202
- * the user is typing, the terminal will just display a corresponding
203
- * number of asterisks, like "****". This is useful for passwords and other
204
- * secrets that should not be displayed. */
205
-void linenoiseMaskModeEnable(void) {
206
- maskmode = 1;
207
-}
208
-
209
-/* Disable mask mode. */
210
-void linenoiseMaskModeDisable(void) {
211
- maskmode = 0;
212
-}
213
-
214
-/* Set if to use or not the multi line mode. */
215
-void linenoiseSetMultiLine(int ml) {
216
- mlmode = ml;
217
-}
218
-
219
-/* Return true if the terminal name is in the list of terminals we know are
220
- * not able to understand basic escape sequences. */
221
-static int isUnsupportedTerm(void) {
222
- char *term = getenv("TERM");
223
- int j;
224
-
225
- if (term == NULL) return 0;
226
- for (j = 0; unsupported_term[j]; j++)
227
- if (!strcasecmp(term,unsupported_term[j])) return 1;
228
- return 0;
229
-}
230
-
231
-/* Raw mode: 1960 magic shit. */
232
-static int enableRawMode(int fd) {
233
- struct termios raw;
234
-
235
- if (!isatty(STDIN_FILENO)) goto fatal;
883
+/* Structure to contain the status of the current (being edited) line */
884
+struct current {
885
+ stringbuf *buf; /* Current buffer. Always null terminated */
886
+ int pos; /* Cursor position, measured in chars */
887
+ int cols; /* Size of the window, in chars */
888
+ int nrows; /* How many rows are being used in multiline mode (>= 1) */
889
+ int rpos; /* The current row containing the cursor - multiline mode only */
890
+ int colsright; /* refreshLine() cached cols for insert_char() optimisation */
891
+ int colsleft; /* refreshLine() cached cols for remove_char() optimisation */
892
+ const char *prompt;
893
+ stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
894
+ stringbuf *output; /* used only during refreshLine() - output accumulator */
895
+#if defined(USE_TERMIOS)
896
+ int fd; /* Terminal fd */
897
+#elif defined(USE_WINCONSOLE)
898
+ HANDLE outh; /* Console output handle */
899
+ HANDLE inh; /* Console input handle */
900
+ int rows; /* Screen rows */
901
+ int x; /* Current column during output */
902
+ int y; /* Current row */
903
+#ifdef USE_UTF8
904
+ #define UBUF_MAX_CHARS 132
905
+ WORD ubuf[UBUF_MAX_CHARS + 1]; /* Accumulates utf16 output - one extra for final surrogate pairs */
906
+ int ubuflen; /* length used in ubuf */
907
+ int ubufcols; /* how many columns are represented by the chars in ubuf? */
908
+#endif
909
+#endif
910
+};
911
+
912
+static int fd_read(struct current *current);
913
+static int getWindowSize(struct current *current);
914
+static void cursorDown(struct current *current, int n);
915
+static void cursorUp(struct current *current, int n);
916
+static void eraseEol(struct current *current);
917
+static void refreshLine(struct current *current);
918
+static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
919
+static void setCursorPos(struct current *current, int x);
920
+static void setOutputHighlight(struct current *current, const int *props, int nprops);
921
+static void set_current(struct current *current, const char *str);
922
+
923
+static int fd_isatty(struct current *current)
924
+{
925
+#ifdef USE_TERMIOS
926
+ return isatty(current->fd);
927
+#else
928
+ (void)current;
929
+ return 0;
930
+#endif
931
+}
932
+
933
+void linenoiseHistoryFree(void) {
934
+ if (history) {
935
+ int j;
936
+
937
+ for (j = 0; j < history_len; j++)
938
+ free(history[j]);
939
+ free(history);
940
+ history = NULL;
941
+ history_len = 0;
942
+ }
943
+}
944
+
945
+typedef enum {
946
+ EP_START, /* looking for ESC */
947
+ EP_ESC, /* looking for [ */
948
+ EP_DIGITS, /* parsing digits */
949
+ EP_PROPS, /* parsing digits or semicolons */
950
+ EP_END, /* ok */
951
+ EP_ERROR, /* error */
952
+} ep_state_t;
953
+
954
+struct esc_parser {
955
+ ep_state_t state;
956
+ int props[5]; /* properties are stored here */
957
+ int maxprops; /* size of the props[] array */
958
+ int numprops; /* number of properties found */
959
+ int termchar; /* terminator char, or 0 for any alpha */
960
+ int current; /* current (partial) property value */
961
+};
962
+
963
+/**
964
+ * Initialise the escape sequence parser at *parser.
965
+ *
966
+ * If termchar is 0 any alpha char terminates ok. Otherwise only the given
967
+ * char terminates successfully.
968
+ * Run the parser state machine with calls to parseEscapeSequence() for each char.
969
+ */
970
+static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
971
+{
972
+ parser->state = EP_START;
973
+ parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
974
+ parser->numprops = 0;
975
+ parser->current = 0;
976
+ parser->termchar = termchar;
977
+}
978
+
979
+/**
980
+ * Pass character 'ch' into the state machine to parse:
981
+ * 'ESC' '[' <digits> (';' <digits>)* <termchar>
982
+ *
983
+ * The first character must be ESC.
984
+ * Returns the current state. The state machine is done when it returns either EP_END
985
+ * or EP_ERROR.
986
+ *
987
+ * On EP_END, the "property/attribute" values can be read from parser->props[]
988
+ * of length parser->numprops.
989
+ */
990
+static int parseEscapeSequence(struct esc_parser *parser, int ch)
991
+{
992
+ switch (parser->state) {
993
+ case EP_START:
994
+ parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
995
+ break;
996
+ case EP_ESC:
997
+ parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
998
+ break;
999
+ case EP_PROPS:
1000
+ if (ch == ';') {
1001
+ parser->state = EP_DIGITS;
1002
+donedigits:
1003
+ if (parser->numprops + 1 < parser->maxprops) {
1004
+ parser->props[parser->numprops++] = parser->current;
1005
+ parser->current = 0;
1006
+ }
1007
+ break;
1008
+ }
1009
+ /* fall through */
1010
+ case EP_DIGITS:
1011
+ if (ch >= '0' && ch <= '9') {
1012
+ parser->current = parser->current * 10 + (ch - '0');
1013
+ parser->state = EP_PROPS;
1014
+ break;
1015
+ }
1016
+ /* must be terminator */
1017
+ if (parser->termchar != ch) {
1018
+ if (parser->termchar != 0 || !((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))) {
1019
+ parser->state = EP_ERROR;
1020
+ break;
1021
+ }
1022
+ }
1023
+ parser->state = EP_END;
1024
+ goto donedigits;
1025
+ case EP_END:
1026
+ parser->state = EP_ERROR;
1027
+ break;
1028
+ case EP_ERROR:
1029
+ break;
1030
+ }
1031
+ return parser->state;
1032
+}
1033
+
1034
+/*#define DEBUG_REFRESHLINE*/
1035
+
1036
+#ifdef DEBUG_REFRESHLINE
1037
+#define DRL(ARGS...) fprintf(dfh, ARGS)
1038
+static FILE *dfh;
1039
+
1040
+static void DRL_CHAR(int ch)
1041
+{
1042
+ if (ch < ' ') {
1043
+ DRL("^%c", ch + '@');
1044
+ }
1045
+ else if (ch > 127) {
1046
+ DRL("\\u%04x", ch);
1047
+ }
1048
+ else {
1049
+ DRL("%c", ch);
1050
+ }
1051
+}
1052
+static void DRL_STR(const char *str)
1053
+{
1054
+ while (*str) {
1055
+ int ch;
1056
+ int n = utf8_tounicode(str, &ch);
1057
+ str += n;
1058
+ DRL_CHAR(ch);
1059
+ }
1060
+}
1061
+#else
1062
+#define DRL(...)
1063
+#define DRL_CHAR(ch)
1064
+#define DRL_STR(str)
1065
+#endif
1066
+
1067
+#if defined(USE_WINCONSOLE)
1068
+#include "linenoise-win32.c"
1069
+#endif
1070
+
1071
+#if defined(USE_TERMIOS)
1072
+static void linenoiseAtExit(void);
1073
+static struct termios orig_termios; /* in order to restore at exit */
1074
+static int rawmode = 0; /* for atexit() function to check if restore is needed*/
1075
+static int atexit_registered = 0; /* register atexit just 1 time */
1076
+
1077
+static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
1078
+
1079
+static int isUnsupportedTerm(void) {
1080
+ char *term = getenv("TERM");
1081
+
1082
+ if (term) {
1083
+ int j;
1084
+ for (j = 0; unsupported_term[j]; j++) {
1085
+ if (strcmp(term, unsupported_term[j]) == 0) {
1086
+ return 1;
1087
+ }
1088
+ }
1089
+ }
1090
+ return 0;
1091
+}
1092
+
1093
+static int enableRawMode(struct current *current) {
1094
+ struct termios raw;
1095
+
1096
+ current->fd = STDIN_FILENO;
1097
+ current->cols = 0;
1098
+
1099
+ if (!isatty(current->fd) || isUnsupportedTerm() ||
1100
+ tcgetattr(current->fd, &orig_termios) == -1) {
1101
+fatal:
1102
+ errno = ENOTTY;
1103
+ return -1;
1104
+ }
1105
+
2361106
if (!atexit_registered) {
2371107
atexit(linenoiseAtExit);
2381108
atexit_registered = 1;
2391109
}
240
- if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
2411110
2421111
raw = orig_termios; /* modify the original mode */
2431112
/* input modes: no break, no CR to NL, no parity check, no strip char,
2441113
* no start/stop output control. */
2451114
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
246
- /* output modes - disable post processing */
247
- raw.c_oflag &= ~(OPOST);
1115
+ /* output modes - actually, no need to disable post processing */
1116
+ /*raw.c_oflag &= ~(OPOST);*/
2481117
/* control modes - set 8 bit chars */
2491118
raw.c_cflag |= (CS8);
2501119
/* local modes - choing off, canonical off, no extended functions,
2511120
* no signal chars (^Z,^C) */
2521121
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
@@ -253,163 +1122,452 @@
2531122
/* control chars - set return condition: min number of bytes and timer.
2541123
* We want read to return every single byte, without timeout. */
2551124
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
2561125
2571126
/* put terminal in raw mode after flushing */
258
- if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;
1127
+ if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
1128
+ goto fatal;
1129
+ }
2591130
rawmode = 1;
2601131
return 0;
261
-
262
-fatal:
263
- errno = ENOTTY;
264
- return -1;
2651132
}
2661133
267
-static void disableRawMode(int fd) {
1134
+static void disableRawMode(struct current *current) {
2681135
/* Don't even check the return value as it's too late. */
269
- if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)
1136
+ if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
2701137
rawmode = 0;
2711138
}
2721139
273
-/* Use the ESC [6n escape sequence to query the horizontal cursor position
274
- * and return it. On error -1 is returned, on success the position of the
275
- * cursor. */
276
-static int getCursorPosition(int ifd, int ofd) {
277
- char buf[32];
278
- int cols, rows;
279
- unsigned int i = 0;
280
-
281
- /* Report cursor location */
282
- if (write(ofd, "\x1b[6n", 4) != 4) return -1;
283
-
284
- /* Read the response: ESC [ rows ; cols R */
285
- while (i < sizeof(buf)-1) {
286
- if (read(ifd,buf+i,1) != 1) break;
287
- if (buf[i] == 'R') break;
288
- i++;
289
- }
290
- buf[i] = '\0';
291
-
292
- /* Parse it. */
293
- if (buf[0] != ESC || buf[1] != '[') return -1;
294
- if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
295
- return cols;
296
-}
297
-
298
-/* Try to get the number of columns in the current terminal, or assume 80
299
- * if it fails. */
300
-static int getColumns(int ifd, int ofd) {
1140
+/* At exit we'll try to fix the terminal to the initial conditions. */
1141
+static void linenoiseAtExit(void) {
1142
+ if (rawmode) {
1143
+ tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
1144
+ }
1145
+ linenoiseHistoryFree();
1146
+}
1147
+
1148
+/* gcc/glibc insists that we care about the return code of write!
1149
+ * Clarification: This means that a void-cast like "(void) (EXPR)"
1150
+ * does not work.
1151
+ */
1152
+#define IGNORE_RC(EXPR) if (EXPR) {}
1153
+
1154
+/**
1155
+ * Output bytes directly, or accumulate output (if current->output is set)
1156
+ */
1157
+static void outputChars(struct current *current, const char *buf, int len)
1158
+{
1159
+ if (len < 0) {
1160
+ len = strlen(buf);
1161
+ }
1162
+ if (current->output) {
1163
+ sb_append_len(current->output, buf, len);
1164
+ }
1165
+ else {
1166
+ IGNORE_RC(write(current->fd, buf, len));
1167
+ }
1168
+}
1169
+
1170
+/* Like outputChars, but using printf-style formatting
1171
+ */
1172
+static void outputFormatted(struct current *current, const char *format, ...)
1173
+{
1174
+ va_list args;
1175
+ char buf[64];
1176
+ int n;
1177
+
1178
+ va_start(args, format);
1179
+ n = vsnprintf(buf, sizeof(buf), format, args);
1180
+ /* This will never happen because we are sure to use outputFormatted() only for short sequences */
1181
+ assert(n < (int)sizeof(buf));
1182
+ va_end(args);
1183
+ outputChars(current, buf, n);
1184
+}
1185
+
1186
+static void cursorToLeft(struct current *current)
1187
+{
1188
+ outputChars(current, "\r", -1);
1189
+}
1190
+
1191
+static void setOutputHighlight(struct current *current, const int *props, int nprops)
1192
+{
1193
+ outputChars(current, "\x1b[", -1);
1194
+ while (nprops--) {
1195
+ outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
1196
+ props++;
1197
+ }
1198
+}
1199
+
1200
+static void eraseEol(struct current *current)
1201
+{
1202
+ outputChars(current, "\x1b[0K", -1);
1203
+}
1204
+
1205
+static void setCursorPos(struct current *current, int x)
1206
+{
1207
+ if (x == 0) {
1208
+ cursorToLeft(current);
1209
+ }
1210
+ else {
1211
+ outputFormatted(current, "\r\x1b[%dC", x);
1212
+ }
1213
+}
1214
+
1215
+static void cursorUp(struct current *current, int n)
1216
+{
1217
+ if (n) {
1218
+ outputFormatted(current, "\x1b[%dA", n);
1219
+ }
1220
+}
1221
+
1222
+static void cursorDown(struct current *current, int n)
1223
+{
1224
+ if (n) {
1225
+ outputFormatted(current, "\x1b[%dB", n);
1226
+ }
1227
+}
1228
+
1229
+void linenoiseClearScreen(void)
1230
+{
1231
+ IGNORE_RC(write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7));
1232
+}
1233
+
1234
+/**
1235
+ * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
1236
+ *
1237
+ * A timeout of -1 means to wait forever.
1238
+ *
1239
+ * Returns -1 if no char is received within the time or an error occurs.
1240
+ */
1241
+static int fd_read_char(int fd, int timeout)
1242
+{
1243
+ struct pollfd p;
1244
+ unsigned char c;
1245
+
1246
+ p.fd = fd;
1247
+ p.events = POLLIN;
1248
+
1249
+ if (poll(&p, 1, timeout) == 0) {
1250
+ /* timeout */
1251
+ return -1;
1252
+ }
1253
+ if (read(fd, &c, 1) != 1) {
1254
+ return -1;
1255
+ }
1256
+ return c;
1257
+}
1258
+
1259
+/**
1260
+ * Reads a complete utf-8 character
1261
+ * and returns the unicode value, or -1 on error.
1262
+ */
1263
+static int fd_read(struct current *current)
1264
+{
1265
+#ifdef USE_UTF8
1266
+ char buf[MAX_UTF8_LEN];
1267
+ int n;
1268
+ int i;
1269
+ int c;
1270
+
1271
+ if (read(current->fd, &buf[0], 1) != 1) {
1272
+ return -1;
1273
+ }
1274
+ n = utf8_charlen(buf[0]);
1275
+ if (n < 1) {
1276
+ return -1;
1277
+ }
1278
+ for (i = 1; i < n; i++) {
1279
+ if (read(current->fd, &buf[i], 1) != 1) {
1280
+ return -1;
1281
+ }
1282
+ }
1283
+ /* decode and return the character */
1284
+ utf8_tounicode(buf, &c);
1285
+ return c;
1286
+#else
1287
+ return fd_read_char(current->fd, -1);
1288
+#endif
1289
+}
1290
+
1291
+
1292
+/**
1293
+ * Stores the current cursor column in '*cols'.
1294
+ * Returns 1 if OK, or 0 if failed to determine cursor pos.
1295
+ */
1296
+static int queryCursor(struct current *current, int* cols)
1297
+{
1298
+ struct esc_parser parser;
1299
+ int ch;
1300
+
1301
+ /* Should not be buffering this output, it needs to go immediately */
1302
+ assert(current->output == NULL);
1303
+
1304
+ /* control sequence - report cursor location */
1305
+ outputChars(current, "\x1b[6n", -1);
1306
+
1307
+ /* Parse the response: ESC [ rows ; cols R */
1308
+ initParseEscapeSeq(&parser, 'R');
1309
+ while ((ch = fd_read_char(current->fd, 100)) > 0) {
1310
+ switch (parseEscapeSequence(&parser, ch)) {
1311
+ default:
1312
+ continue;
1313
+ case EP_END:
1314
+ if (parser.numprops == 2 && parser.props[1] < 1000) {
1315
+ *cols = parser.props[1];
1316
+ return 1;
1317
+ }
1318
+ break;
1319
+ case EP_ERROR:
1320
+ break;
1321
+ }
1322
+ /* failed */
1323
+ break;
1324
+ }
1325
+ return 0;
1326
+}
1327
+
1328
+/**
1329
+ * Updates current->cols with the current window size (width)
1330
+ */
1331
+static int getWindowSize(struct current *current)
1332
+{
3011333
struct winsize ws;
3021334
303
- if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
304
- /* ioctl() failed. Try to query the terminal itself. */
305
- int start, cols;
306
-
307
- /* Get the initial position so we can restore it later. */
308
- start = getCursorPosition(ifd,ofd);
309
- if (start == -1) goto failed;
310
-
311
- /* Go to right margin and get position. */
312
- if (write(ofd,"\x1b[999C",6) != 6) goto failed;
313
- cols = getCursorPosition(ifd,ofd);
314
- if (cols == -1) goto failed;
315
-
316
- /* Restore position. */
317
- if (cols > start) {
318
- char seq[32];
319
- snprintf(seq,32,"\x1b[%dD",cols-start);
320
- if (write(ofd,seq,strlen(seq)) == -1) {
321
- /* Can't recover... */
322
- }
323
- }
324
- return cols;
325
- } else {
326
- return ws.ws_col;
327
- }
328
-
329
-failed:
330
- return 80;
331
-}
332
-
333
-/* Clear the screen. Used to handle ctrl+l */
334
-void linenoiseClearScreen(void) {
335
- if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
336
- /* nothing to do, just to avoid warning. */
337
- }
338
-}
339
-
340
-/* Beep, used for completion when there is nothing to complete or when all
341
- * the choices were already shown. */
342
-static void linenoiseBeep(void) {
1335
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) {
1336
+ current->cols = ws.ws_col;
1337
+ return 0;
1338
+ }
1339
+
1340
+ /* Failed to query the window size. Perhaps we are on a serial terminal.
1341
+ * Try to query the width by sending the cursor as far to the right
1342
+ * and reading back the cursor position.
1343
+ * Note that this is only done once per call to linenoise rather than
1344
+ * every time the line is refreshed for efficiency reasons.
1345
+ *
1346
+ * In more detail, we:
1347
+ * (a) request current cursor position,
1348
+ * (b) move cursor far right,
1349
+ * (c) request cursor position again,
1350
+ * (d) at last move back to the old position.
1351
+ * This gives us the width without messing with the externally
1352
+ * visible cursor position.
1353
+ */
1354
+
1355
+ if (current->cols == 0) {
1356
+ int here;
1357
+
1358
+ /* If anything fails => default 80 */
1359
+ current->cols = 80;
1360
+
1361
+ /* (a) */
1362
+ if (queryCursor (current, &here)) {
1363
+ /* (b) */
1364
+ setCursorPos(current, 999);
1365
+
1366
+ /* (c). Note: If (a) succeeded, then (c) should as well.
1367
+ * For paranoia we still check and have a fallback action
1368
+ * for (d) in case of failure..
1369
+ */
1370
+ if (queryCursor (current, &current->cols)) {
1371
+ /* (d) Reset the cursor back to the original location. */
1372
+ if (current->cols > here) {
1373
+ setCursorPos(current, here);
1374
+ }
1375
+ }
1376
+ }
1377
+ }
1378
+
1379
+ return 0;
1380
+}
1381
+
1382
+/**
1383
+ * If CHAR_ESCAPE was received, reads subsequent
1384
+ * chars to determine if this is a known special key.
1385
+ *
1386
+ * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
1387
+ *
1388
+ * If no additional char is received within a short time,
1389
+ * CHAR_ESCAPE is returned.
1390
+ */
1391
+static int check_special(int fd)
1392
+{
1393
+ int c = fd_read_char(fd, 50);
1394
+ int c2;
1395
+
1396
+ if (c < 0) {
1397
+ return CHAR_ESCAPE;
1398
+ }
1399
+ else if (c >= 'a' && c <= 'z') {
1400
+ /* esc-a => meta-a */
1401
+ return meta(c);
1402
+ }
1403
+
1404
+ c2 = fd_read_char(fd, 50);
1405
+ if (c2 < 0) {
1406
+ return c2;
1407
+ }
1408
+ if (c == '[' || c == 'O') {
1409
+ /* Potential arrow key */
1410
+ switch (c2) {
1411
+ case 'A':
1412
+ return SPECIAL_UP;
1413
+ case 'B':
1414
+ return SPECIAL_DOWN;
1415
+ case 'C':
1416
+ return SPECIAL_RIGHT;
1417
+ case 'D':
1418
+ return SPECIAL_LEFT;
1419
+ case 'F':
1420
+ return SPECIAL_END;
1421
+ case 'H':
1422
+ return SPECIAL_HOME;
1423
+ }
1424
+ }
1425
+ if (c == '[' && c2 >= '1' && c2 <= '8') {
1426
+ /* extended escape */
1427
+ c = fd_read_char(fd, 50);
1428
+ if (c == '~') {
1429
+ switch (c2) {
1430
+ case '2':
1431
+ return SPECIAL_INSERT;
1432
+ case '3':
1433
+ return SPECIAL_DELETE;
1434
+ case '5':
1435
+ return SPECIAL_PAGE_UP;
1436
+ case '6':
1437
+ return SPECIAL_PAGE_DOWN;
1438
+ case '7':
1439
+ return SPECIAL_HOME;
1440
+ case '8':
1441
+ return SPECIAL_END;
1442
+ }
1443
+ }
1444
+ while (c != -1 && c != '~') {
1445
+ /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
1446
+ c = fd_read_char(fd, 50);
1447
+ }
1448
+ }
1449
+
1450
+ return SPECIAL_NONE;
1451
+}
1452
+#endif
1453
+
1454
+static void clearOutputHighlight(struct current *current)
1455
+{
1456
+ int nohighlight = 0;
1457
+ setOutputHighlight(current, &nohighlight, 1);
1458
+}
1459
+
1460
+static void outputControlChar(struct current *current, char ch)
1461
+{
1462
+ int reverse = 7;
1463
+ setOutputHighlight(current, &reverse, 1);
1464
+ outputChars(current, "^", 1);
1465
+ outputChars(current, &ch, 1);
1466
+ clearOutputHighlight(current);
1467
+}
1468
+
1469
+#ifndef utf8_getchars
1470
+static int utf8_getchars(char *buf, int c)
1471
+{
1472
+#ifdef USE_UTF8
1473
+ return utf8_fromunicode(buf, c);
1474
+#else
1475
+ *buf = c;
1476
+ return 1;
1477
+#endif
1478
+}
1479
+#endif
1480
+
1481
+/**
1482
+ * Returns the unicode character at the given offset,
1483
+ * or -1 if none.
1484
+ */
1485
+static int get_char(struct current *current, int pos)
1486
+{
1487
+ if (pos >= 0 && pos < sb_chars(current->buf)) {
1488
+ int c;
1489
+ int i = utf8_index(sb_str(current->buf), pos);
1490
+ (void)utf8_tounicode(sb_str(current->buf) + i, &c);
1491
+ return c;
1492
+ }
1493
+ return -1;
1494
+}
1495
+
1496
+static int char_display_width(int ch)
1497
+{
1498
+ if (ch < ' ') {
1499
+ /* control chars take two positions */
1500
+ return 2;
1501
+ }
1502
+ else {
1503
+ return utf8_width(ch);
1504
+ }
1505
+}
1506
+
1507
+#ifndef NO_COMPLETION
1508
+static linenoiseCompletionCallback *completionCallback = NULL;
1509
+static void *completionUserdata = NULL;
1510
+static int showhints = 1;
1511
+static linenoiseHintsCallback *hintsCallback = NULL;
1512
+static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
1513
+static void *hintsUserdata = NULL;
1514
+
1515
+static void beep(void) {
1516
+#ifdef USE_TERMIOS
3431517
fprintf(stderr, "\x7");
3441518
fflush(stderr);
1519
+#endif
3451520
}
3461521
347
-/* ============================== Completion ================================ */
348
-
349
-/* Free a list of completion option populated by linenoiseAddCompletion(). */
3501522
static void freeCompletions(linenoiseCompletions *lc) {
3511523
size_t i;
3521524
for (i = 0; i < lc->len; i++)
3531525
free(lc->cvec[i]);
354
- if (lc->cvec != NULL)
355
- free(lc->cvec);
1526
+ free(lc->cvec);
3561527
}
3571528
358
-/* This is an helper function for linenoiseEdit() and is called when the
359
- * user types the <tab> key in order to complete the string currently in the
360
- * input.
361
- *
362
- * The state of the editing is encapsulated into the pointed linenoiseState
363
- * structure as described in the structure definition. */
364
-static int completeLine(struct linenoiseState *ls) {
1529
+static int completeLine(struct current *current) {
3651530
linenoiseCompletions lc = { 0, NULL };
366
- int nread, nwritten;
367
- char c = 0;
1531
+ int c = 0;
3681532
369
- completionCallback(ls->buf,&lc);
1533
+ completionCallback(sb_str(current->buf),&lc,completionUserdata);
3701534
if (lc.len == 0) {
371
- linenoiseBeep();
1535
+ beep();
3721536
} else {
3731537
size_t stop = 0, i = 0;
3741538
3751539
while(!stop) {
3761540
/* Show completion or original buffer */
3771541
if (i < lc.len) {
378
- struct linenoiseState saved = *ls;
379
-
380
- ls->len = ls->pos = strlen(lc.cvec[i]);
381
- ls->buf = lc.cvec[i];
382
- refreshLine(ls);
383
- ls->len = saved.len;
384
- ls->pos = saved.pos;
385
- ls->buf = saved.buf;
1542
+ int chars = utf8_strlen(lc.cvec[i], -1);
1543
+ refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
3861544
} else {
387
- refreshLine(ls);
1545
+ refreshLine(current);
3881546
}
3891547
390
- nread = read(ls->ifd,&c,1);
391
- if (nread <= 0) {
392
- freeCompletions(&lc);
393
- return -1;
1548
+ c = fd_read(current);
1549
+ if (c == -1) {
1550
+ break;
3941551
}
3951552
3961553
switch(c) {
397
- case 9: /* tab */
1554
+ case '\t': /* tab */
3981555
i = (i+1) % (lc.len+1);
399
- if (i == lc.len) linenoiseBeep();
1556
+ if (i == lc.len) beep();
4001557
break;
401
- case 27: /* escape */
1558
+ case CHAR_ESCAPE: /* escape */
4021559
/* Re-show original buffer */
403
- if (i < lc.len) refreshLine(ls);
1560
+ if (i < lc.len) {
1561
+ refreshLine(current);
1562
+ }
4041563
stop = 1;
4051564
break;
4061565
default:
4071566
/* Update buffer and return */
4081567
if (i < lc.len) {
409
- nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
410
- ls->len = ls->pos = nwritten;
1568
+ set_current(current,lc.cvec[i]);
4111569
}
4121570
stop = 1;
4131571
break;
4141572
}
4151573
}
@@ -417,769 +1575,1126 @@
4171575
4181576
freeCompletions(&lc);
4191577
return c; /* Return last read character */
4201578
}
4211579
422
-/* Register a callback function to be called for tab-completion. */
423
-void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
1580
+/* Register a callback function to be called for tab-completion.
1581
+ Returns the prior callback so that the caller may (if needed)
1582
+ restore it when done. */
1583
+linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
1584
+ linenoiseCompletionCallback * old = completionCallback;
4241585
completionCallback = fn;
425
-}
426
-
427
-/* Register a hits function to be called to show hits to the user at the
428
- * right of the prompt. */
429
-void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
430
- hintsCallback = fn;
431
-}
432
-
433
-/* Register a function to free the hints returned by the hints callback
434
- * registered with linenoiseSetHintsCallback(). */
435
-void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
436
- freeHintsCallback = fn;
437
-}
438
-
439
-/* This function is used by the callback function registered by the user
440
- * in order to add completion options given the input string when the
441
- * user typed <tab>. See the example.c source code for a very easy to
442
- * understand example. */
1586
+ completionUserdata = userdata;
1587
+ return old;
1588
+}
1589
+
4431590
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
444
- size_t len = strlen(str);
445
- char *copy, **cvec;
446
-
447
- copy = malloc(len+1);
448
- if (copy == NULL) return;
449
- memcpy(copy,str,len+1);
450
- cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
451
- if (cvec == NULL) {
452
- free(copy);
453
- return;
454
- }
455
- lc->cvec = cvec;
456
- lc->cvec[lc->len++] = copy;
457
-}
458
-
459
-/* =========================== Line editing ================================= */
460
-
461
-/* We define a very simple "append buffer" structure, that is an heap
462
- * allocated string where we can append to. This is useful in order to
463
- * write all the escape sequences in a buffer and flush them to the standard
464
- * output in a single call, to avoid flickering effects. */
465
-struct abuf {
466
- char *b;
467
- int len;
468
-};
469
-
470
-static void abInit(struct abuf *ab) {
471
- ab->b = NULL;
472
- ab->len = 0;
473
-}
474
-
475
-static void abAppend(struct abuf *ab, const char *s, int len) {
476
- char *new = realloc(ab->b,ab->len+len);
477
-
478
- if (new == NULL) return;
479
- memcpy(new+ab->len,s,len);
480
- ab->b = new;
481
- ab->len += len;
482
-}
483
-
484
-static void abFree(struct abuf *ab) {
485
- free(ab->b);
1591
+ lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
1592
+ lc->cvec[lc->len++] = strdup(str);
1593
+}
1594
+
1595
+void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
1596
+{
1597
+ hintsCallback = callback;
1598
+ hintsUserdata = userdata;
1599
+}
1600
+
1601
+void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
1602
+{
1603
+ freeHintsCallback = callback;
1604
+}
1605
+
1606
+#endif
1607
+
1608
+
1609
+static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
1610
+{
1611
+ /* We have availcols columns available.
1612
+ * If necessary, strip chars off the front of buf until *cursor_pos
1613
+ * fits within availcols
1614
+ */
1615
+ int needcols = 0;
1616
+ int pos = 0;
1617
+ int new_cursor_pos = *cursor_pos;
1618
+ const char *pt = buf;
1619
+
1620
+ DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
1621
+
1622
+ while (*pt) {
1623
+ int ch;
1624
+ int n = utf8_tounicode(pt, &ch);
1625
+ pt += n;
1626
+
1627
+ needcols += char_display_width(ch);
1628
+
1629
+ /* If we need too many cols, strip
1630
+ * chars off the front of buf to make it fit.
1631
+ * We keep 3 extra cols to the right of the cursor.
1632
+ * 2 for possible wide chars, 1 for the last column that
1633
+ * can't be used.
1634
+ */
1635
+ while (needcols >= availcols - 3) {
1636
+ n = utf8_tounicode(buf, &ch);
1637
+ buf += n;
1638
+ needcols -= char_display_width(ch);
1639
+ DRL_CHAR(ch);
1640
+
1641
+ /* and adjust the apparent cursor position */
1642
+ new_cursor_pos--;
1643
+
1644
+ if (buf == pt) {
1645
+ /* can't remove more than this */
1646
+ break;
1647
+ }
1648
+ }
1649
+
1650
+ if (pos++ == *cursor_pos) {
1651
+ break;
1652
+ }
1653
+
1654
+ }
1655
+ DRL("<snip>");
1656
+ DRL_STR(buf);
1657
+ DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
1658
+
1659
+ /* Done, now new_cursor_pos contains the adjusted cursor position
1660
+ * and buf points to he adjusted start
1661
+ */
1662
+ *cursor_pos = new_cursor_pos;
1663
+ return buf;
1664
+}
1665
+
1666
+static int mlmode = 0;
1667
+
1668
+void linenoiseSetMultiLine(int enableml)
1669
+{
1670
+ mlmode = enableml;
4861671
}
4871672
4881673
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
489
- * to the right of the prompt. */
490
-void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
491
- char seq[64];
492
- if (hintsCallback && plen+l->len < l->cols) {
493
- int color = -1, bold = 0;
494
- char *hint = hintsCallback(l->buf,&color,&bold);
1674
+ * to the right of the prompt.
1675
+ * Returns 1 if a hint was shown, or 0 if not
1676
+ * If 'display' is 0, does no output. Just returns the appropriate return code.
1677
+ */
1678
+static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
1679
+{
1680
+ int rc = 0;
1681
+ if (showhints && hintsCallback && availcols > 0) {
1682
+ int bold = 0;
1683
+ int color = -1;
1684
+ char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
4951685
if (hint) {
496
- int hintlen = strlen(hint);
497
- int hintmaxlen = l->cols-(plen+l->len);
498
- if (hintlen > hintmaxlen) hintlen = hintmaxlen;
499
- if (bold == 1 && color == -1) color = 37;
500
- if (color != -1 || bold != 0)
501
- snprintf(seq,64,"\033[%d;%d;49m",bold,color);
502
- else
503
- seq[0] = '\0';
504
- abAppend(ab,seq,strlen(seq));
505
- abAppend(ab,hint,hintlen);
506
- if (color != -1 || bold != 0)
507
- abAppend(ab,"\033[0m",4);
508
- /* Call the function to free the hint returned. */
509
- if (freeHintsCallback) freeHintsCallback(hint);
510
- }
511
- }
512
-}
513
-
514
-/* Single line low level line refresh.
515
- *
516
- * Rewrite the currently edited line accordingly to the buffer content,
517
- * cursor position, and number of columns of the terminal. */
518
-static void refreshSingleLine(struct linenoiseState *l) {
519
- char seq[64];
520
- size_t plen = strlen(l->prompt);
521
- int fd = l->ofd;
522
- char *buf = l->buf;
523
- size_t len = l->len;
524
- size_t pos = l->pos;
525
- struct abuf ab;
526
-
527
- while((plen+pos) >= l->cols) {
528
- buf++;
529
- len--;
530
- pos--;
531
- }
532
- while (plen+len > l->cols) {
533
- len--;
534
- }
535
-
536
- abInit(&ab);
537
- /* Cursor to left edge */
538
- snprintf(seq,64,"\r");
539
- abAppend(&ab,seq,strlen(seq));
540
- /* Write the prompt and the current buffer content */
541
- abAppend(&ab,l->prompt,strlen(l->prompt));
542
- if (maskmode == 1) {
543
- while (len--) abAppend(&ab,"*",1);
544
- } else {
545
- abAppend(&ab,buf,len);
546
- }
547
- /* Show hits if any. */
548
- refreshShowHints(&ab,l,plen);
549
- /* Erase to right */
550
- snprintf(seq,64,"\x1b[0K");
551
- abAppend(&ab,seq,strlen(seq));
552
- /* Move cursor to original position. */
553
- snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
554
- abAppend(&ab,seq,strlen(seq));
555
- if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
556
- abFree(&ab);
557
-}
558
-
559
-/* Multi line low level line refresh.
560
- *
561
- * Rewrite the currently edited line accordingly to the buffer content,
562
- * cursor position, and number of columns of the terminal. */
563
-static void refreshMultiLine(struct linenoiseState *l) {
564
- char seq[64];
565
- int plen = strlen(l->prompt);
566
- int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
567
- int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
568
- int rpos2; /* rpos after refresh. */
569
- int col; /* colum position, zero-based. */
570
- int old_rows = l->maxrows;
571
- int fd = l->ofd, j;
572
- struct abuf ab;
573
-
574
- /* Update maxrows if needed. */
575
- if (rows > (int)l->maxrows) l->maxrows = rows;
576
-
577
- /* First step: clear all the lines used before. To do so start by
578
- * going to the last row. */
579
- abInit(&ab);
580
- if (old_rows-rpos > 0) {
581
- lndebug("go down %d", old_rows-rpos);
582
- snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
583
- abAppend(&ab,seq,strlen(seq));
584
- }
585
-
586
- /* Now for every row clear it, go up. */
587
- for (j = 0; j < old_rows-1; j++) {
588
- lndebug("clear+up");
589
- snprintf(seq,64,"\r\x1b[0K\x1b[1A");
590
- abAppend(&ab,seq,strlen(seq));
591
- }
592
-
593
- /* Clean the top line. */
594
- lndebug("clear");
595
- snprintf(seq,64,"\r\x1b[0K");
596
- abAppend(&ab,seq,strlen(seq));
597
-
598
- /* Write the prompt and the current buffer content */
599
- abAppend(&ab,l->prompt,strlen(l->prompt));
600
- if (maskmode == 1) {
601
- unsigned int i;
602
- for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
603
- } else {
604
- abAppend(&ab,l->buf,l->len);
605
- }
606
-
607
- /* Show hits if any. */
608
- refreshShowHints(&ab,l,plen);
609
-
610
- /* If we are at the very end of the screen with our prompt, we need to
611
- * emit a newline and move the prompt to the first column. */
612
- if (l->pos &&
613
- l->pos == l->len &&
614
- (l->pos+plen) % l->cols == 0)
615
- {
616
- lndebug("<newline>");
617
- abAppend(&ab,"\n",1);
618
- snprintf(seq,64,"\r");
619
- abAppend(&ab,seq,strlen(seq));
620
- rows++;
621
- if (rows > (int)l->maxrows) l->maxrows = rows;
622
- }
623
-
624
- /* Move cursor to right position. */
625
- rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */
626
- lndebug("rpos2 %d", rpos2);
627
-
628
- /* Go up till we reach the expected positon. */
629
- if (rows-rpos2 > 0) {
630
- lndebug("go-up %d", rows-rpos2);
631
- snprintf(seq,64,"\x1b[%dA", rows-rpos2);
632
- abAppend(&ab,seq,strlen(seq));
633
- }
634
-
635
- /* Set column. */
636
- col = (plen+(int)l->pos) % (int)l->cols;
637
- lndebug("set col %d", 1+col);
638
- if (col)
639
- snprintf(seq,64,"\r\x1b[%dC", col);
640
- else
641
- snprintf(seq,64,"\r");
642
- abAppend(&ab,seq,strlen(seq));
643
-
644
- lndebug("\n");
645
- l->oldpos = l->pos;
646
-
647
- if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
648
- abFree(&ab);
649
-}
650
-
651
-/* Calls the two low level functions refreshSingleLine() or
652
- * refreshMultiLine() according to the selected mode. */
653
-static void refreshLine(struct linenoiseState *l) {
654
- if (mlmode)
655
- refreshMultiLine(l);
656
- else
657
- refreshSingleLine(l);
658
-}
659
-
660
-/* Insert the character 'c' at cursor current position.
661
- *
662
- * On error writing to the terminal -1 is returned, otherwise 0. */
663
-int linenoiseEditInsert(struct linenoiseState *l, char c) {
664
- if (l->len < l->buflen) {
665
- if (l->len == l->pos) {
666
- l->buf[l->pos] = c;
667
- l->pos++;
668
- l->len++;
669
- l->buf[l->len] = '\0';
670
- if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
671
- /* Avoid a full update of the line in the
672
- * trivial case. */
673
- char d = (maskmode==1) ? '*' : c;
674
- if (write(l->ofd,&d,1) == -1) return -1;
675
- } else {
676
- refreshLine(l);
677
- }
678
- } else {
679
- memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);
680
- l->buf[l->pos] = c;
681
- l->len++;
682
- l->pos++;
683
- l->buf[l->len] = '\0';
684
- refreshLine(l);
685
- }
1686
+ rc = 1;
1687
+ if (display) {
1688
+ const char *pt;
1689
+ if (bold == 1 && color == -1) color = 37;
1690
+ if (bold || color > 0) {
1691
+ int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
1692
+ setOutputHighlight(current, props, 3);
1693
+ }
1694
+ DRL("<hint bold=%d,color=%d>", bold, color);
1695
+ pt = hint;
1696
+ while (*pt) {
1697
+ int ch;
1698
+ int n = utf8_tounicode(pt, &ch);
1699
+ int width = char_display_width(ch);
1700
+
1701
+ if (width >= availcols) {
1702
+ DRL("<hinteol>");
1703
+ break;
1704
+ }
1705
+ DRL_CHAR(ch);
1706
+
1707
+ availcols -= width;
1708
+ outputChars(current, pt, n);
1709
+ pt += n;
1710
+ }
1711
+ if (bold || color > 0) {
1712
+ clearOutputHighlight(current);
1713
+ }
1714
+ /* Call the function to free the hint returned. */
1715
+ if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
1716
+ }
1717
+ }
1718
+ }
1719
+ return rc;
1720
+}
1721
+
1722
+#ifdef USE_TERMIOS
1723
+static void refreshStart(struct current *current)
1724
+{
1725
+ /* We accumulate all output here */
1726
+ assert(current->output == NULL);
1727
+ current->output = sb_alloc();
1728
+}
1729
+
1730
+static void refreshEnd(struct current *current)
1731
+{
1732
+ /* Output everything at once */
1733
+ IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
1734
+ sb_free(current->output);
1735
+ current->output = NULL;
1736
+}
1737
+
1738
+static void refreshStartChars(struct current *current)
1739
+{
1740
+ (void)current;
1741
+}
1742
+
1743
+static void refreshNewline(struct current *current)
1744
+{
1745
+ DRL("<nl>");
1746
+ outputChars(current, "\n", 1);
1747
+}
1748
+
1749
+static void refreshEndChars(struct current *current)
1750
+{
1751
+ (void)current;
1752
+}
1753
+#endif
1754
+
1755
+static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
1756
+{
1757
+ int i;
1758
+ const char *pt;
1759
+ int displaycol;
1760
+ int displayrow;
1761
+ int visible;
1762
+ int currentpos;
1763
+ int notecursor;
1764
+ int cursorcol = 0;
1765
+ int cursorrow = 0;
1766
+ int hint;
1767
+ struct esc_parser parser;
1768
+
1769
+#ifdef DEBUG_REFRESHLINE
1770
+ dfh = fopen("linenoise.debuglog", "a");
1771
+#endif
1772
+
1773
+ /* Should intercept SIGWINCH. For now, just get the size every time */
1774
+ getWindowSize(current);
1775
+
1776
+ refreshStart(current);
1777
+
1778
+ DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
1779
+
1780
+ /* Here is the plan:
1781
+ * (a) move the the bottom row, going down the appropriate number of lines
1782
+ * (b) move to beginning of line and erase the current line
1783
+ * (c) go up one line and do the same, until we have erased up to the first row
1784
+ * (d) output the prompt, counting cols and rows, taking into account escape sequences
1785
+ * (e) output the buffer, counting cols and rows
1786
+ * (e') when we hit the current pos, save the cursor position
1787
+ * (f) move the cursor to the saved cursor position
1788
+ * (g) save the current cursor row and number of rows
1789
+ */
1790
+
1791
+ /* (a) - The cursor is currently at row rpos */
1792
+ cursorDown(current, current->nrows - current->rpos - 1);
1793
+ DRL("<cud=%d>", current->nrows - current->rpos - 1);
1794
+
1795
+ /* (b), (c) - Erase lines upwards until we get to the first row */
1796
+ for (i = 0; i < current->nrows; i++) {
1797
+ if (i) {
1798
+ DRL("<cup>");
1799
+ cursorUp(current, 1);
1800
+ }
1801
+ DRL("<clearline>");
1802
+ cursorToLeft(current);
1803
+ eraseEol(current);
1804
+ }
1805
+ DRL("\n");
1806
+
1807
+ /* (d) First output the prompt. control sequences don't take up display space */
1808
+ pt = prompt;
1809
+ displaycol = 0; /* current display column */
1810
+ displayrow = 0; /* current display row */
1811
+ visible = 1;
1812
+
1813
+ refreshStartChars(current);
1814
+
1815
+ while (*pt) {
1816
+ int width;
1817
+ int ch;
1818
+ int n = utf8_tounicode(pt, &ch);
1819
+
1820
+ if (visible && ch == CHAR_ESCAPE) {
1821
+ /* The start of an escape sequence, so not visible */
1822
+ visible = 0;
1823
+ initParseEscapeSeq(&parser, 'm');
1824
+ DRL("<esc-seq-start>");
1825
+ }
1826
+
1827
+ if (ch == '\n' || ch == '\r') {
1828
+ /* treat both CR and NL the same and force wrap */
1829
+ refreshNewline(current);
1830
+ displaycol = 0;
1831
+ displayrow++;
1832
+ }
1833
+ else {
1834
+ width = visible * utf8_width(ch);
1835
+
1836
+ displaycol += width;
1837
+ if (displaycol >= current->cols) {
1838
+ /* need to wrap to the next line because of newline or if it doesn't fit
1839
+ * XXX this is a problem in single line mode
1840
+ */
1841
+ refreshNewline(current);
1842
+ displaycol = width;
1843
+ displayrow++;
1844
+ }
1845
+
1846
+ DRL_CHAR(ch);
1847
+#ifdef USE_WINCONSOLE
1848
+ if (visible) {
1849
+ outputChars(current, pt, n);
1850
+ }
1851
+#else
1852
+ outputChars(current, pt, n);
1853
+#endif
1854
+ }
1855
+ pt += n;
1856
+
1857
+ if (!visible) {
1858
+ switch (parseEscapeSequence(&parser, ch)) {
1859
+ case EP_END:
1860
+ visible = 1;
1861
+ setOutputHighlight(current, parser.props, parser.numprops);
1862
+ DRL("<esc-seq-end,numprops=%d>", parser.numprops);
1863
+ break;
1864
+ case EP_ERROR:
1865
+ DRL("<esc-seq-err>");
1866
+ visible = 1;
1867
+ break;
1868
+ }
1869
+ }
1870
+ }
1871
+
1872
+ /* Now we are at the first line with all lines erased */
1873
+ DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);
1874
+
1875
+
1876
+ /* (e) output the buffer, counting cols and rows */
1877
+ if (mlmode == 0) {
1878
+ /* In this mode we may need to trim chars from the start of the buffer until the
1879
+ * cursor fits in the window.
1880
+ */
1881
+ pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
1882
+ }
1883
+ else {
1884
+ pt = buf;
1885
+ }
1886
+
1887
+ currentpos = 0;
1888
+ notecursor = -1;
1889
+
1890
+ while (*pt) {
1891
+ int ch;
1892
+ int n = utf8_tounicode(pt, &ch);
1893
+ int width = char_display_width(ch);
1894
+
1895
+ if (currentpos == cursor_pos) {
1896
+ /* (e') wherever we output this character is where we want the cursor */
1897
+ notecursor = 1;
1898
+ }
1899
+
1900
+ if (displaycol + width >= current->cols) {
1901
+ if (mlmode == 0) {
1902
+ /* In single line mode stop once we print as much as we can on one line */
1903
+ DRL("<slmode>");
1904
+ break;
1905
+ }
1906
+ /* need to wrap to the next line since it doesn't fit */
1907
+ refreshNewline(current);
1908
+ displaycol = 0;
1909
+ displayrow++;
1910
+ }
1911
+
1912
+ if (notecursor == 1) {
1913
+ /* (e') Save this position as the current cursor position */
1914
+ cursorcol = displaycol;
1915
+ cursorrow = displayrow;
1916
+ notecursor = 0;
1917
+ DRL("<cursor>");
1918
+ }
1919
+
1920
+ displaycol += width;
1921
+
1922
+ if (ch < ' ') {
1923
+ outputControlChar(current, ch + '@');
1924
+ }
1925
+ else {
1926
+ outputChars(current, pt, n);
1927
+ }
1928
+ DRL_CHAR(ch);
1929
+ if (width != 1) {
1930
+ DRL("<w=%d>", width);
1931
+ }
1932
+
1933
+ pt += n;
1934
+ currentpos++;
1935
+ }
1936
+
1937
+ /* If we didn't see the cursor, it is at the current location */
1938
+ if (notecursor) {
1939
+ DRL("<cursor>");
1940
+ cursorcol = displaycol;
1941
+ cursorrow = displayrow;
1942
+ }
1943
+
1944
+ DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n", displaycol, displayrow, cursorcol, cursorrow);
1945
+
1946
+ /* (f) show hints */
1947
+ hint = refreshShowHints(current, buf, current->cols - displaycol, 1);
1948
+
1949
+ /* Remember how many many cols are available for insert optimisation */
1950
+ if (prompt == current->prompt && hint == 0) {
1951
+ current->colsright = current->cols - displaycol;
1952
+ current->colsleft = displaycol;
1953
+ }
1954
+ else {
1955
+ /* Can't optimise */
1956
+ current->colsright = 0;
1957
+ current->colsleft = 0;
1958
+ }
1959
+ DRL("\nafter hints: colsleft=%d, colsright=%d\n\n", current->colsleft, current->colsright);
1960
+
1961
+ refreshEndChars(current);
1962
+
1963
+ /* (g) move the cursor to the correct place */
1964
+ cursorUp(current, displayrow - cursorrow);
1965
+ setCursorPos(current, cursorcol);
1966
+
1967
+ /* (h) Update the number of rows if larger, but never reduce this */
1968
+ if (displayrow >= current->nrows) {
1969
+ current->nrows = displayrow + 1;
1970
+ }
1971
+ /* And remember the row that the cursor is on */
1972
+ current->rpos = cursorrow;
1973
+
1974
+ refreshEnd(current);
1975
+
1976
+#ifdef DEBUG_REFRESHLINE
1977
+ fclose(dfh);
1978
+#endif
1979
+}
1980
+
1981
+static void refreshLine(struct current *current)
1982
+{
1983
+ refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
1984
+}
1985
+
1986
+static void set_current(struct current *current, const char *str)
1987
+{
1988
+ sb_clear(current->buf);
1989
+ sb_append(current->buf, str);
1990
+ current->pos = sb_chars(current->buf);
1991
+}
1992
+
1993
+/**
1994
+ * Removes the char at 'pos'.
1995
+ *
1996
+ * Returns 1 if the line needs to be refreshed, 2 if not
1997
+ * and 0 if nothing was removed
1998
+ */
1999
+static int remove_char(struct current *current, int pos)
2000
+{
2001
+ if (pos >= 0 && pos < sb_chars(current->buf)) {
2002
+ int offset = utf8_index(sb_str(current->buf), pos);
2003
+ int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
2004
+ int rc = 1;
2005
+
2006
+ /* Now we try to optimise in the simple but very common case that:
2007
+ * - outputChars() can be used directly (not win32)
2008
+ * - we are removing the char at EOL
2009
+ * - the buffer is not empty
2010
+ * - there are columns available to the left
2011
+ * - the char being deleted is not a wide or utf-8 character
2012
+ * - no hints are being shown
2013
+ */
2014
+ if (current->output && current->pos == pos + 1 && current->pos == sb_chars(current->buf) && pos > 0) {
2015
+#ifdef USE_UTF8
2016
+ /* Could implement utf8_prev_len() but simplest just to not optimise this case */
2017
+ char last = sb_str(current->buf)[offset];
2018
+#else
2019
+ char last = 0;
2020
+#endif
2021
+ if (current->colsleft > 0 && (last & 0x80) == 0) {
2022
+ /* Have cols on the left and not a UTF-8 char or continuation */
2023
+ /* Yes, can optimise */
2024
+ current->colsleft--;
2025
+ current->colsright++;
2026
+ rc = 2;
2027
+ }
2028
+ }
2029
+
2030
+ sb_delete(current->buf, offset, nbytes);
2031
+
2032
+ if (current->pos > pos) {
2033
+ current->pos--;
2034
+ }
2035
+ if (rc == 2) {
2036
+ if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
2037
+ /* A hint needs to be shown, so can't optimise after all */
2038
+ rc = 1;
2039
+ }
2040
+ else {
2041
+ /* optimised output */
2042
+ outputChars(current, "\b \b", 3);
2043
+ }
2044
+ }
2045
+ return rc;
2046
+ return 1;
2047
+ }
2048
+ return 0;
2049
+}
2050
+
2051
+/**
2052
+ * Insert 'ch' at position 'pos'
2053
+ *
2054
+ * Returns 1 if the line needs to be refreshed, 2 if not
2055
+ * and 0 if nothing was inserted (no room)
2056
+ */
2057
+static int insert_char(struct current *current, int pos, int ch)
2058
+{
2059
+ if (pos >= 0 && pos <= sb_chars(current->buf)) {
2060
+ char buf[MAX_UTF8_LEN + 1];
2061
+ int offset = utf8_index(sb_str(current->buf), pos);
2062
+ int n = utf8_getchars(buf, ch);
2063
+ int rc = 1;
2064
+
2065
+ /* null terminate since sb_insert() requires it */
2066
+ buf[n] = 0;
2067
+
2068
+ /* Now we try to optimise in the simple but very common case that:
2069
+ * - outputChars() can be used directly (not win32)
2070
+ * - we are inserting at EOL
2071
+ * - there are enough columns available
2072
+ * - no hints are being shown
2073
+ */
2074
+ if (current->output && pos == current->pos && pos == sb_chars(current->buf)) {
2075
+ int width = char_display_width(ch);
2076
+ if (current->colsright > width) {
2077
+ /* Yes, can optimise */
2078
+ current->colsright -= width;
2079
+ current->colsleft -= width;
2080
+ rc = 2;
2081
+ }
2082
+ }
2083
+ sb_insert(current->buf, offset, buf);
2084
+ if (current->pos >= pos) {
2085
+ current->pos++;
2086
+ }
2087
+ if (rc == 2) {
2088
+ if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
2089
+ /* A hint needs to be shown, so can't optimise after all */
2090
+ rc = 1;
2091
+ }
2092
+ else {
2093
+ /* optimised output */
2094
+ outputChars(current, buf, n);
2095
+ }
2096
+ }
2097
+ return rc;
6862098
}
6872099
return 0;
6882100
}
6892101
690
-/* Move cursor on the left. */
691
-void linenoiseEditMoveLeft(struct linenoiseState *l) {
692
- if (l->pos > 0) {
693
- l->pos--;
694
- refreshLine(l);
695
- }
696
-}
697
-
698
-/* Move cursor on the right. */
699
-void linenoiseEditMoveRight(struct linenoiseState *l) {
700
- if (l->pos != l->len) {
701
- l->pos++;
702
- refreshLine(l);
703
- }
704
-}
705
-
706
-/* Move cursor to the start of the line. */
707
-void linenoiseEditMoveHome(struct linenoiseState *l) {
708
- if (l->pos != 0) {
709
- l->pos = 0;
710
- refreshLine(l);
711
- }
712
-}
713
-
714
-/* Move cursor to the end of the line. */
715
-void linenoiseEditMoveEnd(struct linenoiseState *l) {
716
- if (l->pos != l->len) {
717
- l->pos = l->len;
718
- refreshLine(l);
719
- }
720
-}
721
-
722
-/* Substitute the currently edited line with the next or previous history
723
- * entry as specified by 'dir'. */
724
-#define LINENOISE_HISTORY_NEXT 0
725
-#define LINENOISE_HISTORY_PREV 1
726
-void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {
727
- if (history_len > 1) {
728
- /* Update the current history entry before to
729
- * overwrite it with the next one. */
730
- free(history[history_len - 1 - l->history_index]);
731
- history[history_len - 1 - l->history_index] = strdup(l->buf);
732
- /* Show the new entry */
733
- l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;
734
- if (l->history_index < 0) {
735
- l->history_index = 0;
736
- return;
737
- } else if (l->history_index >= history_len) {
738
- l->history_index = history_len-1;
739
- return;
740
- }
741
- strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);
742
- l->buf[l->buflen-1] = '\0';
743
- l->len = l->pos = strlen(l->buf);
744
- refreshLine(l);
745
- }
746
-}
747
-
748
-/* Delete the character at the right of the cursor without altering the cursor
749
- * position. Basically this is what happens with the "Delete" keyboard key. */
750
-void linenoiseEditDelete(struct linenoiseState *l) {
751
- if (l->len > 0 && l->pos < l->len) {
752
- memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);
753
- l->len--;
754
- l->buf[l->len] = '\0';
755
- refreshLine(l);
756
- }
757
-}
758
-
759
-/* Backspace implementation. */
760
-void linenoiseEditBackspace(struct linenoiseState *l) {
761
- if (l->pos > 0 && l->len > 0) {
762
- memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);
763
- l->pos--;
764
- l->len--;
765
- l->buf[l->len] = '\0';
766
- refreshLine(l);
767
- }
768
-}
769
-
770
-/* Delete the previosu word, maintaining the cursor at the start of the
771
- * current word. */
772
-void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
773
- size_t old_pos = l->pos;
774
- size_t diff;
775
-
776
- while (l->pos > 0 && l->buf[l->pos-1] == ' ')
777
- l->pos--;
778
- while (l->pos > 0 && l->buf[l->pos-1] != ' ')
779
- l->pos--;
780
- diff = old_pos - l->pos;
781
- memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
782
- l->len -= diff;
783
- refreshLine(l);
784
-}
785
-
786
-/* This function is the core of the line editing capability of linenoise.
787
- * It expects 'fd' to be already in "raw mode" so that every key pressed
788
- * will be returned ASAP to read().
789
- *
790
- * The resulting string is put into 'buf' when the user type enter, or
791
- * when ctrl+d is typed.
792
- *
793
- * The function returns the length of the current buffer. */
794
-static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
795
-{
796
- struct linenoiseState l;
797
-
798
- /* Populate the linenoise state that we pass to functions implementing
799
- * specific editing functionalities. */
800
- l.ifd = stdin_fd;
801
- l.ofd = stdout_fd;
802
- l.buf = buf;
803
- l.buflen = buflen;
804
- l.prompt = prompt;
805
- l.plen = strlen(prompt);
806
- l.oldpos = l.pos = 0;
807
- l.len = 0;
808
- l.cols = getColumns(stdin_fd, stdout_fd);
809
- l.maxrows = 0;
810
- l.history_index = 0;
811
-
812
- /* Buffer starts empty. */
813
- l.buf[0] = '\0';
814
- l.buflen--; /* Make sure there is always space for the nulterm */
815
-
816
- /* The latest history entry is always our current buffer, that
817
- * initially is just an empty string. */
818
- linenoiseHistoryAdd("");
819
-
820
- if (write(l.ofd,prompt,l.plen) == -1) return -1;
821
- while(1) {
822
- char c;
823
- int nread;
824
- char seq[3];
825
-
826
- nread = read(l.ifd,&c,1);
827
- if (nread <= 0) return l.len;
828
-
829
- /* Only autocomplete when the callback is set. It returns < 0 when
830
- * there was an error reading from fd. Otherwise it will return the
831
- * character that should be handled next. */
832
- if (c == 9 && completionCallback != NULL) {
833
- c = completeLine(&l);
834
- /* Return on errors */
835
- if (c < 0) return l.len;
836
- /* Read next character when 0 */
837
- if (c == 0) continue;
838
- }
839
-
840
- switch(c) {
841
- case ENTER: /* enter */
842
- history_len--;
843
- free(history[history_len]);
844
- if (mlmode) linenoiseEditMoveEnd(&l);
845
- if (hintsCallback) {
846
- /* Force a refresh without hints to leave the previous
847
- * line as the user typed it after a newline. */
848
- linenoiseHintsCallback *hc = hintsCallback;
849
- hintsCallback = NULL;
850
- refreshLine(&l);
851
- hintsCallback = hc;
852
- }
853
- return (int)l.len;
854
- case CTRL_C: /* ctrl-c */
855
- errno = EAGAIN;
856
- return -1;
857
- case BACKSPACE: /* backspace */
858
- case 8: /* ctrl-h */
859
- linenoiseEditBackspace(&l);
860
- break;
861
- case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the
862
- line is empty, act as end-of-file. */
863
- if (l.len > 0) {
864
- linenoiseEditDelete(&l);
865
- } else {
866
- history_len--;
867
- free(history[history_len]);
868
- return -1;
869
- }
870
- break;
871
- case CTRL_T: /* ctrl-t, swaps current character with previous. */
872
- if (l.pos > 0 && l.pos < l.len) {
873
- int aux = buf[l.pos-1];
874
- buf[l.pos-1] = buf[l.pos];
875
- buf[l.pos] = aux;
876
- if (l.pos != l.len-1) l.pos++;
877
- refreshLine(&l);
878
- }
879
- break;
880
- case CTRL_B: /* ctrl-b */
881
- linenoiseEditMoveLeft(&l);
882
- break;
883
- case CTRL_F: /* ctrl-f */
884
- linenoiseEditMoveRight(&l);
885
- break;
886
- case CTRL_P: /* ctrl-p */
887
- linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
888
- break;
889
- case CTRL_N: /* ctrl-n */
890
- linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
891
- break;
892
- case ESC: /* escape sequence */
893
- /* Read the next two bytes representing the escape sequence.
894
- * Use two calls to handle slow terminals returning the two
895
- * chars at different times. */
896
- if (read(l.ifd,seq,1) == -1) break;
897
- if (read(l.ifd,seq+1,1) == -1) break;
898
-
899
- /* ESC [ sequences. */
900
- if (seq[0] == '[') {
901
- if (seq[1] >= '0' && seq[1] <= '9') {
902
- /* Extended escape, read additional byte. */
903
- if (read(l.ifd,seq+2,1) == -1) break;
904
- if (seq[2] == '~') {
905
- switch(seq[1]) {
906
- case '3': /* Delete key. */
907
- linenoiseEditDelete(&l);
908
- break;
909
- }
910
- }
911
- } else {
912
- switch(seq[1]) {
913
- case 'A': /* Up */
914
- linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
915
- break;
916
- case 'B': /* Down */
917
- linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
918
- break;
919
- case 'C': /* Right */
920
- linenoiseEditMoveRight(&l);
921
- break;
922
- case 'D': /* Left */
923
- linenoiseEditMoveLeft(&l);
924
- break;
925
- case 'H': /* Home */
926
- linenoiseEditMoveHome(&l);
927
- break;
928
- case 'F': /* End*/
929
- linenoiseEditMoveEnd(&l);
930
- break;
931
- }
932
- }
933
- }
934
-
935
- /* ESC O sequences. */
936
- else if (seq[0] == 'O') {
937
- switch(seq[1]) {
938
- case 'H': /* Home */
939
- linenoiseEditMoveHome(&l);
940
- break;
941
- case 'F': /* End*/
942
- linenoiseEditMoveEnd(&l);
943
- break;
944
- }
945
- }
946
- break;
947
- default:
948
- if (linenoiseEditInsert(&l,c)) return -1;
949
- break;
950
- case CTRL_U: /* Ctrl+u, delete the whole line. */
951
- buf[0] = '\0';
952
- l.pos = l.len = 0;
953
- refreshLine(&l);
954
- break;
955
- case CTRL_K: /* Ctrl+k, delete from current to end of line. */
956
- buf[l.pos] = '\0';
957
- l.len = l.pos;
958
- refreshLine(&l);
959
- break;
960
- case CTRL_A: /* Ctrl+a, go to the start of the line */
961
- linenoiseEditMoveHome(&l);
962
- break;
963
- case CTRL_E: /* ctrl+e, go to the end of the line */
964
- linenoiseEditMoveEnd(&l);
965
- break;
966
- case CTRL_L: /* ctrl+l, clear screen */
967
- linenoiseClearScreen();
968
- refreshLine(&l);
969
- break;
970
- case CTRL_W: /* ctrl+w, delete previous word */
971
- linenoiseEditDeletePrevWord(&l);
972
- break;
973
- }
974
- }
975
- return l.len;
976
-}
977
-
978
-/* This special mode is used by linenoise in order to print scan codes
979
- * on screen for debugging / development purposes. It is implemented
980
- * by the linenoise_example program using the --keycodes option. */
981
-void linenoisePrintKeyCodes(void) {
982
- char quit[4];
983
-
984
- printf("Linenoise key codes debugging mode.\n"
985
- "Press keys to see scan codes. Type 'quit' at any time to exit.\n");
986
- if (enableRawMode(STDIN_FILENO) == -1) return;
987
- memset(quit,' ',4);
988
- while(1) {
989
- char c;
990
- int nread;
991
-
992
- nread = read(STDIN_FILENO,&c,1);
993
- if (nread <= 0) continue;
994
- memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */
995
- quit[sizeof(quit)-1] = c; /* Insert current char on the right. */
996
- if (memcmp(quit,"quit",sizeof(quit)) == 0) break;
997
-
998
- printf("'%c' %02x (%d) (type quit to exit)\n",
999
- isprint(c) ? c : '?', (int)c, (int)c);
1000
- printf("\r"); /* Go left edge manually, we are in raw mode. */
1001
- fflush(stdout);
1002
- }
1003
- disableRawMode(STDIN_FILENO);
1004
-}
1005
-
1006
-/* This function calls the line editing function linenoiseEdit() using
1007
- * the STDIN file descriptor set in raw mode. */
1008
-static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
1009
- int count;
1010
-
1011
- if (buflen == 0) {
1012
- errno = EINVAL;
1013
- return -1;
1014
- }
1015
-
1016
- if (enableRawMode(STDIN_FILENO) == -1) return -1;
1017
- count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
1018
- disableRawMode(STDIN_FILENO);
1019
- printf("\n");
1020
- return count;
1021
-}
1022
-
1023
-/* This function is called when linenoise() is called with the standard
1024
- * input file descriptor not attached to a TTY. So for example when the
1025
- * program using linenoise is called in pipe or with a file redirected
1026
- * to its standard input. In this case, we want to be able to return the
1027
- * line regardless of its length (by default we are limited to 4k). */
1028
-static char *linenoiseNoTTY(void) {
1029
- char *line = NULL;
1030
- size_t len = 0, maxlen = 0;
1031
-
1032
- while(1) {
1033
- int c;
1034
- if (len == maxlen) {
1035
- char *oldval = line;
1036
- if (maxlen == 0) maxlen = 16;
1037
- maxlen *= 2;
1038
- line = realloc(line,maxlen);
1039
- if (line == NULL) {
1040
- if (oldval) free(oldval);
1041
- return NULL;
1042
- }
1043
- }
1044
- c = fgetc(stdin);
1045
- if (c == EOF || c == '\n') {
1046
- if (c == EOF && len == 0) {
1047
- free(line);
1048
- return NULL;
1049
- } else {
1050
- line[len] = '\0';
1051
- return line;
1052
- }
1053
- } else {
1054
- line[len] = c;
1055
- len++;
1056
- }
1057
- }
1058
-}
1059
-
1060
-/* The high level function that is the main API of the linenoise library.
1061
- * This function checks if the terminal has basic capabilities, just checking
1062
- * for a blacklist of stupid terminals, and later either calls the line
1063
- * editing function or uses dummy fgets() so that you will be able to type
1064
- * something even in the most desperate of the conditions. */
1065
-char *linenoise(const char *prompt) {
1066
- char buf[LINENOISE_MAX_LINE];
1067
- int count;
1068
-
1069
- if (!isatty(STDIN_FILENO)) {
1070
- /* Not a tty: read from file / pipe. In this mode we don't want any
1071
- * limit to the line size, so we call a function to handle that. */
1072
- return linenoiseNoTTY();
1073
- } else if (isUnsupportedTerm()) {
1074
- size_t len;
1075
-
1076
- printf("%s",prompt);
1077
- fflush(stdout);
1078
- if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
1079
- len = strlen(buf);
1080
- while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
1081
- len--;
1082
- buf[len] = '\0';
1083
- }
1084
- return strdup(buf);
1085
- } else {
1086
- count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
1087
- if (count == -1) return NULL;
1088
- return strdup(buf);
1089
- }
1090
-}
1091
-
1092
-/* This is just a wrapper the user may want to call in order to make sure
1093
- * the linenoise returned buffer is freed with the same allocator it was
1094
- * created with. Useful when the main program is using an alternative
1095
- * allocator. */
1096
-void linenoiseFree(void *ptr) {
1097
- free(ptr);
1098
-}
1099
-
1100
-/* ================================ History ================================= */
1101
-
1102
-/* Free the history, but does not reset it. Only used when we have to
1103
- * exit() to avoid memory leaks are reported by valgrind & co. */
1104
-static void freeHistory(void) {
1105
- if (history) {
1106
- int j;
1107
-
1108
- for (j = 0; j < history_len; j++)
1109
- free(history[j]);
1110
- free(history);
1111
- }
1112
-}
1113
-
1114
-/* At exit we'll try to fix the terminal to the initial conditions. */
1115
-static void linenoiseAtExit(void) {
1116
- disableRawMode(STDIN_FILENO);
1117
- freeHistory();
1118
-}
1119
-
1120
-/* This is the API call to add a new entry in the linenoise history.
1121
- * It uses a fixed array of char pointers that are shifted (memmoved)
1122
- * when the history max length is reached in order to remove the older
1123
- * entry and make room for the new one, so it is not exactly suitable for huge
1124
- * histories, but will work well for a few hundred of entries.
1125
- *
1126
- * Using a circular buffer is smarter, but a bit more complex to handle. */
1127
-int linenoiseHistoryAdd(const char *line) {
1128
- char *linecopy;
1129
-
1130
- if (history_max_len == 0) return 0;
1131
-
1132
- /* Initialization on first call. */
1133
- if (history == NULL) {
1134
- history = malloc(sizeof(char*)*history_max_len);
1135
- if (history == NULL) return 0;
1136
- memset(history,0,(sizeof(char*)*history_max_len));
1137
- }
1138
-
1139
- /* Don't add duplicated lines. */
1140
- if (history_len && !strcmp(history[history_len-1], line)) return 0;
1141
-
1142
- /* Add an heap allocated copy of the line in the history.
1143
- * If we reached the max length, remove the older line. */
1144
- linecopy = strdup(line);
1145
- if (!linecopy) return 0;
2102
+/**
2103
+ * Captures up to 'n' characters starting at 'pos' for the cut buffer.
2104
+ *
2105
+ * This replaces any existing characters in the cut buffer.
2106
+ */
2107
+static void capture_chars(struct current *current, int pos, int nchars)
2108
+{
2109
+ if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
2110
+ int offset = utf8_index(sb_str(current->buf), pos);
2111
+ int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
2112
+
2113
+ if (nbytes > 0) {
2114
+ if (current->capture) {
2115
+ sb_clear(current->capture);
2116
+ }
2117
+ else {
2118
+ current->capture = sb_alloc();
2119
+ }
2120
+ sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
2121
+ }
2122
+ }
2123
+}
2124
+
2125
+/**
2126
+ * Removes up to 'n' characters at cursor position 'pos'.
2127
+ *
2128
+ * Returns 0 if no chars were removed or non-zero otherwise.
2129
+ */
2130
+static int remove_chars(struct current *current, int pos, int n)
2131
+{
2132
+ int removed = 0;
2133
+
2134
+ /* First save any chars which will be removed */
2135
+ capture_chars(current, pos, n);
2136
+
2137
+ while (n-- && remove_char(current, pos)) {
2138
+ removed++;
2139
+ }
2140
+ return removed;
2141
+}
2142
+/**
2143
+ * Inserts the characters (string) 'chars' at the cursor position 'pos'.
2144
+ *
2145
+ * Returns 0 if no chars were inserted or non-zero otherwise.
2146
+ */
2147
+static int insert_chars(struct current *current, int pos, const char *chars)
2148
+{
2149
+ int inserted = 0;
2150
+
2151
+ while (*chars) {
2152
+ int ch;
2153
+ int n = utf8_tounicode(chars, &ch);
2154
+ if (insert_char(current, pos, ch) == 0) {
2155
+ break;
2156
+ }
2157
+ inserted++;
2158
+ pos++;
2159
+ chars += n;
2160
+ }
2161
+ return inserted;
2162
+}
2163
+
2164
+static int skip_space_nonspace(struct current *current, int dir, int check_is_space)
2165
+{
2166
+ int moved = 0;
2167
+ int checkoffset = (dir < 0) ? -1 : 0;
2168
+ int limit = (dir < 0) ? 0 : sb_chars(current->buf);
2169
+ while (current->pos != limit && (get_char(current, current->pos + checkoffset) == ' ') == check_is_space) {
2170
+ current->pos += dir;
2171
+ moved++;
2172
+ }
2173
+ return moved;
2174
+}
2175
+
2176
+static int skip_space(struct current *current, int dir)
2177
+{
2178
+ return skip_space_nonspace(current, dir, 1);
2179
+}
2180
+
2181
+static int skip_nonspace(struct current *current, int dir)
2182
+{
2183
+ return skip_space_nonspace(current, dir, 0);
2184
+}
2185
+
2186
+static void set_history_index(struct current *current, int new_index)
2187
+{
2188
+ if (history_len > 1) {
2189
+ /* Update the current history entry before to
2190
+ * overwrite it with the next one. */
2191
+ free(history[history_len - 1 - history_index]);
2192
+ history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
2193
+ /* Show the new entry */
2194
+ history_index = new_index;
2195
+ if (history_index < 0) {
2196
+ history_index = 0;
2197
+ } else if (history_index >= history_len) {
2198
+ history_index = history_len - 1;
2199
+ } else {
2200
+ set_current(current, history[history_len - 1 - history_index]);
2201
+ refreshLine(current);
2202
+ }
2203
+ }
2204
+}
2205
+
2206
+/**
2207
+ * Returns the keycode to process, or 0 if none.
2208
+ */
2209
+static int reverseIncrementalSearch(struct current *current)
2210
+{
2211
+ /* Display the reverse-i-search prompt and process chars */
2212
+ char rbuf[50];
2213
+ char rprompt[80];
2214
+ int rchars = 0;
2215
+ int rlen = 0;
2216
+ int searchpos = history_len - 1;
2217
+ int c;
2218
+
2219
+ rbuf[0] = 0;
2220
+ while (1) {
2221
+ int n = 0;
2222
+ const char *p = NULL;
2223
+ int skipsame = 0;
2224
+ int searchdir = -1;
2225
+
2226
+ snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
2227
+ refreshLineAlt(current, rprompt, sb_str(current->buf), current->pos);
2228
+ c = fd_read(current);
2229
+ if (c == ctrl('H') || c == CHAR_DELETE) {
2230
+ if (rchars) {
2231
+ int p_ind = utf8_index(rbuf, --rchars);
2232
+ rbuf[p_ind] = 0;
2233
+ rlen = strlen(rbuf);
2234
+ }
2235
+ continue;
2236
+ }
2237
+#ifdef USE_TERMIOS
2238
+ if (c == CHAR_ESCAPE) {
2239
+ c = check_special(current->fd);
2240
+ }
2241
+#endif
2242
+ if (c == ctrl('R')) {
2243
+ /* Search for the previous (earlier) match */
2244
+ if (searchpos > 0) {
2245
+ searchpos--;
2246
+ }
2247
+ skipsame = 1;
2248
+ }
2249
+ else if (c == ctrl('S')) {
2250
+ /* Search for the next (later) match */
2251
+ if (searchpos < history_len) {
2252
+ searchpos++;
2253
+ }
2254
+ searchdir = 1;
2255
+ skipsame = 1;
2256
+ }
2257
+ else if (c == ctrl('P') || c == SPECIAL_UP) {
2258
+ /* Exit Ctrl-R mode and go to the previous history line from the current search pos */
2259
+ set_history_index(current, history_len - searchpos);
2260
+ c = 0;
2261
+ break;
2262
+ }
2263
+ else if (c == ctrl('N') || c == SPECIAL_DOWN) {
2264
+ /* Exit Ctrl-R mode and go to the next history line from the current search pos */
2265
+ set_history_index(current, history_len - searchpos - 2);
2266
+ c = 0;
2267
+ break;
2268
+ }
2269
+ else if (c >= ' ' && c <= '~') {
2270
+ /* >= here to allow for null terminator */
2271
+ if (rlen >= (int)sizeof(rbuf) - MAX_UTF8_LEN) {
2272
+ continue;
2273
+ }
2274
+
2275
+ n = utf8_getchars(rbuf + rlen, c);
2276
+ rlen += n;
2277
+ rchars++;
2278
+ rbuf[rlen] = 0;
2279
+
2280
+ /* Adding a new char resets the search location */
2281
+ searchpos = history_len - 1;
2282
+ }
2283
+ else {
2284
+ /* Exit from incremental search mode */
2285
+ break;
2286
+ }
2287
+
2288
+ /* Now search through the history for a match */
2289
+ for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
2290
+ p = strstr(history[searchpos], rbuf);
2291
+ if (p) {
2292
+ /* Found a match */
2293
+ if (skipsame && strcmp(history[searchpos], sb_str(current->buf)) == 0) {
2294
+ /* But it is identical, so skip it */
2295
+ continue;
2296
+ }
2297
+ /* Copy the matching line and set the cursor position */
2298
+ history_index = history_len - 1 - searchpos;
2299
+ set_current(current,history[searchpos]);
2300
+ current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
2301
+ break;
2302
+ }
2303
+ }
2304
+ if (!p && n) {
2305
+ /* No match, so don't add it */
2306
+ rchars--;
2307
+ rlen -= n;
2308
+ rbuf[rlen] = 0;
2309
+ }
2310
+ }
2311
+ if (c == ctrl('G') || c == ctrl('C')) {
2312
+ /* ctrl-g terminates the search with no effect */
2313
+ set_current(current, "");
2314
+ history_index = 0;
2315
+ c = 0;
2316
+ }
2317
+ else if (c == ctrl('J')) {
2318
+ /* ctrl-j terminates the search leaving the buffer in place */
2319
+ history_index = 0;
2320
+ c = 0;
2321
+ }
2322
+ /* Go process the char normally */
2323
+ refreshLine(current);
2324
+ return c;
2325
+}
2326
+
2327
+static int linenoiseEdit(struct current *current) {
2328
+ history_index = 0;
2329
+
2330
+ refreshLine(current);
2331
+
2332
+ while(1) {
2333
+ int c = fd_read(current);
2334
+
2335
+#ifndef NO_COMPLETION
2336
+ /* Only autocomplete when the callback is set. It returns < 0 when
2337
+ * there was an error reading from fd. Otherwise it will return the
2338
+ * character that should be handled next. */
2339
+ if (c == '\t' && current->pos == sb_chars(current->buf) && completionCallback != NULL) {
2340
+ c = completeLine(current);
2341
+ }
2342
+#endif
2343
+ if (c == ctrl('R')) {
2344
+ /* reverse incremental search will provide an alternative keycode or 0 for none */
2345
+ c = reverseIncrementalSearch(current);
2346
+ /* go on to process the returned char normally */
2347
+ }
2348
+
2349
+#ifdef USE_TERMIOS
2350
+ if (c == CHAR_ESCAPE) { /* escape sequence */
2351
+ c = check_special(current->fd);
2352
+ }
2353
+#endif
2354
+ if (c == -1) {
2355
+ /* Return on errors */
2356
+ return sb_len(current->buf);
2357
+ }
2358
+
2359
+ switch(c) {
2360
+ case SPECIAL_NONE:
2361
+ break;
2362
+ case '\r': /* enter/CR */
2363
+ case '\n': /* LF */
2364
+ history_len--;
2365
+ free(history[history_len]);
2366
+ current->pos = sb_chars(current->buf);
2367
+ if (mlmode || hintsCallback) {
2368
+ showhints = 0;
2369
+ refreshLine(current);
2370
+ showhints = 1;
2371
+ }
2372
+ return sb_len(current->buf);
2373
+ case ctrl('C'): /* ctrl-c */
2374
+ errno = EAGAIN;
2375
+ return -1;
2376
+ case ctrl('Z'): /* ctrl-z */
2377
+#ifdef SIGTSTP
2378
+ /* send ourselves SIGSUSP */
2379
+ disableRawMode(current);
2380
+ raise(SIGTSTP);
2381
+ /* and resume */
2382
+ enableRawMode(current);
2383
+ refreshLine(current);
2384
+#endif
2385
+ continue;
2386
+ case CHAR_DELETE: /* backspace */
2387
+ case ctrl('H'):
2388
+ if (remove_char(current, current->pos - 1) == 1) {
2389
+ refreshLine(current);
2390
+ }
2391
+ break;
2392
+ case ctrl('D'): /* ctrl-d */
2393
+ if (sb_len(current->buf) == 0) {
2394
+ /* Empty line, so EOF */
2395
+ history_len--;
2396
+ free(history[history_len]);
2397
+ return -1;
2398
+ }
2399
+ /* Otherwise fall through to delete char to right of cursor */
2400
+ /* fall-thru */
2401
+ case SPECIAL_DELETE:
2402
+ if (remove_char(current, current->pos) == 1) {
2403
+ refreshLine(current);
2404
+ }
2405
+ break;
2406
+ case SPECIAL_INSERT:
2407
+ /* Ignore. Expansion Hook.
2408
+ * Future possibility: Toggle Insert/Overwrite Modes
2409
+ */
2410
+ break;
2411
+ case meta('b'): /* meta-b, move word left */
2412
+ if (skip_nonspace(current, -1)) {
2413
+ refreshLine(current);
2414
+ }
2415
+ else if (skip_space(current, -1)) {
2416
+ skip_nonspace(current, -1);
2417
+ refreshLine(current);
2418
+ }
2419
+ break;
2420
+ case meta('f'): /* meta-f, move word right */
2421
+ if (skip_space(current, 1)) {
2422
+ refreshLine(current);
2423
+ }
2424
+ else if (skip_nonspace(current, 1)) {
2425
+ skip_space(current, 1);
2426
+ refreshLine(current);
2427
+ }
2428
+ break;
2429
+ case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */
2430
+ /* eat any spaces on the left */
2431
+ {
2432
+ int pos = current->pos;
2433
+ while (pos > 0 && get_char(current, pos - 1) == ' ') {
2434
+ pos--;
2435
+ }
2436
+
2437
+ /* now eat any non-spaces on the left */
2438
+ while (pos > 0 && get_char(current, pos - 1) != ' ') {
2439
+ pos--;
2440
+ }
2441
+
2442
+ if (remove_chars(current, pos, current->pos - pos)) {
2443
+ refreshLine(current);
2444
+ }
2445
+ }
2446
+ break;
2447
+ case ctrl('T'): /* ctrl-t */
2448
+ if (current->pos > 0 && current->pos <= sb_chars(current->buf)) {
2449
+ /* If cursor is at end, transpose the previous two chars */
2450
+ int fixer = (current->pos == sb_chars(current->buf));
2451
+ c = get_char(current, current->pos - fixer);
2452
+ remove_char(current, current->pos - fixer);
2453
+ insert_char(current, current->pos - 1, c);
2454
+ refreshLine(current);
2455
+ }
2456
+ break;
2457
+ case ctrl('V'): /* ctrl-v */
2458
+ /* Insert the ^V first */
2459
+ if (insert_char(current, current->pos, c)) {
2460
+ refreshLine(current);
2461
+ /* Now wait for the next char. Can insert anything except \0 */
2462
+ c = fd_read(current);
2463
+
2464
+ /* Remove the ^V first */
2465
+ remove_char(current, current->pos - 1);
2466
+ if (c > 0) {
2467
+ /* Insert the actual char, can't be error or null */
2468
+ insert_char(current, current->pos, c);
2469
+ }
2470
+ refreshLine(current);
2471
+ }
2472
+ break;
2473
+ case ctrl('B'):
2474
+ case SPECIAL_LEFT:
2475
+ if (current->pos > 0) {
2476
+ current->pos--;
2477
+ refreshLine(current);
2478
+ }
2479
+ break;
2480
+ case ctrl('F'):
2481
+ case SPECIAL_RIGHT:
2482
+ if (current->pos < sb_chars(current->buf)) {
2483
+ current->pos++;
2484
+ refreshLine(current);
2485
+ }
2486
+ break;
2487
+ case SPECIAL_PAGE_UP: /* move to start of history */
2488
+ set_history_index(current, history_len - 1);
2489
+ break;
2490
+ case SPECIAL_PAGE_DOWN: /* move to 0 == end of history, i.e. current */
2491
+ set_history_index(current, 0);
2492
+ break;
2493
+ case ctrl('P'):
2494
+ case SPECIAL_UP:
2495
+ set_history_index(current, history_index + 1);
2496
+ break;
2497
+ case ctrl('N'):
2498
+ case SPECIAL_DOWN:
2499
+ set_history_index(current, history_index - 1);
2500
+ break;
2501
+ case ctrl('A'): /* Ctrl+a, go to the start of the line */
2502
+ case SPECIAL_HOME:
2503
+ current->pos = 0;
2504
+ refreshLine(current);
2505
+ break;
2506
+ case ctrl('E'): /* ctrl+e, go to the end of the line */
2507
+ case SPECIAL_END:
2508
+ current->pos = sb_chars(current->buf);
2509
+ refreshLine(current);
2510
+ break;
2511
+ case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
2512
+ if (remove_chars(current, 0, current->pos)) {
2513
+ refreshLine(current);
2514
+ }
2515
+ break;
2516
+ case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
2517
+ if (remove_chars(current, current->pos, sb_chars(current->buf) - current->pos)) {
2518
+ refreshLine(current);
2519
+ }
2520
+ break;
2521
+ case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
2522
+ if (current->capture && insert_chars(current, current->pos, sb_str(current->capture))) {
2523
+ refreshLine(current);
2524
+ }
2525
+ break;
2526
+ case ctrl('L'): /* Ctrl+L, clear screen */
2527
+ linenoiseClearScreen();
2528
+ /* Force recalc of window size for serial terminals */
2529
+ current->cols = 0;
2530
+ current->rpos = 0;
2531
+ refreshLine(current);
2532
+ break;
2533
+ default:
2534
+ if (c >= meta('a') && c <= meta('z')) {
2535
+ /* Don't insert meta chars that are not bound */
2536
+ break;
2537
+ }
2538
+ /* Only tab is allowed without ^V */
2539
+ if (c == '\t' || c >= ' ') {
2540
+ if (insert_char(current, current->pos, c) == 1) {
2541
+ refreshLine(current);
2542
+ }
2543
+ }
2544
+ break;
2545
+ }
2546
+ }
2547
+ return sb_len(current->buf);
2548
+}
2549
+
2550
+int linenoiseColumns(void)
2551
+{
2552
+ struct current current;
2553
+ current.output = NULL;
2554
+ enableRawMode (&current);
2555
+ getWindowSize (&current);
2556
+ disableRawMode (&current);
2557
+ return current.cols;
2558
+}
2559
+
2560
+/**
2561
+ * Reads a line from the file handle (without the trailing NL or CRNL)
2562
+ * and returns it in a stringbuf.
2563
+ * Returns NULL if no characters are read before EOF or error.
2564
+ *
2565
+ * Note that the character count will *not* be correct for lines containing
2566
+ * utf8 sequences. Do not rely on the character count.
2567
+ */
2568
+static stringbuf *sb_getline(FILE *fh)
2569
+{
2570
+ stringbuf *sb = sb_alloc();
2571
+ int c;
2572
+ int n = 0;
2573
+
2574
+ while ((c = getc(fh)) != EOF) {
2575
+ char ch;
2576
+ n++;
2577
+ if (c == '\r') {
2578
+ /* CRLF -> LF */
2579
+ continue;
2580
+ }
2581
+ if (c == '\n' || c == '\r') {
2582
+ break;
2583
+ }
2584
+ ch = c;
2585
+ /* ignore the effect of character count for partial utf8 sequences */
2586
+ sb_append_len(sb, &ch, 1);
2587
+ }
2588
+ if (n == 0 || sb->data == NULL) {
2589
+ sb_free(sb);
2590
+ return NULL;
2591
+ }
2592
+ return sb;
2593
+}
2594
+
2595
+char *linenoiseWithInitial(const char *prompt, const char *initial)
2596
+{
2597
+ int count;
2598
+ struct current current;
2599
+ stringbuf *sb;
2600
+
2601
+ memset(&current, 0, sizeof(current));
2602
+
2603
+ if (enableRawMode(&current) == -1) {
2604
+ printf("%s", prompt);
2605
+ fflush(stdout);
2606
+ sb = sb_getline(stdin);
2607
+ if (sb && !fd_isatty(&current)) {
2608
+ printf("%s\n", sb_str(sb));
2609
+ fflush(stdout);
2610
+ }
2611
+ }
2612
+ else {
2613
+ current.buf = sb_alloc();
2614
+ current.pos = 0;
2615
+ current.nrows = 1;
2616
+ current.prompt = prompt;
2617
+
2618
+ /* The latest history entry is always our current buffer */
2619
+ linenoiseHistoryAdd(initial);
2620
+ set_current(&current, initial);
2621
+
2622
+ count = linenoiseEdit(&current);
2623
+
2624
+ disableRawMode(&current);
2625
+ printf("\n");
2626
+
2627
+ sb_free(current.capture);
2628
+ if (count == -1) {
2629
+ sb_free(current.buf);
2630
+ return NULL;
2631
+ }
2632
+ sb = current.buf;
2633
+ }
2634
+ return sb ? sb_to_string(sb) : NULL;
2635
+}
2636
+
2637
+char *linenoise(const char *prompt)
2638
+{
2639
+ return linenoiseWithInitial(prompt, "");
2640
+}
2641
+
2642
+/* Using a circular buffer is smarter, but a bit more complex to handle. */
2643
+static int linenoiseHistoryAddAllocated(char *line) {
2644
+
2645
+ if (history_max_len == 0) {
2646
+notinserted:
2647
+ free(line);
2648
+ return 0;
2649
+ }
2650
+ if (history == NULL) {
2651
+ history = (char **)calloc(sizeof(char*), history_max_len);
2652
+ }
2653
+
2654
+ /* do not insert duplicate lines into history */
2655
+ if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
2656
+ goto notinserted;
2657
+ }
2658
+
11462659
if (history_len == history_max_len) {
11472660
free(history[0]);
11482661
memmove(history,history+1,sizeof(char*)*(history_max_len-1));
11492662
history_len--;
11502663
}
1151
- history[history_len] = linecopy;
2664
+ history[history_len] = line;
11522665
history_len++;
11532666
return 1;
11542667
}
11552668
1156
-/* Set the maximum length for the history. This function can be called even
1157
- * if there is already some history, the function will make sure to retain
1158
- * just the latest 'len' elements if the new history length value is smaller
1159
- * than the amount of items already inside the history. */
2669
+int linenoiseHistoryAdd(const char *line) {
2670
+ return linenoiseHistoryAddAllocated(strdup(line));
2671
+}
2672
+
2673
+int linenoiseHistoryGetMaxLen(void) {
2674
+ return history_max_len;
2675
+}
2676
+
11602677
int linenoiseHistorySetMaxLen(int len) {
1161
- char **new;
2678
+ char **newHistory;
11622679
11632680
if (len < 1) return 0;
11642681
if (history) {
11652682
int tocopy = history_len;
11662683
1167
- new = malloc(sizeof(char*)*len);
1168
- if (new == NULL) return 0;
2684
+ newHistory = (char **)calloc(sizeof(char*), len);
11692685
11702686
/* If we can't copy everything, free the elements we'll not use. */
11712687
if (len < tocopy) {
11722688
int j;
11732689
11742690
for (j = 0; j < tocopy-len; j++) free(history[j]);
11752691
tocopy = len;
11762692
}
1177
- memset(new,0,sizeof(char*)*len);
1178
- memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
2693
+ memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
11792694
free(history);
1180
- history = new;
2695
+ history = newHistory;
11812696
}
11822697
history_max_len = len;
11832698
if (history_len > history_max_len)
11842699
history_len = history_max_len;
11852700
return 1;
@@ -1186,41 +2701,86 @@
11862701
}
11872702
11882703
/* Save the history in the specified file. On success 0 is returned
11892704
* otherwise -1 is returned. */
11902705
int linenoiseHistorySave(const char *filename) {
1191
- mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
1192
- FILE *fp;
1193
- int j;
1194
-
1195
- fp = fopen(filename,"w");
1196
- umask(old_umask);
1197
- if (fp == NULL) return -1;
1198
- chmod(filename,S_IRUSR|S_IWUSR);
1199
- for (j = 0; j < history_len; j++)
1200
- fprintf(fp,"%s\n",history[j]);
1201
- fclose(fp);
1202
- return 0;
1203
-}
1204
-
1205
-/* Load the history from the specified file. If the file does not exist
1206
- * zero is returned and no operation is performed.
1207
- *
1208
- * If the file exists and the operation succeeded 0 is returned, otherwise
1209
- * on error -1 is returned. */
1210
-int linenoiseHistoryLoad(const char *filename) {
1211
- FILE *fp = fopen(filename,"r");
1212
- char buf[LINENOISE_MAX_LINE];
1213
-
1214
- if (fp == NULL) return -1;
1215
-
1216
- while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
1217
- char *p;
1218
-
1219
- p = strchr(buf,'\r');
1220
- if (!p) p = strchr(buf,'\n');
1221
- if (p) *p = '\0';
1222
- linenoiseHistoryAdd(buf);
1223
- }
1224
- fclose(fp);
1225
- return 0;
2706
+ FILE *fp = fopen(filename,"w");
2707
+ int j;
2708
+
2709
+ if (fp == NULL) return -1;
2710
+ for (j = 0; j < history_len; j++) {
2711
+ const char *str = history[j];
2712
+ /* Need to encode backslash, nl and cr */
2713
+ while (*str) {
2714
+ if (*str == '\\') {
2715
+ fputs("\\\\", fp);
2716
+ }
2717
+ else if (*str == '\n') {
2718
+ fputs("\\n", fp);
2719
+ }
2720
+ else if (*str == '\r') {
2721
+ fputs("\\r", fp);
2722
+ }
2723
+ else {
2724
+ fputc(*str, fp);
2725
+ }
2726
+ str++;
2727
+ }
2728
+ fputc('\n', fp);
2729
+ }
2730
+
2731
+ fclose(fp);
2732
+ return 0;
2733
+}
2734
+
2735
+/* Load the history from the specified file.
2736
+ *
2737
+ * If the file does not exist or can't be opened, no operation is performed
2738
+ * and -1 is returned.
2739
+ * Otherwise 0 is returned.
2740
+ */
2741
+int linenoiseHistoryLoad(const char *filename) {
2742
+ FILE *fp = fopen(filename,"r");
2743
+ stringbuf *sb;
2744
+
2745
+ if (fp == NULL) return -1;
2746
+
2747
+ while ((sb = sb_getline(fp)) != NULL) {
2748
+ /* Take the stringbuf and decode backslash escaped values */
2749
+ char *buf = sb_to_string(sb);
2750
+ char *dest = buf;
2751
+ const char *src;
2752
+
2753
+ for (src = buf; *src; src++) {
2754
+ char ch = *src;
2755
+
2756
+ if (ch == '\\') {
2757
+ src++;
2758
+ if (*src == 'n') {
2759
+ ch = '\n';
2760
+ }
2761
+ else if (*src == 'r') {
2762
+ ch = '\r';
2763
+ } else {
2764
+ ch = *src;
2765
+ }
2766
+ }
2767
+ *dest++ = ch;
2768
+ }
2769
+ *dest = 0;
2770
+
2771
+ linenoiseHistoryAddAllocated(buf);
2772
+ }
2773
+ fclose(fp);
2774
+ return 0;
2775
+}
2776
+
2777
+/* Provide access to the history buffer.
2778
+ *
2779
+ * If 'len' is not NULL, the length is stored in *len.
2780
+ */
2781
+char **linenoiseHistory(int *len) {
2782
+ if (len) {
2783
+ *len = history_len;
2784
+ }
2785
+ return history;
12262786
}
12272787
--- extsrc/linenoise.c
+++ extsrc/linenoise.c
@@ -1,19 +1,718 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 /* linenoise.c -- guerrilla line editing library against the idea that a
2 * line editing lib needs to be 20,000 lines of C code.
3 *
4 * You can find the latest source code at:
5 *
6 * http://github.com/antirez/linenoise
 
7 *
8 * Does a number of crazy assumptions that happen to be true in 99.9999% of
9 * the 2010 UNIX computers around.
10 *
11 * ------------------------------------------------------------------------
12 *
13 * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
14 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
 
15 *
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
@@ -42,211 +741,381 @@
42 *
43 * References:
44 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
45 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
46 *
47 * Todo list:
48 * - Filter bogus Ctrl+<char> combinations.
49 * - Win32 support
50 *
51 * Bloat:
52 * - History search like Ctrl+r in readline?
53 *
 
 
54 * List of escape sequences used by this program, we do everything just
55 * with three sequences. In order to be so cheap we may have some
56 * flickering effect with some slow terminal, but the lesser sequences
57 * the more compatible.
58 *
59 * EL (Erase Line)
60 * Sequence: ESC [ n K
61 * Effect: if n is 0 or missing, clear from cursor to end of line
62 * Effect: if n is 1, clear from beginning of line to cursor
63 * Effect: if n is 2, clear entire line
64 *
65 * CUF (CUrsor Forward)
66 * Sequence: ESC [ n C
67 * Effect: moves cursor forward n chars
68 *
69 * CUB (CUrsor Backward)
70 * Sequence: ESC [ n D
71 * Effect: moves cursor backward n chars
72 *
73 * The following is used to get the terminal width if getting
74 * the width with the TIOCGWINSZ ioctl fails
75 *
76 * DSR (Device Status Report)
77 * Sequence: ESC [ 6 n
78 * Effect: reports the current cusor position as ESC [ n ; m R
79 * where n is the row and m is the column
80 *
81 * When multi line mode is enabled, we also use an additional escape
82 * sequence. However multi line editing is disabled by default.
83 *
84 * CUU (Cursor Up)
85 * Sequence: ESC [ n A
86 * Effect: moves cursor up of n chars.
87 *
88 * CUD (Cursor Down)
89 * Sequence: ESC [ n B
90 * Effect: moves cursor down of n chars.
91 *
92 * When linenoiseClearScreen() is called, two additional escape sequences
93 * are used in order to clear the screen and position the cursor at home
94 * position.
95 *
96 * CUP (Cursor position)
97 * Sequence: ESC [ H
98 * Effect: moves the cursor to upper left corner
99 *
100 * ED (Erase display)
101 * Sequence: ESC [ 2 J
102 * Effect: clear the whole screen
103 *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104 */
105
 
 
 
 
 
 
 
 
106 #include <termios.h>
 
 
 
 
 
 
 
107 #include <unistd.h>
 
108 #include <stdlib.h>
 
109 #include <stdio.h>
 
110 #include <errno.h>
111 #include <string.h>
 
112 #include <stdlib.h>
113 #include <ctype.h>
114 #include <sys/stat.h>
115 #include <sys/types.h>
116 #include <sys/ioctl.h>
117 #include <unistd.h>
 
 
 
 
 
118 #include "linenoise.h"
 
 
 
 
 
 
119
120 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
121 #define LINENOISE_MAX_LINE 4096
122 static char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
123 static linenoiseCompletionCallback *completionCallback = NULL;
124 static linenoiseHintsCallback *hintsCallback = NULL;
125 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
126
127 static struct termios orig_termios; /* In order to restore at exit.*/
128 static int maskmode = 0; /* Show "***" instead of input. For passwords. */
129 static int rawmode = 0; /* For atexit() function to check if restore is needed*/
130 static int mlmode = 0; /* Multi line mode. Default is single line. */
131 static int atexit_registered = 0; /* Register atexit just 1 time. */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
133 static int history_len = 0;
 
134 static char **history = NULL;
135
136 /* The linenoiseState structure represents the state during line editing.
137 * We pass this state to functions implementing specific editing
138 * functionalities. */
139 struct linenoiseState {
140 int ifd; /* Terminal stdin file descriptor. */
141 int ofd; /* Terminal stdout file descriptor. */
142 char *buf; /* Edited line buffer. */
143 size_t buflen; /* Edited line buffer size. */
144 const char *prompt; /* Prompt to display. */
145 size_t plen; /* Prompt length. */
146 size_t pos; /* Current cursor position. */
147 size_t oldpos; /* Previous refresh cursor position. */
148 size_t len; /* Current edited line length. */
149 size_t cols; /* Number of columns in terminal. */
150 size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
151 int history_index; /* The history index we are currently editing. */
152 };
153
154 enum KEY_ACTION{
155 KEY_NULL = 0, /* NULL */
156 CTRL_A = 1, /* Ctrl+a */
157 CTRL_B = 2, /* Ctrl-b */
158 CTRL_C = 3, /* Ctrl-c */
159 CTRL_D = 4, /* Ctrl-d */
160 CTRL_E = 5, /* Ctrl-e */
161 CTRL_F = 6, /* Ctrl-f */
162 CTRL_H = 8, /* Ctrl-h */
163 TAB = 9, /* Tab */
164 CTRL_K = 11, /* Ctrl+k */
165 CTRL_L = 12, /* Ctrl+l */
166 ENTER = 13, /* Enter */
167 CTRL_N = 14, /* Ctrl-n */
168 CTRL_P = 16, /* Ctrl-p */
169 CTRL_T = 20, /* Ctrl-t */
170 CTRL_U = 21, /* Ctrl+u */
171 CTRL_W = 23, /* Ctrl+w */
172 ESC = 27, /* Escape */
173 BACKSPACE = 127 /* Backspace */
174 };
175
176 static void linenoiseAtExit(void);
177 int linenoiseHistoryAdd(const char *line);
178 static void refreshLine(struct linenoiseState *l);
179
180 /* Debugging macro. */
181 #if 0
182 FILE *lndebug_fp = NULL;
183 #define lndebug(...) \
184 do { \
185 if (lndebug_fp == NULL) { \
186 lndebug_fp = fopen("/tmp/lndebug.txt","a"); \
187 fprintf(lndebug_fp, \
188 "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \
189 (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \
190 (int)l->maxrows,old_rows); \
191 } \
192 fprintf(lndebug_fp, ", " __VA_ARGS__); \
193 fflush(lndebug_fp); \
194 } while (0)
195 #else
196 #define lndebug(fmt, ...)
197 #endif
198
199 /* ======================= Low level terminal handling ====================== */
200
201 /* Enable "mask mode". When it is enabled, instead of the input that
202 * the user is typing, the terminal will just display a corresponding
203 * number of asterisks, like "****". This is useful for passwords and other
204 * secrets that should not be displayed. */
205 void linenoiseMaskModeEnable(void) {
206 maskmode = 1;
207 }
208
209 /* Disable mask mode. */
210 void linenoiseMaskModeDisable(void) {
211 maskmode = 0;
212 }
213
214 /* Set if to use or not the multi line mode. */
215 void linenoiseSetMultiLine(int ml) {
216 mlmode = ml;
217 }
218
219 /* Return true if the terminal name is in the list of terminals we know are
220 * not able to understand basic escape sequences. */
221 static int isUnsupportedTerm(void) {
222 char *term = getenv("TERM");
223 int j;
224
225 if (term == NULL) return 0;
226 for (j = 0; unsupported_term[j]; j++)
227 if (!strcasecmp(term,unsupported_term[j])) return 1;
228 return 0;
229 }
230
231 /* Raw mode: 1960 magic shit. */
232 static int enableRawMode(int fd) {
233 struct termios raw;
234
235 if (!isatty(STDIN_FILENO)) goto fatal;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236 if (!atexit_registered) {
237 atexit(linenoiseAtExit);
238 atexit_registered = 1;
239 }
240 if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
241
242 raw = orig_termios; /* modify the original mode */
243 /* input modes: no break, no CR to NL, no parity check, no strip char,
244 * no start/stop output control. */
245 raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
246 /* output modes - disable post processing */
247 raw.c_oflag &= ~(OPOST);
248 /* control modes - set 8 bit chars */
249 raw.c_cflag |= (CS8);
250 /* local modes - choing off, canonical off, no extended functions,
251 * no signal chars (^Z,^C) */
252 raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
@@ -253,163 +1122,452 @@
253 /* control chars - set return condition: min number of bytes and timer.
254 * We want read to return every single byte, without timeout. */
255 raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
256
257 /* put terminal in raw mode after flushing */
258 if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;
 
 
259 rawmode = 1;
260 return 0;
261
262 fatal:
263 errno = ENOTTY;
264 return -1;
265 }
266
267 static void disableRawMode(int fd) {
268 /* Don't even check the return value as it's too late. */
269 if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)
270 rawmode = 0;
271 }
272
273 /* Use the ESC [6n escape sequence to query the horizontal cursor position
274 * and return it. On error -1 is returned, on success the position of the
275 * cursor. */
276 static int getCursorPosition(int ifd, int ofd) {
277 char buf[32];
278 int cols, rows;
279 unsigned int i = 0;
280
281 /* Report cursor location */
282 if (write(ofd, "\x1b[6n", 4) != 4) return -1;
283
284 /* Read the response: ESC [ rows ; cols R */
285 while (i < sizeof(buf)-1) {
286 if (read(ifd,buf+i,1) != 1) break;
287 if (buf[i] == 'R') break;
288 i++;
289 }
290 buf[i] = '\0';
291
292 /* Parse it. */
293 if (buf[0] != ESC || buf[1] != '[') return -1;
294 if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
295 return cols;
296 }
297
298 /* Try to get the number of columns in the current terminal, or assume 80
299 * if it fails. */
300 static int getColumns(int ifd, int ofd) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301 struct winsize ws;
302
303 if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
304 /* ioctl() failed. Try to query the terminal itself. */
305 int start, cols;
306
307 /* Get the initial position so we can restore it later. */
308 start = getCursorPosition(ifd,ofd);
309 if (start == -1) goto failed;
310
311 /* Go to right margin and get position. */
312 if (write(ofd,"\x1b[999C",6) != 6) goto failed;
313 cols = getCursorPosition(ifd,ofd);
314 if (cols == -1) goto failed;
315
316 /* Restore position. */
317 if (cols > start) {
318 char seq[32];
319 snprintf(seq,32,"\x1b[%dD",cols-start);
320 if (write(ofd,seq,strlen(seq)) == -1) {
321 /* Can't recover... */
322 }
323 }
324 return cols;
325 } else {
326 return ws.ws_col;
327 }
328
329 failed:
330 return 80;
331 }
332
333 /* Clear the screen. Used to handle ctrl+l */
334 void linenoiseClearScreen(void) {
335 if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
336 /* nothing to do, just to avoid warning. */
337 }
338 }
339
340 /* Beep, used for completion when there is nothing to complete or when all
341 * the choices were already shown. */
342 static void linenoiseBeep(void) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343 fprintf(stderr, "\x7");
344 fflush(stderr);
 
345 }
346
347 /* ============================== Completion ================================ */
348
349 /* Free a list of completion option populated by linenoiseAddCompletion(). */
350 static void freeCompletions(linenoiseCompletions *lc) {
351 size_t i;
352 for (i = 0; i < lc->len; i++)
353 free(lc->cvec[i]);
354 if (lc->cvec != NULL)
355 free(lc->cvec);
356 }
357
358 /* This is an helper function for linenoiseEdit() and is called when the
359 * user types the <tab> key in order to complete the string currently in the
360 * input.
361 *
362 * The state of the editing is encapsulated into the pointed linenoiseState
363 * structure as described in the structure definition. */
364 static int completeLine(struct linenoiseState *ls) {
365 linenoiseCompletions lc = { 0, NULL };
366 int nread, nwritten;
367 char c = 0;
368
369 completionCallback(ls->buf,&lc);
370 if (lc.len == 0) {
371 linenoiseBeep();
372 } else {
373 size_t stop = 0, i = 0;
374
375 while(!stop) {
376 /* Show completion or original buffer */
377 if (i < lc.len) {
378 struct linenoiseState saved = *ls;
379
380 ls->len = ls->pos = strlen(lc.cvec[i]);
381 ls->buf = lc.cvec[i];
382 refreshLine(ls);
383 ls->len = saved.len;
384 ls->pos = saved.pos;
385 ls->buf = saved.buf;
386 } else {
387 refreshLine(ls);
388 }
389
390 nread = read(ls->ifd,&c,1);
391 if (nread <= 0) {
392 freeCompletions(&lc);
393 return -1;
394 }
395
396 switch(c) {
397 case 9: /* tab */
398 i = (i+1) % (lc.len+1);
399 if (i == lc.len) linenoiseBeep();
400 break;
401 case 27: /* escape */
402 /* Re-show original buffer */
403 if (i < lc.len) refreshLine(ls);
 
 
404 stop = 1;
405 break;
406 default:
407 /* Update buffer and return */
408 if (i < lc.len) {
409 nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
410 ls->len = ls->pos = nwritten;
411 }
412 stop = 1;
413 break;
414 }
415 }
@@ -417,769 +1575,1126 @@
417
418 freeCompletions(&lc);
419 return c; /* Return last read character */
420 }
421
422 /* Register a callback function to be called for tab-completion. */
423 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
 
 
 
424 completionCallback = fn;
425 }
426
427 /* Register a hits function to be called to show hits to the user at the
428 * right of the prompt. */
429 void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
430 hintsCallback = fn;
431 }
432
433 /* Register a function to free the hints returned by the hints callback
434 * registered with linenoiseSetHintsCallback(). */
435 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
436 freeHintsCallback = fn;
437 }
438
439 /* This function is used by the callback function registered by the user
440 * in order to add completion options given the input string when the
441 * user typed <tab>. See the example.c source code for a very easy to
442 * understand example. */
443 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
444 size_t len = strlen(str);
445 char *copy, **cvec;
446
447 copy = malloc(len+1);
448 if (copy == NULL) return;
449 memcpy(copy,str,len+1);
450 cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
451 if (cvec == NULL) {
452 free(copy);
453 return;
454 }
455 lc->cvec = cvec;
456 lc->cvec[lc->len++] = copy;
457 }
458
459 /* =========================== Line editing ================================= */
460
461 /* We define a very simple "append buffer" structure, that is an heap
462 * allocated string where we can append to. This is useful in order to
463 * write all the escape sequences in a buffer and flush them to the standard
464 * output in a single call, to avoid flickering effects. */
465 struct abuf {
466 char *b;
467 int len;
468 };
469
470 static void abInit(struct abuf *ab) {
471 ab->b = NULL;
472 ab->len = 0;
473 }
474
475 static void abAppend(struct abuf *ab, const char *s, int len) {
476 char *new = realloc(ab->b,ab->len+len);
477
478 if (new == NULL) return;
479 memcpy(new+ab->len,s,len);
480 ab->b = new;
481 ab->len += len;
482 }
483
484 static void abFree(struct abuf *ab) {
485 free(ab->b);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486 }
487
488 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
489 * to the right of the prompt. */
490 void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
491 char seq[64];
492 if (hintsCallback && plen+l->len < l->cols) {
493 int color = -1, bold = 0;
494 char *hint = hintsCallback(l->buf,&color,&bold);
 
 
 
 
 
495 if (hint) {
496 int hintlen = strlen(hint);
497 int hintmaxlen = l->cols-(plen+l->len);
498 if (hintlen > hintmaxlen) hintlen = hintmaxlen;
499 if (bold == 1 && color == -1) color = 37;
500 if (color != -1 || bold != 0)
501 snprintf(seq,64,"\033[%d;%d;49m",bold,color);
502 else
503 seq[0] = '\0';
504 abAppend(ab,seq,strlen(seq));
505 abAppend(ab,hint,hintlen);
506 if (color != -1 || bold != 0)
507 abAppend(ab,"\033[0m",4);
508 /* Call the function to free the hint returned. */
509 if (freeHintsCallback) freeHintsCallback(hint);
510 }
511 }
512 }
513
514 /* Single line low level line refresh.
515 *
516 * Rewrite the currently edited line accordingly to the buffer content,
517 * cursor position, and number of columns of the terminal. */
518 static void refreshSingleLine(struct linenoiseState *l) {
519 char seq[64];
520 size_t plen = strlen(l->prompt);
521 int fd = l->ofd;
522 char *buf = l->buf;
523 size_t len = l->len;
524 size_t pos = l->pos;
525 struct abuf ab;
526
527 while((plen+pos) >= l->cols) {
528 buf++;
529 len--;
530 pos--;
531 }
532 while (plen+len > l->cols) {
533 len--;
534 }
535
536 abInit(&ab);
537 /* Cursor to left edge */
538 snprintf(seq,64,"\r");
539 abAppend(&ab,seq,strlen(seq));
540 /* Write the prompt and the current buffer content */
541 abAppend(&ab,l->prompt,strlen(l->prompt));
542 if (maskmode == 1) {
543 while (len--) abAppend(&ab,"*",1);
544 } else {
545 abAppend(&ab,buf,len);
546 }
547 /* Show hits if any. */
548 refreshShowHints(&ab,l,plen);
549 /* Erase to right */
550 snprintf(seq,64,"\x1b[0K");
551 abAppend(&ab,seq,strlen(seq));
552 /* Move cursor to original position. */
553 snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
554 abAppend(&ab,seq,strlen(seq));
555 if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
556 abFree(&ab);
557 }
558
559 /* Multi line low level line refresh.
560 *
561 * Rewrite the currently edited line accordingly to the buffer content,
562 * cursor position, and number of columns of the terminal. */
563 static void refreshMultiLine(struct linenoiseState *l) {
564 char seq[64];
565 int plen = strlen(l->prompt);
566 int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
567 int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
568 int rpos2; /* rpos after refresh. */
569 int col; /* colum position, zero-based. */
570 int old_rows = l->maxrows;
571 int fd = l->ofd, j;
572 struct abuf ab;
573
574 /* Update maxrows if needed. */
575 if (rows > (int)l->maxrows) l->maxrows = rows;
576
577 /* First step: clear all the lines used before. To do so start by
578 * going to the last row. */
579 abInit(&ab);
580 if (old_rows-rpos > 0) {
581 lndebug("go down %d", old_rows-rpos);
582 snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
583 abAppend(&ab,seq,strlen(seq));
584 }
585
586 /* Now for every row clear it, go up. */
587 for (j = 0; j < old_rows-1; j++) {
588 lndebug("clear+up");
589 snprintf(seq,64,"\r\x1b[0K\x1b[1A");
590 abAppend(&ab,seq,strlen(seq));
591 }
592
593 /* Clean the top line. */
594 lndebug("clear");
595 snprintf(seq,64,"\r\x1b[0K");
596 abAppend(&ab,seq,strlen(seq));
597
598 /* Write the prompt and the current buffer content */
599 abAppend(&ab,l->prompt,strlen(l->prompt));
600 if (maskmode == 1) {
601 unsigned int i;
602 for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
603 } else {
604 abAppend(&ab,l->buf,l->len);
605 }
606
607 /* Show hits if any. */
608 refreshShowHints(&ab,l,plen);
609
610 /* If we are at the very end of the screen with our prompt, we need to
611 * emit a newline and move the prompt to the first column. */
612 if (l->pos &&
613 l->pos == l->len &&
614 (l->pos+plen) % l->cols == 0)
615 {
616 lndebug("<newline>");
617 abAppend(&ab,"\n",1);
618 snprintf(seq,64,"\r");
619 abAppend(&ab,seq,strlen(seq));
620 rows++;
621 if (rows > (int)l->maxrows) l->maxrows = rows;
622 }
623
624 /* Move cursor to right position. */
625 rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */
626 lndebug("rpos2 %d", rpos2);
627
628 /* Go up till we reach the expected positon. */
629 if (rows-rpos2 > 0) {
630 lndebug("go-up %d", rows-rpos2);
631 snprintf(seq,64,"\x1b[%dA", rows-rpos2);
632 abAppend(&ab,seq,strlen(seq));
633 }
634
635 /* Set column. */
636 col = (plen+(int)l->pos) % (int)l->cols;
637 lndebug("set col %d", 1+col);
638 if (col)
639 snprintf(seq,64,"\r\x1b[%dC", col);
640 else
641 snprintf(seq,64,"\r");
642 abAppend(&ab,seq,strlen(seq));
643
644 lndebug("\n");
645 l->oldpos = l->pos;
646
647 if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
648 abFree(&ab);
649 }
650
651 /* Calls the two low level functions refreshSingleLine() or
652 * refreshMultiLine() according to the selected mode. */
653 static void refreshLine(struct linenoiseState *l) {
654 if (mlmode)
655 refreshMultiLine(l);
656 else
657 refreshSingleLine(l);
658 }
659
660 /* Insert the character 'c' at cursor current position.
661 *
662 * On error writing to the terminal -1 is returned, otherwise 0. */
663 int linenoiseEditInsert(struct linenoiseState *l, char c) {
664 if (l->len < l->buflen) {
665 if (l->len == l->pos) {
666 l->buf[l->pos] = c;
667 l->pos++;
668 l->len++;
669 l->buf[l->len] = '\0';
670 if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
671 /* Avoid a full update of the line in the
672 * trivial case. */
673 char d = (maskmode==1) ? '*' : c;
674 if (write(l->ofd,&d,1) == -1) return -1;
675 } else {
676 refreshLine(l);
677 }
678 } else {
679 memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);
680 l->buf[l->pos] = c;
681 l->len++;
682 l->pos++;
683 l->buf[l->len] = '\0';
684 refreshLine(l);
685 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
686 }
687 return 0;
688 }
689
690 /* Move cursor on the left. */
691 void linenoiseEditMoveLeft(struct linenoiseState *l) {
692 if (l->pos > 0) {
693 l->pos--;
694 refreshLine(l);
695 }
696 }
697
698 /* Move cursor on the right. */
699 void linenoiseEditMoveRight(struct linenoiseState *l) {
700 if (l->pos != l->len) {
701 l->pos++;
702 refreshLine(l);
703 }
704 }
705
706 /* Move cursor to the start of the line. */
707 void linenoiseEditMoveHome(struct linenoiseState *l) {
708 if (l->pos != 0) {
709 l->pos = 0;
710 refreshLine(l);
711 }
712 }
713
714 /* Move cursor to the end of the line. */
715 void linenoiseEditMoveEnd(struct linenoiseState *l) {
716 if (l->pos != l->len) {
717 l->pos = l->len;
718 refreshLine(l);
719 }
720 }
721
722 /* Substitute the currently edited line with the next or previous history
723 * entry as specified by 'dir'. */
724 #define LINENOISE_HISTORY_NEXT 0
725 #define LINENOISE_HISTORY_PREV 1
726 void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {
727 if (history_len > 1) {
728 /* Update the current history entry before to
729 * overwrite it with the next one. */
730 free(history[history_len - 1 - l->history_index]);
731 history[history_len - 1 - l->history_index] = strdup(l->buf);
732 /* Show the new entry */
733 l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;
734 if (l->history_index < 0) {
735 l->history_index = 0;
736 return;
737 } else if (l->history_index >= history_len) {
738 l->history_index = history_len-1;
739 return;
740 }
741 strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);
742 l->buf[l->buflen-1] = '\0';
743 l->len = l->pos = strlen(l->buf);
744 refreshLine(l);
745 }
746 }
747
748 /* Delete the character at the right of the cursor without altering the cursor
749 * position. Basically this is what happens with the "Delete" keyboard key. */
750 void linenoiseEditDelete(struct linenoiseState *l) {
751 if (l->len > 0 && l->pos < l->len) {
752 memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);
753 l->len--;
754 l->buf[l->len] = '\0';
755 refreshLine(l);
756 }
757 }
758
759 /* Backspace implementation. */
760 void linenoiseEditBackspace(struct linenoiseState *l) {
761 if (l->pos > 0 && l->len > 0) {
762 memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);
763 l->pos--;
764 l->len--;
765 l->buf[l->len] = '\0';
766 refreshLine(l);
767 }
768 }
769
770 /* Delete the previosu word, maintaining the cursor at the start of the
771 * current word. */
772 void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
773 size_t old_pos = l->pos;
774 size_t diff;
775
776 while (l->pos > 0 && l->buf[l->pos-1] == ' ')
777 l->pos--;
778 while (l->pos > 0 && l->buf[l->pos-1] != ' ')
779 l->pos--;
780 diff = old_pos - l->pos;
781 memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
782 l->len -= diff;
783 refreshLine(l);
784 }
785
786 /* This function is the core of the line editing capability of linenoise.
787 * It expects 'fd' to be already in "raw mode" so that every key pressed
788 * will be returned ASAP to read().
789 *
790 * The resulting string is put into 'buf' when the user type enter, or
791 * when ctrl+d is typed.
792 *
793 * The function returns the length of the current buffer. */
794 static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
795 {
796 struct linenoiseState l;
797
798 /* Populate the linenoise state that we pass to functions implementing
799 * specific editing functionalities. */
800 l.ifd = stdin_fd;
801 l.ofd = stdout_fd;
802 l.buf = buf;
803 l.buflen = buflen;
804 l.prompt = prompt;
805 l.plen = strlen(prompt);
806 l.oldpos = l.pos = 0;
807 l.len = 0;
808 l.cols = getColumns(stdin_fd, stdout_fd);
809 l.maxrows = 0;
810 l.history_index = 0;
811
812 /* Buffer starts empty. */
813 l.buf[0] = '\0';
814 l.buflen--; /* Make sure there is always space for the nulterm */
815
816 /* The latest history entry is always our current buffer, that
817 * initially is just an empty string. */
818 linenoiseHistoryAdd("");
819
820 if (write(l.ofd,prompt,l.plen) == -1) return -1;
821 while(1) {
822 char c;
823 int nread;
824 char seq[3];
825
826 nread = read(l.ifd,&c,1);
827 if (nread <= 0) return l.len;
828
829 /* Only autocomplete when the callback is set. It returns < 0 when
830 * there was an error reading from fd. Otherwise it will return the
831 * character that should be handled next. */
832 if (c == 9 && completionCallback != NULL) {
833 c = completeLine(&l);
834 /* Return on errors */
835 if (c < 0) return l.len;
836 /* Read next character when 0 */
837 if (c == 0) continue;
838 }
839
840 switch(c) {
841 case ENTER: /* enter */
842 history_len--;
843 free(history[history_len]);
844 if (mlmode) linenoiseEditMoveEnd(&l);
845 if (hintsCallback) {
846 /* Force a refresh without hints to leave the previous
847 * line as the user typed it after a newline. */
848 linenoiseHintsCallback *hc = hintsCallback;
849 hintsCallback = NULL;
850 refreshLine(&l);
851 hintsCallback = hc;
852 }
853 return (int)l.len;
854 case CTRL_C: /* ctrl-c */
855 errno = EAGAIN;
856 return -1;
857 case BACKSPACE: /* backspace */
858 case 8: /* ctrl-h */
859 linenoiseEditBackspace(&l);
860 break;
861 case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the
862 line is empty, act as end-of-file. */
863 if (l.len > 0) {
864 linenoiseEditDelete(&l);
865 } else {
866 history_len--;
867 free(history[history_len]);
868 return -1;
869 }
870 break;
871 case CTRL_T: /* ctrl-t, swaps current character with previous. */
872 if (l.pos > 0 && l.pos < l.len) {
873 int aux = buf[l.pos-1];
874 buf[l.pos-1] = buf[l.pos];
875 buf[l.pos] = aux;
876 if (l.pos != l.len-1) l.pos++;
877 refreshLine(&l);
878 }
879 break;
880 case CTRL_B: /* ctrl-b */
881 linenoiseEditMoveLeft(&l);
882 break;
883 case CTRL_F: /* ctrl-f */
884 linenoiseEditMoveRight(&l);
885 break;
886 case CTRL_P: /* ctrl-p */
887 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
888 break;
889 case CTRL_N: /* ctrl-n */
890 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
891 break;
892 case ESC: /* escape sequence */
893 /* Read the next two bytes representing the escape sequence.
894 * Use two calls to handle slow terminals returning the two
895 * chars at different times. */
896 if (read(l.ifd,seq,1) == -1) break;
897 if (read(l.ifd,seq+1,1) == -1) break;
898
899 /* ESC [ sequences. */
900 if (seq[0] == '[') {
901 if (seq[1] >= '0' && seq[1] <= '9') {
902 /* Extended escape, read additional byte. */
903 if (read(l.ifd,seq+2,1) == -1) break;
904 if (seq[2] == '~') {
905 switch(seq[1]) {
906 case '3': /* Delete key. */
907 linenoiseEditDelete(&l);
908 break;
909 }
910 }
911 } else {
912 switch(seq[1]) {
913 case 'A': /* Up */
914 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
915 break;
916 case 'B': /* Down */
917 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
918 break;
919 case 'C': /* Right */
920 linenoiseEditMoveRight(&l);
921 break;
922 case 'D': /* Left */
923 linenoiseEditMoveLeft(&l);
924 break;
925 case 'H': /* Home */
926 linenoiseEditMoveHome(&l);
927 break;
928 case 'F': /* End*/
929 linenoiseEditMoveEnd(&l);
930 break;
931 }
932 }
933 }
934
935 /* ESC O sequences. */
936 else if (seq[0] == 'O') {
937 switch(seq[1]) {
938 case 'H': /* Home */
939 linenoiseEditMoveHome(&l);
940 break;
941 case 'F': /* End*/
942 linenoiseEditMoveEnd(&l);
943 break;
944 }
945 }
946 break;
947 default:
948 if (linenoiseEditInsert(&l,c)) return -1;
949 break;
950 case CTRL_U: /* Ctrl+u, delete the whole line. */
951 buf[0] = '\0';
952 l.pos = l.len = 0;
953 refreshLine(&l);
954 break;
955 case CTRL_K: /* Ctrl+k, delete from current to end of line. */
956 buf[l.pos] = '\0';
957 l.len = l.pos;
958 refreshLine(&l);
959 break;
960 case CTRL_A: /* Ctrl+a, go to the start of the line */
961 linenoiseEditMoveHome(&l);
962 break;
963 case CTRL_E: /* ctrl+e, go to the end of the line */
964 linenoiseEditMoveEnd(&l);
965 break;
966 case CTRL_L: /* ctrl+l, clear screen */
967 linenoiseClearScreen();
968 refreshLine(&l);
969 break;
970 case CTRL_W: /* ctrl+w, delete previous word */
971 linenoiseEditDeletePrevWord(&l);
972 break;
973 }
974 }
975 return l.len;
976 }
977
978 /* This special mode is used by linenoise in order to print scan codes
979 * on screen for debugging / development purposes. It is implemented
980 * by the linenoise_example program using the --keycodes option. */
981 void linenoisePrintKeyCodes(void) {
982 char quit[4];
983
984 printf("Linenoise key codes debugging mode.\n"
985 "Press keys to see scan codes. Type 'quit' at any time to exit.\n");
986 if (enableRawMode(STDIN_FILENO) == -1) return;
987 memset(quit,' ',4);
988 while(1) {
989 char c;
990 int nread;
991
992 nread = read(STDIN_FILENO,&c,1);
993 if (nread <= 0) continue;
994 memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */
995 quit[sizeof(quit)-1] = c; /* Insert current char on the right. */
996 if (memcmp(quit,"quit",sizeof(quit)) == 0) break;
997
998 printf("'%c' %02x (%d) (type quit to exit)\n",
999 isprint(c) ? c : '?', (int)c, (int)c);
1000 printf("\r"); /* Go left edge manually, we are in raw mode. */
1001 fflush(stdout);
1002 }
1003 disableRawMode(STDIN_FILENO);
1004 }
1005
1006 /* This function calls the line editing function linenoiseEdit() using
1007 * the STDIN file descriptor set in raw mode. */
1008 static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
1009 int count;
1010
1011 if (buflen == 0) {
1012 errno = EINVAL;
1013 return -1;
1014 }
1015
1016 if (enableRawMode(STDIN_FILENO) == -1) return -1;
1017 count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
1018 disableRawMode(STDIN_FILENO);
1019 printf("\n");
1020 return count;
1021 }
1022
1023 /* This function is called when linenoise() is called with the standard
1024 * input file descriptor not attached to a TTY. So for example when the
1025 * program using linenoise is called in pipe or with a file redirected
1026 * to its standard input. In this case, we want to be able to return the
1027 * line regardless of its length (by default we are limited to 4k). */
1028 static char *linenoiseNoTTY(void) {
1029 char *line = NULL;
1030 size_t len = 0, maxlen = 0;
1031
1032 while(1) {
1033 int c;
1034 if (len == maxlen) {
1035 char *oldval = line;
1036 if (maxlen == 0) maxlen = 16;
1037 maxlen *= 2;
1038 line = realloc(line,maxlen);
1039 if (line == NULL) {
1040 if (oldval) free(oldval);
1041 return NULL;
1042 }
1043 }
1044 c = fgetc(stdin);
1045 if (c == EOF || c == '\n') {
1046 if (c == EOF && len == 0) {
1047 free(line);
1048 return NULL;
1049 } else {
1050 line[len] = '\0';
1051 return line;
1052 }
1053 } else {
1054 line[len] = c;
1055 len++;
1056 }
1057 }
1058 }
1059
1060 /* The high level function that is the main API of the linenoise library.
1061 * This function checks if the terminal has basic capabilities, just checking
1062 * for a blacklist of stupid terminals, and later either calls the line
1063 * editing function or uses dummy fgets() so that you will be able to type
1064 * something even in the most desperate of the conditions. */
1065 char *linenoise(const char *prompt) {
1066 char buf[LINENOISE_MAX_LINE];
1067 int count;
1068
1069 if (!isatty(STDIN_FILENO)) {
1070 /* Not a tty: read from file / pipe. In this mode we don't want any
1071 * limit to the line size, so we call a function to handle that. */
1072 return linenoiseNoTTY();
1073 } else if (isUnsupportedTerm()) {
1074 size_t len;
1075
1076 printf("%s",prompt);
1077 fflush(stdout);
1078 if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
1079 len = strlen(buf);
1080 while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
1081 len--;
1082 buf[len] = '\0';
1083 }
1084 return strdup(buf);
1085 } else {
1086 count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
1087 if (count == -1) return NULL;
1088 return strdup(buf);
1089 }
1090 }
1091
1092 /* This is just a wrapper the user may want to call in order to make sure
1093 * the linenoise returned buffer is freed with the same allocator it was
1094 * created with. Useful when the main program is using an alternative
1095 * allocator. */
1096 void linenoiseFree(void *ptr) {
1097 free(ptr);
1098 }
1099
1100 /* ================================ History ================================= */
1101
1102 /* Free the history, but does not reset it. Only used when we have to
1103 * exit() to avoid memory leaks are reported by valgrind & co. */
1104 static void freeHistory(void) {
1105 if (history) {
1106 int j;
1107
1108 for (j = 0; j < history_len; j++)
1109 free(history[j]);
1110 free(history);
1111 }
1112 }
1113
1114 /* At exit we'll try to fix the terminal to the initial conditions. */
1115 static void linenoiseAtExit(void) {
1116 disableRawMode(STDIN_FILENO);
1117 freeHistory();
1118 }
1119
1120 /* This is the API call to add a new entry in the linenoise history.
1121 * It uses a fixed array of char pointers that are shifted (memmoved)
1122 * when the history max length is reached in order to remove the older
1123 * entry and make room for the new one, so it is not exactly suitable for huge
1124 * histories, but will work well for a few hundred of entries.
1125 *
1126 * Using a circular buffer is smarter, but a bit more complex to handle. */
1127 int linenoiseHistoryAdd(const char *line) {
1128 char *linecopy;
1129
1130 if (history_max_len == 0) return 0;
1131
1132 /* Initialization on first call. */
1133 if (history == NULL) {
1134 history = malloc(sizeof(char*)*history_max_len);
1135 if (history == NULL) return 0;
1136 memset(history,0,(sizeof(char*)*history_max_len));
1137 }
1138
1139 /* Don't add duplicated lines. */
1140 if (history_len && !strcmp(history[history_len-1], line)) return 0;
1141
1142 /* Add an heap allocated copy of the line in the history.
1143 * If we reached the max length, remove the older line. */
1144 linecopy = strdup(line);
1145 if (!linecopy) return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1146 if (history_len == history_max_len) {
1147 free(history[0]);
1148 memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1149 history_len--;
1150 }
1151 history[history_len] = linecopy;
1152 history_len++;
1153 return 1;
1154 }
1155
1156 /* Set the maximum length for the history. This function can be called even
1157 * if there is already some history, the function will make sure to retain
1158 * just the latest 'len' elements if the new history length value is smaller
1159 * than the amount of items already inside the history. */
 
 
 
 
1160 int linenoiseHistorySetMaxLen(int len) {
1161 char **new;
1162
1163 if (len < 1) return 0;
1164 if (history) {
1165 int tocopy = history_len;
1166
1167 new = malloc(sizeof(char*)*len);
1168 if (new == NULL) return 0;
1169
1170 /* If we can't copy everything, free the elements we'll not use. */
1171 if (len < tocopy) {
1172 int j;
1173
1174 for (j = 0; j < tocopy-len; j++) free(history[j]);
1175 tocopy = len;
1176 }
1177 memset(new,0,sizeof(char*)*len);
1178 memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
1179 free(history);
1180 history = new;
1181 }
1182 history_max_len = len;
1183 if (history_len > history_max_len)
1184 history_len = history_max_len;
1185 return 1;
@@ -1186,41 +2701,86 @@
1186 }
1187
1188 /* Save the history in the specified file. On success 0 is returned
1189 * otherwise -1 is returned. */
1190 int linenoiseHistorySave(const char *filename) {
1191 mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
1192 FILE *fp;
1193 int j;
1194
1195 fp = fopen(filename,"w");
1196 umask(old_umask);
1197 if (fp == NULL) return -1;
1198 chmod(filename,S_IRUSR|S_IWUSR);
1199 for (j = 0; j < history_len; j++)
1200 fprintf(fp,"%s\n",history[j]);
1201 fclose(fp);
1202 return 0;
1203 }
1204
1205 /* Load the history from the specified file. If the file does not exist
1206 * zero is returned and no operation is performed.
1207 *
1208 * If the file exists and the operation succeeded 0 is returned, otherwise
1209 * on error -1 is returned. */
1210 int linenoiseHistoryLoad(const char *filename) {
1211 FILE *fp = fopen(filename,"r");
1212 char buf[LINENOISE_MAX_LINE];
1213
1214 if (fp == NULL) return -1;
1215
1216 while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
1217 char *p;
1218
1219 p = strchr(buf,'\r');
1220 if (!p) p = strchr(buf,'\n');
1221 if (p) *p = '\0';
1222 linenoiseHistoryAdd(buf);
1223 }
1224 fclose(fp);
1225 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1226 }
1227
--- extsrc/linenoise.c
+++ extsrc/linenoise.c
@@ -1,19 +1,718 @@
1 #line 1 "utf8.h"
2 #ifndef UTF8_UTIL_H
3 #define UTF8_UTIL_H
4
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8
9 /**
10 * UTF-8 utility functions
11 *
12 * (c) 2010-2019 Steve Bennett <[email protected]>
13 *
14 * See utf8.c for licence details.
15 */
16
17 #ifndef USE_UTF8
18 #include <ctype.h>
19
20 #define MAX_UTF8_LEN 1
21
22 /* No utf-8 support. 1 byte = 1 char */
23 #define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
24 #define utf8_strwidth(S, B) utf8_strlen((S), (B))
25 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
26 #define utf8_index(C, I) (I)
27 #define utf8_charlen(C) 1
28 #define utf8_width(C) 1
29
30 #else
31
32 #define MAX_UTF8_LEN 4
33
34 /**
35 * Converts the given unicode codepoint (0 - 0x1fffff) to utf-8
36 * and stores the result at 'p'.
37 *
38 * Returns the number of utf-8 characters
39 */
40 int utf8_fromunicode(char *p, unsigned uc);
41
42 /**
43 * Returns the length of the utf-8 sequence starting with 'c'.
44 *
45 * Returns 1-4, or -1 if this is not a valid start byte.
46 *
47 * Note that charlen=4 is not supported by the rest of the API.
48 */
49 int utf8_charlen(int c);
50
51 /**
52 * Returns the number of characters in the utf-8
53 * string of the given byte length.
54 *
55 * Any bytes which are not part of an valid utf-8
56 * sequence are treated as individual characters.
57 *
58 * The string *must* be null terminated.
59 *
60 * Does not support unicode code points > \u1fffff
61 */
62 int utf8_strlen(const char *str, int bytelen);
63
64 /**
65 * Calculates the display width of the first 'charlen' characters in 'str'.
66 * See utf8_width()
67 */
68 int utf8_strwidth(const char *str, int charlen);
69
70 /**
71 * Returns the byte index of the given character in the utf-8 string.
72 *
73 * The string *must* be null terminated.
74 *
75 * This will return the byte length of a utf-8 string
76 * if given the char length.
77 */
78 int utf8_index(const char *str, int charindex);
79
80 /**
81 * Returns the unicode codepoint corresponding to the
82 * utf-8 sequence 'str'.
83 *
84 * Stores the result in *uc and returns the number of bytes
85 * consumed.
86 *
87 * If 'str' is null terminated, then an invalid utf-8 sequence
88 * at the end of the string will be returned as individual bytes.
89 *
90 * If it is not null terminated, the length *must* be checked first.
91 *
92 * Does not support unicode code points > \u1fffff
93 */
94 int utf8_tounicode(const char *str, int *uc);
95
96 /**
97 * Returns the width (in characters) of the given unicode codepoint.
98 * This is 1 for normal letters and 0 for combining characters and 2 for wide characters.
99 */
100 int utf8_width(int ch);
101
102 #endif
103
104 #ifdef __cplusplus
105 }
106 #endif
107
108 #endif
109 #line 1 "utf8.c"
110 /**
111 * UTF-8 utility functions
112 *
113 * (c) 2010-2019 Steve Bennett <[email protected]>
114 *
115 * All rights reserved.
116 *
117 * Redistribution and use in source and binary forms, with or without
118 * modification, are permitted provided that the following conditions are met:
119 *
120 * * Redistributions of source code must retain the above copyright notice,
121 * this list of conditions and the following disclaimer.
122 *
123 * * Redistributions in binary form must reproduce the above copyright notice,
124 * this list of conditions and the following disclaimer in the documentation
125 * and/or other materials provided with the distribution.
126 *
127 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
128 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
129 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
130 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
131 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
132 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
133 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
134 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
135 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
136 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
137 */
138
139 #include <ctype.h>
140 #include <stdlib.h>
141 #include <string.h>
142 #include <stdio.h>
143 #ifndef UTF8_UTIL_H
144 #include "utf8.h"
145 #endif
146
147 #ifdef USE_UTF8
148 int utf8_fromunicode(char *p, unsigned uc)
149 {
150 if (uc <= 0x7f) {
151 *p = uc;
152 return 1;
153 }
154 else if (uc <= 0x7ff) {
155 *p++ = 0xc0 | ((uc & 0x7c0) >> 6);
156 *p = 0x80 | (uc & 0x3f);
157 return 2;
158 }
159 else if (uc <= 0xffff) {
160 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
161 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
162 *p = 0x80 | (uc & 0x3f);
163 return 3;
164 }
165 /* Note: We silently truncate to 21 bits here: 0x1fffff */
166 else {
167 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
168 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
169 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
170 *p = 0x80 | (uc & 0x3f);
171 return 4;
172 }
173 }
174
175 int utf8_charlen(int c)
176 {
177 if ((c & 0x80) == 0) {
178 return 1;
179 }
180 if ((c & 0xe0) == 0xc0) {
181 return 2;
182 }
183 if ((c & 0xf0) == 0xe0) {
184 return 3;
185 }
186 if ((c & 0xf8) == 0xf0) {
187 return 4;
188 }
189 /* Invalid sequence */
190 return -1;
191 }
192
193 int utf8_strlen(const char *str, int bytelen)
194 {
195 int charlen = 0;
196 if (bytelen < 0) {
197 bytelen = strlen(str);
198 }
199 while (bytelen > 0) {
200 int c;
201 int l = utf8_tounicode(str, &c);
202 charlen++;
203 str += l;
204 bytelen -= l;
205 }
206 return charlen;
207 }
208
209 int utf8_strwidth(const char *str, int charlen)
210 {
211 int width = 0;
212 while (charlen) {
213 int c;
214 int l = utf8_tounicode(str, &c);
215 width += utf8_width(c);
216 str += l;
217 charlen--;
218 }
219 return width;
220 }
221
222 int utf8_index(const char *str, int index)
223 {
224 const char *s = str;
225 while (index--) {
226 int c;
227 s += utf8_tounicode(s, &c);
228 }
229 return s - str;
230 }
231
232 int utf8_tounicode(const char *str, int *uc)
233 {
234 unsigned const char *s = (unsigned const char *)str;
235
236 if (s[0] < 0xc0) {
237 *uc = s[0];
238 return 1;
239 }
240 if (s[0] < 0xe0) {
241 if ((s[1] & 0xc0) == 0x80) {
242 *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80);
243 if (*uc >= 0x80) {
244 return 2;
245 }
246 /* Otherwise this is an invalid sequence */
247 }
248 }
249 else if (s[0] < 0xf0) {
250 if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) {
251 *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80);
252 if (*uc >= 0x800) {
253 return 3;
254 }
255 /* Otherwise this is an invalid sequence */
256 }
257 }
258 else if (s[0] < 0xf8) {
259 if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80) && ((str[3] & 0xc0) == 0x80)) {
260 *uc = ((s[0] & ~0xf0) << 18) | ((s[1] & ~0x80) << 12) | ((s[2] & ~0x80) << 6) | (s[3] & ~0x80);
261 if (*uc >= 0x10000) {
262 return 4;
263 }
264 /* Otherwise this is an invalid sequence */
265 }
266 }
267
268 /* Invalid sequence, so just return the byte */
269 *uc = *s;
270 return 1;
271 }
272
273 struct utf8range {
274 int lower; /* lower inclusive */
275 int upper; /* upper exclusive */
276 };
277
278 /* From http://unicode.org/Public/UNIDATA/UnicodeData.txt */
279 static const struct utf8range unicode_range_combining[] = {
280 { 0x0300, 0x0370 }, { 0x0483, 0x048a }, { 0x0591, 0x05d0 }, { 0x0610, 0x061b },
281 { 0x064b, 0x0660 }, { 0x0670, 0x0671 }, { 0x06d6, 0x06dd }, { 0x06df, 0x06e5 },
282 { 0x06e7, 0x06ee }, { 0x0711, 0x0712 }, { 0x0730, 0x074d }, { 0x07a6, 0x07b1 },
283 { 0x07eb, 0x07f4 }, { 0x0816, 0x0830 }, { 0x0859, 0x085e }, { 0x08d4, 0x0904 },
284 { 0x093a, 0x0958 }, { 0x0962, 0x0964 }, { 0x0981, 0x0985 }, { 0x09bc, 0x09ce },
285 { 0x09d7, 0x09dc }, { 0x09e2, 0x09e6 }, { 0x0a01, 0x0a05 }, { 0x0a3c, 0x0a59 },
286 { 0x0a70, 0x0a72 }, { 0x0a75, 0x0a85 }, { 0x0abc, 0x0ad0 }, { 0x0ae2, 0x0ae6 },
287 { 0x0afa, 0x0b05 }, { 0x0b3c, 0x0b5c }, { 0x0b62, 0x0b66 }, { 0x0b82, 0x0b83 },
288 { 0x0bbe, 0x0bd0 }, { 0x0bd7, 0x0be6 }, { 0x0c00, 0x0c05 }, { 0x0c3e, 0x0c58 },
289 { 0x0c62, 0x0c66 }, { 0x0c81, 0x0c85 }, { 0x0cbc, 0x0cde }, { 0x0ce2, 0x0ce6 },
290 { 0x0d00, 0x0d05 }, { 0x0d3b, 0x0d4e }, { 0x0d57, 0x0d58 }, { 0x0d62, 0x0d66 },
291 { 0x0d82, 0x0d85 }, { 0x0dca, 0x0de6 }, { 0x0df2, 0x0df4 }, { 0x0e31, 0x0e32 },
292 { 0x0e34, 0x0e3f }, { 0x0e47, 0x0e4f }, { 0x0eb1, 0x0eb2 }, { 0x0eb4, 0x0ebd },
293 { 0x0ec8, 0x0ed0 }, { 0x0f18, 0x0f1a }, { 0x0f35, 0x0f3a }, { 0x0f3e, 0x0f40 },
294 { 0x0f71, 0x0f88 }, { 0x0f8d, 0x0fbe }, { 0x0fc6, 0x0fc7 }, { 0x102b, 0x103f },
295 { 0x1056, 0x105a }, { 0x105e, 0x1065 }, { 0x1067, 0x106e }, { 0x1071, 0x1075 },
296 { 0x1082, 0x1090 }, { 0x109a, 0x109e }, { 0x135d, 0x1360 }, { 0x1712, 0x1720 },
297 { 0x1732, 0x1735 }, { 0x1752, 0x1760 }, { 0x1772, 0x1780 }, { 0x17b4, 0x17d4 },
298 { 0x17dd, 0x17e0 }, { 0x180b, 0x180e }, { 0x1885, 0x1887 }, { 0x18a9, 0x18aa },
299 { 0x1920, 0x1940 }, { 0x1a17, 0x1a1e }, { 0x1a55, 0x1a80 }, { 0x1ab0, 0x1b05 },
300 { 0x1b34, 0x1b45 }, { 0x1b6b, 0x1b74 }, { 0x1b80, 0x1b83 }, { 0x1ba1, 0x1bae },
301 { 0x1be6, 0x1bfc }, { 0x1c24, 0x1c3b }, { 0x1cd0, 0x1ce9 }, { 0x1ced, 0x1cee },
302 { 0x1cf2, 0x1cf5 }, { 0x1cf7, 0x1d00 }, { 0x1dc0, 0x1e00 }, { 0x20d0, 0x2100 },
303 { 0x2cef, 0x2cf2 }, { 0x2d7f, 0x2d80 }, { 0x2de0, 0x2e00 }, { 0x302a, 0x3030 },
304 { 0x3099, 0x309b }, { 0xa66f, 0xa67e }, { 0xa69e, 0xa6a0 }, { 0xa6f0, 0xa6f2 },
305 { 0xa802, 0xa803 }, { 0xa806, 0xa807 }, { 0xa80b, 0xa80c }, { 0xa823, 0xa828 },
306 { 0xa880, 0xa882 }, { 0xa8b4, 0xa8ce }, { 0xa8e0, 0xa8f2 }, { 0xa926, 0xa92e },
307 { 0xa947, 0xa95f }, { 0xa980, 0xa984 }, { 0xa9b3, 0xa9c1 }, { 0xa9e5, 0xa9e6 },
308 { 0xaa29, 0xaa40 }, { 0xaa43, 0xaa44 }, { 0xaa4c, 0xaa50 }, { 0xaa7b, 0xaa7e },
309 { 0xaab0, 0xaab5 }, { 0xaab7, 0xaab9 }, { 0xaabe, 0xaac2 }, { 0xaaeb, 0xaaf0 },
310 { 0xaaf5, 0xab01 }, { 0xabe3, 0xabf0 }, { 0xfb1e, 0xfb1f }, { 0xfe00, 0xfe10 },
311 { 0xfe20, 0xfe30 },
312 };
313
314 /* From http://unicode.org/Public/UNIDATA/EastAsianWidth.txt */
315 static const struct utf8range unicode_range_wide[] = {
316 { 0x1100, 0x115f }, { 0x231a, 0x231b }, { 0x2329, 0x232a }, { 0x23e9, 0x23ec },
317 { 0x23f0, 0x23f0 }, { 0x23f3, 0x23f3 }, { 0x25fd, 0x25fe }, { 0x2614, 0x2615 },
318 { 0x2648, 0x2653 }, { 0x267f, 0x267f }, { 0x2693, 0x2693 }, { 0x26a1, 0x26a1 },
319 { 0x26aa, 0x26ab }, { 0x26bd, 0x26be }, { 0x26c4, 0x26c5 }, { 0x26ce, 0x26ce },
320 { 0x26d4, 0x26d4 }, { 0x26ea, 0x26ea }, { 0x26f2, 0x26f3 }, { 0x26f5, 0x26f5 },
321 { 0x26fa, 0x26fa }, { 0x26fd, 0x26fd }, { 0x2705, 0x2705 }, { 0x270a, 0x270b },
322 { 0x2728, 0x2728 }, { 0x274c, 0x274c }, { 0x274e, 0x274e }, { 0x2753, 0x2755 },
323 { 0x2757, 0x2757 }, { 0x2795, 0x2797 }, { 0x27b0, 0x27b0 }, { 0x27bf, 0x27bf },
324 { 0x2b1b, 0x2b1c }, { 0x2b50, 0x2b50 }, { 0x2b55, 0x2b55 }, { 0x2e80, 0x2e99 },
325 { 0x2e9b, 0x2ef3 }, { 0x2f00, 0x2fd5 }, { 0x2ff0, 0x2ffb }, { 0x3001, 0x303e },
326 { 0x3041, 0x3096 }, { 0x3099, 0x30ff }, { 0x3105, 0x312e }, { 0x3131, 0x318e },
327 { 0x3190, 0x31ba }, { 0x31c0, 0x31e3 }, { 0x31f0, 0x321e }, { 0x3220, 0x3247 },
328 { 0x3250, 0x32fe }, { 0x3300, 0x4dbf }, { 0x4e00, 0xa48c }, { 0xa490, 0xa4c6 },
329 { 0xa960, 0xa97c }, { 0xac00, 0xd7a3 }, { 0xf900, 0xfaff }, { 0xfe10, 0xfe19 },
330 { 0xfe30, 0xfe52 }, { 0xfe54, 0xfe66 }, { 0xfe68, 0xfe6b }, { 0x16fe0, 0x16fe1 },
331 { 0x17000, 0x187ec }, { 0x18800, 0x18af2 }, { 0x1b000, 0x1b11e }, { 0x1b170, 0x1b2fb },
332 { 0x1f004, 0x1f004 }, { 0x1f0cf, 0x1f0cf }, { 0x1f18e, 0x1f18e }, { 0x1f191, 0x1f19a },
333 { 0x1f200, 0x1f202 }, { 0x1f210, 0x1f23b }, { 0x1f240, 0x1f248 }, { 0x1f250, 0x1f251 },
334 { 0x1f260, 0x1f265 }, { 0x1f300, 0x1f320 }, { 0x1f32d, 0x1f335 }, { 0x1f337, 0x1f37c },
335 { 0x1f37e, 0x1f393 }, { 0x1f3a0, 0x1f3ca }, { 0x1f3cf, 0x1f3d3 }, { 0x1f3e0, 0x1f3f0 },
336 { 0x1f3f4, 0x1f3f4 }, { 0x1f3f8, 0x1f43e }, { 0x1f440, 0x1f440 }, { 0x1f442, 0x1f4fc },
337 { 0x1f4ff, 0x1f53d }, { 0x1f54b, 0x1f54e }, { 0x1f550, 0x1f567 }, { 0x1f57a, 0x1f57a },
338 { 0x1f595, 0x1f596 }, { 0x1f5a4, 0x1f5a4 }, { 0x1f5fb, 0x1f64f }, { 0x1f680, 0x1f6c5 },
339 { 0x1f6cc, 0x1f6cc }, { 0x1f6d0, 0x1f6d2 }, { 0x1f6eb, 0x1f6ec }, { 0x1f6f4, 0x1f6f8 },
340 { 0x1f910, 0x1f93e }, { 0x1f940, 0x1f94c }, { 0x1f950, 0x1f96b }, { 0x1f980, 0x1f997 },
341 { 0x1f9c0, 0x1f9c0 }, { 0x1f9d0, 0x1f9e6 }, { 0x20000, 0x2fffd }, { 0x30000, 0x3fffd },
342 };
343
344 #define ARRAYSIZE(A) sizeof(A) / sizeof(*(A))
345
346 static int cmp_range(const void *key, const void *cm)
347 {
348 const struct utf8range *range = (const struct utf8range *)cm;
349 int ch = *(int *)key;
350 if (ch < range->lower) {
351 return -1;
352 }
353 if (ch >= range->upper) {
354 return 1;
355 }
356 return 0;
357 }
358
359 static int utf8_in_range(const struct utf8range *range, int num, int ch)
360 {
361 const struct utf8range *r =
362 bsearch(&ch, range, num, sizeof(*range), cmp_range);
363
364 if (r) {
365 return 1;
366 }
367 return 0;
368 }
369
370 int utf8_width(int ch)
371 {
372 /* short circuit for common case */
373 if (isascii(ch)) {
374 return 1;
375 }
376 if (utf8_in_range(unicode_range_combining, ARRAYSIZE(unicode_range_combining), ch)) {
377 return 0;
378 }
379 if (utf8_in_range(unicode_range_wide, ARRAYSIZE(unicode_range_wide), ch)) {
380 return 2;
381 }
382 return 1;
383 }
384 #endif
385 #line 1 "stringbuf.h"
386 #ifndef STRINGBUF_H
387 #define STRINGBUF_H
388 /**
389 * resizable string buffer
390 *
391 * (c) 2017-2020 Steve Bennett <[email protected]>
392 *
393 * See utf8.c for licence details.
394 */
395 #ifdef __cplusplus
396 extern "C" {
397 #endif
398
399 /** @file
400 * A stringbuf is a resizing, null terminated string buffer.
401 *
402 * The buffer is reallocated as necessary.
403 *
404 * In general it is *not* OK to call these functions with a NULL pointer
405 * unless stated otherwise.
406 *
407 * If USE_UTF8 is defined, supports utf8.
408 */
409
410 /**
411 * The stringbuf structure should not be accessed directly.
412 * Use the functions below.
413 */
414 typedef struct {
415 int remaining; /**< Allocated, but unused space */
416 int last; /**< Index of the null terminator (and thus the length of the string) */
417 #ifdef USE_UTF8
418 int chars; /**< Count of characters */
419 #endif
420 char *data; /**< Allocated memory containing the string or NULL for empty */
421 } stringbuf;
422
423 /**
424 * Allocates and returns a new stringbuf with no elements.
425 */
426 stringbuf *sb_alloc(void);
427
428 /**
429 * Frees a stringbuf.
430 * It is OK to call this with NULL.
431 */
432 void sb_free(stringbuf *sb);
433
434 /**
435 * Returns an allocated copy of the stringbuf
436 */
437 stringbuf *sb_copy(stringbuf *sb);
438
439 /**
440 * Returns the byte length of the buffer.
441 *
442 * Returns 0 for both a NULL buffer and an empty buffer.
443 */
444 static inline int sb_len(stringbuf *sb) {
445 return sb->last;
446 }
447
448 /**
449 * Returns the utf8 character length of the buffer.
450 *
451 * Returns 0 for both a NULL buffer and an empty buffer.
452 */
453 static inline int sb_chars(stringbuf *sb) {
454 #ifdef USE_UTF8
455 return sb->chars;
456 #else
457 return sb->last;
458 #endif
459 }
460
461 /**
462 * Appends a null terminated string to the stringbuf
463 */
464 void sb_append(stringbuf *sb, const char *str);
465
466 /**
467 * Like sb_append() except does not require a null terminated string.
468 * The length of 'str' is given as 'len'
469 *
470 * Note that in utf8 mode, characters will *not* be counted correctly
471 * if a partial utf8 sequence is added with sb_append_len()
472 */
473 void sb_append_len(stringbuf *sb, const char *str, int len);
474
475 /**
476 * Returns a pointer to the null terminated string in the buffer.
477 *
478 * Note this pointer only remains valid until the next modification to the
479 * string buffer.
480 *
481 * The returned pointer can be used to update the buffer in-place
482 * as long as care is taken to not overwrite the end of the buffer.
483 */
484 static inline char *sb_str(const stringbuf *sb)
485 {
486 return sb->data;
487 }
488
489 /**
490 * Inserts the given string *before* (zero-based) byte 'index' in the stringbuf.
491 * If index is past the end of the buffer, the string is appended,
492 * just like sb_append()
493 */
494 void sb_insert(stringbuf *sb, int index, const char *str);
495
496 /**
497 * Delete 'len' bytes in the string at the given index.
498 *
499 * Any bytes past the end of the buffer are ignored.
500 * The buffer remains null terminated.
501 *
502 * If len is -1, deletes to the end of the buffer.
503 */
504 void sb_delete(stringbuf *sb, int index, int len);
505
506 /**
507 * Clear to an empty buffer.
508 */
509 void sb_clear(stringbuf *sb);
510
511 /**
512 * Return an allocated copy of buffer and frees 'sb'.
513 *
514 * If 'sb' is empty, returns an allocated copy of "".
515 */
516 char *sb_to_string(stringbuf *sb);
517
518 #ifdef __cplusplus
519 }
520 #endif
521
522 #endif
523 #line 1 "stringbuf.c"
524 /**
525 * resizable string buffer
526 *
527 * (c) 2017-2020 Steve Bennett <[email protected]>
528 *
529 * See utf8.c for licence details.
530 */
531 #include <stdlib.h>
532 #include <string.h>
533 #include <stdio.h>
534 #include <ctype.h>
535 #include <assert.h>
536
537 #ifndef STRINGBUF_H
538 #include "stringbuf.h"
539 #endif
540 #ifdef USE_UTF8
541 #ifndef UTF8_UTIL_H
542 #include "utf8.h"
543 #endif
544 #endif
545
546 #define SB_INCREMENT 200
547
548 stringbuf *sb_alloc(void)
549 {
550 stringbuf *sb = (stringbuf *)malloc(sizeof(*sb));
551 sb->remaining = 0;
552 sb->last = 0;
553 #ifdef USE_UTF8
554 sb->chars = 0;
555 #endif
556 sb->data = NULL;
557
558 return(sb);
559 }
560
561 void sb_free(stringbuf *sb)
562 {
563 if (sb) {
564 free(sb->data);
565 }
566 free(sb);
567 }
568
569 static void sb_realloc(stringbuf *sb, int newlen)
570 {
571 sb->data = (char *)realloc(sb->data, newlen);
572 sb->remaining = newlen - sb->last;
573 }
574
575 void sb_append(stringbuf *sb, const char *str)
576 {
577 sb_append_len(sb, str, strlen(str));
578 }
579
580 void sb_append_len(stringbuf *sb, const char *str, int len)
581 {
582 if (sb->remaining < len + 1) {
583 sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
584 }
585 memcpy(sb->data + sb->last, str, len);
586 sb->data[sb->last + len] = 0;
587
588 sb->last += len;
589 sb->remaining -= len;
590 #ifdef USE_UTF8
591 sb->chars += utf8_strlen(str, len);
592 #endif
593 }
594
595 char *sb_to_string(stringbuf *sb)
596 {
597 if (sb->data == NULL) {
598 /* Return an allocated empty string, not null */
599 return strdup("");
600 }
601 else {
602 /* Just return the data and free the stringbuf structure */
603 char *pt = sb->data;
604 free(sb);
605 return pt;
606 }
607 }
608
609 /* Insert and delete operations */
610
611 /* Moves up all the data at position 'pos' and beyond by 'len' bytes
612 * to make room for new data
613 *
614 * Note: Does *not* update sb->chars
615 */
616 static void sb_insert_space(stringbuf *sb, int pos, int len)
617 {
618 assert(pos <= sb->last);
619
620 /* Make sure there is enough space */
621 if (sb->remaining < len) {
622 sb_realloc(sb, sb->last + len + SB_INCREMENT);
623 }
624 /* Now move it up */
625 memmove(sb->data + pos + len, sb->data + pos, sb->last - pos);
626 sb->last += len;
627 sb->remaining -= len;
628 /* And null terminate */
629 sb->data[sb->last] = 0;
630 }
631
632 /**
633 * Move down all the data from pos + len, effectively
634 * deleting the data at position 'pos' of length 'len'
635 */
636 static void sb_delete_space(stringbuf *sb, int pos, int len)
637 {
638 assert(pos < sb->last);
639 assert(pos + len <= sb->last);
640
641 #ifdef USE_UTF8
642 sb->chars -= utf8_strlen(sb->data + pos, len);
643 #endif
644
645 /* Now move it up */
646 memmove(sb->data + pos, sb->data + pos + len, sb->last - pos - len);
647 sb->last -= len;
648 sb->remaining += len;
649 /* And null terminate */
650 sb->data[sb->last] = 0;
651 }
652
653 void sb_insert(stringbuf *sb, int index, const char *str)
654 {
655 if (index >= sb->last) {
656 /* Inserting after the end of the list appends. */
657 sb_append(sb, str);
658 }
659 else {
660 int len = strlen(str);
661
662 sb_insert_space(sb, index, len);
663 memcpy(sb->data + index, str, len);
664 #ifdef USE_UTF8
665 sb->chars += utf8_strlen(str, len);
666 #endif
667 }
668 }
669
670 /**
671 * Delete the bytes at index 'index' for length 'len'
672 * Has no effect if the index is past the end of the list.
673 */
674 void sb_delete(stringbuf *sb, int index, int len)
675 {
676 if (index < sb->last) {
677 char *pos = sb->data + index;
678 if (len < 0) {
679 len = sb->last;
680 }
681
682 sb_delete_space(sb, pos - sb->data, len);
683 }
684 }
685
686 void sb_clear(stringbuf *sb)
687 {
688 if (sb->data) {
689 /* Null terminate */
690 sb->data[0] = 0;
691 sb->last = 0;
692 #ifdef USE_UTF8
693 sb->chars = 0;
694 #endif
695 }
696 }
697 #line 1 "linenoise.c"
698 /* linenoise.c -- guerrilla line editing library against the idea that a
699 * line editing lib needs to be 20,000 lines of C code.
700 *
701 * You can find the latest source code at:
702 *
703 * http://github.com/msteveb/linenoise
704 * (forked from http://github.com/antirez/linenoise)
705 *
706 * Does a number of crazy assumptions that happen to be true in 99.9999% of
707 * the 2010 UNIX computers around.
708 *
709 * ------------------------------------------------------------------------
710 *
711 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
712 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
713 * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
714 *
715 * All rights reserved.
716 *
717 * Redistribution and use in source and binary forms, with or without
718 * modification, are permitted provided that the following conditions are
@@ -42,211 +741,381 @@
741 *
742 * References:
743 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
744 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
745 *
 
 
 
 
746 * Bloat:
747 * - Completion?
748 *
749 * Unix/termios
750 * ------------
751 * List of escape sequences used by this program, we do everything just
752 * a few sequences. In order to be so cheap we may have some
753 * flickering effect with some slow terminal, but the lesser sequences
754 * the more compatible.
755 *
756 * EL (Erase Line)
757 * Sequence: ESC [ 0 K
758 * Effect: clear from cursor to end of line
 
 
759 *
760 * CUF (CUrsor Forward)
761 * Sequence: ESC [ n C
762 * Effect: moves cursor forward n chars
763 *
764 * CR (Carriage Return)
765 * Sequence: \r
766 * Effect: moves cursor to column 1
767 *
768 * The following are used to clear the screen: ESC [ H ESC [ 2 J
769 * This is actually composed of two sequences:
770 *
771 * cursorhome
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
772 * Sequence: ESC [ H
773 * Effect: moves the cursor to upper left corner
774 *
775 * ED2 (Clear entire screen)
776 * Sequence: ESC [ 2 J
777 * Effect: clear the whole screen
778 *
779 * == For highlighting control characters, we also use the following two ==
780 * SO (enter StandOut)
781 * Sequence: ESC [ 7 m
782 * Effect: Uses some standout mode such as reverse video
783 *
784 * SE (Standout End)
785 * Sequence: ESC [ 0 m
786 * Effect: Exit standout mode
787 *
788 * == Only used if TIOCGWINSZ fails ==
789 * DSR/CPR (Report cursor position)
790 * Sequence: ESC [ 6 n
791 * Effect: reports current cursor position as ESC [ NNN ; MMM R
792 *
793 * == Only used in multiline mode ==
794 * CUU (Cursor Up)
795 * Sequence: ESC [ n A
796 * Effect: moves cursor up n chars.
797 *
798 * CUD (Cursor Down)
799 * Sequence: ESC [ n B
800 * Effect: moves cursor down n chars.
801 *
802 * win32/console
803 * -------------
804 * If __MINGW32__ is defined, the win32 console API is used.
805 * This could probably be made to work for the msvc compiler too.
806 * This support based in part on work by Jon Griffiths.
807 */
808
809 #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
810 #include <windows.h>
811 #include <fcntl.h>
812 #define USE_WINCONSOLE
813 #ifdef __MINGW32__
814 #define HAVE_UNISTD_H
815 #endif
816 #else
817 #include <termios.h>
818 #include <sys/ioctl.h>
819 #include <poll.h>
820 #define USE_TERMIOS
821 #define HAVE_UNISTD_H
822 #endif
823
824 #ifdef HAVE_UNISTD_H
825 #include <unistd.h>
826 #endif
827 #include <stdlib.h>
828 #include <stdarg.h>
829 #include <stdio.h>
830 #include <assert.h>
831 #include <errno.h>
832 #include <string.h>
833 #include <signal.h>
834 #include <stdlib.h>
 
 
835 #include <sys/types.h>
836
837 #if defined(_WIN32) && !defined(__MINGW32__)
838 /* Microsoft headers don't like old POSIX names */
839 #define strdup _strdup
840 #define snprintf _snprintf
841 #endif
842
843 #include "linenoise.h"
844 #ifndef STRINGBUF_H
845 #include "stringbuf.h"
846 #endif
847 #ifndef UTF8_UTIL_H
848 #include "utf8.h"
849 #endif
850
851 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
852
853 /* ctrl('A') -> 0x01 */
854 #define ctrl(C) ((C) - '@')
855 /* meta('a') -> 0xe1 */
856 #define meta(C) ((C) | 0x80)
857
858 /* Use -ve numbers here to co-exist with normal unicode chars */
859 enum {
860 SPECIAL_NONE,
861 /* don't use -1 here since that indicates error */
862 SPECIAL_UP = -20,
863 SPECIAL_DOWN = -21,
864 SPECIAL_LEFT = -22,
865 SPECIAL_RIGHT = -23,
866 SPECIAL_DELETE = -24,
867 SPECIAL_HOME = -25,
868 SPECIAL_END = -26,
869 SPECIAL_INSERT = -27,
870 SPECIAL_PAGE_UP = -28,
871 SPECIAL_PAGE_DOWN = -29,
872
873 /* Some handy names for other special keycodes */
874 CHAR_ESCAPE = 27,
875 CHAR_DELETE = 127,
876 };
877
878 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
879 static int history_len = 0;
880 static int history_index = 0;
881 static char **history = NULL;
882
883 /* Structure to contain the status of the current (being edited) line */
884 struct current {
885 stringbuf *buf; /* Current buffer. Always null terminated */
886 int pos; /* Cursor position, measured in chars */
887 int cols; /* Size of the window, in chars */
888 int nrows; /* How many rows are being used in multiline mode (>= 1) */
889 int rpos; /* The current row containing the cursor - multiline mode only */
890 int colsright; /* refreshLine() cached cols for insert_char() optimisation */
891 int colsleft; /* refreshLine() cached cols for remove_char() optimisation */
892 const char *prompt;
893 stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
894 stringbuf *output; /* used only during refreshLine() - output accumulator */
895 #if defined(USE_TERMIOS)
896 int fd; /* Terminal fd */
897 #elif defined(USE_WINCONSOLE)
898 HANDLE outh; /* Console output handle */
899 HANDLE inh; /* Console input handle */
900 int rows; /* Screen rows */
901 int x; /* Current column during output */
902 int y; /* Current row */
903 #ifdef USE_UTF8
904 #define UBUF_MAX_CHARS 132
905 WORD ubuf[UBUF_MAX_CHARS + 1]; /* Accumulates utf16 output - one extra for final surrogate pairs */
906 int ubuflen; /* length used in ubuf */
907 int ubufcols; /* how many columns are represented by the chars in ubuf? */
908 #endif
909 #endif
910 };
911
912 static int fd_read(struct current *current);
913 static int getWindowSize(struct current *current);
914 static void cursorDown(struct current *current, int n);
915 static void cursorUp(struct current *current, int n);
916 static void eraseEol(struct current *current);
917 static void refreshLine(struct current *current);
918 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
919 static void setCursorPos(struct current *current, int x);
920 static void setOutputHighlight(struct current *current, const int *props, int nprops);
921 static void set_current(struct current *current, const char *str);
922
923 static int fd_isatty(struct current *current)
924 {
925 #ifdef USE_TERMIOS
926 return isatty(current->fd);
927 #else
928 (void)current;
929 return 0;
930 #endif
931 }
932
933 void linenoiseHistoryFree(void) {
934 if (history) {
935 int j;
936
937 for (j = 0; j < history_len; j++)
938 free(history[j]);
939 free(history);
940 history = NULL;
941 history_len = 0;
942 }
943 }
944
945 typedef enum {
946 EP_START, /* looking for ESC */
947 EP_ESC, /* looking for [ */
948 EP_DIGITS, /* parsing digits */
949 EP_PROPS, /* parsing digits or semicolons */
950 EP_END, /* ok */
951 EP_ERROR, /* error */
952 } ep_state_t;
953
954 struct esc_parser {
955 ep_state_t state;
956 int props[5]; /* properties are stored here */
957 int maxprops; /* size of the props[] array */
958 int numprops; /* number of properties found */
959 int termchar; /* terminator char, or 0 for any alpha */
960 int current; /* current (partial) property value */
961 };
962
963 /**
964 * Initialise the escape sequence parser at *parser.
965 *
966 * If termchar is 0 any alpha char terminates ok. Otherwise only the given
967 * char terminates successfully.
968 * Run the parser state machine with calls to parseEscapeSequence() for each char.
969 */
970 static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
971 {
972 parser->state = EP_START;
973 parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
974 parser->numprops = 0;
975 parser->current = 0;
976 parser->termchar = termchar;
977 }
978
979 /**
980 * Pass character 'ch' into the state machine to parse:
981 * 'ESC' '[' <digits> (';' <digits>)* <termchar>
982 *
983 * The first character must be ESC.
984 * Returns the current state. The state machine is done when it returns either EP_END
985 * or EP_ERROR.
986 *
987 * On EP_END, the "property/attribute" values can be read from parser->props[]
988 * of length parser->numprops.
989 */
990 static int parseEscapeSequence(struct esc_parser *parser, int ch)
991 {
992 switch (parser->state) {
993 case EP_START:
994 parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
995 break;
996 case EP_ESC:
997 parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
998 break;
999 case EP_PROPS:
1000 if (ch == ';') {
1001 parser->state = EP_DIGITS;
1002 donedigits:
1003 if (parser->numprops + 1 < parser->maxprops) {
1004 parser->props[parser->numprops++] = parser->current;
1005 parser->current = 0;
1006 }
1007 break;
1008 }
1009 /* fall through */
1010 case EP_DIGITS:
1011 if (ch >= '0' && ch <= '9') {
1012 parser->current = parser->current * 10 + (ch - '0');
1013 parser->state = EP_PROPS;
1014 break;
1015 }
1016 /* must be terminator */
1017 if (parser->termchar != ch) {
1018 if (parser->termchar != 0 || !((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))) {
1019 parser->state = EP_ERROR;
1020 break;
1021 }
1022 }
1023 parser->state = EP_END;
1024 goto donedigits;
1025 case EP_END:
1026 parser->state = EP_ERROR;
1027 break;
1028 case EP_ERROR:
1029 break;
1030 }
1031 return parser->state;
1032 }
1033
1034 /*#define DEBUG_REFRESHLINE*/
1035
1036 #ifdef DEBUG_REFRESHLINE
1037 #define DRL(ARGS...) fprintf(dfh, ARGS)
1038 static FILE *dfh;
1039
1040 static void DRL_CHAR(int ch)
1041 {
1042 if (ch < ' ') {
1043 DRL("^%c", ch + '@');
1044 }
1045 else if (ch > 127) {
1046 DRL("\\u%04x", ch);
1047 }
1048 else {
1049 DRL("%c", ch);
1050 }
1051 }
1052 static void DRL_STR(const char *str)
1053 {
1054 while (*str) {
1055 int ch;
1056 int n = utf8_tounicode(str, &ch);
1057 str += n;
1058 DRL_CHAR(ch);
1059 }
1060 }
1061 #else
1062 #define DRL(...)
1063 #define DRL_CHAR(ch)
1064 #define DRL_STR(str)
1065 #endif
1066
1067 #if defined(USE_WINCONSOLE)
1068 #include "linenoise-win32.c"
1069 #endif
1070
1071 #if defined(USE_TERMIOS)
1072 static void linenoiseAtExit(void);
1073 static struct termios orig_termios; /* in order to restore at exit */
1074 static int rawmode = 0; /* for atexit() function to check if restore is needed*/
1075 static int atexit_registered = 0; /* register atexit just 1 time */
1076
1077 static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
1078
1079 static int isUnsupportedTerm(void) {
1080 char *term = getenv("TERM");
1081
1082 if (term) {
1083 int j;
1084 for (j = 0; unsupported_term[j]; j++) {
1085 if (strcmp(term, unsupported_term[j]) == 0) {
1086 return 1;
1087 }
1088 }
1089 }
1090 return 0;
1091 }
1092
1093 static int enableRawMode(struct current *current) {
1094 struct termios raw;
1095
1096 current->fd = STDIN_FILENO;
1097 current->cols = 0;
1098
1099 if (!isatty(current->fd) || isUnsupportedTerm() ||
1100 tcgetattr(current->fd, &orig_termios) == -1) {
1101 fatal:
1102 errno = ENOTTY;
1103 return -1;
1104 }
1105
1106 if (!atexit_registered) {
1107 atexit(linenoiseAtExit);
1108 atexit_registered = 1;
1109 }
 
1110
1111 raw = orig_termios; /* modify the original mode */
1112 /* input modes: no break, no CR to NL, no parity check, no strip char,
1113 * no start/stop output control. */
1114 raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
1115 /* output modes - actually, no need to disable post processing */
1116 /*raw.c_oflag &= ~(OPOST);*/
1117 /* control modes - set 8 bit chars */
1118 raw.c_cflag |= (CS8);
1119 /* local modes - choing off, canonical off, no extended functions,
1120 * no signal chars (^Z,^C) */
1121 raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
@@ -253,163 +1122,452 @@
1122 /* control chars - set return condition: min number of bytes and timer.
1123 * We want read to return every single byte, without timeout. */
1124 raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
1125
1126 /* put terminal in raw mode after flushing */
1127 if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
1128 goto fatal;
1129 }
1130 rawmode = 1;
1131 return 0;
 
 
 
 
1132 }
1133
1134 static void disableRawMode(struct current *current) {
1135 /* Don't even check the return value as it's too late. */
1136 if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
1137 rawmode = 0;
1138 }
1139
1140 /* At exit we'll try to fix the terminal to the initial conditions. */
1141 static void linenoiseAtExit(void) {
1142 if (rawmode) {
1143 tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
1144 }
1145 linenoiseHistoryFree();
1146 }
1147
1148 /* gcc/glibc insists that we care about the return code of write!
1149 * Clarification: This means that a void-cast like "(void) (EXPR)"
1150 * does not work.
1151 */
1152 #define IGNORE_RC(EXPR) if (EXPR) {}
1153
1154 /**
1155 * Output bytes directly, or accumulate output (if current->output is set)
1156 */
1157 static void outputChars(struct current *current, const char *buf, int len)
1158 {
1159 if (len < 0) {
1160 len = strlen(buf);
1161 }
1162 if (current->output) {
1163 sb_append_len(current->output, buf, len);
1164 }
1165 else {
1166 IGNORE_RC(write(current->fd, buf, len));
1167 }
1168 }
1169
1170 /* Like outputChars, but using printf-style formatting
1171 */
1172 static void outputFormatted(struct current *current, const char *format, ...)
1173 {
1174 va_list args;
1175 char buf[64];
1176 int n;
1177
1178 va_start(args, format);
1179 n = vsnprintf(buf, sizeof(buf), format, args);
1180 /* This will never happen because we are sure to use outputFormatted() only for short sequences */
1181 assert(n < (int)sizeof(buf));
1182 va_end(args);
1183 outputChars(current, buf, n);
1184 }
1185
1186 static void cursorToLeft(struct current *current)
1187 {
1188 outputChars(current, "\r", -1);
1189 }
1190
1191 static void setOutputHighlight(struct current *current, const int *props, int nprops)
1192 {
1193 outputChars(current, "\x1b[", -1);
1194 while (nprops--) {
1195 outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
1196 props++;
1197 }
1198 }
1199
1200 static void eraseEol(struct current *current)
1201 {
1202 outputChars(current, "\x1b[0K", -1);
1203 }
1204
1205 static void setCursorPos(struct current *current, int x)
1206 {
1207 if (x == 0) {
1208 cursorToLeft(current);
1209 }
1210 else {
1211 outputFormatted(current, "\r\x1b[%dC", x);
1212 }
1213 }
1214
1215 static void cursorUp(struct current *current, int n)
1216 {
1217 if (n) {
1218 outputFormatted(current, "\x1b[%dA", n);
1219 }
1220 }
1221
1222 static void cursorDown(struct current *current, int n)
1223 {
1224 if (n) {
1225 outputFormatted(current, "\x1b[%dB", n);
1226 }
1227 }
1228
1229 void linenoiseClearScreen(void)
1230 {
1231 IGNORE_RC(write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7));
1232 }
1233
1234 /**
1235 * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
1236 *
1237 * A timeout of -1 means to wait forever.
1238 *
1239 * Returns -1 if no char is received within the time or an error occurs.
1240 */
1241 static int fd_read_char(int fd, int timeout)
1242 {
1243 struct pollfd p;
1244 unsigned char c;
1245
1246 p.fd = fd;
1247 p.events = POLLIN;
1248
1249 if (poll(&p, 1, timeout) == 0) {
1250 /* timeout */
1251 return -1;
1252 }
1253 if (read(fd, &c, 1) != 1) {
1254 return -1;
1255 }
1256 return c;
1257 }
1258
1259 /**
1260 * Reads a complete utf-8 character
1261 * and returns the unicode value, or -1 on error.
1262 */
1263 static int fd_read(struct current *current)
1264 {
1265 #ifdef USE_UTF8
1266 char buf[MAX_UTF8_LEN];
1267 int n;
1268 int i;
1269 int c;
1270
1271 if (read(current->fd, &buf[0], 1) != 1) {
1272 return -1;
1273 }
1274 n = utf8_charlen(buf[0]);
1275 if (n < 1) {
1276 return -1;
1277 }
1278 for (i = 1; i < n; i++) {
1279 if (read(current->fd, &buf[i], 1) != 1) {
1280 return -1;
1281 }
1282 }
1283 /* decode and return the character */
1284 utf8_tounicode(buf, &c);
1285 return c;
1286 #else
1287 return fd_read_char(current->fd, -1);
1288 #endif
1289 }
1290
1291
1292 /**
1293 * Stores the current cursor column in '*cols'.
1294 * Returns 1 if OK, or 0 if failed to determine cursor pos.
1295 */
1296 static int queryCursor(struct current *current, int* cols)
1297 {
1298 struct esc_parser parser;
1299 int ch;
1300
1301 /* Should not be buffering this output, it needs to go immediately */
1302 assert(current->output == NULL);
1303
1304 /* control sequence - report cursor location */
1305 outputChars(current, "\x1b[6n", -1);
1306
1307 /* Parse the response: ESC [ rows ; cols R */
1308 initParseEscapeSeq(&parser, 'R');
1309 while ((ch = fd_read_char(current->fd, 100)) > 0) {
1310 switch (parseEscapeSequence(&parser, ch)) {
1311 default:
1312 continue;
1313 case EP_END:
1314 if (parser.numprops == 2 && parser.props[1] < 1000) {
1315 *cols = parser.props[1];
1316 return 1;
1317 }
1318 break;
1319 case EP_ERROR:
1320 break;
1321 }
1322 /* failed */
1323 break;
1324 }
1325 return 0;
1326 }
1327
1328 /**
1329 * Updates current->cols with the current window size (width)
1330 */
1331 static int getWindowSize(struct current *current)
1332 {
1333 struct winsize ws;
1334
1335 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) {
1336 current->cols = ws.ws_col;
1337 return 0;
1338 }
1339
1340 /* Failed to query the window size. Perhaps we are on a serial terminal.
1341 * Try to query the width by sending the cursor as far to the right
1342 * and reading back the cursor position.
1343 * Note that this is only done once per call to linenoise rather than
1344 * every time the line is refreshed for efficiency reasons.
1345 *
1346 * In more detail, we:
1347 * (a) request current cursor position,
1348 * (b) move cursor far right,
1349 * (c) request cursor position again,
1350 * (d) at last move back to the old position.
1351 * This gives us the width without messing with the externally
1352 * visible cursor position.
1353 */
1354
1355 if (current->cols == 0) {
1356 int here;
1357
1358 /* If anything fails => default 80 */
1359 current->cols = 80;
1360
1361 /* (a) */
1362 if (queryCursor (current, &here)) {
1363 /* (b) */
1364 setCursorPos(current, 999);
1365
1366 /* (c). Note: If (a) succeeded, then (c) should as well.
1367 * For paranoia we still check and have a fallback action
1368 * for (d) in case of failure..
1369 */
1370 if (queryCursor (current, &current->cols)) {
1371 /* (d) Reset the cursor back to the original location. */
1372 if (current->cols > here) {
1373 setCursorPos(current, here);
1374 }
1375 }
1376 }
1377 }
1378
1379 return 0;
1380 }
1381
1382 /**
1383 * If CHAR_ESCAPE was received, reads subsequent
1384 * chars to determine if this is a known special key.
1385 *
1386 * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
1387 *
1388 * If no additional char is received within a short time,
1389 * CHAR_ESCAPE is returned.
1390 */
1391 static int check_special(int fd)
1392 {
1393 int c = fd_read_char(fd, 50);
1394 int c2;
1395
1396 if (c < 0) {
1397 return CHAR_ESCAPE;
1398 }
1399 else if (c >= 'a' && c <= 'z') {
1400 /* esc-a => meta-a */
1401 return meta(c);
1402 }
1403
1404 c2 = fd_read_char(fd, 50);
1405 if (c2 < 0) {
1406 return c2;
1407 }
1408 if (c == '[' || c == 'O') {
1409 /* Potential arrow key */
1410 switch (c2) {
1411 case 'A':
1412 return SPECIAL_UP;
1413 case 'B':
1414 return SPECIAL_DOWN;
1415 case 'C':
1416 return SPECIAL_RIGHT;
1417 case 'D':
1418 return SPECIAL_LEFT;
1419 case 'F':
1420 return SPECIAL_END;
1421 case 'H':
1422 return SPECIAL_HOME;
1423 }
1424 }
1425 if (c == '[' && c2 >= '1' && c2 <= '8') {
1426 /* extended escape */
1427 c = fd_read_char(fd, 50);
1428 if (c == '~') {
1429 switch (c2) {
1430 case '2':
1431 return SPECIAL_INSERT;
1432 case '3':
1433 return SPECIAL_DELETE;
1434 case '5':
1435 return SPECIAL_PAGE_UP;
1436 case '6':
1437 return SPECIAL_PAGE_DOWN;
1438 case '7':
1439 return SPECIAL_HOME;
1440 case '8':
1441 return SPECIAL_END;
1442 }
1443 }
1444 while (c != -1 && c != '~') {
1445 /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
1446 c = fd_read_char(fd, 50);
1447 }
1448 }
1449
1450 return SPECIAL_NONE;
1451 }
1452 #endif
1453
1454 static void clearOutputHighlight(struct current *current)
1455 {
1456 int nohighlight = 0;
1457 setOutputHighlight(current, &nohighlight, 1);
1458 }
1459
1460 static void outputControlChar(struct current *current, char ch)
1461 {
1462 int reverse = 7;
1463 setOutputHighlight(current, &reverse, 1);
1464 outputChars(current, "^", 1);
1465 outputChars(current, &ch, 1);
1466 clearOutputHighlight(current);
1467 }
1468
1469 #ifndef utf8_getchars
1470 static int utf8_getchars(char *buf, int c)
1471 {
1472 #ifdef USE_UTF8
1473 return utf8_fromunicode(buf, c);
1474 #else
1475 *buf = c;
1476 return 1;
1477 #endif
1478 }
1479 #endif
1480
1481 /**
1482 * Returns the unicode character at the given offset,
1483 * or -1 if none.
1484 */
1485 static int get_char(struct current *current, int pos)
1486 {
1487 if (pos >= 0 && pos < sb_chars(current->buf)) {
1488 int c;
1489 int i = utf8_index(sb_str(current->buf), pos);
1490 (void)utf8_tounicode(sb_str(current->buf) + i, &c);
1491 return c;
1492 }
1493 return -1;
1494 }
1495
1496 static int char_display_width(int ch)
1497 {
1498 if (ch < ' ') {
1499 /* control chars take two positions */
1500 return 2;
1501 }
1502 else {
1503 return utf8_width(ch);
1504 }
1505 }
1506
1507 #ifndef NO_COMPLETION
1508 static linenoiseCompletionCallback *completionCallback = NULL;
1509 static void *completionUserdata = NULL;
1510 static int showhints = 1;
1511 static linenoiseHintsCallback *hintsCallback = NULL;
1512 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
1513 static void *hintsUserdata = NULL;
1514
1515 static void beep(void) {
1516 #ifdef USE_TERMIOS
1517 fprintf(stderr, "\x7");
1518 fflush(stderr);
1519 #endif
1520 }
1521
 
 
 
1522 static void freeCompletions(linenoiseCompletions *lc) {
1523 size_t i;
1524 for (i = 0; i < lc->len; i++)
1525 free(lc->cvec[i]);
1526 free(lc->cvec);
 
1527 }
1528
1529 static int completeLine(struct current *current) {
 
 
 
 
 
 
1530 linenoiseCompletions lc = { 0, NULL };
1531 int c = 0;
 
1532
1533 completionCallback(sb_str(current->buf),&lc,completionUserdata);
1534 if (lc.len == 0) {
1535 beep();
1536 } else {
1537 size_t stop = 0, i = 0;
1538
1539 while(!stop) {
1540 /* Show completion or original buffer */
1541 if (i < lc.len) {
1542 int chars = utf8_strlen(lc.cvec[i], -1);
1543 refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
 
 
 
 
 
 
1544 } else {
1545 refreshLine(current);
1546 }
1547
1548 c = fd_read(current);
1549 if (c == -1) {
1550 break;
 
1551 }
1552
1553 switch(c) {
1554 case '\t': /* tab */
1555 i = (i+1) % (lc.len+1);
1556 if (i == lc.len) beep();
1557 break;
1558 case CHAR_ESCAPE: /* escape */
1559 /* Re-show original buffer */
1560 if (i < lc.len) {
1561 refreshLine(current);
1562 }
1563 stop = 1;
1564 break;
1565 default:
1566 /* Update buffer and return */
1567 if (i < lc.len) {
1568 set_current(current,lc.cvec[i]);
 
1569 }
1570 stop = 1;
1571 break;
1572 }
1573 }
@@ -417,769 +1575,1126 @@
1575
1576 freeCompletions(&lc);
1577 return c; /* Return last read character */
1578 }
1579
1580 /* Register a callback function to be called for tab-completion.
1581 Returns the prior callback so that the caller may (if needed)
1582 restore it when done. */
1583 linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
1584 linenoiseCompletionCallback * old = completionCallback;
1585 completionCallback = fn;
1586 completionUserdata = userdata;
1587 return old;
1588 }
1589
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1590 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
1591 lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
1592 lc->cvec[lc->len++] = strdup(str);
1593 }
1594
1595 void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
1596 {
1597 hintsCallback = callback;
1598 hintsUserdata = userdata;
1599 }
1600
1601 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
1602 {
1603 freeHintsCallback = callback;
1604 }
1605
1606 #endif
1607
1608
1609 static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
1610 {
1611 /* We have availcols columns available.
1612 * If necessary, strip chars off the front of buf until *cursor_pos
1613 * fits within availcols
1614 */
1615 int needcols = 0;
1616 int pos = 0;
1617 int new_cursor_pos = *cursor_pos;
1618 const char *pt = buf;
1619
1620 DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
1621
1622 while (*pt) {
1623 int ch;
1624 int n = utf8_tounicode(pt, &ch);
1625 pt += n;
1626
1627 needcols += char_display_width(ch);
1628
1629 /* If we need too many cols, strip
1630 * chars off the front of buf to make it fit.
1631 * We keep 3 extra cols to the right of the cursor.
1632 * 2 for possible wide chars, 1 for the last column that
1633 * can't be used.
1634 */
1635 while (needcols >= availcols - 3) {
1636 n = utf8_tounicode(buf, &ch);
1637 buf += n;
1638 needcols -= char_display_width(ch);
1639 DRL_CHAR(ch);
1640
1641 /* and adjust the apparent cursor position */
1642 new_cursor_pos--;
1643
1644 if (buf == pt) {
1645 /* can't remove more than this */
1646 break;
1647 }
1648 }
1649
1650 if (pos++ == *cursor_pos) {
1651 break;
1652 }
1653
1654 }
1655 DRL("<snip>");
1656 DRL_STR(buf);
1657 DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
1658
1659 /* Done, now new_cursor_pos contains the adjusted cursor position
1660 * and buf points to he adjusted start
1661 */
1662 *cursor_pos = new_cursor_pos;
1663 return buf;
1664 }
1665
1666 static int mlmode = 0;
1667
1668 void linenoiseSetMultiLine(int enableml)
1669 {
1670 mlmode = enableml;
1671 }
1672
1673 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
1674 * to the right of the prompt.
1675 * Returns 1 if a hint was shown, or 0 if not
1676 * If 'display' is 0, does no output. Just returns the appropriate return code.
1677 */
1678 static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
1679 {
1680 int rc = 0;
1681 if (showhints && hintsCallback && availcols > 0) {
1682 int bold = 0;
1683 int color = -1;
1684 char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
1685 if (hint) {
1686 rc = 1;
1687 if (display) {
1688 const char *pt;
1689 if (bold == 1 && color == -1) color = 37;
1690 if (bold || color > 0) {
1691 int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
1692 setOutputHighlight(current, props, 3);
1693 }
1694 DRL("<hint bold=%d,color=%d>", bold, color);
1695 pt = hint;
1696 while (*pt) {
1697 int ch;
1698 int n = utf8_tounicode(pt, &ch);
1699 int width = char_display_width(ch);
1700
1701 if (width >= availcols) {
1702 DRL("<hinteol>");
1703 break;
1704 }
1705 DRL_CHAR(ch);
1706
1707 availcols -= width;
1708 outputChars(current, pt, n);
1709 pt += n;
1710 }
1711 if (bold || color > 0) {
1712 clearOutputHighlight(current);
1713 }
1714 /* Call the function to free the hint returned. */
1715 if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
1716 }
1717 }
1718 }
1719 return rc;
1720 }
1721
1722 #ifdef USE_TERMIOS
1723 static void refreshStart(struct current *current)
1724 {
1725 /* We accumulate all output here */
1726 assert(current->output == NULL);
1727 current->output = sb_alloc();
1728 }
1729
1730 static void refreshEnd(struct current *current)
1731 {
1732 /* Output everything at once */
1733 IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
1734 sb_free(current->output);
1735 current->output = NULL;
1736 }
1737
1738 static void refreshStartChars(struct current *current)
1739 {
1740 (void)current;
1741 }
1742
1743 static void refreshNewline(struct current *current)
1744 {
1745 DRL("<nl>");
1746 outputChars(current, "\n", 1);
1747 }
1748
1749 static void refreshEndChars(struct current *current)
1750 {
1751 (void)current;
1752 }
1753 #endif
1754
1755 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
1756 {
1757 int i;
1758 const char *pt;
1759 int displaycol;
1760 int displayrow;
1761 int visible;
1762 int currentpos;
1763 int notecursor;
1764 int cursorcol = 0;
1765 int cursorrow = 0;
1766 int hint;
1767 struct esc_parser parser;
1768
1769 #ifdef DEBUG_REFRESHLINE
1770 dfh = fopen("linenoise.debuglog", "a");
1771 #endif
1772
1773 /* Should intercept SIGWINCH. For now, just get the size every time */
1774 getWindowSize(current);
1775
1776 refreshStart(current);
1777
1778 DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
1779
1780 /* Here is the plan:
1781 * (a) move the the bottom row, going down the appropriate number of lines
1782 * (b) move to beginning of line and erase the current line
1783 * (c) go up one line and do the same, until we have erased up to the first row
1784 * (d) output the prompt, counting cols and rows, taking into account escape sequences
1785 * (e) output the buffer, counting cols and rows
1786 * (e') when we hit the current pos, save the cursor position
1787 * (f) move the cursor to the saved cursor position
1788 * (g) save the current cursor row and number of rows
1789 */
1790
1791 /* (a) - The cursor is currently at row rpos */
1792 cursorDown(current, current->nrows - current->rpos - 1);
1793 DRL("<cud=%d>", current->nrows - current->rpos - 1);
1794
1795 /* (b), (c) - Erase lines upwards until we get to the first row */
1796 for (i = 0; i < current->nrows; i++) {
1797 if (i) {
1798 DRL("<cup>");
1799 cursorUp(current, 1);
1800 }
1801 DRL("<clearline>");
1802 cursorToLeft(current);
1803 eraseEol(current);
1804 }
1805 DRL("\n");
1806
1807 /* (d) First output the prompt. control sequences don't take up display space */
1808 pt = prompt;
1809 displaycol = 0; /* current display column */
1810 displayrow = 0; /* current display row */
1811 visible = 1;
1812
1813 refreshStartChars(current);
1814
1815 while (*pt) {
1816 int width;
1817 int ch;
1818 int n = utf8_tounicode(pt, &ch);
1819
1820 if (visible && ch == CHAR_ESCAPE) {
1821 /* The start of an escape sequence, so not visible */
1822 visible = 0;
1823 initParseEscapeSeq(&parser, 'm');
1824 DRL("<esc-seq-start>");
1825 }
1826
1827 if (ch == '\n' || ch == '\r') {
1828 /* treat both CR and NL the same and force wrap */
1829 refreshNewline(current);
1830 displaycol = 0;
1831 displayrow++;
1832 }
1833 else {
1834 width = visible * utf8_width(ch);
1835
1836 displaycol += width;
1837 if (displaycol >= current->cols) {
1838 /* need to wrap to the next line because of newline or if it doesn't fit
1839 * XXX this is a problem in single line mode
1840 */
1841 refreshNewline(current);
1842 displaycol = width;
1843 displayrow++;
1844 }
1845
1846 DRL_CHAR(ch);
1847 #ifdef USE_WINCONSOLE
1848 if (visible) {
1849 outputChars(current, pt, n);
1850 }
1851 #else
1852 outputChars(current, pt, n);
1853 #endif
1854 }
1855 pt += n;
1856
1857 if (!visible) {
1858 switch (parseEscapeSequence(&parser, ch)) {
1859 case EP_END:
1860 visible = 1;
1861 setOutputHighlight(current, parser.props, parser.numprops);
1862 DRL("<esc-seq-end,numprops=%d>", parser.numprops);
1863 break;
1864 case EP_ERROR:
1865 DRL("<esc-seq-err>");
1866 visible = 1;
1867 break;
1868 }
1869 }
1870 }
1871
1872 /* Now we are at the first line with all lines erased */
1873 DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);
1874
1875
1876 /* (e) output the buffer, counting cols and rows */
1877 if (mlmode == 0) {
1878 /* In this mode we may need to trim chars from the start of the buffer until the
1879 * cursor fits in the window.
1880 */
1881 pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
1882 }
1883 else {
1884 pt = buf;
1885 }
1886
1887 currentpos = 0;
1888 notecursor = -1;
1889
1890 while (*pt) {
1891 int ch;
1892 int n = utf8_tounicode(pt, &ch);
1893 int width = char_display_width(ch);
1894
1895 if (currentpos == cursor_pos) {
1896 /* (e') wherever we output this character is where we want the cursor */
1897 notecursor = 1;
1898 }
1899
1900 if (displaycol + width >= current->cols) {
1901 if (mlmode == 0) {
1902 /* In single line mode stop once we print as much as we can on one line */
1903 DRL("<slmode>");
1904 break;
1905 }
1906 /* need to wrap to the next line since it doesn't fit */
1907 refreshNewline(current);
1908 displaycol = 0;
1909 displayrow++;
1910 }
1911
1912 if (notecursor == 1) {
1913 /* (e') Save this position as the current cursor position */
1914 cursorcol = displaycol;
1915 cursorrow = displayrow;
1916 notecursor = 0;
1917 DRL("<cursor>");
1918 }
1919
1920 displaycol += width;
1921
1922 if (ch < ' ') {
1923 outputControlChar(current, ch + '@');
1924 }
1925 else {
1926 outputChars(current, pt, n);
1927 }
1928 DRL_CHAR(ch);
1929 if (width != 1) {
1930 DRL("<w=%d>", width);
1931 }
1932
1933 pt += n;
1934 currentpos++;
1935 }
1936
1937 /* If we didn't see the cursor, it is at the current location */
1938 if (notecursor) {
1939 DRL("<cursor>");
1940 cursorcol = displaycol;
1941 cursorrow = displayrow;
1942 }
1943
1944 DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n", displaycol, displayrow, cursorcol, cursorrow);
1945
1946 /* (f) show hints */
1947 hint = refreshShowHints(current, buf, current->cols - displaycol, 1);
1948
1949 /* Remember how many many cols are available for insert optimisation */
1950 if (prompt == current->prompt && hint == 0) {
1951 current->colsright = current->cols - displaycol;
1952 current->colsleft = displaycol;
1953 }
1954 else {
1955 /* Can't optimise */
1956 current->colsright = 0;
1957 current->colsleft = 0;
1958 }
1959 DRL("\nafter hints: colsleft=%d, colsright=%d\n\n", current->colsleft, current->colsright);
1960
1961 refreshEndChars(current);
1962
1963 /* (g) move the cursor to the correct place */
1964 cursorUp(current, displayrow - cursorrow);
1965 setCursorPos(current, cursorcol);
1966
1967 /* (h) Update the number of rows if larger, but never reduce this */
1968 if (displayrow >= current->nrows) {
1969 current->nrows = displayrow + 1;
1970 }
1971 /* And remember the row that the cursor is on */
1972 current->rpos = cursorrow;
1973
1974 refreshEnd(current);
1975
1976 #ifdef DEBUG_REFRESHLINE
1977 fclose(dfh);
1978 #endif
1979 }
1980
1981 static void refreshLine(struct current *current)
1982 {
1983 refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
1984 }
1985
1986 static void set_current(struct current *current, const char *str)
1987 {
1988 sb_clear(current->buf);
1989 sb_append(current->buf, str);
1990 current->pos = sb_chars(current->buf);
1991 }
1992
1993 /**
1994 * Removes the char at 'pos'.
1995 *
1996 * Returns 1 if the line needs to be refreshed, 2 if not
1997 * and 0 if nothing was removed
1998 */
1999 static int remove_char(struct current *current, int pos)
2000 {
2001 if (pos >= 0 && pos < sb_chars(current->buf)) {
2002 int offset = utf8_index(sb_str(current->buf), pos);
2003 int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
2004 int rc = 1;
2005
2006 /* Now we try to optimise in the simple but very common case that:
2007 * - outputChars() can be used directly (not win32)
2008 * - we are removing the char at EOL
2009 * - the buffer is not empty
2010 * - there are columns available to the left
2011 * - the char being deleted is not a wide or utf-8 character
2012 * - no hints are being shown
2013 */
2014 if (current->output && current->pos == pos + 1 && current->pos == sb_chars(current->buf) && pos > 0) {
2015 #ifdef USE_UTF8
2016 /* Could implement utf8_prev_len() but simplest just to not optimise this case */
2017 char last = sb_str(current->buf)[offset];
2018 #else
2019 char last = 0;
2020 #endif
2021 if (current->colsleft > 0 && (last & 0x80) == 0) {
2022 /* Have cols on the left and not a UTF-8 char or continuation */
2023 /* Yes, can optimise */
2024 current->colsleft--;
2025 current->colsright++;
2026 rc = 2;
2027 }
2028 }
2029
2030 sb_delete(current->buf, offset, nbytes);
2031
2032 if (current->pos > pos) {
2033 current->pos--;
2034 }
2035 if (rc == 2) {
2036 if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
2037 /* A hint needs to be shown, so can't optimise after all */
2038 rc = 1;
2039 }
2040 else {
2041 /* optimised output */
2042 outputChars(current, "\b \b", 3);
2043 }
2044 }
2045 return rc;
2046 return 1;
2047 }
2048 return 0;
2049 }
2050
2051 /**
2052 * Insert 'ch' at position 'pos'
2053 *
2054 * Returns 1 if the line needs to be refreshed, 2 if not
2055 * and 0 if nothing was inserted (no room)
2056 */
2057 static int insert_char(struct current *current, int pos, int ch)
2058 {
2059 if (pos >= 0 && pos <= sb_chars(current->buf)) {
2060 char buf[MAX_UTF8_LEN + 1];
2061 int offset = utf8_index(sb_str(current->buf), pos);
2062 int n = utf8_getchars(buf, ch);
2063 int rc = 1;
2064
2065 /* null terminate since sb_insert() requires it */
2066 buf[n] = 0;
2067
2068 /* Now we try to optimise in the simple but very common case that:
2069 * - outputChars() can be used directly (not win32)
2070 * - we are inserting at EOL
2071 * - there are enough columns available
2072 * - no hints are being shown
2073 */
2074 if (current->output && pos == current->pos && pos == sb_chars(current->buf)) {
2075 int width = char_display_width(ch);
2076 if (current->colsright > width) {
2077 /* Yes, can optimise */
2078 current->colsright -= width;
2079 current->colsleft -= width;
2080 rc = 2;
2081 }
2082 }
2083 sb_insert(current->buf, offset, buf);
2084 if (current->pos >= pos) {
2085 current->pos++;
2086 }
2087 if (rc == 2) {
2088 if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
2089 /* A hint needs to be shown, so can't optimise after all */
2090 rc = 1;
2091 }
2092 else {
2093 /* optimised output */
2094 outputChars(current, buf, n);
2095 }
2096 }
2097 return rc;
2098 }
2099 return 0;
2100 }
2101
2102 /**
2103 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
2104 *
2105 * This replaces any existing characters in the cut buffer.
2106 */
2107 static void capture_chars(struct current *current, int pos, int nchars)
2108 {
2109 if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
2110 int offset = utf8_index(sb_str(current->buf), pos);
2111 int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
2112
2113 if (nbytes > 0) {
2114 if (current->capture) {
2115 sb_clear(current->capture);
2116 }
2117 else {
2118 current->capture = sb_alloc();
2119 }
2120 sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
2121 }
2122 }
2123 }
2124
2125 /**
2126 * Removes up to 'n' characters at cursor position 'pos'.
2127 *
2128 * Returns 0 if no chars were removed or non-zero otherwise.
2129 */
2130 static int remove_chars(struct current *current, int pos, int n)
2131 {
2132 int removed = 0;
2133
2134 /* First save any chars which will be removed */
2135 capture_chars(current, pos, n);
2136
2137 while (n-- && remove_char(current, pos)) {
2138 removed++;
2139 }
2140 return removed;
2141 }
2142 /**
2143 * Inserts the characters (string) 'chars' at the cursor position 'pos'.
2144 *
2145 * Returns 0 if no chars were inserted or non-zero otherwise.
2146 */
2147 static int insert_chars(struct current *current, int pos, const char *chars)
2148 {
2149 int inserted = 0;
2150
2151 while (*chars) {
2152 int ch;
2153 int n = utf8_tounicode(chars, &ch);
2154 if (insert_char(current, pos, ch) == 0) {
2155 break;
2156 }
2157 inserted++;
2158 pos++;
2159 chars += n;
2160 }
2161 return inserted;
2162 }
2163
2164 static int skip_space_nonspace(struct current *current, int dir, int check_is_space)
2165 {
2166 int moved = 0;
2167 int checkoffset = (dir < 0) ? -1 : 0;
2168 int limit = (dir < 0) ? 0 : sb_chars(current->buf);
2169 while (current->pos != limit && (get_char(current, current->pos + checkoffset) == ' ') == check_is_space) {
2170 current->pos += dir;
2171 moved++;
2172 }
2173 return moved;
2174 }
2175
2176 static int skip_space(struct current *current, int dir)
2177 {
2178 return skip_space_nonspace(current, dir, 1);
2179 }
2180
2181 static int skip_nonspace(struct current *current, int dir)
2182 {
2183 return skip_space_nonspace(current, dir, 0);
2184 }
2185
2186 static void set_history_index(struct current *current, int new_index)
2187 {
2188 if (history_len > 1) {
2189 /* Update the current history entry before to
2190 * overwrite it with the next one. */
2191 free(history[history_len - 1 - history_index]);
2192 history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
2193 /* Show the new entry */
2194 history_index = new_index;
2195 if (history_index < 0) {
2196 history_index = 0;
2197 } else if (history_index >= history_len) {
2198 history_index = history_len - 1;
2199 } else {
2200 set_current(current, history[history_len - 1 - history_index]);
2201 refreshLine(current);
2202 }
2203 }
2204 }
2205
2206 /**
2207 * Returns the keycode to process, or 0 if none.
2208 */
2209 static int reverseIncrementalSearch(struct current *current)
2210 {
2211 /* Display the reverse-i-search prompt and process chars */
2212 char rbuf[50];
2213 char rprompt[80];
2214 int rchars = 0;
2215 int rlen = 0;
2216 int searchpos = history_len - 1;
2217 int c;
2218
2219 rbuf[0] = 0;
2220 while (1) {
2221 int n = 0;
2222 const char *p = NULL;
2223 int skipsame = 0;
2224 int searchdir = -1;
2225
2226 snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
2227 refreshLineAlt(current, rprompt, sb_str(current->buf), current->pos);
2228 c = fd_read(current);
2229 if (c == ctrl('H') || c == CHAR_DELETE) {
2230 if (rchars) {
2231 int p_ind = utf8_index(rbuf, --rchars);
2232 rbuf[p_ind] = 0;
2233 rlen = strlen(rbuf);
2234 }
2235 continue;
2236 }
2237 #ifdef USE_TERMIOS
2238 if (c == CHAR_ESCAPE) {
2239 c = check_special(current->fd);
2240 }
2241 #endif
2242 if (c == ctrl('R')) {
2243 /* Search for the previous (earlier) match */
2244 if (searchpos > 0) {
2245 searchpos--;
2246 }
2247 skipsame = 1;
2248 }
2249 else if (c == ctrl('S')) {
2250 /* Search for the next (later) match */
2251 if (searchpos < history_len) {
2252 searchpos++;
2253 }
2254 searchdir = 1;
2255 skipsame = 1;
2256 }
2257 else if (c == ctrl('P') || c == SPECIAL_UP) {
2258 /* Exit Ctrl-R mode and go to the previous history line from the current search pos */
2259 set_history_index(current, history_len - searchpos);
2260 c = 0;
2261 break;
2262 }
2263 else if (c == ctrl('N') || c == SPECIAL_DOWN) {
2264 /* Exit Ctrl-R mode and go to the next history line from the current search pos */
2265 set_history_index(current, history_len - searchpos - 2);
2266 c = 0;
2267 break;
2268 }
2269 else if (c >= ' ' && c <= '~') {
2270 /* >= here to allow for null terminator */
2271 if (rlen >= (int)sizeof(rbuf) - MAX_UTF8_LEN) {
2272 continue;
2273 }
2274
2275 n = utf8_getchars(rbuf + rlen, c);
2276 rlen += n;
2277 rchars++;
2278 rbuf[rlen] = 0;
2279
2280 /* Adding a new char resets the search location */
2281 searchpos = history_len - 1;
2282 }
2283 else {
2284 /* Exit from incremental search mode */
2285 break;
2286 }
2287
2288 /* Now search through the history for a match */
2289 for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
2290 p = strstr(history[searchpos], rbuf);
2291 if (p) {
2292 /* Found a match */
2293 if (skipsame && strcmp(history[searchpos], sb_str(current->buf)) == 0) {
2294 /* But it is identical, so skip it */
2295 continue;
2296 }
2297 /* Copy the matching line and set the cursor position */
2298 history_index = history_len - 1 - searchpos;
2299 set_current(current,history[searchpos]);
2300 current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
2301 break;
2302 }
2303 }
2304 if (!p && n) {
2305 /* No match, so don't add it */
2306 rchars--;
2307 rlen -= n;
2308 rbuf[rlen] = 0;
2309 }
2310 }
2311 if (c == ctrl('G') || c == ctrl('C')) {
2312 /* ctrl-g terminates the search with no effect */
2313 set_current(current, "");
2314 history_index = 0;
2315 c = 0;
2316 }
2317 else if (c == ctrl('J')) {
2318 /* ctrl-j terminates the search leaving the buffer in place */
2319 history_index = 0;
2320 c = 0;
2321 }
2322 /* Go process the char normally */
2323 refreshLine(current);
2324 return c;
2325 }
2326
2327 static int linenoiseEdit(struct current *current) {
2328 history_index = 0;
2329
2330 refreshLine(current);
2331
2332 while(1) {
2333 int c = fd_read(current);
2334
2335 #ifndef NO_COMPLETION
2336 /* Only autocomplete when the callback is set. It returns < 0 when
2337 * there was an error reading from fd. Otherwise it will return the
2338 * character that should be handled next. */
2339 if (c == '\t' && current->pos == sb_chars(current->buf) && completionCallback != NULL) {
2340 c = completeLine(current);
2341 }
2342 #endif
2343 if (c == ctrl('R')) {
2344 /* reverse incremental search will provide an alternative keycode or 0 for none */
2345 c = reverseIncrementalSearch(current);
2346 /* go on to process the returned char normally */
2347 }
2348
2349 #ifdef USE_TERMIOS
2350 if (c == CHAR_ESCAPE) { /* escape sequence */
2351 c = check_special(current->fd);
2352 }
2353 #endif
2354 if (c == -1) {
2355 /* Return on errors */
2356 return sb_len(current->buf);
2357 }
2358
2359 switch(c) {
2360 case SPECIAL_NONE:
2361 break;
2362 case '\r': /* enter/CR */
2363 case '\n': /* LF */
2364 history_len--;
2365 free(history[history_len]);
2366 current->pos = sb_chars(current->buf);
2367 if (mlmode || hintsCallback) {
2368 showhints = 0;
2369 refreshLine(current);
2370 showhints = 1;
2371 }
2372 return sb_len(current->buf);
2373 case ctrl('C'): /* ctrl-c */
2374 errno = EAGAIN;
2375 return -1;
2376 case ctrl('Z'): /* ctrl-z */
2377 #ifdef SIGTSTP
2378 /* send ourselves SIGSUSP */
2379 disableRawMode(current);
2380 raise(SIGTSTP);
2381 /* and resume */
2382 enableRawMode(current);
2383 refreshLine(current);
2384 #endif
2385 continue;
2386 case CHAR_DELETE: /* backspace */
2387 case ctrl('H'):
2388 if (remove_char(current, current->pos - 1) == 1) {
2389 refreshLine(current);
2390 }
2391 break;
2392 case ctrl('D'): /* ctrl-d */
2393 if (sb_len(current->buf) == 0) {
2394 /* Empty line, so EOF */
2395 history_len--;
2396 free(history[history_len]);
2397 return -1;
2398 }
2399 /* Otherwise fall through to delete char to right of cursor */
2400 /* fall-thru */
2401 case SPECIAL_DELETE:
2402 if (remove_char(current, current->pos) == 1) {
2403 refreshLine(current);
2404 }
2405 break;
2406 case SPECIAL_INSERT:
2407 /* Ignore. Expansion Hook.
2408 * Future possibility: Toggle Insert/Overwrite Modes
2409 */
2410 break;
2411 case meta('b'): /* meta-b, move word left */
2412 if (skip_nonspace(current, -1)) {
2413 refreshLine(current);
2414 }
2415 else if (skip_space(current, -1)) {
2416 skip_nonspace(current, -1);
2417 refreshLine(current);
2418 }
2419 break;
2420 case meta('f'): /* meta-f, move word right */
2421 if (skip_space(current, 1)) {
2422 refreshLine(current);
2423 }
2424 else if (skip_nonspace(current, 1)) {
2425 skip_space(current, 1);
2426 refreshLine(current);
2427 }
2428 break;
2429 case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */
2430 /* eat any spaces on the left */
2431 {
2432 int pos = current->pos;
2433 while (pos > 0 && get_char(current, pos - 1) == ' ') {
2434 pos--;
2435 }
2436
2437 /* now eat any non-spaces on the left */
2438 while (pos > 0 && get_char(current, pos - 1) != ' ') {
2439 pos--;
2440 }
2441
2442 if (remove_chars(current, pos, current->pos - pos)) {
2443 refreshLine(current);
2444 }
2445 }
2446 break;
2447 case ctrl('T'): /* ctrl-t */
2448 if (current->pos > 0 && current->pos <= sb_chars(current->buf)) {
2449 /* If cursor is at end, transpose the previous two chars */
2450 int fixer = (current->pos == sb_chars(current->buf));
2451 c = get_char(current, current->pos - fixer);
2452 remove_char(current, current->pos - fixer);
2453 insert_char(current, current->pos - 1, c);
2454 refreshLine(current);
2455 }
2456 break;
2457 case ctrl('V'): /* ctrl-v */
2458 /* Insert the ^V first */
2459 if (insert_char(current, current->pos, c)) {
2460 refreshLine(current);
2461 /* Now wait for the next char. Can insert anything except \0 */
2462 c = fd_read(current);
2463
2464 /* Remove the ^V first */
2465 remove_char(current, current->pos - 1);
2466 if (c > 0) {
2467 /* Insert the actual char, can't be error or null */
2468 insert_char(current, current->pos, c);
2469 }
2470 refreshLine(current);
2471 }
2472 break;
2473 case ctrl('B'):
2474 case SPECIAL_LEFT:
2475 if (current->pos > 0) {
2476 current->pos--;
2477 refreshLine(current);
2478 }
2479 break;
2480 case ctrl('F'):
2481 case SPECIAL_RIGHT:
2482 if (current->pos < sb_chars(current->buf)) {
2483 current->pos++;
2484 refreshLine(current);
2485 }
2486 break;
2487 case SPECIAL_PAGE_UP: /* move to start of history */
2488 set_history_index(current, history_len - 1);
2489 break;
2490 case SPECIAL_PAGE_DOWN: /* move to 0 == end of history, i.e. current */
2491 set_history_index(current, 0);
2492 break;
2493 case ctrl('P'):
2494 case SPECIAL_UP:
2495 set_history_index(current, history_index + 1);
2496 break;
2497 case ctrl('N'):
2498 case SPECIAL_DOWN:
2499 set_history_index(current, history_index - 1);
2500 break;
2501 case ctrl('A'): /* Ctrl+a, go to the start of the line */
2502 case SPECIAL_HOME:
2503 current->pos = 0;
2504 refreshLine(current);
2505 break;
2506 case ctrl('E'): /* ctrl+e, go to the end of the line */
2507 case SPECIAL_END:
2508 current->pos = sb_chars(current->buf);
2509 refreshLine(current);
2510 break;
2511 case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
2512 if (remove_chars(current, 0, current->pos)) {
2513 refreshLine(current);
2514 }
2515 break;
2516 case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
2517 if (remove_chars(current, current->pos, sb_chars(current->buf) - current->pos)) {
2518 refreshLine(current);
2519 }
2520 break;
2521 case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
2522 if (current->capture && insert_chars(current, current->pos, sb_str(current->capture))) {
2523 refreshLine(current);
2524 }
2525 break;
2526 case ctrl('L'): /* Ctrl+L, clear screen */
2527 linenoiseClearScreen();
2528 /* Force recalc of window size for serial terminals */
2529 current->cols = 0;
2530 current->rpos = 0;
2531 refreshLine(current);
2532 break;
2533 default:
2534 if (c >= meta('a') && c <= meta('z')) {
2535 /* Don't insert meta chars that are not bound */
2536 break;
2537 }
2538 /* Only tab is allowed without ^V */
2539 if (c == '\t' || c >= ' ') {
2540 if (insert_char(current, current->pos, c) == 1) {
2541 refreshLine(current);
2542 }
2543 }
2544 break;
2545 }
2546 }
2547 return sb_len(current->buf);
2548 }
2549
2550 int linenoiseColumns(void)
2551 {
2552 struct current current;
2553 current.output = NULL;
2554 enableRawMode (&current);
2555 getWindowSize (&current);
2556 disableRawMode (&current);
2557 return current.cols;
2558 }
2559
2560 /**
2561 * Reads a line from the file handle (without the trailing NL or CRNL)
2562 * and returns it in a stringbuf.
2563 * Returns NULL if no characters are read before EOF or error.
2564 *
2565 * Note that the character count will *not* be correct for lines containing
2566 * utf8 sequences. Do not rely on the character count.
2567 */
2568 static stringbuf *sb_getline(FILE *fh)
2569 {
2570 stringbuf *sb = sb_alloc();
2571 int c;
2572 int n = 0;
2573
2574 while ((c = getc(fh)) != EOF) {
2575 char ch;
2576 n++;
2577 if (c == '\r') {
2578 /* CRLF -> LF */
2579 continue;
2580 }
2581 if (c == '\n' || c == '\r') {
2582 break;
2583 }
2584 ch = c;
2585 /* ignore the effect of character count for partial utf8 sequences */
2586 sb_append_len(sb, &ch, 1);
2587 }
2588 if (n == 0 || sb->data == NULL) {
2589 sb_free(sb);
2590 return NULL;
2591 }
2592 return sb;
2593 }
2594
2595 char *linenoiseWithInitial(const char *prompt, const char *initial)
2596 {
2597 int count;
2598 struct current current;
2599 stringbuf *sb;
2600
2601 memset(&current, 0, sizeof(current));
2602
2603 if (enableRawMode(&current) == -1) {
2604 printf("%s", prompt);
2605 fflush(stdout);
2606 sb = sb_getline(stdin);
2607 if (sb && !fd_isatty(&current)) {
2608 printf("%s\n", sb_str(sb));
2609 fflush(stdout);
2610 }
2611 }
2612 else {
2613 current.buf = sb_alloc();
2614 current.pos = 0;
2615 current.nrows = 1;
2616 current.prompt = prompt;
2617
2618 /* The latest history entry is always our current buffer */
2619 linenoiseHistoryAdd(initial);
2620 set_current(&current, initial);
2621
2622 count = linenoiseEdit(&current);
2623
2624 disableRawMode(&current);
2625 printf("\n");
2626
2627 sb_free(current.capture);
2628 if (count == -1) {
2629 sb_free(current.buf);
2630 return NULL;
2631 }
2632 sb = current.buf;
2633 }
2634 return sb ? sb_to_string(sb) : NULL;
2635 }
2636
2637 char *linenoise(const char *prompt)
2638 {
2639 return linenoiseWithInitial(prompt, "");
2640 }
2641
2642 /* Using a circular buffer is smarter, but a bit more complex to handle. */
2643 static int linenoiseHistoryAddAllocated(char *line) {
2644
2645 if (history_max_len == 0) {
2646 notinserted:
2647 free(line);
2648 return 0;
2649 }
2650 if (history == NULL) {
2651 history = (char **)calloc(sizeof(char*), history_max_len);
2652 }
2653
2654 /* do not insert duplicate lines into history */
2655 if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
2656 goto notinserted;
2657 }
2658
2659 if (history_len == history_max_len) {
2660 free(history[0]);
2661 memmove(history,history+1,sizeof(char*)*(history_max_len-1));
2662 history_len--;
2663 }
2664 history[history_len] = line;
2665 history_len++;
2666 return 1;
2667 }
2668
2669 int linenoiseHistoryAdd(const char *line) {
2670 return linenoiseHistoryAddAllocated(strdup(line));
2671 }
2672
2673 int linenoiseHistoryGetMaxLen(void) {
2674 return history_max_len;
2675 }
2676
2677 int linenoiseHistorySetMaxLen(int len) {
2678 char **newHistory;
2679
2680 if (len < 1) return 0;
2681 if (history) {
2682 int tocopy = history_len;
2683
2684 newHistory = (char **)calloc(sizeof(char*), len);
 
2685
2686 /* If we can't copy everything, free the elements we'll not use. */
2687 if (len < tocopy) {
2688 int j;
2689
2690 for (j = 0; j < tocopy-len; j++) free(history[j]);
2691 tocopy = len;
2692 }
2693 memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
 
2694 free(history);
2695 history = newHistory;
2696 }
2697 history_max_len = len;
2698 if (history_len > history_max_len)
2699 history_len = history_max_len;
2700 return 1;
@@ -1186,41 +2701,86 @@
2701 }
2702
2703 /* Save the history in the specified file. On success 0 is returned
2704 * otherwise -1 is returned. */
2705 int linenoiseHistorySave(const char *filename) {
2706 FILE *fp = fopen(filename,"w");
2707 int j;
2708
2709 if (fp == NULL) return -1;
2710 for (j = 0; j < history_len; j++) {
2711 const char *str = history[j];
2712 /* Need to encode backslash, nl and cr */
2713 while (*str) {
2714 if (*str == '\\') {
2715 fputs("\\\\", fp);
2716 }
2717 else if (*str == '\n') {
2718 fputs("\\n", fp);
2719 }
2720 else if (*str == '\r') {
2721 fputs("\\r", fp);
2722 }
2723 else {
2724 fputc(*str, fp);
2725 }
2726 str++;
2727 }
2728 fputc('\n', fp);
2729 }
2730
2731 fclose(fp);
2732 return 0;
2733 }
2734
2735 /* Load the history from the specified file.
2736 *
2737 * If the file does not exist or can't be opened, no operation is performed
2738 * and -1 is returned.
2739 * Otherwise 0 is returned.
2740 */
2741 int linenoiseHistoryLoad(const char *filename) {
2742 FILE *fp = fopen(filename,"r");
2743 stringbuf *sb;
2744
2745 if (fp == NULL) return -1;
2746
2747 while ((sb = sb_getline(fp)) != NULL) {
2748 /* Take the stringbuf and decode backslash escaped values */
2749 char *buf = sb_to_string(sb);
2750 char *dest = buf;
2751 const char *src;
2752
2753 for (src = buf; *src; src++) {
2754 char ch = *src;
2755
2756 if (ch == '\\') {
2757 src++;
2758 if (*src == 'n') {
2759 ch = '\n';
2760 }
2761 else if (*src == 'r') {
2762 ch = '\r';
2763 } else {
2764 ch = *src;
2765 }
2766 }
2767 *dest++ = ch;
2768 }
2769 *dest = 0;
2770
2771 linenoiseHistoryAddAllocated(buf);
2772 }
2773 fclose(fp);
2774 return 0;
2775 }
2776
2777 /* Provide access to the history buffer.
2778 *
2779 * If 'len' is not NULL, the length is stored in *len.
2780 */
2781 char **linenoiseHistory(int *len) {
2782 if (len) {
2783 *len = history_len;
2784 }
2785 return history;
2786 }
2787
+97 -23
--- extsrc/linenoise.h
+++ extsrc/linenoise.h
@@ -1,16 +1,14 @@
1
-/* linenoise.h -- VERSION 1.0
2
- *
3
- * Guerrilla line editing library against the idea that a line editing lib
4
- * needs to be 20,000 lines of C code.
1
+/* linenoise.h -- guerrilla line editing library against the idea that a
2
+ * line editing lib needs to be 20,000 lines of C code.
53
*
64
* See linenoise.c for more information.
75
*
86
* ------------------------------------------------------------------------
97
*
10
- * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
11
- * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
8
+ * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
9
+ * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
1210
*
1311
* All rights reserved.
1412
*
1513
* Redistribution and use in source and binary forms, with or without
1614
* modification, are permitted provided that the following conditions are
@@ -41,35 +39,111 @@
4139
4240
#ifdef __cplusplus
4341
extern "C" {
4442
#endif
4543
44
+#ifndef NO_COMPLETION
4645
typedef struct linenoiseCompletions {
4746
size_t len;
4847
char **cvec;
4948
} linenoiseCompletions;
5049
51
-typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
52
-typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
53
-typedef void(linenoiseFreeHintsCallback)(void *);
54
-void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
55
-void linenoiseSetHintsCallback(linenoiseHintsCallback *);
56
-void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
57
-void linenoiseAddCompletion(linenoiseCompletions *, const char *);
58
-
50
+/*
51
+ * The callback type for tab completion handlers.
52
+ */
53
+typedef void(linenoiseCompletionCallback)(const char *prefix, linenoiseCompletions *comp, void *userdata);
54
+
55
+/*
56
+ * Sets the current tab completion handler and returns the previous one, or NULL
57
+ * if no prior one has been set.
58
+ */
59
+linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *comp, void *userdata);
60
+
61
+/*
62
+ * Adds a copy of the given string to the given completion list. The copy is owned
63
+ * by the linenoiseCompletions object.
64
+ */
65
+void linenoiseAddCompletion(linenoiseCompletions *comp, const char *str);
66
+
67
+typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold, void *userdata);
68
+typedef void(linenoiseFreeHintsCallback)(void *hint, void *userdata);
69
+void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata);
70
+void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback);
71
+
72
+#endif
73
+
74
+/*
75
+ * Prompts for input using the given string as the input
76
+ * prompt. Returns when the user has tapped ENTER or (on an empty
77
+ * line) EOF (Ctrl-D on Unix, Ctrl-Z on Windows). Returns either
78
+ * a copy of the entered string (for ENTER) or NULL (on EOF). The
79
+ * caller owns the returned string and must eventually free() it.
80
+ */
5981
char *linenoise(const char *prompt);
60
-void linenoiseFree(void *ptr);
61
-int linenoiseHistoryAdd(const char *line);
62
-int linenoiseHistorySetMaxLen(int len);
63
-int linenoiseHistorySave(const char *filename);
64
-int linenoiseHistoryLoad(const char *filename);
82
+
83
+/**
84
+ * Like linenoise() but starts with an initial buffer.
85
+ */
86
+char *linenoiseWithInitial(const char *prompt, const char *initial);
87
+
88
+/**
89
+ * Clear the screen.
90
+ */
6591
void linenoiseClearScreen(void);
66
-void linenoiseSetMultiLine(int ml);
67
-void linenoisePrintKeyCodes(void);
68
-void linenoiseMaskModeEnable(void);
69
-void linenoiseMaskModeDisable(void);
92
+
93
+/*
94
+ * Adds a copy of the given line of the command history.
95
+ */
96
+int linenoiseHistoryAdd(const char *line);
97
+
98
+/*
99
+ * Sets the maximum length of the command history, in lines.
100
+ * If the history is currently longer, it will be trimmed,
101
+ * retaining only the most recent entries. If len is 0 or less
102
+ * then this function does nothing.
103
+ */
104
+int linenoiseHistorySetMaxLen(int len);
105
+
106
+/*
107
+ * Returns the current maximum length of the history, in lines.
108
+ */
109
+int linenoiseHistoryGetMaxLen(void);
110
+
111
+/*
112
+ * Saves the current contents of the history to the given file.
113
+ * Returns 0 on success.
114
+ */
115
+int linenoiseHistorySave(const char *filename);
116
+
117
+/*
118
+ * Replaces the current history with the contents
119
+ * of the given file. Returns 0 on success.
120
+ */
121
+int linenoiseHistoryLoad(const char *filename);
122
+
123
+/*
124
+ * Frees all history entries, clearing the history.
125
+ */
126
+void linenoiseHistoryFree(void);
127
+
128
+/*
129
+ * Returns a pointer to the list of history entries, writing its
130
+ * length to *len if len is not NULL. The memory is owned by linenoise
131
+ * and must not be freed.
132
+ */
133
+char **linenoiseHistory(int *len);
134
+
135
+/*
136
+ * Returns the number of display columns in the current terminal.
137
+ */
138
+int linenoiseColumns(void);
139
+
140
+/**
141
+ * Enable or disable multiline mode (disabled by default)
142
+ */
143
+void linenoiseSetMultiLine(int enableml);
70144
71145
#ifdef __cplusplus
72146
}
73147
#endif
74148
75149
#endif /* __LINENOISE_H */
76150
--- extsrc/linenoise.h
+++ extsrc/linenoise.h
@@ -1,16 +1,14 @@
1 /* linenoise.h -- VERSION 1.0
2 *
3 * Guerrilla line editing library against the idea that a line editing lib
4 * needs to be 20,000 lines of C code.
5 *
6 * See linenoise.c for more information.
7 *
8 * ------------------------------------------------------------------------
9 *
10 * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
11 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
12 *
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
@@ -41,35 +39,111 @@
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
 
46 typedef struct linenoiseCompletions {
47 size_t len;
48 char **cvec;
49 } linenoiseCompletions;
50
51 typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
52 typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
53 typedef void(linenoiseFreeHintsCallback)(void *);
54 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
55 void linenoiseSetHintsCallback(linenoiseHintsCallback *);
56 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
57 void linenoiseAddCompletion(linenoiseCompletions *, const char *);
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59 char *linenoise(const char *prompt);
60 void linenoiseFree(void *ptr);
61 int linenoiseHistoryAdd(const char *line);
62 int linenoiseHistorySetMaxLen(int len);
63 int linenoiseHistorySave(const char *filename);
64 int linenoiseHistoryLoad(const char *filename);
 
 
 
 
65 void linenoiseClearScreen(void);
66 void linenoiseSetMultiLine(int ml);
67 void linenoisePrintKeyCodes(void);
68 void linenoiseMaskModeEnable(void);
69 void linenoiseMaskModeDisable(void);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
71 #ifdef __cplusplus
72 }
73 #endif
74
75 #endif /* __LINENOISE_H */
76
--- extsrc/linenoise.h
+++ extsrc/linenoise.h
@@ -1,16 +1,14 @@
1 /* linenoise.h -- guerrilla line editing library against the idea that a
2 * line editing lib needs to be 20,000 lines of C code.
 
 
3 *
4 * See linenoise.c for more information.
5 *
6 * ------------------------------------------------------------------------
7 *
8 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
9 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
10 *
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are
@@ -41,35 +39,111 @@
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 #ifndef NO_COMPLETION
45 typedef struct linenoiseCompletions {
46 size_t len;
47 char **cvec;
48 } linenoiseCompletions;
49
50 /*
51 * The callback type for tab completion handlers.
52 */
53 typedef void(linenoiseCompletionCallback)(const char *prefix, linenoiseCompletions *comp, void *userdata);
54
55 /*
56 * Sets the current tab completion handler and returns the previous one, or NULL
57 * if no prior one has been set.
58 */
59 linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *comp, void *userdata);
60
61 /*
62 * Adds a copy of the given string to the given completion list. The copy is owned
63 * by the linenoiseCompletions object.
64 */
65 void linenoiseAddCompletion(linenoiseCompletions *comp, const char *str);
66
67 typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold, void *userdata);
68 typedef void(linenoiseFreeHintsCallback)(void *hint, void *userdata);
69 void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata);
70 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback);
71
72 #endif
73
74 /*
75 * Prompts for input using the given string as the input
76 * prompt. Returns when the user has tapped ENTER or (on an empty
77 * line) EOF (Ctrl-D on Unix, Ctrl-Z on Windows). Returns either
78 * a copy of the entered string (for ENTER) or NULL (on EOF). The
79 * caller owns the returned string and must eventually free() it.
80 */
81 char *linenoise(const char *prompt);
82
83 /**
84 * Like linenoise() but starts with an initial buffer.
85 */
86 char *linenoiseWithInitial(const char *prompt, const char *initial);
87
88 /**
89 * Clear the screen.
90 */
91 void linenoiseClearScreen(void);
92
93 /*
94 * Adds a copy of the given line of the command history.
95 */
96 int linenoiseHistoryAdd(const char *line);
97
98 /*
99 * Sets the maximum length of the command history, in lines.
100 * If the history is currently longer, it will be trimmed,
101 * retaining only the most recent entries. If len is 0 or less
102 * then this function does nothing.
103 */
104 int linenoiseHistorySetMaxLen(int len);
105
106 /*
107 * Returns the current maximum length of the history, in lines.
108 */
109 int linenoiseHistoryGetMaxLen(void);
110
111 /*
112 * Saves the current contents of the history to the given file.
113 * Returns 0 on success.
114 */
115 int linenoiseHistorySave(const char *filename);
116
117 /*
118 * Replaces the current history with the contents
119 * of the given file. Returns 0 on success.
120 */
121 int linenoiseHistoryLoad(const char *filename);
122
123 /*
124 * Frees all history entries, clearing the history.
125 */
126 void linenoiseHistoryFree(void);
127
128 /*
129 * Returns a pointer to the list of history entries, writing its
130 * length to *len if len is not NULL. The memory is owned by linenoise
131 * and must not be freed.
132 */
133 char **linenoiseHistory(int *len);
134
135 /*
136 * Returns the number of display columns in the current terminal.
137 */
138 int linenoiseColumns(void);
139
140 /**
141 * Enable or disable multiline mode (disabled by default)
142 */
143 void linenoiseSetMultiLine(int enableml);
144
145 #ifdef __cplusplus
146 }
147 #endif
148
149 #endif /* __LINENOISE_H */
150
+6 -5
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -267,11 +267,11 @@
267267
268268
/* Extra token types not generated by LEMON but needed by the
269269
** tokenizer
270270
*/
271271
#define T_PARAMETER 253 /* $1, $2, ..., $9 */
272
-#define T_WHITESPACE 254 /* Whitespace of comments */
272
+#define T_WHITESPACE 254 /* Whitespace or comments */
273273
#define T_ERROR 255 /* Any text that is not a valid token */
274274
275275
/* Directions of movement */
276276
#define DIR_RIGHT 0
277277
#define DIR_DOWN 1
@@ -6122,11 +6122,11 @@
61226122
return;
61236123
}
61246124
pObj->mProp |= A_AT;
61256125
pObj->eWith = pEdge ? pEdge->eEdge : CP_C;
61266126
if( pObj->eWith>=CP_END ){
6127
- int dir = pObj->eWith==CP_END ? pObj->outDir : pObj->inDir;
6127
+ int dir = pObj->eWith==CP_END ? pObj->outDir : (pObj->inDir+2)%4;
61286128
pObj->eWith = eDirToCp[dir];
61296129
}
61306130
pObj->with = *pAt;
61316131
}
61326132
@@ -7436,11 +7436,11 @@
74367436
}
74377437
case ' ':
74387438
case '\t':
74397439
case '\f':
74407440
case '\r': {
7441
- for(i=1; (c = z[i])==' ' || c=='\t' || c=='\r' || c=='\t'; i++){}
7441
+ for(i=1; (c = z[i])==' ' || c=='\t' || c=='\r' || c=='\f'; i++){}
74427442
pToken->eType = T_WHITESPACE;
74437443
return i;
74447444
}
74457445
case '#': {
74467446
for(i=1; (c = z[i])!=0 && c!='\n'; i++){}
@@ -7999,10 +7999,11 @@
79997999
fprintf(stderr, "usage: %s [OPTIONS] FILE ...\n", argv0);
80008000
fprintf(stderr,
80018001
"Convert Pikchr input files into SVG. Filename \"-\" means stdin.\n"
80028002
"All output goes to stdout.\n"
80038003
"Options:\n"
8004
+ " --dark-mode Generate \"dark mode\" output\n"
80048005
" --dont-stop Process all files even if earlier files have errors\n"
80058006
" --svg-only Emit raw SVG without the HTML wrapper\n"
80068007
);
80078008
exit(1);
80088009
}
@@ -8137,11 +8138,11 @@
81378138
continue;
81388139
}
81398140
zIn = readFile(argv[i]);
81408141
if( zIn==0 ) continue;
81418142
zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
8142
- if( w<0 ) exitCode = 1;
8143
+ if( w<0 && !bDontStop ) exitCode = 1;
81438144
if( zOut==0 ){
81448145
fprintf(stderr, "pikchr() returns NULL. Out of memory?\n");
81458146
if( !bDontStop ) exit(1);
81468147
}else if( bSvgOnly ){
81478148
printf("%s\n", zOut);
@@ -8240,6 +8241,6 @@
82408241
82418242
82428243
#endif /* PIKCHR_TCL */
82438244
82448245
8245
-#line 8270 "pikchr.c"
8246
+#line 8271 "pikchr.c"
82468247
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -267,11 +267,11 @@
267
268 /* Extra token types not generated by LEMON but needed by the
269 ** tokenizer
270 */
271 #define T_PARAMETER 253 /* $1, $2, ..., $9 */
272 #define T_WHITESPACE 254 /* Whitespace of comments */
273 #define T_ERROR 255 /* Any text that is not a valid token */
274
275 /* Directions of movement */
276 #define DIR_RIGHT 0
277 #define DIR_DOWN 1
@@ -6122,11 +6122,11 @@
6122 return;
6123 }
6124 pObj->mProp |= A_AT;
6125 pObj->eWith = pEdge ? pEdge->eEdge : CP_C;
6126 if( pObj->eWith>=CP_END ){
6127 int dir = pObj->eWith==CP_END ? pObj->outDir : pObj->inDir;
6128 pObj->eWith = eDirToCp[dir];
6129 }
6130 pObj->with = *pAt;
6131 }
6132
@@ -7436,11 +7436,11 @@
7436 }
7437 case ' ':
7438 case '\t':
7439 case '\f':
7440 case '\r': {
7441 for(i=1; (c = z[i])==' ' || c=='\t' || c=='\r' || c=='\t'; i++){}
7442 pToken->eType = T_WHITESPACE;
7443 return i;
7444 }
7445 case '#': {
7446 for(i=1; (c = z[i])!=0 && c!='\n'; i++){}
@@ -7999,10 +7999,11 @@
7999 fprintf(stderr, "usage: %s [OPTIONS] FILE ...\n", argv0);
8000 fprintf(stderr,
8001 "Convert Pikchr input files into SVG. Filename \"-\" means stdin.\n"
8002 "All output goes to stdout.\n"
8003 "Options:\n"
 
8004 " --dont-stop Process all files even if earlier files have errors\n"
8005 " --svg-only Emit raw SVG without the HTML wrapper\n"
8006 );
8007 exit(1);
8008 }
@@ -8137,11 +8138,11 @@
8137 continue;
8138 }
8139 zIn = readFile(argv[i]);
8140 if( zIn==0 ) continue;
8141 zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
8142 if( w<0 ) exitCode = 1;
8143 if( zOut==0 ){
8144 fprintf(stderr, "pikchr() returns NULL. Out of memory?\n");
8145 if( !bDontStop ) exit(1);
8146 }else if( bSvgOnly ){
8147 printf("%s\n", zOut);
@@ -8240,6 +8241,6 @@
8240
8241
8242 #endif /* PIKCHR_TCL */
8243
8244
8245 #line 8270 "pikchr.c"
8246
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -267,11 +267,11 @@
267
268 /* Extra token types not generated by LEMON but needed by the
269 ** tokenizer
270 */
271 #define T_PARAMETER 253 /* $1, $2, ..., $9 */
272 #define T_WHITESPACE 254 /* Whitespace or comments */
273 #define T_ERROR 255 /* Any text that is not a valid token */
274
275 /* Directions of movement */
276 #define DIR_RIGHT 0
277 #define DIR_DOWN 1
@@ -6122,11 +6122,11 @@
6122 return;
6123 }
6124 pObj->mProp |= A_AT;
6125 pObj->eWith = pEdge ? pEdge->eEdge : CP_C;
6126 if( pObj->eWith>=CP_END ){
6127 int dir = pObj->eWith==CP_END ? pObj->outDir : (pObj->inDir+2)%4;
6128 pObj->eWith = eDirToCp[dir];
6129 }
6130 pObj->with = *pAt;
6131 }
6132
@@ -7436,11 +7436,11 @@
7436 }
7437 case ' ':
7438 case '\t':
7439 case '\f':
7440 case '\r': {
7441 for(i=1; (c = z[i])==' ' || c=='\t' || c=='\r' || c=='\f'; i++){}
7442 pToken->eType = T_WHITESPACE;
7443 return i;
7444 }
7445 case '#': {
7446 for(i=1; (c = z[i])!=0 && c!='\n'; i++){}
@@ -7999,10 +7999,11 @@
7999 fprintf(stderr, "usage: %s [OPTIONS] FILE ...\n", argv0);
8000 fprintf(stderr,
8001 "Convert Pikchr input files into SVG. Filename \"-\" means stdin.\n"
8002 "All output goes to stdout.\n"
8003 "Options:\n"
8004 " --dark-mode Generate \"dark mode\" output\n"
8005 " --dont-stop Process all files even if earlier files have errors\n"
8006 " --svg-only Emit raw SVG without the HTML wrapper\n"
8007 );
8008 exit(1);
8009 }
@@ -8137,11 +8138,11 @@
8138 continue;
8139 }
8140 zIn = readFile(argv[i]);
8141 if( zIn==0 ) continue;
8142 zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
8143 if( w<0 && !bDontStop ) exitCode = 1;
8144 if( zOut==0 ){
8145 fprintf(stderr, "pikchr() returns NULL. Out of memory?\n");
8146 if( !bDontStop ) exit(1);
8147 }else if( bSvgOnly ){
8148 printf("%s\n", zOut);
@@ -8240,6 +8241,6 @@
8241
8242
8243 #endif /* PIKCHR_TCL */
8244
8245
8246 #line 8271 "pikchr.c"
8247
+384 -385
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -1,17 +1,18 @@
11
22
var initPikchrModule = (() => {
33
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
44
55
return (
6
-function(moduleArg = {}) {
6
+function(config) {
7
+ var initPikchrModule = config || {};
78
8
-var Module = moduleArg;
9
+var Module = typeof initPikchrModule != "undefined" ? initPikchrModule : {};
910
1011
var readyPromiseResolve, readyPromiseReject;
1112
12
-Module["ready"] = new Promise((resolve, reject) => {
13
+Module["ready"] = new Promise(function(resolve, reject) {
1314
readyPromiseResolve = resolve;
1415
readyPromiseReject = reject;
1516
});
1617
1718
var moduleOverrides = Object.assign({}, Module);
@@ -35,11 +36,11 @@
3536
return Module["locateFile"](path, scriptDirectory);
3637
}
3738
return scriptDirectory + path;
3839
}
3940
40
-var read_, readAsync, readBinary;
41
+var read_, readAsync, readBinary, setWindowTitle;
4142
4243
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
4344
if (ENVIRONMENT_IS_WORKER) {
4445
scriptDirectory = self.location.href;
4546
} else if (typeof document != "undefined" && document.currentScript) {
@@ -46,51 +47,52 @@
4647
scriptDirectory = document.currentScript.src;
4748
}
4849
if (_scriptDir) {
4950
scriptDirectory = _scriptDir;
5051
}
51
- if (scriptDirectory.startsWith("blob:")) {
52
- scriptDirectory = "";
52
+ if (scriptDirectory.indexOf("blob:") !== 0) {
53
+ scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
5354
} else {
54
- scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
55
+ scriptDirectory = "";
5556
}
5657
{
5758
read_ = url => {
58
- var xhr = new XMLHttpRequest;
59
+ var xhr = new XMLHttpRequest();
5960
xhr.open("GET", url, false);
6061
xhr.send(null);
6162
return xhr.responseText;
6263
};
6364
if (ENVIRONMENT_IS_WORKER) {
6465
readBinary = url => {
65
- var xhr = new XMLHttpRequest;
66
+ var xhr = new XMLHttpRequest();
6667
xhr.open("GET", url, false);
6768
xhr.responseType = "arraybuffer";
6869
xhr.send(null);
69
- return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
70
+ return new Uint8Array(xhr.response);
7071
};
7172
}
7273
readAsync = (url, onload, onerror) => {
73
- var xhr = new XMLHttpRequest;
74
+ var xhr = new XMLHttpRequest();
7475
xhr.open("GET", url, true);
7576
xhr.responseType = "arraybuffer";
7677
xhr.onload = () => {
77
- if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
78
+ if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
7879
onload(xhr.response);
7980
return;
8081
}
8182
onerror();
8283
};
8384
xhr.onerror = onerror;
8485
xhr.send(null);
8586
};
8687
}
88
+ setWindowTitle = title => document.title = title;
8789
} else {}
8890
8991
var out = Module["print"] || console.log.bind(console);
9092
91
-var err = Module["printErr"] || console.error.bind(console);
93
+var err = Module["printErr"] || console.warn.bind(console);
9294
9395
Object.assign(Module, moduleOverrides);
9496
9597
moduleOverrides = null;
9698
@@ -102,10 +104,12 @@
102104
103105
var wasmBinary;
104106
105107
if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
106108
109
+var noExitRuntime = Module["noExitRuntime"] || true;
110
+
107111
if (typeof WebAssembly != "object") {
108112
abort("no native wasm support detected");
109113
}
110114
111115
var wasmMemory;
@@ -112,31 +116,118 @@
112116
113117
var ABORT = false;
114118
115119
var EXITSTATUS;
116120
117
-var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
121
+var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
122
+
123
+function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
124
+ var endIdx = idx + maxBytesToRead;
125
+ var endPtr = idx;
126
+ while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
127
+ if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
128
+ return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
129
+ }
130
+ var str = "";
131
+ while (idx < endPtr) {
132
+ var u0 = heapOrArray[idx++];
133
+ if (!(u0 & 128)) {
134
+ str += String.fromCharCode(u0);
135
+ continue;
136
+ }
137
+ var u1 = heapOrArray[idx++] & 63;
138
+ if ((u0 & 224) == 192) {
139
+ str += String.fromCharCode((u0 & 31) << 6 | u1);
140
+ continue;
141
+ }
142
+ var u2 = heapOrArray[idx++] & 63;
143
+ if ((u0 & 240) == 224) {
144
+ u0 = (u0 & 15) << 12 | u1 << 6 | u2;
145
+ } else {
146
+ u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
147
+ }
148
+ if (u0 < 65536) {
149
+ str += String.fromCharCode(u0);
150
+ } else {
151
+ var ch = u0 - 65536;
152
+ str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
153
+ }
154
+ }
155
+ return str;
156
+}
157
+
158
+function UTF8ToString(ptr, maxBytesToRead) {
159
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
160
+}
161
+
162
+function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
163
+ if (!(maxBytesToWrite > 0)) return 0;
164
+ var startIdx = outIdx;
165
+ var endIdx = outIdx + maxBytesToWrite - 1;
166
+ for (var i = 0; i < str.length; ++i) {
167
+ var u = str.charCodeAt(i);
168
+ if (u >= 55296 && u <= 57343) {
169
+ var u1 = str.charCodeAt(++i);
170
+ u = 65536 + ((u & 1023) << 10) | u1 & 1023;
171
+ }
172
+ if (u <= 127) {
173
+ if (outIdx >= endIdx) break;
174
+ heap[outIdx++] = u;
175
+ } else if (u <= 2047) {
176
+ if (outIdx + 1 >= endIdx) break;
177
+ heap[outIdx++] = 192 | u >> 6;
178
+ heap[outIdx++] = 128 | u & 63;
179
+ } else if (u <= 65535) {
180
+ if (outIdx + 2 >= endIdx) break;
181
+ heap[outIdx++] = 224 | u >> 12;
182
+ heap[outIdx++] = 128 | u >> 6 & 63;
183
+ heap[outIdx++] = 128 | u & 63;
184
+ } else {
185
+ if (outIdx + 3 >= endIdx) break;
186
+ heap[outIdx++] = 240 | u >> 18;
187
+ heap[outIdx++] = 128 | u >> 12 & 63;
188
+ heap[outIdx++] = 128 | u >> 6 & 63;
189
+ heap[outIdx++] = 128 | u & 63;
190
+ }
191
+ }
192
+ heap[outIdx] = 0;
193
+ return outIdx - startIdx;
194
+}
195
+
196
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
197
+ return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
198
+}
199
+
200
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
118201
119202
function updateMemoryViews() {
120203
var b = wasmMemory.buffer;
121204
Module["HEAP8"] = HEAP8 = new Int8Array(b);
122205
Module["HEAP16"] = HEAP16 = new Int16Array(b);
206
+ Module["HEAP32"] = HEAP32 = new Int32Array(b);
123207
Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
124208
Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
125
- Module["HEAP32"] = HEAP32 = new Int32Array(b);
126209
Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
127210
Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
128211
Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
129212
}
213
+
214
+var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 16777216;
215
+
216
+var wasmTable;
130217
131218
var __ATPRERUN__ = [];
132219
133220
var __ATINIT__ = [];
134221
135222
var __ATPOSTRUN__ = [];
136223
137224
var runtimeInitialized = false;
225
+
226
+function keepRuntimeAlive() {
227
+ return noExitRuntime;
228
+}
138229
139230
function preRun() {
140231
if (Module["preRun"]) {
141232
if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
142233
while (Module["preRun"].length) {
@@ -179,16 +270,20 @@
179270
180271
var dependenciesFulfilled = null;
181272
182273
function addRunDependency(id) {
183274
runDependencies++;
184
- Module["monitorRunDependencies"]?.(runDependencies);
275
+ if (Module["monitorRunDependencies"]) {
276
+ Module["monitorRunDependencies"](runDependencies);
277
+ }
185278
}
186279
187280
function removeRunDependency(id) {
188281
runDependencies--;
189
- Module["monitorRunDependencies"]?.(runDependencies);
282
+ if (Module["monitorRunDependencies"]) {
283
+ Module["monitorRunDependencies"](runDependencies);
284
+ }
190285
if (runDependencies == 0) {
191286
if (runDependencyWatcher !== null) {
192287
clearInterval(runDependencyWatcher);
193288
runDependencyWatcher = null;
194289
}
@@ -198,382 +293,278 @@
198293
callback();
199294
}
200295
}
201296
}
202297
203
-/** @param {string|number=} what */ function abort(what) {
204
- Module["onAbort"]?.(what);
298
+function abort(what) {
299
+ if (Module["onAbort"]) {
300
+ Module["onAbort"](what);
301
+ }
205302
what = "Aborted(" + what + ")";
206303
err(what);
207304
ABORT = true;
208305
EXITSTATUS = 1;
209306
what += ". Build with -sASSERTIONS for more info.";
210
- /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
307
+ var e = new WebAssembly.RuntimeError(what);
211308
readyPromiseReject(e);
212309
throw e;
213310
}
214311
215312
var dataURIPrefix = "data:application/octet-stream;base64,";
216313
217
-/**
218
- * Indicates whether filename is a base64 data URI.
219
- * @noinline
220
- */ var isDataURI = filename => filename.startsWith(dataURIPrefix);
314
+function isDataURI(filename) {
315
+ return filename.startsWith(dataURIPrefix);
316
+}
221317
222318
var wasmBinaryFile;
223319
224320
wasmBinaryFile = "pikchr.wasm";
225321
226322
if (!isDataURI(wasmBinaryFile)) {
227323
wasmBinaryFile = locateFile(wasmBinaryFile);
228324
}
229325
230
-function getBinarySync(file) {
231
- if (file == wasmBinaryFile && wasmBinary) {
232
- return new Uint8Array(wasmBinary);
233
- }
234
- if (readBinary) {
235
- return readBinary(file);
236
- }
237
- throw "both async and sync fetching of the wasm failed";
238
-}
239
-
240
-function getBinaryPromise(binaryFile) {
241
- if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
242
- if (typeof fetch == "function") {
243
- return fetch(binaryFile, {
244
- credentials: "same-origin"
245
- }).then(response => {
246
- if (!response["ok"]) {
247
- throw `failed to load wasm binary file at '${binaryFile}'`;
248
- }
249
- return response["arrayBuffer"]();
250
- }).catch(() => getBinarySync(binaryFile));
251
- }
252
- }
253
- return Promise.resolve().then(() => getBinarySync(binaryFile));
254
-}
255
-
256
-function instantiateArrayBuffer(binaryFile, imports, receiver) {
257
- return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(instance => instance).then(receiver, reason => {
258
- err(`failed to asynchronously prepare wasm: ${reason}`);
259
- abort(reason);
260
- });
261
-}
262
-
263
-function instantiateAsync(binary, binaryFile, imports, callback) {
264
- if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && typeof fetch == "function") {
265
- return fetch(binaryFile, {
266
- credentials: "same-origin"
267
- }).then(response => {
268
- /** @suppress {checkTypes} */ var result = WebAssembly.instantiateStreaming(response, imports);
269
- return result.then(callback, function(reason) {
270
- err(`wasm streaming compile failed: ${reason}`);
271
- err("falling back to ArrayBuffer instantiation");
272
- return instantiateArrayBuffer(binaryFile, imports, callback);
273
- });
274
- });
275
- }
276
- return instantiateArrayBuffer(binaryFile, imports, callback);
326
+function getBinary(file) {
327
+ try {
328
+ if (file == wasmBinaryFile && wasmBinary) {
329
+ return new Uint8Array(wasmBinary);
330
+ }
331
+ if (readBinary) {
332
+ return readBinary(file);
333
+ }
334
+ throw "both async and sync fetching of the wasm failed";
335
+ } catch (err) {
336
+ abort(err);
337
+ }
338
+}
339
+
340
+function getBinaryPromise() {
341
+ if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
342
+ if (typeof fetch == "function") {
343
+ return fetch(wasmBinaryFile, {
344
+ credentials: "same-origin"
345
+ }).then(function(response) {
346
+ if (!response["ok"]) {
347
+ throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
348
+ }
349
+ return response["arrayBuffer"]();
350
+ }).catch(function() {
351
+ return getBinary(wasmBinaryFile);
352
+ });
353
+ }
354
+ }
355
+ return Promise.resolve().then(function() {
356
+ return getBinary(wasmBinaryFile);
357
+ });
277358
}
278359
279360
function createWasm() {
280361
var info = {
281
- "a": wasmImports
362
+ "a": asmLibraryArg
282363
};
283
- /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
284
- wasmExports = instance.exports;
285
- wasmMemory = wasmExports["d"];
364
+ function receiveInstance(instance, module) {
365
+ var exports = instance.exports;
366
+ Module["asm"] = exports;
367
+ wasmMemory = Module["asm"]["d"];
286368
updateMemoryViews();
287
- addOnInit(wasmExports["e"]);
369
+ wasmTable = Module["asm"]["g"];
370
+ addOnInit(Module["asm"]["e"]);
288371
removeRunDependency("wasm-instantiate");
289
- return wasmExports;
290372
}
291373
addRunDependency("wasm-instantiate");
292374
function receiveInstantiationResult(result) {
293375
receiveInstance(result["instance"]);
294376
}
295
- if (Module["instantiateWasm"]) {
296
- try {
297
- return Module["instantiateWasm"](info, receiveInstance);
298
- } catch (e) {
299
- err(`Module.instantiateWasm callback failed with error: ${e}`);
300
- readyPromiseReject(e);
301
- }
302
- }
303
- instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
304
- return {};
305
-}
306
-
307
-/** @constructor */ function ExitStatus(status) {
308
- this.name = "ExitStatus";
309
- this.message = `Program terminated with exit(${status})`;
310
- this.status = status;
311
-}
312
-
313
-var callRuntimeCallbacks = callbacks => {
314
- while (callbacks.length > 0) {
315
- callbacks.shift()(Module);
316
- }
317
-};
318
-
319
-/**
320
- * @param {number} ptr
321
- * @param {string} type
322
- */ function getValue(ptr, type = "i8") {
323
- if (type.endsWith("*")) type = "*";
324
- switch (type) {
325
- case "i1":
326
- return HEAP8[((ptr) >> 0)];
327
-
328
- case "i8":
329
- return HEAP8[((ptr) >> 0)];
330
-
331
- case "i16":
332
- return HEAP16[((ptr) >> 1)];
333
-
334
- case "i32":
335
- return HEAP32[((ptr) >> 2)];
336
-
337
- case "i64":
338
- abort("to do getValue(i64) use WASM_BIGINT");
339
-
340
- case "float":
341
- return HEAPF32[((ptr) >> 2)];
342
-
343
- case "double":
344
- return HEAPF64[((ptr) >> 3)];
345
-
346
- case "*":
347
- return HEAPU32[((ptr) >> 2)];
348
-
349
- default:
350
- abort(`invalid type for getValue: ${type}`);
351
- }
352
-}
353
-
354
-var noExitRuntime = Module["noExitRuntime"] || true;
355
-
356
-/**
357
- * @param {number} ptr
358
- * @param {number} value
359
- * @param {string} type
360
- */ function setValue(ptr, value, type = "i8") {
361
- if (type.endsWith("*")) type = "*";
362
- switch (type) {
363
- case "i1":
364
- HEAP8[((ptr) >> 0)] = value;
365
- break;
366
-
367
- case "i8":
368
- HEAP8[((ptr) >> 0)] = value;
369
- break;
370
-
371
- case "i16":
372
- HEAP16[((ptr) >> 1)] = value;
373
- break;
374
-
375
- case "i32":
376
- HEAP32[((ptr) >> 2)] = value;
377
- break;
378
-
379
- case "i64":
380
- abort("to do setValue(i64) use WASM_BIGINT");
381
-
382
- case "float":
383
- HEAPF32[((ptr) >> 2)] = value;
384
- break;
385
-
386
- case "double":
387
- HEAPF64[((ptr) >> 3)] = value;
388
- break;
389
-
390
- case "*":
391
- HEAPU32[((ptr) >> 2)] = value;
392
- break;
393
-
394
- default:
395
- abort(`invalid type for setValue: ${type}`);
396
- }
397
-}
398
-
399
-var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
400
-
401
-/**
402
- * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
403
- * array that contains uint8 values, returns a copy of that string as a
404
- * Javascript String object.
405
- * heapOrArray is either a regular array, or a JavaScript typed array view.
406
- * @param {number} idx
407
- * @param {number=} maxBytesToRead
408
- * @return {string}
409
- */ var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
410
- var endIdx = idx + maxBytesToRead;
411
- var endPtr = idx;
412
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
413
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
414
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
415
- }
416
- var str = "";
417
- while (idx < endPtr) {
418
- var u0 = heapOrArray[idx++];
419
- if (!(u0 & 128)) {
420
- str += String.fromCharCode(u0);
421
- continue;
422
- }
423
- var u1 = heapOrArray[idx++] & 63;
424
- if ((u0 & 224) == 192) {
425
- str += String.fromCharCode(((u0 & 31) << 6) | u1);
426
- continue;
427
- }
428
- var u2 = heapOrArray[idx++] & 63;
429
- if ((u0 & 240) == 224) {
430
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
431
- } else {
432
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
433
- }
434
- if (u0 < 65536) {
435
- str += String.fromCharCode(u0);
436
- } else {
437
- var ch = u0 - 65536;
438
- str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
439
- }
440
- }
441
- return str;
442
-};
443
-
444
-/**
445
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
446
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
447
- *
448
- * @param {number} ptr
449
- * @param {number=} maxBytesToRead - An optional length that specifies the
450
- * maximum number of bytes to read. You can omit this parameter to scan the
451
- * string until the first 0 byte. If maxBytesToRead is passed, and the string
452
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
453
- * string will cut short at that byte index (i.e. maxBytesToRead will not
454
- * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
455
- * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
456
- * JS JIT optimizations off, so it is worth to consider consistently using one
457
- * @return {string}
458
- */ var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
459
-
460
-var ___assert_fail = (condition, filename, line, func) => {
461
- abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
462
-};
463
-
464
-var abortOnCannotGrowMemory = requestedSize => {
465
- abort("OOM");
466
-};
467
-
468
-var _emscripten_resize_heap = requestedSize => {
469
- var oldSize = HEAPU8.length;
470
- requestedSize >>>= 0;
471
- abortOnCannotGrowMemory(requestedSize);
472
-};
473
-
474
-var runtimeKeepaliveCounter = 0;
475
-
476
-var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
477
-
478
-var _proc_exit = code => {
479
- EXITSTATUS = code;
480
- if (!keepRuntimeAlive()) {
481
- Module["onExit"]?.(code);
482
- ABORT = true;
483
- }
484
- quit_(code, new ExitStatus(code));
485
-};
486
-
487
-/** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
488
- EXITSTATUS = status;
489
- _proc_exit(status);
490
-};
491
-
492
-var _exit = exitJS;
493
-
494
-var getCFunc = ident => {
495
- var func = Module["_" + ident];
496
- return func;
497
-};
498
-
499
-var writeArrayToMemory = (array, buffer) => {
500
- HEAP8.set(array, buffer);
501
-};
502
-
503
-var lengthBytesUTF8 = str => {
504
- var len = 0;
505
- for (var i = 0; i < str.length; ++i) {
506
- var c = str.charCodeAt(i);
507
- if (c <= 127) {
508
- len++;
509
- } else if (c <= 2047) {
510
- len += 2;
511
- } else if (c >= 55296 && c <= 57343) {
512
- len += 4;
513
- ++i;
514
- } else {
515
- len += 3;
516
- }
517
- }
518
- return len;
519
-};
520
-
521
-var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
522
- if (!(maxBytesToWrite > 0)) return 0;
523
- var startIdx = outIdx;
524
- var endIdx = outIdx + maxBytesToWrite - 1;
525
- for (var i = 0; i < str.length; ++i) {
526
- var u = str.charCodeAt(i);
527
- if (u >= 55296 && u <= 57343) {
528
- var u1 = str.charCodeAt(++i);
529
- u = 65536 + ((u & 1023) << 10) | (u1 & 1023);
530
- }
531
- if (u <= 127) {
532
- if (outIdx >= endIdx) break;
533
- heap[outIdx++] = u;
534
- } else if (u <= 2047) {
535
- if (outIdx + 1 >= endIdx) break;
536
- heap[outIdx++] = 192 | (u >> 6);
537
- heap[outIdx++] = 128 | (u & 63);
538
- } else if (u <= 65535) {
539
- if (outIdx + 2 >= endIdx) break;
540
- heap[outIdx++] = 224 | (u >> 12);
541
- heap[outIdx++] = 128 | ((u >> 6) & 63);
542
- heap[outIdx++] = 128 | (u & 63);
543
- } else {
544
- if (outIdx + 3 >= endIdx) break;
545
- heap[outIdx++] = 240 | (u >> 18);
546
- heap[outIdx++] = 128 | ((u >> 12) & 63);
547
- heap[outIdx++] = 128 | ((u >> 6) & 63);
548
- heap[outIdx++] = 128 | (u & 63);
549
- }
550
- }
551
- heap[outIdx] = 0;
552
- return outIdx - startIdx;
553
-};
554
-
555
-var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
556
-
557
-var stringToUTF8OnStack = str => {
558
- var size = lengthBytesUTF8(str) + 1;
559
- var ret = stackAlloc(size);
560
- stringToUTF8(str, ret, size);
561
- return ret;
562
-};
563
-
564
-/**
565
- * @param {string|null=} returnType
566
- * @param {Array=} argTypes
567
- * @param {Arguments|Array=} args
568
- * @param {Object=} opts
569
- */ var ccall = (ident, returnType, argTypes, args, opts) => {
377
+ function instantiateArrayBuffer(receiver) {
378
+ return getBinaryPromise().then(function(binary) {
379
+ return WebAssembly.instantiate(binary, info);
380
+ }).then(function(instance) {
381
+ return instance;
382
+ }).then(receiver, function(reason) {
383
+ err("failed to asynchronously prepare wasm: " + reason);
384
+ abort(reason);
385
+ });
386
+ }
387
+ function instantiateAsync() {
388
+ if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && typeof fetch == "function") {
389
+ return fetch(wasmBinaryFile, {
390
+ credentials: "same-origin"
391
+ }).then(function(response) {
392
+ var result = WebAssembly.instantiateStreaming(response, info);
393
+ return result.then(receiveInstantiationResult, function(reason) {
394
+ err("wasm streaming compile failed: " + reason);
395
+ err("falling back to ArrayBuffer instantiation");
396
+ return instantiateArrayBuffer(receiveInstantiationResult);
397
+ });
398
+ });
399
+ } else {
400
+ return instantiateArrayBuffer(receiveInstantiationResult);
401
+ }
402
+ }
403
+ if (Module["instantiateWasm"]) {
404
+ try {
405
+ var exports = Module["instantiateWasm"](info, receiveInstance);
406
+ return exports;
407
+ } catch (e) {
408
+ err("Module.instantiateWasm callback failed with error: " + e);
409
+ readyPromiseReject(e);
410
+ }
411
+ }
412
+ instantiateAsync().catch(readyPromiseReject);
413
+ return {};
414
+}
415
+
416
+var tempDouble;
417
+
418
+var tempI64;
419
+
420
+function ExitStatus(status) {
421
+ this.name = "ExitStatus";
422
+ this.message = "Program terminated with exit(" + status + ")";
423
+ this.status = status;
424
+}
425
+
426
+function callRuntimeCallbacks(callbacks) {
427
+ while (callbacks.length > 0) {
428
+ callbacks.shift()(Module);
429
+ }
430
+}
431
+
432
+function getValue(ptr, type = "i8") {
433
+ if (type.endsWith("*")) type = "*";
434
+ switch (type) {
435
+ case "i1":
436
+ return HEAP8[ptr >> 0];
437
+
438
+ case "i8":
439
+ return HEAP8[ptr >> 0];
440
+
441
+ case "i16":
442
+ return HEAP16[ptr >> 1];
443
+
444
+ case "i32":
445
+ return HEAP32[ptr >> 2];
446
+
447
+ case "i64":
448
+ return HEAP32[ptr >> 2];
449
+
450
+ case "float":
451
+ return HEAPF32[ptr >> 2];
452
+
453
+ case "double":
454
+ return HEAPF64[ptr >> 3];
455
+
456
+ case "*":
457
+ return HEAPU32[ptr >> 2];
458
+
459
+ default:
460
+ abort("invalid type for getValue: " + type);
461
+ }
462
+ return null;
463
+}
464
+
465
+function setValue(ptr, value, type = "i8") {
466
+ if (type.endsWith("*")) type = "*";
467
+ switch (type) {
468
+ case "i1":
469
+ HEAP8[ptr >> 0] = value;
470
+ break;
471
+
472
+ case "i8":
473
+ HEAP8[ptr >> 0] = value;
474
+ break;
475
+
476
+ case "i16":
477
+ HEAP16[ptr >> 1] = value;
478
+ break;
479
+
480
+ case "i32":
481
+ HEAP32[ptr >> 2] = value;
482
+ break;
483
+
484
+ case "i64":
485
+ tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
486
+ HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
487
+ break;
488
+
489
+ case "float":
490
+ HEAPF32[ptr >> 2] = value;
491
+ break;
492
+
493
+ case "double":
494
+ HEAPF64[ptr >> 3] = value;
495
+ break;
496
+
497
+ case "*":
498
+ HEAPU32[ptr >> 2] = value;
499
+ break;
500
+
501
+ default:
502
+ abort("invalid type for setValue: " + type);
503
+ }
504
+}
505
+
506
+function ___assert_fail(condition, filename, line, func) {
507
+ abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
508
+}
509
+
510
+function abortOnCannotGrowMemory(requestedSize) {
511
+ abort("OOM");
512
+}
513
+
514
+function _emscripten_resize_heap(requestedSize) {
515
+ var oldSize = HEAPU8.length;
516
+ requestedSize = requestedSize >>> 0;
517
+ abortOnCannotGrowMemory(requestedSize);
518
+}
519
+
520
+var SYSCALLS = {
521
+ varargs: undefined,
522
+ get: function() {
523
+ SYSCALLS.varargs += 4;
524
+ var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
525
+ return ret;
526
+ },
527
+ getStr: function(ptr) {
528
+ var ret = UTF8ToString(ptr);
529
+ return ret;
530
+ }
531
+};
532
+
533
+function _proc_exit(code) {
534
+ EXITSTATUS = code;
535
+ if (!keepRuntimeAlive()) {
536
+ if (Module["onExit"]) Module["onExit"](code);
537
+ ABORT = true;
538
+ }
539
+ quit_(code, new ExitStatus(code));
540
+}
541
+
542
+function exitJS(status, implicit) {
543
+ EXITSTATUS = status;
544
+ _proc_exit(status);
545
+}
546
+
547
+var _exit = exitJS;
548
+
549
+function getCFunc(ident) {
550
+ var func = Module["_" + ident];
551
+ return func;
552
+}
553
+
554
+function writeArrayToMemory(array, buffer) {
555
+ HEAP8.set(array, buffer);
556
+}
557
+
558
+function ccall(ident, returnType, argTypes, args, opts) {
570559
var toC = {
571560
"string": str => {
572561
var ret = 0;
573562
if (str !== null && str !== undefined && str !== 0) {
574
- ret = stringToUTF8OnStack(str);
563
+ var len = (str.length << 2) + 1;
564
+ ret = stackAlloc(len);
565
+ stringToUTF8(str, ret, len);
575566
}
576567
return ret;
577568
},
578569
"array": arr => {
579570
var ret = stackAlloc(arr.length);
@@ -607,46 +598,51 @@
607598
if (stack !== 0) stackRestore(stack);
608599
return convertReturnValue(ret);
609600
}
610601
ret = onDone(ret);
611602
return ret;
612
-};
613
-
614
-/**
615
- * @param {string=} returnType
616
- * @param {Array=} argTypes
617
- * @param {Object=} opts
618
- */ var cwrap = (ident, returnType, argTypes, opts) => {
619
- var numericArgs = !argTypes || argTypes.every(type => type === "number" || type === "boolean");
603
+}
604
+
605
+function cwrap(ident, returnType, argTypes, opts) {
606
+ argTypes = argTypes || [];
607
+ var numericArgs = argTypes.every(type => type === "number" || type === "boolean");
620608
var numericRet = returnType !== "string";
621609
if (numericRet && numericArgs && !opts) {
622610
return getCFunc(ident);
623611
}
624612
return function() {
625613
return ccall(ident, returnType, argTypes, arguments, opts);
626614
};
627
-};
628
-
629
-var wasmImports = {
630
- /** @export */ a: ___assert_fail,
631
- /** @export */ b: _emscripten_resize_heap,
632
- /** @export */ c: _exit
633
-};
634
-
635
-var wasmExports = createWasm();
636
-
637
-var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["e"])();
638
-
639
-var _pikchr = Module["_pikchr"] = (a0, a1, a2, a3, a4) => (_pikchr = Module["_pikchr"] = wasmExports["f"])(a0, a1, a2, a3, a4);
640
-
641
-var stackSave = () => (stackSave = wasmExports["h"])();
642
-
643
-var stackRestore = a0 => (stackRestore = wasmExports["i"])(a0);
644
-
645
-var stackAlloc = a0 => (stackAlloc = wasmExports["j"])(a0);
646
-
647
-Module["stackAlloc"] = stackAlloc;
615
+}
616
+
617
+var asmLibraryArg = {
618
+ "a": ___assert_fail,
619
+ "b": _emscripten_resize_heap,
620
+ "c": _exit
621
+};
622
+
623
+var asm = createWasm();
624
+
625
+var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
626
+ return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["e"]).apply(null, arguments);
627
+};
628
+
629
+var _pikchr = Module["_pikchr"] = function() {
630
+ return (_pikchr = Module["_pikchr"] = Module["asm"]["f"]).apply(null, arguments);
631
+};
632
+
633
+var stackSave = Module["stackSave"] = function() {
634
+ return (stackSave = Module["stackSave"] = Module["asm"]["h"]).apply(null, arguments);
635
+};
636
+
637
+var stackRestore = Module["stackRestore"] = function() {
638
+ return (stackRestore = Module["stackRestore"] = Module["asm"]["i"]).apply(null, arguments);
639
+};
640
+
641
+var stackAlloc = Module["stackAlloc"] = function() {
642
+ return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
643
+};
648644
649645
Module["stackSave"] = stackSave;
650646
651647
Module["stackRestore"] = stackRestore;
652648
@@ -661,11 +657,12 @@
661657
dependenciesFulfilled = function runCaller() {
662658
if (!calledRun) run();
663659
if (!calledRun) dependenciesFulfilled = runCaller;
664660
};
665661
666
-function run() {
662
+function run(args) {
663
+ args = args || arguments_;
667664
if (runDependencies > 0) {
668665
return;
669666
}
670667
preRun();
671668
if (runDependencies > 0) {
@@ -702,13 +699,15 @@
702699
}
703700
704701
run();
705702
706703
707
- return moduleArg.ready
704
+ return initPikchrModule.ready
708705
}
709706
);
710707
})();
711708
if (typeof exports === 'object' && typeof module === 'object')
712709
module.exports = initPikchrModule;
713710
else if (typeof define === 'function' && define['amd'])
714
- define([], () => initPikchrModule);
711
+ define([], function() { return initPikchrModule; });
712
+else if (typeof exports === 'object')
713
+ exports["initPikchrModule"] = initPikchrModule;
715714
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -1,17 +1,18 @@
1
2 var initPikchrModule = (() => {
3 var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
4
5 return (
6 function(moduleArg = {}) {
 
7
8 var Module = moduleArg;
9
10 var readyPromiseResolve, readyPromiseReject;
11
12 Module["ready"] = new Promise((resolve, reject) => {
13 readyPromiseResolve = resolve;
14 readyPromiseReject = reject;
15 });
16
17 var moduleOverrides = Object.assign({}, Module);
@@ -35,11 +36,11 @@
35 return Module["locateFile"](path, scriptDirectory);
36 }
37 return scriptDirectory + path;
38 }
39
40 var read_, readAsync, readBinary;
41
42 if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
43 if (ENVIRONMENT_IS_WORKER) {
44 scriptDirectory = self.location.href;
45 } else if (typeof document != "undefined" && document.currentScript) {
@@ -46,51 +47,52 @@
46 scriptDirectory = document.currentScript.src;
47 }
48 if (_scriptDir) {
49 scriptDirectory = _scriptDir;
50 }
51 if (scriptDirectory.startsWith("blob:")) {
52 scriptDirectory = "";
53 } else {
54 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
55 }
56 {
57 read_ = url => {
58 var xhr = new XMLHttpRequest;
59 xhr.open("GET", url, false);
60 xhr.send(null);
61 return xhr.responseText;
62 };
63 if (ENVIRONMENT_IS_WORKER) {
64 readBinary = url => {
65 var xhr = new XMLHttpRequest;
66 xhr.open("GET", url, false);
67 xhr.responseType = "arraybuffer";
68 xhr.send(null);
69 return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
70 };
71 }
72 readAsync = (url, onload, onerror) => {
73 var xhr = new XMLHttpRequest;
74 xhr.open("GET", url, true);
75 xhr.responseType = "arraybuffer";
76 xhr.onload = () => {
77 if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
78 onload(xhr.response);
79 return;
80 }
81 onerror();
82 };
83 xhr.onerror = onerror;
84 xhr.send(null);
85 };
86 }
 
87 } else {}
88
89 var out = Module["print"] || console.log.bind(console);
90
91 var err = Module["printErr"] || console.error.bind(console);
92
93 Object.assign(Module, moduleOverrides);
94
95 moduleOverrides = null;
96
@@ -102,10 +104,12 @@
102
103 var wasmBinary;
104
105 if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
106
 
 
107 if (typeof WebAssembly != "object") {
108 abort("no native wasm support detected");
109 }
110
111 var wasmMemory;
@@ -112,31 +116,118 @@
112
113 var ABORT = false;
114
115 var EXITSTATUS;
116
117 var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
119 function updateMemoryViews() {
120 var b = wasmMemory.buffer;
121 Module["HEAP8"] = HEAP8 = new Int8Array(b);
122 Module["HEAP16"] = HEAP16 = new Int16Array(b);
 
123 Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
124 Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
125 Module["HEAP32"] = HEAP32 = new Int32Array(b);
126 Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
127 Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
128 Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
129 }
 
 
 
 
130
131 var __ATPRERUN__ = [];
132
133 var __ATINIT__ = [];
134
135 var __ATPOSTRUN__ = [];
136
137 var runtimeInitialized = false;
 
 
 
 
138
139 function preRun() {
140 if (Module["preRun"]) {
141 if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
142 while (Module["preRun"].length) {
@@ -179,16 +270,20 @@
179
180 var dependenciesFulfilled = null;
181
182 function addRunDependency(id) {
183 runDependencies++;
184 Module["monitorRunDependencies"]?.(runDependencies);
 
 
185 }
186
187 function removeRunDependency(id) {
188 runDependencies--;
189 Module["monitorRunDependencies"]?.(runDependencies);
 
 
190 if (runDependencies == 0) {
191 if (runDependencyWatcher !== null) {
192 clearInterval(runDependencyWatcher);
193 runDependencyWatcher = null;
194 }
@@ -198,382 +293,278 @@
198 callback();
199 }
200 }
201 }
202
203 /** @param {string|number=} what */ function abort(what) {
204 Module["onAbort"]?.(what);
 
 
205 what = "Aborted(" + what + ")";
206 err(what);
207 ABORT = true;
208 EXITSTATUS = 1;
209 what += ". Build with -sASSERTIONS for more info.";
210 /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
211 readyPromiseReject(e);
212 throw e;
213 }
214
215 var dataURIPrefix = "data:application/octet-stream;base64,";
216
217 /**
218 * Indicates whether filename is a base64 data URI.
219 * @noinline
220 */ var isDataURI = filename => filename.startsWith(dataURIPrefix);
221
222 var wasmBinaryFile;
223
224 wasmBinaryFile = "pikchr.wasm";
225
226 if (!isDataURI(wasmBinaryFile)) {
227 wasmBinaryFile = locateFile(wasmBinaryFile);
228 }
229
230 function getBinarySync(file) {
231 if (file == wasmBinaryFile && wasmBinary) {
232 return new Uint8Array(wasmBinary);
233 }
234 if (readBinary) {
235 return readBinary(file);
236 }
237 throw "both async and sync fetching of the wasm failed";
238 }
239
240 function getBinaryPromise(binaryFile) {
241 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
242 if (typeof fetch == "function") {
243 return fetch(binaryFile, {
244 credentials: "same-origin"
245 }).then(response => {
246 if (!response["ok"]) {
247 throw `failed to load wasm binary file at '${binaryFile}'`;
248 }
249 return response["arrayBuffer"]();
250 }).catch(() => getBinarySync(binaryFile));
251 }
252 }
253 return Promise.resolve().then(() => getBinarySync(binaryFile));
254 }
255
256 function instantiateArrayBuffer(binaryFile, imports, receiver) {
257 return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(instance => instance).then(receiver, reason => {
258 err(`failed to asynchronously prepare wasm: ${reason}`);
259 abort(reason);
260 });
261 }
262
263 function instantiateAsync(binary, binaryFile, imports, callback) {
264 if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && typeof fetch == "function") {
265 return fetch(binaryFile, {
266 credentials: "same-origin"
267 }).then(response => {
268 /** @suppress {checkTypes} */ var result = WebAssembly.instantiateStreaming(response, imports);
269 return result.then(callback, function(reason) {
270 err(`wasm streaming compile failed: ${reason}`);
271 err("falling back to ArrayBuffer instantiation");
272 return instantiateArrayBuffer(binaryFile, imports, callback);
273 });
274 });
275 }
276 return instantiateArrayBuffer(binaryFile, imports, callback);
277 }
278
279 function createWasm() {
280 var info = {
281 "a": wasmImports
282 };
283 /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
284 wasmExports = instance.exports;
285 wasmMemory = wasmExports["d"];
 
286 updateMemoryViews();
287 addOnInit(wasmExports["e"]);
 
288 removeRunDependency("wasm-instantiate");
289 return wasmExports;
290 }
291 addRunDependency("wasm-instantiate");
292 function receiveInstantiationResult(result) {
293 receiveInstance(result["instance"]);
294 }
295 if (Module["instantiateWasm"]) {
296 try {
297 return Module["instantiateWasm"](info, receiveInstance);
298 } catch (e) {
299 err(`Module.instantiateWasm callback failed with error: ${e}`);
300 readyPromiseReject(e);
301 }
302 }
303 instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
304 return {};
305 }
306
307 /** @constructor */ function ExitStatus(status) {
308 this.name = "ExitStatus";
309 this.message = `Program terminated with exit(${status})`;
310 this.status = status;
311 }
312
313 var callRuntimeCallbacks = callbacks => {
314 while (callbacks.length > 0) {
315 callbacks.shift()(Module);
316 }
317 };
318
319 /**
320 * @param {number} ptr
321 * @param {string} type
322 */ function getValue(ptr, type = "i8") {
323 if (type.endsWith("*")) type = "*";
324 switch (type) {
325 case "i1":
326 return HEAP8[((ptr) >> 0)];
327
328 case "i8":
329 return HEAP8[((ptr) >> 0)];
330
331 case "i16":
332 return HEAP16[((ptr) >> 1)];
333
334 case "i32":
335 return HEAP32[((ptr) >> 2)];
336
337 case "i64":
338 abort("to do getValue(i64) use WASM_BIGINT");
339
340 case "float":
341 return HEAPF32[((ptr) >> 2)];
342
343 case "double":
344 return HEAPF64[((ptr) >> 3)];
345
346 case "*":
347 return HEAPU32[((ptr) >> 2)];
348
349 default:
350 abort(`invalid type for getValue: ${type}`);
351 }
352 }
353
354 var noExitRuntime = Module["noExitRuntime"] || true;
355
356 /**
357 * @param {number} ptr
358 * @param {number} value
359 * @param {string} type
360 */ function setValue(ptr, value, type = "i8") {
361 if (type.endsWith("*")) type = "*";
362 switch (type) {
363 case "i1":
364 HEAP8[((ptr) >> 0)] = value;
365 break;
366
367 case "i8":
368 HEAP8[((ptr) >> 0)] = value;
369 break;
370
371 case "i16":
372 HEAP16[((ptr) >> 1)] = value;
373 break;
374
375 case "i32":
376 HEAP32[((ptr) >> 2)] = value;
377 break;
378
379 case "i64":
380 abort("to do setValue(i64) use WASM_BIGINT");
381
382 case "float":
383 HEAPF32[((ptr) >> 2)] = value;
384 break;
385
386 case "double":
387 HEAPF64[((ptr) >> 3)] = value;
388 break;
389
390 case "*":
391 HEAPU32[((ptr) >> 2)] = value;
392 break;
393
394 default:
395 abort(`invalid type for setValue: ${type}`);
396 }
397 }
398
399 var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
400
401 /**
402 * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
403 * array that contains uint8 values, returns a copy of that string as a
404 * Javascript String object.
405 * heapOrArray is either a regular array, or a JavaScript typed array view.
406 * @param {number} idx
407 * @param {number=} maxBytesToRead
408 * @return {string}
409 */ var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
410 var endIdx = idx + maxBytesToRead;
411 var endPtr = idx;
412 while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
413 if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
414 return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
415 }
416 var str = "";
417 while (idx < endPtr) {
418 var u0 = heapOrArray[idx++];
419 if (!(u0 & 128)) {
420 str += String.fromCharCode(u0);
421 continue;
422 }
423 var u1 = heapOrArray[idx++] & 63;
424 if ((u0 & 224) == 192) {
425 str += String.fromCharCode(((u0 & 31) << 6) | u1);
426 continue;
427 }
428 var u2 = heapOrArray[idx++] & 63;
429 if ((u0 & 240) == 224) {
430 u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
431 } else {
432 u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
433 }
434 if (u0 < 65536) {
435 str += String.fromCharCode(u0);
436 } else {
437 var ch = u0 - 65536;
438 str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
439 }
440 }
441 return str;
442 };
443
444 /**
445 * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
446 * emscripten HEAP, returns a copy of that string as a Javascript String object.
447 *
448 * @param {number} ptr
449 * @param {number=} maxBytesToRead - An optional length that specifies the
450 * maximum number of bytes to read. You can omit this parameter to scan the
451 * string until the first 0 byte. If maxBytesToRead is passed, and the string
452 * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
453 * string will cut short at that byte index (i.e. maxBytesToRead will not
454 * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
455 * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
456 * JS JIT optimizations off, so it is worth to consider consistently using one
457 * @return {string}
458 */ var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
459
460 var ___assert_fail = (condition, filename, line, func) => {
461 abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
462 };
463
464 var abortOnCannotGrowMemory = requestedSize => {
465 abort("OOM");
466 };
467
468 var _emscripten_resize_heap = requestedSize => {
469 var oldSize = HEAPU8.length;
470 requestedSize >>>= 0;
471 abortOnCannotGrowMemory(requestedSize);
472 };
473
474 var runtimeKeepaliveCounter = 0;
475
476 var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
477
478 var _proc_exit = code => {
479 EXITSTATUS = code;
480 if (!keepRuntimeAlive()) {
481 Module["onExit"]?.(code);
482 ABORT = true;
483 }
484 quit_(code, new ExitStatus(code));
485 };
486
487 /** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
488 EXITSTATUS = status;
489 _proc_exit(status);
490 };
491
492 var _exit = exitJS;
493
494 var getCFunc = ident => {
495 var func = Module["_" + ident];
496 return func;
497 };
498
499 var writeArrayToMemory = (array, buffer) => {
500 HEAP8.set(array, buffer);
501 };
502
503 var lengthBytesUTF8 = str => {
504 var len = 0;
505 for (var i = 0; i < str.length; ++i) {
506 var c = str.charCodeAt(i);
507 if (c <= 127) {
508 len++;
509 } else if (c <= 2047) {
510 len += 2;
511 } else if (c >= 55296 && c <= 57343) {
512 len += 4;
513 ++i;
514 } else {
515 len += 3;
516 }
517 }
518 return len;
519 };
520
521 var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
522 if (!(maxBytesToWrite > 0)) return 0;
523 var startIdx = outIdx;
524 var endIdx = outIdx + maxBytesToWrite - 1;
525 for (var i = 0; i < str.length; ++i) {
526 var u = str.charCodeAt(i);
527 if (u >= 55296 && u <= 57343) {
528 var u1 = str.charCodeAt(++i);
529 u = 65536 + ((u & 1023) << 10) | (u1 & 1023);
530 }
531 if (u <= 127) {
532 if (outIdx >= endIdx) break;
533 heap[outIdx++] = u;
534 } else if (u <= 2047) {
535 if (outIdx + 1 >= endIdx) break;
536 heap[outIdx++] = 192 | (u >> 6);
537 heap[outIdx++] = 128 | (u & 63);
538 } else if (u <= 65535) {
539 if (outIdx + 2 >= endIdx) break;
540 heap[outIdx++] = 224 | (u >> 12);
541 heap[outIdx++] = 128 | ((u >> 6) & 63);
542 heap[outIdx++] = 128 | (u & 63);
543 } else {
544 if (outIdx + 3 >= endIdx) break;
545 heap[outIdx++] = 240 | (u >> 18);
546 heap[outIdx++] = 128 | ((u >> 12) & 63);
547 heap[outIdx++] = 128 | ((u >> 6) & 63);
548 heap[outIdx++] = 128 | (u & 63);
549 }
550 }
551 heap[outIdx] = 0;
552 return outIdx - startIdx;
553 };
554
555 var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
556
557 var stringToUTF8OnStack = str => {
558 var size = lengthBytesUTF8(str) + 1;
559 var ret = stackAlloc(size);
560 stringToUTF8(str, ret, size);
561 return ret;
562 };
563
564 /**
565 * @param {string|null=} returnType
566 * @param {Array=} argTypes
567 * @param {Arguments|Array=} args
568 * @param {Object=} opts
569 */ var ccall = (ident, returnType, argTypes, args, opts) => {
570 var toC = {
571 "string": str => {
572 var ret = 0;
573 if (str !== null && str !== undefined && str !== 0) {
574 ret = stringToUTF8OnStack(str);
 
 
575 }
576 return ret;
577 },
578 "array": arr => {
579 var ret = stackAlloc(arr.length);
@@ -607,46 +598,51 @@
607 if (stack !== 0) stackRestore(stack);
608 return convertReturnValue(ret);
609 }
610 ret = onDone(ret);
611 return ret;
612 };
613
614 /**
615 * @param {string=} returnType
616 * @param {Array=} argTypes
617 * @param {Object=} opts
618 */ var cwrap = (ident, returnType, argTypes, opts) => {
619 var numericArgs = !argTypes || argTypes.every(type => type === "number" || type === "boolean");
620 var numericRet = returnType !== "string";
621 if (numericRet && numericArgs && !opts) {
622 return getCFunc(ident);
623 }
624 return function() {
625 return ccall(ident, returnType, argTypes, arguments, opts);
626 };
627 };
628
629 var wasmImports = {
630 /** @export */ a: ___assert_fail,
631 /** @export */ b: _emscripten_resize_heap,
632 /** @export */ c: _exit
633 };
634
635 var wasmExports = createWasm();
636
637 var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["e"])();
638
639 var _pikchr = Module["_pikchr"] = (a0, a1, a2, a3, a4) => (_pikchr = Module["_pikchr"] = wasmExports["f"])(a0, a1, a2, a3, a4);
640
641 var stackSave = () => (stackSave = wasmExports["h"])();
642
643 var stackRestore = a0 => (stackRestore = wasmExports["i"])(a0);
644
645 var stackAlloc = a0 => (stackAlloc = wasmExports["j"])(a0);
646
647 Module["stackAlloc"] = stackAlloc;
 
 
 
 
 
 
 
 
648
649 Module["stackSave"] = stackSave;
650
651 Module["stackRestore"] = stackRestore;
652
@@ -661,11 +657,12 @@
661 dependenciesFulfilled = function runCaller() {
662 if (!calledRun) run();
663 if (!calledRun) dependenciesFulfilled = runCaller;
664 };
665
666 function run() {
 
667 if (runDependencies > 0) {
668 return;
669 }
670 preRun();
671 if (runDependencies > 0) {
@@ -702,13 +699,15 @@
702 }
703
704 run();
705
706
707 return moduleArg.ready
708 }
709 );
710 })();
711 if (typeof exports === 'object' && typeof module === 'object')
712 module.exports = initPikchrModule;
713 else if (typeof define === 'function' && define['amd'])
714 define([], () => initPikchrModule);
 
 
715
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -1,17 +1,18 @@
1
2 var initPikchrModule = (() => {
3 var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
4
5 return (
6 function(config) {
7 var initPikchrModule = config || {};
8
9 var Module = typeof initPikchrModule != "undefined" ? initPikchrModule : {};
10
11 var readyPromiseResolve, readyPromiseReject;
12
13 Module["ready"] = new Promise(function(resolve, reject) {
14 readyPromiseResolve = resolve;
15 readyPromiseReject = reject;
16 });
17
18 var moduleOverrides = Object.assign({}, Module);
@@ -35,11 +36,11 @@
36 return Module["locateFile"](path, scriptDirectory);
37 }
38 return scriptDirectory + path;
39 }
40
41 var read_, readAsync, readBinary, setWindowTitle;
42
43 if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
44 if (ENVIRONMENT_IS_WORKER) {
45 scriptDirectory = self.location.href;
46 } else if (typeof document != "undefined" && document.currentScript) {
@@ -46,51 +47,52 @@
47 scriptDirectory = document.currentScript.src;
48 }
49 if (_scriptDir) {
50 scriptDirectory = _scriptDir;
51 }
52 if (scriptDirectory.indexOf("blob:") !== 0) {
53 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
54 } else {
55 scriptDirectory = "";
56 }
57 {
58 read_ = url => {
59 var xhr = new XMLHttpRequest();
60 xhr.open("GET", url, false);
61 xhr.send(null);
62 return xhr.responseText;
63 };
64 if (ENVIRONMENT_IS_WORKER) {
65 readBinary = url => {
66 var xhr = new XMLHttpRequest();
67 xhr.open("GET", url, false);
68 xhr.responseType = "arraybuffer";
69 xhr.send(null);
70 return new Uint8Array(xhr.response);
71 };
72 }
73 readAsync = (url, onload, onerror) => {
74 var xhr = new XMLHttpRequest();
75 xhr.open("GET", url, true);
76 xhr.responseType = "arraybuffer";
77 xhr.onload = () => {
78 if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
79 onload(xhr.response);
80 return;
81 }
82 onerror();
83 };
84 xhr.onerror = onerror;
85 xhr.send(null);
86 };
87 }
88 setWindowTitle = title => document.title = title;
89 } else {}
90
91 var out = Module["print"] || console.log.bind(console);
92
93 var err = Module["printErr"] || console.warn.bind(console);
94
95 Object.assign(Module, moduleOverrides);
96
97 moduleOverrides = null;
98
@@ -102,10 +104,12 @@
104
105 var wasmBinary;
106
107 if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
108
109 var noExitRuntime = Module["noExitRuntime"] || true;
110
111 if (typeof WebAssembly != "object") {
112 abort("no native wasm support detected");
113 }
114
115 var wasmMemory;
@@ -112,31 +116,118 @@
116
117 var ABORT = false;
118
119 var EXITSTATUS;
120
121 var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
122
123 function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
124 var endIdx = idx + maxBytesToRead;
125 var endPtr = idx;
126 while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
127 if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
128 return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
129 }
130 var str = "";
131 while (idx < endPtr) {
132 var u0 = heapOrArray[idx++];
133 if (!(u0 & 128)) {
134 str += String.fromCharCode(u0);
135 continue;
136 }
137 var u1 = heapOrArray[idx++] & 63;
138 if ((u0 & 224) == 192) {
139 str += String.fromCharCode((u0 & 31) << 6 | u1);
140 continue;
141 }
142 var u2 = heapOrArray[idx++] & 63;
143 if ((u0 & 240) == 224) {
144 u0 = (u0 & 15) << 12 | u1 << 6 | u2;
145 } else {
146 u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
147 }
148 if (u0 < 65536) {
149 str += String.fromCharCode(u0);
150 } else {
151 var ch = u0 - 65536;
152 str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
153 }
154 }
155 return str;
156 }
157
158 function UTF8ToString(ptr, maxBytesToRead) {
159 return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
160 }
161
162 function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
163 if (!(maxBytesToWrite > 0)) return 0;
164 var startIdx = outIdx;
165 var endIdx = outIdx + maxBytesToWrite - 1;
166 for (var i = 0; i < str.length; ++i) {
167 var u = str.charCodeAt(i);
168 if (u >= 55296 && u <= 57343) {
169 var u1 = str.charCodeAt(++i);
170 u = 65536 + ((u & 1023) << 10) | u1 & 1023;
171 }
172 if (u <= 127) {
173 if (outIdx >= endIdx) break;
174 heap[outIdx++] = u;
175 } else if (u <= 2047) {
176 if (outIdx + 1 >= endIdx) break;
177 heap[outIdx++] = 192 | u >> 6;
178 heap[outIdx++] = 128 | u & 63;
179 } else if (u <= 65535) {
180 if (outIdx + 2 >= endIdx) break;
181 heap[outIdx++] = 224 | u >> 12;
182 heap[outIdx++] = 128 | u >> 6 & 63;
183 heap[outIdx++] = 128 | u & 63;
184 } else {
185 if (outIdx + 3 >= endIdx) break;
186 heap[outIdx++] = 240 | u >> 18;
187 heap[outIdx++] = 128 | u >> 12 & 63;
188 heap[outIdx++] = 128 | u >> 6 & 63;
189 heap[outIdx++] = 128 | u & 63;
190 }
191 }
192 heap[outIdx] = 0;
193 return outIdx - startIdx;
194 }
195
196 function stringToUTF8(str, outPtr, maxBytesToWrite) {
197 return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
198 }
199
200 var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
201
202 function updateMemoryViews() {
203 var b = wasmMemory.buffer;
204 Module["HEAP8"] = HEAP8 = new Int8Array(b);
205 Module["HEAP16"] = HEAP16 = new Int16Array(b);
206 Module["HEAP32"] = HEAP32 = new Int32Array(b);
207 Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
208 Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
 
209 Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
210 Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
211 Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
212 }
213
214 var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 16777216;
215
216 var wasmTable;
217
218 var __ATPRERUN__ = [];
219
220 var __ATINIT__ = [];
221
222 var __ATPOSTRUN__ = [];
223
224 var runtimeInitialized = false;
225
226 function keepRuntimeAlive() {
227 return noExitRuntime;
228 }
229
230 function preRun() {
231 if (Module["preRun"]) {
232 if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
233 while (Module["preRun"].length) {
@@ -179,16 +270,20 @@
270
271 var dependenciesFulfilled = null;
272
273 function addRunDependency(id) {
274 runDependencies++;
275 if (Module["monitorRunDependencies"]) {
276 Module["monitorRunDependencies"](runDependencies);
277 }
278 }
279
280 function removeRunDependency(id) {
281 runDependencies--;
282 if (Module["monitorRunDependencies"]) {
283 Module["monitorRunDependencies"](runDependencies);
284 }
285 if (runDependencies == 0) {
286 if (runDependencyWatcher !== null) {
287 clearInterval(runDependencyWatcher);
288 runDependencyWatcher = null;
289 }
@@ -198,382 +293,278 @@
293 callback();
294 }
295 }
296 }
297
298 function abort(what) {
299 if (Module["onAbort"]) {
300 Module["onAbort"](what);
301 }
302 what = "Aborted(" + what + ")";
303 err(what);
304 ABORT = true;
305 EXITSTATUS = 1;
306 what += ". Build with -sASSERTIONS for more info.";
307 var e = new WebAssembly.RuntimeError(what);
308 readyPromiseReject(e);
309 throw e;
310 }
311
312 var dataURIPrefix = "data:application/octet-stream;base64,";
313
314 function isDataURI(filename) {
315 return filename.startsWith(dataURIPrefix);
316 }
 
317
318 var wasmBinaryFile;
319
320 wasmBinaryFile = "pikchr.wasm";
321
322 if (!isDataURI(wasmBinaryFile)) {
323 wasmBinaryFile = locateFile(wasmBinaryFile);
324 }
325
326 function getBinary(file) {
327 try {
328 if (file == wasmBinaryFile && wasmBinary) {
329 return new Uint8Array(wasmBinary);
330 }
331 if (readBinary) {
332 return readBinary(file);
333 }
334 throw "both async and sync fetching of the wasm failed";
335 } catch (err) {
336 abort(err);
337 }
338 }
339
340 function getBinaryPromise() {
341 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
342 if (typeof fetch == "function") {
343 return fetch(wasmBinaryFile, {
344 credentials: "same-origin"
345 }).then(function(response) {
346 if (!response["ok"]) {
347 throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
348 }
349 return response["arrayBuffer"]();
350 }).catch(function() {
351 return getBinary(wasmBinaryFile);
352 });
353 }
354 }
355 return Promise.resolve().then(function() {
356 return getBinary(wasmBinaryFile);
357 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358 }
359
360 function createWasm() {
361 var info = {
362 "a": asmLibraryArg
363 };
364 function receiveInstance(instance, module) {
365 var exports = instance.exports;
366 Module["asm"] = exports;
367 wasmMemory = Module["asm"]["d"];
368 updateMemoryViews();
369 wasmTable = Module["asm"]["g"];
370 addOnInit(Module["asm"]["e"]);
371 removeRunDependency("wasm-instantiate");
 
372 }
373 addRunDependency("wasm-instantiate");
374 function receiveInstantiationResult(result) {
375 receiveInstance(result["instance"]);
376 }
377 function instantiateArrayBuffer(receiver) {
378 return getBinaryPromise().then(function(binary) {
379 return WebAssembly.instantiate(binary, info);
380 }).then(function(instance) {
381 return instance;
382 }).then(receiver, function(reason) {
383 err("failed to asynchronously prepare wasm: " + reason);
384 abort(reason);
385 });
386 }
387 function instantiateAsync() {
388 if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && typeof fetch == "function") {
389 return fetch(wasmBinaryFile, {
390 credentials: "same-origin"
391 }).then(function(response) {
392 var result = WebAssembly.instantiateStreaming(response, info);
393 return result.then(receiveInstantiationResult, function(reason) {
394 err("wasm streaming compile failed: " + reason);
395 err("falling back to ArrayBuffer instantiation");
396 return instantiateArrayBuffer(receiveInstantiationResult);
397 });
398 });
399 } else {
400 return instantiateArrayBuffer(receiveInstantiationResult);
401 }
402 }
403 if (Module["instantiateWasm"]) {
404 try {
405 var exports = Module["instantiateWasm"](info, receiveInstance);
406 return exports;
407 } catch (e) {
408 err("Module.instantiateWasm callback failed with error: " + e);
409 readyPromiseReject(e);
410 }
411 }
412 instantiateAsync().catch(readyPromiseReject);
413 return {};
414 }
415
416 var tempDouble;
417
418 var tempI64;
419
420 function ExitStatus(status) {
421 this.name = "ExitStatus";
422 this.message = "Program terminated with exit(" + status + ")";
423 this.status = status;
424 }
425
426 function callRuntimeCallbacks(callbacks) {
427 while (callbacks.length > 0) {
428 callbacks.shift()(Module);
429 }
430 }
431
432 function getValue(ptr, type = "i8") {
433 if (type.endsWith("*")) type = "*";
434 switch (type) {
435 case "i1":
436 return HEAP8[ptr >> 0];
437
438 case "i8":
439 return HEAP8[ptr >> 0];
440
441 case "i16":
442 return HEAP16[ptr >> 1];
443
444 case "i32":
445 return HEAP32[ptr >> 2];
446
447 case "i64":
448 return HEAP32[ptr >> 2];
449
450 case "float":
451 return HEAPF32[ptr >> 2];
452
453 case "double":
454 return HEAPF64[ptr >> 3];
455
456 case "*":
457 return HEAPU32[ptr >> 2];
458
459 default:
460 abort("invalid type for getValue: " + type);
461 }
462 return null;
463 }
464
465 function setValue(ptr, value, type = "i8") {
466 if (type.endsWith("*")) type = "*";
467 switch (type) {
468 case "i1":
469 HEAP8[ptr >> 0] = value;
470 break;
471
472 case "i8":
473 HEAP8[ptr >> 0] = value;
474 break;
475
476 case "i16":
477 HEAP16[ptr >> 1] = value;
478 break;
479
480 case "i32":
481 HEAP32[ptr >> 2] = value;
482 break;
483
484 case "i64":
485 tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
486 HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
487 break;
488
489 case "float":
490 HEAPF32[ptr >> 2] = value;
491 break;
492
493 case "double":
494 HEAPF64[ptr >> 3] = value;
495 break;
496
497 case "*":
498 HEAPU32[ptr >> 2] = value;
499 break;
500
501 default:
502 abort("invalid type for setValue: " + type);
503 }
504 }
505
506 function ___assert_fail(condition, filename, line, func) {
507 abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
508 }
509
510 function abortOnCannotGrowMemory(requestedSize) {
511 abort("OOM");
512 }
513
514 function _emscripten_resize_heap(requestedSize) {
515 var oldSize = HEAPU8.length;
516 requestedSize = requestedSize >>> 0;
517 abortOnCannotGrowMemory(requestedSize);
518 }
519
520 var SYSCALLS = {
521 varargs: undefined,
522 get: function() {
523 SYSCALLS.varargs += 4;
524 var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
525 return ret;
526 },
527 getStr: function(ptr) {
528 var ret = UTF8ToString(ptr);
529 return ret;
530 }
531 };
532
533 function _proc_exit(code) {
534 EXITSTATUS = code;
535 if (!keepRuntimeAlive()) {
536 if (Module["onExit"]) Module["onExit"](code);
537 ABORT = true;
538 }
539 quit_(code, new ExitStatus(code));
540 }
541
542 function exitJS(status, implicit) {
543 EXITSTATUS = status;
544 _proc_exit(status);
545 }
546
547 var _exit = exitJS;
548
549 function getCFunc(ident) {
550 var func = Module["_" + ident];
551 return func;
552 }
553
554 function writeArrayToMemory(array, buffer) {
555 HEAP8.set(array, buffer);
556 }
557
558 function ccall(ident, returnType, argTypes, args, opts) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559 var toC = {
560 "string": str => {
561 var ret = 0;
562 if (str !== null && str !== undefined && str !== 0) {
563 var len = (str.length << 2) + 1;
564 ret = stackAlloc(len);
565 stringToUTF8(str, ret, len);
566 }
567 return ret;
568 },
569 "array": arr => {
570 var ret = stackAlloc(arr.length);
@@ -607,46 +598,51 @@
598 if (stack !== 0) stackRestore(stack);
599 return convertReturnValue(ret);
600 }
601 ret = onDone(ret);
602 return ret;
603 }
604
605 function cwrap(ident, returnType, argTypes, opts) {
606 argTypes = argTypes || [];
607 var numericArgs = argTypes.every(type => type === "number" || type === "boolean");
 
 
 
608 var numericRet = returnType !== "string";
609 if (numericRet && numericArgs && !opts) {
610 return getCFunc(ident);
611 }
612 return function() {
613 return ccall(ident, returnType, argTypes, arguments, opts);
614 };
615 }
616
617 var asmLibraryArg = {
618 "a": ___assert_fail,
619 "b": _emscripten_resize_heap,
620 "c": _exit
621 };
622
623 var asm = createWasm();
624
625 var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
626 return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["e"]).apply(null, arguments);
627 };
628
629 var _pikchr = Module["_pikchr"] = function() {
630 return (_pikchr = Module["_pikchr"] = Module["asm"]["f"]).apply(null, arguments);
631 };
632
633 var stackSave = Module["stackSave"] = function() {
634 return (stackSave = Module["stackSave"] = Module["asm"]["h"]).apply(null, arguments);
635 };
636
637 var stackRestore = Module["stackRestore"] = function() {
638 return (stackRestore = Module["stackRestore"] = Module["asm"]["i"]).apply(null, arguments);
639 };
640
641 var stackAlloc = Module["stackAlloc"] = function() {
642 return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
643 };
644
645 Module["stackSave"] = stackSave;
646
647 Module["stackRestore"] = stackRestore;
648
@@ -661,11 +657,12 @@
657 dependenciesFulfilled = function runCaller() {
658 if (!calledRun) run();
659 if (!calledRun) dependenciesFulfilled = runCaller;
660 };
661
662 function run(args) {
663 args = args || arguments_;
664 if (runDependencies > 0) {
665 return;
666 }
667 preRun();
668 if (runDependencies > 0) {
@@ -702,13 +699,15 @@
699 }
700
701 run();
702
703
704 return initPikchrModule.ready
705 }
706 );
707 })();
708 if (typeof exports === 'object' && typeof module === 'object')
709 module.exports = initPikchrModule;
710 else if (typeof define === 'function' && define['amd'])
711 define([], function() { return initPikchrModule; });
712 else if (typeof exports === 'object')
713 exports["initPikchrModule"] = initPikchrModule;
714
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
cannot compute difference between binary files
11
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
+423 -157
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6002,17 +6002,17 @@
60026002
**
60036003
** The query plan selected by seriesBestIndex is passed in the idxNum
60046004
** parameter. (idxStr is not used in this implementation.) idxNum
60056005
** is a bitmask showing which constraints are available:
60066006
**
6007
-** 1: start=VALUE
6008
-** 2: stop=VALUE
6009
-** 4: step=VALUE
6010
-**
6011
-** Also, if bit 8 is set, that means that the series should be output
6012
-** in descending order rather than in ascending order. If bit 16 is
6013
-** set, then output must appear in ascending order.
6007
+** 0x01: start=VALUE
6008
+** 0x02: stop=VALUE
6009
+** 0x04: step=VALUE
6010
+** 0x08: descending order
6011
+** 0x10: ascending order
6012
+** 0x20: LIMIT VALUE
6013
+** 0x40: OFFSET VALUE
60146014
**
60156015
** This routine should initialize the cursor and position it so that it
60166016
** is pointing at the first row, or pointing off the end of the table
60176017
** (so that seriesEof() will return true) if the table is empty.
60186018
*/
@@ -6022,29 +6022,47 @@
60226022
int argc, sqlite3_value **argv
60236023
){
60246024
series_cursor *pCur = (series_cursor *)pVtabCursor;
60256025
int i = 0;
60266026
(void)idxStrUnused;
6027
- if( idxNum & 1 ){
6027
+ if( idxNum & 0x01 ){
60286028
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
60296029
}else{
60306030
pCur->ss.iBase = 0;
60316031
}
6032
- if( idxNum & 2 ){
6032
+ if( idxNum & 0x02 ){
60336033
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
60346034
}else{
60356035
pCur->ss.iTerm = 0xffffffff;
60366036
}
6037
- if( idxNum & 4 ){
6037
+ if( idxNum & 0x04 ){
60386038
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
60396039
if( pCur->ss.iStep==0 ){
60406040
pCur->ss.iStep = 1;
60416041
}else if( pCur->ss.iStep<0 ){
6042
- if( (idxNum & 16)==0 ) idxNum |= 8;
6042
+ if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
60436043
}
60446044
}else{
60456045
pCur->ss.iStep = 1;
6046
+ }
6047
+ if( idxNum & 0x20 ){
6048
+ sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
6049
+ sqlite3_int64 iTerm;
6050
+ if( idxNum & 0x40 ){
6051
+ sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
6052
+ if( iOffset>0 ){
6053
+ pCur->ss.iBase += pCur->ss.iStep*iOffset;
6054
+ }
6055
+ }
6056
+ if( iLimit>=0 ){
6057
+ iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
6058
+ if( pCur->ss.iStep<0 ){
6059
+ if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
6060
+ }else{
6061
+ if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
6062
+ }
6063
+ }
60466064
}
60476065
for(i=0; i<argc; i++){
60486066
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
60496067
/* If any of the constraints have a NULL value, then return no rows.
60506068
** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
@@ -6052,11 +6070,11 @@
60526070
pCur->ss.iTerm = 0;
60536071
pCur->ss.iStep = 1;
60546072
break;
60556073
}
60566074
}
6057
- if( idxNum & 8 ){
6075
+ if( idxNum & 0x08 ){
60586076
pCur->ss.isReversing = pCur->ss.iStep > 0;
60596077
}else{
60606078
pCur->ss.isReversing = pCur->ss.iStep < 0;
60616079
}
60626080
setupSequence( &pCur->ss );
@@ -6072,54 +6090,85 @@
60726090
** In this implementation idxNum is used to represent the
60736091
** query plan. idxStr is unused.
60746092
**
60756093
** The query plan is represented by bits in idxNum:
60766094
**
6077
-** (1) start = $value -- constraint exists
6078
-** (2) stop = $value -- constraint exists
6079
-** (4) step = $value -- constraint exists
6080
-** (8) output in descending order
6095
+** 0x01 start = $value -- constraint exists
6096
+** 0x02 stop = $value -- constraint exists
6097
+** 0x04 step = $value -- constraint exists
6098
+** 0x08 output is in descending order
6099
+** 0x10 output is in ascending order
6100
+** 0x20 LIMIT $value -- constraint exists
6101
+** 0x40 OFFSET $value -- constraint exists
60816102
*/
60826103
static int seriesBestIndex(
60836104
sqlite3_vtab *pVTab,
60846105
sqlite3_index_info *pIdxInfo
60856106
){
60866107
int i, j; /* Loop over constraints */
60876108
int idxNum = 0; /* The query plan bitmask */
6109
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
60886110
int bStartSeen = 0; /* EQ constraint seen on the START column */
6111
+#endif
60896112
int unusableMask = 0; /* Mask of unusable constraints */
60906113
int nArg = 0; /* Number of arguments that seriesFilter() expects */
6091
- int aIdx[3]; /* Constraints on start, stop, and step */
6114
+ int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
60926115
const struct sqlite3_index_constraint *pConstraint;
60936116
60946117
/* This implementation assumes that the start, stop, and step columns
60956118
** are the last three columns in the virtual table. */
60966119
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
60976120
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
60986121
6099
- aIdx[0] = aIdx[1] = aIdx[2] = -1;
6122
+ aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
61006123
pConstraint = pIdxInfo->aConstraint;
61016124
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
61026125
int iCol; /* 0 for start, 1 for stop, 2 for step */
61036126
int iMask; /* bitmask for those column */
6127
+ int op = pConstraint->op;
6128
+ if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
6129
+ && op<=SQLITE_INDEX_CONSTRAINT_OFFSET
6130
+ ){
6131
+ if( pConstraint->usable==0 ){
6132
+ /* do nothing */
6133
+ }else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
6134
+ aIdx[3] = i;
6135
+ idxNum |= 0x20;
6136
+ }else{
6137
+ assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
6138
+ aIdx[4] = i;
6139
+ idxNum |= 0x40;
6140
+ }
6141
+ continue;
6142
+ }
61046143
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
61056144
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
61066145
assert( iCol>=0 && iCol<=2 );
61076146
iMask = 1 << iCol;
6108
- if( iCol==0 ) bStartSeen = 1;
6147
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
6148
+ if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
6149
+ bStartSeen = 1;
6150
+ }
6151
+#endif
61096152
if( pConstraint->usable==0 ){
61106153
unusableMask |= iMask;
61116154
continue;
6112
- }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
6155
+ }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
61136156
idxNum |= iMask;
61146157
aIdx[iCol] = i;
61156158
}
61166159
}
6117
- for(i=0; i<3; i++){
6160
+ if( aIdx[3]==0 ){
6161
+ /* Ignore OFFSET if LIMIT is omitted */
6162
+ idxNum &= ~0x60;
6163
+ aIdx[4] = 0;
6164
+ }
6165
+ for(i=0; i<5; i++){
61186166
if( (j = aIdx[i])>=0 ){
61196167
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
6120
- pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
6168
+ pIdxInfo->aConstraintUsage[j].omit =
6169
+ !SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
61216170
}
61226171
}
61236172
/* The current generate_column() implementation requires at least one
61246173
** argument (the START value). Legacy versions assumed START=0 if the
61256174
** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
@@ -6136,23 +6185,26 @@
61366185
/* The start, stop, and step columns are inputs. Therefore if there
61376186
** are unusable constraints on any of start, stop, or step then
61386187
** this plan is unusable */
61396188
return SQLITE_CONSTRAINT;
61406189
}
6141
- if( (idxNum & 3)==3 ){
6190
+ if( (idxNum & 0x03)==0x03 ){
61426191
/* Both start= and stop= boundaries are available. This is the
61436192
** the preferred case */
61446193
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
61456194
pIdxInfo->estimatedRows = 1000;
61466195
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
61476196
if( pIdxInfo->aOrderBy[0].desc ){
6148
- idxNum |= 8;
6197
+ idxNum |= 0x08;
61496198
}else{
6150
- idxNum |= 16;
6199
+ idxNum |= 0x10;
61516200
}
61526201
pIdxInfo->orderByConsumed = 1;
61536202
}
6203
+ }else if( (idxNum & 0x21)==0x21 ){
6204
+ /* We have start= and LIMIT */
6205
+ pIdxInfo->estimatedRows = 2500;
61546206
}else{
61556207
/* If either boundary is missing, we have to generate a huge span
61566208
** of numbers. Make this case very expensive so that the query
61576209
** planner will work hard to avoid it. */
61586210
pIdxInfo->estimatedRows = 2147483647;
@@ -7475,11 +7527,13 @@
74757527
){
74767528
if( zFile==0 ) return 1;
74777529
#if !defined(_WIN32) && !defined(WIN32)
74787530
if( S_ISLNK(mode) ){
74797531
const char *zTo = (const char*)sqlite3_value_text(pData);
7480
- if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
7532
+ if( zTo==0 ) return 1;
7533
+ unlink(zFile);
7534
+ if( symlink(zTo, zFile)<0 ) return 1;
74817535
}else
74827536
#endif
74837537
{
74847538
if( S_ISDIR(mode) ){
74857539
if( mkdir(zFile, mode) ){
@@ -7561,17 +7615,23 @@
75617615
times[1].tv_sec = mtime;
75627616
if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
75637617
return 1;
75647618
}
75657619
#else
7566
- /* Legacy unix */
7567
- struct timeval times[2];
7568
- times[0].tv_usec = times[1].tv_usec = 0;
7569
- times[0].tv_sec = time(0);
7570
- times[1].tv_sec = mtime;
7571
- if( utimes(zFile, times) ){
7572
- return 1;
7620
+ /* Legacy unix.
7621
+ **
7622
+ ** Do not use utimes() on a symbolic link - it sees through the link and
7623
+ ** modifies the timestamps on the target. Or fails if the target does
7624
+ ** not exist. */
7625
+ if( 0==S_ISLNK(mode) ){
7626
+ struct timeval times[2];
7627
+ times[0].tv_usec = times[1].tv_usec = 0;
7628
+ times[0].tv_sec = time(0);
7629
+ times[1].tv_sec = mtime;
7630
+ if( utimes(zFile, times) ){
7631
+ return 1;
7632
+ }
75737633
}
75747634
#endif
75757635
}
75767636
75777637
return 0;
@@ -9348,11 +9408,13 @@
93489408
/* #include "sqlite3ext.h" */
93499409
SQLITE_EXTENSION_INIT1
93509410
#include <stdio.h>
93519411
#include <string.h>
93529412
#include <assert.h>
9353
-#include <stdint.h>
9413
+#ifndef SQLITE_NO_STDINT
9414
+# include <stdint.h>
9415
+#endif
93549416
93559417
#include <zlib.h>
93569418
93579419
#ifndef SQLITE_OMIT_VIRTUALTABLE
93589420
@@ -11639,26 +11701,27 @@
1163911701
sqlite3_context *context,
1164011702
int argc,
1164111703
sqlite3_value **argv
1164211704
){
1164311705
uLong nData;
11644
- uLongf sz;
11706
+ sqlite3_int64 sz;
1164511707
1164611708
assert( argc==2 );
1164711709
sz = sqlite3_value_int(argv[1]);
1164811710
1164911711
if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
1165011712
sqlite3_result_value(context, argv[0]);
1165111713
}else{
11714
+ uLongf szf = sz;
1165211715
const Bytef *pData= sqlite3_value_blob(argv[0]);
1165311716
Bytef *pOut = sqlite3_malloc(sz);
1165411717
if( pOut==0 ){
1165511718
sqlite3_result_error_nomem(context);
11656
- }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
11719
+ }else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
1165711720
sqlite3_result_error(context, "error in uncompress()", -1);
1165811721
}else{
11659
- sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
11722
+ sqlite3_result_blob(context, pOut, szf, SQLITE_TRANSIENT);
1166011723
}
1166111724
sqlite3_free(pOut);
1166211725
}
1166311726
}
1166411727
@@ -14007,11 +14070,10 @@
1400714070
}
1400814071
1400914072
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
1401014073
1401114074
/************************* End ../ext/expert/sqlite3expert.c ********************/
14012
-
1401314075
/************************* Begin ../ext/intck/sqlite3intck.h ******************/
1401414076
/*
1401514077
** 2024-02-08
1401614078
**
1401714079
** The author disclaims copyright to this source code. In place of
@@ -15125,10 +15187,110 @@
1512515187
}
1512615188
return p->zTestSql;
1512715189
}
1512815190
1512915191
/************************* End ../ext/intck/sqlite3intck.c ********************/
15192
+/************************* Begin ../ext/misc/stmtrand.c ******************/
15193
+/*
15194
+** 2024-05-24
15195
+**
15196
+** The author disclaims copyright to this source code. In place of
15197
+** a legal notice, here is a blessing:
15198
+**
15199
+** May you do good and not evil.
15200
+** May you find forgiveness for yourself and forgive others.
15201
+** May you share freely, never taking more than you give.
15202
+**
15203
+******************************************************************************
15204
+**
15205
+** An SQL function that return pseudo-random non-negative integers.
15206
+**
15207
+** SELECT stmtrand(123);
15208
+**
15209
+** A special feature of this function is that the same sequence of random
15210
+** integers is returned for each invocation of the statement. This makes
15211
+** the results repeatable, and hence useful for testing. The argument is
15212
+** an integer which is the seed for the random number sequence. The seed
15213
+** is used by the first invocation of this function only and is ignored
15214
+** for all subsequent calls within the same statement.
15215
+**
15216
+** Resetting a statement (sqlite3_reset()) also resets the random number
15217
+** sequence.
15218
+*/
15219
+/* #include "sqlite3ext.h" */
15220
+SQLITE_EXTENSION_INIT1
15221
+#include <assert.h>
15222
+#include <string.h>
15223
+
15224
+/* State of the pseudo-random number generator */
15225
+typedef struct Stmtrand {
15226
+ unsigned int x, y;
15227
+} Stmtrand;
15228
+
15229
+/* auxdata key */
15230
+#define STMTRAND_KEY (-4418371)
15231
+
15232
+/*
15233
+** Function: stmtrand(SEED)
15234
+**
15235
+** Return a pseudo-random number.
15236
+*/
15237
+static void stmtrandFunc(
15238
+ sqlite3_context *context,
15239
+ int argc,
15240
+ sqlite3_value **argv
15241
+){
15242
+ Stmtrand *p;
15243
+
15244
+ p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
15245
+ if( p==0 ){
15246
+ unsigned int seed;
15247
+ p = sqlite3_malloc( sizeof(*p) );
15248
+ if( p==0 ){
15249
+ sqlite3_result_error_nomem(context);
15250
+ return;
15251
+ }
15252
+ if( argc>=1 ){
15253
+ seed = (unsigned int)sqlite3_value_int(argv[0]);
15254
+ }else{
15255
+ seed = 0;
15256
+ }
15257
+ p->x = seed | 1;
15258
+ p->y = seed;
15259
+ sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
15260
+ p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
15261
+ if( p==0 ){
15262
+ sqlite3_result_error_nomem(context);
15263
+ return;
15264
+ }
15265
+ }
15266
+ p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
15267
+ p->y = p->y*1103515245 + 12345;
15268
+ sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
15269
+}
15270
+
15271
+#ifdef _WIN32
15272
+
15273
+#endif
15274
+int sqlite3_stmtrand_init(
15275
+ sqlite3 *db,
15276
+ char **pzErrMsg,
15277
+ const sqlite3_api_routines *pApi
15278
+){
15279
+ int rc = SQLITE_OK;
15280
+ SQLITE_EXTENSION_INIT2(pApi);
15281
+ (void)pzErrMsg; /* Unused parameter */
15282
+ rc = sqlite3_create_function(db, "stmtrand", 1, SQLITE_UTF8, 0,
15283
+ stmtrandFunc, 0, 0);
15284
+ if( rc==SQLITE_OK ){
15285
+ rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
15286
+ stmtrandFunc, 0, 0);
15287
+ }
15288
+ return rc;
15289
+}
15290
+
15291
+/************************* End ../ext/misc/stmtrand.c ********************/
1513015292
1513115293
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
1513215294
#define SQLITE_SHELL_HAVE_RECOVER 1
1513315295
#else
1513415296
#define SQLITE_SHELL_HAVE_RECOVER 0
@@ -15476,10 +15638,19 @@
1547615638
1547715639
#define DBDATA_PADDING_BYTES 100
1547815640
1547915641
typedef struct DbdataTable DbdataTable;
1548015642
typedef struct DbdataCursor DbdataCursor;
15643
+typedef struct DbdataBuffer DbdataBuffer;
15644
+
15645
+/*
15646
+** Buffer type.
15647
+*/
15648
+struct DbdataBuffer {
15649
+ u8 *aBuf;
15650
+ sqlite3_int64 nBuf;
15651
+};
1548115652
1548215653
/* Cursor object */
1548315654
struct DbdataCursor {
1548415655
sqlite3_vtab_cursor base; /* Base class. Must be first */
1548515656
sqlite3_stmt *pStmt; /* For fetching database pages */
@@ -15492,11 +15663,11 @@
1549215663
int bOnePage; /* True to stop after one page */
1549315664
int szDb;
1549415665
sqlite3_int64 iRowid;
1549515666
1549615667
/* Only for the sqlite_dbdata table */
15497
- u8 *pRec; /* Buffer containing current record */
15668
+ DbdataBuffer rec;
1549815669
sqlite3_int64 nRec; /* Size of pRec[] in bytes */
1549915670
sqlite3_int64 nHdr; /* Size of header in bytes */
1550015671
int iField; /* Current field number */
1550115672
u8 *pHdrPtr;
1550215673
u8 *pPtr;
@@ -15536,10 +15707,35 @@
1553615707
"CREATE TABLE x(" \
1553715708
" pgno INTEGER," \
1553815709
" child INTEGER," \
1553915710
" schema TEXT HIDDEN" \
1554015711
")"
15712
+
15713
+/*
15714
+** Ensure the buffer passed as the first argument is at least nMin bytes
15715
+** in size. If an error occurs while attempting to resize the buffer,
15716
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
15717
+*/
15718
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
15719
+ if( nMin>pBuf->nBuf ){
15720
+ sqlite3_int64 nNew = nMin+16384;
15721
+ u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
15722
+
15723
+ if( aNew==0 ) return SQLITE_NOMEM;
15724
+ pBuf->aBuf = aNew;
15725
+ pBuf->nBuf = nNew;
15726
+ }
15727
+ return SQLITE_OK;
15728
+}
15729
+
15730
+/*
15731
+** Release the allocation managed by buffer pBuf.
15732
+*/
15733
+static void dbdataBufferFree(DbdataBuffer *pBuf){
15734
+ sqlite3_free(pBuf->aBuf);
15735
+ memset(pBuf, 0, sizeof(*pBuf));
15736
+}
1554115737
1554215738
/*
1554315739
** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
1554415740
** table.
1554515741
*/
@@ -15677,13 +15873,13 @@
1567715873
pCsr->iPgno = 1;
1567815874
pCsr->iCell = 0;
1567915875
pCsr->iField = 0;
1568015876
pCsr->bOnePage = 0;
1568115877
sqlite3_free(pCsr->aPage);
15682
- sqlite3_free(pCsr->pRec);
15683
- pCsr->pRec = 0;
15878
+ dbdataBufferFree(&pCsr->rec);
1568415879
pCsr->aPage = 0;
15880
+ pCsr->nRec = 0;
1568515881
}
1568615882
1568715883
/*
1568815884
** Close an sqlite_dbdata or sqlite_dbptr cursor.
1568915885
*/
@@ -15821,70 +16017,91 @@
1582116017
u32 enc,
1582216018
int eType,
1582316019
u8 *pData,
1582416020
sqlite3_int64 nData
1582516021
){
15826
- if( eType>=0 && dbdataValueBytes(eType)<=nData ){
15827
- switch( eType ){
15828
- case 0:
15829
- case 10:
15830
- case 11:
15831
- sqlite3_result_null(pCtx);
15832
- break;
15833
-
15834
- case 8:
16022
+ if( eType>=0 ){
16023
+ if( dbdataValueBytes(eType)<=nData ){
16024
+ switch( eType ){
16025
+ case 0:
16026
+ case 10:
16027
+ case 11:
16028
+ sqlite3_result_null(pCtx);
16029
+ break;
16030
+
16031
+ case 8:
16032
+ sqlite3_result_int(pCtx, 0);
16033
+ break;
16034
+ case 9:
16035
+ sqlite3_result_int(pCtx, 1);
16036
+ break;
16037
+
16038
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
16039
+ sqlite3_uint64 v = (signed char)pData[0];
16040
+ pData++;
16041
+ switch( eType ){
16042
+ case 7:
16043
+ case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
16044
+ case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
16045
+ case 4: v = (v<<8) + pData[0]; pData++;
16046
+ case 3: v = (v<<8) + pData[0]; pData++;
16047
+ case 2: v = (v<<8) + pData[0]; pData++;
16048
+ }
16049
+
16050
+ if( eType==7 ){
16051
+ double r;
16052
+ memcpy(&r, &v, sizeof(r));
16053
+ sqlite3_result_double(pCtx, r);
16054
+ }else{
16055
+ sqlite3_result_int64(pCtx, (sqlite3_int64)v);
16056
+ }
16057
+ break;
16058
+ }
16059
+
16060
+ default: {
16061
+ int n = ((eType-12) / 2);
16062
+ if( eType % 2 ){
16063
+ switch( enc ){
16064
+ #ifndef SQLITE_OMIT_UTF16
16065
+ case SQLITE_UTF16BE:
16066
+ sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
16067
+ break;
16068
+ case SQLITE_UTF16LE:
16069
+ sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
16070
+ break;
16071
+ #endif
16072
+ default:
16073
+ sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
16074
+ break;
16075
+ }
16076
+ }else{
16077
+ sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
16078
+ }
16079
+ }
16080
+ }
16081
+ }else{
16082
+ if( eType==7 ){
16083
+ sqlite3_result_double(pCtx, 0.0);
16084
+ }else if( eType<7 ){
1583516085
sqlite3_result_int(pCtx, 0);
15836
- break;
15837
- case 9:
15838
- sqlite3_result_int(pCtx, 1);
15839
- break;
15840
-
15841
- case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
15842
- sqlite3_uint64 v = (signed char)pData[0];
15843
- pData++;
15844
- switch( eType ){
15845
- case 7:
15846
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
15847
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
15848
- case 4: v = (v<<8) + pData[0]; pData++;
15849
- case 3: v = (v<<8) + pData[0]; pData++;
15850
- case 2: v = (v<<8) + pData[0]; pData++;
15851
- }
15852
-
15853
- if( eType==7 ){
15854
- double r;
15855
- memcpy(&r, &v, sizeof(r));
15856
- sqlite3_result_double(pCtx, r);
15857
- }else{
15858
- sqlite3_result_int64(pCtx, (sqlite3_int64)v);
15859
- }
15860
- break;
15861
- }
15862
-
15863
- default: {
15864
- int n = ((eType-12) / 2);
15865
- if( eType % 2 ){
15866
- switch( enc ){
15867
-#ifndef SQLITE_OMIT_UTF16
15868
- case SQLITE_UTF16BE:
15869
- sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
15870
- break;
15871
- case SQLITE_UTF16LE:
15872
- sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
15873
- break;
15874
-#endif
15875
- default:
15876
- sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
15877
- break;
15878
- }
15879
- }else{
15880
- sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
15881
- }
15882
- }
15883
- }
15884
- }
15885
-}
16086
+ }else if( eType%2 ){
16087
+ sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
16088
+ }else{
16089
+ sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
16090
+ }
16091
+ }
16092
+ }
16093
+}
16094
+
16095
+/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
16096
+** a page-size, it returns the maximum number of cells that may be present
16097
+** on the page. */
16098
+#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
16099
+
16100
+/* Maximum number of fields that may appear in a single record. This is
16101
+** the "hard-limit", according to comments in sqliteLimit.h. */
16102
+#define DBDATA_MX_FIELD 32676
1588616103
1588716104
/*
1588816105
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
1588916106
*/
1589016107
static int dbdataNext(sqlite3_vtab_cursor *pCursor){
@@ -15910,10 +16127,13 @@
1591016127
}
1591116128
1591216129
assert( iOff+3+2<=pCsr->nPage );
1591316130
pCsr->iCell = pTab->bPtr ? -2 : 0;
1591416131
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
16132
+ if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
16133
+ pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
16134
+ }
1591516135
}
1591616136
1591716137
if( pTab->bPtr ){
1591816138
if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
1591916139
pCsr->iCell = pCsr->nCell;
@@ -15927,11 +16147,12 @@
1592716147
}else{
1592816148
return SQLITE_OK;
1592916149
}
1593016150
}else{
1593116151
/* If there is no record loaded, load it now. */
15932
- if( pCsr->pRec==0 ){
16152
+ assert( pCsr->rec.aBuf!=0 || pCsr->nRec==0 );
16153
+ if( pCsr->nRec==0 ){
1593316154
int bHasRowid = 0;
1593416155
int nPointer = 0;
1593516156
sqlite3_int64 nPayload = 0;
1593616157
sqlite3_int64 nHdr = 0;
1593716158
int iHdr;
@@ -15954,27 +16175,28 @@
1595416175
}
1595516176
1595616177
if( pCsr->iCell>=pCsr->nCell ){
1595716178
bNextPage = 1;
1595816179
}else{
16180
+ int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
1595916181
15960
- iOff += 8 + nPointer + pCsr->iCell*2;
15961
- if( iOff>pCsr->nPage ){
16182
+ if( iCellPtr>pCsr->nPage ){
1596216183
bNextPage = 1;
1596316184
}else{
15964
- iOff = get_uint16(&pCsr->aPage[iOff]);
16185
+ iOff = get_uint16(&pCsr->aPage[iCellPtr]);
1596516186
}
1596616187
1596716188
/* For an interior node cell, skip past the child-page number */
1596816189
iOff += nPointer;
1596916190
1597016191
/* Load the "byte of payload including overflow" field */
15971
- if( bNextPage || iOff>pCsr->nPage ){
16192
+ if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
1597216193
bNextPage = 1;
1597316194
}else{
1597416195
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
1597516196
if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
16197
+ if( nPayload==0 ) nPayload = 1;
1597616198
}
1597716199
1597816200
/* If this is a leaf intkey cell, load the rowid */
1597916201
if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
1598016202
iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
@@ -16005,17 +16227,16 @@
1600516227
}else{
1600616228
1600716229
/* Allocate space for payload. And a bit more to catch small buffer
1600816230
** overruns caused by attempting to read a varint or similar from
1600916231
** near the end of a corrupt record. */
16010
- pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
16011
- if( pCsr->pRec==0 ) return SQLITE_NOMEM;
16012
- memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
16013
- pCsr->nRec = nPayload;
16232
+ rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
16233
+ if( rc!=SQLITE_OK ) return rc;
16234
+ assert( nPayload!=0 );
1601416235
1601516236
/* Load the nLocal bytes of payload */
16016
- memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
16237
+ memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
1601716238
iOff += nLocal;
1601816239
1601916240
/* Load content from overflow pages */
1602016241
if( nPayload>nLocal ){
1602116242
sqlite3_int64 nRem = nPayload - nLocal;
@@ -16029,61 +16250,64 @@
1602916250
if( rc!=SQLITE_OK ) return rc;
1603016251
if( aOvfl==0 ) break;
1603116252
1603216253
nCopy = U-4;
1603316254
if( nCopy>nRem ) nCopy = nRem;
16034
- memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
16255
+ memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
1603516256
nRem -= nCopy;
1603616257
1603716258
pgnoOvfl = get_uint32(aOvfl);
1603816259
sqlite3_free(aOvfl);
1603916260
}
16261
+ nPayload -= nRem;
1604016262
}
16263
+ memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
16264
+ pCsr->nRec = nPayload;
1604116265
16042
- iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
16266
+ iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
1604316267
if( nHdr>nPayload ) nHdr = 0;
1604416268
pCsr->nHdr = nHdr;
16045
- pCsr->pHdrPtr = &pCsr->pRec[iHdr];
16046
- pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
16269
+ pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
16270
+ pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
1604716271
pCsr->iField = (bHasRowid ? -1 : 0);
1604816272
}
1604916273
}
1605016274
}else{
1605116275
pCsr->iField++;
1605216276
if( pCsr->iField>0 ){
1605316277
sqlite3_int64 iType;
16054
- if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
16278
+ if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
16279
+ || pCsr->iField>=DBDATA_MX_FIELD
16280
+ ){
1605516281
bNextPage = 1;
1605616282
}else{
1605716283
int szField = 0;
1605816284
pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
1605916285
szField = dbdataValueBytes(iType);
16060
- if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
16061
- pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
16286
+ if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
16287
+ pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
1606216288
}else{
1606316289
pCsr->pPtr += szField;
1606416290
}
1606516291
}
1606616292
}
1606716293
}
1606816294
1606916295
if( bNextPage ){
1607016296
sqlite3_free(pCsr->aPage);
16071
- sqlite3_free(pCsr->pRec);
1607216297
pCsr->aPage = 0;
16073
- pCsr->pRec = 0;
16298
+ pCsr->nRec = 0;
1607416299
if( pCsr->bOnePage ) return SQLITE_OK;
1607516300
pCsr->iPgno++;
1607616301
}else{
16077
- if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
16302
+ if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
1607816303
return SQLITE_OK;
1607916304
}
1608016305
1608116306
/* Advance to the next cell. The next iteration of the loop will load
1608216307
** the record and so on. */
16083
- sqlite3_free(pCsr->pRec);
16084
- pCsr->pRec = 0;
16308
+ pCsr->nRec = 0;
1608516309
pCsr->iCell++;
1608616310
}
1608716311
}
1608816312
}
1608916313
@@ -16269,16 +16493,16 @@
1626916493
sqlite3_result_int(ctx, pCsr->iField);
1627016494
break;
1627116495
case DBDATA_COLUMN_VALUE: {
1627216496
if( pCsr->iField<0 ){
1627316497
sqlite3_result_int64(ctx, pCsr->iIntkey);
16274
- }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
16498
+ }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
1627516499
sqlite3_int64 iType;
1627616500
dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
1627716501
dbdataValue(
1627816502
ctx, pCsr->enc, iType, pCsr->pPtr,
16279
- &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
16503
+ &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
1628016504
);
1628116505
}
1628216506
break;
1628316507
}
1628416508
}
@@ -17537,11 +17761,11 @@
1753717761
if( rc==SQLITE_OK ){
1753817762
recoverSqlCallback(p, zSql);
1753917763
if( bTable && !bVirtual ){
1754017764
if( SQLITE_ROW==sqlite3_step(pTblname) ){
1754117765
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
17542
- recoverAddTable(p, zTbl, iRoot);
17766
+ if( zTbl ) recoverAddTable(p, zTbl, iRoot);
1754317767
}
1754417768
recoverReset(p, pTblname);
1754517769
}
1754617770
}else if( rc!=SQLITE_ERROR ){
1754717771
recoverDbError(p, p->dbOut);
@@ -20403,11 +20627,11 @@
2040320627
}
2040420628
case MODE_ScanExp:
2040520629
case MODE_Explain: {
2040620630
static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2040720631
static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 };
20408
- static const int aScanExpWidth[] = {4, 6, 6, 13, 4, 4, 4, 13, 2, 13};
20632
+ static const int aScanExpWidth[] = {4, 15, 6, 13, 4, 4, 4, 13, 2, 13};
2040920633
static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 };
2041020634
2041120635
const int *aWidth = aExplainWidth;
2041220636
const int *aMap = aExplainMap;
2041320637
int nWidth = ArraySize(aExplainWidth);
@@ -21413,11 +21637,17 @@
2141321637
UNUSED_PARAMETER(pArg);
2141421638
#else
2141521639
if( pArg->scanstatsOn==3 ){
2141621640
const char *zSql =
2141721641
" SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
21418
- " round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
21642
+ " format('% 6s (%.2f%%)',"
21643
+ " CASE WHEN ncycle<100_000 THEN ncycle || ' '"
21644
+ " WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'"
21645
+ " WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'"
21646
+ " ELSE (ncycle/1000_000_000) || 'G' END,"
21647
+ " ncycle*100.0/(sum(ncycle) OVER ())"
21648
+ " ) AS cycles"
2141921649
" FROM bytecode(?)";
2142021650
2142121651
int rc = SQLITE_OK;
2142221652
sqlite3_stmt *pStmt = 0;
2142321653
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
@@ -22236,10 +22466,11 @@
2223622466
}
2223722467
pExplain = pStmt;
2223822468
sqlite3_reset(pExplain);
2223922469
rc = sqlite3_stmt_explain(pExplain, 2);
2224022470
if( rc==SQLITE_OK ){
22471
+ bind_prepared_stmt(pArg, pExplain);
2224122472
while( sqlite3_step(pExplain)==SQLITE_ROW ){
2224222473
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
2224322474
int iEqpId = sqlite3_column_int(pExplain, 0);
2224422475
int iParentId = sqlite3_column_int(pExplain, 1);
2224522476
if( zEQPLine==0 ) zEQPLine = "";
@@ -22253,10 +22484,11 @@
2225322484
sqlite3_reset(pExplain);
2225422485
rc = sqlite3_stmt_explain(pExplain, 1);
2225522486
if( rc==SQLITE_OK ){
2225622487
pArg->cMode = MODE_Explain;
2225722488
assert( sqlite3_stmt_isexplain(pExplain)==1 );
22489
+ bind_prepared_stmt(pArg, pExplain);
2225822490
explain_data_prepare(pArg, pExplain);
2225922491
exec_prepared_stmt(pArg, pExplain);
2226022492
explain_data_delete(pArg);
2226122493
}
2226222494
}
@@ -23347,10 +23579,11 @@
2334723579
#ifndef SQLITE_OMIT_LOAD_EXTENSION
2334823580
sqlite3_enable_load_extension(p->db, 1);
2334923581
#endif
2335023582
sqlite3_shathree_init(p->db, 0, 0);
2335123583
sqlite3_uint_init(p->db, 0, 0);
23584
+ sqlite3_stmtrand_init(p->db, 0, 0);
2335223585
sqlite3_decimal_init(p->db, 0, 0);
2335323586
sqlite3_base64_init(p->db, 0, 0);
2335423587
sqlite3_base85_init(p->db, 0, 0);
2335523588
sqlite3_regexp_init(p->db, 0, 0);
2335623589
sqlite3_ieee_init(p->db, 0, 0);
@@ -23500,19 +23733,22 @@
2350023733
return rl_completion_matches(zText, readline_completion_generator);
2350123734
}
2350223735
2350323736
#elif HAVE_LINENOISE
2350423737
/*
23505
-** Linenoise completion callback
23738
+** Linenoise completion callback. Note that the 3rd argument is from
23739
+** the "msteveb" version of linenoise, not the "antirez" version.
2350623740
*/
23507
-static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
23741
+static void linenoise_completion(const char *zLine, linenoiseCompletions *lc,
23742
+ void *pUserData){
2350823743
i64 nLine = strlen(zLine);
2350923744
i64 i, iStart;
2351023745
sqlite3_stmt *pStmt = 0;
2351123746
char *zSql;
2351223747
char zBuf[1000];
2351323748
23749
+ UNUSED_PARAMETER(pUserData);
2351423750
if( nLine>(i64)sizeof(zBuf)-30 ) return;
2351523751
if( zLine[0]=='.' || zLine[0]=='#') return;
2351623752
for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
2351723753
if( i==nLine-1 ) return;
2351823754
iStart = i+1;
@@ -25923,30 +26159,37 @@
2592326159
int iId; /* ID that triggers a simulated fault. -1 means "any" */
2592426160
int iErr; /* The error code to return on a fault */
2592526161
int iCnt; /* Trigger the fault only if iCnt is already zero */
2592626162
int iInterval; /* Reset iCnt to this value after each fault */
2592726163
int eVerbose; /* When to print output */
25928
-} faultsim_state = {-1, 0, 0, 0, 0};
26164
+ int nHit; /* Number of hits seen so far */
26165
+ int nRepeat; /* Turn off after this many hits. 0 for never */
26166
+ int nSkip; /* Skip this many before first fault */
26167
+} faultsim_state = {-1, 0, 0, 0, 0, 0, 0, 0};
2592926168
2593026169
/*
2593126170
** This is the fault-sim callback
2593226171
*/
2593326172
static int faultsim_callback(int iArg){
2593426173
if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
2593526174
return SQLITE_OK;
2593626175
}
25937
- if( faultsim_state.iCnt>0 ){
25938
- faultsim_state.iCnt--;
26176
+ if( faultsim_state.iCnt ){
26177
+ if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--;
2593926178
if( faultsim_state.eVerbose>=2 ){
2594026179
oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
2594126180
}
2594226181
return SQLITE_OK;
2594326182
}
2594426183
if( faultsim_state.eVerbose>=1 ){
2594526184
oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
2594626185
}
2594726186
faultsim_state.iCnt = faultsim_state.iInterval;
26187
+ faultsim_state.nHit++;
26188
+ if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){
26189
+ faultsim_state.iCnt = -1;
26190
+ }
2594826191
return faultsim_state.iErr;
2594926192
}
2595026193
2595126194
/*
2595226195
** If an input line begins with "." then invoke this routine to
@@ -26927,10 +27170,11 @@
2692727170
assert(dbCols==0);
2692827171
if( zColDefs==0 ){
2692927172
eputf("%s: empty file\n", sCtx.zFile);
2693027173
import_cleanup(&sCtx);
2693127174
rc = 1;
27175
+ sqlite3_free(zCreate);
2693227176
goto meta_command_exit;
2693327177
}
2693427178
zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
2693527179
if( zCreate==0 ){
2693627180
import_cleanup(&sCtx);
@@ -26953,11 +27197,10 @@
2695327197
zTable, zSchema);
2695427198
if( zSql==0 ){
2695527199
import_cleanup(&sCtx);
2695627200
shell_out_of_memory();
2695727201
}
26958
- nByte = strlen(zSql);
2695927202
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2696027203
sqlite3_free(zSql);
2696127204
zSql = 0;
2696227205
if( rc ){
2696327206
if (pStmt) sqlite3_finalize(pStmt);
@@ -26972,28 +27215,34 @@
2697227215
nCol = 0;
2697327216
}
2697427217
sqlite3_finalize(pStmt);
2697527218
pStmt = 0;
2697627219
if( nCol==0 ) return 0; /* no columns, no error */
26977
- zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
27220
+
27221
+ nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */
27222
+ + (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */
27223
+ + strlen(zTable)*2 + 2 /* Quoted table name */
27224
+ + nCol*2; /* Space for ",?" for each column */
27225
+ zSql = sqlite3_malloc64( nByte );
2697827226
if( zSql==0 ){
2697927227
import_cleanup(&sCtx);
2698027228
shell_out_of_memory();
2698127229
}
2698227230
if( zSchema ){
26983
- sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
27231
+ sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
2698427232
zSchema, zTable);
2698527233
}else{
26986
- sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
27234
+ sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
2698727235
}
2698827236
j = strlen30(zSql);
2698927237
for(i=1; i<nCol; i++){
2699027238
zSql[j++] = ',';
2699127239
zSql[j++] = '?';
2699227240
}
2699327241
zSql[j++] = ')';
2699427242
zSql[j] = 0;
27243
+ assert( j<nByte );
2699527244
if( eVerbose>=2 ){
2699627245
oputf("Insert using: %s\n", zSql);
2699727246
}
2699827247
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2699927248
sqlite3_free(zSql);
@@ -28872,11 +29121,11 @@
2887229121
{"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
2887329122
{"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
2887429123
#ifdef YYCOVERAGE
2887529124
{"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
2887629125
#endif
28877
- {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
29126
+ {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET " },
2887829127
{"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
2887929128
{"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
2888029129
{"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
2888129130
{"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
2888229131
{"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
@@ -29104,21 +29353,27 @@
2910429353
const char *z = azArg[kk];
2910529354
if( z[0]=='-' && z[1]=='-' ) z++;
2910629355
if( cli_strcmp(z,"off")==0 ){
2910729356
sqlite3_test_control(testctrl, 0);
2910829357
}else if( cli_strcmp(z,"on")==0 ){
29109
- faultsim_state.iCnt = faultsim_state.iInterval;
29358
+ faultsim_state.iCnt = faultsim_state.nSkip;
2911029359
if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
29360
+ faultsim_state.nHit = 0;
2911129361
sqlite3_test_control(testctrl, faultsim_callback);
2911229362
}else if( cli_strcmp(z,"reset")==0 ){
29113
- faultsim_state.iCnt = faultsim_state.iInterval;
29363
+ faultsim_state.iCnt = faultsim_state.nSkip;
29364
+ faultsim_state.nHit = 0;
29365
+ sqlite3_test_control(testctrl, faultsim_callback);
2911429366
}else if( cli_strcmp(z,"status")==0 ){
2911529367
oputf("faultsim.iId: %d\n", faultsim_state.iId);
2911629368
oputf("faultsim.iErr: %d\n", faultsim_state.iErr);
2911729369
oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt);
29370
+ oputf("faultsim.nHit: %d\n", faultsim_state.nHit);
2911829371
oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
2911929372
oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose);
29373
+ oputf("faultsim.nRepeat: %d\n", faultsim_state.nRepeat);
29374
+ oputf("faultsim.nSkip: %d\n", faultsim_state.nSkip);
2912029375
}else if( cli_strcmp(z,"-v")==0 ){
2912129376
if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
2912229377
}else if( cli_strcmp(z,"-q")==0 ){
2912329378
if( faultsim_state.eVerbose>0 ) faultsim_state.eVerbose--;
2912429379
}else if( cli_strcmp(z,"-id")==0 && kk+1<nArg ){
@@ -29125,10 +29380,14 @@
2912529380
faultsim_state.iId = atoi(azArg[++kk]);
2912629381
}else if( cli_strcmp(z,"-errcode")==0 && kk+1<nArg ){
2912729382
faultsim_state.iErr = atoi(azArg[++kk]);
2912829383
}else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
2912929384
faultsim_state.iInterval = atoi(azArg[++kk]);
29385
+ }else if( cli_strcmp(z,"-repeat")==0 && kk+1<nArg ){
29386
+ faultsim_state.nRepeat = atoi(azArg[++kk]);
29387
+ }else if( cli_strcmp(z,"-skip")==0 && kk+1<nArg ){
29388
+ faultsim_state.nSkip = atoi(azArg[++kk]);
2913029389
}else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
2913129390
bShowHelp = 1;
2913229391
}else{
2913329392
eputf("Unrecognized fault_install argument: \"%s\"\n",
2913429393
azArg[kk]);
@@ -29148,10 +29407,12 @@
2914829407
" -v Increase verbosity\n"
2914929408
" -q Decrease verbosity\n"
2915029409
" --errcode N When triggered, return N as error code\n"
2915129410
" --id ID Trigger only for the ID specified\n"
2915229411
" --interval N Trigger only after every N-th call\n"
29412
+ " --repeat N Turn off after N hits. 0 means never\n"
29413
+ " --skip N Skip the first N encounters\n"
2915329414
);
2915429415
}
2915529416
break;
2915629417
}
2915729418
}
@@ -29920,31 +30181,33 @@
2992030181
}
2992130182
2992230183
/*
2992330184
** On non-Windows platforms, look for $XDG_CONFIG_HOME.
2992430185
** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
29925
-** the path to it, else return 0. The result is cached for
29926
-** subsequent calls.
30186
+** the path to it. If there is no $(XDG_CONFIG_HOME) then
30187
+** look for $(HOME)/.config/sqlite3/sqliterc and if found
30188
+** return that. If none of these are found, return 0.
30189
+**
30190
+** The string returned is obtained from sqlite3_malloc() and
30191
+** should be freed by the caller.
2992730192
*/
29928
-static const char *find_xdg_config(void){
30193
+static char *find_xdg_config(void){
2992930194
#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
2993030195
|| defined(__RTP__) || defined(_WRS_KERNEL)
2993130196
return 0;
2993230197
#else
29933
- static int alreadyTried = 0;
29934
- static char *zConfig = 0;
30198
+ char *zConfig = 0;
2993530199
const char *zXdgHome;
2993630200
29937
- if( alreadyTried!=0 ){
29938
- return zConfig;
29939
- }
29940
- alreadyTried = 1;
2994130201
zXdgHome = getenv("XDG_CONFIG_HOME");
2994230202
if( zXdgHome==0 ){
29943
- return 0;
30203
+ const char *zHome = getenv("HOME");
30204
+ if( zHome==0 ) return 0;
30205
+ zConfig = sqlite3_mprintf("%s/.config/sqlite3/sqliterc", zHome);
30206
+ }else{
30207
+ zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
2994430208
}
29945
- zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
2994630209
shell_check_oom(zConfig);
2994730210
if( access(zConfig,0)!=0 ){
2994830211
sqlite3_free(zConfig);
2994930212
zConfig = 0;
2995030213
}
@@ -29968,11 +30231,11 @@
2996830231
char *zBuf = 0;
2996930232
FILE *inSaved = p->in;
2997030233
int savedLineno = p->lineno;
2997130234
2997230235
if( sqliterc == NULL ){
29973
- sqliterc = find_xdg_config();
30236
+ sqliterc = zBuf = find_xdg_config();
2997430237
}
2997530238
if( sqliterc == NULL ){
2997630239
home_dir = find_home_dir(0);
2997730240
if( home_dir==0 ){
2997830241
eputz("-- warning: cannot find home directory;"
@@ -30704,12 +30967,12 @@
3070430967
*/
3070530968
for(i=0; i<nCmd; i++){
3070630969
if( azCmd[i][0]=='.' ){
3070730970
rc = do_meta_command(azCmd[i], &data);
3070830971
if( rc ){
30709
- free(azCmd);
30710
- return rc==2 ? 0 : rc;
30972
+ if( rc==2 ) rc = 0;
30973
+ goto shell_main_exit;
3071130974
}
3071230975
}else{
3071330976
open_db(&data, 0);
3071430977
echo_group_input(&data, azCmd[i]);
3071530978
rc = shell_exec(&data, azCmd[i], &zErrMsg);
@@ -30718,12 +30981,12 @@
3071830981
eputf("Error: %s\n", zErrMsg);
3071930982
}else{
3072030983
eputf("Error: unable to process SQL: %s\n", azCmd[i]);
3072130984
}
3072230985
sqlite3_free(zErrMsg);
30723
- free(azCmd);
30724
- return rc!=0 ? rc : 1;
30986
+ if( rc==0 ) rc = 1;
30987
+ goto shell_main_exit;
3072530988
}
3072630989
}
3072730990
}
3072830991
}else{
3072930992
/* Run commands received from standard input
@@ -30757,11 +31020,11 @@
3075731020
}
3075831021
if( zHistory ){ shell_read_history(zHistory); }
3075931022
#if HAVE_READLINE || HAVE_EDITLINE
3076031023
rl_attempted_completion_function = readline_completion;
3076131024
#elif HAVE_LINENOISE
30762
- linenoiseSetCompletionCallback(linenoise_completion);
31025
+ linenoiseSetCompletionCallback(linenoise_completion, NULL);
3076331026
#endif
3076431027
data.in = 0;
3076531028
rc = process_input(&data);
3076631029
if( zHistory ){
3076731030
shell_stifle_history(2000);
@@ -30779,10 +31042,11 @@
3077931042
#ifndef SQLITE_OMIT_VIRTUALTABLE
3078031043
if( data.expert.pExpert ){
3078131044
expertFinish(&data, 1, 0);
3078231045
}
3078331046
#endif
31047
+ shell_main_exit:
3078431048
free(azCmd);
3078531049
set_table_name(&data, 0);
3078631050
if( data.db ){
3078731051
session_close_all(&data, -1);
3078831052
close_db(data.db);
@@ -30811,11 +31075,13 @@
3081131075
if( sqlite3_memory_used()>mem_main_enter ){
3081231076
eputf("Memory leaked: %u bytes\n",
3081331077
(unsigned int)(sqlite3_memory_used()-mem_main_enter));
3081431078
}
3081531079
#endif
30816
-#endif /* !SQLITE_SHELL_FIDDLE */
31080
+#else /* SQLITE_SHELL_FIDDLE... */
31081
+ shell_main_exit:
31082
+#endif
3081731083
return rc;
3081831084
}
3081931085
3082031086
3082131087
#ifdef SQLITE_SHELL_FIDDLE
3082231088
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6002,17 +6002,17 @@
6002 **
6003 ** The query plan selected by seriesBestIndex is passed in the idxNum
6004 ** parameter. (idxStr is not used in this implementation.) idxNum
6005 ** is a bitmask showing which constraints are available:
6006 **
6007 ** 1: start=VALUE
6008 ** 2: stop=VALUE
6009 ** 4: step=VALUE
6010 **
6011 ** Also, if bit 8 is set, that means that the series should be output
6012 ** in descending order rather than in ascending order. If bit 16 is
6013 ** set, then output must appear in ascending order.
6014 **
6015 ** This routine should initialize the cursor and position it so that it
6016 ** is pointing at the first row, or pointing off the end of the table
6017 ** (so that seriesEof() will return true) if the table is empty.
6018 */
@@ -6022,29 +6022,47 @@
6022 int argc, sqlite3_value **argv
6023 ){
6024 series_cursor *pCur = (series_cursor *)pVtabCursor;
6025 int i = 0;
6026 (void)idxStrUnused;
6027 if( idxNum & 1 ){
6028 pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
6029 }else{
6030 pCur->ss.iBase = 0;
6031 }
6032 if( idxNum & 2 ){
6033 pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
6034 }else{
6035 pCur->ss.iTerm = 0xffffffff;
6036 }
6037 if( idxNum & 4 ){
6038 pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
6039 if( pCur->ss.iStep==0 ){
6040 pCur->ss.iStep = 1;
6041 }else if( pCur->ss.iStep<0 ){
6042 if( (idxNum & 16)==0 ) idxNum |= 8;
6043 }
6044 }else{
6045 pCur->ss.iStep = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6046 }
6047 for(i=0; i<argc; i++){
6048 if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
6049 /* If any of the constraints have a NULL value, then return no rows.
6050 ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
@@ -6052,11 +6070,11 @@
6052 pCur->ss.iTerm = 0;
6053 pCur->ss.iStep = 1;
6054 break;
6055 }
6056 }
6057 if( idxNum & 8 ){
6058 pCur->ss.isReversing = pCur->ss.iStep > 0;
6059 }else{
6060 pCur->ss.isReversing = pCur->ss.iStep < 0;
6061 }
6062 setupSequence( &pCur->ss );
@@ -6072,54 +6090,85 @@
6072 ** In this implementation idxNum is used to represent the
6073 ** query plan. idxStr is unused.
6074 **
6075 ** The query plan is represented by bits in idxNum:
6076 **
6077 ** (1) start = $value -- constraint exists
6078 ** (2) stop = $value -- constraint exists
6079 ** (4) step = $value -- constraint exists
6080 ** (8) output in descending order
 
 
 
6081 */
6082 static int seriesBestIndex(
6083 sqlite3_vtab *pVTab,
6084 sqlite3_index_info *pIdxInfo
6085 ){
6086 int i, j; /* Loop over constraints */
6087 int idxNum = 0; /* The query plan bitmask */
 
6088 int bStartSeen = 0; /* EQ constraint seen on the START column */
 
6089 int unusableMask = 0; /* Mask of unusable constraints */
6090 int nArg = 0; /* Number of arguments that seriesFilter() expects */
6091 int aIdx[3]; /* Constraints on start, stop, and step */
6092 const struct sqlite3_index_constraint *pConstraint;
6093
6094 /* This implementation assumes that the start, stop, and step columns
6095 ** are the last three columns in the virtual table. */
6096 assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
6097 assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
6098
6099 aIdx[0] = aIdx[1] = aIdx[2] = -1;
6100 pConstraint = pIdxInfo->aConstraint;
6101 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
6102 int iCol; /* 0 for start, 1 for stop, 2 for step */
6103 int iMask; /* bitmask for those column */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6104 if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
6105 iCol = pConstraint->iColumn - SERIES_COLUMN_START;
6106 assert( iCol>=0 && iCol<=2 );
6107 iMask = 1 << iCol;
6108 if( iCol==0 ) bStartSeen = 1;
 
 
 
 
6109 if( pConstraint->usable==0 ){
6110 unusableMask |= iMask;
6111 continue;
6112 }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
6113 idxNum |= iMask;
6114 aIdx[iCol] = i;
6115 }
6116 }
6117 for(i=0; i<3; i++){
 
 
 
 
 
6118 if( (j = aIdx[i])>=0 ){
6119 pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
6120 pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
 
6121 }
6122 }
6123 /* The current generate_column() implementation requires at least one
6124 ** argument (the START value). Legacy versions assumed START=0 if the
6125 ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
@@ -6136,23 +6185,26 @@
6136 /* The start, stop, and step columns are inputs. Therefore if there
6137 ** are unusable constraints on any of start, stop, or step then
6138 ** this plan is unusable */
6139 return SQLITE_CONSTRAINT;
6140 }
6141 if( (idxNum & 3)==3 ){
6142 /* Both start= and stop= boundaries are available. This is the
6143 ** the preferred case */
6144 pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
6145 pIdxInfo->estimatedRows = 1000;
6146 if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
6147 if( pIdxInfo->aOrderBy[0].desc ){
6148 idxNum |= 8;
6149 }else{
6150 idxNum |= 16;
6151 }
6152 pIdxInfo->orderByConsumed = 1;
6153 }
 
 
 
6154 }else{
6155 /* If either boundary is missing, we have to generate a huge span
6156 ** of numbers. Make this case very expensive so that the query
6157 ** planner will work hard to avoid it. */
6158 pIdxInfo->estimatedRows = 2147483647;
@@ -7475,11 +7527,13 @@
7475 ){
7476 if( zFile==0 ) return 1;
7477 #if !defined(_WIN32) && !defined(WIN32)
7478 if( S_ISLNK(mode) ){
7479 const char *zTo = (const char*)sqlite3_value_text(pData);
7480 if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
 
 
7481 }else
7482 #endif
7483 {
7484 if( S_ISDIR(mode) ){
7485 if( mkdir(zFile, mode) ){
@@ -7561,17 +7615,23 @@
7561 times[1].tv_sec = mtime;
7562 if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
7563 return 1;
7564 }
7565 #else
7566 /* Legacy unix */
7567 struct timeval times[2];
7568 times[0].tv_usec = times[1].tv_usec = 0;
7569 times[0].tv_sec = time(0);
7570 times[1].tv_sec = mtime;
7571 if( utimes(zFile, times) ){
7572 return 1;
 
 
 
 
 
 
7573 }
7574 #endif
7575 }
7576
7577 return 0;
@@ -9348,11 +9408,13 @@
9348 /* #include "sqlite3ext.h" */
9349 SQLITE_EXTENSION_INIT1
9350 #include <stdio.h>
9351 #include <string.h>
9352 #include <assert.h>
9353 #include <stdint.h>
 
 
9354
9355 #include <zlib.h>
9356
9357 #ifndef SQLITE_OMIT_VIRTUALTABLE
9358
@@ -11639,26 +11701,27 @@
11639 sqlite3_context *context,
11640 int argc,
11641 sqlite3_value **argv
11642 ){
11643 uLong nData;
11644 uLongf sz;
11645
11646 assert( argc==2 );
11647 sz = sqlite3_value_int(argv[1]);
11648
11649 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
11650 sqlite3_result_value(context, argv[0]);
11651 }else{
 
11652 const Bytef *pData= sqlite3_value_blob(argv[0]);
11653 Bytef *pOut = sqlite3_malloc(sz);
11654 if( pOut==0 ){
11655 sqlite3_result_error_nomem(context);
11656 }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
11657 sqlite3_result_error(context, "error in uncompress()", -1);
11658 }else{
11659 sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
11660 }
11661 sqlite3_free(pOut);
11662 }
11663 }
11664
@@ -14007,11 +14070,10 @@
14007 }
14008
14009 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
14010
14011 /************************* End ../ext/expert/sqlite3expert.c ********************/
14012
14013 /************************* Begin ../ext/intck/sqlite3intck.h ******************/
14014 /*
14015 ** 2024-02-08
14016 **
14017 ** The author disclaims copyright to this source code. In place of
@@ -15125,10 +15187,110 @@
15125 }
15126 return p->zTestSql;
15127 }
15128
15129 /************************* End ../ext/intck/sqlite3intck.c ********************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15130
15131 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
15132 #define SQLITE_SHELL_HAVE_RECOVER 1
15133 #else
15134 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -15476,10 +15638,19 @@
15476
15477 #define DBDATA_PADDING_BYTES 100
15478
15479 typedef struct DbdataTable DbdataTable;
15480 typedef struct DbdataCursor DbdataCursor;
 
 
 
 
 
 
 
 
 
15481
15482 /* Cursor object */
15483 struct DbdataCursor {
15484 sqlite3_vtab_cursor base; /* Base class. Must be first */
15485 sqlite3_stmt *pStmt; /* For fetching database pages */
@@ -15492,11 +15663,11 @@
15492 int bOnePage; /* True to stop after one page */
15493 int szDb;
15494 sqlite3_int64 iRowid;
15495
15496 /* Only for the sqlite_dbdata table */
15497 u8 *pRec; /* Buffer containing current record */
15498 sqlite3_int64 nRec; /* Size of pRec[] in bytes */
15499 sqlite3_int64 nHdr; /* Size of header in bytes */
15500 int iField; /* Current field number */
15501 u8 *pHdrPtr;
15502 u8 *pPtr;
@@ -15536,10 +15707,35 @@
15536 "CREATE TABLE x(" \
15537 " pgno INTEGER," \
15538 " child INTEGER," \
15539 " schema TEXT HIDDEN" \
15540 ")"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15541
15542 /*
15543 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
15544 ** table.
15545 */
@@ -15677,13 +15873,13 @@
15677 pCsr->iPgno = 1;
15678 pCsr->iCell = 0;
15679 pCsr->iField = 0;
15680 pCsr->bOnePage = 0;
15681 sqlite3_free(pCsr->aPage);
15682 sqlite3_free(pCsr->pRec);
15683 pCsr->pRec = 0;
15684 pCsr->aPage = 0;
 
15685 }
15686
15687 /*
15688 ** Close an sqlite_dbdata or sqlite_dbptr cursor.
15689 */
@@ -15821,70 +16017,91 @@
15821 u32 enc,
15822 int eType,
15823 u8 *pData,
15824 sqlite3_int64 nData
15825 ){
15826 if( eType>=0 && dbdataValueBytes(eType)<=nData ){
15827 switch( eType ){
15828 case 0:
15829 case 10:
15830 case 11:
15831 sqlite3_result_null(pCtx);
15832 break;
15833
15834 case 8:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15835 sqlite3_result_int(pCtx, 0);
15836 break;
15837 case 9:
15838 sqlite3_result_int(pCtx, 1);
15839 break;
15840
15841 case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
15842 sqlite3_uint64 v = (signed char)pData[0];
15843 pData++;
15844 switch( eType ){
15845 case 7:
15846 case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
15847 case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
15848 case 4: v = (v<<8) + pData[0]; pData++;
15849 case 3: v = (v<<8) + pData[0]; pData++;
15850 case 2: v = (v<<8) + pData[0]; pData++;
15851 }
15852
15853 if( eType==7 ){
15854 double r;
15855 memcpy(&r, &v, sizeof(r));
15856 sqlite3_result_double(pCtx, r);
15857 }else{
15858 sqlite3_result_int64(pCtx, (sqlite3_int64)v);
15859 }
15860 break;
15861 }
15862
15863 default: {
15864 int n = ((eType-12) / 2);
15865 if( eType % 2 ){
15866 switch( enc ){
15867 #ifndef SQLITE_OMIT_UTF16
15868 case SQLITE_UTF16BE:
15869 sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
15870 break;
15871 case SQLITE_UTF16LE:
15872 sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
15873 break;
15874 #endif
15875 default:
15876 sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
15877 break;
15878 }
15879 }else{
15880 sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
15881 }
15882 }
15883 }
15884 }
15885 }
15886
15887 /*
15888 ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
15889 */
15890 static int dbdataNext(sqlite3_vtab_cursor *pCursor){
@@ -15910,10 +16127,13 @@
15910 }
15911
15912 assert( iOff+3+2<=pCsr->nPage );
15913 pCsr->iCell = pTab->bPtr ? -2 : 0;
15914 pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
 
 
 
15915 }
15916
15917 if( pTab->bPtr ){
15918 if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
15919 pCsr->iCell = pCsr->nCell;
@@ -15927,11 +16147,12 @@
15927 }else{
15928 return SQLITE_OK;
15929 }
15930 }else{
15931 /* If there is no record loaded, load it now. */
15932 if( pCsr->pRec==0 ){
 
15933 int bHasRowid = 0;
15934 int nPointer = 0;
15935 sqlite3_int64 nPayload = 0;
15936 sqlite3_int64 nHdr = 0;
15937 int iHdr;
@@ -15954,27 +16175,28 @@
15954 }
15955
15956 if( pCsr->iCell>=pCsr->nCell ){
15957 bNextPage = 1;
15958 }else{
 
15959
15960 iOff += 8 + nPointer + pCsr->iCell*2;
15961 if( iOff>pCsr->nPage ){
15962 bNextPage = 1;
15963 }else{
15964 iOff = get_uint16(&pCsr->aPage[iOff]);
15965 }
15966
15967 /* For an interior node cell, skip past the child-page number */
15968 iOff += nPointer;
15969
15970 /* Load the "byte of payload including overflow" field */
15971 if( bNextPage || iOff>pCsr->nPage ){
15972 bNextPage = 1;
15973 }else{
15974 iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
15975 if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
 
15976 }
15977
15978 /* If this is a leaf intkey cell, load the rowid */
15979 if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
15980 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
@@ -16005,17 +16227,16 @@
16005 }else{
16006
16007 /* Allocate space for payload. And a bit more to catch small buffer
16008 ** overruns caused by attempting to read a varint or similar from
16009 ** near the end of a corrupt record. */
16010 pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
16011 if( pCsr->pRec==0 ) return SQLITE_NOMEM;
16012 memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
16013 pCsr->nRec = nPayload;
16014
16015 /* Load the nLocal bytes of payload */
16016 memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
16017 iOff += nLocal;
16018
16019 /* Load content from overflow pages */
16020 if( nPayload>nLocal ){
16021 sqlite3_int64 nRem = nPayload - nLocal;
@@ -16029,61 +16250,64 @@
16029 if( rc!=SQLITE_OK ) return rc;
16030 if( aOvfl==0 ) break;
16031
16032 nCopy = U-4;
16033 if( nCopy>nRem ) nCopy = nRem;
16034 memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
16035 nRem -= nCopy;
16036
16037 pgnoOvfl = get_uint32(aOvfl);
16038 sqlite3_free(aOvfl);
16039 }
 
16040 }
 
 
16041
16042 iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
16043 if( nHdr>nPayload ) nHdr = 0;
16044 pCsr->nHdr = nHdr;
16045 pCsr->pHdrPtr = &pCsr->pRec[iHdr];
16046 pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
16047 pCsr->iField = (bHasRowid ? -1 : 0);
16048 }
16049 }
16050 }else{
16051 pCsr->iField++;
16052 if( pCsr->iField>0 ){
16053 sqlite3_int64 iType;
16054 if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
 
 
16055 bNextPage = 1;
16056 }else{
16057 int szField = 0;
16058 pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
16059 szField = dbdataValueBytes(iType);
16060 if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
16061 pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
16062 }else{
16063 pCsr->pPtr += szField;
16064 }
16065 }
16066 }
16067 }
16068
16069 if( bNextPage ){
16070 sqlite3_free(pCsr->aPage);
16071 sqlite3_free(pCsr->pRec);
16072 pCsr->aPage = 0;
16073 pCsr->pRec = 0;
16074 if( pCsr->bOnePage ) return SQLITE_OK;
16075 pCsr->iPgno++;
16076 }else{
16077 if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
16078 return SQLITE_OK;
16079 }
16080
16081 /* Advance to the next cell. The next iteration of the loop will load
16082 ** the record and so on. */
16083 sqlite3_free(pCsr->pRec);
16084 pCsr->pRec = 0;
16085 pCsr->iCell++;
16086 }
16087 }
16088 }
16089
@@ -16269,16 +16493,16 @@
16269 sqlite3_result_int(ctx, pCsr->iField);
16270 break;
16271 case DBDATA_COLUMN_VALUE: {
16272 if( pCsr->iField<0 ){
16273 sqlite3_result_int64(ctx, pCsr->iIntkey);
16274 }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
16275 sqlite3_int64 iType;
16276 dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
16277 dbdataValue(
16278 ctx, pCsr->enc, iType, pCsr->pPtr,
16279 &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
16280 );
16281 }
16282 break;
16283 }
16284 }
@@ -17537,11 +17761,11 @@
17537 if( rc==SQLITE_OK ){
17538 recoverSqlCallback(p, zSql);
17539 if( bTable && !bVirtual ){
17540 if( SQLITE_ROW==sqlite3_step(pTblname) ){
17541 const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
17542 recoverAddTable(p, zTbl, iRoot);
17543 }
17544 recoverReset(p, pTblname);
17545 }
17546 }else if( rc!=SQLITE_ERROR ){
17547 recoverDbError(p, p->dbOut);
@@ -20403,11 +20627,11 @@
20403 }
20404 case MODE_ScanExp:
20405 case MODE_Explain: {
20406 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
20407 static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 };
20408 static const int aScanExpWidth[] = {4, 6, 6, 13, 4, 4, 4, 13, 2, 13};
20409 static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 };
20410
20411 const int *aWidth = aExplainWidth;
20412 const int *aMap = aExplainMap;
20413 int nWidth = ArraySize(aExplainWidth);
@@ -21413,11 +21637,17 @@
21413 UNUSED_PARAMETER(pArg);
21414 #else
21415 if( pArg->scanstatsOn==3 ){
21416 const char *zSql =
21417 " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
21418 " round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
 
 
 
 
 
 
21419 " FROM bytecode(?)";
21420
21421 int rc = SQLITE_OK;
21422 sqlite3_stmt *pStmt = 0;
21423 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
@@ -22236,10 +22466,11 @@
22236 }
22237 pExplain = pStmt;
22238 sqlite3_reset(pExplain);
22239 rc = sqlite3_stmt_explain(pExplain, 2);
22240 if( rc==SQLITE_OK ){
 
22241 while( sqlite3_step(pExplain)==SQLITE_ROW ){
22242 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
22243 int iEqpId = sqlite3_column_int(pExplain, 0);
22244 int iParentId = sqlite3_column_int(pExplain, 1);
22245 if( zEQPLine==0 ) zEQPLine = "";
@@ -22253,10 +22484,11 @@
22253 sqlite3_reset(pExplain);
22254 rc = sqlite3_stmt_explain(pExplain, 1);
22255 if( rc==SQLITE_OK ){
22256 pArg->cMode = MODE_Explain;
22257 assert( sqlite3_stmt_isexplain(pExplain)==1 );
 
22258 explain_data_prepare(pArg, pExplain);
22259 exec_prepared_stmt(pArg, pExplain);
22260 explain_data_delete(pArg);
22261 }
22262 }
@@ -23347,10 +23579,11 @@
23347 #ifndef SQLITE_OMIT_LOAD_EXTENSION
23348 sqlite3_enable_load_extension(p->db, 1);
23349 #endif
23350 sqlite3_shathree_init(p->db, 0, 0);
23351 sqlite3_uint_init(p->db, 0, 0);
 
23352 sqlite3_decimal_init(p->db, 0, 0);
23353 sqlite3_base64_init(p->db, 0, 0);
23354 sqlite3_base85_init(p->db, 0, 0);
23355 sqlite3_regexp_init(p->db, 0, 0);
23356 sqlite3_ieee_init(p->db, 0, 0);
@@ -23500,19 +23733,22 @@
23500 return rl_completion_matches(zText, readline_completion_generator);
23501 }
23502
23503 #elif HAVE_LINENOISE
23504 /*
23505 ** Linenoise completion callback
 
23506 */
23507 static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
 
23508 i64 nLine = strlen(zLine);
23509 i64 i, iStart;
23510 sqlite3_stmt *pStmt = 0;
23511 char *zSql;
23512 char zBuf[1000];
23513
 
23514 if( nLine>(i64)sizeof(zBuf)-30 ) return;
23515 if( zLine[0]=='.' || zLine[0]=='#') return;
23516 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
23517 if( i==nLine-1 ) return;
23518 iStart = i+1;
@@ -25923,30 +26159,37 @@
25923 int iId; /* ID that triggers a simulated fault. -1 means "any" */
25924 int iErr; /* The error code to return on a fault */
25925 int iCnt; /* Trigger the fault only if iCnt is already zero */
25926 int iInterval; /* Reset iCnt to this value after each fault */
25927 int eVerbose; /* When to print output */
25928 } faultsim_state = {-1, 0, 0, 0, 0};
 
 
 
25929
25930 /*
25931 ** This is the fault-sim callback
25932 */
25933 static int faultsim_callback(int iArg){
25934 if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
25935 return SQLITE_OK;
25936 }
25937 if( faultsim_state.iCnt>0 ){
25938 faultsim_state.iCnt--;
25939 if( faultsim_state.eVerbose>=2 ){
25940 oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
25941 }
25942 return SQLITE_OK;
25943 }
25944 if( faultsim_state.eVerbose>=1 ){
25945 oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
25946 }
25947 faultsim_state.iCnt = faultsim_state.iInterval;
 
 
 
 
25948 return faultsim_state.iErr;
25949 }
25950
25951 /*
25952 ** If an input line begins with "." then invoke this routine to
@@ -26927,10 +27170,11 @@
26927 assert(dbCols==0);
26928 if( zColDefs==0 ){
26929 eputf("%s: empty file\n", sCtx.zFile);
26930 import_cleanup(&sCtx);
26931 rc = 1;
 
26932 goto meta_command_exit;
26933 }
26934 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
26935 if( zCreate==0 ){
26936 import_cleanup(&sCtx);
@@ -26953,11 +27197,10 @@
26953 zTable, zSchema);
26954 if( zSql==0 ){
26955 import_cleanup(&sCtx);
26956 shell_out_of_memory();
26957 }
26958 nByte = strlen(zSql);
26959 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
26960 sqlite3_free(zSql);
26961 zSql = 0;
26962 if( rc ){
26963 if (pStmt) sqlite3_finalize(pStmt);
@@ -26972,28 +27215,34 @@
26972 nCol = 0;
26973 }
26974 sqlite3_finalize(pStmt);
26975 pStmt = 0;
26976 if( nCol==0 ) return 0; /* no columns, no error */
26977 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
 
 
 
 
 
26978 if( zSql==0 ){
26979 import_cleanup(&sCtx);
26980 shell_out_of_memory();
26981 }
26982 if( zSchema ){
26983 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
26984 zSchema, zTable);
26985 }else{
26986 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
26987 }
26988 j = strlen30(zSql);
26989 for(i=1; i<nCol; i++){
26990 zSql[j++] = ',';
26991 zSql[j++] = '?';
26992 }
26993 zSql[j++] = ')';
26994 zSql[j] = 0;
 
26995 if( eVerbose>=2 ){
26996 oputf("Insert using: %s\n", zSql);
26997 }
26998 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
26999 sqlite3_free(zSql);
@@ -28872,11 +29121,11 @@
28872 {"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
28873 {"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
28874 #ifdef YYCOVERAGE
28875 {"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
28876 #endif
28877 {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
28878 {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
28879 {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
28880 {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
28881 {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
28882 {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
@@ -29104,21 +29353,27 @@
29104 const char *z = azArg[kk];
29105 if( z[0]=='-' && z[1]=='-' ) z++;
29106 if( cli_strcmp(z,"off")==0 ){
29107 sqlite3_test_control(testctrl, 0);
29108 }else if( cli_strcmp(z,"on")==0 ){
29109 faultsim_state.iCnt = faultsim_state.iInterval;
29110 if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
 
29111 sqlite3_test_control(testctrl, faultsim_callback);
29112 }else if( cli_strcmp(z,"reset")==0 ){
29113 faultsim_state.iCnt = faultsim_state.iInterval;
 
 
29114 }else if( cli_strcmp(z,"status")==0 ){
29115 oputf("faultsim.iId: %d\n", faultsim_state.iId);
29116 oputf("faultsim.iErr: %d\n", faultsim_state.iErr);
29117 oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt);
 
29118 oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
29119 oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose);
 
 
29120 }else if( cli_strcmp(z,"-v")==0 ){
29121 if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
29122 }else if( cli_strcmp(z,"-q")==0 ){
29123 if( faultsim_state.eVerbose>0 ) faultsim_state.eVerbose--;
29124 }else if( cli_strcmp(z,"-id")==0 && kk+1<nArg ){
@@ -29125,10 +29380,14 @@
29125 faultsim_state.iId = atoi(azArg[++kk]);
29126 }else if( cli_strcmp(z,"-errcode")==0 && kk+1<nArg ){
29127 faultsim_state.iErr = atoi(azArg[++kk]);
29128 }else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
29129 faultsim_state.iInterval = atoi(azArg[++kk]);
 
 
 
 
29130 }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
29131 bShowHelp = 1;
29132 }else{
29133 eputf("Unrecognized fault_install argument: \"%s\"\n",
29134 azArg[kk]);
@@ -29148,10 +29407,12 @@
29148 " -v Increase verbosity\n"
29149 " -q Decrease verbosity\n"
29150 " --errcode N When triggered, return N as error code\n"
29151 " --id ID Trigger only for the ID specified\n"
29152 " --interval N Trigger only after every N-th call\n"
 
 
29153 );
29154 }
29155 break;
29156 }
29157 }
@@ -29920,31 +30181,33 @@
29920 }
29921
29922 /*
29923 ** On non-Windows platforms, look for $XDG_CONFIG_HOME.
29924 ** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
29925 ** the path to it, else return 0. The result is cached for
29926 ** subsequent calls.
 
 
 
 
29927 */
29928 static const char *find_xdg_config(void){
29929 #if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
29930 || defined(__RTP__) || defined(_WRS_KERNEL)
29931 return 0;
29932 #else
29933 static int alreadyTried = 0;
29934 static char *zConfig = 0;
29935 const char *zXdgHome;
29936
29937 if( alreadyTried!=0 ){
29938 return zConfig;
29939 }
29940 alreadyTried = 1;
29941 zXdgHome = getenv("XDG_CONFIG_HOME");
29942 if( zXdgHome==0 ){
29943 return 0;
 
 
 
 
29944 }
29945 zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
29946 shell_check_oom(zConfig);
29947 if( access(zConfig,0)!=0 ){
29948 sqlite3_free(zConfig);
29949 zConfig = 0;
29950 }
@@ -29968,11 +30231,11 @@
29968 char *zBuf = 0;
29969 FILE *inSaved = p->in;
29970 int savedLineno = p->lineno;
29971
29972 if( sqliterc == NULL ){
29973 sqliterc = find_xdg_config();
29974 }
29975 if( sqliterc == NULL ){
29976 home_dir = find_home_dir(0);
29977 if( home_dir==0 ){
29978 eputz("-- warning: cannot find home directory;"
@@ -30704,12 +30967,12 @@
30704 */
30705 for(i=0; i<nCmd; i++){
30706 if( azCmd[i][0]=='.' ){
30707 rc = do_meta_command(azCmd[i], &data);
30708 if( rc ){
30709 free(azCmd);
30710 return rc==2 ? 0 : rc;
30711 }
30712 }else{
30713 open_db(&data, 0);
30714 echo_group_input(&data, azCmd[i]);
30715 rc = shell_exec(&data, azCmd[i], &zErrMsg);
@@ -30718,12 +30981,12 @@
30718 eputf("Error: %s\n", zErrMsg);
30719 }else{
30720 eputf("Error: unable to process SQL: %s\n", azCmd[i]);
30721 }
30722 sqlite3_free(zErrMsg);
30723 free(azCmd);
30724 return rc!=0 ? rc : 1;
30725 }
30726 }
30727 }
30728 }else{
30729 /* Run commands received from standard input
@@ -30757,11 +31020,11 @@
30757 }
30758 if( zHistory ){ shell_read_history(zHistory); }
30759 #if HAVE_READLINE || HAVE_EDITLINE
30760 rl_attempted_completion_function = readline_completion;
30761 #elif HAVE_LINENOISE
30762 linenoiseSetCompletionCallback(linenoise_completion);
30763 #endif
30764 data.in = 0;
30765 rc = process_input(&data);
30766 if( zHistory ){
30767 shell_stifle_history(2000);
@@ -30779,10 +31042,11 @@
30779 #ifndef SQLITE_OMIT_VIRTUALTABLE
30780 if( data.expert.pExpert ){
30781 expertFinish(&data, 1, 0);
30782 }
30783 #endif
 
30784 free(azCmd);
30785 set_table_name(&data, 0);
30786 if( data.db ){
30787 session_close_all(&data, -1);
30788 close_db(data.db);
@@ -30811,11 +31075,13 @@
30811 if( sqlite3_memory_used()>mem_main_enter ){
30812 eputf("Memory leaked: %u bytes\n",
30813 (unsigned int)(sqlite3_memory_used()-mem_main_enter));
30814 }
30815 #endif
30816 #endif /* !SQLITE_SHELL_FIDDLE */
 
 
30817 return rc;
30818 }
30819
30820
30821 #ifdef SQLITE_SHELL_FIDDLE
30822
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6002,17 +6002,17 @@
6002 **
6003 ** The query plan selected by seriesBestIndex is passed in the idxNum
6004 ** parameter. (idxStr is not used in this implementation.) idxNum
6005 ** is a bitmask showing which constraints are available:
6006 **
6007 ** 0x01: start=VALUE
6008 ** 0x02: stop=VALUE
6009 ** 0x04: step=VALUE
6010 ** 0x08: descending order
6011 ** 0x10: ascending order
6012 ** 0x20: LIMIT VALUE
6013 ** 0x40: OFFSET VALUE
6014 **
6015 ** This routine should initialize the cursor and position it so that it
6016 ** is pointing at the first row, or pointing off the end of the table
6017 ** (so that seriesEof() will return true) if the table is empty.
6018 */
@@ -6022,29 +6022,47 @@
6022 int argc, sqlite3_value **argv
6023 ){
6024 series_cursor *pCur = (series_cursor *)pVtabCursor;
6025 int i = 0;
6026 (void)idxStrUnused;
6027 if( idxNum & 0x01 ){
6028 pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
6029 }else{
6030 pCur->ss.iBase = 0;
6031 }
6032 if( idxNum & 0x02 ){
6033 pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
6034 }else{
6035 pCur->ss.iTerm = 0xffffffff;
6036 }
6037 if( idxNum & 0x04 ){
6038 pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
6039 if( pCur->ss.iStep==0 ){
6040 pCur->ss.iStep = 1;
6041 }else if( pCur->ss.iStep<0 ){
6042 if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
6043 }
6044 }else{
6045 pCur->ss.iStep = 1;
6046 }
6047 if( idxNum & 0x20 ){
6048 sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
6049 sqlite3_int64 iTerm;
6050 if( idxNum & 0x40 ){
6051 sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
6052 if( iOffset>0 ){
6053 pCur->ss.iBase += pCur->ss.iStep*iOffset;
6054 }
6055 }
6056 if( iLimit>=0 ){
6057 iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
6058 if( pCur->ss.iStep<0 ){
6059 if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
6060 }else{
6061 if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
6062 }
6063 }
6064 }
6065 for(i=0; i<argc; i++){
6066 if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
6067 /* If any of the constraints have a NULL value, then return no rows.
6068 ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
@@ -6052,11 +6070,11 @@
6070 pCur->ss.iTerm = 0;
6071 pCur->ss.iStep = 1;
6072 break;
6073 }
6074 }
6075 if( idxNum & 0x08 ){
6076 pCur->ss.isReversing = pCur->ss.iStep > 0;
6077 }else{
6078 pCur->ss.isReversing = pCur->ss.iStep < 0;
6079 }
6080 setupSequence( &pCur->ss );
@@ -6072,54 +6090,85 @@
6090 ** In this implementation idxNum is used to represent the
6091 ** query plan. idxStr is unused.
6092 **
6093 ** The query plan is represented by bits in idxNum:
6094 **
6095 ** 0x01 start = $value -- constraint exists
6096 ** 0x02 stop = $value -- constraint exists
6097 ** 0x04 step = $value -- constraint exists
6098 ** 0x08 output is in descending order
6099 ** 0x10 output is in ascending order
6100 ** 0x20 LIMIT $value -- constraint exists
6101 ** 0x40 OFFSET $value -- constraint exists
6102 */
6103 static int seriesBestIndex(
6104 sqlite3_vtab *pVTab,
6105 sqlite3_index_info *pIdxInfo
6106 ){
6107 int i, j; /* Loop over constraints */
6108 int idxNum = 0; /* The query plan bitmask */
6109 #ifndef ZERO_ARGUMENT_GENERATE_SERIES
6110 int bStartSeen = 0; /* EQ constraint seen on the START column */
6111 #endif
6112 int unusableMask = 0; /* Mask of unusable constraints */
6113 int nArg = 0; /* Number of arguments that seriesFilter() expects */
6114 int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
6115 const struct sqlite3_index_constraint *pConstraint;
6116
6117 /* This implementation assumes that the start, stop, and step columns
6118 ** are the last three columns in the virtual table. */
6119 assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
6120 assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
6121
6122 aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
6123 pConstraint = pIdxInfo->aConstraint;
6124 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
6125 int iCol; /* 0 for start, 1 for stop, 2 for step */
6126 int iMask; /* bitmask for those column */
6127 int op = pConstraint->op;
6128 if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
6129 && op<=SQLITE_INDEX_CONSTRAINT_OFFSET
6130 ){
6131 if( pConstraint->usable==0 ){
6132 /* do nothing */
6133 }else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
6134 aIdx[3] = i;
6135 idxNum |= 0x20;
6136 }else{
6137 assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
6138 aIdx[4] = i;
6139 idxNum |= 0x40;
6140 }
6141 continue;
6142 }
6143 if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
6144 iCol = pConstraint->iColumn - SERIES_COLUMN_START;
6145 assert( iCol>=0 && iCol<=2 );
6146 iMask = 1 << iCol;
6147 #ifndef ZERO_ARGUMENT_GENERATE_SERIES
6148 if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
6149 bStartSeen = 1;
6150 }
6151 #endif
6152 if( pConstraint->usable==0 ){
6153 unusableMask |= iMask;
6154 continue;
6155 }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
6156 idxNum |= iMask;
6157 aIdx[iCol] = i;
6158 }
6159 }
6160 if( aIdx[3]==0 ){
6161 /* Ignore OFFSET if LIMIT is omitted */
6162 idxNum &= ~0x60;
6163 aIdx[4] = 0;
6164 }
6165 for(i=0; i<5; i++){
6166 if( (j = aIdx[i])>=0 ){
6167 pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
6168 pIdxInfo->aConstraintUsage[j].omit =
6169 !SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
6170 }
6171 }
6172 /* The current generate_column() implementation requires at least one
6173 ** argument (the START value). Legacy versions assumed START=0 if the
6174 ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
@@ -6136,23 +6185,26 @@
6185 /* The start, stop, and step columns are inputs. Therefore if there
6186 ** are unusable constraints on any of start, stop, or step then
6187 ** this plan is unusable */
6188 return SQLITE_CONSTRAINT;
6189 }
6190 if( (idxNum & 0x03)==0x03 ){
6191 /* Both start= and stop= boundaries are available. This is the
6192 ** the preferred case */
6193 pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
6194 pIdxInfo->estimatedRows = 1000;
6195 if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
6196 if( pIdxInfo->aOrderBy[0].desc ){
6197 idxNum |= 0x08;
6198 }else{
6199 idxNum |= 0x10;
6200 }
6201 pIdxInfo->orderByConsumed = 1;
6202 }
6203 }else if( (idxNum & 0x21)==0x21 ){
6204 /* We have start= and LIMIT */
6205 pIdxInfo->estimatedRows = 2500;
6206 }else{
6207 /* If either boundary is missing, we have to generate a huge span
6208 ** of numbers. Make this case very expensive so that the query
6209 ** planner will work hard to avoid it. */
6210 pIdxInfo->estimatedRows = 2147483647;
@@ -7475,11 +7527,13 @@
7527 ){
7528 if( zFile==0 ) return 1;
7529 #if !defined(_WIN32) && !defined(WIN32)
7530 if( S_ISLNK(mode) ){
7531 const char *zTo = (const char*)sqlite3_value_text(pData);
7532 if( zTo==0 ) return 1;
7533 unlink(zFile);
7534 if( symlink(zTo, zFile)<0 ) return 1;
7535 }else
7536 #endif
7537 {
7538 if( S_ISDIR(mode) ){
7539 if( mkdir(zFile, mode) ){
@@ -7561,17 +7615,23 @@
7615 times[1].tv_sec = mtime;
7616 if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
7617 return 1;
7618 }
7619 #else
7620 /* Legacy unix.
7621 **
7622 ** Do not use utimes() on a symbolic link - it sees through the link and
7623 ** modifies the timestamps on the target. Or fails if the target does
7624 ** not exist. */
7625 if( 0==S_ISLNK(mode) ){
7626 struct timeval times[2];
7627 times[0].tv_usec = times[1].tv_usec = 0;
7628 times[0].tv_sec = time(0);
7629 times[1].tv_sec = mtime;
7630 if( utimes(zFile, times) ){
7631 return 1;
7632 }
7633 }
7634 #endif
7635 }
7636
7637 return 0;
@@ -9348,11 +9408,13 @@
9408 /* #include "sqlite3ext.h" */
9409 SQLITE_EXTENSION_INIT1
9410 #include <stdio.h>
9411 #include <string.h>
9412 #include <assert.h>
9413 #ifndef SQLITE_NO_STDINT
9414 # include <stdint.h>
9415 #endif
9416
9417 #include <zlib.h>
9418
9419 #ifndef SQLITE_OMIT_VIRTUALTABLE
9420
@@ -11639,26 +11701,27 @@
11701 sqlite3_context *context,
11702 int argc,
11703 sqlite3_value **argv
11704 ){
11705 uLong nData;
11706 sqlite3_int64 sz;
11707
11708 assert( argc==2 );
11709 sz = sqlite3_value_int(argv[1]);
11710
11711 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
11712 sqlite3_result_value(context, argv[0]);
11713 }else{
11714 uLongf szf = sz;
11715 const Bytef *pData= sqlite3_value_blob(argv[0]);
11716 Bytef *pOut = sqlite3_malloc(sz);
11717 if( pOut==0 ){
11718 sqlite3_result_error_nomem(context);
11719 }else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
11720 sqlite3_result_error(context, "error in uncompress()", -1);
11721 }else{
11722 sqlite3_result_blob(context, pOut, szf, SQLITE_TRANSIENT);
11723 }
11724 sqlite3_free(pOut);
11725 }
11726 }
11727
@@ -14007,11 +14070,10 @@
14070 }
14071
14072 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
14073
14074 /************************* End ../ext/expert/sqlite3expert.c ********************/
 
14075 /************************* Begin ../ext/intck/sqlite3intck.h ******************/
14076 /*
14077 ** 2024-02-08
14078 **
14079 ** The author disclaims copyright to this source code. In place of
@@ -15125,10 +15187,110 @@
15187 }
15188 return p->zTestSql;
15189 }
15190
15191 /************************* End ../ext/intck/sqlite3intck.c ********************/
15192 /************************* Begin ../ext/misc/stmtrand.c ******************/
15193 /*
15194 ** 2024-05-24
15195 **
15196 ** The author disclaims copyright to this source code. In place of
15197 ** a legal notice, here is a blessing:
15198 **
15199 ** May you do good and not evil.
15200 ** May you find forgiveness for yourself and forgive others.
15201 ** May you share freely, never taking more than you give.
15202 **
15203 ******************************************************************************
15204 **
15205 ** An SQL function that return pseudo-random non-negative integers.
15206 **
15207 ** SELECT stmtrand(123);
15208 **
15209 ** A special feature of this function is that the same sequence of random
15210 ** integers is returned for each invocation of the statement. This makes
15211 ** the results repeatable, and hence useful for testing. The argument is
15212 ** an integer which is the seed for the random number sequence. The seed
15213 ** is used by the first invocation of this function only and is ignored
15214 ** for all subsequent calls within the same statement.
15215 **
15216 ** Resetting a statement (sqlite3_reset()) also resets the random number
15217 ** sequence.
15218 */
15219 /* #include "sqlite3ext.h" */
15220 SQLITE_EXTENSION_INIT1
15221 #include <assert.h>
15222 #include <string.h>
15223
15224 /* State of the pseudo-random number generator */
15225 typedef struct Stmtrand {
15226 unsigned int x, y;
15227 } Stmtrand;
15228
15229 /* auxdata key */
15230 #define STMTRAND_KEY (-4418371)
15231
15232 /*
15233 ** Function: stmtrand(SEED)
15234 **
15235 ** Return a pseudo-random number.
15236 */
15237 static void stmtrandFunc(
15238 sqlite3_context *context,
15239 int argc,
15240 sqlite3_value **argv
15241 ){
15242 Stmtrand *p;
15243
15244 p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
15245 if( p==0 ){
15246 unsigned int seed;
15247 p = sqlite3_malloc( sizeof(*p) );
15248 if( p==0 ){
15249 sqlite3_result_error_nomem(context);
15250 return;
15251 }
15252 if( argc>=1 ){
15253 seed = (unsigned int)sqlite3_value_int(argv[0]);
15254 }else{
15255 seed = 0;
15256 }
15257 p->x = seed | 1;
15258 p->y = seed;
15259 sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
15260 p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
15261 if( p==0 ){
15262 sqlite3_result_error_nomem(context);
15263 return;
15264 }
15265 }
15266 p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
15267 p->y = p->y*1103515245 + 12345;
15268 sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
15269 }
15270
15271 #ifdef _WIN32
15272
15273 #endif
15274 int sqlite3_stmtrand_init(
15275 sqlite3 *db,
15276 char **pzErrMsg,
15277 const sqlite3_api_routines *pApi
15278 ){
15279 int rc = SQLITE_OK;
15280 SQLITE_EXTENSION_INIT2(pApi);
15281 (void)pzErrMsg; /* Unused parameter */
15282 rc = sqlite3_create_function(db, "stmtrand", 1, SQLITE_UTF8, 0,
15283 stmtrandFunc, 0, 0);
15284 if( rc==SQLITE_OK ){
15285 rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
15286 stmtrandFunc, 0, 0);
15287 }
15288 return rc;
15289 }
15290
15291 /************************* End ../ext/misc/stmtrand.c ********************/
15292
15293 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
15294 #define SQLITE_SHELL_HAVE_RECOVER 1
15295 #else
15296 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -15476,10 +15638,19 @@
15638
15639 #define DBDATA_PADDING_BYTES 100
15640
15641 typedef struct DbdataTable DbdataTable;
15642 typedef struct DbdataCursor DbdataCursor;
15643 typedef struct DbdataBuffer DbdataBuffer;
15644
15645 /*
15646 ** Buffer type.
15647 */
15648 struct DbdataBuffer {
15649 u8 *aBuf;
15650 sqlite3_int64 nBuf;
15651 };
15652
15653 /* Cursor object */
15654 struct DbdataCursor {
15655 sqlite3_vtab_cursor base; /* Base class. Must be first */
15656 sqlite3_stmt *pStmt; /* For fetching database pages */
@@ -15492,11 +15663,11 @@
15663 int bOnePage; /* True to stop after one page */
15664 int szDb;
15665 sqlite3_int64 iRowid;
15666
15667 /* Only for the sqlite_dbdata table */
15668 DbdataBuffer rec;
15669 sqlite3_int64 nRec; /* Size of pRec[] in bytes */
15670 sqlite3_int64 nHdr; /* Size of header in bytes */
15671 int iField; /* Current field number */
15672 u8 *pHdrPtr;
15673 u8 *pPtr;
@@ -15536,10 +15707,35 @@
15707 "CREATE TABLE x(" \
15708 " pgno INTEGER," \
15709 " child INTEGER," \
15710 " schema TEXT HIDDEN" \
15711 ")"
15712
15713 /*
15714 ** Ensure the buffer passed as the first argument is at least nMin bytes
15715 ** in size. If an error occurs while attempting to resize the buffer,
15716 ** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
15717 */
15718 static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
15719 if( nMin>pBuf->nBuf ){
15720 sqlite3_int64 nNew = nMin+16384;
15721 u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
15722
15723 if( aNew==0 ) return SQLITE_NOMEM;
15724 pBuf->aBuf = aNew;
15725 pBuf->nBuf = nNew;
15726 }
15727 return SQLITE_OK;
15728 }
15729
15730 /*
15731 ** Release the allocation managed by buffer pBuf.
15732 */
15733 static void dbdataBufferFree(DbdataBuffer *pBuf){
15734 sqlite3_free(pBuf->aBuf);
15735 memset(pBuf, 0, sizeof(*pBuf));
15736 }
15737
15738 /*
15739 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
15740 ** table.
15741 */
@@ -15677,13 +15873,13 @@
15873 pCsr->iPgno = 1;
15874 pCsr->iCell = 0;
15875 pCsr->iField = 0;
15876 pCsr->bOnePage = 0;
15877 sqlite3_free(pCsr->aPage);
15878 dbdataBufferFree(&pCsr->rec);
 
15879 pCsr->aPage = 0;
15880 pCsr->nRec = 0;
15881 }
15882
15883 /*
15884 ** Close an sqlite_dbdata or sqlite_dbptr cursor.
15885 */
@@ -15821,70 +16017,91 @@
16017 u32 enc,
16018 int eType,
16019 u8 *pData,
16020 sqlite3_int64 nData
16021 ){
16022 if( eType>=0 ){
16023 if( dbdataValueBytes(eType)<=nData ){
16024 switch( eType ){
16025 case 0:
16026 case 10:
16027 case 11:
16028 sqlite3_result_null(pCtx);
16029 break;
16030
16031 case 8:
16032 sqlite3_result_int(pCtx, 0);
16033 break;
16034 case 9:
16035 sqlite3_result_int(pCtx, 1);
16036 break;
16037
16038 case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
16039 sqlite3_uint64 v = (signed char)pData[0];
16040 pData++;
16041 switch( eType ){
16042 case 7:
16043 case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
16044 case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
16045 case 4: v = (v<<8) + pData[0]; pData++;
16046 case 3: v = (v<<8) + pData[0]; pData++;
16047 case 2: v = (v<<8) + pData[0]; pData++;
16048 }
16049
16050 if( eType==7 ){
16051 double r;
16052 memcpy(&r, &v, sizeof(r));
16053 sqlite3_result_double(pCtx, r);
16054 }else{
16055 sqlite3_result_int64(pCtx, (sqlite3_int64)v);
16056 }
16057 break;
16058 }
16059
16060 default: {
16061 int n = ((eType-12) / 2);
16062 if( eType % 2 ){
16063 switch( enc ){
16064 #ifndef SQLITE_OMIT_UTF16
16065 case SQLITE_UTF16BE:
16066 sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
16067 break;
16068 case SQLITE_UTF16LE:
16069 sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
16070 break;
16071 #endif
16072 default:
16073 sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
16074 break;
16075 }
16076 }else{
16077 sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
16078 }
16079 }
16080 }
16081 }else{
16082 if( eType==7 ){
16083 sqlite3_result_double(pCtx, 0.0);
16084 }else if( eType<7 ){
16085 sqlite3_result_int(pCtx, 0);
16086 }else if( eType%2 ){
16087 sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
16088 }else{
16089 sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
16090 }
16091 }
16092 }
16093 }
16094
16095 /* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
16096 ** a page-size, it returns the maximum number of cells that may be present
16097 ** on the page. */
16098 #define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
16099
16100 /* Maximum number of fields that may appear in a single record. This is
16101 ** the "hard-limit", according to comments in sqliteLimit.h. */
16102 #define DBDATA_MX_FIELD 32676
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16103
16104 /*
16105 ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
16106 */
16107 static int dbdataNext(sqlite3_vtab_cursor *pCursor){
@@ -15910,10 +16127,13 @@
16127 }
16128
16129 assert( iOff+3+2<=pCsr->nPage );
16130 pCsr->iCell = pTab->bPtr ? -2 : 0;
16131 pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
16132 if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
16133 pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
16134 }
16135 }
16136
16137 if( pTab->bPtr ){
16138 if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
16139 pCsr->iCell = pCsr->nCell;
@@ -15927,11 +16147,12 @@
16147 }else{
16148 return SQLITE_OK;
16149 }
16150 }else{
16151 /* If there is no record loaded, load it now. */
16152 assert( pCsr->rec.aBuf!=0 || pCsr->nRec==0 );
16153 if( pCsr->nRec==0 ){
16154 int bHasRowid = 0;
16155 int nPointer = 0;
16156 sqlite3_int64 nPayload = 0;
16157 sqlite3_int64 nHdr = 0;
16158 int iHdr;
@@ -15954,27 +16175,28 @@
16175 }
16176
16177 if( pCsr->iCell>=pCsr->nCell ){
16178 bNextPage = 1;
16179 }else{
16180 int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
16181
16182 if( iCellPtr>pCsr->nPage ){
 
16183 bNextPage = 1;
16184 }else{
16185 iOff = get_uint16(&pCsr->aPage[iCellPtr]);
16186 }
16187
16188 /* For an interior node cell, skip past the child-page number */
16189 iOff += nPointer;
16190
16191 /* Load the "byte of payload including overflow" field */
16192 if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
16193 bNextPage = 1;
16194 }else{
16195 iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
16196 if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
16197 if( nPayload==0 ) nPayload = 1;
16198 }
16199
16200 /* If this is a leaf intkey cell, load the rowid */
16201 if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
16202 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
@@ -16005,17 +16227,16 @@
16227 }else{
16228
16229 /* Allocate space for payload. And a bit more to catch small buffer
16230 ** overruns caused by attempting to read a varint or similar from
16231 ** near the end of a corrupt record. */
16232 rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
16233 if( rc!=SQLITE_OK ) return rc;
16234 assert( nPayload!=0 );
 
16235
16236 /* Load the nLocal bytes of payload */
16237 memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
16238 iOff += nLocal;
16239
16240 /* Load content from overflow pages */
16241 if( nPayload>nLocal ){
16242 sqlite3_int64 nRem = nPayload - nLocal;
@@ -16029,61 +16250,64 @@
16250 if( rc!=SQLITE_OK ) return rc;
16251 if( aOvfl==0 ) break;
16252
16253 nCopy = U-4;
16254 if( nCopy>nRem ) nCopy = nRem;
16255 memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
16256 nRem -= nCopy;
16257
16258 pgnoOvfl = get_uint32(aOvfl);
16259 sqlite3_free(aOvfl);
16260 }
16261 nPayload -= nRem;
16262 }
16263 memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
16264 pCsr->nRec = nPayload;
16265
16266 iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
16267 if( nHdr>nPayload ) nHdr = 0;
16268 pCsr->nHdr = nHdr;
16269 pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
16270 pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
16271 pCsr->iField = (bHasRowid ? -1 : 0);
16272 }
16273 }
16274 }else{
16275 pCsr->iField++;
16276 if( pCsr->iField>0 ){
16277 sqlite3_int64 iType;
16278 if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
16279 || pCsr->iField>=DBDATA_MX_FIELD
16280 ){
16281 bNextPage = 1;
16282 }else{
16283 int szField = 0;
16284 pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
16285 szField = dbdataValueBytes(iType);
16286 if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
16287 pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
16288 }else{
16289 pCsr->pPtr += szField;
16290 }
16291 }
16292 }
16293 }
16294
16295 if( bNextPage ){
16296 sqlite3_free(pCsr->aPage);
 
16297 pCsr->aPage = 0;
16298 pCsr->nRec = 0;
16299 if( pCsr->bOnePage ) return SQLITE_OK;
16300 pCsr->iPgno++;
16301 }else{
16302 if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
16303 return SQLITE_OK;
16304 }
16305
16306 /* Advance to the next cell. The next iteration of the loop will load
16307 ** the record and so on. */
16308 pCsr->nRec = 0;
 
16309 pCsr->iCell++;
16310 }
16311 }
16312 }
16313
@@ -16269,16 +16493,16 @@
16493 sqlite3_result_int(ctx, pCsr->iField);
16494 break;
16495 case DBDATA_COLUMN_VALUE: {
16496 if( pCsr->iField<0 ){
16497 sqlite3_result_int64(ctx, pCsr->iIntkey);
16498 }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
16499 sqlite3_int64 iType;
16500 dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
16501 dbdataValue(
16502 ctx, pCsr->enc, iType, pCsr->pPtr,
16503 &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
16504 );
16505 }
16506 break;
16507 }
16508 }
@@ -17537,11 +17761,11 @@
17761 if( rc==SQLITE_OK ){
17762 recoverSqlCallback(p, zSql);
17763 if( bTable && !bVirtual ){
17764 if( SQLITE_ROW==sqlite3_step(pTblname) ){
17765 const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
17766 if( zTbl ) recoverAddTable(p, zTbl, iRoot);
17767 }
17768 recoverReset(p, pTblname);
17769 }
17770 }else if( rc!=SQLITE_ERROR ){
17771 recoverDbError(p, p->dbOut);
@@ -20403,11 +20627,11 @@
20627 }
20628 case MODE_ScanExp:
20629 case MODE_Explain: {
20630 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
20631 static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 };
20632 static const int aScanExpWidth[] = {4, 15, 6, 13, 4, 4, 4, 13, 2, 13};
20633 static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 };
20634
20635 const int *aWidth = aExplainWidth;
20636 const int *aMap = aExplainMap;
20637 int nWidth = ArraySize(aExplainWidth);
@@ -21413,11 +21637,17 @@
21637 UNUSED_PARAMETER(pArg);
21638 #else
21639 if( pArg->scanstatsOn==3 ){
21640 const char *zSql =
21641 " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
21642 " format('% 6s (%.2f%%)',"
21643 " CASE WHEN ncycle<100_000 THEN ncycle || ' '"
21644 " WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'"
21645 " WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'"
21646 " ELSE (ncycle/1000_000_000) || 'G' END,"
21647 " ncycle*100.0/(sum(ncycle) OVER ())"
21648 " ) AS cycles"
21649 " FROM bytecode(?)";
21650
21651 int rc = SQLITE_OK;
21652 sqlite3_stmt *pStmt = 0;
21653 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
@@ -22236,10 +22466,11 @@
22466 }
22467 pExplain = pStmt;
22468 sqlite3_reset(pExplain);
22469 rc = sqlite3_stmt_explain(pExplain, 2);
22470 if( rc==SQLITE_OK ){
22471 bind_prepared_stmt(pArg, pExplain);
22472 while( sqlite3_step(pExplain)==SQLITE_ROW ){
22473 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
22474 int iEqpId = sqlite3_column_int(pExplain, 0);
22475 int iParentId = sqlite3_column_int(pExplain, 1);
22476 if( zEQPLine==0 ) zEQPLine = "";
@@ -22253,10 +22484,11 @@
22484 sqlite3_reset(pExplain);
22485 rc = sqlite3_stmt_explain(pExplain, 1);
22486 if( rc==SQLITE_OK ){
22487 pArg->cMode = MODE_Explain;
22488 assert( sqlite3_stmt_isexplain(pExplain)==1 );
22489 bind_prepared_stmt(pArg, pExplain);
22490 explain_data_prepare(pArg, pExplain);
22491 exec_prepared_stmt(pArg, pExplain);
22492 explain_data_delete(pArg);
22493 }
22494 }
@@ -23347,10 +23579,11 @@
23579 #ifndef SQLITE_OMIT_LOAD_EXTENSION
23580 sqlite3_enable_load_extension(p->db, 1);
23581 #endif
23582 sqlite3_shathree_init(p->db, 0, 0);
23583 sqlite3_uint_init(p->db, 0, 0);
23584 sqlite3_stmtrand_init(p->db, 0, 0);
23585 sqlite3_decimal_init(p->db, 0, 0);
23586 sqlite3_base64_init(p->db, 0, 0);
23587 sqlite3_base85_init(p->db, 0, 0);
23588 sqlite3_regexp_init(p->db, 0, 0);
23589 sqlite3_ieee_init(p->db, 0, 0);
@@ -23500,19 +23733,22 @@
23733 return rl_completion_matches(zText, readline_completion_generator);
23734 }
23735
23736 #elif HAVE_LINENOISE
23737 /*
23738 ** Linenoise completion callback. Note that the 3rd argument is from
23739 ** the "msteveb" version of linenoise, not the "antirez" version.
23740 */
23741 static void linenoise_completion(const char *zLine, linenoiseCompletions *lc,
23742 void *pUserData){
23743 i64 nLine = strlen(zLine);
23744 i64 i, iStart;
23745 sqlite3_stmt *pStmt = 0;
23746 char *zSql;
23747 char zBuf[1000];
23748
23749 UNUSED_PARAMETER(pUserData);
23750 if( nLine>(i64)sizeof(zBuf)-30 ) return;
23751 if( zLine[0]=='.' || zLine[0]=='#') return;
23752 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
23753 if( i==nLine-1 ) return;
23754 iStart = i+1;
@@ -25923,30 +26159,37 @@
26159 int iId; /* ID that triggers a simulated fault. -1 means "any" */
26160 int iErr; /* The error code to return on a fault */
26161 int iCnt; /* Trigger the fault only if iCnt is already zero */
26162 int iInterval; /* Reset iCnt to this value after each fault */
26163 int eVerbose; /* When to print output */
26164 int nHit; /* Number of hits seen so far */
26165 int nRepeat; /* Turn off after this many hits. 0 for never */
26166 int nSkip; /* Skip this many before first fault */
26167 } faultsim_state = {-1, 0, 0, 0, 0, 0, 0, 0};
26168
26169 /*
26170 ** This is the fault-sim callback
26171 */
26172 static int faultsim_callback(int iArg){
26173 if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
26174 return SQLITE_OK;
26175 }
26176 if( faultsim_state.iCnt ){
26177 if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--;
26178 if( faultsim_state.eVerbose>=2 ){
26179 oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
26180 }
26181 return SQLITE_OK;
26182 }
26183 if( faultsim_state.eVerbose>=1 ){
26184 oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
26185 }
26186 faultsim_state.iCnt = faultsim_state.iInterval;
26187 faultsim_state.nHit++;
26188 if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){
26189 faultsim_state.iCnt = -1;
26190 }
26191 return faultsim_state.iErr;
26192 }
26193
26194 /*
26195 ** If an input line begins with "." then invoke this routine to
@@ -26927,10 +27170,11 @@
27170 assert(dbCols==0);
27171 if( zColDefs==0 ){
27172 eputf("%s: empty file\n", sCtx.zFile);
27173 import_cleanup(&sCtx);
27174 rc = 1;
27175 sqlite3_free(zCreate);
27176 goto meta_command_exit;
27177 }
27178 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
27179 if( zCreate==0 ){
27180 import_cleanup(&sCtx);
@@ -26953,11 +27197,10 @@
27197 zTable, zSchema);
27198 if( zSql==0 ){
27199 import_cleanup(&sCtx);
27200 shell_out_of_memory();
27201 }
 
27202 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
27203 sqlite3_free(zSql);
27204 zSql = 0;
27205 if( rc ){
27206 if (pStmt) sqlite3_finalize(pStmt);
@@ -26972,28 +27215,34 @@
27215 nCol = 0;
27216 }
27217 sqlite3_finalize(pStmt);
27218 pStmt = 0;
27219 if( nCol==0 ) return 0; /* no columns, no error */
27220
27221 nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */
27222 + (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */
27223 + strlen(zTable)*2 + 2 /* Quoted table name */
27224 + nCol*2; /* Space for ",?" for each column */
27225 zSql = sqlite3_malloc64( nByte );
27226 if( zSql==0 ){
27227 import_cleanup(&sCtx);
27228 shell_out_of_memory();
27229 }
27230 if( zSchema ){
27231 sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
27232 zSchema, zTable);
27233 }else{
27234 sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
27235 }
27236 j = strlen30(zSql);
27237 for(i=1; i<nCol; i++){
27238 zSql[j++] = ',';
27239 zSql[j++] = '?';
27240 }
27241 zSql[j++] = ')';
27242 zSql[j] = 0;
27243 assert( j<nByte );
27244 if( eVerbose>=2 ){
27245 oputf("Insert using: %s\n", zSql);
27246 }
27247 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
27248 sqlite3_free(zSql);
@@ -28872,11 +29121,11 @@
29121 {"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
29122 {"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
29123 #ifdef YYCOVERAGE
29124 {"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
29125 #endif
29126 {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET " },
29127 {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
29128 {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
29129 {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
29130 {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
29131 {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
@@ -29104,21 +29353,27 @@
29353 const char *z = azArg[kk];
29354 if( z[0]=='-' && z[1]=='-' ) z++;
29355 if( cli_strcmp(z,"off")==0 ){
29356 sqlite3_test_control(testctrl, 0);
29357 }else if( cli_strcmp(z,"on")==0 ){
29358 faultsim_state.iCnt = faultsim_state.nSkip;
29359 if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
29360 faultsim_state.nHit = 0;
29361 sqlite3_test_control(testctrl, faultsim_callback);
29362 }else if( cli_strcmp(z,"reset")==0 ){
29363 faultsim_state.iCnt = faultsim_state.nSkip;
29364 faultsim_state.nHit = 0;
29365 sqlite3_test_control(testctrl, faultsim_callback);
29366 }else if( cli_strcmp(z,"status")==0 ){
29367 oputf("faultsim.iId: %d\n", faultsim_state.iId);
29368 oputf("faultsim.iErr: %d\n", faultsim_state.iErr);
29369 oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt);
29370 oputf("faultsim.nHit: %d\n", faultsim_state.nHit);
29371 oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
29372 oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose);
29373 oputf("faultsim.nRepeat: %d\n", faultsim_state.nRepeat);
29374 oputf("faultsim.nSkip: %d\n", faultsim_state.nSkip);
29375 }else if( cli_strcmp(z,"-v")==0 ){
29376 if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
29377 }else if( cli_strcmp(z,"-q")==0 ){
29378 if( faultsim_state.eVerbose>0 ) faultsim_state.eVerbose--;
29379 }else if( cli_strcmp(z,"-id")==0 && kk+1<nArg ){
@@ -29125,10 +29380,14 @@
29380 faultsim_state.iId = atoi(azArg[++kk]);
29381 }else if( cli_strcmp(z,"-errcode")==0 && kk+1<nArg ){
29382 faultsim_state.iErr = atoi(azArg[++kk]);
29383 }else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
29384 faultsim_state.iInterval = atoi(azArg[++kk]);
29385 }else if( cli_strcmp(z,"-repeat")==0 && kk+1<nArg ){
29386 faultsim_state.nRepeat = atoi(azArg[++kk]);
29387 }else if( cli_strcmp(z,"-skip")==0 && kk+1<nArg ){
29388 faultsim_state.nSkip = atoi(azArg[++kk]);
29389 }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
29390 bShowHelp = 1;
29391 }else{
29392 eputf("Unrecognized fault_install argument: \"%s\"\n",
29393 azArg[kk]);
@@ -29148,10 +29407,12 @@
29407 " -v Increase verbosity\n"
29408 " -q Decrease verbosity\n"
29409 " --errcode N When triggered, return N as error code\n"
29410 " --id ID Trigger only for the ID specified\n"
29411 " --interval N Trigger only after every N-th call\n"
29412 " --repeat N Turn off after N hits. 0 means never\n"
29413 " --skip N Skip the first N encounters\n"
29414 );
29415 }
29416 break;
29417 }
29418 }
@@ -29920,31 +30181,33 @@
30181 }
30182
30183 /*
30184 ** On non-Windows platforms, look for $XDG_CONFIG_HOME.
30185 ** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
30186 ** the path to it. If there is no $(XDG_CONFIG_HOME) then
30187 ** look for $(HOME)/.config/sqlite3/sqliterc and if found
30188 ** return that. If none of these are found, return 0.
30189 **
30190 ** The string returned is obtained from sqlite3_malloc() and
30191 ** should be freed by the caller.
30192 */
30193 static char *find_xdg_config(void){
30194 #if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
30195 || defined(__RTP__) || defined(_WRS_KERNEL)
30196 return 0;
30197 #else
30198 char *zConfig = 0;
 
30199 const char *zXdgHome;
30200
 
 
 
 
30201 zXdgHome = getenv("XDG_CONFIG_HOME");
30202 if( zXdgHome==0 ){
30203 const char *zHome = getenv("HOME");
30204 if( zHome==0 ) return 0;
30205 zConfig = sqlite3_mprintf("%s/.config/sqlite3/sqliterc", zHome);
30206 }else{
30207 zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
30208 }
 
30209 shell_check_oom(zConfig);
30210 if( access(zConfig,0)!=0 ){
30211 sqlite3_free(zConfig);
30212 zConfig = 0;
30213 }
@@ -29968,11 +30231,11 @@
30231 char *zBuf = 0;
30232 FILE *inSaved = p->in;
30233 int savedLineno = p->lineno;
30234
30235 if( sqliterc == NULL ){
30236 sqliterc = zBuf = find_xdg_config();
30237 }
30238 if( sqliterc == NULL ){
30239 home_dir = find_home_dir(0);
30240 if( home_dir==0 ){
30241 eputz("-- warning: cannot find home directory;"
@@ -30704,12 +30967,12 @@
30967 */
30968 for(i=0; i<nCmd; i++){
30969 if( azCmd[i][0]=='.' ){
30970 rc = do_meta_command(azCmd[i], &data);
30971 if( rc ){
30972 if( rc==2 ) rc = 0;
30973 goto shell_main_exit;
30974 }
30975 }else{
30976 open_db(&data, 0);
30977 echo_group_input(&data, azCmd[i]);
30978 rc = shell_exec(&data, azCmd[i], &zErrMsg);
@@ -30718,12 +30981,12 @@
30981 eputf("Error: %s\n", zErrMsg);
30982 }else{
30983 eputf("Error: unable to process SQL: %s\n", azCmd[i]);
30984 }
30985 sqlite3_free(zErrMsg);
30986 if( rc==0 ) rc = 1;
30987 goto shell_main_exit;
30988 }
30989 }
30990 }
30991 }else{
30992 /* Run commands received from standard input
@@ -30757,11 +31020,11 @@
31020 }
31021 if( zHistory ){ shell_read_history(zHistory); }
31022 #if HAVE_READLINE || HAVE_EDITLINE
31023 rl_attempted_completion_function = readline_completion;
31024 #elif HAVE_LINENOISE
31025 linenoiseSetCompletionCallback(linenoise_completion, NULL);
31026 #endif
31027 data.in = 0;
31028 rc = process_input(&data);
31029 if( zHistory ){
31030 shell_stifle_history(2000);
@@ -30779,10 +31042,11 @@
31042 #ifndef SQLITE_OMIT_VIRTUALTABLE
31043 if( data.expert.pExpert ){
31044 expertFinish(&data, 1, 0);
31045 }
31046 #endif
31047 shell_main_exit:
31048 free(azCmd);
31049 set_table_name(&data, 0);
31050 if( data.db ){
31051 session_close_all(&data, -1);
31052 close_db(data.db);
@@ -30811,11 +31075,13 @@
31075 if( sqlite3_memory_used()>mem_main_enter ){
31076 eputf("Memory leaked: %u bytes\n",
31077 (unsigned int)(sqlite3_memory_used()-mem_main_enter));
31078 }
31079 #endif
31080 #else /* SQLITE_SHELL_FIDDLE... */
31081 shell_main_exit:
31082 #endif
31083 return rc;
31084 }
31085
31086
31087 #ifdef SQLITE_SHELL_FIDDLE
31088
+2876 -1845
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.46.0. By combining all the individual C code files into this
3
+** version 3.47.0. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** a49296de0061931badaf3db6b965131a78b1.
21
+** baa83b460c677c210c7fa3f20314d7e05f30.
2222
*/
2323
#define SQLITE_CORE 1
2424
#define SQLITE_AMALGAMATION 1
2525
#ifndef SQLITE_PRIVATE
2626
# define SQLITE_PRIVATE static
@@ -254,14 +254,17 @@
254254
#endif
255255
256256
/*
257257
** Macro to disable warnings about missing "break" at the end of a "case".
258258
*/
259
-#if GCC_VERSION>=7000000
260
-# define deliberate_fall_through __attribute__((fallthrough));
261
-#else
262
-# define deliberate_fall_through
259
+#if defined(__has_attribute)
260
+# if __has_attribute(fallthrough)
261
+# define deliberate_fall_through __attribute__((fallthrough));
262
+# endif
263
+#endif
264
+#if !defined(deliberate_fall_through)
265
+# define deliberate_fall_through
263266
#endif
264267
265268
/*
266269
** For MinGW, check to see if we can include the header file containing its
267270
** version information, among other things. Normally, this internal MinGW
@@ -457,13 +460,13 @@
457460
**
458461
** See also: [sqlite3_libversion()],
459462
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
460463
** [sqlite_version()] and [sqlite_source_id()].
461464
*/
462
-#define SQLITE_VERSION "3.46.0"
463
-#define SQLITE_VERSION_NUMBER 3046000
464
-#define SQLITE_SOURCE_ID "2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3"
465
+#define SQLITE_VERSION "3.47.0"
466
+#define SQLITE_VERSION_NUMBER 3047000
467
+#define SQLITE_SOURCE_ID "2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38"
465468
466469
/*
467470
** CAPI3REF: Run-Time Library Version Numbers
468471
** KEYWORDS: sqlite3_version sqlite3_sourceid
469472
**
@@ -1083,12 +1086,12 @@
10831086
** xUnlock() downgrades the database file lock to either SHARED or NONE.
10841087
** If the lock is already at or below the requested lock state, then the call
10851088
** to xUnlock() is a no-op.
10861089
** The xCheckReservedLock() method checks whether any database connection,
10871090
** either in this process or in some other process, is holding a RESERVED,
1088
-** PENDING, or EXCLUSIVE lock on the file. It returns true
1089
-** if such a lock exists and false otherwise.
1091
+** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
1092
+** pointer parameter, true if such a lock exists and false otherwise.
10901093
**
10911094
** The xFileControl() method is a generic interface that allows custom
10921095
** VFS implementations to directly control an open file using the
10931096
** [sqlite3_file_control()] interface. The second "op" argument is an
10941097
** integer opcode. The third argument is a generic pointer intended to
@@ -3881,12 +3884,12 @@
38813884
** the default shared cache setting provided by
38823885
** [sqlite3_enable_shared_cache()].)^
38833886
**
38843887
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
38853888
** <dd>The database connection comes up in "extended result code mode".
3886
-** In other words, the database behaves has if
3887
-** [sqlite3_extended_result_codes(db,1)] where called on the database
3889
+** In other words, the database behaves as if
3890
+** [sqlite3_extended_result_codes(db,1)] were called on the database
38883891
** connection as soon as the connection is created. In addition to setting
38893892
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
38903893
** to return an extended result code.</dd>
38913894
**
38923895
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -7197,10 +7200,16 @@
71977200
** is not invoked when conflicting rows are deleted because of an
71987201
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
71997202
** invoked when rows are deleted using the [truncate optimization].
72007203
** The exceptions defined in this paragraph might change in a future
72017204
** release of SQLite.
7205
+**
7206
+** Whether the update hook is invoked before or after the
7207
+** corresponding change is currently unspecified and may differ
7208
+** depending on the type of change. Do not rely on the order of the
7209
+** hook call with regards to the final result of the operation which
7210
+** triggers the hook.
72027211
**
72037212
** The update hook implementation must not do anything that will modify
72047213
** the database connection that invoked the update hook. Any actions
72057214
** to modify the database connection must be deferred until after the
72067215
** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8668,11 +8677,11 @@
86688677
** by enclosing in double-quotes) so as not to confuse the parser.
86698678
**
86708679
** The sqlite3_keyword_count() interface returns the number of distinct
86718680
** keywords understood by SQLite.
86728681
**
8673
-** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
8682
+** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
86748683
** makes *Z point to that keyword expressed as UTF8 and writes the number
86758684
** of bytes in the keyword into *L. The string that *Z points to is not
86768685
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
86778686
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
86788687
** or L are NULL or invalid pointers then calls to
@@ -10247,27 +10256,48 @@
1024710256
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
1024810257
** is doing a GROUP BY.
1024910258
** <li value="2"><p>
1025010259
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
1025110260
** that the query planner does not need the rows returned in any particular
10252
-** order, as long as rows with the same values in all "aOrderBy" columns
10253
-** are adjacent.)^ ^(Furthermore, only a single row for each particular
10254
-** combination of values in the columns identified by the "aOrderBy" field
10255
-** needs to be returned.)^ ^It is always ok for two or more rows with the same
10256
-** values in all "aOrderBy" columns to be returned, as long as all such rows
10257
-** are adjacent. ^The virtual table may, if it chooses, omit extra rows
10258
-** that have the same value for all columns identified by "aOrderBy".
10259
-** ^However omitting the extra rows is optional.
10261
+** order, as long as rows with the same values in all columns identified
10262
+** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
10263
+** contain the same values for all columns identified by "colUsed", all but
10264
+** one such row may optionally be omitted from the result.)^
10265
+** The virtual table is not required to omit rows that are duplicates
10266
+** over the "colUsed" columns, but if the virtual table can do that without
10267
+** too much extra effort, it could potentially help the query to run faster.
1026010268
** This mode is used for a DISTINCT query.
1026110269
** <li value="3"><p>
10262
-** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
10263
-** that the query planner needs only distinct rows but it does need the
10264
-** rows to be sorted.)^ ^The virtual table implementation is free to omit
10265
-** rows that are identical in all aOrderBy columns, if it wants to, but
10266
-** it is not required to omit any rows. This mode is used for queries
10270
+** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
10271
+** virtual table must return rows in the order defined by "aOrderBy" as
10272
+** if the sqlite3_vtab_distinct() interface had returned 0. However if
10273
+** two or more rows in the result have the same values for all columns
10274
+** identified by "colUsed", then all but one such row may optionally be
10275
+** omitted.)^ Like when the return value is 2, the virtual table
10276
+** is not required to omit rows that are duplicates over the "colUsed"
10277
+** columns, but if the virtual table can do that without
10278
+** too much extra effort, it could potentially help the query to run faster.
10279
+** This mode is used for queries
1026710280
** that have both DISTINCT and ORDER BY clauses.
1026810281
** </ol>
10282
+**
10283
+** <p>The following table summarizes the conditions under which the
10284
+** virtual table is allowed to set the "orderByConsumed" flag based on
10285
+** the value returned by sqlite3_vtab_distinct(). This table is a
10286
+** restatement of the previous four paragraphs:
10287
+**
10288
+** <table border=1 cellspacing=0 cellpadding=10 width="90%">
10289
+** <tr>
10290
+** <td valign="top">sqlite3_vtab_distinct() return value
10291
+** <td valign="top">Rows are returned in aOrderBy order
10292
+** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
10293
+** <td valign="top">Duplicates over all colUsed columns may be omitted
10294
+** <tr><td>0<td>yes<td>yes<td>no
10295
+** <tr><td>1<td>no<td>yes<td>no
10296
+** <tr><td>2<td>no<td>yes<td>yes
10297
+** <tr><td>3<td>yes<td>yes<td>yes
10298
+** </table>
1026910299
**
1027010300
** ^For the purposes of comparing virtual table output values to see if the
1027110301
** values are same value for sorting purposes, two NULL values are considered
1027210302
** to be the same. In other words, the comparison operator is "IS"
1027310303
** (or "IS NOT DISTINCT FROM") and not "==".
@@ -11116,12 +11146,10 @@
1111611146
#endif
1111711147
1111811148
#if defined(__wasi__)
1111911149
# undef SQLITE_WASI
1112011150
# define SQLITE_WASI 1
11121
-# undef SQLITE_OMIT_WAL
11122
-# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
1112311151
# ifndef SQLITE_OMIT_LOAD_EXTENSION
1112411152
# define SQLITE_OMIT_LOAD_EXTENSION
1112511153
# endif
1112611154
# ifndef SQLITE_THREADSAFE
1112711155
# define SQLITE_THREADSAFE 0
@@ -12308,10 +12336,34 @@
1230812336
**
1230912337
** In all cases, if an error occurs the state of the final contents of the
1231012338
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
1231112339
*/
1231212340
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
12341
+
12342
+/*
12343
+** CAPI3REF: Add A Single Change To A Changegroup
12344
+** METHOD: sqlite3_changegroup
12345
+**
12346
+** This function adds the single change currently indicated by the iterator
12347
+** passed as the second argument to the changegroup object. The rules for
12348
+** adding the change are just as described for [sqlite3changegroup_add()].
12349
+**
12350
+** If the change is successfully added to the changegroup, SQLITE_OK is
12351
+** returned. Otherwise, an SQLite error code is returned.
12352
+**
12353
+** The iterator must point to a valid entry when this function is called.
12354
+** If it does not, SQLITE_ERROR is returned and no change is added to the
12355
+** changegroup. Additionally, the iterator must not have been opened with
12356
+** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
12357
+** returned.
12358
+*/
12359
+SQLITE_API int sqlite3changegroup_add_change(
12360
+ sqlite3_changegroup*,
12361
+ sqlite3_changeset_iter*
12362
+);
12363
+
12364
+
1231312365
1231412366
/*
1231512367
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
1231612368
** METHOD: sqlite3_changegroup
1231712369
**
@@ -13113,12 +13165,12 @@
1311313165
1311413166
/*
1311513167
** EXTENSION API FUNCTIONS
1311613168
**
1311713169
** xUserData(pFts):
13118
-** Return a copy of the context pointer the extension function was
13119
-** registered with.
13170
+** Return a copy of the pUserData pointer passed to the xCreateFunction()
13171
+** API when the extension function was registered.
1312013172
**
1312113173
** xColumnTotalSize(pFts, iCol, pnToken):
1312213174
** If parameter iCol is less than zero, set output variable *pnToken
1312313175
** to the total number of tokens in the FTS5 table. Or, if iCol is
1312413176
** non-negative but less than the number of columns in the table, return
@@ -13295,10 +13347,14 @@
1329513347
** This API can be quite slow if used with an FTS5 table created with the
1329613348
** "detail=none" or "detail=column" option. If the FTS5 table is created
1329713349
** with either "detail=none" or "detail=column" and "content=" option
1329813350
** (i.e. if it is a contentless table), then this API always iterates
1329913351
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
13352
+**
13353
+** In all cases, matches are visited in (column ASC, offset ASC) order.
13354
+** i.e. all those in column 0, sorted by offset, followed by those in
13355
+** column 1, etc.
1330013356
**
1330113357
** xPhraseNext()
1330213358
** See xPhraseFirst above.
1330313359
**
1330413360
** xPhraseFirstColumn()
@@ -14479,139 +14535,139 @@
1447914535
#define TK_EACH 41
1448014536
#define TK_FAIL 42
1448114537
#define TK_OR 43
1448214538
#define TK_AND 44
1448314539
#define TK_IS 45
14484
-#define TK_MATCH 46
14485
-#define TK_LIKE_KW 47
14486
-#define TK_BETWEEN 48
14487
-#define TK_IN 49
14488
-#define TK_ISNULL 50
14489
-#define TK_NOTNULL 51
14490
-#define TK_NE 52
14491
-#define TK_EQ 53
14492
-#define TK_GT 54
14493
-#define TK_LE 55
14494
-#define TK_LT 56
14495
-#define TK_GE 57
14496
-#define TK_ESCAPE 58
14497
-#define TK_ID 59
14498
-#define TK_COLUMNKW 60
14499
-#define TK_DO 61
14500
-#define TK_FOR 62
14501
-#define TK_IGNORE 63
14502
-#define TK_INITIALLY 64
14503
-#define TK_INSTEAD 65
14504
-#define TK_NO 66
14505
-#define TK_KEY 67
14506
-#define TK_OF 68
14507
-#define TK_OFFSET 69
14508
-#define TK_PRAGMA 70
14509
-#define TK_RAISE 71
14510
-#define TK_RECURSIVE 72
14511
-#define TK_REPLACE 73
14512
-#define TK_RESTRICT 74
14513
-#define TK_ROW 75
14514
-#define TK_ROWS 76
14515
-#define TK_TRIGGER 77
14516
-#define TK_VACUUM 78
14517
-#define TK_VIEW 79
14518
-#define TK_VIRTUAL 80
14519
-#define TK_WITH 81
14520
-#define TK_NULLS 82
14521
-#define TK_FIRST 83
14522
-#define TK_LAST 84
14523
-#define TK_CURRENT 85
14524
-#define TK_FOLLOWING 86
14525
-#define TK_PARTITION 87
14526
-#define TK_PRECEDING 88
14527
-#define TK_RANGE 89
14528
-#define TK_UNBOUNDED 90
14529
-#define TK_EXCLUDE 91
14530
-#define TK_GROUPS 92
14531
-#define TK_OTHERS 93
14532
-#define TK_TIES 94
14533
-#define TK_GENERATED 95
14534
-#define TK_ALWAYS 96
14535
-#define TK_MATERIALIZED 97
14536
-#define TK_REINDEX 98
14537
-#define TK_RENAME 99
14538
-#define TK_CTIME_KW 100
14539
-#define TK_ANY 101
14540
-#define TK_BITAND 102
14541
-#define TK_BITOR 103
14542
-#define TK_LSHIFT 104
14543
-#define TK_RSHIFT 105
14544
-#define TK_PLUS 106
14545
-#define TK_MINUS 107
14546
-#define TK_STAR 108
14547
-#define TK_SLASH 109
14548
-#define TK_REM 110
14549
-#define TK_CONCAT 111
14550
-#define TK_PTR 112
14551
-#define TK_COLLATE 113
14552
-#define TK_BITNOT 114
14553
-#define TK_ON 115
14554
-#define TK_INDEXED 116
14555
-#define TK_STRING 117
14556
-#define TK_JOIN_KW 118
14557
-#define TK_CONSTRAINT 119
14558
-#define TK_DEFAULT 120
14559
-#define TK_NULL 121
14560
-#define TK_PRIMARY 122
14561
-#define TK_UNIQUE 123
14562
-#define TK_CHECK 124
14563
-#define TK_REFERENCES 125
14564
-#define TK_AUTOINCR 126
14565
-#define TK_INSERT 127
14566
-#define TK_DELETE 128
14567
-#define TK_UPDATE 129
14568
-#define TK_SET 130
14569
-#define TK_DEFERRABLE 131
14570
-#define TK_FOREIGN 132
14571
-#define TK_DROP 133
14572
-#define TK_UNION 134
14573
-#define TK_ALL 135
14574
-#define TK_EXCEPT 136
14575
-#define TK_INTERSECT 137
14576
-#define TK_SELECT 138
14577
-#define TK_VALUES 139
14578
-#define TK_DISTINCT 140
14579
-#define TK_DOT 141
14580
-#define TK_FROM 142
14581
-#define TK_JOIN 143
14582
-#define TK_USING 144
14583
-#define TK_ORDER 145
14584
-#define TK_GROUP 146
14585
-#define TK_HAVING 147
14586
-#define TK_LIMIT 148
14587
-#define TK_WHERE 149
14588
-#define TK_RETURNING 150
14589
-#define TK_INTO 151
14590
-#define TK_NOTHING 152
14591
-#define TK_FLOAT 153
14592
-#define TK_BLOB 154
14593
-#define TK_INTEGER 155
14594
-#define TK_VARIABLE 156
14595
-#define TK_CASE 157
14596
-#define TK_WHEN 158
14597
-#define TK_THEN 159
14598
-#define TK_ELSE 160
14599
-#define TK_INDEX 161
14600
-#define TK_ALTER 162
14601
-#define TK_ADD 163
14602
-#define TK_WINDOW 164
14603
-#define TK_OVER 165
14604
-#define TK_FILTER 166
14605
-#define TK_COLUMN 167
14606
-#define TK_AGG_FUNCTION 168
14607
-#define TK_AGG_COLUMN 169
14608
-#define TK_TRUEFALSE 170
14609
-#define TK_ISNOT 171
14540
+#define TK_ISNOT 46
14541
+#define TK_MATCH 47
14542
+#define TK_LIKE_KW 48
14543
+#define TK_BETWEEN 49
14544
+#define TK_IN 50
14545
+#define TK_ISNULL 51
14546
+#define TK_NOTNULL 52
14547
+#define TK_NE 53
14548
+#define TK_EQ 54
14549
+#define TK_GT 55
14550
+#define TK_LE 56
14551
+#define TK_LT 57
14552
+#define TK_GE 58
14553
+#define TK_ESCAPE 59
14554
+#define TK_ID 60
14555
+#define TK_COLUMNKW 61
14556
+#define TK_DO 62
14557
+#define TK_FOR 63
14558
+#define TK_IGNORE 64
14559
+#define TK_INITIALLY 65
14560
+#define TK_INSTEAD 66
14561
+#define TK_NO 67
14562
+#define TK_KEY 68
14563
+#define TK_OF 69
14564
+#define TK_OFFSET 70
14565
+#define TK_PRAGMA 71
14566
+#define TK_RAISE 72
14567
+#define TK_RECURSIVE 73
14568
+#define TK_REPLACE 74
14569
+#define TK_RESTRICT 75
14570
+#define TK_ROW 76
14571
+#define TK_ROWS 77
14572
+#define TK_TRIGGER 78
14573
+#define TK_VACUUM 79
14574
+#define TK_VIEW 80
14575
+#define TK_VIRTUAL 81
14576
+#define TK_WITH 82
14577
+#define TK_NULLS 83
14578
+#define TK_FIRST 84
14579
+#define TK_LAST 85
14580
+#define TK_CURRENT 86
14581
+#define TK_FOLLOWING 87
14582
+#define TK_PARTITION 88
14583
+#define TK_PRECEDING 89
14584
+#define TK_RANGE 90
14585
+#define TK_UNBOUNDED 91
14586
+#define TK_EXCLUDE 92
14587
+#define TK_GROUPS 93
14588
+#define TK_OTHERS 94
14589
+#define TK_TIES 95
14590
+#define TK_GENERATED 96
14591
+#define TK_ALWAYS 97
14592
+#define TK_MATERIALIZED 98
14593
+#define TK_REINDEX 99
14594
+#define TK_RENAME 100
14595
+#define TK_CTIME_KW 101
14596
+#define TK_ANY 102
14597
+#define TK_BITAND 103
14598
+#define TK_BITOR 104
14599
+#define TK_LSHIFT 105
14600
+#define TK_RSHIFT 106
14601
+#define TK_PLUS 107
14602
+#define TK_MINUS 108
14603
+#define TK_STAR 109
14604
+#define TK_SLASH 110
14605
+#define TK_REM 111
14606
+#define TK_CONCAT 112
14607
+#define TK_PTR 113
14608
+#define TK_COLLATE 114
14609
+#define TK_BITNOT 115
14610
+#define TK_ON 116
14611
+#define TK_INDEXED 117
14612
+#define TK_STRING 118
14613
+#define TK_JOIN_KW 119
14614
+#define TK_CONSTRAINT 120
14615
+#define TK_DEFAULT 121
14616
+#define TK_NULL 122
14617
+#define TK_PRIMARY 123
14618
+#define TK_UNIQUE 124
14619
+#define TK_CHECK 125
14620
+#define TK_REFERENCES 126
14621
+#define TK_AUTOINCR 127
14622
+#define TK_INSERT 128
14623
+#define TK_DELETE 129
14624
+#define TK_UPDATE 130
14625
+#define TK_SET 131
14626
+#define TK_DEFERRABLE 132
14627
+#define TK_FOREIGN 133
14628
+#define TK_DROP 134
14629
+#define TK_UNION 135
14630
+#define TK_ALL 136
14631
+#define TK_EXCEPT 137
14632
+#define TK_INTERSECT 138
14633
+#define TK_SELECT 139
14634
+#define TK_VALUES 140
14635
+#define TK_DISTINCT 141
14636
+#define TK_DOT 142
14637
+#define TK_FROM 143
14638
+#define TK_JOIN 144
14639
+#define TK_USING 145
14640
+#define TK_ORDER 146
14641
+#define TK_GROUP 147
14642
+#define TK_HAVING 148
14643
+#define TK_LIMIT 149
14644
+#define TK_WHERE 150
14645
+#define TK_RETURNING 151
14646
+#define TK_INTO 152
14647
+#define TK_NOTHING 153
14648
+#define TK_FLOAT 154
14649
+#define TK_BLOB 155
14650
+#define TK_INTEGER 156
14651
+#define TK_VARIABLE 157
14652
+#define TK_CASE 158
14653
+#define TK_WHEN 159
14654
+#define TK_THEN 160
14655
+#define TK_ELSE 161
14656
+#define TK_INDEX 162
14657
+#define TK_ALTER 163
14658
+#define TK_ADD 164
14659
+#define TK_WINDOW 165
14660
+#define TK_OVER 166
14661
+#define TK_FILTER 167
14662
+#define TK_COLUMN 168
14663
+#define TK_AGG_FUNCTION 169
14664
+#define TK_AGG_COLUMN 170
14665
+#define TK_TRUEFALSE 171
1461014666
#define TK_FUNCTION 172
14611
-#define TK_UMINUS 173
14612
-#define TK_UPLUS 174
14667
+#define TK_UPLUS 173
14668
+#define TK_UMINUS 174
1461314669
#define TK_TRUTH 175
1461414670
#define TK_REGISTER 176
1461514671
#define TK_VECTOR 177
1461614672
#define TK_SELECT_COLUMN 178
1461714673
#define TK_IF_NULL_ROW 179
@@ -15148,11 +15204,11 @@
1514815204
** 0x00000008 WhereLoop inserts
1514915205
**
1515015206
** 0x00000010 Display sqlite3_index_info xBestIndex calls
1515115207
** 0x00000020 Range an equality scan metrics
1515215208
** 0x00000040 IN operator decisions
15153
-** 0x00000080 WhereLoop cost adjustements
15209
+** 0x00000080 WhereLoop cost adjustments
1515415210
** 0x00000100
1515515211
** 0x00000200 Covering index decisions
1515615212
** 0x00000400 OR optimization
1515715213
** 0x00000800 Index scanner
1515815214
** 0x00001000 More details associated with code generation
@@ -16610,20 +16666,20 @@
1661016666
#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
1661116667
#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
1661216668
#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
1661316669
#define OP_Program 48 /* jump0 */
1661416670
#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
16615
-#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
16616
-#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
16617
-#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
16618
-#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
16619
-#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
16620
-#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
16621
-#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
16622
-#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
16623
-#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
16624
-#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
16671
+#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
16672
+#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
16673
+#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
16674
+#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
16675
+#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
16676
+#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
16677
+#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
16678
+#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
16679
+#define OP_Ge 58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
16680
+#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
1662516681
#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
1662616682
#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
1662716683
#define OP_IncrVacuum 62 /* jump */
1662816684
#define OP_VNext 63 /* jump */
1662916685
#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
@@ -16662,27 +16718,27 @@
1666216718
#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
1666316719
#define OP_Count 98 /* synopsis: r[P2]=count() */
1666416720
#define OP_ReadCookie 99
1666516721
#define OP_SetCookie 100
1666616722
#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
16667
-#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
16668
-#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
16669
-#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
16670
-#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
16671
-#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
16672
-#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
16673
-#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
16674
-#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
16675
-#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
16676
-#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
16677
-#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
16723
+#define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */
16724
+#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
16725
+#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
16726
+#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
16727
+#define OP_ShiftRight 106 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
16728
+#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
16729
+#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
16730
+#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
16731
+#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
16732
+#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
16733
+#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
1667816734
#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
16679
-#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
16680
-#define OP_OpenDup 115
16735
+#define OP_OpenDup 114
16736
+#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
1668116737
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
16682
-#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
16683
-#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
16738
+#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */
16739
+#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
1668416740
#define OP_SorterOpen 119
1668516741
#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
1668616742
#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
1668716743
#define OP_Close 122
1668816744
#define OP_ColumnsUsed 123
@@ -16713,12 +16769,12 @@
1671316769
#define OP_SqlExec 148
1671416770
#define OP_ParseSchema 149
1671516771
#define OP_LoadAnalysis 150
1671616772
#define OP_DropTable 151
1671716773
#define OP_DropIndex 152
16718
-#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
16719
-#define OP_DropTrigger 154
16774
+#define OP_DropTrigger 153
16775
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
1672016776
#define OP_IntegrityCk 155
1672116777
#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
1672216778
#define OP_Param 157
1672316779
#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
1672416780
#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
@@ -16770,24 +16826,24 @@
1677016826
/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
1677116827
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
1677216828
/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
1677316829
/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
1677416830
/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
16775
-/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
16776
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
16831
+/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
16832
+/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\
1677716833
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
1677816834
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
1677916835
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
1678016836
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
16781
-/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
16837
+/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\
1678216838
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
16783
-/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
16839
+/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\
1678416840
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
1678516841
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
1678616842
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
1678716843
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
16788
-/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
16844
+/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\
1678916845
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
1679016846
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
1679116847
/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
1679216848
/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
1679316849
@@ -17826,11 +17882,11 @@
1782617882
#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
1782717883
#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
1782817884
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
1782917885
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
1783017886
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
17831
-#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
17887
+#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
1783217888
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
1783317889
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
1783417890
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
1783517891
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
1783617892
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
@@ -19232,10 +19288,11 @@
1923219288
unsigned notCte :1; /* This item may not match a CTE */
1923319289
unsigned isUsing :1; /* u3.pUsing is valid */
1923419290
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
1923519291
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
1923619292
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
19293
+ unsigned rowidUsed :1; /* The ROWID of this table is referenced */
1923719294
} fg;
1923819295
int iCursor; /* The VDBE cursor number used to access this table */
1923919296
union {
1924019297
Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
1924119298
IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
@@ -19307,11 +19364,11 @@
1930719364
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
1930819365
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
1930919366
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
1931019367
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
1931119368
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
19312
- /* 0x2000 not currently used */
19369
+#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
1931319370
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
1931419371
/* 0x8000 not currently used */
1931519372
1931619373
/* Allowed return values from sqlite3WhereIsDistinct()
1931719374
*/
@@ -19379,11 +19436,11 @@
1937919436
#define NC_UEList 0x000080 /* True if uNC.pEList is used */
1938019437
#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
1938119438
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
1938219439
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
1938319440
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
19384
-#define NC_Complex 0x002000 /* True if a function or subquery seen */
19441
+/* 0x002000 // available for reuse */
1938519442
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
1938619443
#define NC_HasWin 0x008000 /* One or more window functions seen */
1938719444
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
1938819445
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
1938919446
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
@@ -19500,15 +19557,16 @@
1950019557
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
1950119558
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
1950219559
#define SF_View 0x0200000 /* SELECT statement is a view */
1950319560
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
1950419561
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
19505
-#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
19562
+#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
1950619563
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
1950719564
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
1950819565
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
1950919566
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
19567
+#define SF_Correlated 0x20000000 /* True if references the outer context */
1951019568
1951119569
/* True if S exists and has SF_NestedFrom */
1951219570
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
1951319571
1951419572
/*
@@ -19537,11 +19595,15 @@
1953719595
** of the query. This destination implies "LIMIT 1".
1953819596
**
1953919597
** SRT_Set The result must be a single column. Store each
1954019598
** row of result as the key in table pDest->iSDParm.
1954119599
** Apply the affinity pDest->affSdst before storing
19542
-** results. Used to implement "IN (SELECT ...)".
19600
+** results. if pDest->iSDParm2 is positive, then it is
19601
+** a regsiter holding a Bloom filter for the IN operator
19602
+** that should be populated in addition to the
19603
+** pDest->iSDParm table. This SRT is used to
19604
+** implement "IN (SELECT ...)".
1954319605
**
1954419606
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
1954519607
** the result there. The cursor is left open after
1954619608
** returning. This is like SRT_Table except that
1954719609
** this destination uses OP_OpenEphemeral to create
@@ -20040,11 +20102,11 @@
2004020102
int iRetReg; /* Register array for holding a row of RETURNING */
2004120103
char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
2004220104
};
2004320105
2004420106
/*
20045
-** An objected used to accumulate the text of a string where we
20107
+** An object used to accumulate the text of a string where we
2004620108
** do not necessarily know how big the string will be in the end.
2004720109
*/
2004820110
struct sqlite3_str {
2004920111
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
2005020112
char *zText; /* The string collected so far */
@@ -20054,11 +20116,11 @@
2005420116
u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
2005520117
u8 printfFlags; /* SQLITE_PRINTF flags below */
2005620118
};
2005720119
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
2005820120
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
20059
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
20121
+#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
2006020122
2006120123
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
2006220124
2006320125
/*
2006420126
** The following object is the header for an "RCStr" or "reference-counted
@@ -20775,11 +20837,11 @@
2077520837
SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
2077620838
SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
2077720839
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
2077820840
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
2077920841
SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
20780
-SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
20842
+SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*);
2078120843
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
2078220844
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
2078320845
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
2078420846
SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
2078520847
SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
@@ -20943,10 +21005,11 @@
2094321005
SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
2094421006
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
2094521007
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
2094621008
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
2094721009
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
21010
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
2094821011
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
2094921012
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
2095021013
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
2095121014
#endif
2095221015
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
@@ -21001,16 +21064,15 @@
2100121064
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
2100221065
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
2100321066
SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
2100421067
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
2100521068
SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
21006
-SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
21007
-SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
21069
+SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
2100821070
#ifdef SQLITE_ENABLE_CURSOR_HINTS
2100921071
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
2101021072
#endif
21011
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
21073
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
2101221074
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
2101321075
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
2101421076
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
2101521077
SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
2101621078
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
@@ -21187,11 +21249,13 @@
2118721249
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
2118821250
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
2118921251
SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
2119021252
SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
2119121253
SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
21254
+#if !defined(SQLITE_OMIT_BLOB_LITERAL)
2119221255
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
21256
+#endif
2119321257
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
2119421258
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
2119521259
2119621260
#if defined(SQLITE_NEED_ERR_NAME)
2119721261
SQLITE_PRIVATE const char *sqlite3ErrName(int);
@@ -24830,12 +24894,12 @@
2483024894
} aXformType[] = {
2483124895
/* 0 */ { 6, "second", 4.6427e+14, 1.0 },
2483224896
/* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
2483324897
/* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
2483424898
/* 3 */ { 3, "day", 5373485.0, 86400.0 },
24835
- /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
24836
- /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
24899
+ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
24900
+ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
2483724901
};
2483824902
2483924903
/*
2484024904
** If the DateTime p is raw number, try to figure out if it is
2484124905
** a julian day number of a unix timestamp. Set the p value
@@ -31939,11 +32003,11 @@
3193932003
sqlite3_str_appendall(pAccum, pItem->zName);
3194032004
}else if( pItem->zAlias ){
3194132005
sqlite3_str_appendall(pAccum, pItem->zAlias);
3194232006
}else{
3194332007
Select *pSel = pItem->pSelect;
31944
- assert( pSel!=0 );
32008
+ assert( pSel!=0 ); /* Because of tag-20240424-1 */
3194532009
if( pSel->selFlags & SF_NestedFrom ){
3194632010
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
3194732011
}else if( pSel->selFlags & SF_MultiValue ){
3194832012
assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
3194932013
sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
@@ -32722,12 +32786,14 @@
3272232786
char zLine[1000];
3272332787
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
3272432788
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
3272532789
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
3272632790
if( pItem->pTab ){
32727
- sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
32728
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
32791
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
32792
+ pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
32793
+ pItem->colUsed,
32794
+ pItem->fg.rowidUsed ? "+rowid" : "");
3272932795
}
3273032796
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
3273132797
sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
3273232798
}else if( pItem->fg.jointype & JT_LEFT ){
3273332799
sqlite3_str_appendf(&x, " LEFT-JOIN");
@@ -32763,16 +32829,18 @@
3276332829
if( pItem->fg.isUsing ) n++;
3276432830
if( pItem->fg.isUsing ){
3276532831
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
3276632832
}
3276732833
if( pItem->pSelect ){
32834
+ sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
3276832835
if( pItem->pTab ){
3276932836
Table *pTab = pItem->pTab;
3277032837
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
3277132838
}
3277232839
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
3277332840
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
32841
+ sqlite3TreeViewPop(&pView);
3277432842
}
3277532843
if( pItem->fg.isTabFunc ){
3277632844
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
3277732845
}
3277832846
sqlite3TreeViewPop(&pView);
@@ -32872,11 +32940,11 @@
3287232940
}
3287332941
if( p->pLimit ){
3287432942
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
3287532943
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
3287632944
if( p->pLimit->pRight ){
32877
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
32945
+ sqlite3TreeViewItem(pView, "OFFSET", 0);
3287832946
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
3287932947
sqlite3TreeViewPop(&pView);
3288032948
}
3288132949
sqlite3TreeViewPop(&pView);
3288232950
}
@@ -33344,11 +33412,12 @@
3334433412
case OE_Abort: zType = "abort"; break;
3334533413
case OE_Fail: zType = "fail"; break;
3334633414
case OE_Ignore: zType = "ignore"; break;
3334733415
}
3334833416
assert( !ExprHasProperty(pExpr, EP_IntValue) );
33349
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
33417
+ sqlite3TreeViewLine(pView, "RAISE %s", zType);
33418
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
3335033419
break;
3335133420
}
3335233421
#endif
3335333422
case TK_MATCH: {
3335433423
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
@@ -33424,13 +33493,14 @@
3342433493
}else{
3342533494
int i;
3342633495
sqlite3TreeViewLine(pView, "%s", zLabel);
3342733496
for(i=0; i<pList->nExpr; i++){
3342833497
int j = pList->a[i].u.x.iOrderByCol;
33498
+ u8 sortFlags = pList->a[i].fg.sortFlags;
3342933499
char *zName = pList->a[i].zEName;
3343033500
int moreToFollow = i<pList->nExpr - 1;
33431
- if( j || zName ){
33501
+ if( j || zName || sortFlags ){
3343233502
sqlite3TreeViewPush(&pView, moreToFollow);
3343333503
moreToFollow = 0;
3343433504
sqlite3TreeViewLine(pView, 0);
3343533505
if( zName ){
3343633506
switch( pList->a[i].fg.eEName ){
@@ -33447,17 +33517,22 @@
3344733517
fprintf(stdout, "SPAN(\"%s\") ", zName);
3344833518
break;
3344933519
}
3345033520
}
3345133521
if( j ){
33452
- fprintf(stdout, "iOrderByCol=%d", j);
33522
+ fprintf(stdout, "iOrderByCol=%d ", j);
33523
+ }
33524
+ if( sortFlags & KEYINFO_ORDER_DESC ){
33525
+ fprintf(stdout, "DESC ");
33526
+ }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
33527
+ fprintf(stdout, "NULLS-LAST");
3345333528
}
3345433529
fprintf(stdout, "\n");
3345533530
fflush(stdout);
3345633531
}
3345733532
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
33458
- if( j || zName ){
33533
+ if( j || zName || sortFlags ){
3345933534
sqlite3TreeViewPop(&pView);
3346033535
}
3346133536
}
3346233537
}
3346333538
}
@@ -35864,14 +35939,17 @@
3586435939
3586535940
/*
3586635941
** Decode a floating-point value into an approximate decimal
3586735942
** representation.
3586835943
**
35869
-** Round the decimal representation to n significant digits if
35870
-** n is positive. Or round to -n signficant digits after the
35871
-** decimal point if n is negative. No rounding is performed if
35872
-** n is zero.
35944
+** If iRound<=0 then round to -iRound significant digits to the
35945
+** the left of the decimal point, or to a maximum of mxRound total
35946
+** significant digits.
35947
+**
35948
+** If iRound>0 round to min(iRound,mxRound) significant digits total.
35949
+**
35950
+** mxRound must be positive.
3587335951
**
3587435952
** The significant digits of the decimal representation are
3587535953
** stored in p->z[] which is a often (but not always) a pointer
3587635954
** into the middle of p->zBuf[]. There are p->n significant digits.
3587735955
** The p->z[] array is *not* zero-terminated.
@@ -35880,10 +35958,12 @@
3588035958
int i;
3588135959
u64 v;
3588235960
int e, exp = 0;
3588335961
p->isSpecial = 0;
3588435962
p->z = p->zBuf;
35963
+
35964
+ assert( mxRound>0 );
3588535965
3588635966
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
3588735967
** NaN. */
3588835968
if( r<0.0 ){
3588935969
p->sign = '-';
@@ -37167,20 +37247,20 @@
3716737247
/* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
3716837248
/* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
3716937249
/* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
3717037250
/* 48 */ "Program" OpHelp(""),
3717137251
/* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
37172
- /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
37173
- /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
37174
- /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
37175
- /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
37176
- /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
37177
- /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
37178
- /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
37179
- /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
37180
- /* 58 */ "ElseEq" OpHelp(""),
37181
- /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
37252
+ /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
37253
+ /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
37254
+ /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
37255
+ /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
37256
+ /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
37257
+ /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
37258
+ /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
37259
+ /* 57 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
37260
+ /* 58 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
37261
+ /* 59 */ "ElseEq" OpHelp(""),
3718237262
/* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
3718337263
/* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
3718437264
/* 62 */ "IncrVacuum" OpHelp(""),
3718537265
/* 63 */ "VNext" OpHelp(""),
3718637266
/* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
@@ -37219,27 +37299,27 @@
3721937299
/* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
3722037300
/* 98 */ "Count" OpHelp("r[P2]=count()"),
3722137301
/* 99 */ "ReadCookie" OpHelp(""),
3722237302
/* 100 */ "SetCookie" OpHelp(""),
3722337303
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
37224
- /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
37225
- /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
37226
- /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
37227
- /* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
37228
- /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
37229
- /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
37230
- /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
37231
- /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
37232
- /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
37233
- /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
37234
- /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
37304
+ /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
37305
+ /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
37306
+ /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
37307
+ /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
37308
+ /* 106 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
37309
+ /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
37310
+ /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
37311
+ /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
37312
+ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
37313
+ /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
37314
+ /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
3723537315
/* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
37236
- /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
37237
- /* 115 */ "OpenDup" OpHelp(""),
37316
+ /* 114 */ "OpenDup" OpHelp(""),
37317
+ /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
3723837318
/* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
37239
- /* 117 */ "String8" OpHelp("r[P2]='P4'"),
37240
- /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
37319
+ /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"),
37320
+ /* 118 */ "String8" OpHelp("r[P2]='P4'"),
3724137321
/* 119 */ "SorterOpen" OpHelp(""),
3724237322
/* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
3724337323
/* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
3724437324
/* 122 */ "Close" OpHelp(""),
3724537325
/* 123 */ "ColumnsUsed" OpHelp(""),
@@ -37270,12 +37350,12 @@
3727037350
/* 148 */ "SqlExec" OpHelp(""),
3727137351
/* 149 */ "ParseSchema" OpHelp(""),
3727237352
/* 150 */ "LoadAnalysis" OpHelp(""),
3727337353
/* 151 */ "DropTable" OpHelp(""),
3727437354
/* 152 */ "DropIndex" OpHelp(""),
37275
- /* 153 */ "Real" OpHelp("r[P2]=P4"),
37276
- /* 154 */ "DropTrigger" OpHelp(""),
37355
+ /* 153 */ "DropTrigger" OpHelp(""),
37356
+ /* 154 */ "Real" OpHelp("r[P2]=P4"),
3727737357
/* 155 */ "IntegrityCk" OpHelp(""),
3727837358
/* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
3727937359
/* 157 */ "Param" OpHelp(""),
3728037360
/* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
3728137361
/* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
@@ -40577,30 +40657,26 @@
4057740657
*/
4057840658
#define DOTLOCK_SUFFIX ".lock"
4057940659
4058040660
/*
4058140661
** This routine checks if there is a RESERVED lock held on the specified
40582
-** file by this or any other process. If such a lock is held, set *pResOut
40583
-** to a non-zero value otherwise *pResOut is set to zero. The return value
40584
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
40585
-**
40586
-** In dotfile locking, either a lock exists or it does not. So in this
40587
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
40588
-** is held on the file and false if the file is unlocked.
40662
+** file by this or any other process. If the caller holds a SHARED
40663
+** or greater lock when it is called, then it is assumed that no other
40664
+** client may hold RESERVED. Or, if the caller holds no lock, then it
40665
+** is assumed another client holds RESERVED if the lock-file exists.
4058940666
*/
4059040667
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
40591
- int rc = SQLITE_OK;
40592
- int reserved = 0;
4059340668
unixFile *pFile = (unixFile*)id;
40594
-
4059540669
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
4059640670
40597
- assert( pFile );
40598
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
40599
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
40600
- *pResOut = reserved;
40601
- return rc;
40671
+ if( pFile->eFileLock>=SHARED_LOCK ){
40672
+ *pResOut = 0;
40673
+ }else{
40674
+ *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
40675
+ }
40676
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
40677
+ return SQLITE_OK;
4060240678
}
4060340679
4060440680
/*
4060540681
** Lock the file with the lock specified by parameter eFileLock - one
4060640682
** of the following:
@@ -42285,11 +42361,11 @@
4228542361
}
4228642362
}
4228742363
4228842364
/* Forward declaration */
4228942365
static int unixGetTempname(int nBuf, char *zBuf);
42290
-#ifndef SQLITE_OMIT_WAL
42366
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
4229142367
static int unixFcntlExternalReader(unixFile*, int*);
4229242368
#endif
4229342369
4229442370
/*
4229542371
** Information and control of an open file handle.
@@ -42412,11 +42488,11 @@
4241242488
return proxyFileControl(id,op,pArg);
4241342489
}
4241442490
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
4241542491
4241642492
case SQLITE_FCNTL_EXTERNAL_READER: {
42417
-#ifndef SQLITE_OMIT_WAL
42493
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
4241842494
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
4241942495
#else
4242042496
*(int*)pArg = 0;
4242142497
return SQLITE_OK;
4242242498
#endif
@@ -42585,11 +42661,11 @@
4258542661
#endif
4258642662
}
4258742663
4258842664
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
4258942665
42590
-#ifndef SQLITE_OMIT_WAL
42666
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
4259142667
4259242668
/*
4259342669
** Object used to represent an shared memory buffer.
4259442670
**
4259542671
** When multiple threads all reference the same wal-index, each thread
@@ -64135,11 +64211,11 @@
6413564211
/*
6413664212
** Return the file handle for the journal file (if it exists).
6413764213
** This will be either the rollback journal or the WAL file.
6413864214
*/
6413964215
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
64140
-#if SQLITE_OMIT_WAL
64216
+#ifdef SQLITE_OMIT_WAL
6414164217
return pPager->jfd;
6414264218
#else
6414364219
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
6414464220
#endif
6414564221
}
@@ -75626,10 +75702,16 @@
7562675702
}
7562775703
}
7562875704
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
7562975705
pCur->curFlags |= BTCF_ValidOvfl;
7563075706
}else{
75707
+ /* Sanity check the validity of the overflow page cache */
75708
+ assert( pCur->aOverflow[0]==nextPage
75709
+ || pCur->aOverflow[0]==0
75710
+ || CORRUPT_DB );
75711
+ assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
75712
+
7563175713
/* If the overflow page-list cache has been allocated and the
7563275714
** entry for the first required overflow page is valid, skip
7563375715
** directly to it.
7563475716
*/
7563575717
if( pCur->aOverflow[offset/ovflSize] ){
@@ -76106,10 +76188,27 @@
7610676188
*pRes = 1;
7610776189
rc = SQLITE_OK;
7610876190
}
7610976191
return rc;
7611076192
}
76193
+
76194
+#ifdef SQLITE_DEBUG
76195
+/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
76196
+** this flags are true for a consistent database.
76197
+**
76198
+** This routine is is called from within assert() statements only.
76199
+** It is an internal verification routine and does not appear in production
76200
+** builds.
76201
+*/
76202
+static int cursorIsAtLastEntry(BtCursor *pCur){
76203
+ int ii;
76204
+ for(ii=0; ii<pCur->iPage; ii++){
76205
+ if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
76206
+ }
76207
+ return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
76208
+}
76209
+#endif
7611176210
7611276211
/* Move the cursor to the last entry in the table. Return SQLITE_OK
7611376212
** on success. Set *pRes to 0 if the cursor actually points to something
7611476213
** or set *pRes to 1 if the table is empty.
7611576214
*/
@@ -76135,22 +76234,11 @@
7613576234
assert( cursorOwnsBtShared(pCur) );
7613676235
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
7613776236
7613876237
/* If the cursor already points to the last entry, this is a no-op. */
7613976238
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
76140
-#ifdef SQLITE_DEBUG
76141
- /* This block serves to assert() that the cursor really does point
76142
- ** to the last entry in the b-tree. */
76143
- int ii;
76144
- for(ii=0; ii<pCur->iPage; ii++){
76145
- assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
76146
- }
76147
- assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
76148
- testcase( pCur->ix!=pCur->pPage->nCell-1 );
76149
- /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
76150
- assert( pCur->pPage->leaf );
76151
-#endif
76239
+ assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
7615276240
*pRes = 0;
7615376241
return SQLITE_OK;
7615476242
}
7615576243
return btreeLast(pCur, pRes);
7615676244
}
@@ -76199,10 +76287,11 @@
7619976287
*pRes = 0;
7620076288
return SQLITE_OK;
7620176289
}
7620276290
if( pCur->info.nKey<intKey ){
7620376291
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
76292
+ assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
7620476293
*pRes = -1;
7620576294
return SQLITE_OK;
7620676295
}
7620776296
/* If the requested key is one more than the previous key, then
7620876297
** try to get there using sqlite3BtreeNext() rather than a full
@@ -78037,11 +78126,12 @@
7803778126
assert( i<iEnd );
7803878127
j = get2byte(&aData[hdr+5]);
7803978128
if( j>(u32)usableSize ){ j = 0; }
7804078129
memcpy(&pTmp[j], &aData[j], usableSize - j);
7804178130
78042
- for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
78131
+ assert( pCArray->ixNx[NB*2-1]>i );
78132
+ for(k=0; pCArray->ixNx[k]<=i; k++){}
7804378133
pSrcEnd = pCArray->apEnd[k];
7804478134
7804578135
pData = pEnd;
7804678136
while( 1/*exit by break*/ ){
7804778137
u8 *pCell = pCArray->apCell[i];
@@ -78120,11 +78210,12 @@
7812078210
int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
7812178211
int k; /* Current slot in pCArray->apEnd[] */
7812278212
u8 *pEnd; /* Maximum extent of cell data */
7812378213
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
7812478214
if( iEnd<=iFirst ) return 0;
78125
- for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
78215
+ assert( pCArray->ixNx[NB*2-1]>i );
78216
+ for(k=0; pCArray->ixNx[k]<=i ; k++){}
7812678217
pEnd = pCArray->apEnd[k];
7812778218
while( 1 /*Exit by break*/ ){
7812878219
int sz, rc;
7812978220
u8 *pSlot;
7813078221
assert( pCArray->szCell[i]!=0 );
@@ -78405,10 +78496,11 @@
7840578496
b.pRef = pPage;
7840678497
b.apCell = &pCell;
7840778498
b.szCell = &szCell;
7840878499
b.apEnd[0] = pPage->aDataEnd;
7840978500
b.ixNx[0] = 2;
78501
+ b.ixNx[NB*2-1] = 0x7fffffff;
7841078502
rc = rebuildPage(&b, 0, 1, pNew);
7841178503
if( NEVER(rc) ){
7841278504
releasePage(pNew);
7841378505
return rc;
7841478506
}
@@ -78640,11 +78732,13 @@
7864078732
u8 abDone[NB+2]; /* True after i'th new page is populated */
7864178733
Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */
7864278734
CellArray b; /* Parsed information on cells being balanced */
7864378735
7864478736
memset(abDone, 0, sizeof(abDone));
78645
- memset(&b, 0, sizeof(b));
78737
+ assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
78738
+ memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
78739
+ b.ixNx[NB*2-1] = 0x7fffffff;
7864678740
pBt = pParent->pBt;
7864778741
assert( sqlite3_mutex_held(pBt->mutex) );
7864878742
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
7864978743
7865078744
/* At this point pParent may have at most one overflow cell. And if
@@ -79231,11 +79325,12 @@
7923179325
}
7923279326
}
7923379327
iOvflSpace += sz;
7923479328
assert( sz<=pBt->maxLocal+23 );
7923579329
assert( iOvflSpace <= (int)pBt->pageSize );
79236
- for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
79330
+ assert( b.ixNx[NB*2-1]>j );
79331
+ for(k=0; b.ixNx[k]<=j; k++){}
7923779332
pSrcEnd = b.apEnd[k];
7923879333
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
7923979334
rc = SQLITE_CORRUPT_BKPT;
7924079335
goto balance_cleanup;
7924179336
}
@@ -80004,11 +80099,11 @@
8000480099
dropCell(pPage, idx, info.nSize, &rc);
8000580100
if( rc ) goto end_insert;
8000680101
}else if( loc<0 && pPage->nCell>0 ){
8000780102
assert( pPage->leaf );
8000880103
idx = ++pCur->ix;
80009
- pCur->curFlags &= ~BTCF_ValidNKey;
80104
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
8001080105
}else{
8001180106
assert( pPage->leaf );
8001280107
}
8001380108
rc = insertCellFast(pPage, idx, newCell, szNew);
8001480109
assert( pPage->nOverflow==0 || rc==SQLITE_OK );
@@ -80034,11 +80129,11 @@
8003480129
** larger than the largest existing key, it is possible to insert the
8003580130
** row without seeking the cursor. This can be a big performance boost.
8003680131
*/
8003780132
if( pPage->nOverflow ){
8003880133
assert( rc==SQLITE_OK );
80039
- pCur->curFlags &= ~(BTCF_ValidNKey);
80134
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
8004080135
rc = balance(pCur);
8004180136
8004280137
/* Must make sure nOverflow is reset to zero even if the balance()
8004380138
** fails. Internal data structure corruption will result otherwise.
8004480139
** Also, set the cursor state to invalid. This stops saveCursorPosition()
@@ -84658,21 +84753,21 @@
8465884753
int nRec, /* Size of buffer pRec in bytes */
8465984754
int iCol, /* Column to extract */
8466084755
sqlite3_value **ppVal /* OUT: Extracted value */
8466184756
){
8466284757
u32 t = 0; /* a column type code */
84663
- int nHdr; /* Size of the header in the record */
84664
- int iHdr; /* Next unread header byte */
84665
- int iField; /* Next unread data byte */
84666
- int szField = 0; /* Size of the current data field */
84758
+ u32 nHdr; /* Size of the header in the record */
84759
+ u32 iHdr; /* Next unread header byte */
84760
+ i64 iField; /* Next unread data byte */
84761
+ u32 szField = 0; /* Size of the current data field */
8466784762
int i; /* Column index */
8466884763
u8 *a = (u8*)pRec; /* Typecast byte array */
8466984764
Mem *pMem = *ppVal; /* Write result into this Mem object */
8467084765
8467184766
assert( iCol>0 );
8467284767
iHdr = getVarint32(a, nHdr);
84673
- if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
84768
+ if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
8467484769
iField = nHdr;
8467584770
for(i=0; i<=iCol; i++){
8467684771
iHdr += getVarint32(&a[iHdr], t);
8467784772
testcase( iHdr==nHdr );
8467884773
testcase( iHdr==nHdr+1 );
@@ -88119,11 +88214,11 @@
8811988214
}
8812088215
}
8812188216
8812288217
/* Check for immediate foreign key violations. */
8812388218
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
88124
- sqlite3VdbeCheckFk(p, 0);
88219
+ (void)sqlite3VdbeCheckFk(p, 0);
8812588220
}
8812688221
8812788222
/* If the auto-commit flag is set and this is the only active writer
8812888223
** VM, then we do either a commit or rollback of the current transaction.
8812988224
**
@@ -90100,11 +90195,12 @@
9010090195
*/
9010190196
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
9010290197
assert( iVar>0 );
9010390198
if( v ){
9010490199
Mem *pMem = &v->aVar[iVar-1];
90105
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
90200
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
90201
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
9010690202
if( 0==(pMem->flags & MEM_Null) ){
9010790203
sqlite3_value *pRet = sqlite3ValueNew(v->db);
9010890204
if( pRet ){
9010990205
sqlite3VdbeMemCopy((Mem *)pRet, pMem);
9011090206
sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
@@ -90120,11 +90216,12 @@
9012090216
** to sqlite3_reoptimize() that re-preparing the statement may result
9012190217
** in a better query plan.
9012290218
*/
9012390219
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
9012490220
assert( iVar>0 );
90125
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
90221
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
90222
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
9012690223
if( iVar>=32 ){
9012790224
v->expmask |= 0x80000000;
9012890225
}else{
9012990226
v->expmask |= ((u32)1 << (iVar-1));
9013090227
}
@@ -94190,11 +94287,13 @@
9419094287
9419194288
/* Opcode: EndCoroutine P1 * * * *
9419294289
**
9419394290
** The instruction at the address in register P1 is a Yield.
9419494291
** Jump to the P2 parameter of that Yield.
94195
-** After the jump, register P1 becomes undefined.
94292
+** After the jump, the value register P1 is left with a value
94293
+** such that subsequent OP_Yields go back to the this same
94294
+** OP_EndCoroutine instruction.
9419694295
**
9419794296
** See also: InitCoroutine
9419894297
*/
9419994298
case OP_EndCoroutine: { /* in1 */
9420094299
VdbeOp *pCaller;
@@ -94202,12 +94301,12 @@
9420294301
assert( pIn1->flags==MEM_Int );
9420394302
assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
9420494303
pCaller = &aOp[pIn1->u.i];
9420594304
assert( pCaller->opcode==OP_Yield );
9420694305
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
94306
+ pIn1->u.i = (int)(pOp - p->aOp) - 1;
9420794307
pOp = &aOp[pCaller->p2 - 1];
94208
- pIn1->flags = MEM_Undefined;
9420994308
break;
9421094309
}
9421194310
9421294311
/* Opcode: Yield P1 P2 * * *
9421394312
**
@@ -94250,11 +94349,11 @@
9425094349
if( (pIn3->flags & MEM_Null)==0 ) break;
9425194350
/* Fall through into OP_Halt */
9425294351
/* no break */ deliberate_fall_through
9425394352
}
9425494353
94255
-/* Opcode: Halt P1 P2 * P4 P5
94354
+/* Opcode: Halt P1 P2 P3 P4 P5
9425694355
**
9425794356
** Exit immediately. All open cursors, etc are closed
9425894357
** automatically.
9425994358
**
9426094359
** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
@@ -94263,22 +94362,26 @@
9426394362
** whether or not to rollback the current transaction. Do not rollback
9426494363
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
9426594364
** then back out all changes that have occurred during this execution of the
9426694365
** VDBE, but do not rollback the transaction.
9426794366
**
94268
-** If P4 is not null then it is an error message string.
94367
+** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
94368
+** text of an error message.
9426994369
**
94270
-** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
94370
+** If P3 is zero and P4 is not null then the error message string is held
94371
+** in P4.
9427194372
**
94272
-** 0: (no change)
94373
+** P5 is a value between 1 and 4, inclusive, then the P4 error message
94374
+** string is modified as follows:
94375
+**
9427394376
** 1: NOT NULL constraint failed: P4
9427494377
** 2: UNIQUE constraint failed: P4
9427594378
** 3: CHECK constraint failed: P4
9427694379
** 4: FOREIGN KEY constraint failed: P4
9427794380
**
94278
-** If P5 is not zero and P4 is NULL, then everything after the ":" is
94279
-** omitted.
94381
+** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
94382
+** the ":" is omitted.
9428094383
**
9428194384
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
9428294385
** every program. So a jump past the last instruction of the program
9428394386
** is the same as executing Halt.
9428494387
*/
@@ -94287,10 +94390,13 @@
9428794390
int pcx;
9428894391
9428994392
#ifdef SQLITE_DEBUG
9429094393
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
9429194394
#endif
94395
+ assert( pOp->p4type==P4_NOTUSED
94396
+ || pOp->p4type==P4_STATIC
94397
+ || pOp->p4type==P4_DYNAMIC );
9429294398
9429394399
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
9429494400
** something is wrong with the code generator. Raise an assertion in order
9429594401
** to bring this to the attention of fuzzers and other testing tools. */
9429694402
assert( pOp->p1!=SQLITE_INTERNAL );
@@ -94317,11 +94423,16 @@
9431794423
}
9431894424
p->rc = pOp->p1;
9431994425
p->errorAction = (u8)pOp->p2;
9432094426
assert( pOp->p5<=4 );
9432194427
if( p->rc ){
94322
- if( pOp->p5 ){
94428
+ if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
94429
+ const char *zErr;
94430
+ assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
94431
+ zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
94432
+ sqlite3VdbeError(p, "%s", zErr);
94433
+ }else if( pOp->p5 ){
9432394434
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
9432494435
"FOREIGN KEY" };
9432594436
testcase( pOp->p5==1 );
9432694437
testcase( pOp->p5==2 );
9432794438
testcase( pOp->p5==3 );
@@ -97360,27 +97471,27 @@
9736097471
wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
9736197472
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
9736297473
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
9736397474
p->minWriteFileFormat = pDb->pSchema->file_format;
9736497475
}
97476
+ if( pOp->p5 & OPFLAG_P2ISREG ){
97477
+ assert( p2>0 );
97478
+ assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
97479
+ pIn2 = &aMem[p2];
97480
+ assert( memIsValid(pIn2) );
97481
+ assert( (pIn2->flags & MEM_Int)!=0 );
97482
+ sqlite3VdbeMemIntegerify(pIn2);
97483
+ p2 = (int)pIn2->u.i;
97484
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
97485
+ ** that opcode will always set the p2 value to 2 or more or else fail.
97486
+ ** If there were a failure, the prepared statement would have halted
97487
+ ** before reaching this instruction. */
97488
+ assert( p2>=2 );
97489
+ }
9736597490
}else{
9736697491
wrFlag = 0;
97367
- }
97368
- if( pOp->p5 & OPFLAG_P2ISREG ){
97369
- assert( p2>0 );
97370
- assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
97371
- assert( pOp->opcode==OP_OpenWrite );
97372
- pIn2 = &aMem[p2];
97373
- assert( memIsValid(pIn2) );
97374
- assert( (pIn2->flags & MEM_Int)!=0 );
97375
- sqlite3VdbeMemIntegerify(pIn2);
97376
- p2 = (int)pIn2->u.i;
97377
- /* The p2 value always comes from a prior OP_CreateBtree opcode and
97378
- ** that opcode will always set the p2 value to 2 or more or else fail.
97379
- ** If there were a failure, the prepared statement would have halted
97380
- ** before reaching this instruction. */
97381
- assert( p2>=2 );
97492
+ assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
9738297493
}
9738397494
if( pOp->p4type==P4_KEYINFO ){
9738497495
pKeyInfo = pOp->p4.pKeyInfo;
9738597496
assert( pKeyInfo->enc==ENC(db) );
9738697497
assert( pKeyInfo->db==db );
@@ -97620,11 +97731,12 @@
9762097731
** row output from the sorter so that the row can be decomposed into
9762197732
** individual columns using the OP_Column opcode. The OP_Column opcode
9762297733
** is the only cursor opcode that works with a pseudo-table.
9762397734
**
9762497735
** P3 is the number of fields in the records that will be stored by
97625
-** the pseudo-table.
97736
+** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
97737
+** will return NULL for every column.
9762697738
*/
9762797739
case OP_OpenPseudo: {
9762897740
VdbeCursor *pCx;
9762997741
9763097742
assert( pOp->p1>=0 );
@@ -98331,10 +98443,11 @@
9833198443
if( r.nField>0 ){
9833298444
/* Key values in an array of registers */
9833398445
r.pKeyInfo = pC->pKeyInfo;
9833498446
r.default_rc = 0;
9833598447
#ifdef SQLITE_DEBUG
98448
+ (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
9833698449
for(ii=0; ii<r.nField; ii++){
9833798450
assert( memIsValid(&r.aMem[ii]) );
9833898451
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
9833998452
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
9834098453
}
@@ -102038,18 +102151,33 @@
102038102151
}
102039102152
#endif
102040102153
102041102154
/* Opcode: Noop * * * * *
102042102155
**
102043
-** Do nothing. This instruction is often useful as a jump
102044
-** destination.
102156
+** Do nothing. Continue downward to the next opcode.
102045102157
*/
102046
-/*
102047
-** The magic Explain opcode are only inserted when explain==2 (which
102048
-** is to say when the EXPLAIN QUERY PLAN syntax is used.)
102049
-** This opcode records information from the optimizer. It is the
102050
-** the same as a no-op. This opcodesnever appears in a real VM program.
102158
+/* Opcode: Explain P1 P2 P3 P4 *
102159
+**
102160
+** This is the same as OP_Noop during normal query execution. The
102161
+** purpose of this opcode is to hold information about the query
102162
+** plan for the purpose of EXPLAIN QUERY PLAN output.
102163
+**
102164
+** The P4 value is human-readable text that describes the query plan
102165
+** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
102166
+**
102167
+** The P1 value is the ID of the current element and P2 is the parent
102168
+** element for the case of nested query plan elements. If P2 is zero
102169
+** then this element is a top-level element.
102170
+**
102171
+** For loop elements, P3 is the estimated code of each invocation of this
102172
+** element.
102173
+**
102174
+** As with all opcodes, the meanings of the parameters for OP_Explain
102175
+** are subject to change from one release to the next. Applications
102176
+** should not attempt to interpret or use any of the information
102177
+** contined in the OP_Explain opcode. The information provided by this
102178
+** opcode is intended for testing and debugging use only.
102051102179
*/
102052102180
default: { /* This is really OP_Noop, OP_Explain */
102053102181
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
102054102182
102055102183
break;
@@ -105778,14 +105906,14 @@
105778105906
break;
105779105907
}
105780105908
105781105909
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
105782105910
case 9: /* nexec */
105783
- sqlite3_result_int(ctx, pOp->nExec);
105911
+ sqlite3_result_int64(ctx, pOp->nExec);
105784105912
break;
105785105913
case 10: /* ncycle */
105786
- sqlite3_result_int(ctx, pOp->nCycle);
105914
+ sqlite3_result_int64(ctx, pOp->nCycle);
105787105915
break;
105788105916
#else
105789105917
case 9: /* nexec */
105790105918
case 10: /* ncycle */
105791105919
sqlite3_result_int(ctx, 0);
@@ -106874,11 +107002,11 @@
106874107002
** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab.
106875107003
*/
106876107004
static SQLITE_NOINLINE int isValidSchemaTableName(
106877107005
const char *zTab, /* Name as it appears in the SQL */
106878107006
Table *pTab, /* The schema table we are trying to match */
106879
- Schema *pSchema /* non-NULL if a database qualifier is present */
107007
+ const char *zDb /* non-NULL if a database qualifier is present */
106880107008
){
106881107009
const char *zLegacy;
106882107010
assert( pTab!=0 );
106883107011
assert( pTab->tnum==1 );
106884107012
if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0;
@@ -106885,11 +107013,11 @@
106885107013
zLegacy = pTab->zName;
106886107014
if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
106887107015
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
106888107016
return 1;
106889107017
}
106890
- if( pSchema==0 ) return 0;
107018
+ if( zDb==0 ) return 0;
106891107019
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
106892107020
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
106893107021
}else{
106894107022
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
106895107023
}
@@ -107068,11 +107196,11 @@
107068107196
if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){
107069107197
continue;
107070107198
}
107071107199
}else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
107072107200
if( pTab->tnum!=1 ) continue;
107073
- if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
107201
+ if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
107074107202
}
107075107203
assert( ExprUseYTab(pExpr) );
107076107204
if( IN_RENAME_OBJECT && pItem->zAlias ){
107077107205
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
107078107206
}
@@ -107174,11 +107302,12 @@
107174107302
int op = pParse->eTriggerOp;
107175107303
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
107176107304
if( pParse->bReturning ){
107177107305
if( (pNC->ncFlags & NC_UBaseReg)!=0
107178107306
&& ALWAYS(zTab==0
107179
- || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
107307
+ || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0
107308
+ || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0))
107180107309
){
107181107310
pExpr->iTable = op!=TK_DELETE;
107182107311
pTab = pParse->pTriggerTab;
107183107312
}
107184107313
}else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
@@ -107278,10 +107407,15 @@
107278107407
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
107279107408
&& sqlite3IsRowid(zCol)
107280107409
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
107281107410
){
107282107411
cnt = cntTab;
107412
+#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
107413
+ if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
107414
+ eNewExprOp = TK_NULL;
107415
+ }
107416
+#endif
107283107417
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
107284107418
pExpr->affExpr = SQLITE_AFF_INTEGER;
107285107419
}
107286107420
107287107421
/*
@@ -107468,12 +107602,16 @@
107468107602
** (See ticket [b92e5e8ec2cdbaa1]).
107469107603
**
107470107604
** If a generated column is referenced, set bits for every column
107471107605
** of the table.
107472107606
*/
107473
- if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){
107474
- pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
107607
+ if( pMatch ){
107608
+ if( pExpr->iColumn>=0 ){
107609
+ pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
107610
+ }else{
107611
+ pMatch->fg.rowidUsed = 1;
107612
+ }
107475107613
}
107476107614
107477107615
pExpr->op = eNewExprOp;
107478107616
lookupname_end:
107479107617
if( cnt==1 ){
@@ -107921,15 +108059,13 @@
107921108059
#else
107922108060
pNC->ncFlags &= ~NC_AllowAgg;
107923108061
#endif
107924108062
}
107925108063
}
107926
-#ifndef SQLITE_OMIT_WINDOWFUNC
107927
- else if( ExprHasProperty(pExpr, EP_WinFunc) ){
108064
+ else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){
107928108065
is_agg = 1;
107929108066
}
107930
-#endif
107931108067
sqlite3WalkExprList(pWalker, pList);
107932108068
if( is_agg ){
107933108069
if( pExpr->pLeft ){
107934108070
assert( pExpr->pLeft->op==TK_ORDER );
107935108071
assert( ExprUseXList(pExpr->pLeft) );
@@ -107995,18 +108131,20 @@
107995108131
int nRef = pNC->nRef;
107996108132
testcase( pNC->ncFlags & NC_IsCheck );
107997108133
testcase( pNC->ncFlags & NC_PartIdx );
107998108134
testcase( pNC->ncFlags & NC_IdxExpr );
107999108135
testcase( pNC->ncFlags & NC_GenCol );
108136
+ assert( pExpr->x.pSelect );
108000108137
if( pNC->ncFlags & NC_SelfRef ){
108001108138
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
108002108139
}else{
108003108140
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
108004108141
}
108005108142
assert( pNC->nRef>=nRef );
108006108143
if( nRef!=pNC->nRef ){
108007108144
ExprSetProperty(pExpr, EP_VarSelect);
108145
+ pExpr->x.pSelect->selFlags |= SF_Correlated;
108008108146
}
108009108147
pNC->ncFlags |= NC_Subquery;
108010108148
}
108011108149
break;
108012108150
}
@@ -108141,11 +108279,11 @@
108141108279
NameContext nc; /* Name context for resolving pE */
108142108280
sqlite3 *db; /* Database connection */
108143108281
int rc; /* Return code from subprocedures */
108144108282
u8 savedSuppErr; /* Saved value of db->suppressErr */
108145108283
108146
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
108284
+ assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
108147108285
pEList = pSelect->pEList;
108148108286
108149108287
/* Resolve all names in the ORDER BY term expression
108150108288
*/
108151108289
memset(&nc, 0, sizeof(nc));
@@ -108240,11 +108378,11 @@
108240108378
int iCol = -1;
108241108379
Expr *pE, *pDup;
108242108380
if( pItem->fg.done ) continue;
108243108381
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
108244108382
if( NEVER(pE==0) ) continue;
108245
- if( sqlite3ExprIsInteger(pE, &iCol) ){
108383
+ if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
108246108384
if( iCol<=0 || iCol>pEList->nExpr ){
108247108385
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
108248108386
return 1;
108249108387
}
108250108388
}else{
@@ -108425,11 +108563,11 @@
108425108563
** copy of the iCol-th result-set expression. */
108426108564
pItem->u.x.iOrderByCol = (u16)iCol;
108427108565
continue;
108428108566
}
108429108567
}
108430
- if( sqlite3ExprIsInteger(pE2, &iCol) ){
108568
+ if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
108431108569
/* The ORDER BY term is an integer constant. Again, set the column
108432108570
** number so that sqlite3ResolveOrderGroupBy() will convert the
108433108571
** order-by term to a copy of the result-set expression */
108434108572
if( iCol<1 || iCol>0xffff ){
108435108573
resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
@@ -108528,10 +108666,11 @@
108528108666
/* Recursively resolve names in all subqueries in the FROM clause
108529108667
*/
108530108668
if( pOuterNC ) pOuterNC->nNestedSelect++;
108531108669
for(i=0; i<p->pSrc->nSrc; i++){
108532108670
SrcItem *pItem = &p->pSrc->a[i];
108671
+ assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
108533108672
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
108534108673
int nRef = pOuterNC ? pOuterNC->nRef : 0;
108535108674
const char *zSavedContext = pParse->zAuthContext;
108536108675
108537108676
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
@@ -109004,11 +109143,13 @@
109004109143
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
109005109144
pExpr = pExpr->pLeft;
109006109145
op = pExpr->op;
109007109146
continue;
109008109147
}
109009
- if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
109148
+ if( op!=TK_REGISTER ) break;
109149
+ op = pExpr->op2;
109150
+ if( NEVER( op==TK_REGISTER ) ) break;
109010109151
}
109011109152
return pExpr->affExpr;
109012109153
}
109013109154
109014109155
/*
@@ -110287,10 +110428,11 @@
110287110428
** Recursively delete an expression tree.
110288110429
*/
110289110430
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
110290110431
assert( p!=0 );
110291110432
assert( db!=0 );
110433
+exprDeleteRestart:
110292110434
assert( !ExprUseUValue(p) || p->u.iValue>=0 );
110293110435
assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
110294110436
assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
110295110437
assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
110296110438
#ifdef SQLITE_DEBUG
@@ -110302,11 +110444,10 @@
110302110444
}
110303110445
#endif
110304110446
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
110305110447
/* The Expr.x union is never used at the same time as Expr.pRight */
110306110448
assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
110307
- if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
110308110449
if( p->pRight ){
110309110450
assert( !ExprHasProperty(p, EP_WinFunc) );
110310110451
sqlite3ExprDeleteNN(db, p->pRight);
110311110452
}else if( ExprUseXSelect(p) ){
110312110453
assert( !ExprHasProperty(p, EP_WinFunc) );
@@ -110316,10 +110457,23 @@
110316110457
#ifndef SQLITE_OMIT_WINDOWFUNC
110317110458
if( ExprHasProperty(p, EP_WinFunc) ){
110318110459
sqlite3WindowDelete(db, p->y.pWin);
110319110460
}
110320110461
#endif
110462
+ }
110463
+ if( p->pLeft && p->op!=TK_SELECT_COLUMN ){
110464
+ Expr *pLeft = p->pLeft;
110465
+ if( !ExprHasProperty(p, EP_Static)
110466
+ && !ExprHasProperty(pLeft, EP_Static)
110467
+ ){
110468
+ /* Avoid unnecessary recursion on unary operators */
110469
+ sqlite3DbNNFreeNN(db, p);
110470
+ p = pLeft;
110471
+ goto exprDeleteRestart;
110472
+ }else{
110473
+ sqlite3ExprDeleteNN(db, pLeft);
110474
+ }
110321110475
}
110322110476
}
110323110477
if( !ExprHasProperty(p, EP_Static) ){
110324110478
sqlite3DbNNFreeNN(db, p);
110325110479
}
@@ -110349,15 +110503,15 @@
110349110503
** This is similar to sqlite3ExprDelete() except that the delete is
110350110504
** deferred until the pParse is deleted.
110351110505
**
110352110506
** The pExpr might be deleted immediately on an OOM error.
110353110507
**
110354
-** The deferred delete is (currently) implemented by adding the
110355
-** pExpr to the pParse->pConstExpr list with a register number of 0.
110508
+** Return 0 if the delete was successfully deferred. Return non-zero
110509
+** if the delete happened immediately because of an OOM.
110356110510
*/
110357
-SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
110358
- sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
110511
+SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
110512
+ return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
110359110513
}
110360110514
110361110515
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
110362110516
** expression.
110363110517
*/
@@ -111312,11 +111466,11 @@
111312111466
|| ExprHasProperty(pExpr, EP_WinFunc)
111313111467
){
111314111468
pWalker->eCode = 0;
111315111469
return WRC_Abort;
111316111470
}
111317
- return WRC_Continue;
111471
+ return WRC_Prune;
111318111472
}
111319111473
111320111474
111321111475
/*
111322111476
** These routines are Walker callbacks used to check expressions to
@@ -111419,20 +111573,19 @@
111419111573
testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
111420111574
testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
111421111575
return WRC_Continue;
111422111576
}
111423111577
}
111424
-static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
111578
+static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
111425111579
Walker w;
111426111580
w.eCode = initFlag;
111427111581
w.pParse = pParse;
111428111582
w.xExprCallback = exprNodeIsConstant;
111429111583
w.xSelectCallback = sqlite3SelectWalkFail;
111430111584
#ifdef SQLITE_DEBUG
111431111585
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
111432111586
#endif
111433
- w.u.iCur = iCur;
111434111587
sqlite3WalkExpr(&w, p);
111435111588
return w.eCode;
111436111589
}
111437111590
111438111591
/*
@@ -111448,11 +111601,11 @@
111448111601
** function calls will be considered to be non-constant. If pParse is
111449111602
** not NULL, then a function call might be constant, depending on the
111450111603
** function and on its parameters.
111451111604
*/
111452111605
SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
111453
- return exprIsConst(pParse, p, 1, 0);
111606
+ return exprIsConst(pParse, p, 1);
111454111607
}
111455111608
111456111609
/*
111457111610
** Walk an expression tree. Return non-zero if
111458111611
**
@@ -111465,21 +111618,54 @@
111465111618
** When this routine returns true, it indicates that the expression
111466111619
** can be added to the pParse->pConstExpr list and evaluated once when
111467111620
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
111468111621
*/
111469111622
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
111470
- return exprIsConst(pParse, p, 2, 0);
111623
+ return exprIsConst(pParse, p, 2);
111624
+}
111625
+
111626
+/*
111627
+** This routine examines sub-SELECT statements as an expression is being
111628
+** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
111629
+** constant as long as they are uncorrelated - meaning that they do not
111630
+** contain any terms from outer contexts.
111631
+*/
111632
+static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
111633
+ assert( pSelect!=0 );
111634
+ assert( pWalker->eCode==3 || pWalker->eCode==0 );
111635
+ if( (pSelect->selFlags & SF_Correlated)!=0 ){
111636
+ pWalker->eCode = 0;
111637
+ return WRC_Abort;
111638
+ }
111639
+ return WRC_Prune;
111471111640
}
111472111641
111473111642
/*
111474111643
** Walk an expression tree. Return non-zero if the expression is constant
111475111644
** for any single row of the table with cursor iCur. In other words, the
111476111645
** expression must not refer to any non-deterministic function nor any
111477111646
** table other than iCur.
111647
+**
111648
+** Consider uncorrelated subqueries to be constants if the bAllowSubq
111649
+** parameter is true.
111478111650
*/
111479
-SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
111480
- return exprIsConst(0, p, 3, iCur);
111651
+static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
111652
+ Walker w;
111653
+ w.eCode = 3;
111654
+ w.pParse = 0;
111655
+ w.xExprCallback = exprNodeIsConstant;
111656
+ if( bAllowSubq ){
111657
+ w.xSelectCallback = exprSelectWalkTableConstant;
111658
+ }else{
111659
+ w.xSelectCallback = sqlite3SelectWalkFail;
111660
+#ifdef SQLITE_DEBUG
111661
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
111662
+#endif
111663
+ }
111664
+ w.u.iCur = iCur;
111665
+ sqlite3WalkExpr(&w, p);
111666
+ return w.eCode;
111481111667
}
111482111668
111483111669
/*
111484111670
** Check pExpr to see if it is an constraint on the single data source
111485111671
** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr
@@ -111493,11 +111679,14 @@
111493111679
**
111494111680
** To be an single-source constraint, the following must be true:
111495111681
**
111496111682
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
111497111683
**
111498
-** (2) pExpr cannot use subqueries or non-deterministic functions.
111684
+** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
111685
+** true and the subquery is non-correlated
111686
+**
111687
+** (2b) pExpr cannot use non-deterministic functions.
111499111688
**
111500111689
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
111501111690
** (Is there some way to relax this constraint?)
111502111691
**
111503111692
** (4) If pSrc is the right operand of a LEFT JOIN, then...
@@ -111522,11 +111711,12 @@
111522111711
** on push-down.
111523111712
*/
111524111713
SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(
111525111714
Expr *pExpr, /* The constraint */
111526111715
const SrcList *pSrcList, /* Complete FROM clause */
111527
- int iSrc /* Which element of pSrcList to use */
111716
+ int iSrc, /* Which element of pSrcList to use */
111717
+ int bAllowSubq /* Allow non-correlated subqueries */
111528111718
){
111529111719
const SrcItem *pSrc = &pSrcList->a[iSrc];
111530111720
if( pSrc->fg.jointype & JT_LTORJ ){
111531111721
return 0; /* rule (3) */
111532111722
}
@@ -111547,11 +111737,12 @@
111547111737
}
111548111738
break;
111549111739
}
111550111740
}
111551111741
}
111552
- return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
111742
+ /* Rules (1), (2a), and (2b) handled by the following: */
111743
+ return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
111553111744
}
111554111745
111555111746
111556111747
/*
111557111748
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
@@ -111632,11 +111823,11 @@
111632111823
** is considered a variable but a single-quoted string (ex: 'abc') is
111633111824
** a constant.
111634111825
*/
111635111826
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
111636111827
assert( isInit==0 || isInit==1 );
111637
- return exprIsConst(0, p, 4+isInit, 0);
111828
+ return exprIsConst(0, p, 4+isInit);
111638111829
}
111639111830
111640111831
#ifdef SQLITE_ENABLE_CURSOR_HINTS
111641111832
/*
111642111833
** Walk an expression tree. Return 1 if the expression contains a
@@ -111658,12 +111849,16 @@
111658111849
/*
111659111850
** If the expression p codes a constant integer that is small enough
111660111851
** to fit in a 32-bit integer, return 1 and put the value of the integer
111661111852
** in *pValue. If the expression is not an integer or if it is too big
111662111853
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
111854
+**
111855
+** If the pParse pointer is provided, then allow the expression p to be
111856
+** a parameter (TK_VARIABLE) that is bound to an integer.
111857
+** But if pParse is NULL, then p must be a pure integer literal.
111663111858
*/
111664
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
111859
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
111665111860
int rc = 0;
111666111861
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
111667111862
111668111863
/* If an expression is an integer literal that fits in a signed 32-bit
111669111864
** integer, then the EP_IntValue flag will have already been set */
@@ -111674,21 +111869,41 @@
111674111869
*pValue = p->u.iValue;
111675111870
return 1;
111676111871
}
111677111872
switch( p->op ){
111678111873
case TK_UPLUS: {
111679
- rc = sqlite3ExprIsInteger(p->pLeft, pValue);
111874
+ rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
111680111875
break;
111681111876
}
111682111877
case TK_UMINUS: {
111683111878
int v = 0;
111684
- if( sqlite3ExprIsInteger(p->pLeft, &v) ){
111879
+ if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
111685111880
assert( ((unsigned int)v)!=0x80000000 );
111686111881
*pValue = -v;
111687111882
rc = 1;
111688111883
}
111689111884
break;
111885
+ }
111886
+ case TK_VARIABLE: {
111887
+ sqlite3_value *pVal;
111888
+ if( pParse==0 ) break;
111889
+ if( NEVER(pParse->pVdbe==0) ) break;
111890
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
111891
+ sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
111892
+ pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
111893
+ SQLITE_AFF_BLOB);
111894
+ if( pVal ){
111895
+ if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
111896
+ sqlite3_int64 vv = sqlite3_value_int64(pVal);
111897
+ if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
111898
+ *pValue = (int)vv;
111899
+ rc = 1;
111900
+ }
111901
+ }
111902
+ sqlite3ValueFree(pVal);
111903
+ }
111904
+ break;
111690111905
}
111691111906
default: break;
111692111907
}
111693111908
return rc;
111694111909
}
@@ -112379,19 +112594,34 @@
112379112594
if( ALWAYS(pEList->nExpr==nVal) ){
112380112595
Select *pCopy;
112381112596
SelectDest dest;
112382112597
int i;
112383112598
int rc;
112599
+ int addrBloom = 0;
112384112600
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
112385112601
dest.zAffSdst = exprINAffinity(pParse, pExpr);
112386112602
pSelect->iLimit = 0;
112603
+ if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
112604
+ int regBloom = ++pParse->nMem;
112605
+ addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
112606
+ VdbeComment((v, "Bloom filter"));
112607
+ dest.iSDParm2 = regBloom;
112608
+ }
112387112609
testcase( pSelect->selFlags & SF_Distinct );
112388112610
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
112389112611
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
112390112612
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
112391112613
sqlite3SelectDelete(pParse->db, pCopy);
112392112614
sqlite3DbFree(pParse->db, dest.zAffSdst);
112615
+ if( addrBloom ){
112616
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
112617
+ if( dest.iSDParm2==0 ){
112618
+ sqlite3VdbeChangeToNoop(v, addrBloom);
112619
+ }else{
112620
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
112621
+ }
112622
+ }
112393112623
if( rc ){
112394112624
sqlite3KeyInfoUnref(pKeyInfo);
112395112625
return;
112396112626
}
112397112627
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
@@ -112830,10 +113060,19 @@
112830113060
addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
112831113061
}else{
112832113062
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
112833113063
if( destIfFalse==destIfNull ){
112834113064
/* Combine Step 3 and Step 5 into a single opcode */
113065
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
113066
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
113067
+ assert( pOp->opcode==OP_Once || pParse->nErr );
113068
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){
113069
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
113070
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
113071
+ rLhs, nVector); VdbeCoverage(v);
113072
+ }
113073
+ }
112835113074
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
112836113075
rLhs, nVector); VdbeCoverage(v);
112837113076
goto sqlite3ExprCodeIN_finished;
112838113077
}
112839113078
/* Ordinary Step 3, for the case where FALSE and NULL are distinct */
@@ -113112,17 +113351,21 @@
113112113351
/*
113113113352
** Convert a scalar expression node to a TK_REGISTER referencing
113114113353
** register iReg. The caller must ensure that iReg already contains
113115113354
** the correct value for the expression.
113116113355
*/
113117
-static void exprToRegister(Expr *pExpr, int iReg){
113356
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
113118113357
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
113119113358
if( NEVER(p==0) ) return;
113120
- p->op2 = p->op;
113121
- p->op = TK_REGISTER;
113122
- p->iTable = iReg;
113123
- ExprClearProperty(p, EP_Skip);
113359
+ if( p->op==TK_REGISTER ){
113360
+ assert( p->iTable==iReg );
113361
+ }else{
113362
+ p->op2 = p->op;
113363
+ p->op = TK_REGISTER;
113364
+ p->iTable = iReg;
113365
+ ExprClearProperty(p, EP_Skip);
113366
+ }
113124113367
}
113125113368
113126113369
/*
113127113370
** Evaluate an expression (either a vector or a scalar expression) and store
113128113371
** the result in contiguous temporary registers. Return the index of
@@ -113950,12 +114193,13 @@
113950114193
}
113951114194
case TK_COLLATE: {
113952114195
if( !ExprHasProperty(pExpr, EP_Collate) ){
113953114196
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
113954114197
** "SOFT-COLLATE" that is added to constraints that are pushed down
113955
- ** from outer queries into sub-queries by the push-down optimization.
113956
- ** Clear subtypes as subtypes may not cross a subquery boundary.
114198
+ ** from outer queries into sub-queries by the WHERE-clause push-down
114199
+ ** optimization. Clear subtypes as subtypes may not cross a subquery
114200
+ ** boundary.
113957114201
*/
113958114202
assert( pExpr->pLeft );
113959114203
sqlite3ExprCode(pParse, pExpr->pLeft, target);
113960114204
sqlite3VdbeAddOp1(v, OP_ClrSubtype, target);
113961114205
return target;
@@ -114120,11 +114364,11 @@
114120114364
if( db->mallocFailed ){
114121114365
sqlite3ExprDelete(db, pDel);
114122114366
break;
114123114367
}
114124114368
testcase( pX->op==TK_COLUMN );
114125
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114369
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114126114370
testcase( regFree1==0 );
114127114371
memset(&opCompare, 0, sizeof(opCompare));
114128114372
opCompare.op = TK_EQ;
114129114373
opCompare.pLeft = pDel;
114130114374
pTest = &opCompare;
@@ -114174,19 +114418,18 @@
114174114418
if( pExpr->affExpr==OE_Abort ){
114175114419
sqlite3MayAbort(pParse);
114176114420
}
114177114421
assert( !ExprHasProperty(pExpr, EP_IntValue) );
114178114422
if( pExpr->affExpr==OE_Ignore ){
114179
- sqlite3VdbeAddOp4(
114180
- v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
114423
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
114181114424
VdbeCoverage(v);
114182114425
}else{
114183
- sqlite3HaltConstraint(pParse,
114426
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
114427
+ sqlite3VdbeAddOp3(v, OP_Halt,
114184114428
pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
114185
- pExpr->affExpr, pExpr->u.zToken, 0, 0);
114429
+ pExpr->affExpr, r1);
114186114430
}
114187
-
114188114431
break;
114189114432
}
114190114433
#endif
114191114434
}
114192114435
sqlite3ReleaseTempReg(pParse, regFree1);
@@ -114471,11 +114714,11 @@
114471114714
compLeft.pLeft = pDel;
114472114715
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
114473114716
compRight.op = TK_LE;
114474114717
compRight.pLeft = pDel;
114475114718
compRight.pRight = pExpr->x.pList->a[1].pExpr;
114476
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114719
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114477114720
if( xJump ){
114478114721
xJump(pParse, &exprAnd, dest, jumpIfNull);
114479114722
}else{
114480114723
/* Mark the expression is being from the ON or USING clause of a join
114481114724
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
@@ -115549,24 +115792,22 @@
115549115792
if( pExpr->op!=TK_AGG_FUNCTION ){
115550115793
if( iAgg<pAggInfo->nColumn
115551115794
&& pAggInfo->aCol[iAgg].pCExpr==pExpr
115552115795
){
115553115796
pExpr = sqlite3ExprDup(db, pExpr, 0);
115554
- if( pExpr ){
115797
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
115555115798
pAggInfo->aCol[iAgg].pCExpr = pExpr;
115556
- sqlite3ExprDeferredDelete(pParse, pExpr);
115557115799
}
115558115800
}
115559115801
}else{
115560115802
assert( pExpr->op==TK_AGG_FUNCTION );
115561115803
if( ALWAYS(iAgg<pAggInfo->nFunc)
115562115804
&& pAggInfo->aFunc[iAgg].pFExpr==pExpr
115563115805
){
115564115806
pExpr = sqlite3ExprDup(db, pExpr, 0);
115565
- if( pExpr ){
115807
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
115566115808
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
115567
- sqlite3ExprDeferredDelete(pParse, pExpr);
115568115809
}
115569115810
}
115570115811
}
115571115812
}
115572115813
return WRC_Continue;
@@ -124153,13 +124394,10 @@
124153124394
if( p->tabFlags & TF_HasGenerated ){
124154124395
sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
124155124396
sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
124156124397
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
124157124398
}
124158
- sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
124159
- sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)",
124160
- db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
124161124399
}
124162124400
124163124401
/* Add the table to the in-memory representation of the database.
124164124402
*/
124165124403
if( db->init.busy ){
@@ -124293,12 +124531,13 @@
124293124531
#endif /* SQLITE_OMIT_VIEW */
124294124532
124295124533
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
124296124534
/*
124297124535
** The Table structure pTable is really a VIEW. Fill in the names of
124298
-** the columns of the view in the pTable structure. Return the number
124299
-** of errors. If an error is seen leave an error message in pParse->zErrMsg.
124536
+** the columns of the view in the pTable structure. Return non-zero if
124537
+** there are errors. If an error is seen an error message is left
124538
+** in pParse->zErrMsg.
124300124539
*/
124301124540
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
124302124541
Table *pSelTab; /* A fake table from which we get the result set */
124303124542
Select *pSel; /* Copy of the SELECT that implements the view */
124304124543
int nErr = 0; /* Number of errors encountered */
@@ -124417,11 +124656,11 @@
124417124656
pTable->pSchema->schemaFlags |= DB_UnresetViews;
124418124657
if( db->mallocFailed ){
124419124658
sqlite3DeleteColumnNames(db, pTable);
124420124659
}
124421124660
#endif /* SQLITE_OMIT_VIEW */
124422
- return nErr;
124661
+ return nErr + pParse->nErr;
124423124662
}
124424124663
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
124425124664
assert( pTable!=0 );
124426124665
if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0;
124427124666
return viewGetColumnNames(pParse, pTable);
@@ -130715,10 +130954,12 @@
130715130954
StrAccum *pAccum = &pGCC->str;
130716130955
if( pAccum->accError==SQLITE_TOOBIG ){
130717130956
sqlite3_result_error_toobig(context);
130718130957
}else if( pAccum->accError==SQLITE_NOMEM ){
130719130958
sqlite3_result_error_nomem(context);
130959
+ }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
130960
+ sqlite3_result_text(context, "", 1, SQLITE_STATIC);
130720130961
}else{
130721130962
const char *zText = sqlite3_str_value(pAccum);
130722130963
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
130723130964
}
130724130965
}
@@ -131054,10 +131295,11 @@
131054131295
UNUSED_PARAMETER(argc);
131055131296
assert( argc==3 );
131056131297
x = sqlite3_value_double(argv[0]);
131057131298
y = sqlite3_value_int(argv[1]);
131058131299
z = sqlite3_value_int(argv[2]);
131300
+ if( z<=0 ) z = 1;
131059131301
sqlite3FpDecode(&s, x, y, z);
131060131302
if( s.isSpecial==2 ){
131061131303
sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
131062131304
}else{
131063131305
sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP);
@@ -132595,11 +132837,12 @@
132595132837
if( action==OE_Restrict ){
132596132838
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
132597132839
SrcList *pSrc;
132598132840
Expr *pRaise;
132599132841
132600
- pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
132842
+ pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
132843
+ pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
132601132844
if( pRaise ){
132602132845
pRaise->affExpr = OE_Abort;
132603132846
}
132604132847
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
132605132848
if( pSrc ){
@@ -135934,11 +136177,14 @@
135934136177
** further downstream. */
135935136178
return 0; /* Corrupt schema - two indexes on the same btree */
135936136179
}
135937136180
}
135938136181
#ifndef SQLITE_OMIT_CHECK
135939
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
136182
+ if( pDest->pCheck
136183
+ && (db->mDbFlags & DBFLAG_Vacuum)==0
136184
+ && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
136185
+ ){
135940136186
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
135941136187
}
135942136188
#endif
135943136189
#ifndef SQLITE_OMIT_FOREIGN_KEY
135944136190
/* Disallow the transfer optimization if the destination table contains
@@ -140282,11 +140528,11 @@
140282140528
pParse->nMem = 6;
140283140529
140284140530
/* Set the maximum error count */
140285140531
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140286140532
if( zRight ){
140287
- if( sqlite3GetInt32(zRight, &mxErr) ){
140533
+ if( sqlite3GetInt32(pValue->z, &mxErr) ){
140288140534
if( mxErr<=0 ){
140289140535
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140290140536
}
140291140537
}else{
140292140538
pObjTab = sqlite3LocateTable(pParse, 0, zRight,
@@ -141490,10 +141736,11 @@
141490141736
/* Clear all content from pragma virtual table cursor. */
141491141737
static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
141492141738
int i;
141493141739
sqlite3_finalize(pCsr->pPragma);
141494141740
pCsr->pPragma = 0;
141741
+ pCsr->iRowid = 0;
141495141742
for(i=0; i<ArraySize(pCsr->azArg); i++){
141496141743
sqlite3_free(pCsr->azArg[i]);
141497141744
pCsr->azArg[i] = 0;
141498141745
}
141499141746
}
@@ -142290,11 +142537,17 @@
142290142537
SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
142291142538
Parse *pParse, /* Destroy when this Parser finishes */
142292142539
void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
142293142540
void *pPtr /* Pointer to object to be cleaned up */
142294142541
){
142295
- ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
142542
+ ParseCleanup *pCleanup;
142543
+ if( sqlite3FaultSim(300) ){
142544
+ pCleanup = 0;
142545
+ sqlite3OomFault(pParse->db);
142546
+ }else{
142547
+ pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
142548
+ }
142296142549
if( pCleanup ){
142297142550
pCleanup->pNext = pParse->pCleanup;
142298142551
pParse->pCleanup = pCleanup;
142299142552
pCleanup->pPtr = pPtr;
142300142553
pCleanup->xCleanup = xCleanup;
@@ -144116,16 +144369,22 @@
144116144369
** ORDER BY in this case since the order of entries in the set
144117144370
** does not matter. But there might be a LIMIT clause, in which
144118144371
** case the order does matter */
144119144372
pushOntoSorter(
144120144373
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
144374
+ pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
144121144375
}else{
144122144376
int r1 = sqlite3GetTempReg(pParse);
144123144377
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
144124144378
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
144125144379
r1, pDest->zAffSdst, nResultCol);
144126144380
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
144381
+ if( pDest->iSDParm2 ){
144382
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
144383
+ regResult, nResultCol);
144384
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
144385
+ }
144127144386
sqlite3ReleaseTempReg(pParse, r1);
144128144387
}
144129144388
break;
144130144389
}
144131144390
@@ -145063,12 +145322,11 @@
145063145322
Expr *p;
145064145323
struct ExprList_item *a;
145065145324
NameContext sNC;
145066145325
145067145326
assert( pSelect!=0 );
145068
- testcase( (pSelect->selFlags & SF_Resolved)==0 );
145069
- assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT );
145327
+ assert( (pSelect->selFlags & SF_Resolved)!=0 );
145070145328
assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
145071145329
assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
145072145330
if( db->mallocFailed || IN_RENAME_OBJECT ) return;
145073145331
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
145074145332
a = pSelect->pEList->a;
@@ -145075,21 +145333,26 @@
145075145333
memset(&sNC, 0, sizeof(sNC));
145076145334
sNC.pSrcList = pSelect->pSrc;
145077145335
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
145078145336
const char *zType;
145079145337
i64 n;
145338
+ int m = 0;
145339
+ Select *pS2 = pSelect;
145080145340
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
145081145341
p = a[i].pExpr;
145082145342
/* pCol->szEst = ... // Column size est for SELECT tables never used */
145083145343
pCol->affinity = sqlite3ExprAffinity(p);
145344
+ while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
145345
+ m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
145346
+ pS2 = pS2->pNext;
145347
+ pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
145348
+ }
145084145349
if( pCol->affinity<=SQLITE_AFF_NONE ){
145085145350
pCol->affinity = aff;
145086145351
}
145087
- if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
145088
- int m = 0;
145089
- Select *pS2;
145090
- for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
145352
+ if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
145353
+ for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
145091145354
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
145092145355
}
145093145356
if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
145094145357
pCol->affinity = SQLITE_AFF_BLOB;
145095145358
}else
@@ -145115,16 +145378,16 @@
145115145378
}
145116145379
}
145117145380
}
145118145381
}
145119145382
if( zType ){
145120
- i64 m = sqlite3Strlen30(zType);
145383
+ const i64 k = sqlite3Strlen30(zType);
145121145384
n = sqlite3Strlen30(pCol->zCnName);
145122
- pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
145385
+ pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2);
145123145386
pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
145124145387
if( pCol->zCnName ){
145125
- memcpy(&pCol->zCnName[n+1], zType, m+1);
145388
+ memcpy(&pCol->zCnName[n+1], zType, k+1);
145126145389
pCol->colFlags |= COLFLAG_HASTYPE;
145127145390
}
145128145391
}
145129145392
pColl = sqlite3ExprCollSeq(pParse, p);
145130145393
if( pColl ){
@@ -145227,11 +145490,11 @@
145227145490
assert( pLimit->op==TK_LIMIT );
145228145491
assert( pLimit->pLeft!=0 );
145229145492
p->iLimit = iLimit = ++pParse->nMem;
145230145493
v = sqlite3GetVdbe(pParse);
145231145494
assert( v!=0 );
145232
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
145495
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
145233145496
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
145234145497
VdbeComment((v, "LIMIT counter"));
145235145498
if( n==0 ){
145236145499
sqlite3VdbeGoto(v, iBreak);
145237145500
}else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
@@ -145707,11 +145970,11 @@
145707145970
testcase( rc!=SQLITE_OK );
145708145971
pDelete = p->pPrior;
145709145972
p->pPrior = pPrior;
145710145973
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
145711145974
if( p->pLimit
145712
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
145975
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
145713145976
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
145714145977
){
145715145978
p->nSelectRow = sqlite3LogEst((u64)nLimit);
145716145979
}
145717145980
if( addr ){
@@ -146051,10 +146314,15 @@
146051146314
r1 = sqlite3GetTempReg(pParse);
146052146315
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
146053146316
r1, pDest->zAffSdst, pIn->nSdst);
146054146317
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
146055146318
pIn->iSdst, pIn->nSdst);
146319
+ if( pDest->iSDParm2>0 ){
146320
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
146321
+ pIn->iSdst, pIn->nSdst);
146322
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
146323
+ }
146056146324
sqlite3ReleaseTempReg(pParse, r1);
146057146325
break;
146058146326
}
146059146327
146060146328
/* If this is a scalar select that is part of an expression, then
@@ -147798,10 +148066,22 @@
147798148066
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
147799148067
** WHERE x=5 AND y=10;
147800148068
**
147801148069
** The hope is that the terms added to the inner query will make it more
147802148070
** efficient.
148071
+**
148072
+** NAME AMBIGUITY
148073
+**
148074
+** This optimization is called the "WHERE-clause push-down optimization".
148075
+**
148076
+** Do not confuse this optimization with another unrelated optimization
148077
+** with a similar name: The "MySQL push-down optimization" causes WHERE
148078
+** clause terms that can be evaluated using only the index and without
148079
+** reference to the table are run first, so that if they are false,
148080
+** unnecessary table seeks are avoided.
148081
+**
148082
+** RULES
147803148083
**
147804148084
** Do not attempt this optimization if:
147805148085
**
147806148086
** (1) (** This restriction was removed on 2017-09-29. We used to
147807148087
** disallow this optimization for aggregate subqueries, but now
@@ -147864,14 +148144,14 @@
147864148144
** (9b) The subquery is to the right of the ON/USING clause
147865148145
**
147866148146
** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
147867148147
** clause and the subquery.
147868148148
**
147869
-** Without this restriction, the push-down optimization might move
147870
-** the ON/USING filter expression from the left side of a RIGHT JOIN
147871
-** over to the right side, which leads to incorrect answers. See
147872
-** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
148149
+** Without this restriction, the WHERE-clause push-down optimization
148150
+** might move the ON/USING filter expression from the left side of a
148151
+** RIGHT JOIN over to the right side, which leads to incorrect answers.
148152
+** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
147873148153
**
147874148154
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
147875148155
**
147876148156
** (11) The subquery is not a VALUES clause
147877148157
**
@@ -147999,11 +148279,11 @@
147999148279
return 0; /* Restriction (12) */
148000148280
}
148001148281
}
148002148282
#endif
148003148283
148004
- if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
148284
+ if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
148005148285
nChng++;
148006148286
pSubq->selFlags |= SF_PushDown;
148007148287
while( pSubq ){
148008148288
SubstContext x;
148009148289
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -149134,12 +149414,11 @@
149134149414
SrcItem *pFrom;
149135149415
149136149416
if( p->selFlags & SF_HasTypeInfo ) return;
149137149417
p->selFlags |= SF_HasTypeInfo;
149138149418
pParse = pWalker->pParse;
149139
- testcase( (p->selFlags & SF_Resolved)==0 );
149140
- assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT );
149419
+ assert( (p->selFlags & SF_Resolved) );
149141149420
pTabList = p->pSrc;
149142149421
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
149143149422
Table *pTab = pFrom->pTab;
149144149423
assert( pTab!=0 );
149145149424
if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
@@ -150259,17 +150538,20 @@
150259150538
** (5) The ORDER BY isn't going to accomplish anything because
150260150539
** one of:
150261150540
** (a) The outer query has a different ORDER BY clause
150262150541
** (b) The subquery is part of a join
150263150542
** See forum post 062d576715d277c8
150543
+ ** (6) The subquery is not a recursive CTE. ORDER BY has a different
150544
+ ** meaning for recursive CTEs and this optimization does not
150545
+ ** apply.
150264150546
**
150265150547
** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
150266150548
*/
150267150549
if( pSub->pOrderBy!=0
150268150550
&& (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
150269150551
&& pSub->pLimit==0 /* Condition (1) */
150270
- && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
150552
+ && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */
150271150553
&& (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
150272150554
&& OptimizationEnabled(db, SQLITE_OmitOrderBy)
150273150555
){
150274150556
TREETRACE(0x800,pParse,p,
150275150557
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
@@ -150428,11 +150710,11 @@
150428150710
sqlite3TreeViewSelect(0, p, 0);
150429150711
}
150430150712
#endif
150431150713
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
150432150714
}else{
150433
- TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
150715
+ TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
150434150716
}
150435150717
150436150718
/* Convert unused result columns of the subquery into simple NULL
150437150719
** expressions, to avoid unneeded searching and computation.
150438150720
*/
@@ -150571,16 +150853,22 @@
150571150853
** written the query must use a temp-table for at least one of the ORDER
150572150854
** BY and DISTINCT, and an index or separate temp-table for the other.
150573150855
*/
150574150856
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
150575150857
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
150858
+ && OptimizationEnabled(db, SQLITE_GroupByOrder)
150576150859
#ifndef SQLITE_OMIT_WINDOWFUNC
150577150860
&& p->pWin==0
150578150861
#endif
150579150862
){
150580150863
p->selFlags &= ~SF_Distinct;
150581150864
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
150865
+ if( pGroupBy ){
150866
+ for(i=0; i<pGroupBy->nExpr; i++){
150867
+ pGroupBy->a[i].u.x.iOrderByCol = i+1;
150868
+ }
150869
+ }
150582150870
p->selFlags |= SF_Aggregate;
150583150871
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
150584150872
** the sDistinct.isTnct is still set. Hence, isTnct represents the
150585150873
** original setting of the SF_Distinct flag, not the current setting */
150586150874
assert( sDistinct.isTnct );
@@ -151039,16 +151327,29 @@
151039151327
if( groupBySort ){
151040151328
sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
151041151329
sortOut, sortPTab);
151042151330
}
151043151331
for(j=0; j<pGroupBy->nExpr; j++){
151332
+ int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
151333
+
151044151334
if( groupBySort ){
151045151335
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
151046151336
}else{
151047151337
pAggInfo->directMode = 1;
151048151338
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
151049151339
}
151340
+
151341
+ if( iOrderByCol ){
151342
+ Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
151343
+ Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
151344
+ if( ALWAYS(pBase!=0)
151345
+ && pBase->op!=TK_AGG_COLUMN
151346
+ && pBase->op!=TK_REGISTER
151347
+ ){
151348
+ sqlite3ExprToRegister(pX, iAMem+j);
151349
+ }
151350
+ }
151050151351
}
151051151352
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
151052151353
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
151053151354
addr1 = sqlite3VdbeCurrentAddr(v);
151054151355
sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
@@ -151060,13 +151361,13 @@
151060151361
** This code copies current group by terms in b0,b1,b2,...
151061151362
** over to a0,a1,a2. It then calls the output subroutine
151062151363
** and resets the aggregate accumulator registers in preparation
151063151364
** for the next GROUP BY batch.
151064151365
*/
151065
- sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
151066151366
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
151067151367
VdbeComment((v, "output one row"));
151368
+ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
151068151369
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
151069151370
VdbeComment((v, "check abort flag"));
151070151371
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
151071151372
VdbeComment((v, "reset accumulator"));
151072151373
@@ -152495,10 +152796,76 @@
152495152796
}
152496152797
}
152497152798
}
152498152799
return pNew;
152499152800
}
152801
+
152802
+/* If the Expr node is a subquery or an EXISTS operator or an IN operator that
152803
+** uses a subquery, and if the subquery is SF_Correlated, then mark the
152804
+** expression as EP_VarSelect.
152805
+*/
152806
+static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){
152807
+ UNUSED_PARAMETER(NotUsed);
152808
+ if( ExprUseXSelect(pExpr)
152809
+ && (pExpr->x.pSelect->selFlags & SF_Correlated)!=0
152810
+ ){
152811
+ testcase( ExprHasProperty(pExpr, EP_VarSelect) );
152812
+ ExprSetProperty(pExpr, EP_VarSelect);
152813
+ }
152814
+ return WRC_Continue;
152815
+}
152816
+
152817
+
152818
+/*
152819
+** If the SELECT references the table pWalker->u.pTab, then do two things:
152820
+**
152821
+** (1) Mark the SELECT as as SF_Correlated.
152822
+** (2) Set pWalker->eCode to non-zero so that the caller will know
152823
+** that (1) has happened.
152824
+*/
152825
+static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
152826
+ int i;
152827
+ SrcList *pSrc;
152828
+ assert( pSelect!=0 );
152829
+ pSrc = pSelect->pSrc;
152830
+ assert( pSrc!=0 );
152831
+ for(i=0; i<pSrc->nSrc; i++){
152832
+ if( pSrc->a[i].pTab==pWalker->u.pTab ){
152833
+ testcase( pSelect->selFlags & SF_Correlated );
152834
+ pSelect->selFlags |= SF_Correlated;
152835
+ pWalker->eCode = 1;
152836
+ break;
152837
+ }
152838
+ }
152839
+ return WRC_Continue;
152840
+}
152841
+
152842
+/*
152843
+** Scan the expression list that is the argument to RETURNING looking
152844
+** for subqueries that depend on the table which is being modified in the
152845
+** statement that is hosting the RETURNING clause (pTab). Mark all such
152846
+** subqueries as SF_Correlated. If the subqueries are part of an
152847
+** expression, mark the expression as EP_VarSelect.
152848
+**
152849
+** https://sqlite.org/forum/forumpost/2c83569ce8945d39
152850
+*/
152851
+static void sqlite3ProcessReturningSubqueries(
152852
+ ExprList *pEList,
152853
+ Table *pTab
152854
+){
152855
+ Walker w;
152856
+ memset(&w, 0, sizeof(w));
152857
+ w.xExprCallback = sqlite3ExprWalkNoop;
152858
+ w.xSelectCallback = sqlite3ReturningSubqueryCorrelated;
152859
+ w.u.pTab = pTab;
152860
+ sqlite3WalkExprList(&w, pEList);
152861
+ if( w.eCode ){
152862
+ w.xExprCallback = sqlite3ReturningSubqueryVarSelect;
152863
+ w.xSelectCallback = sqlite3SelectWalkNoop;
152864
+ sqlite3WalkExprList(&w, pEList);
152865
+ }
152866
+}
152500152867
152501152868
/*
152502152869
** Generate code for the RETURNING trigger. Unlike other triggers
152503152870
** that invoke a subprogram in the bytecode, the code for RETURNING
152504152871
** is generated in-line.
@@ -152532,10 +152899,11 @@
152532152899
memset(&sFrom, 0, sizeof(sFrom));
152533152900
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
152534152901
sSelect.pSrc = &sFrom;
152535152902
sFrom.nSrc = 1;
152536152903
sFrom.a[0].pTab = pTab;
152904
+ sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
152537152905
sFrom.a[0].iCursor = -1;
152538152906
sqlite3SelectPrep(pParse, &sSelect, 0);
152539152907
if( pParse->nErr==0 ){
152540152908
assert( db->mallocFailed==0 );
152541152909
sqlite3GenerateColumnNames(pParse, &sSelect);
@@ -152558,10 +152926,11 @@
152558152926
&& ALWAYS(!db->mallocFailed)
152559152927
){
152560152928
int i;
152561152929
int nCol = pNew->nExpr;
152562152930
int reg = pParse->nMem+1;
152931
+ sqlite3ProcessReturningSubqueries(pNew, pTab);
152563152932
pParse->nMem += nCol+2;
152564152933
pReturning->iRetReg = reg;
152565152934
for(i=0; i<nCol; i++){
152566152935
Expr *pCol = pNew->a[i].pExpr;
152567152936
assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
@@ -153959,10 +154328,13 @@
153959154328
}else{
153960154329
sqlite3VdbeAddOp2(v, OP_Null, 0, k);
153961154330
}
153962154331
}
153963154332
if( chngRowid==0 && pPk==0 ){
154333
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
154334
+ if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
154335
+#endif
153964154336
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
153965154337
}
153966154338
}
153967154339
153968154340
/* Populate the array of registers beginning at regNew with the new
@@ -155985,11 +156357,14 @@
155985156357
*/
155986156358
z = (const unsigned char*)zCreateTable;
155987156359
for(i=0; aKeyword[i]; i++){
155988156360
int tokenType = 0;
155989156361
do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
155990
- if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT;
156362
+ if( tokenType!=aKeyword[i] ){
156363
+ sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
156364
+ return SQLITE_ERROR;
156365
+ }
155991156366
}
155992156367
155993156368
sqlite3_mutex_enter(db->mutex);
155994156369
pCtx = db->pVtabCtx;
155995156370
if( !pCtx || pCtx->bDeclared ){
@@ -156709,10 +157084,12 @@
156709157084
u16 nLTerm; /* Number of entries in aLTerm[] */
156710157085
u16 nSkip; /* Number of NULL aLTerm[] entries */
156711157086
/**** whereLoopXfer() copies fields above ***********************/
156712157087
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
156713157088
u16 nLSlot; /* Number of slots allocated for aLTerm[] */
157089
+ LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not
157090
+ ** initialized unless pWInfo->nOutStarDelta>0 */
156714157091
WhereTerm **aLTerm; /* WhereTerms used */
156715157092
WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
156716157093
WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
156717157094
};
156718157095
@@ -157031,10 +157408,11 @@
157031157408
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
157032157409
unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
157033157410
unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
157034157411
unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
157035157412
unsigned sorted :1; /* True if really sorted (not just grouped) */
157413
+ LogEst nOutStarDelta; /* Artifical nOut reduction for star-query */
157036157414
LogEst nRowOut; /* Estimated number of output rows */
157037157415
int iTop; /* The very beginning of the WHERE loop */
157038157416
int iEndWhere; /* End of the WHERE clause itself */
157039157417
WhereLoop *pLoops; /* List of all WhereLoop objects */
157040157418
WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
@@ -157388,11 +157766,12 @@
157388157766
}
157389157767
#endif
157390157768
zMsg = sqlite3StrAccumFinish(&str);
157391157769
sqlite3ExplainBreakpoint("",zMsg);
157392157770
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
157393
- pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
157771
+ pParse->addrExplain, pLoop->rRun,
157772
+ zMsg, P4_DYNAMIC);
157394157773
}
157395157774
return ret;
157396157775
}
157397157776
157398157777
/*
@@ -157630,10 +158009,43 @@
157630158009
zAff[i] = SQLITE_AFF_BLOB;
157631158010
}
157632158011
}
157633158012
}
157634158013
158014
+/*
158015
+** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
158016
+** columns might have been rearranged in the result set. This routine
158017
+** fixes them up.
158018
+**
158019
+** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values
158020
+** contain the *old* locations of each expression. This is a temporary
158021
+** use of u.x.iOrderByCol, not its intended use. The caller must reset
158022
+** u.x.iOrderByCol back to zero for all entries in pEList before the
158023
+** caller returns.
158024
+**
158025
+** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
158026
+** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based
158027
+** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero.
158028
+*/
158029
+static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
158030
+ int i, j;
158031
+ if( pOrderBy==0 ) return;
158032
+ for(i=0; i<pOrderBy->nExpr; i++){
158033
+ int t = pOrderBy->a[i].u.x.iOrderByCol;
158034
+ if( t==0 ) continue;
158035
+ for(j=0; j<pEList->nExpr; j++){
158036
+ if( pEList->a[j].u.x.iOrderByCol==t ){
158037
+ pOrderBy->a[i].u.x.iOrderByCol = j+1;
158038
+ break;
158039
+ }
158040
+ }
158041
+ if( j>=pEList->nExpr ){
158042
+ pOrderBy->a[i].u.x.iOrderByCol = 0;
158043
+ }
158044
+ }
158045
+}
158046
+
157635158047
157636158048
/*
157637158049
** pX is an expression of the form: (vector) IN (SELECT ...)
157638158050
** In other words, it is a vector IN operator with a SELECT clause on the
157639158051
** LHS. But not all terms in the vector are indexable and the terms might
@@ -157693,10 +158105,11 @@
157693158105
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
157694158106
iField = pLoop->aLTerm[i]->u.x.iField - 1;
157695158107
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
157696158108
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
157697158109
pOrigRhs->a[iField].pExpr = 0;
158110
+ if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
157698158111
if( pOrigLhs ){
157699158112
assert( pOrigLhs->a[iField].pExpr!=0 );
157700158113
pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
157701158114
pOrigLhs->a[iField].pExpr = 0;
157702158115
}
@@ -157715,22 +158128,20 @@
157715158128
Expr *p = pLhs->a[0].pExpr;
157716158129
pLhs->a[0].pExpr = 0;
157717158130
sqlite3ExprDelete(db, pNew->pLeft);
157718158131
pNew->pLeft = p;
157719158132
}
157720
- if( pSelect->pOrderBy ){
157721
- /* If the SELECT statement has an ORDER BY clause, zero the
157722
- ** iOrderByCol variables. These are set to non-zero when an
157723
- ** ORDER BY term exactly matches one of the terms of the
157724
- ** result-set. Since the result-set of the SELECT statement may
157725
- ** have been modified or reordered, these variables are no longer
157726
- ** set correctly. Since setting them is just an optimization,
157727
- ** it's easiest just to zero them here. */
157728
- ExprList *pOrderBy = pSelect->pOrderBy;
157729
- for(i=0; i<pOrderBy->nExpr; i++){
157730
- pOrderBy->a[i].u.x.iOrderByCol = 0;
157731
- }
158133
+
158134
+ /* If either the ORDER BY clause or the GROUP BY clause contains
158135
+ ** references to result-set columns, those references might now be
158136
+ ** obsolete. So fix them up.
158137
+ */
158138
+ assert( pRhs!=0 || db->mallocFailed );
158139
+ if( pRhs ){
158140
+ adjustOrderByCol(pSelect->pOrderBy, pRhs);
158141
+ adjustOrderByCol(pSelect->pGroupBy, pRhs);
158142
+ for(i=0; i<pRhs->nExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
157732158143
}
157733158144
157734158145
#if 0
157735158146
printf("For indexing, change the IN expr:\n");
157736158147
sqlite3TreeViewExpr(0, pX, 0);
@@ -157740,10 +158151,151 @@
157740158151
}
157741158152
}
157742158153
return pNew;
157743158154
}
157744158155
158156
+
158157
+#ifndef SQLITE_OMIT_SUBQUERY
158158
+/*
158159
+** Generate code for a single X IN (....) term of the WHERE clause.
158160
+**
158161
+** This is a special-case of codeEqualityTerm() that works for IN operators
158162
+** only. It is broken out into a subroutine because this case is
158163
+** uncommon and by splitting it off into a subroutine, the common case
158164
+** runs faster.
158165
+**
158166
+** The current value for the constraint is left in register iTarget.
158167
+** This routine sets up a loop that will iterate over all values of X.
158168
+*/
158169
+static SQLITE_NOINLINE void codeINTerm(
158170
+ Parse *pParse, /* The parsing context */
158171
+ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
158172
+ WhereLevel *pLevel, /* The level of the FROM clause we are working on */
158173
+ int iEq, /* Index of the equality term within this level */
158174
+ int bRev, /* True for reverse-order IN operations */
158175
+ int iTarget /* Attempt to leave results in this register */
158176
+){
158177
+ Expr *pX = pTerm->pExpr;
158178
+ int eType = IN_INDEX_NOOP;
158179
+ int iTab;
158180
+ struct InLoop *pIn;
158181
+ WhereLoop *pLoop = pLevel->pWLoop;
158182
+ Vdbe *v = pParse->pVdbe;
158183
+ int i;
158184
+ int nEq = 0;
158185
+ int *aiMap = 0;
158186
+
158187
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
158188
+ && pLoop->u.btree.pIndex!=0
158189
+ && pLoop->u.btree.pIndex->aSortOrder[iEq]
158190
+ ){
158191
+ testcase( iEq==0 );
158192
+ testcase( bRev );
158193
+ bRev = !bRev;
158194
+ }
158195
+ assert( pX->op==TK_IN );
158196
+
158197
+ for(i=0; i<iEq; i++){
158198
+ if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
158199
+ disableTerm(pLevel, pTerm);
158200
+ return;
158201
+ }
158202
+ }
158203
+ for(i=iEq;i<pLoop->nLTerm; i++){
158204
+ assert( pLoop->aLTerm[i]!=0 );
158205
+ if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
158206
+ }
158207
+
158208
+ iTab = 0;
158209
+ if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
158210
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
158211
+ }else{
158212
+ Expr *pExpr = pTerm->pExpr;
158213
+ if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
158214
+ sqlite3 *db = pParse->db;
158215
+ pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
158216
+ if( !db->mallocFailed ){
158217
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
158218
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
158219
+ pExpr->iTable = iTab;
158220
+ }
158221
+ sqlite3ExprDelete(db, pX);
158222
+ }else{
158223
+ int n = sqlite3ExprVectorSize(pX->pLeft);
158224
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
158225
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
158226
+ }
158227
+ pX = pExpr;
158228
+ }
158229
+
158230
+ if( eType==IN_INDEX_INDEX_DESC ){
158231
+ testcase( bRev );
158232
+ bRev = !bRev;
158233
+ }
158234
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
158235
+ VdbeCoverageIf(v, bRev);
158236
+ VdbeCoverageIf(v, !bRev);
158237
+
158238
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
158239
+ pLoop->wsFlags |= WHERE_IN_ABLE;
158240
+ if( pLevel->u.in.nIn==0 ){
158241
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
158242
+ }
158243
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
158244
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
158245
+ }
158246
+
158247
+ i = pLevel->u.in.nIn;
158248
+ pLevel->u.in.nIn += nEq;
158249
+ pLevel->u.in.aInLoop =
158250
+ sqlite3WhereRealloc(pTerm->pWC->pWInfo,
158251
+ pLevel->u.in.aInLoop,
158252
+ sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
158253
+ pIn = pLevel->u.in.aInLoop;
158254
+ if( pIn ){
158255
+ int iMap = 0; /* Index in aiMap[] */
158256
+ pIn += i;
158257
+ for(i=iEq;i<pLoop->nLTerm; i++){
158258
+ if( pLoop->aLTerm[i]->pExpr==pX ){
158259
+ int iOut = iTarget + i - iEq;
158260
+ if( eType==IN_INDEX_ROWID ){
158261
+ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
158262
+ }else{
158263
+ int iCol = aiMap ? aiMap[iMap++] : 0;
158264
+ pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
158265
+ }
158266
+ sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
158267
+ if( i==iEq ){
158268
+ pIn->iCur = iTab;
158269
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
158270
+ if( iEq>0 ){
158271
+ pIn->iBase = iTarget - i;
158272
+ pIn->nPrefix = i;
158273
+ }else{
158274
+ pIn->nPrefix = 0;
158275
+ }
158276
+ }else{
158277
+ pIn->eEndLoopOp = OP_Noop;
158278
+ }
158279
+ pIn++;
158280
+ }
158281
+ }
158282
+ testcase( iEq>0
158283
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
158284
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
158285
+ if( iEq>0
158286
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
158287
+ ){
158288
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
158289
+ }
158290
+ }else{
158291
+ pLevel->u.in.nIn = 0;
158292
+ }
158293
+ sqlite3DbFree(pParse->db, aiMap);
158294
+}
158295
+#endif
158296
+
157745158297
157746158298
/*
157747158299
** Generate code for a single equality term of the WHERE clause. An equality
157748158300
** term can be either X=expr or X IN (...). pTerm is the term to be
157749158301
** coded.
@@ -157765,138 +158317,24 @@
157765158317
int iEq, /* Index of the equality term within this level */
157766158318
int bRev, /* True for reverse-order IN operations */
157767158319
int iTarget /* Attempt to leave results in this register */
157768158320
){
157769158321
Expr *pX = pTerm->pExpr;
157770
- Vdbe *v = pParse->pVdbe;
157771158322
int iReg; /* Register holding results */
157772158323
157773158324
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
157774158325
assert( iTarget>0 );
157775158326
if( pX->op==TK_EQ || pX->op==TK_IS ){
157776158327
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
157777158328
}else if( pX->op==TK_ISNULL ){
157778158329
iReg = iTarget;
157779
- sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
158330
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
157780158331
#ifndef SQLITE_OMIT_SUBQUERY
157781158332
}else{
157782
- int eType = IN_INDEX_NOOP;
157783
- int iTab;
157784
- struct InLoop *pIn;
157785
- WhereLoop *pLoop = pLevel->pWLoop;
157786
- int i;
157787
- int nEq = 0;
157788
- int *aiMap = 0;
157789
-
157790
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
157791
- && pLoop->u.btree.pIndex!=0
157792
- && pLoop->u.btree.pIndex->aSortOrder[iEq]
157793
- ){
157794
- testcase( iEq==0 );
157795
- testcase( bRev );
157796
- bRev = !bRev;
157797
- }
157798158333
assert( pX->op==TK_IN );
157799158334
iReg = iTarget;
157800
-
157801
- for(i=0; i<iEq; i++){
157802
- if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
157803
- disableTerm(pLevel, pTerm);
157804
- return iTarget;
157805
- }
157806
- }
157807
- for(i=iEq;i<pLoop->nLTerm; i++){
157808
- assert( pLoop->aLTerm[i]!=0 );
157809
- if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
157810
- }
157811
-
157812
- iTab = 0;
157813
- if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
157814
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
157815
- }else{
157816
- Expr *pExpr = pTerm->pExpr;
157817
- if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
157818
- sqlite3 *db = pParse->db;
157819
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
157820
- if( !db->mallocFailed ){
157821
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
157822
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
157823
- pExpr->iTable = iTab;
157824
- }
157825
- sqlite3ExprDelete(db, pX);
157826
- }else{
157827
- int n = sqlite3ExprVectorSize(pX->pLeft);
157828
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
157829
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
157830
- }
157831
- pX = pExpr;
157832
- }
157833
-
157834
- if( eType==IN_INDEX_INDEX_DESC ){
157835
- testcase( bRev );
157836
- bRev = !bRev;
157837
- }
157838
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
157839
- VdbeCoverageIf(v, bRev);
157840
- VdbeCoverageIf(v, !bRev);
157841
-
157842
- assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
157843
- pLoop->wsFlags |= WHERE_IN_ABLE;
157844
- if( pLevel->u.in.nIn==0 ){
157845
- pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
157846
- }
157847
- if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
157848
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
157849
- }
157850
-
157851
- i = pLevel->u.in.nIn;
157852
- pLevel->u.in.nIn += nEq;
157853
- pLevel->u.in.aInLoop =
157854
- sqlite3WhereRealloc(pTerm->pWC->pWInfo,
157855
- pLevel->u.in.aInLoop,
157856
- sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
157857
- pIn = pLevel->u.in.aInLoop;
157858
- if( pIn ){
157859
- int iMap = 0; /* Index in aiMap[] */
157860
- pIn += i;
157861
- for(i=iEq;i<pLoop->nLTerm; i++){
157862
- if( pLoop->aLTerm[i]->pExpr==pX ){
157863
- int iOut = iReg + i - iEq;
157864
- if( eType==IN_INDEX_ROWID ){
157865
- pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
157866
- }else{
157867
- int iCol = aiMap ? aiMap[iMap++] : 0;
157868
- pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
157869
- }
157870
- sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
157871
- if( i==iEq ){
157872
- pIn->iCur = iTab;
157873
- pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
157874
- if( iEq>0 ){
157875
- pIn->iBase = iReg - i;
157876
- pIn->nPrefix = i;
157877
- }else{
157878
- pIn->nPrefix = 0;
157879
- }
157880
- }else{
157881
- pIn->eEndLoopOp = OP_Noop;
157882
- }
157883
- pIn++;
157884
- }
157885
- }
157886
- testcase( iEq>0
157887
- && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
157888
- && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
157889
- if( iEq>0
157890
- && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
157891
- ){
157892
- sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
157893
- }
157894
- }else{
157895
- pLevel->u.in.nIn = 0;
157896
- }
157897
- sqlite3DbFree(pParse->db, aiMap);
158335
+ codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
157898158336
#endif
157899158337
}
157900158338
157901158339
/* As an optimization, try to disable the WHERE clause term that is
157902158340
** driving the index as it will always be true. The correct answer is
@@ -158506,10 +158944,31 @@
158506158944
}
158507158945
pLevel->regFilter = 0;
158508158946
pLevel->addrBrk = 0;
158509158947
}
158510158948
}
158949
+
158950
+/*
158951
+** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
158952
+** operator. Return true if level pLoop is guaranteed to visit only one
158953
+** row for each key generated for the index.
158954
+*/
158955
+static int whereLoopIsOneRow(WhereLoop *pLoop){
158956
+ if( pLoop->u.btree.pIndex->onError
158957
+ && pLoop->nSkip==0
158958
+ && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
158959
+ ){
158960
+ int ii;
158961
+ for(ii=0; ii<pLoop->u.btree.nEq; ii++){
158962
+ if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){
158963
+ return 0;
158964
+ }
158965
+ }
158966
+ return 1;
158967
+ }
158968
+ return 0;
158969
+}
158511158970
158512158971
/*
158513158972
** Generate code for the start of the iLevel-th loop in the WHERE clause
158514158973
** implementation described by pWInfo.
158515158974
*/
@@ -158585,11 +159044,11 @@
158585159044
|| pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
158586159045
);
158587159046
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
158588159047
pLevel->iLeftJoin = ++pParse->nMem;
158589159048
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
158590
- VdbeComment((v, "init LEFT JOIN no-match flag"));
159049
+ VdbeComment((v, "init LEFT JOIN match flag"));
158591159050
}
158592159051
158593159052
/* Compute a safe address to jump to if we discover that the table for
158594159053
** this loop is empty and can never contribute content. */
158595159054
for(j=iLevel; j>0; j--){
@@ -159254,11 +159713,13 @@
159254159713
** a LEFT JOIN: */
159255159714
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
159256159715
}
159257159716
159258159717
/* Record the instruction used to terminate the loop. */
159259
- if( pLoop->wsFlags & WHERE_ONEROW ){
159718
+ if( (pLoop->wsFlags & WHERE_ONEROW)
159719
+ || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
159720
+ ){
159260159721
pLevel->op = OP_Noop;
159261159722
}else if( bRev ){
159262159723
pLevel->op = OP_Prev;
159263159724
}else{
159264159725
pLevel->op = OP_Next;
@@ -159644,10 +160105,16 @@
159644160105
** iLoop==2: Code remaining expressions that do not contain correlated
159645160106
** sub-queries.
159646160107
** iLoop==3: Code all remaining expressions.
159647160108
**
159648160109
** An effort is made to skip unnecessary iterations of the loop.
160110
+ **
160111
+ ** This optimization of causing simple query restrictions to occur before
160112
+ ** more complex one is call the "push-down" optimization in MySQL. Here
160113
+ ** in SQLite, the name is "MySQL push-down", since there is also another
160114
+ ** totally unrelated optimization called "WHERE-clause push-down".
160115
+ ** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
159649160116
*/
159650160117
iLoop = (pIdx ? 1 : 2);
159651160118
do{
159652160119
int iNext = 0; /* Next value for iLoop */
159653160120
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
@@ -159894,11 +160361,20 @@
159894160361
ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
159895160362
sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
159896160363
pRJ->regReturn);
159897160364
for(k=0; k<iLevel; k++){
159898160365
int iIdxCur;
160366
+ SrcItem *pRight;
160367
+ assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom );
160368
+ pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
159899160369
mAll |= pWInfo->a[k].pWLoop->maskSelf;
160370
+ if( pRight->fg.viaCoroutine ){
160371
+ sqlite3VdbeAddOp3(
160372
+ v, OP_Null, 0, pRight->regResult,
160373
+ pRight->regResult + pRight->pSelect->pEList->nExpr-1
160374
+ );
160375
+ }
159900160376
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
159901160377
iIdxCur = pWInfo->a[k].iIdxCur;
159902160378
if( iIdxCur ){
159903160379
sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
159904160380
}
@@ -160063,11 +160539,16 @@
160063160539
static int allowedOp(int op){
160064160540
assert( TK_GT>TK_EQ && TK_GT<TK_GE );
160065160541
assert( TK_LT>TK_EQ && TK_LT<TK_GE );
160066160542
assert( TK_LE>TK_EQ && TK_LE<TK_GE );
160067160543
assert( TK_GE==TK_EQ+4 );
160068
- return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
160544
+ assert( TK_IN<TK_EQ );
160545
+ assert( TK_IS<TK_EQ );
160546
+ assert( TK_ISNULL<TK_EQ );
160547
+ if( op>TK_GE ) return 0;
160548
+ if( op>=TK_EQ ) return 1;
160549
+ return op==TK_IN || op==TK_ISNULL || op==TK_IS;
160069160550
}
160070160551
160071160552
/*
160072160553
** Commute a comparison operator. Expressions of the form "X op Y"
160073160554
** are converted into "Y op X".
@@ -160096,19 +160577,20 @@
160096160577
** Translate from TK_xx operator to WO_xx bitmask.
160097160578
*/
160098160579
static u16 operatorMask(int op){
160099160580
u16 c;
160100160581
assert( allowedOp(op) );
160101
- if( op==TK_IN ){
160582
+ if( op>=TK_EQ ){
160583
+ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
160584
+ c = (u16)(WO_EQ<<(op-TK_EQ));
160585
+ }else if( op==TK_IN ){
160102160586
c = WO_IN;
160103160587
}else if( op==TK_ISNULL ){
160104160588
c = WO_ISNULL;
160105
- }else if( op==TK_IS ){
160589
+ }else{
160590
+ assert( op==TK_IS );
160106160591
c = WO_IS;
160107
- }else{
160108
- assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
160109
- c = (u16)(WO_EQ<<(op-TK_EQ));
160110160592
}
160111160593
assert( op!=TK_ISNULL || c==WO_ISNULL );
160112160594
assert( op!=TK_IN || c==WO_IN );
160113160595
assert( op!=TK_EQ || c==WO_EQ );
160114160596
assert( op!=TK_LT || c==WO_LT );
@@ -160391,10 +160873,17 @@
160391160873
*ppLeft = pCol;
160392160874
return 1;
160393160875
}
160394160876
}
160395160877
}
160878
+ }else if( pExpr->op>=TK_EQ ){
160879
+ /* Comparison operators are a common case. Save a few comparisons for
160880
+ ** that common case by terminating early. */
160881
+ assert( TK_NE < TK_EQ );
160882
+ assert( TK_ISNOT < TK_EQ );
160883
+ assert( TK_NOTNULL < TK_EQ );
160884
+ return 0;
160396160885
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
160397160886
int res = 0;
160398160887
Expr *pLeft = pExpr->pLeft;
160399160888
Expr *pRight = pExpr->pRight;
160400160889
assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
@@ -161532,11 +162021,11 @@
161532162021
Parse *pParse = pWC->pWInfo->pParse;
161533162022
sqlite3 *db = pParse->db;
161534162023
Expr *pNew;
161535162024
int iVal = 0;
161536162025
161537
- if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
162026
+ if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
161538162027
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
161539162028
if( pVal==0 ) return;
161540162029
ExprSetProperty(pVal, EP_IntValue);
161541162030
pVal->u.iValue = iVal;
161542162031
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
@@ -161600,10 +162089,11 @@
161600162089
** will only be added if each of the child terms passes the
161601162090
** (leftCursor==iCsr) test below. */
161602162091
continue;
161603162092
}
161604162093
if( pWC->a[ii].leftCursor!=iCsr ) return;
162094
+ if( pWC->a[ii].prereqRight!=0 ) return;
161605162095
}
161606162096
161607162097
/* Check condition (5). Return early if it is not met. */
161608162098
if( pOrderBy ){
161609162099
for(ii=0; ii<pOrderBy->nExpr; ii++){
@@ -161614,16 +162104,18 @@
161614162104
}
161615162105
}
161616162106
161617162107
/* All conditions are met. Add the terms to the where-clause object. */
161618162108
assert( p->pLimit->op==TK_LIMIT );
161619
- whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
161620
- iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
161621
- if( p->iOffset>0 ){
162109
+ if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){
161622162110
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
161623162111
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
161624162112
}
162113
+ if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){
162114
+ whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
162115
+ iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
162116
+ }
161625162117
}
161626162118
}
161627162119
161628162120
/*
161629162121
** Initialize a preallocated WhereClause structure.
@@ -162136,10 +162628,46 @@
162136162628
if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
162137162629
return p;
162138162630
}
162139162631
return 0;
162140162632
}
162633
+
162634
+/*
162635
+** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
162636
+** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
162637
+** This function checks to see if the term is compatible with an index
162638
+** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
162639
+** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
162640
+** or "NOCASE") used by the comparison in pTerm. If it is not compatible
162641
+** with affinity idxaff, NULL is returned.
162642
+*/
162643
+static SQLITE_NOINLINE const char *indexInAffinityOk(
162644
+ Parse *pParse,
162645
+ WhereTerm *pTerm,
162646
+ u8 idxaff
162647
+){
162648
+ Expr *pX = pTerm->pExpr;
162649
+ Expr inexpr;
162650
+
162651
+ assert( pTerm->eOperator & WO_IN );
162652
+
162653
+ if( sqlite3ExprIsVector(pX->pLeft) ){
162654
+ int iField = pTerm->u.x.iField - 1;
162655
+ inexpr.flags = 0;
162656
+ inexpr.op = TK_EQ;
162657
+ inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
162658
+ assert( ExprUseXSelect(pX) );
162659
+ inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
162660
+ pX = &inexpr;
162661
+ }
162662
+
162663
+ if( sqlite3IndexAffinityOk(pX, idxaff) ){
162664
+ CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
162665
+ return pRet ? pRet->zName : sqlite3StrBINARY;
162666
+ }
162667
+ return 0;
162668
+}
162141162669
162142162670
/*
162143162671
** Advance to the next WhereTerm that matches according to the criteria
162144162672
** established when the pScan object was initialized by whereScanInit().
162145162673
** Return NULL if there are no more matching WhereTerms.
@@ -162187,20 +162715,28 @@
162187162715
}
162188162716
}
162189162717
if( (pTerm->eOperator & pScan->opMask)!=0 ){
162190162718
/* Verify the affinity and collating sequence match */
162191162719
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
162192
- CollSeq *pColl;
162720
+ const char *zCollName;
162193162721
Parse *pParse = pWC->pWInfo->pParse;
162194162722
pX = pTerm->pExpr;
162195
- if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
162196
- continue;
162723
+
162724
+ if( (pTerm->eOperator & WO_IN) ){
162725
+ zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
162726
+ if( !zCollName ) continue;
162727
+ }else{
162728
+ CollSeq *pColl;
162729
+ if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
162730
+ continue;
162731
+ }
162732
+ assert(pX->pLeft);
162733
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
162734
+ zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
162197162735
}
162198
- assert(pX->pLeft);
162199
- pColl = sqlite3ExprCompareCollSeq(pParse, pX);
162200
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
162201
- if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
162736
+
162737
+ if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
162202162738
continue;
162203162739
}
162204162740
}
162205162741
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
162206162742
&& (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
@@ -162631,10 +163167,44 @@
162631163167
return 0;
162632163168
}
162633163169
return 1;
162634163170
}
162635163171
163172
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
163173
+/*
163174
+** Return true if column iCol of table pTab seem like it might be a
163175
+** good column to use as part of a query-time index.
163176
+**
163177
+** Current algorithm (subject to improvement!):
163178
+**
163179
+** 1. If iCol is already the left-most column of some other index,
163180
+** then return false.
163181
+**
163182
+** 2. If iCol is part of an existing index that has an aiRowLogEst of
163183
+** more than 20, then return false.
163184
+**
163185
+** 3. If no disqualifying conditions above are found, return true.
163186
+*/
163187
+static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
163188
+ const Table *pTab,
163189
+ int iCol
163190
+){
163191
+ const Index *pIdx;
163192
+ for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
163193
+ int j;
163194
+ for(j=0; j<pIdx->nKeyCol; j++){
163195
+ if( pIdx->aiColumn[j]==iCol ){
163196
+ if( j==0 ) return 0;
163197
+ if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
163198
+ break;
163199
+ }
163200
+ }
163201
+ }
163202
+ return 1;
163203
+}
163204
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
163205
+
162636163206
162637163207
162638163208
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
162639163209
/*
162640163210
** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -162645,10 +163215,12 @@
162645163215
const WhereTerm *pTerm, /* WHERE clause term to check */
162646163216
const SrcItem *pSrc, /* Table we are trying to access */
162647163217
const Bitmask notReady /* Tables in outer loops of the join */
162648163218
){
162649163219
char aff;
163220
+ int leftCol;
163221
+
162650163222
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
162651163223
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
162652163224
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
162653163225
if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
162654163226
&& !constraintCompatibleWithOuterJoin(pTerm,pSrc)
@@ -162655,15 +163227,16 @@
162655163227
){
162656163228
return 0; /* See https://sqlite.org/forum/forumpost/51e6959f61 */
162657163229
}
162658163230
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
162659163231
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
162660
- if( pTerm->u.x.leftColumn<0 ) return 0;
162661
- aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
163232
+ leftCol = pTerm->u.x.leftColumn;
163233
+ if( leftCol<0 ) return 0;
163234
+ aff = pSrc->pTab->aCol[leftCol].affinity;
162662163235
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
162663163236
testcase( pTerm->pExpr->op==TK_IS );
162664
- return 1;
163237
+ return columnIsGoodIndexCandidate(pSrc->pTab, leftCol);
162665163238
}
162666163239
#endif
162667163240
162668163241
162669163242
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -162777,11 +163350,11 @@
162777163350
Expr *pExpr = pTerm->pExpr;
162778163351
/* Make the automatic index a partial index if there are terms in the
162779163352
** WHERE clause (or the ON clause of a LEFT join) that constrain which
162780163353
** rows of the target table (pSrc) that can be used. */
162781163354
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
162782
- && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
163355
+ && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
162783163356
){
162784163357
pPartial = sqlite3ExprAnd(pParse, pPartial,
162785163358
sqlite3ExprDup(pParse->db, pExpr, 0));
162786163359
}
162787163360
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
@@ -163046,11 +163619,11 @@
163046163619
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
163047163620
pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
163048163621
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
163049163622
Expr *pExpr = pTerm->pExpr;
163050163623
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
163051
- && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
163624
+ && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
163052163625
){
163053163626
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
163054163627
}
163055163628
}
163056163629
if( pLoop->wsFlags & WHERE_IPK ){
@@ -163100,10 +163673,24 @@
163100163673
pParse->pIdxPartExpr = saved_pIdxPartExpr;
163101163674
}
163102163675
163103163676
163104163677
#ifndef SQLITE_OMIT_VIRTUALTABLE
163678
+/*
163679
+** Return term iTerm of the WhereClause passed as the first argument. Terms
163680
+** are numbered from 0 upwards, starting with the terms in pWC->a[], then
163681
+** those in pWC->pOuter->a[] (if any), and so on.
163682
+*/
163683
+static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
163684
+ WhereClause *p;
163685
+ for(p=pWC; p; p=p->pOuter){
163686
+ if( iTerm<p->nTerm ) return &p->a[iTerm];
163687
+ iTerm -= p->nTerm;
163688
+ }
163689
+ return 0;
163690
+}
163691
+
163105163692
/*
163106163693
** Allocate and populate an sqlite3_index_info structure. It is the
163107163694
** responsibility of the caller to eventually release the structure
163108163695
** by passing the pointer returned by this function to freeIndexInfo().
163109163696
*/
@@ -163126,10 +163713,11 @@
163126163713
sqlite3_index_info *pIdxInfo;
163127163714
u16 mNoOmit = 0;
163128163715
const Table *pTab;
163129163716
int eDistinct = 0;
163130163717
ExprList *pOrderBy = pWInfo->pOrderBy;
163718
+ WhereClause *p;
163131163719
163132163720
assert( pSrc!=0 );
163133163721
pTab = pSrc->pTab;
163134163722
assert( pTab!=0 );
163135163723
assert( IsVirtual(pTab) );
@@ -163136,32 +163724,34 @@
163136163724
163137163725
/* Find all WHERE clause constraints referring to this virtual table.
163138163726
** Mark each term with the TERM_OK flag. Set nTerm to the number of
163139163727
** terms found.
163140163728
*/
163141
- for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
163142
- pTerm->wtFlags &= ~TERM_OK;
163143
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
163144
- if( pTerm->prereqRight & mUnusable ) continue;
163145
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
163146
- testcase( pTerm->eOperator & WO_IN );
163147
- testcase( pTerm->eOperator & WO_ISNULL );
163148
- testcase( pTerm->eOperator & WO_IS );
163149
- testcase( pTerm->eOperator & WO_ALL );
163150
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
163151
- if( pTerm->wtFlags & TERM_VNULL ) continue;
163152
-
163153
- assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
163154
- assert( pTerm->u.x.leftColumn>=XN_ROWID );
163155
- assert( pTerm->u.x.leftColumn<pTab->nCol );
163156
- if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
163157
- && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
163158
- ){
163159
- continue;
163160
- }
163161
- nTerm++;
163162
- pTerm->wtFlags |= TERM_OK;
163729
+ for(p=pWC, nTerm=0; p; p=p->pOuter){
163730
+ for(i=0, pTerm=p->a; i<p->nTerm; i++, pTerm++){
163731
+ pTerm->wtFlags &= ~TERM_OK;
163732
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
163733
+ if( pTerm->prereqRight & mUnusable ) continue;
163734
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
163735
+ testcase( pTerm->eOperator & WO_IN );
163736
+ testcase( pTerm->eOperator & WO_ISNULL );
163737
+ testcase( pTerm->eOperator & WO_IS );
163738
+ testcase( pTerm->eOperator & WO_ALL );
163739
+ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
163740
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
163741
+
163742
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
163743
+ assert( pTerm->u.x.leftColumn>=XN_ROWID );
163744
+ assert( pTerm->u.x.leftColumn<pTab->nCol );
163745
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
163746
+ && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
163747
+ ){
163748
+ continue;
163749
+ }
163750
+ nTerm++;
163751
+ pTerm->wtFlags |= TERM_OK;
163752
+ }
163163163753
}
163164163754
163165163755
/* If the ORDER BY clause contains only columns in the current
163166163756
** virtual table then allocate space for the aOrderBy part of
163167163757
** the sqlite3_index_info structure.
@@ -163207,11 +163797,11 @@
163207163797
/* No matches cause a break out of the loop */
163208163798
break;
163209163799
}
163210163800
if( i==n ){
163211163801
nOrderBy = n;
163212
- if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){
163802
+ if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
163213163803
eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
163214163804
}else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
163215163805
eDistinct = 1;
163216163806
}
163217163807
}
@@ -163236,53 +163826,56 @@
163236163826
pIdxInfo->aConstraintUsage = pUsage;
163237163827
pHidden->pWC = pWC;
163238163828
pHidden->pParse = pParse;
163239163829
pHidden->eDistinct = eDistinct;
163240163830
pHidden->mIn = 0;
163241
- for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
163242
- u16 op;
163243
- if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
163244
- pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
163245
- pIdxCons[j].iTermOffset = i;
163246
- op = pTerm->eOperator & WO_ALL;
163247
- if( op==WO_IN ){
163248
- if( (pTerm->wtFlags & TERM_SLICE)==0 ){
163249
- pHidden->mIn |= SMASKBIT32(j);
163250
- }
163251
- op = WO_EQ;
163252
- }
163253
- if( op==WO_AUX ){
163254
- pIdxCons[j].op = pTerm->eMatchOp;
163255
- }else if( op & (WO_ISNULL|WO_IS) ){
163256
- if( op==WO_ISNULL ){
163257
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
163258
- }else{
163259
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
163260
- }
163261
- }else{
163262
- pIdxCons[j].op = (u8)op;
163263
- /* The direct assignment in the previous line is possible only because
163264
- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
163265
- ** following asserts verify this fact. */
163266
- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
163267
- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
163268
- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
163269
- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
163270
- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
163271
- assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
163272
-
163273
- if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
163274
- && sqlite3ExprIsVector(pTerm->pExpr->pRight)
163275
- ){
163276
- testcase( j!=i );
163277
- if( j<16 ) mNoOmit |= (1 << j);
163278
- if( op==WO_LT ) pIdxCons[j].op = WO_LE;
163279
- if( op==WO_GT ) pIdxCons[j].op = WO_GE;
163280
- }
163281
- }
163282
-
163283
- j++;
163831
+ for(p=pWC, i=j=0; p; p=p->pOuter){
163832
+ int nLast = i+p->nTerm;;
163833
+ for(pTerm=p->a; i<nLast; i++, pTerm++){
163834
+ u16 op;
163835
+ if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
163836
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
163837
+ pIdxCons[j].iTermOffset = i;
163838
+ op = pTerm->eOperator & WO_ALL;
163839
+ if( op==WO_IN ){
163840
+ if( (pTerm->wtFlags & TERM_SLICE)==0 ){
163841
+ pHidden->mIn |= SMASKBIT32(j);
163842
+ }
163843
+ op = WO_EQ;
163844
+ }
163845
+ if( op==WO_AUX ){
163846
+ pIdxCons[j].op = pTerm->eMatchOp;
163847
+ }else if( op & (WO_ISNULL|WO_IS) ){
163848
+ if( op==WO_ISNULL ){
163849
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
163850
+ }else{
163851
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
163852
+ }
163853
+ }else{
163854
+ pIdxCons[j].op = (u8)op;
163855
+ /* The direct assignment in the previous line is possible only because
163856
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
163857
+ ** following asserts verify this fact. */
163858
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
163859
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
163860
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
163861
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
163862
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
163863
+ assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
163864
+
163865
+ if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
163866
+ && sqlite3ExprIsVector(pTerm->pExpr->pRight)
163867
+ ){
163868
+ testcase( j!=i );
163869
+ if( j<16 ) mNoOmit |= (1 << j);
163870
+ if( op==WO_LT ) pIdxCons[j].op = WO_LE;
163871
+ if( op==WO_GT ) pIdxCons[j].op = WO_GE;
163872
+ }
163873
+ }
163874
+
163875
+ j++;
163876
+ }
163284163877
}
163285163878
assert( j==nTerm );
163286163879
pIdxInfo->nConstraint = j;
163287163880
for(i=j=0; i<nOrderBy; i++){
163288163881
Expr *pExpr = pOrderBy->a[i].pExpr;
@@ -163297,10 +163890,21 @@
163297163890
pIdxInfo->nOrderBy = j;
163298163891
163299163892
*pmNoOmit = mNoOmit;
163300163893
return pIdxInfo;
163301163894
}
163895
+
163896
+/*
163897
+** Free and zero the sqlite3_index_info.idxStr value if needed.
163898
+*/
163899
+static void freeIdxStr(sqlite3_index_info *pIdxInfo){
163900
+ if( pIdxInfo->needToFreeIdxStr ){
163901
+ sqlite3_free(pIdxInfo->idxStr);
163902
+ pIdxInfo->idxStr = 0;
163903
+ pIdxInfo->needToFreeIdxStr = 0;
163904
+ }
163905
+}
163302163906
163303163907
/*
163304163908
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
163305163909
** and possibly modified by xBestIndex methods.
163306163910
*/
@@ -163313,10 +163917,11 @@
163313163917
assert( pHidden->pParse->db==db );
163314163918
for(i=0; i<pIdxInfo->nConstraint; i++){
163315163919
sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
163316163920
pHidden->aRhs[i] = 0;
163317163921
}
163922
+ freeIdxStr(pIdxInfo);
163318163923
sqlite3DbFree(db, pIdxInfo);
163319163924
}
163320163925
163321163926
/*
163322163927
** The table object reference passed as the second argument to this function
@@ -164664,11 +165269,11 @@
164664165269
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
164665165270
){
164666165271
Expr *pRight = pTerm->pExpr->pRight;
164667165272
int k = 0;
164668165273
testcase( pTerm->pExpr->op==TK_IS );
164669
- if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
165274
+ if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
164670165275
k = 10;
164671165276
}else{
164672165277
k = 20;
164673165278
}
164674165279
if( iReduce<k ){
@@ -164961,11 +165566,11 @@
164961165566
assert( saved_nEq==pNew->u.btree.nEq );
164962165567
if( iCol==XN_ROWID
164963165568
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
164964165569
){
164965165570
if( iCol==XN_ROWID || pProbe->uniqNotNull
164966
- || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
165571
+ || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
164967165572
){
164968165573
pNew->wsFlags |= WHERE_ONEROW;
164969165574
}else{
164970165575
pNew->wsFlags |= WHERE_UNQ_WANTED;
164971165576
}
@@ -165087,14 +165692,17 @@
165087165692
}
165088165693
}
165089165694
}
165090165695
}
165091165696
165092
- /* Set rCostIdx to the cost of visiting selected rows in index. Add
165093
- ** it to pNew->rRun, which is currently set to the cost of the index
165094
- ** seek only. Then, if this is a non-covering index, add the cost of
165095
- ** visiting the rows in the main table. */
165697
+ /* Set rCostIdx to the estimated cost of visiting selected rows in the
165698
+ ** index. The estimate is the sum of two values:
165699
+ ** 1. The cost of doing one search-by-key to find the first matching
165700
+ ** entry
165701
+ ** 2. Stepping forward in the index pNew->nOut times to find all
165702
+ ** additional matching entries.
165703
+ */
165096165704
assert( pSrc->pTab->szTabRow>0 );
165097165705
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
165098165706
/* The pProbe->szIdxRow is low for an IPK table since the interior
165099165707
** pages are small. Thus szIdxRow gives a good estimate of seek cost.
165100165708
** But the leaf pages are full-size, so pProbe->szIdxRow would badly
@@ -165101,11 +165709,19 @@
165101165709
** under-estimate the scanning cost. */
165102165710
rCostIdx = pNew->nOut + 16;
165103165711
}else{
165104165712
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
165105165713
}
165106
- pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
165714
+ rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
165715
+
165716
+ /* Estimate the cost of running the loop. If all data is coming
165717
+ ** from the index, then this is just the cost of doing the index
165718
+ ** lookup and scan. But if some data is coming out of the main table,
165719
+ ** we also have to add in the cost of doing pNew->nOut searches to
165720
+ ** locate the row in the main table that corresponds to the index entry.
165721
+ */
165722
+ pNew->rRun = rCostIdx;
165107165723
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
165108165724
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
165109165725
}
165110165726
ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
165111165727
@@ -165836,10 +166452,25 @@
165836166452
static int isLimitTerm(WhereTerm *pTerm){
165837166453
assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
165838166454
return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
165839166455
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
165840166456
}
166457
+
166458
+/*
166459
+** Return true if the first nCons constraints in the pUsage array are
166460
+** marked as in-use (have argvIndex>0). False otherwise.
166461
+*/
166462
+static int allConstraintsUsed(
166463
+ struct sqlite3_index_constraint_usage *aUsage,
166464
+ int nCons
166465
+){
166466
+ int ii;
166467
+ for(ii=0; ii<nCons; ii++){
166468
+ if( aUsage[ii].argvIndex<=0 ) return 0;
166469
+ }
166470
+ return 1;
166471
+}
165841166472
165842166473
/*
165843166474
** Argument pIdxInfo is already populated with all constraints that may
165844166475
** be used by the virtual table identified by pBuilder->pNew->iTab. This
165845166476
** function marks a subset of those constraints usable, invokes the
@@ -165887,11 +166518,11 @@
165887166518
165888166519
/* Set the usable flag on the subset of constraints identified by
165889166520
** arguments mUsable and mExclude. */
165890166521
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
165891166522
for(i=0; i<nConstraint; i++, pIdxCons++){
165892
- WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
166523
+ WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
165893166524
pIdxCons->usable = 0;
165894166525
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
165895166526
&& (pTerm->eOperator & mExclude)==0
165896166527
&& (pbRetryLimit || !isLimitTerm(pTerm))
165897166528
){
@@ -165918,10 +166549,11 @@
165918166549
/* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
165919166550
** that the particular combination of parameters provided is unusable.
165920166551
** Make no entries in the loop table.
165921166552
*/
165922166553
WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
166554
+ freeIdxStr(pIdxInfo);
165923166555
return SQLITE_OK;
165924166556
}
165925166557
return rc;
165926166558
}
165927166559
@@ -165935,22 +166567,21 @@
165935166567
if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
165936166568
WhereTerm *pTerm;
165937166569
int j = pIdxCons->iTermOffset;
165938166570
if( iTerm>=nConstraint
165939166571
|| j<0
165940
- || j>=pWC->nTerm
166572
+ || (pTerm = termFromWhereClause(pWC, j))==0
165941166573
|| pNew->aLTerm[iTerm]!=0
165942166574
|| pIdxCons->usable==0
165943166575
){
165944166576
sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
165945
- testcase( pIdxInfo->needToFreeIdxStr );
166577
+ freeIdxStr(pIdxInfo);
165946166578
return SQLITE_ERROR;
165947166579
}
165948166580
testcase( iTerm==nConstraint-1 );
165949166581
testcase( j==0 );
165950166582
testcase( j==pWC->nTerm-1 );
165951
- pTerm = &pWC->a[j];
165952166583
pNew->prereq |= pTerm->prereqRight;
165953166584
assert( iTerm<pNew->nLSlot );
165954166585
pNew->aLTerm[iTerm] = pTerm;
165955166586
if( iTerm>mxTerm ) mxTerm = iTerm;
165956166587
testcase( iTerm==15 );
@@ -165977,22 +166608,25 @@
165977166608
pIdxInfo->orderByConsumed = 0;
165978166609
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
165979166610
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
165980166611
}
165981166612
166613
+ /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
166614
+ ** terms. And if there are any, they should follow all other terms. */
165982166615
assert( pbRetryLimit || !isLimitTerm(pTerm) );
165983
- if( isLimitTerm(pTerm) && *pbIn ){
166616
+ assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
166617
+ assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
166618
+
166619
+ if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
165984166620
/* If there is an IN(...) term handled as an == (separate call to
165985166621
** xFilter for each value on the RHS of the IN) and a LIMIT or
165986
- ** OFFSET term handled as well, the plan is unusable. Set output
165987
- ** variable *pbRetryLimit to true to tell the caller to retry with
165988
- ** LIMIT and OFFSET disabled. */
165989
- if( pIdxInfo->needToFreeIdxStr ){
165990
- sqlite3_free(pIdxInfo->idxStr);
165991
- pIdxInfo->idxStr = 0;
165992
- pIdxInfo->needToFreeIdxStr = 0;
165993
- }
166622
+ ** OFFSET term handled as well, the plan is unusable. Similarly,
166623
+ ** if there is a LIMIT/OFFSET and there are other unused terms,
166624
+ ** the plan cannot be used. In these cases set variable *pbRetryLimit
166625
+ ** to true to tell the caller to retry with LIMIT and OFFSET
166626
+ ** disabled. */
166627
+ freeIdxStr(pIdxInfo);
165994166628
*pbRetryLimit = 1;
165995166629
return SQLITE_OK;
165996166630
}
165997166631
}
165998166632
}
@@ -166001,11 +166635,11 @@
166001166635
for(i=0; i<=mxTerm; i++){
166002166636
if( pNew->aLTerm[i]==0 ){
166003166637
/* The non-zero argvIdx values must be contiguous. Raise an
166004166638
** error if they are not */
166005166639
sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
166006
- testcase( pIdxInfo->needToFreeIdxStr );
166640
+ freeIdxStr(pIdxInfo);
166007166641
return SQLITE_ERROR;
166008166642
}
166009166643
}
166010166644
assert( pNew->nLTerm<=pNew->nLSlot );
166011166645
pNew->u.vtab.idxNum = pIdxInfo->idxNum;
@@ -166056,11 +166690,11 @@
166056166690
HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
166057166691
const char *zRet = 0;
166058166692
if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
166059166693
CollSeq *pC = 0;
166060166694
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
166061
- Expr *pX = pHidden->pWC->a[iTerm].pExpr;
166695
+ Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
166062166696
if( pX->pLeft ){
166063166697
pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
166064166698
}
166065166699
zRet = (pC ? pC->zName : sqlite3StrBINARY);
166066166700
}
@@ -166102,11 +166736,13 @@
166102166736
int rc = SQLITE_OK;
166103166737
if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
166104166738
rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
166105166739
}else{
166106166740
if( pH->aRhs[iCons]==0 ){
166107
- WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
166741
+ WhereTerm *pTerm = termFromWhereClause(
166742
+ pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
166743
+ );
166108166744
rc = sqlite3ValueFromExpr(
166109166745
pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
166110166746
SQLITE_AFF_BLOB, &pH->aRhs[iCons]
166111166747
);
166112166748
testcase( rc!=SQLITE_OK );
@@ -166258,13 +166894,12 @@
166258166894
while( rc==SQLITE_OK ){
166259166895
int i;
166260166896
Bitmask mNext = ALLBITS;
166261166897
assert( mNext>0 );
166262166898
for(i=0; i<nConstraint; i++){
166263
- Bitmask mThis = (
166264
- pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
166265
- );
166899
+ int iTerm = p->aConstraint[i].iTermOffset;
166900
+ Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
166266166901
if( mThis>mPrev && mThis<mNext ) mNext = mThis;
166267166902
}
166268166903
mPrev = mNext;
166269166904
if( mNext==ALLBITS ) break;
166270166905
if( mNext==mBest || mNext==mBestNoIn ) continue;
@@ -166296,11 +166931,10 @@
166296166931
rc = whereLoopAddVirtualOne(
166297166932
pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
166298166933
}
166299166934
}
166300166935
166301
- if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
166302166936
freeIndexInfo(pParse->db, p);
166303166937
WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
166304166938
return rc;
166305166939
}
166306166940
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166673,11 +167307,11 @@
166673167307
nColumn = pIndex->nColumn;
166674167308
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
166675167309
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
166676167310
|| !HasRowid(pIndex->pTable));
166677167311
/* All relevant terms of the index must also be non-NULL in order
166678
- ** for isOrderDistinct to be true. So the isOrderDistint value
167312
+ ** for isOrderDistinct to be true. So the isOrderDistinct value
166679167313
** computed here might be a false positive. Corrections will be
166680167314
** made at tag-20210426-1 below */
166681167315
isOrderDistinct = IsUniqueIndex(pIndex)
166682167316
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
166683167317
}
@@ -166964,10 +167598,87 @@
166964167598
if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
166965167599
}
166966167600
rSortCost += estLog(nRow);
166967167601
return rSortCost;
166968167602
}
167603
+
167604
+/*
167605
+** Compute the maximum number of paths in the solver algorithm, for
167606
+** queries that have three or more terms in the FROM clause. Queries with
167607
+** two or fewer FROM clause terms are handled by the caller.
167608
+**
167609
+** Query planning is NP-hard. We must limit the number of paths at
167610
+** each step of the solver search algorithm to avoid exponential behavior.
167611
+**
167612
+** The value returned is a tuning parameter. Currently the value is:
167613
+**
167614
+** 18 for star queries
167615
+** 12 otherwise
167616
+**
167617
+** For the purposes of SQLite, a star-query is defined as a query
167618
+** with a large central table that is joined against four or more
167619
+** smaller tables. The central table is called the "fact" table.
167620
+** The smaller tables that get joined are "dimension tables".
167621
+**
167622
+** SIDE EFFECT: (and really the whole point of this subroutine)
167623
+**
167624
+** If pWInfo describes a star-query, then the cost on WhereLoops for the
167625
+** fact table is reduced. This heuristic helps keep fact tables in
167626
+** outer loops. Without this heuristic, paths with fact tables in outer
167627
+** loops tend to get pruned by the mxChoice limit on the number of paths,
167628
+** resulting in poor query plans. The total amount of heuristic cost
167629
+** adjustment is stored in pWInfo->nOutStarDelta and the cost adjustment
167630
+** for each WhereLoop is stored in its rStarDelta field.
167631
+*/
167632
+static int computeMxChoice(WhereInfo *pWInfo, LogEst nRowEst){
167633
+ int nLoop = pWInfo->nLevel; /* Number of terms in the join */
167634
+ if( nRowEst==0 && nLoop>=5 ){
167635
+ /* Check to see if we are dealing with a star schema and if so, reduce
167636
+ ** the cost of fact tables relative to dimension tables, as a heuristic
167637
+ ** to help keep the fact tables in outer loops.
167638
+ */
167639
+ int iLoop; /* Counter over join terms */
167640
+ Bitmask m; /* Bitmask for current loop */
167641
+ assert( pWInfo->nOutStarDelta==0 );
167642
+ for(iLoop=0, m=1; iLoop<nLoop; iLoop++, m<<=1){
167643
+ WhereLoop *pWLoop; /* For looping over WhereLoops */
167644
+ int nDep = 0; /* Number of dimension tables */
167645
+ LogEst rDelta; /* Heuristic cost adjustment */
167646
+ Bitmask mSeen = 0; /* Mask of dimension tables */
167647
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167648
+ if( (pWLoop->prereq & m)!=0 && (pWLoop->maskSelf & mSeen)==0 ){
167649
+ nDep++;
167650
+ mSeen |= pWLoop->maskSelf;
167651
+ }
167652
+ }
167653
+ if( nDep<=3 ) continue;
167654
+ rDelta = 15*(nDep-3);
167655
+#ifdef WHERETRACE_ENABLED /* 0x4 */
167656
+ if( sqlite3WhereTrace&0x4 ){
167657
+ SrcItem *pItem = pWInfo->pTabList->a + iLoop;
167658
+ sqlite3DebugPrintf("Fact-table %s: %d dimensions, cost reduced %d\n",
167659
+ pItem->zAlias ? pItem->zAlias : pItem->pTab->zName,
167660
+ nDep, rDelta);
167661
+ }
167662
+#endif
167663
+ if( pWInfo->nOutStarDelta==0 ){
167664
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167665
+ pWLoop->rStarDelta = 0;
167666
+ }
167667
+ }
167668
+ pWInfo->nOutStarDelta += rDelta;
167669
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167670
+ if( pWLoop->maskSelf==m ){
167671
+ pWLoop->rRun -= rDelta;
167672
+ pWLoop->nOut -= rDelta;
167673
+ pWLoop->rStarDelta = rDelta;
167674
+ }
167675
+ }
167676
+ }
167677
+ }
167678
+ return pWInfo->nOutStarDelta>0 ? 18 : 12;
167679
+}
166969167680
166970167681
/*
166971167682
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
166972167683
** attempts to find the lowest cost path that visits each WhereLoop
166973167684
** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -167000,17 +167711,29 @@
167000167711
char *pSpace; /* Temporary memory used by this routine */
167001167712
int nSpace; /* Bytes of space allocated at pSpace */
167002167713
167003167714
pParse = pWInfo->pParse;
167004167715
nLoop = pWInfo->nLevel;
167005
- /* TUNING: For simple queries, only the best path is tracked.
167006
- ** For 2-way joins, the 5 best paths are followed.
167007
- ** For joins of 3 or more tables, track the 10 best paths */
167008
- mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
167009
- assert( nLoop<=pWInfo->pTabList->nSrc );
167010167716
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
167011167717
nRowEst, pParse->nQueryLoop));
167718
+ /* TUNING: mxChoice is the maximum number of possible paths to preserve
167719
+ ** at each step. Based on the number of loops in the FROM clause:
167720
+ **
167721
+ ** nLoop mxChoice
167722
+ ** ----- --------
167723
+ ** 1 1 // the most common case
167724
+ ** 2 5
167725
+ ** 3+ 12 or 18 // see computeMxChoice()
167726
+ */
167727
+ if( nLoop<=1 ){
167728
+ mxChoice = 1;
167729
+ }else if( nLoop==2 ){
167730
+ mxChoice = 5;
167731
+ }else{
167732
+ mxChoice = computeMxChoice(pWInfo, nRowEst);
167733
+ }
167734
+ assert( nLoop<=pWInfo->pTabList->nSrc );
167012167735
167013167736
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
167014167737
** case the purpose of this call is to estimate the number of rows returned
167015167738
** by the overall query. Once this estimate has been obtained, the caller
167016167739
** will invoke this function a second time, passing the estimate as the
@@ -167089,11 +167812,14 @@
167089167812
continue;
167090167813
}
167091167814
167092167815
/* At this point, pWLoop is a candidate to be the next loop.
167093167816
** Compute its cost */
167094
- rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
167817
+ rUnsorted = pWLoop->rRun + pFrom->nRow;
167818
+ if( pWLoop->rSetup ){
167819
+ rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup, rUnsorted);
167820
+ }
167095167821
rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
167096167822
nOut = pFrom->nRow + pWLoop->nOut;
167097167823
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
167098167824
isOrdered = pFrom->isOrdered;
167099167825
if( isOrdered<0 ){
@@ -167134,10 +167860,11 @@
167134167860
**
167135167861
** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
167136167862
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
167137167863
** of legal values for isOrdered, -1..64.
167138167864
*/
167865
+ testcase( nTo==0 );
167139167866
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
167140167867
if( pTo->maskLoop==maskNew
167141167868
&& ((pTo->isOrdered^isOrdered)&0x80)==0
167142167869
){
167143167870
testcase( jj==nTo-1 );
@@ -167250,20 +167977,32 @@
167250167977
}
167251167978
}
167252167979
167253167980
#ifdef WHERETRACE_ENABLED /* >=2 */
167254167981
if( sqlite3WhereTrace & 0x02 ){
167982
+ LogEst rMin, rFloor = 0;
167983
+ int nDone = 0;
167255167984
sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
167256
- for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167257
- sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
167258
- wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
167259
- pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
167260
- if( pTo->isOrdered>0 ){
167261
- sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
167262
- }else{
167263
- sqlite3DebugPrintf("\n");
167264
- }
167985
+ while( nDone<nTo ){
167986
+ rMin = 0x7fff;
167987
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167988
+ if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost;
167989
+ }
167990
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167991
+ if( pTo->rCost==rMin ){
167992
+ sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
167993
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
167994
+ pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
167995
+ if( pTo->isOrdered>0 ){
167996
+ sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
167997
+ }else{
167998
+ sqlite3DebugPrintf("\n");
167999
+ }
168000
+ nDone++;
168001
+ }
168002
+ }
168003
+ rFloor = rMin;
167265168004
}
167266168005
}
167267168006
#endif
167268168007
167269168008
/* Swap the roles of aFrom and aTo for the next generation */
@@ -167354,17 +168093,93 @@
167354168093
pWInfo->revMask = revMask;
167355168094
}
167356168095
}
167357168096
}
167358168097
167359
-
167360
- pWInfo->nRowOut = pFrom->nRow;
168098
+ pWInfo->nRowOut = pFrom->nRow + pWInfo->nOutStarDelta;
167361168099
167362168100
/* Free temporary memory and return success */
167363168101
sqlite3StackFreeNN(pParse->db, pSpace);
167364168102
return SQLITE_OK;
167365168103
}
168104
+
168105
+/*
168106
+** This routine implements a heuristic designed to improve query planning.
168107
+** This routine is called in between the first and second call to
168108
+** wherePathSolver(). Hence the name "Interstage" "Heuristic".
168109
+**
168110
+** The first call to wherePathSolver() (hereafter just "solver()") computes
168111
+** the best path without regard to the order of the outputs. The second call
168112
+** to the solver() builds upon the first call to try to find an alternative
168113
+** path that satisfies the ORDER BY clause.
168114
+**
168115
+** This routine looks at the results of the first solver() run, and for
168116
+** every FROM clause term in the resulting query plan that uses an equality
168117
+** constraint against an index, disable other WhereLoops for that same
168118
+** FROM clause term that would try to do a full-table scan. This prevents
168119
+** an index search from being converted into a full-table scan in order to
168120
+** satisfy an ORDER BY clause, since even though we might get slightly better
168121
+** performance using the full-scan without sorting if the output size
168122
+** estimates are very precise, we might also get severe performance
168123
+** degradation using the full-scan if the output size estimate is too large.
168124
+** It is better to err on the side of caution.
168125
+**
168126
+** Except, if the first solver() call generated a full-table scan in an outer
168127
+** loop then stop this analysis at the first full-scan, since the second
168128
+** solver() run might try to swap that full-scan for another in order to
168129
+** get the output into the correct order. In other words, we allow a
168130
+** rewrite like this:
168131
+**
168132
+** First Solver() Second Solver()
168133
+** |-- SCAN t1 |-- SCAN t2
168134
+** |-- SEARCH t2 `-- SEARCH t1
168135
+** `-- SORT USING B-TREE
168136
+**
168137
+** The purpose of this routine is to disallow rewrites such as:
168138
+**
168139
+** First Solver() Second Solver()
168140
+** |-- SEARCH t1 |-- SCAN t2 <--- bad!
168141
+** |-- SEARCH t2 `-- SEARCH t1
168142
+** `-- SORT USING B-TREE
168143
+**
168144
+** See test cases in test/whereN.test for the real-world query that
168145
+** originally provoked this heuristic.
168146
+*/
168147
+static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
168148
+ int i;
168149
+#ifdef WHERETRACE_ENABLED
168150
+ int once = 0;
168151
+#endif
168152
+ for(i=0; i<pWInfo->nLevel; i++){
168153
+ WhereLoop *p = pWInfo->a[i].pWLoop;
168154
+ if( p==0 ) break;
168155
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
168156
+ if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
168157
+ u8 iTab = p->iTab;
168158
+ WhereLoop *pLoop;
168159
+ for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
168160
+ if( pLoop->iTab!=iTab ) continue;
168161
+ if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
168162
+ /* Auto-index and index-constrained loops allowed to remain */
168163
+ continue;
168164
+ }
168165
+#ifdef WHERETRACE_ENABLED
168166
+ if( sqlite3WhereTrace & 0x80 ){
168167
+ if( once==0 ){
168168
+ sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n");
168169
+ once = 1;
168170
+ }
168171
+ sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC);
168172
+ }
168173
+#endif /* WHERETRACE_ENABLED */
168174
+ pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */
168175
+ }
168176
+ }else{
168177
+ break;
168178
+ }
168179
+ }
168180
+}
167366168181
167367168182
/*
167368168183
** Most queries use only a single table (they are not joins) and have
167369168184
** simple == constraints against indexed fields. This routine attempts
167370168185
** to plan those simple cases using much less ceremony than the
@@ -167530,10 +168345,14 @@
167530168345
** might move from the right side to the left side of the RIGHT JOIN.
167531168346
** Note: Due to (2), this condition can only arise if the table is
167532168347
** the right-most table of a subquery that was flattened into the
167533168348
** main query and that subquery was the right-hand operand of an
167534168349
** inner join that held an ON or USING clause.
168350
+** 6) The ORDER BY clause has 63 or fewer terms
168351
+** 7) The omit-noop-join optimization is enabled.
168352
+**
168353
+** Items (1), (6), and (7) are checked by the caller.
167535168354
**
167536168355
** For example, given:
167537168356
**
167538168357
** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
167539168358
** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
@@ -167668,12 +168487,65 @@
167668168487
pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
167669168488
(double)sqlite3LogEstToInt(pTab->nRowLogEst)));
167670168489
}
167671168490
}
167672168491
nSearch += pLoop->nOut;
168492
+ if( pWInfo->nOutStarDelta ) nSearch += pLoop->rStarDelta;
167673168493
}
167674168494
}
168495
+
168496
+/*
168497
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
168498
+**
168499
+** Only a function call is able to return a subtype. So if the node
168500
+** is not a function call, return WRC_Prune immediately.
168501
+**
168502
+** A function call is able to return a subtype if it has the
168503
+** SQLITE_RESULT_SUBTYPE property.
168504
+**
168505
+** Assume that every function is able to pass-through a subtype from
168506
+** one of its argument (using sqlite3_result_value()). Most functions
168507
+** are not this way, but we don't have a mechanism to distinguish those
168508
+** that are from those that are not, so assume they all work this way.
168509
+** That means that if one of its arguments is another function and that
168510
+** other function is able to return a subtype, then this function is
168511
+** able to return a subtype.
168512
+*/
168513
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
168514
+ int n;
168515
+ FuncDef *pDef;
168516
+ sqlite3 *db;
168517
+ if( pExpr->op!=TK_FUNCTION ){
168518
+ return WRC_Prune;
168519
+ }
168520
+ assert( ExprUseXList(pExpr) );
168521
+ db = pWalker->pParse->db;
168522
+ n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
168523
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
168524
+ if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
168525
+ pWalker->eCode = 1;
168526
+ return WRC_Prune;
168527
+ }
168528
+ return WRC_Continue;
168529
+}
168530
+
168531
+/*
168532
+** Return TRUE if expression pExpr is able to return a subtype.
168533
+**
168534
+** A TRUE return does not guarantee that a subtype will be returned.
168535
+** It only indicates that a subtype return is possible. False positives
168536
+** are acceptable as they only disable an optimization. False negatives,
168537
+** on the other hand, can lead to incorrect answers.
168538
+*/
168539
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
168540
+ Walker w;
168541
+ memset(&w, 0, sizeof(w));
168542
+ w.pParse = pParse;
168543
+ w.xExprCallback = exprNodeCanReturnSubtype;
168544
+ sqlite3WalkExpr(&w, pExpr);
168545
+ return w.eCode;
168546
+}
167675168547
167676168548
/*
167677168549
** The index pIdx is used by a query and contains one or more expressions.
167678168550
** In other words pIdx is an index on an expression. iIdxCur is the cursor
167679168551
** number for the index and iDataCur is the cursor number for the corresponding
@@ -167696,37 +168568,23 @@
167696168568
assert( pIdx->bHasExpr );
167697168569
pTab = pIdx->pTable;
167698168570
for(i=0; i<pIdx->nColumn; i++){
167699168571
Expr *pExpr;
167700168572
int j = pIdx->aiColumn[i];
167701
- int bMaybeNullRow;
167702168573
if( j==XN_EXPR ){
167703168574
pExpr = pIdx->aColExpr->a[i].pExpr;
167704
- testcase( pTabItem->fg.jointype & JT_LEFT );
167705
- testcase( pTabItem->fg.jointype & JT_RIGHT );
167706
- testcase( pTabItem->fg.jointype & JT_LTORJ );
167707
- bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
167708168575
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
167709168576
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
167710
- bMaybeNullRow = 0;
167711168577
}else{
167712168578
continue;
167713168579
}
167714168580
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
167715
- if( pExpr->op==TK_FUNCTION ){
168581
+ if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
167716168582
/* Functions that might set a subtype should not be replaced by the
167717168583
** value taken from an expression index since the index omits the
167718168584
** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
167719
- int n;
167720
- FuncDef *pDef;
167721
- sqlite3 *db = pParse->db;
167722
- assert( ExprUseXList(pExpr) );
167723
- n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
167724
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
167725
- if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
167726
- continue;
167727
- }
168585
+ continue;
167728168586
}
167729168587
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
167730168588
if( p==0 ) break;
167731168589
p->pIENext = pParse->pIdxEpr;
167732168590
#ifdef WHERETRACE_ENABLED
@@ -167737,11 +168595,11 @@
167737168595
#endif
167738168596
p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
167739168597
p->iDataCur = pTabItem->iCursor;
167740168598
p->iIdxCur = iIdxCur;
167741168599
p->iIdxCol = i;
167742
- p->bMaybeNullRow = bMaybeNullRow;
168600
+ p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
167743168601
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
167744168602
p->aff = pIdx->zColAff[i];
167745168603
}
167746168604
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
167747168605
p->zIdxName = pIdx->zName;
@@ -167905,10 +168763,11 @@
167905168763
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
167906168764
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
167907168765
if( pOrderBy && pOrderBy->nExpr>=BMS ){
167908168766
pOrderBy = 0;
167909168767
wctrlFlags &= ~WHERE_WANT_DISTINCT;
168768
+ wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */
167910168769
}
167911168770
167912168771
/* The number of tables in the FROM clause is limited by the number of
167913168772
** bits in a Bitmask
167914168773
*/
@@ -168144,11 +169003,12 @@
168144169003
WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
168145169004
168146169005
wherePathSolver(pWInfo, 0);
168147169006
if( db->mallocFailed ) goto whereBeginError;
168148169007
if( pWInfo->pOrderBy ){
168149
- wherePathSolver(pWInfo, pWInfo->nRowOut+1);
169008
+ whereInterstageHeuristic(pWInfo);
169009
+ wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1);
168150169010
if( db->mallocFailed ) goto whereBeginError;
168151169011
}
168152169012
168153169013
/* TUNING: Assume that a DISTINCT clause on a subquery reduces
168154169014
** the output size by a factor of 8 (LogEst -30).
@@ -168204,14 +169064,14 @@
168204169064
** some C-compiler optimizers from in-lining the
168205169065
** sqlite3WhereCodeOneLoopStart() procedure, and it is important to
168206169066
** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
168207169067
*/
168208169068
notReady = ~(Bitmask)0;
168209
- if( pWInfo->nLevel>=2
168210
- && pResultSet!=0 /* these two combine to guarantee */
168211
- && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
168212
- && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
169069
+ if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */
169070
+ && pResultSet!=0 /* Condition (1) */
169071
+ && 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */
169072
+ && OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */
168213169073
){
168214169074
notReady = whereOmitNoopJoin(pWInfo, notReady);
168215169075
nTabList = pWInfo->nLevel;
168216169076
assert( nTabList>0 );
168217169077
}
@@ -168693,11 +169553,19 @@
168693169553
if( pLevel->iLeftJoin ){
168694169554
int ws = pLoop->wsFlags;
168695169555
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
168696169556
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
168697169557
if( (ws & WHERE_IDX_ONLY)==0 ){
168698
- assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
169558
+ SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
169559
+ assert( pLevel->iTabCur==pSrc->iCursor );
169560
+ if( pSrc->fg.viaCoroutine ){
169561
+ int m, n;
169562
+ n = pSrc->regResult;
169563
+ assert( pSrc->pTab!=0 );
169564
+ m = pSrc->pTab->nCol;
169565
+ sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
169566
+ }
168699169567
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
168700169568
}
168701169569
if( (ws & WHERE_INDEXED)
168702169570
|| ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx)
168703169571
){
@@ -169793,11 +170661,11 @@
169793170661
}
169794170662
if( bIntToNull ){
169795170663
int iDummy;
169796170664
Expr *pSub;
169797170665
pSub = sqlite3ExprSkipCollateAndLikely(pDup);
169798
- if( sqlite3ExprIsInteger(pSub, &iDummy) ){
170666
+ if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
169799170667
pSub->op = TK_NULL;
169800170668
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
169801170669
pSub->u.zToken = 0;
169802170670
}
169803170671
}
@@ -172270,139 +173138,139 @@
172270173138
#define TK_EACH 41
172271173139
#define TK_FAIL 42
172272173140
#define TK_OR 43
172273173141
#define TK_AND 44
172274173142
#define TK_IS 45
172275
-#define TK_MATCH 46
172276
-#define TK_LIKE_KW 47
172277
-#define TK_BETWEEN 48
172278
-#define TK_IN 49
172279
-#define TK_ISNULL 50
172280
-#define TK_NOTNULL 51
172281
-#define TK_NE 52
172282
-#define TK_EQ 53
172283
-#define TK_GT 54
172284
-#define TK_LE 55
172285
-#define TK_LT 56
172286
-#define TK_GE 57
172287
-#define TK_ESCAPE 58
172288
-#define TK_ID 59
172289
-#define TK_COLUMNKW 60
172290
-#define TK_DO 61
172291
-#define TK_FOR 62
172292
-#define TK_IGNORE 63
172293
-#define TK_INITIALLY 64
172294
-#define TK_INSTEAD 65
172295
-#define TK_NO 66
172296
-#define TK_KEY 67
172297
-#define TK_OF 68
172298
-#define TK_OFFSET 69
172299
-#define TK_PRAGMA 70
172300
-#define TK_RAISE 71
172301
-#define TK_RECURSIVE 72
172302
-#define TK_REPLACE 73
172303
-#define TK_RESTRICT 74
172304
-#define TK_ROW 75
172305
-#define TK_ROWS 76
172306
-#define TK_TRIGGER 77
172307
-#define TK_VACUUM 78
172308
-#define TK_VIEW 79
172309
-#define TK_VIRTUAL 80
172310
-#define TK_WITH 81
172311
-#define TK_NULLS 82
172312
-#define TK_FIRST 83
172313
-#define TK_LAST 84
172314
-#define TK_CURRENT 85
172315
-#define TK_FOLLOWING 86
172316
-#define TK_PARTITION 87
172317
-#define TK_PRECEDING 88
172318
-#define TK_RANGE 89
172319
-#define TK_UNBOUNDED 90
172320
-#define TK_EXCLUDE 91
172321
-#define TK_GROUPS 92
172322
-#define TK_OTHERS 93
172323
-#define TK_TIES 94
172324
-#define TK_GENERATED 95
172325
-#define TK_ALWAYS 96
172326
-#define TK_MATERIALIZED 97
172327
-#define TK_REINDEX 98
172328
-#define TK_RENAME 99
172329
-#define TK_CTIME_KW 100
172330
-#define TK_ANY 101
172331
-#define TK_BITAND 102
172332
-#define TK_BITOR 103
172333
-#define TK_LSHIFT 104
172334
-#define TK_RSHIFT 105
172335
-#define TK_PLUS 106
172336
-#define TK_MINUS 107
172337
-#define TK_STAR 108
172338
-#define TK_SLASH 109
172339
-#define TK_REM 110
172340
-#define TK_CONCAT 111
172341
-#define TK_PTR 112
172342
-#define TK_COLLATE 113
172343
-#define TK_BITNOT 114
172344
-#define TK_ON 115
172345
-#define TK_INDEXED 116
172346
-#define TK_STRING 117
172347
-#define TK_JOIN_KW 118
172348
-#define TK_CONSTRAINT 119
172349
-#define TK_DEFAULT 120
172350
-#define TK_NULL 121
172351
-#define TK_PRIMARY 122
172352
-#define TK_UNIQUE 123
172353
-#define TK_CHECK 124
172354
-#define TK_REFERENCES 125
172355
-#define TK_AUTOINCR 126
172356
-#define TK_INSERT 127
172357
-#define TK_DELETE 128
172358
-#define TK_UPDATE 129
172359
-#define TK_SET 130
172360
-#define TK_DEFERRABLE 131
172361
-#define TK_FOREIGN 132
172362
-#define TK_DROP 133
172363
-#define TK_UNION 134
172364
-#define TK_ALL 135
172365
-#define TK_EXCEPT 136
172366
-#define TK_INTERSECT 137
172367
-#define TK_SELECT 138
172368
-#define TK_VALUES 139
172369
-#define TK_DISTINCT 140
172370
-#define TK_DOT 141
172371
-#define TK_FROM 142
172372
-#define TK_JOIN 143
172373
-#define TK_USING 144
172374
-#define TK_ORDER 145
172375
-#define TK_GROUP 146
172376
-#define TK_HAVING 147
172377
-#define TK_LIMIT 148
172378
-#define TK_WHERE 149
172379
-#define TK_RETURNING 150
172380
-#define TK_INTO 151
172381
-#define TK_NOTHING 152
172382
-#define TK_FLOAT 153
172383
-#define TK_BLOB 154
172384
-#define TK_INTEGER 155
172385
-#define TK_VARIABLE 156
172386
-#define TK_CASE 157
172387
-#define TK_WHEN 158
172388
-#define TK_THEN 159
172389
-#define TK_ELSE 160
172390
-#define TK_INDEX 161
172391
-#define TK_ALTER 162
172392
-#define TK_ADD 163
172393
-#define TK_WINDOW 164
172394
-#define TK_OVER 165
172395
-#define TK_FILTER 166
172396
-#define TK_COLUMN 167
172397
-#define TK_AGG_FUNCTION 168
172398
-#define TK_AGG_COLUMN 169
172399
-#define TK_TRUEFALSE 170
172400
-#define TK_ISNOT 171
173143
+#define TK_ISNOT 46
173144
+#define TK_MATCH 47
173145
+#define TK_LIKE_KW 48
173146
+#define TK_BETWEEN 49
173147
+#define TK_IN 50
173148
+#define TK_ISNULL 51
173149
+#define TK_NOTNULL 52
173150
+#define TK_NE 53
173151
+#define TK_EQ 54
173152
+#define TK_GT 55
173153
+#define TK_LE 56
173154
+#define TK_LT 57
173155
+#define TK_GE 58
173156
+#define TK_ESCAPE 59
173157
+#define TK_ID 60
173158
+#define TK_COLUMNKW 61
173159
+#define TK_DO 62
173160
+#define TK_FOR 63
173161
+#define TK_IGNORE 64
173162
+#define TK_INITIALLY 65
173163
+#define TK_INSTEAD 66
173164
+#define TK_NO 67
173165
+#define TK_KEY 68
173166
+#define TK_OF 69
173167
+#define TK_OFFSET 70
173168
+#define TK_PRAGMA 71
173169
+#define TK_RAISE 72
173170
+#define TK_RECURSIVE 73
173171
+#define TK_REPLACE 74
173172
+#define TK_RESTRICT 75
173173
+#define TK_ROW 76
173174
+#define TK_ROWS 77
173175
+#define TK_TRIGGER 78
173176
+#define TK_VACUUM 79
173177
+#define TK_VIEW 80
173178
+#define TK_VIRTUAL 81
173179
+#define TK_WITH 82
173180
+#define TK_NULLS 83
173181
+#define TK_FIRST 84
173182
+#define TK_LAST 85
173183
+#define TK_CURRENT 86
173184
+#define TK_FOLLOWING 87
173185
+#define TK_PARTITION 88
173186
+#define TK_PRECEDING 89
173187
+#define TK_RANGE 90
173188
+#define TK_UNBOUNDED 91
173189
+#define TK_EXCLUDE 92
173190
+#define TK_GROUPS 93
173191
+#define TK_OTHERS 94
173192
+#define TK_TIES 95
173193
+#define TK_GENERATED 96
173194
+#define TK_ALWAYS 97
173195
+#define TK_MATERIALIZED 98
173196
+#define TK_REINDEX 99
173197
+#define TK_RENAME 100
173198
+#define TK_CTIME_KW 101
173199
+#define TK_ANY 102
173200
+#define TK_BITAND 103
173201
+#define TK_BITOR 104
173202
+#define TK_LSHIFT 105
173203
+#define TK_RSHIFT 106
173204
+#define TK_PLUS 107
173205
+#define TK_MINUS 108
173206
+#define TK_STAR 109
173207
+#define TK_SLASH 110
173208
+#define TK_REM 111
173209
+#define TK_CONCAT 112
173210
+#define TK_PTR 113
173211
+#define TK_COLLATE 114
173212
+#define TK_BITNOT 115
173213
+#define TK_ON 116
173214
+#define TK_INDEXED 117
173215
+#define TK_STRING 118
173216
+#define TK_JOIN_KW 119
173217
+#define TK_CONSTRAINT 120
173218
+#define TK_DEFAULT 121
173219
+#define TK_NULL 122
173220
+#define TK_PRIMARY 123
173221
+#define TK_UNIQUE 124
173222
+#define TK_CHECK 125
173223
+#define TK_REFERENCES 126
173224
+#define TK_AUTOINCR 127
173225
+#define TK_INSERT 128
173226
+#define TK_DELETE 129
173227
+#define TK_UPDATE 130
173228
+#define TK_SET 131
173229
+#define TK_DEFERRABLE 132
173230
+#define TK_FOREIGN 133
173231
+#define TK_DROP 134
173232
+#define TK_UNION 135
173233
+#define TK_ALL 136
173234
+#define TK_EXCEPT 137
173235
+#define TK_INTERSECT 138
173236
+#define TK_SELECT 139
173237
+#define TK_VALUES 140
173238
+#define TK_DISTINCT 141
173239
+#define TK_DOT 142
173240
+#define TK_FROM 143
173241
+#define TK_JOIN 144
173242
+#define TK_USING 145
173243
+#define TK_ORDER 146
173244
+#define TK_GROUP 147
173245
+#define TK_HAVING 148
173246
+#define TK_LIMIT 149
173247
+#define TK_WHERE 150
173248
+#define TK_RETURNING 151
173249
+#define TK_INTO 152
173250
+#define TK_NOTHING 153
173251
+#define TK_FLOAT 154
173252
+#define TK_BLOB 155
173253
+#define TK_INTEGER 156
173254
+#define TK_VARIABLE 157
173255
+#define TK_CASE 158
173256
+#define TK_WHEN 159
173257
+#define TK_THEN 160
173258
+#define TK_ELSE 161
173259
+#define TK_INDEX 162
173260
+#define TK_ALTER 163
173261
+#define TK_ADD 164
173262
+#define TK_WINDOW 165
173263
+#define TK_OVER 166
173264
+#define TK_FILTER 167
173265
+#define TK_COLUMN 168
173266
+#define TK_AGG_FUNCTION 169
173267
+#define TK_AGG_COLUMN 170
173268
+#define TK_TRUEFALSE 171
172401173269
#define TK_FUNCTION 172
172402
-#define TK_UMINUS 173
172403
-#define TK_UPLUS 174
173270
+#define TK_UPLUS 173
173271
+#define TK_UMINUS 174
172404173272
#define TK_TRUTH 175
172405173273
#define TK_REGISTER 176
172406173274
#define TK_VECTOR 177
172407173275
#define TK_SELECT_COLUMN 178
172408173276
#define TK_IF_NULL_ROW 179
@@ -172476,11 +173344,11 @@
172476173344
#endif
172477173345
/************* Begin control #defines *****************************************/
172478173346
#define YYCODETYPE unsigned short int
172479173347
#define YYNOCODE 322
172480173348
#define YYACTIONTYPE unsigned short int
172481
-#define YYWILDCARD 101
173349
+#define YYWILDCARD 102
172482173350
#define sqlite3ParserTOKENTYPE Token
172483173351
typedef union {
172484173352
int yyinit;
172485173353
sqlite3ParserTOKENTYPE yy0;
172486173354
ExprList* yy14;
@@ -172613,450 +173481,456 @@
172613173481
** yy_reduce_ofst[] For each state, the offset into yy_action for
172614173482
** shifting non-terminals after a reduce.
172615173483
** yy_default[] Default action for each state.
172616173484
**
172617173485
*********** Begin parsing tables **********************************************/
172618
-#define YY_ACTTAB_COUNT (2142)
173486
+#define YY_ACTTAB_COUNT (2207)
172619173487
static const YYACTIONTYPE yy_action[] = {
172620
- /* 0 */ 576, 128, 125, 232, 1622, 549, 576, 1290, 1281, 576,
172621
- /* 10 */ 328, 576, 1300, 212, 576, 128, 125, 232, 578, 412,
172622
- /* 20 */ 578, 391, 1542, 51, 51, 523, 405, 1293, 529, 51,
172623
- /* 30 */ 51, 983, 51, 51, 81, 81, 1107, 61, 61, 984,
172624
- /* 40 */ 1107, 1292, 380, 135, 136, 90, 1228, 1228, 1063, 1066,
172625
- /* 50 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 1577, 412,
172626
- /* 60 */ 287, 287, 7, 287, 287, 422, 1050, 1050, 1064, 1067,
172627
- /* 70 */ 289, 556, 492, 573, 524, 561, 573, 497, 561, 482,
172628
- /* 80 */ 530, 262, 229, 135, 136, 90, 1228, 1228, 1063, 1066,
172629
- /* 90 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 128, 125,
172630
- /* 100 */ 232, 1506, 132, 132, 132, 132, 131, 131, 130, 130,
172631
- /* 110 */ 130, 129, 126, 450, 1204, 1255, 1, 1, 582, 2,
172632
- /* 120 */ 1259, 1571, 420, 1582, 379, 320, 1174, 153, 1174, 1584,
172633
- /* 130 */ 412, 378, 1582, 543, 1341, 330, 111, 570, 570, 570,
172634
- /* 140 */ 293, 1054, 132, 132, 132, 132, 131, 131, 130, 130,
172635
- /* 150 */ 130, 129, 126, 450, 135, 136, 90, 1228, 1228, 1063,
172636
- /* 160 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 287,
172637
- /* 170 */ 287, 1204, 1205, 1204, 255, 287, 287, 510, 507, 506,
172638
- /* 180 */ 137, 455, 573, 212, 561, 447, 446, 505, 573, 1616,
172639
- /* 190 */ 561, 134, 134, 134, 134, 127, 400, 243, 132, 132,
172640
- /* 200 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
172641
- /* 210 */ 282, 471, 345, 132, 132, 132, 132, 131, 131, 130,
172642
- /* 220 */ 130, 130, 129, 126, 450, 574, 155, 936, 936, 454,
172643
- /* 230 */ 227, 521, 1236, 412, 1236, 134, 134, 134, 134, 132,
172644
- /* 240 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
172645
- /* 250 */ 450, 130, 130, 130, 129, 126, 450, 135, 136, 90,
172646
- /* 260 */ 1228, 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134,
172647
- /* 270 */ 134, 134, 128, 125, 232, 450, 576, 412, 397, 1249,
172648
- /* 280 */ 180, 92, 93, 132, 132, 132, 132, 131, 131, 130,
172649
- /* 290 */ 130, 130, 129, 126, 450, 381, 387, 1204, 383, 81,
172650
- /* 300 */ 81, 135, 136, 90, 1228, 1228, 1063, 1066, 1053, 1053,
172651
- /* 310 */ 133, 133, 134, 134, 134, 134, 132, 132, 132, 132,
172652
- /* 320 */ 131, 131, 130, 130, 130, 129, 126, 450, 131, 131,
172653
- /* 330 */ 130, 130, 130, 129, 126, 450, 556, 1204, 302, 319,
172654
- /* 340 */ 567, 121, 568, 480, 4, 555, 1149, 1657, 1628, 1657,
172655
- /* 350 */ 45, 128, 125, 232, 1204, 1205, 1204, 1250, 571, 1169,
172656
- /* 360 */ 132, 132, 132, 132, 131, 131, 130, 130, 130, 129,
172657
- /* 370 */ 126, 450, 1169, 287, 287, 1169, 1019, 576, 422, 1019,
172658
- /* 380 */ 412, 451, 1602, 582, 2, 1259, 573, 44, 561, 95,
172659
- /* 390 */ 320, 110, 153, 565, 1204, 1205, 1204, 522, 522, 1341,
172660
- /* 400 */ 81, 81, 7, 44, 135, 136, 90, 1228, 1228, 1063,
172661
- /* 410 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 295,
172662
- /* 420 */ 1149, 1658, 1040, 1658, 1204, 1147, 319, 567, 119, 119,
172663
- /* 430 */ 343, 466, 331, 343, 287, 287, 120, 556, 451, 577,
172664
- /* 440 */ 451, 1169, 1169, 1028, 319, 567, 438, 573, 210, 561,
172665
- /* 450 */ 1339, 1451, 546, 531, 1169, 1169, 1598, 1169, 1169, 416,
172666
- /* 460 */ 319, 567, 243, 132, 132, 132, 132, 131, 131, 130,
172667
- /* 470 */ 130, 130, 129, 126, 450, 1028, 1028, 1030, 1031, 35,
172668
- /* 480 */ 44, 1204, 1205, 1204, 472, 287, 287, 1328, 412, 1307,
172669
- /* 490 */ 372, 1595, 359, 225, 454, 1204, 195, 1328, 573, 1147,
172670
- /* 500 */ 561, 1333, 1333, 274, 576, 1188, 576, 340, 46, 196,
172671
- /* 510 */ 537, 217, 135, 136, 90, 1228, 1228, 1063, 1066, 1053,
172672
- /* 520 */ 1053, 133, 133, 134, 134, 134, 134, 19, 19, 19,
172673
- /* 530 */ 19, 412, 581, 1204, 1259, 511, 1204, 319, 567, 320,
172674
- /* 540 */ 944, 153, 425, 491, 430, 943, 1204, 488, 1341, 1450,
172675
- /* 550 */ 532, 1277, 1204, 1205, 1204, 135, 136, 90, 1228, 1228,
172676
- /* 560 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172677
- /* 570 */ 575, 132, 132, 132, 132, 131, 131, 130, 130, 130,
172678
- /* 580 */ 129, 126, 450, 287, 287, 528, 287, 287, 372, 1595,
172679
- /* 590 */ 1204, 1205, 1204, 1204, 1205, 1204, 573, 486, 561, 573,
172680
- /* 600 */ 889, 561, 412, 1204, 1205, 1204, 886, 40, 22, 22,
172681
- /* 610 */ 220, 243, 525, 1449, 132, 132, 132, 132, 131, 131,
172682
- /* 620 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172683
- /* 630 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172684
- /* 640 */ 134, 412, 180, 454, 1204, 879, 255, 287, 287, 510,
172685
- /* 650 */ 507, 506, 372, 1595, 1568, 1331, 1331, 576, 889, 505,
172686
- /* 660 */ 573, 44, 561, 559, 1207, 135, 136, 90, 1228, 1228,
172687
- /* 670 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172688
- /* 680 */ 81, 81, 422, 576, 377, 132, 132, 132, 132, 131,
172689
- /* 690 */ 131, 130, 130, 130, 129, 126, 450, 297, 287, 287,
172690
- /* 700 */ 460, 1204, 1205, 1204, 1204, 534, 19, 19, 448, 448,
172691
- /* 710 */ 448, 573, 412, 561, 230, 436, 1187, 535, 319, 567,
172692
- /* 720 */ 363, 432, 1207, 1435, 132, 132, 132, 132, 131, 131,
172693
- /* 730 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172694
- /* 740 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172695
- /* 750 */ 134, 412, 211, 949, 1169, 1041, 1110, 1110, 494, 547,
172696
- /* 760 */ 547, 1204, 1205, 1204, 7, 539, 1570, 1169, 376, 576,
172697
- /* 770 */ 1169, 5, 1204, 486, 3, 135, 136, 90, 1228, 1228,
172698
- /* 780 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172699
- /* 790 */ 576, 513, 19, 19, 427, 132, 132, 132, 132, 131,
172700
- /* 800 */ 131, 130, 130, 130, 129, 126, 450, 305, 1204, 433,
172701
- /* 810 */ 225, 1204, 385, 19, 19, 273, 290, 371, 516, 366,
172702
- /* 820 */ 515, 260, 412, 538, 1568, 549, 1024, 362, 437, 1204,
172703
- /* 830 */ 1205, 1204, 902, 1552, 132, 132, 132, 132, 131, 131,
172704
- /* 840 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172705
- /* 850 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172706
- /* 860 */ 134, 412, 1435, 514, 1281, 1204, 1205, 1204, 1204, 1205,
172707
- /* 870 */ 1204, 903, 48, 342, 1568, 1568, 1279, 1627, 1568, 911,
172708
- /* 880 */ 576, 129, 126, 450, 110, 135, 136, 90, 1228, 1228,
172709
- /* 890 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172710
- /* 900 */ 265, 576, 459, 19, 19, 132, 132, 132, 132, 131,
172711
- /* 910 */ 131, 130, 130, 130, 129, 126, 450, 1345, 204, 576,
172712
- /* 920 */ 459, 458, 50, 47, 19, 19, 49, 434, 1105, 573,
172713
- /* 930 */ 497, 561, 412, 428, 108, 1224, 1569, 1554, 376, 205,
172714
- /* 940 */ 550, 550, 81, 81, 132, 132, 132, 132, 131, 131,
172715
- /* 950 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172716
- /* 960 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172717
- /* 970 */ 134, 480, 576, 1204, 576, 1541, 412, 1435, 969, 315,
172718
- /* 980 */ 1659, 398, 284, 497, 969, 893, 1569, 1569, 376, 376,
172719
- /* 990 */ 1569, 461, 376, 1224, 459, 80, 80, 81, 81, 497,
172720
- /* 1000 */ 374, 114, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133,
172721
- /* 1010 */ 133, 134, 134, 134, 134, 132, 132, 132, 132, 131,
172722
- /* 1020 */ 131, 130, 130, 130, 129, 126, 450, 1204, 1505, 576,
172723
- /* 1030 */ 1204, 1205, 1204, 1366, 316, 486, 281, 281, 497, 431,
172724
- /* 1040 */ 557, 288, 288, 402, 1340, 471, 345, 298, 429, 573,
172725
- /* 1050 */ 576, 561, 81, 81, 573, 374, 561, 971, 386, 132,
172726
- /* 1060 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
172727
- /* 1070 */ 450, 231, 117, 81, 81, 287, 287, 231, 287, 287,
172728
- /* 1080 */ 576, 1511, 576, 1336, 1204, 1205, 1204, 139, 573, 556,
172729
- /* 1090 */ 561, 573, 412, 561, 441, 456, 969, 213, 558, 1511,
172730
- /* 1100 */ 1513, 1550, 969, 143, 143, 145, 145, 1368, 314, 478,
172731
- /* 1110 */ 444, 970, 412, 850, 851, 852, 135, 136, 90, 1228,
172732
- /* 1120 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172733
- /* 1130 */ 134, 357, 412, 397, 1148, 304, 135, 136, 90, 1228,
172734
- /* 1140 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172735
- /* 1150 */ 134, 1575, 323, 6, 862, 7, 135, 124, 90, 1228,
172736
- /* 1160 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172737
- /* 1170 */ 134, 409, 408, 1511, 212, 132, 132, 132, 132, 131,
172738
- /* 1180 */ 131, 130, 130, 130, 129, 126, 450, 411, 118, 1204,
172739
- /* 1190 */ 116, 10, 352, 265, 355, 132, 132, 132, 132, 131,
172740
- /* 1200 */ 131, 130, 130, 130, 129, 126, 450, 576, 324, 306,
172741
- /* 1210 */ 576, 306, 1250, 469, 158, 132, 132, 132, 132, 131,
172742
- /* 1220 */ 131, 130, 130, 130, 129, 126, 450, 207, 1224, 1126,
172743
- /* 1230 */ 65, 65, 470, 66, 66, 412, 447, 446, 882, 531,
172744
- /* 1240 */ 335, 258, 257, 256, 1127, 1233, 1204, 1205, 1204, 327,
172745
- /* 1250 */ 1235, 874, 159, 576, 16, 480, 1085, 1040, 1234, 1128,
172746
- /* 1260 */ 136, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133, 133,
172747
- /* 1270 */ 134, 134, 134, 134, 1029, 576, 81, 81, 1028, 1040,
172748
- /* 1280 */ 922, 576, 463, 1236, 576, 1236, 1224, 502, 107, 1435,
172749
- /* 1290 */ 923, 6, 576, 410, 1498, 882, 1029, 480, 21, 21,
172750
- /* 1300 */ 1028, 332, 1380, 334, 53, 53, 497, 81, 81, 874,
172751
- /* 1310 */ 1028, 1028, 1030, 445, 259, 19, 19, 533, 132, 132,
172752
- /* 1320 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
172753
- /* 1330 */ 551, 301, 1028, 1028, 1030, 107, 532, 545, 121, 568,
172754
- /* 1340 */ 1188, 4, 1126, 1576, 449, 576, 462, 7, 1282, 418,
172755
- /* 1350 */ 462, 350, 1435, 576, 518, 571, 544, 1127, 121, 568,
172756
- /* 1360 */ 442, 4, 1188, 464, 533, 1180, 1223, 9, 67, 67,
172757
- /* 1370 */ 487, 576, 1128, 303, 410, 571, 54, 54, 451, 576,
172758
- /* 1380 */ 123, 944, 576, 417, 576, 333, 943, 1379, 576, 236,
172759
- /* 1390 */ 565, 576, 1574, 564, 68, 68, 7, 576, 451, 362,
172760
- /* 1400 */ 419, 182, 69, 69, 541, 70, 70, 71, 71, 540,
172761
- /* 1410 */ 565, 72, 72, 484, 55, 55, 473, 1180, 296, 1040,
172762
- /* 1420 */ 56, 56, 296, 493, 541, 119, 119, 410, 1573, 542,
172763
- /* 1430 */ 569, 418, 7, 120, 1244, 451, 577, 451, 465, 1040,
172764
- /* 1440 */ 1028, 576, 1557, 552, 476, 119, 119, 527, 259, 121,
172765
- /* 1450 */ 568, 240, 4, 120, 576, 451, 577, 451, 576, 477,
172766
- /* 1460 */ 1028, 576, 156, 576, 57, 57, 571, 576, 286, 229,
172767
- /* 1470 */ 410, 336, 1028, 1028, 1030, 1031, 35, 59, 59, 219,
172768
- /* 1480 */ 983, 60, 60, 220, 73, 73, 74, 74, 984, 451,
172769
- /* 1490 */ 75, 75, 1028, 1028, 1030, 1031, 35, 96, 216, 291,
172770
- /* 1500 */ 552, 565, 1188, 318, 395, 395, 394, 276, 392, 576,
172771
- /* 1510 */ 485, 859, 474, 1311, 410, 541, 576, 417, 1530, 1144,
172772
- /* 1520 */ 540, 399, 1188, 292, 237, 1153, 326, 38, 23, 576,
172773
- /* 1530 */ 1040, 576, 20, 20, 325, 299, 119, 119, 164, 76,
172774
- /* 1540 */ 76, 1529, 121, 568, 120, 4, 451, 577, 451, 203,
172775
- /* 1550 */ 576, 1028, 141, 141, 142, 142, 576, 322, 39, 571,
172776
- /* 1560 */ 341, 1021, 110, 264, 239, 901, 900, 423, 242, 908,
172777
- /* 1570 */ 909, 370, 173, 77, 77, 43, 479, 1310, 264, 62,
172778
- /* 1580 */ 62, 369, 451, 1028, 1028, 1030, 1031, 35, 1601, 1192,
172779
- /* 1590 */ 453, 1092, 238, 291, 565, 163, 1309, 110, 395, 395,
172780
- /* 1600 */ 394, 276, 392, 986, 987, 859, 481, 346, 264, 110,
172781
- /* 1610 */ 1032, 489, 576, 1188, 503, 1088, 261, 261, 237, 576,
172782
- /* 1620 */ 326, 121, 568, 1040, 4, 347, 1376, 413, 325, 119,
172783
- /* 1630 */ 119, 948, 319, 567, 351, 78, 78, 120, 571, 451,
172784
- /* 1640 */ 577, 451, 79, 79, 1028, 354, 356, 576, 360, 1092,
172785
- /* 1650 */ 110, 576, 974, 942, 264, 123, 457, 358, 239, 576,
172786
- /* 1660 */ 519, 451, 939, 1104, 123, 1104, 173, 576, 1032, 43,
172787
- /* 1670 */ 63, 63, 1324, 565, 168, 168, 1028, 1028, 1030, 1031,
172788
- /* 1680 */ 35, 576, 169, 169, 1308, 872, 238, 157, 1589, 576,
172789
- /* 1690 */ 86, 86, 365, 89, 568, 375, 4, 1103, 941, 1103,
172790
- /* 1700 */ 123, 576, 1040, 1389, 64, 64, 1188, 1434, 119, 119,
172791
- /* 1710 */ 571, 576, 82, 82, 563, 576, 120, 165, 451, 577,
172792
- /* 1720 */ 451, 413, 1362, 1028, 144, 144, 319, 567, 576, 1374,
172793
- /* 1730 */ 562, 498, 279, 451, 83, 83, 1439, 576, 166, 166,
172794
- /* 1740 */ 576, 1289, 554, 576, 1280, 565, 576, 12, 576, 1268,
172795
- /* 1750 */ 457, 146, 146, 1267, 576, 1028, 1028, 1030, 1031, 35,
172796
- /* 1760 */ 140, 140, 1269, 167, 167, 1609, 160, 160, 1359, 150,
172797
- /* 1770 */ 150, 149, 149, 311, 1040, 576, 312, 147, 147, 313,
172798
- /* 1780 */ 119, 119, 222, 235, 576, 1188, 396, 576, 120, 576,
172799
- /* 1790 */ 451, 577, 451, 1192, 453, 1028, 508, 291, 148, 148,
172800
- /* 1800 */ 1421, 1612, 395, 395, 394, 276, 392, 85, 85, 859,
172801
- /* 1810 */ 87, 87, 84, 84, 553, 576, 294, 576, 1426, 338,
172802
- /* 1820 */ 339, 1425, 237, 300, 326, 1416, 1409, 1028, 1028, 1030,
172803
- /* 1830 */ 1031, 35, 325, 344, 403, 483, 226, 1307, 52, 52,
172804
- /* 1840 */ 58, 58, 368, 1371, 1502, 566, 1501, 121, 568, 221,
172805
- /* 1850 */ 4, 208, 268, 209, 390, 1244, 1549, 1188, 1372, 1370,
172806
- /* 1860 */ 1369, 1547, 239, 184, 571, 233, 421, 1241, 95, 218,
172807
- /* 1870 */ 173, 1507, 193, 43, 91, 94, 178, 186, 467, 188,
172808
- /* 1880 */ 468, 1422, 13, 189, 190, 191, 501, 451, 245, 108,
172809
- /* 1890 */ 238, 401, 1428, 1427, 1430, 475, 404, 1496, 197, 565,
172810
- /* 1900 */ 14, 490, 249, 101, 1518, 496, 349, 280, 251, 201,
172811
- /* 1910 */ 353, 499, 252, 406, 1270, 253, 517, 1327, 1326, 435,
172812
- /* 1920 */ 1325, 1318, 103, 893, 1296, 413, 227, 407, 1040, 1626,
172813
- /* 1930 */ 319, 567, 1625, 1297, 119, 119, 439, 367, 1317, 1295,
172814
- /* 1940 */ 1624, 526, 120, 440, 451, 577, 451, 1594, 309, 1028,
172815
- /* 1950 */ 310, 373, 266, 267, 457, 1580, 1579, 443, 138, 1394,
172816
- /* 1960 */ 552, 1393, 11, 1483, 384, 115, 317, 1350, 109, 536,
172817
- /* 1970 */ 42, 579, 382, 214, 1349, 388, 1198, 389, 275, 277,
172818
- /* 1980 */ 278, 1028, 1028, 1030, 1031, 35, 580, 1265, 414, 1260,
172819
- /* 1990 */ 170, 415, 183, 1534, 1535, 1533, 171, 154, 307, 1532,
172820
- /* 2000 */ 846, 223, 224, 88, 452, 215, 172, 321, 234, 1102,
172821
- /* 2010 */ 152, 1188, 1100, 329, 185, 174, 1223, 925, 187, 241,
172822
- /* 2020 */ 337, 244, 1116, 192, 175, 176, 424, 426, 97, 194,
172823
- /* 2030 */ 98, 99, 100, 177, 1119, 1115, 246, 247, 161, 24,
172824
- /* 2040 */ 248, 348, 1238, 264, 1108, 250, 495, 199, 198, 15,
172825
- /* 2050 */ 861, 500, 369, 254, 504, 509, 512, 200, 102, 25,
172826
- /* 2060 */ 179, 361, 26, 364, 104, 891, 308, 162, 105, 904,
172827
- /* 2070 */ 520, 106, 1185, 1069, 1155, 17, 228, 27, 1154, 283,
172828
- /* 2080 */ 285, 263, 978, 202, 972, 123, 28, 1175, 29, 30,
172829
- /* 2090 */ 1179, 1171, 31, 1173, 1160, 41, 32, 206, 548, 33,
172830
- /* 2100 */ 110, 1178, 1083, 8, 112, 1070, 113, 1068, 1072, 34,
172831
- /* 2110 */ 1073, 560, 1125, 269, 1124, 270, 36, 18, 1194, 1033,
172832
- /* 2120 */ 873, 151, 122, 37, 393, 271, 272, 572, 181, 1193,
172833
- /* 2130 */ 1256, 1256, 1256, 935, 1256, 1256, 1256, 1256, 1256, 1256,
172834
- /* 2140 */ 1256, 1617,
173488
+ /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289,
173489
+ /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413,
173490
+ /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82,
173491
+ /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984,
173492
+ /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063,
173493
+ /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413,
173494
+ /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130,
173495
+ /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290,
173496
+ /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063,
173497
+ /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296,
173498
+ /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132,
173499
+ /* 110 */ 132, 132, 131, 128, 451, 44, 1050, 1050, 1064, 1067,
173500
+ /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174,
173501
+ /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 498, 1341,
173502
+ /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132,
173503
+ /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 1105, 1228,
173504
+ /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136,
173505
+ /* 170 */ 136, 1204, 320, 567, 288, 288, 283, 288, 288, 523,
173506
+ /* 180 */ 523, 1250, 139, 1541, 7, 214, 503, 573, 1169, 562,
173507
+ /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 401, 547,
173508
+ /* 200 */ 487, 1169, 245, 1568, 1169, 245, 133, 133, 132, 132,
173509
+ /* 210 */ 132, 131, 128, 451, 261, 134, 134, 134, 134, 133,
173510
+ /* 220 */ 133, 132, 132, 132, 131, 128, 451, 451, 1204, 1205,
173511
+ /* 230 */ 1204, 130, 127, 234, 455, 413, 182, 455, 130, 127,
173512
+ /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132,
173513
+ /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 576, 137,
173514
+ /* 260 */ 138, 91, 261, 1228, 1228, 1063, 1066, 1053, 1053, 135,
173515
+ /* 270 */ 135, 136, 136, 136, 136, 44, 472, 346, 1204, 472,
173516
+ /* 280 */ 346, 51, 51, 418, 93, 157, 134, 134, 134, 134,
173517
+ /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 166, 363,
173518
+ /* 300 */ 298, 134, 134, 134, 134, 133, 133, 132, 132, 132,
173519
+ /* 310 */ 131, 128, 451, 1293, 461, 1570, 423, 377, 275, 134,
173520
+ /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128,
173521
+ /* 330 */ 451, 418, 320, 567, 1292, 1204, 1205, 1204, 257, 413,
173522
+ /* 340 */ 483, 511, 508, 507, 94, 132, 132, 132, 131, 128,
173523
+ /* 350 */ 451, 506, 1204, 548, 548, 388, 576, 384, 7, 413,
173524
+ /* 360 */ 550, 229, 522, 137, 138, 91, 530, 1228, 1228, 1063,
173525
+ /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 51,
173526
+ /* 380 */ 51, 1582, 380, 137, 138, 91, 331, 1228, 1228, 1063,
173527
+ /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 320,
173528
+ /* 400 */ 567, 288, 288, 320, 567, 1602, 582, 2, 1259, 1204,
173529
+ /* 410 */ 1205, 1204, 1628, 321, 573, 155, 562, 576, 1511, 264,
173530
+ /* 420 */ 231, 520, 1341, 134, 134, 134, 134, 133, 133, 132,
173531
+ /* 430 */ 132, 132, 131, 128, 451, 519, 1511, 1513, 1333, 1333,
173532
+ /* 440 */ 82, 82, 498, 134, 134, 134, 134, 133, 133, 132,
173533
+ /* 450 */ 132, 132, 131, 128, 451, 1435, 257, 288, 288, 511,
173534
+ /* 460 */ 508, 507, 944, 1568, 413, 1019, 1204, 943, 360, 506,
173535
+ /* 470 */ 573, 1598, 562, 44, 575, 551, 551, 557, 1107, 1582,
173536
+ /* 480 */ 544, 576, 1107, 40, 417, 245, 531, 1505, 137, 138,
173537
+ /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
173538
+ /* 500 */ 136, 136, 136, 136, 81, 81, 1281, 1204, 413, 553,
173539
+ /* 510 */ 1511, 48, 512, 448, 447, 493, 578, 455, 578, 344,
173540
+ /* 520 */ 45, 1204, 1233, 1204, 1205, 1204, 428, 1235, 158, 882,
173541
+ /* 530 */ 320, 567, 137, 138, 91, 1234, 1228, 1228, 1063, 1066,
173542
+ /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134,
173543
+ /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
173544
+ /* 560 */ 1236, 576, 1236, 329, 1204, 1205, 1204, 387, 492, 403,
173545
+ /* 570 */ 1040, 382, 489, 123, 568, 1569, 4, 377, 1204, 1205,
173546
+ /* 580 */ 1204, 570, 570, 570, 82, 82, 882, 1029, 1331, 1331,
173547
+ /* 590 */ 571, 1028, 134, 134, 134, 134, 133, 133, 132, 132,
173548
+ /* 600 */ 132, 131, 128, 451, 288, 288, 1281, 1204, 576, 423,
173549
+ /* 610 */ 576, 1568, 413, 423, 452, 378, 886, 573, 1279, 562,
173550
+ /* 620 */ 46, 557, 532, 1028, 1028, 1030, 565, 130, 127, 234,
173551
+ /* 630 */ 556, 82, 82, 82, 82, 479, 137, 138, 91, 462,
173552
+ /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173553
+ /* 650 */ 136, 136, 1188, 487, 1506, 1040, 413, 6, 1204, 50,
173554
+ /* 660 */ 879, 121, 121, 948, 1204, 1205, 1204, 358, 557, 122,
173555
+ /* 670 */ 316, 452, 577, 452, 535, 1204, 1028, 439, 303, 212,
173556
+ /* 680 */ 137, 138, 91, 213, 1228, 1228, 1063, 1066, 1053, 1053,
173557
+ /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134,
173558
+ /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028,
173559
+ /* 710 */ 1030, 1031, 35, 288, 288, 1204, 1205, 1204, 1040, 1339,
173560
+ /* 720 */ 533, 123, 568, 1569, 4, 377, 573, 1019, 562, 353,
173561
+ /* 730 */ 1277, 356, 1204, 1205, 1204, 1029, 488, 1188, 571, 1028,
173562
+ /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173563
+ /* 750 */ 128, 451, 576, 343, 288, 288, 449, 449, 449, 971,
173564
+ /* 760 */ 413, 1627, 452, 911, 1187, 288, 288, 573, 464, 562,
173565
+ /* 770 */ 238, 1028, 1028, 1030, 565, 82, 82, 498, 573, 411,
173566
+ /* 780 */ 562, 344, 467, 332, 137, 138, 91, 197, 1228, 1228,
173567
+ /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173568
+ /* 800 */ 1188, 528, 1169, 1040, 413, 1110, 1110, 495, 1041, 121,
173569
+ /* 810 */ 121, 1204, 317, 540, 862, 1169, 1244, 122, 1169, 452,
173570
+ /* 820 */ 577, 452, 1340, 198, 1028, 1204, 481, 526, 137, 138,
173571
+ /* 830 */ 91, 560, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
173572
+ /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133,
173573
+ /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031,
173574
+ /* 860 */ 35, 1204, 288, 288, 1204, 477, 288, 288, 1204, 1205,
173575
+ /* 870 */ 1204, 539, 481, 437, 470, 573, 1451, 562, 364, 573,
173576
+ /* 880 */ 1153, 562, 1204, 1205, 1204, 1188, 5, 576, 134, 134,
173577
+ /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
173578
+ /* 900 */ 221, 214, 302, 96, 1149, 1657, 232, 1657, 413, 392,
173579
+ /* 910 */ 19, 19, 1024, 949, 406, 373, 1595, 1085, 1204, 1205,
173580
+ /* 920 */ 1204, 1204, 1205, 1204, 1204, 426, 1149, 1658, 413, 1658,
173581
+ /* 930 */ 1659, 399, 137, 138, 91, 3, 1228, 1228, 1063, 1066,
173582
+ /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 304, 1311,
173583
+ /* 950 */ 514, 1204, 137, 138, 91, 1498, 1228, 1228, 1063, 1066,
173584
+ /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 131,
173585
+ /* 970 */ 128, 451, 375, 1204, 274, 291, 372, 517, 367, 516,
173586
+ /* 980 */ 262, 1204, 1205, 1204, 1147, 227, 363, 448, 447, 1435,
173587
+ /* 990 */ 1568, 1310, 134, 134, 134, 134, 133, 133, 132, 132,
173588
+ /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 487, 1204, 1205,
173589
+ /* 1010 */ 1204, 442, 134, 134, 134, 134, 133, 133, 132, 132,
173590
+ /* 1020 */ 132, 131, 128, 451, 386, 576, 485, 576, 19, 19,
173591
+ /* 1030 */ 1204, 1205, 1204, 1345, 1236, 970, 1236, 574, 47, 936,
173592
+ /* 1040 */ 936, 473, 413, 431, 1552, 573, 1125, 562, 19, 19,
173593
+ /* 1050 */ 19, 19, 49, 336, 850, 851, 852, 111, 1368, 315,
173594
+ /* 1060 */ 429, 576, 413, 433, 341, 306, 137, 138, 91, 115,
173595
+ /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173596
+ /* 1080 */ 136, 136, 576, 1309, 82, 82, 137, 138, 91, 529,
173597
+ /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173598
+ /* 1100 */ 136, 136, 1569, 222, 377, 19, 19, 305, 1126, 1169,
173599
+ /* 1110 */ 398, 1148, 22, 22, 498, 333, 1569, 335, 377, 576,
173600
+ /* 1120 */ 438, 445, 1169, 1127, 486, 1169, 134, 134, 134, 134,
173601
+ /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576,
173602
+ /* 1140 */ 902, 576, 145, 145, 6, 576, 134, 134, 134, 134,
173603
+ /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 214, 1336,
173604
+ /* 1160 */ 922, 576, 19, 19, 19, 19, 1282, 419, 19, 19,
173605
+ /* 1170 */ 923, 412, 515, 141, 576, 1169, 413, 206, 465, 207,
173606
+ /* 1180 */ 903, 215, 1575, 552, 147, 147, 7, 227, 1169, 411,
173607
+ /* 1190 */ 1250, 1169, 120, 307, 117, 307, 413, 66, 66, 334,
173608
+ /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053,
173609
+ /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 285, 209, 969,
173610
+ /* 1220 */ 137, 138, 91, 471, 1228, 1228, 1063, 1066, 1053, 1053,
173611
+ /* 1230 */ 135, 135, 136, 136, 136, 136, 435, 10, 1450, 267,
173612
+ /* 1240 */ 137, 126, 91, 1435, 1228, 1228, 1063, 1066, 1053, 1053,
173613
+ /* 1250 */ 135, 135, 136, 136, 136, 136, 1435, 1435, 410, 409,
173614
+ /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173615
+ /* 1270 */ 128, 451, 576, 969, 576, 1224, 498, 373, 1595, 1554,
173616
+ /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173617
+ /* 1290 */ 128, 451, 532, 457, 576, 82, 82, 82, 82, 111,
173618
+ /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173619
+ /* 1310 */ 128, 451, 109, 233, 430, 1576, 546, 67, 67, 7,
173620
+ /* 1320 */ 413, 351, 550, 1550, 260, 259, 258, 494, 443, 569,
173621
+ /* 1330 */ 419, 983, 446, 1224, 450, 545, 1207, 576, 969, 984,
173622
+ /* 1340 */ 413, 475, 1449, 1574, 1180, 138, 91, 7, 1228, 1228,
173623
+ /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173624
+ /* 1360 */ 21, 21, 267, 576, 300, 1126, 91, 233, 1228, 1228,
173625
+ /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173626
+ /* 1380 */ 1127, 373, 1595, 161, 1573, 16, 53, 53, 7, 108,
173627
+ /* 1390 */ 533, 38, 969, 125, 1207, 1128, 1180, 576, 1224, 123,
173628
+ /* 1400 */ 568, 893, 4, 324, 134, 134, 134, 134, 133, 133,
173629
+ /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 576,
173630
+ /* 1420 */ 68, 68, 576, 39, 134, 134, 134, 134, 133, 133,
173631
+ /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 160, 1571, 1223,
173632
+ /* 1440 */ 452, 576, 54, 54, 576, 69, 69, 576, 1366, 576,
173633
+ /* 1450 */ 420, 184, 565, 463, 297, 576, 1224, 463, 297, 70,
173634
+ /* 1460 */ 70, 576, 44, 474, 71, 71, 576, 72, 72, 576,
173635
+ /* 1470 */ 73, 73, 55, 55, 411, 874, 242, 576, 56, 56,
173636
+ /* 1480 */ 576, 1040, 576, 478, 57, 57, 576, 121, 121, 59,
173637
+ /* 1490 */ 59, 23, 60, 60, 411, 122, 319, 452, 577, 452,
173638
+ /* 1500 */ 74, 74, 1028, 75, 75, 76, 76, 411, 290, 20,
173639
+ /* 1510 */ 20, 108, 287, 231, 553, 123, 568, 325, 4, 320,
173640
+ /* 1520 */ 567, 97, 218, 944, 1144, 328, 400, 576, 943, 576,
173641
+ /* 1530 */ 1380, 424, 571, 874, 1028, 1028, 1030, 1031, 35, 293,
173642
+ /* 1540 */ 534, 576, 1104, 576, 1104, 9, 576, 342, 576, 111,
173643
+ /* 1550 */ 77, 77, 143, 143, 576, 205, 452, 222, 1379, 889,
173644
+ /* 1560 */ 576, 901, 900, 1188, 144, 144, 78, 78, 565, 62,
173645
+ /* 1570 */ 62, 79, 79, 323, 1021, 576, 266, 63, 63, 908,
173646
+ /* 1580 */ 909, 1589, 542, 80, 80, 576, 371, 541, 123, 568,
173647
+ /* 1590 */ 480, 4, 266, 482, 244, 266, 370, 1040, 64, 64,
173648
+ /* 1600 */ 576, 466, 576, 121, 121, 571, 1557, 576, 170, 170,
173649
+ /* 1610 */ 576, 122, 576, 452, 577, 452, 576, 889, 1028, 576,
173650
+ /* 1620 */ 165, 576, 111, 171, 171, 87, 87, 337, 1616, 452,
173651
+ /* 1630 */ 65, 65, 1530, 83, 83, 146, 146, 986, 987, 84,
173652
+ /* 1640 */ 84, 565, 168, 168, 148, 148, 1092, 347, 1032, 111,
173653
+ /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 1103, 576, 1103, 576,
173654
+ /* 1660 */ 543, 123, 568, 504, 4, 263, 576, 361, 1529, 111,
173655
+ /* 1670 */ 1040, 1088, 576, 263, 576, 490, 121, 121, 571, 1188,
173656
+ /* 1680 */ 142, 142, 169, 169, 122, 576, 452, 577, 452, 162,
173657
+ /* 1690 */ 162, 1028, 576, 563, 576, 152, 152, 151, 151, 348,
173658
+ /* 1700 */ 1376, 974, 452, 266, 1092, 942, 1032, 125, 149, 149,
173659
+ /* 1710 */ 939, 576, 125, 576, 565, 150, 150, 86, 86, 872,
173660
+ /* 1720 */ 352, 159, 576, 1028, 1028, 1030, 1031, 35, 542, 941,
173661
+ /* 1730 */ 576, 125, 355, 541, 88, 88, 85, 85, 357, 359,
173662
+ /* 1740 */ 1324, 1308, 366, 1040, 376, 52, 52, 499, 1389, 121,
173663
+ /* 1750 */ 121, 1434, 1188, 58, 58, 1362, 1374, 122, 1439, 452,
173664
+ /* 1760 */ 577, 452, 1289, 167, 1028, 1280, 280, 1268, 1267, 1269,
173665
+ /* 1770 */ 1609, 1359, 312, 313, 12, 314, 397, 1421, 224, 1416,
173666
+ /* 1780 */ 295, 237, 1409, 339, 340, 1426, 301, 345, 484, 228,
173667
+ /* 1790 */ 1371, 1307, 1372, 1370, 1425, 404, 1028, 1028, 1030, 1031,
173668
+ /* 1800 */ 35, 1601, 1192, 454, 509, 369, 292, 1502, 210, 1501,
173669
+ /* 1810 */ 1369, 396, 396, 395, 277, 393, 211, 566, 859, 1612,
173670
+ /* 1820 */ 1244, 123, 568, 391, 4, 1188, 223, 270, 1549, 1547,
173671
+ /* 1830 */ 1241, 239, 186, 327, 422, 96, 195, 220, 571, 235,
173672
+ /* 1840 */ 180, 326, 188, 468, 190, 1507, 191, 192, 92, 193,
173673
+ /* 1850 */ 469, 95, 1422, 13, 502, 247, 1430, 109, 199, 402,
173674
+ /* 1860 */ 476, 405, 452, 1496, 1428, 1427, 14, 491, 251, 102,
173675
+ /* 1870 */ 497, 1518, 241, 281, 565, 253, 203, 354, 500, 254,
173676
+ /* 1880 */ 175, 1270, 407, 43, 350, 518, 1327, 436, 255, 1326,
173677
+ /* 1890 */ 1325, 1318, 104, 893, 1626, 229, 408, 440, 1625, 441,
173678
+ /* 1900 */ 240, 310, 1296, 1040, 311, 1317, 527, 1594, 1297, 121,
173679
+ /* 1910 */ 121, 368, 1295, 1624, 268, 269, 1580, 122, 1579, 452,
173680
+ /* 1920 */ 577, 452, 374, 444, 1028, 1394, 1393, 140, 553, 90,
173681
+ /* 1930 */ 568, 11, 4, 1483, 383, 414, 385, 110, 116, 216,
173682
+ /* 1940 */ 320, 567, 1350, 555, 42, 318, 571, 537, 1349, 389,
173683
+ /* 1950 */ 390, 579, 1198, 276, 279, 278, 1028, 1028, 1030, 1031,
173684
+ /* 1960 */ 35, 580, 415, 1265, 458, 1260, 416, 185, 1534, 172,
173685
+ /* 1970 */ 452, 1535, 173, 156, 308, 846, 1533, 1532, 453, 217,
173686
+ /* 1980 */ 225, 89, 565, 174, 322, 1188, 226, 236, 1102, 154,
173687
+ /* 1990 */ 1100, 330, 176, 187, 1223, 189, 925, 338, 243, 1116,
173688
+ /* 2000 */ 246, 194, 177, 178, 425, 427, 98, 99, 196, 100,
173689
+ /* 2010 */ 101, 1040, 179, 1119, 248, 1115, 249, 121, 121, 24,
173690
+ /* 2020 */ 163, 250, 349, 1108, 266, 122, 1238, 452, 577, 452,
173691
+ /* 2030 */ 1192, 454, 1028, 200, 292, 496, 252, 201, 861, 396,
173692
+ /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256,
173693
+ /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239,
173694
+ /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326,
173695
+ /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309,
173696
+ /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155,
173697
+ /* 2090 */ 17, 1154, 284, 1188, 286, 978, 265, 204, 125, 1171,
173698
+ /* 2100 */ 241, 230, 972, 1175, 28, 1160, 29, 1179, 175, 1173,
173699
+ /* 2110 */ 30, 43, 31, 1178, 241, 32, 41, 549, 8, 33,
173700
+ /* 2120 */ 208, 111, 175, 1083, 1070, 43, 113, 1068, 240, 114,
173701
+ /* 2130 */ 1072, 34, 1073, 561, 1124, 118, 271, 36, 18, 1194,
173702
+ /* 2140 */ 1033, 873, 240, 935, 124, 37, 272, 273, 1617, 572,
173703
+ /* 2150 */ 183, 153, 394, 1193, 1256, 1256, 1256, 1256, 1256, 1256,
173704
+ /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567,
173705
+ /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256,
173706
+ /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256,
173707
+ /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
173708
+ /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458,
172835173709
};
172836173710
static const YYCODETYPE yy_lookahead[] = {
172837
- /* 0 */ 194, 276, 277, 278, 216, 194, 194, 217, 194, 194,
172838
- /* 10 */ 194, 194, 224, 194, 194, 276, 277, 278, 204, 19,
172839
- /* 20 */ 206, 202, 297, 217, 218, 205, 207, 217, 205, 217,
172840
- /* 30 */ 218, 31, 217, 218, 217, 218, 29, 217, 218, 39,
172841
- /* 40 */ 33, 217, 220, 43, 44, 45, 46, 47, 48, 49,
172842
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 312, 19,
172843
- /* 60 */ 240, 241, 316, 240, 241, 194, 46, 47, 48, 49,
172844
- /* 70 */ 22, 254, 65, 253, 254, 255, 253, 194, 255, 194,
172845
- /* 80 */ 263, 258, 259, 43, 44, 45, 46, 47, 48, 49,
172846
- /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 276, 277,
172847
- /* 100 */ 278, 285, 102, 103, 104, 105, 106, 107, 108, 109,
172848
- /* 110 */ 110, 111, 112, 113, 59, 186, 187, 188, 189, 190,
172849
- /* 120 */ 191, 310, 239, 317, 318, 196, 86, 198, 88, 317,
172850
- /* 130 */ 19, 319, 317, 318, 205, 264, 25, 211, 212, 213,
172851
- /* 140 */ 205, 121, 102, 103, 104, 105, 106, 107, 108, 109,
172852
- /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48,
172853
- /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 240,
172854
- /* 170 */ 241, 116, 117, 118, 119, 240, 241, 122, 123, 124,
172855
- /* 180 */ 69, 298, 253, 194, 255, 106, 107, 132, 253, 141,
172856
- /* 190 */ 255, 54, 55, 56, 57, 58, 207, 268, 102, 103,
172857
- /* 200 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
172858
- /* 210 */ 214, 128, 129, 102, 103, 104, 105, 106, 107, 108,
172859
- /* 220 */ 109, 110, 111, 112, 113, 134, 25, 136, 137, 300,
172860
- /* 230 */ 165, 166, 153, 19, 155, 54, 55, 56, 57, 102,
172861
- /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
172862
- /* 250 */ 113, 108, 109, 110, 111, 112, 113, 43, 44, 45,
172863
- /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
172864
- /* 270 */ 56, 57, 276, 277, 278, 113, 194, 19, 22, 23,
172865
- /* 280 */ 194, 67, 24, 102, 103, 104, 105, 106, 107, 108,
172866
- /* 290 */ 109, 110, 111, 112, 113, 220, 250, 59, 252, 217,
172867
- /* 300 */ 218, 43, 44, 45, 46, 47, 48, 49, 50, 51,
172868
- /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105,
172869
- /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 106, 107,
172870
- /* 330 */ 108, 109, 110, 111, 112, 113, 254, 59, 205, 138,
172871
- /* 340 */ 139, 19, 20, 194, 22, 263, 22, 23, 231, 25,
172872
- /* 350 */ 72, 276, 277, 278, 116, 117, 118, 101, 36, 76,
172873
- /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
172874
- /* 370 */ 112, 113, 89, 240, 241, 92, 73, 194, 194, 73,
172875
- /* 380 */ 19, 59, 188, 189, 190, 191, 253, 81, 255, 151,
172876
- /* 390 */ 196, 25, 198, 71, 116, 117, 118, 311, 312, 205,
172877
- /* 400 */ 217, 218, 316, 81, 43, 44, 45, 46, 47, 48,
172878
- /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 270,
172879
- /* 420 */ 22, 23, 100, 25, 59, 101, 138, 139, 106, 107,
172880
- /* 430 */ 127, 128, 129, 127, 240, 241, 114, 254, 116, 117,
172881
- /* 440 */ 118, 76, 76, 121, 138, 139, 263, 253, 264, 255,
172882
- /* 450 */ 205, 275, 87, 19, 89, 89, 194, 92, 92, 199,
172883
- /* 460 */ 138, 139, 268, 102, 103, 104, 105, 106, 107, 108,
172884
- /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157,
172885
- /* 480 */ 81, 116, 117, 118, 129, 240, 241, 224, 19, 226,
172886
- /* 490 */ 314, 315, 23, 25, 300, 59, 22, 234, 253, 101,
172887
- /* 500 */ 255, 236, 237, 26, 194, 183, 194, 152, 72, 22,
172888
- /* 510 */ 145, 150, 43, 44, 45, 46, 47, 48, 49, 50,
172889
- /* 520 */ 51, 52, 53, 54, 55, 56, 57, 217, 218, 217,
172890
- /* 530 */ 218, 19, 189, 59, 191, 23, 59, 138, 139, 196,
172891
- /* 540 */ 135, 198, 232, 283, 232, 140, 59, 287, 205, 275,
172892
- /* 550 */ 116, 205, 116, 117, 118, 43, 44, 45, 46, 47,
172893
- /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172894
- /* 570 */ 194, 102, 103, 104, 105, 106, 107, 108, 109, 110,
172895
- /* 580 */ 111, 112, 113, 240, 241, 194, 240, 241, 314, 315,
172896
- /* 590 */ 116, 117, 118, 116, 117, 118, 253, 194, 255, 253,
172897
- /* 600 */ 59, 255, 19, 116, 117, 118, 23, 22, 217, 218,
172898
- /* 610 */ 142, 268, 205, 275, 102, 103, 104, 105, 106, 107,
172899
- /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172900
- /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172901
- /* 640 */ 57, 19, 194, 300, 59, 23, 119, 240, 241, 122,
172902
- /* 650 */ 123, 124, 314, 315, 194, 236, 237, 194, 117, 132,
172903
- /* 660 */ 253, 81, 255, 205, 59, 43, 44, 45, 46, 47,
172904
- /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172905
- /* 680 */ 217, 218, 194, 194, 194, 102, 103, 104, 105, 106,
172906
- /* 690 */ 107, 108, 109, 110, 111, 112, 113, 294, 240, 241,
172907
- /* 700 */ 120, 116, 117, 118, 59, 194, 217, 218, 211, 212,
172908
- /* 710 */ 213, 253, 19, 255, 194, 19, 23, 254, 138, 139,
172909
- /* 720 */ 24, 232, 117, 194, 102, 103, 104, 105, 106, 107,
172910
- /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172911
- /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172912
- /* 750 */ 57, 19, 264, 108, 76, 23, 127, 128, 129, 311,
172913
- /* 760 */ 312, 116, 117, 118, 316, 87, 306, 89, 308, 194,
172914
- /* 770 */ 92, 22, 59, 194, 22, 43, 44, 45, 46, 47,
172915
- /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172916
- /* 790 */ 194, 95, 217, 218, 265, 102, 103, 104, 105, 106,
172917
- /* 800 */ 107, 108, 109, 110, 111, 112, 113, 232, 59, 113,
172918
- /* 810 */ 25, 59, 194, 217, 218, 119, 120, 121, 122, 123,
172919
- /* 820 */ 124, 125, 19, 145, 194, 194, 23, 131, 232, 116,
172920
- /* 830 */ 117, 118, 35, 194, 102, 103, 104, 105, 106, 107,
172921
- /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172922
- /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172923
- /* 860 */ 57, 19, 194, 66, 194, 116, 117, 118, 116, 117,
172924
- /* 870 */ 118, 74, 242, 294, 194, 194, 206, 23, 194, 25,
172925
- /* 880 */ 194, 111, 112, 113, 25, 43, 44, 45, 46, 47,
172926
- /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172927
- /* 900 */ 24, 194, 194, 217, 218, 102, 103, 104, 105, 106,
172928
- /* 910 */ 107, 108, 109, 110, 111, 112, 113, 241, 232, 194,
172929
- /* 920 */ 212, 213, 242, 242, 217, 218, 242, 130, 11, 253,
172930
- /* 930 */ 194, 255, 19, 265, 149, 59, 306, 194, 308, 232,
172931
- /* 940 */ 309, 310, 217, 218, 102, 103, 104, 105, 106, 107,
172932
- /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172933
- /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172934
- /* 970 */ 57, 194, 194, 59, 194, 239, 19, 194, 25, 254,
172935
- /* 980 */ 303, 304, 23, 194, 25, 126, 306, 306, 308, 308,
172936
- /* 990 */ 306, 271, 308, 117, 286, 217, 218, 217, 218, 194,
172937
- /* 1000 */ 194, 159, 45, 46, 47, 48, 49, 50, 51, 52,
172938
- /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106,
172939
- /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 59, 239, 194,
172940
- /* 1030 */ 116, 117, 118, 260, 254, 194, 240, 241, 194, 233,
172941
- /* 1040 */ 205, 240, 241, 205, 239, 128, 129, 270, 265, 253,
172942
- /* 1050 */ 194, 255, 217, 218, 253, 194, 255, 143, 280, 102,
172943
- /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
172944
- /* 1070 */ 113, 118, 159, 217, 218, 240, 241, 118, 240, 241,
172945
- /* 1080 */ 194, 194, 194, 239, 116, 117, 118, 22, 253, 254,
172946
- /* 1090 */ 255, 253, 19, 255, 233, 194, 143, 24, 263, 212,
172947
- /* 1100 */ 213, 194, 143, 217, 218, 217, 218, 261, 262, 271,
172948
- /* 1110 */ 254, 143, 19, 7, 8, 9, 43, 44, 45, 46,
172949
- /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172950
- /* 1130 */ 57, 16, 19, 22, 23, 294, 43, 44, 45, 46,
172951
- /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172952
- /* 1150 */ 57, 312, 194, 214, 21, 316, 43, 44, 45, 46,
172953
- /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172954
- /* 1170 */ 57, 106, 107, 286, 194, 102, 103, 104, 105, 106,
172955
- /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 207, 158, 59,
172956
- /* 1190 */ 160, 22, 77, 24, 79, 102, 103, 104, 105, 106,
172957
- /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 194, 194, 229,
172958
- /* 1210 */ 194, 231, 101, 80, 22, 102, 103, 104, 105, 106,
172959
- /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 288, 59, 12,
172960
- /* 1230 */ 217, 218, 293, 217, 218, 19, 106, 107, 59, 19,
172961
- /* 1240 */ 16, 127, 128, 129, 27, 115, 116, 117, 118, 194,
172962
- /* 1250 */ 120, 59, 22, 194, 24, 194, 123, 100, 128, 42,
172963
- /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
172964
- /* 1270 */ 54, 55, 56, 57, 117, 194, 217, 218, 121, 100,
172965
- /* 1280 */ 63, 194, 245, 153, 194, 155, 117, 19, 115, 194,
172966
- /* 1290 */ 73, 214, 194, 256, 161, 116, 117, 194, 217, 218,
172967
- /* 1300 */ 121, 77, 194, 79, 217, 218, 194, 217, 218, 117,
172968
- /* 1310 */ 153, 154, 155, 254, 46, 217, 218, 144, 102, 103,
172969
- /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
172970
- /* 1330 */ 232, 270, 153, 154, 155, 115, 116, 66, 19, 20,
172971
- /* 1340 */ 183, 22, 12, 312, 254, 194, 262, 316, 209, 210,
172972
- /* 1350 */ 266, 239, 194, 194, 108, 36, 85, 27, 19, 20,
172973
- /* 1360 */ 265, 22, 183, 245, 144, 94, 25, 48, 217, 218,
172974
- /* 1370 */ 293, 194, 42, 270, 256, 36, 217, 218, 59, 194,
172975
- /* 1380 */ 25, 135, 194, 115, 194, 161, 140, 194, 194, 15,
172976
- /* 1390 */ 71, 194, 312, 63, 217, 218, 316, 194, 59, 131,
172977
- /* 1400 */ 301, 302, 217, 218, 85, 217, 218, 217, 218, 90,
172978
- /* 1410 */ 71, 217, 218, 19, 217, 218, 245, 146, 262, 100,
172979
- /* 1420 */ 217, 218, 266, 265, 85, 106, 107, 256, 312, 90,
172980
- /* 1430 */ 209, 210, 316, 114, 60, 116, 117, 118, 194, 100,
172981
- /* 1440 */ 121, 194, 194, 145, 115, 106, 107, 19, 46, 19,
172982
- /* 1450 */ 20, 24, 22, 114, 194, 116, 117, 118, 194, 245,
172983
- /* 1460 */ 121, 194, 164, 194, 217, 218, 36, 194, 258, 259,
172984
- /* 1470 */ 256, 194, 153, 154, 155, 156, 157, 217, 218, 150,
172985
- /* 1480 */ 31, 217, 218, 142, 217, 218, 217, 218, 39, 59,
172986
- /* 1490 */ 217, 218, 153, 154, 155, 156, 157, 149, 150, 5,
172987
- /* 1500 */ 145, 71, 183, 245, 10, 11, 12, 13, 14, 194,
172988
- /* 1510 */ 116, 17, 129, 227, 256, 85, 194, 115, 194, 23,
172989
- /* 1520 */ 90, 25, 183, 99, 30, 97, 32, 22, 22, 194,
172990
- /* 1530 */ 100, 194, 217, 218, 40, 152, 106, 107, 23, 217,
172991
- /* 1540 */ 218, 194, 19, 20, 114, 22, 116, 117, 118, 257,
172992
- /* 1550 */ 194, 121, 217, 218, 217, 218, 194, 133, 53, 36,
172993
- /* 1560 */ 23, 23, 25, 25, 70, 120, 121, 61, 141, 7,
172994
- /* 1570 */ 8, 121, 78, 217, 218, 81, 23, 227, 25, 217,
172995
- /* 1580 */ 218, 131, 59, 153, 154, 155, 156, 157, 0, 1,
172996
- /* 1590 */ 2, 59, 98, 5, 71, 23, 227, 25, 10, 11,
172997
- /* 1600 */ 12, 13, 14, 83, 84, 17, 23, 23, 25, 25,
172998
- /* 1610 */ 59, 194, 194, 183, 23, 23, 25, 25, 30, 194,
172999
- /* 1620 */ 32, 19, 20, 100, 22, 194, 194, 133, 40, 106,
173000
- /* 1630 */ 107, 108, 138, 139, 194, 217, 218, 114, 36, 116,
173001
- /* 1640 */ 117, 118, 217, 218, 121, 194, 194, 194, 23, 117,
173002
- /* 1650 */ 25, 194, 23, 23, 25, 25, 162, 194, 70, 194,
173003
- /* 1660 */ 145, 59, 23, 153, 25, 155, 78, 194, 117, 81,
173004
- /* 1670 */ 217, 218, 194, 71, 217, 218, 153, 154, 155, 156,
173005
- /* 1680 */ 157, 194, 217, 218, 194, 23, 98, 25, 321, 194,
173006
- /* 1690 */ 217, 218, 194, 19, 20, 194, 22, 153, 23, 155,
173007
- /* 1700 */ 25, 194, 100, 194, 217, 218, 183, 194, 106, 107,
173008
- /* 1710 */ 36, 194, 217, 218, 237, 194, 114, 243, 116, 117,
173009
- /* 1720 */ 118, 133, 194, 121, 217, 218, 138, 139, 194, 194,
173010
- /* 1730 */ 194, 290, 289, 59, 217, 218, 194, 194, 217, 218,
173011
- /* 1740 */ 194, 194, 140, 194, 194, 71, 194, 244, 194, 194,
173012
- /* 1750 */ 162, 217, 218, 194, 194, 153, 154, 155, 156, 157,
173013
- /* 1760 */ 217, 218, 194, 217, 218, 194, 217, 218, 257, 217,
173014
- /* 1770 */ 218, 217, 218, 257, 100, 194, 257, 217, 218, 257,
173015
- /* 1780 */ 106, 107, 215, 299, 194, 183, 192, 194, 114, 194,
173016
- /* 1790 */ 116, 117, 118, 1, 2, 121, 221, 5, 217, 218,
173017
- /* 1800 */ 273, 197, 10, 11, 12, 13, 14, 217, 218, 17,
173018
- /* 1810 */ 217, 218, 217, 218, 140, 194, 246, 194, 273, 295,
173019
- /* 1820 */ 247, 273, 30, 247, 32, 269, 269, 153, 154, 155,
173020
- /* 1830 */ 156, 157, 40, 246, 273, 295, 230, 226, 217, 218,
173021
- /* 1840 */ 217, 218, 220, 261, 220, 282, 220, 19, 20, 244,
173022
- /* 1850 */ 22, 250, 141, 250, 246, 60, 201, 183, 261, 261,
173023
- /* 1860 */ 261, 201, 70, 299, 36, 299, 201, 38, 151, 150,
173024
- /* 1870 */ 78, 285, 22, 81, 296, 296, 43, 235, 18, 238,
173025
- /* 1880 */ 201, 274, 272, 238, 238, 238, 18, 59, 200, 149,
173026
- /* 1890 */ 98, 247, 274, 274, 235, 247, 247, 247, 235, 71,
173027
- /* 1900 */ 272, 201, 200, 158, 292, 62, 291, 201, 200, 22,
173028
- /* 1910 */ 201, 222, 200, 222, 201, 200, 115, 219, 219, 64,
173029
- /* 1920 */ 219, 228, 22, 126, 221, 133, 165, 222, 100, 225,
173030
- /* 1930 */ 138, 139, 225, 219, 106, 107, 24, 219, 228, 219,
173031
- /* 1940 */ 219, 307, 114, 113, 116, 117, 118, 315, 284, 121,
173032
- /* 1950 */ 284, 222, 201, 91, 162, 320, 320, 82, 148, 267,
173033
- /* 1960 */ 145, 267, 22, 279, 201, 158, 281, 251, 147, 146,
173034
- /* 1970 */ 25, 203, 250, 249, 251, 248, 13, 247, 195, 195,
173035
- /* 1980 */ 6, 153, 154, 155, 156, 157, 193, 193, 305, 193,
173036
- /* 1990 */ 208, 305, 302, 214, 214, 214, 208, 223, 223, 214,
173037
- /* 2000 */ 4, 215, 215, 214, 3, 22, 208, 163, 15, 23,
173038
- /* 2010 */ 16, 183, 23, 139, 151, 130, 25, 20, 142, 24,
173039
- /* 2020 */ 16, 144, 1, 142, 130, 130, 61, 37, 53, 151,
173040
- /* 2030 */ 53, 53, 53, 130, 116, 1, 34, 141, 5, 22,
173041
- /* 2040 */ 115, 161, 75, 25, 68, 141, 41, 115, 68, 24,
173042
- /* 2050 */ 20, 19, 131, 125, 67, 67, 96, 22, 22, 22,
173043
- /* 2060 */ 37, 23, 22, 24, 22, 59, 67, 23, 149, 28,
173044
- /* 2070 */ 22, 25, 23, 23, 23, 22, 141, 34, 97, 23,
173045
- /* 2080 */ 23, 34, 116, 22, 143, 25, 34, 75, 34, 34,
173046
- /* 2090 */ 75, 88, 34, 86, 23, 22, 34, 25, 24, 34,
173047
- /* 2100 */ 25, 93, 23, 44, 142, 23, 142, 23, 23, 22,
173048
- /* 2110 */ 11, 25, 23, 25, 23, 22, 22, 22, 1, 23,
173049
- /* 2120 */ 23, 23, 22, 22, 15, 141, 141, 25, 25, 1,
173050
- /* 2130 */ 322, 322, 322, 135, 322, 322, 322, 322, 322, 322,
173051
- /* 2140 */ 322, 141, 322, 322, 322, 322, 322, 322, 322, 322,
173052
- /* 2150 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173053
- /* 2160 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173054
- /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173055
- /* 2180 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173056
- /* 2190 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173057
- /* 2200 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173711
+ /* 0 */ 276, 277, 278, 240, 241, 224, 194, 226, 194, 240,
173712
+ /* 10 */ 241, 194, 216, 220, 194, 234, 253, 194, 255, 19,
173713
+ /* 20 */ 224, 297, 253, 194, 255, 205, 212, 213, 205, 217,
173714
+ /* 30 */ 218, 31, 205, 194, 217, 218, 194, 217, 218, 39,
173715
+ /* 40 */ 217, 218, 312, 43, 44, 45, 316, 47, 48, 49,
173716
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19,
173717
+ /* 60 */ 240, 241, 194, 240, 241, 194, 254, 240, 241, 276,
173718
+ /* 70 */ 277, 278, 233, 253, 254, 255, 253, 254, 255, 217,
173719
+ /* 80 */ 253, 239, 255, 43, 44, 45, 263, 47, 48, 49,
173720
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 270,
173721
+ /* 100 */ 286, 22, 23, 103, 104, 105, 106, 107, 108, 109,
173722
+ /* 110 */ 110, 111, 112, 113, 114, 82, 47, 48, 49, 50,
173723
+ /* 120 */ 186, 187, 188, 189, 190, 191, 189, 87, 191, 89,
173724
+ /* 130 */ 196, 19, 198, 196, 317, 198, 319, 25, 194, 205,
173725
+ /* 140 */ 298, 270, 205, 103, 104, 105, 106, 107, 108, 109,
173726
+ /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 11, 47,
173727
+ /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
173728
+ /* 170 */ 58, 60, 139, 140, 240, 241, 214, 240, 241, 311,
173729
+ /* 180 */ 312, 102, 70, 239, 316, 194, 19, 253, 77, 255,
173730
+ /* 190 */ 253, 122, 255, 55, 56, 57, 58, 59, 207, 88,
173731
+ /* 200 */ 194, 90, 268, 194, 93, 268, 107, 108, 109, 110,
173732
+ /* 210 */ 111, 112, 113, 114, 47, 103, 104, 105, 106, 107,
173733
+ /* 220 */ 108, 109, 110, 111, 112, 113, 114, 114, 117, 118,
173734
+ /* 230 */ 119, 276, 277, 278, 300, 19, 194, 300, 276, 277,
173735
+ /* 240 */ 278, 103, 104, 105, 106, 107, 108, 109, 110, 111,
173736
+ /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 194, 43,
173737
+ /* 260 */ 44, 45, 47, 47, 48, 49, 50, 51, 52, 53,
173738
+ /* 270 */ 54, 55, 56, 57, 58, 82, 129, 130, 60, 129,
173739
+ /* 280 */ 130, 217, 218, 116, 68, 25, 103, 104, 105, 106,
173740
+ /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 23, 132,
173741
+ /* 300 */ 294, 103, 104, 105, 106, 107, 108, 109, 110, 111,
173742
+ /* 310 */ 112, 113, 114, 217, 121, 306, 194, 308, 26, 103,
173743
+ /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
173744
+ /* 330 */ 114, 116, 139, 140, 217, 117, 118, 119, 120, 19,
173745
+ /* 340 */ 194, 123, 124, 125, 24, 109, 110, 111, 112, 113,
173746
+ /* 350 */ 114, 133, 60, 311, 312, 250, 194, 252, 316, 19,
173747
+ /* 360 */ 194, 166, 167, 43, 44, 45, 205, 47, 48, 49,
173748
+ /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 217,
173749
+ /* 380 */ 218, 317, 318, 43, 44, 45, 264, 47, 48, 49,
173750
+ /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 139,
173751
+ /* 400 */ 140, 240, 241, 139, 140, 188, 189, 190, 191, 117,
173752
+ /* 410 */ 118, 119, 231, 196, 253, 198, 255, 194, 194, 258,
173753
+ /* 420 */ 259, 146, 205, 103, 104, 105, 106, 107, 108, 109,
173754
+ /* 430 */ 110, 111, 112, 113, 114, 109, 212, 213, 236, 237,
173755
+ /* 440 */ 217, 218, 194, 103, 104, 105, 106, 107, 108, 109,
173756
+ /* 450 */ 110, 111, 112, 113, 114, 194, 120, 240, 241, 123,
173757
+ /* 460 */ 124, 125, 136, 194, 19, 74, 60, 141, 23, 133,
173758
+ /* 470 */ 253, 194, 255, 82, 194, 309, 310, 254, 29, 317,
173759
+ /* 480 */ 318, 194, 33, 22, 199, 268, 263, 239, 43, 44,
173760
+ /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54,
173761
+ /* 500 */ 55, 56, 57, 58, 217, 218, 194, 60, 19, 146,
173762
+ /* 510 */ 286, 242, 23, 107, 108, 66, 204, 300, 206, 128,
173763
+ /* 520 */ 73, 60, 116, 117, 118, 119, 265, 121, 165, 60,
173764
+ /* 530 */ 139, 140, 43, 44, 45, 129, 47, 48, 49, 50,
173765
+ /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104,
173766
+ /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
173767
+ /* 560 */ 154, 194, 156, 194, 117, 118, 119, 280, 283, 205,
173768
+ /* 570 */ 101, 220, 287, 19, 20, 306, 22, 308, 117, 118,
173769
+ /* 580 */ 119, 211, 212, 213, 217, 218, 117, 118, 236, 237,
173770
+ /* 590 */ 36, 122, 103, 104, 105, 106, 107, 108, 109, 110,
173771
+ /* 600 */ 111, 112, 113, 114, 240, 241, 194, 60, 194, 194,
173772
+ /* 610 */ 194, 194, 19, 194, 60, 194, 23, 253, 206, 255,
173773
+ /* 620 */ 73, 254, 19, 154, 155, 156, 72, 276, 277, 278,
173774
+ /* 630 */ 263, 217, 218, 217, 218, 271, 43, 44, 45, 271,
173775
+ /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173776
+ /* 650 */ 57, 58, 183, 194, 285, 101, 19, 214, 60, 242,
173777
+ /* 660 */ 23, 107, 108, 109, 117, 118, 119, 16, 254, 115,
173778
+ /* 670 */ 254, 117, 118, 119, 194, 60, 122, 263, 205, 264,
173779
+ /* 680 */ 43, 44, 45, 264, 47, 48, 49, 50, 51, 52,
173780
+ /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106,
173781
+ /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155,
173782
+ /* 710 */ 156, 157, 158, 240, 241, 117, 118, 119, 101, 205,
173783
+ /* 720 */ 117, 19, 20, 306, 22, 308, 253, 74, 255, 78,
173784
+ /* 730 */ 205, 80, 117, 118, 119, 118, 293, 183, 36, 122,
173785
+ /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173786
+ /* 750 */ 113, 114, 194, 294, 240, 241, 211, 212, 213, 144,
173787
+ /* 760 */ 19, 23, 60, 25, 23, 240, 241, 253, 245, 255,
173788
+ /* 770 */ 15, 154, 155, 156, 72, 217, 218, 194, 253, 256,
173789
+ /* 780 */ 255, 128, 129, 130, 43, 44, 45, 22, 47, 48,
173790
+ /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173791
+ /* 800 */ 183, 19, 77, 101, 19, 128, 129, 130, 23, 107,
173792
+ /* 810 */ 108, 60, 254, 88, 21, 90, 61, 115, 93, 117,
173793
+ /* 820 */ 118, 119, 239, 22, 122, 60, 194, 205, 43, 44,
173794
+ /* 830 */ 45, 205, 47, 48, 49, 50, 51, 52, 53, 54,
173795
+ /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108,
173796
+ /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157,
173797
+ /* 860 */ 158, 60, 240, 241, 60, 116, 240, 241, 117, 118,
173798
+ /* 870 */ 119, 146, 194, 19, 81, 253, 275, 255, 24, 253,
173799
+ /* 880 */ 98, 255, 117, 118, 119, 183, 22, 194, 103, 104,
173800
+ /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
173801
+ /* 900 */ 151, 194, 270, 152, 22, 23, 194, 25, 19, 202,
173802
+ /* 910 */ 217, 218, 23, 109, 207, 314, 315, 124, 117, 118,
173803
+ /* 920 */ 119, 117, 118, 119, 60, 232, 22, 23, 19, 25,
173804
+ /* 930 */ 303, 304, 43, 44, 45, 22, 47, 48, 49, 50,
173805
+ /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 270, 227,
173806
+ /* 950 */ 96, 60, 43, 44, 45, 162, 47, 48, 49, 50,
173807
+ /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 112,
173808
+ /* 970 */ 113, 114, 194, 60, 120, 121, 122, 123, 124, 125,
173809
+ /* 980 */ 126, 117, 118, 119, 102, 25, 132, 107, 108, 194,
173810
+ /* 990 */ 194, 227, 103, 104, 105, 106, 107, 108, 109, 110,
173811
+ /* 1000 */ 111, 112, 113, 114, 194, 194, 102, 194, 117, 118,
173812
+ /* 1010 */ 119, 233, 103, 104, 105, 106, 107, 108, 109, 110,
173813
+ /* 1020 */ 111, 112, 113, 114, 194, 194, 19, 194, 217, 218,
173814
+ /* 1030 */ 117, 118, 119, 241, 154, 144, 156, 135, 242, 137,
173815
+ /* 1040 */ 138, 130, 19, 232, 194, 253, 23, 255, 217, 218,
173816
+ /* 1050 */ 217, 218, 242, 16, 7, 8, 9, 25, 261, 262,
173817
+ /* 1060 */ 265, 194, 19, 232, 153, 232, 43, 44, 45, 160,
173818
+ /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173819
+ /* 1080 */ 57, 58, 194, 227, 217, 218, 43, 44, 45, 194,
173820
+ /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173821
+ /* 1100 */ 57, 58, 306, 143, 308, 217, 218, 294, 12, 77,
173822
+ /* 1110 */ 22, 23, 217, 218, 194, 78, 306, 80, 308, 194,
173823
+ /* 1120 */ 232, 254, 90, 27, 117, 93, 103, 104, 105, 106,
173824
+ /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 194,
173825
+ /* 1140 */ 35, 194, 217, 218, 214, 194, 103, 104, 105, 106,
173826
+ /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 194, 239,
173827
+ /* 1160 */ 64, 194, 217, 218, 217, 218, 209, 210, 217, 218,
173828
+ /* 1170 */ 74, 207, 67, 22, 194, 77, 19, 232, 245, 232,
173829
+ /* 1180 */ 75, 24, 312, 232, 217, 218, 316, 25, 90, 256,
173830
+ /* 1190 */ 102, 93, 159, 229, 161, 231, 19, 217, 218, 162,
173831
+ /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52,
173832
+ /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 23, 288, 25,
173833
+ /* 1220 */ 43, 44, 45, 293, 47, 48, 49, 50, 51, 52,
173834
+ /* 1230 */ 53, 54, 55, 56, 57, 58, 131, 22, 275, 24,
173835
+ /* 1240 */ 43, 44, 45, 194, 47, 48, 49, 50, 51, 52,
173836
+ /* 1250 */ 53, 54, 55, 56, 57, 58, 194, 194, 107, 108,
173837
+ /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173838
+ /* 1270 */ 113, 114, 194, 25, 194, 60, 194, 314, 315, 194,
173839
+ /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173840
+ /* 1290 */ 113, 114, 19, 194, 194, 217, 218, 217, 218, 25,
173841
+ /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173842
+ /* 1310 */ 113, 114, 150, 119, 265, 312, 67, 217, 218, 316,
173843
+ /* 1320 */ 19, 239, 194, 194, 128, 129, 130, 265, 265, 209,
173844
+ /* 1330 */ 210, 31, 254, 118, 254, 86, 60, 194, 144, 39,
173845
+ /* 1340 */ 19, 130, 275, 312, 95, 44, 45, 316, 47, 48,
173846
+ /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173847
+ /* 1360 */ 217, 218, 24, 194, 153, 12, 45, 119, 47, 48,
173848
+ /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173849
+ /* 1380 */ 27, 314, 315, 22, 312, 24, 217, 218, 316, 116,
173850
+ /* 1390 */ 117, 22, 144, 25, 118, 42, 147, 194, 60, 19,
173851
+ /* 1400 */ 20, 127, 22, 194, 103, 104, 105, 106, 107, 108,
173852
+ /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 194,
173853
+ /* 1420 */ 217, 218, 194, 54, 103, 104, 105, 106, 107, 108,
173854
+ /* 1430 */ 109, 110, 111, 112, 113, 114, 194, 22, 310, 25,
173855
+ /* 1440 */ 60, 194, 217, 218, 194, 217, 218, 194, 260, 194,
173856
+ /* 1450 */ 301, 302, 72, 262, 262, 194, 118, 266, 266, 217,
173857
+ /* 1460 */ 218, 194, 82, 245, 217, 218, 194, 217, 218, 194,
173858
+ /* 1470 */ 217, 218, 217, 218, 256, 60, 24, 194, 217, 218,
173859
+ /* 1480 */ 194, 101, 194, 245, 217, 218, 194, 107, 108, 217,
173860
+ /* 1490 */ 218, 22, 217, 218, 256, 115, 245, 117, 118, 119,
173861
+ /* 1500 */ 217, 218, 122, 217, 218, 217, 218, 256, 22, 217,
173862
+ /* 1510 */ 218, 116, 258, 259, 146, 19, 20, 194, 22, 139,
173863
+ /* 1520 */ 140, 150, 151, 136, 23, 194, 25, 194, 141, 194,
173864
+ /* 1530 */ 194, 62, 36, 118, 154, 155, 156, 157, 158, 100,
173865
+ /* 1540 */ 145, 194, 154, 194, 156, 49, 194, 23, 194, 25,
173866
+ /* 1550 */ 217, 218, 217, 218, 194, 257, 60, 143, 194, 60,
173867
+ /* 1560 */ 194, 121, 122, 183, 217, 218, 217, 218, 72, 217,
173868
+ /* 1570 */ 218, 217, 218, 134, 23, 194, 25, 217, 218, 7,
173869
+ /* 1580 */ 8, 321, 86, 217, 218, 194, 122, 91, 19, 20,
173870
+ /* 1590 */ 23, 22, 25, 23, 142, 25, 132, 101, 217, 218,
173871
+ /* 1600 */ 194, 194, 194, 107, 108, 36, 194, 194, 217, 218,
173872
+ /* 1610 */ 194, 115, 194, 117, 118, 119, 194, 118, 122, 194,
173873
+ /* 1620 */ 23, 194, 25, 217, 218, 217, 218, 194, 142, 60,
173874
+ /* 1630 */ 217, 218, 194, 217, 218, 217, 218, 84, 85, 217,
173875
+ /* 1640 */ 218, 72, 217, 218, 217, 218, 60, 23, 60, 25,
173876
+ /* 1650 */ 154, 155, 156, 157, 158, 86, 154, 194, 156, 194,
173877
+ /* 1660 */ 91, 19, 20, 23, 22, 25, 194, 23, 194, 25,
173878
+ /* 1670 */ 101, 23, 194, 25, 194, 194, 107, 108, 36, 183,
173879
+ /* 1680 */ 217, 218, 217, 218, 115, 194, 117, 118, 119, 217,
173880
+ /* 1690 */ 218, 122, 194, 237, 194, 217, 218, 217, 218, 194,
173881
+ /* 1700 */ 194, 23, 60, 25, 118, 23, 118, 25, 217, 218,
173882
+ /* 1710 */ 23, 194, 25, 194, 72, 217, 218, 217, 218, 23,
173883
+ /* 1720 */ 194, 25, 194, 154, 155, 156, 157, 158, 86, 23,
173884
+ /* 1730 */ 194, 25, 194, 91, 217, 218, 217, 218, 194, 194,
173885
+ /* 1740 */ 194, 194, 194, 101, 194, 217, 218, 290, 194, 107,
173886
+ /* 1750 */ 108, 194, 183, 217, 218, 194, 194, 115, 194, 117,
173887
+ /* 1760 */ 118, 119, 194, 243, 122, 194, 289, 194, 194, 194,
173888
+ /* 1770 */ 194, 257, 257, 257, 244, 257, 192, 273, 215, 269,
173889
+ /* 1780 */ 246, 299, 269, 295, 247, 273, 247, 246, 295, 230,
173890
+ /* 1790 */ 261, 226, 261, 261, 273, 273, 154, 155, 156, 157,
173891
+ /* 1800 */ 158, 0, 1, 2, 221, 220, 5, 220, 250, 220,
173892
+ /* 1810 */ 261, 10, 11, 12, 13, 14, 250, 282, 17, 197,
173893
+ /* 1820 */ 61, 19, 20, 246, 22, 183, 244, 142, 201, 201,
173894
+ /* 1830 */ 38, 30, 299, 32, 201, 152, 22, 151, 36, 299,
173895
+ /* 1840 */ 43, 40, 235, 18, 238, 285, 238, 238, 296, 238,
173896
+ /* 1850 */ 201, 296, 274, 272, 18, 200, 235, 150, 235, 247,
173897
+ /* 1860 */ 247, 247, 60, 247, 274, 274, 272, 201, 200, 159,
173898
+ /* 1870 */ 63, 292, 71, 201, 72, 200, 22, 201, 222, 200,
173899
+ /* 1880 */ 79, 201, 222, 82, 291, 116, 219, 65, 200, 219,
173900
+ /* 1890 */ 219, 228, 22, 127, 225, 166, 222, 24, 225, 114,
173901
+ /* 1900 */ 99, 284, 221, 101, 284, 228, 307, 315, 219, 107,
173902
+ /* 1910 */ 108, 219, 219, 219, 201, 92, 320, 115, 320, 117,
173903
+ /* 1920 */ 118, 119, 222, 83, 122, 267, 267, 149, 146, 19,
173904
+ /* 1930 */ 20, 22, 22, 279, 250, 134, 201, 148, 159, 249,
173905
+ /* 1940 */ 139, 140, 251, 141, 25, 281, 36, 147, 251, 248,
173906
+ /* 1950 */ 247, 203, 13, 195, 6, 195, 154, 155, 156, 157,
173907
+ /* 1960 */ 158, 193, 305, 193, 163, 193, 305, 302, 214, 208,
173908
+ /* 1970 */ 60, 214, 208, 223, 223, 4, 214, 214, 3, 22,
173909
+ /* 1980 */ 215, 214, 72, 208, 164, 183, 215, 15, 23, 16,
173910
+ /* 1990 */ 23, 140, 131, 152, 25, 143, 20, 16, 24, 1,
173911
+ /* 2000 */ 145, 143, 131, 131, 62, 37, 54, 54, 152, 54,
173912
+ /* 2010 */ 54, 101, 131, 117, 34, 1, 142, 107, 108, 22,
173913
+ /* 2020 */ 5, 116, 162, 69, 25, 115, 76, 117, 118, 119,
173914
+ /* 2030 */ 1, 2, 122, 69, 5, 41, 142, 116, 20, 10,
173915
+ /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126,
173916
+ /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30,
173917
+ /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40,
173918
+ /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68,
173919
+ /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23,
173920
+ /* 2090 */ 22, 98, 23, 183, 23, 117, 34, 22, 25, 89,
173921
+ /* 2100 */ 71, 142, 144, 76, 34, 23, 34, 76, 79, 87,
173922
+ /* 2110 */ 34, 82, 34, 94, 71, 34, 22, 24, 44, 34,
173923
+ /* 2120 */ 25, 25, 79, 23, 23, 82, 143, 23, 99, 143,
173924
+ /* 2130 */ 23, 22, 11, 25, 23, 25, 22, 22, 22, 1,
173925
+ /* 2140 */ 23, 23, 99, 136, 22, 22, 142, 142, 142, 25,
173926
+ /* 2150 */ 25, 23, 15, 1, 322, 322, 322, 322, 322, 322,
173927
+ /* 2160 */ 322, 322, 322, 134, 322, 322, 322, 322, 139, 140,
173928
+ /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 134, 322, 322,
173929
+ /* 2180 */ 322, 322, 139, 140, 322, 322, 322, 322, 322, 322,
173930
+ /* 2190 */ 322, 322, 163, 322, 322, 322, 322, 322, 322, 322,
173931
+ /* 2200 */ 322, 322, 322, 322, 322, 322, 163, 322, 322, 322,
173058173932
/* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173059173933
/* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173060173934
/* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173061173935
/* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173062173936
/* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
@@ -173064,181 +173938,188 @@
173064173938
/* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173065173939
/* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173066173940
/* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173067173941
/* 2300 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173068173942
/* 2310 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173069
- /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322,
173943
+ /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173944
+ /* 2330 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173945
+ /* 2340 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173946
+ /* 2350 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173947
+ /* 2360 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173948
+ /* 2370 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173949
+ /* 2380 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173950
+ /* 2390 */ 186, 186, 186,
173070173951
};
173071173952
#define YY_SHIFT_COUNT (582)
173072173953
#define YY_SHIFT_MIN (0)
173073
-#define YY_SHIFT_MAX (2128)
173954
+#define YY_SHIFT_MAX (2152)
173074173955
static const unsigned short int yy_shift_ofst[] = {
173075
- /* 0 */ 1792, 1588, 1494, 322, 322, 399, 306, 1319, 1339, 1430,
173076
- /* 10 */ 1828, 1828, 1828, 580, 399, 399, 399, 399, 399, 0,
173077
- /* 20 */ 0, 214, 1093, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173078
- /* 30 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1130, 1130,
173079
- /* 40 */ 365, 365, 55, 278, 436, 713, 713, 201, 201, 201,
173080
- /* 50 */ 201, 40, 111, 258, 361, 469, 512, 583, 622, 693,
173081
- /* 60 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093,
173082
- /* 70 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
173083
- /* 80 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1523, 1602,
173084
- /* 90 */ 1674, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173085
- /* 100 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173086
- /* 110 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173087
- /* 120 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173088
- /* 130 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173089
- /* 140 */ 137, 181, 181, 181, 181, 181, 181, 181, 96, 222,
173090
- /* 150 */ 143, 477, 713, 1133, 1268, 713, 713, 79, 79, 713,
173091
- /* 160 */ 770, 83, 65, 65, 65, 288, 162, 162, 2142, 2142,
173092
- /* 170 */ 696, 696, 696, 238, 474, 474, 474, 474, 1217, 1217,
173093
- /* 180 */ 678, 477, 324, 398, 713, 713, 713, 713, 713, 713,
173094
- /* 190 */ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
173095
- /* 200 */ 713, 713, 713, 1220, 366, 366, 713, 917, 283, 283,
173096
- /* 210 */ 434, 434, 605, 605, 1298, 2142, 2142, 2142, 2142, 2142,
173097
- /* 220 */ 2142, 2142, 1179, 1157, 1157, 487, 527, 585, 645, 749,
173098
- /* 230 */ 914, 968, 752, 713, 713, 713, 713, 713, 713, 713,
173099
- /* 240 */ 713, 713, 713, 303, 713, 713, 713, 713, 713, 713,
173100
- /* 250 */ 713, 713, 713, 713, 713, 713, 797, 797, 797, 713,
173101
- /* 260 */ 713, 713, 959, 713, 713, 713, 1169, 1271, 713, 713,
173102
- /* 270 */ 1330, 713, 713, 713, 713, 713, 713, 713, 713, 629,
173103
- /* 280 */ 7, 91, 876, 876, 876, 876, 953, 91, 91, 1246,
173104
- /* 290 */ 1065, 1106, 1374, 1329, 1348, 468, 1348, 1394, 785, 1329,
173105
- /* 300 */ 1329, 785, 1329, 468, 1394, 859, 854, 1402, 1449, 1449,
173106
- /* 310 */ 1449, 1173, 1173, 1173, 1173, 1355, 1355, 1030, 1341, 405,
173107
- /* 320 */ 1230, 1795, 1795, 1711, 1711, 1829, 1829, 1711, 1717, 1719,
173108
- /* 330 */ 1850, 1833, 1860, 1860, 1860, 1860, 1711, 1868, 1740, 1719,
173109
- /* 340 */ 1719, 1740, 1850, 1833, 1740, 1833, 1740, 1711, 1868, 1745,
173110
- /* 350 */ 1843, 1711, 1868, 1887, 1711, 1868, 1711, 1868, 1887, 1801,
173111
- /* 360 */ 1801, 1801, 1855, 1900, 1900, 1887, 1801, 1797, 1801, 1855,
173112
- /* 370 */ 1801, 1801, 1761, 1912, 1830, 1830, 1887, 1711, 1862, 1862,
173113
- /* 380 */ 1875, 1875, 1810, 1815, 1940, 1711, 1807, 1810, 1821, 1823,
173114
- /* 390 */ 1740, 1945, 1963, 1963, 1974, 1974, 1974, 2142, 2142, 2142,
173115
- /* 400 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
173116
- /* 410 */ 2142, 2142, 20, 1224, 256, 1111, 1115, 1114, 1192, 1496,
173117
- /* 420 */ 1424, 1505, 1427, 355, 1383, 1537, 1506, 1538, 1553, 1583,
173118
- /* 430 */ 1584, 1591, 1625, 541, 1445, 1562, 1450, 1572, 1515, 1428,
173119
- /* 440 */ 1532, 1592, 1629, 1520, 1630, 1639, 1510, 1544, 1662, 1675,
173120
- /* 450 */ 1551, 48, 1996, 2001, 1983, 1844, 1993, 1994, 1986, 1989,
173121
- /* 460 */ 1874, 1863, 1885, 1991, 1991, 1995, 1876, 1997, 1877, 2004,
173122
- /* 470 */ 2021, 1881, 1894, 1991, 1895, 1965, 1990, 1991, 1878, 1975,
173123
- /* 480 */ 1977, 1978, 1979, 1903, 1918, 2002, 1896, 2034, 2033, 2017,
173124
- /* 490 */ 1925, 1880, 1976, 2018, 1980, 1967, 2005, 1904, 1932, 2025,
173125
- /* 500 */ 2030, 2032, 1921, 1928, 2035, 1987, 2036, 2037, 2038, 2040,
173126
- /* 510 */ 1988, 2006, 2039, 1960, 2041, 2042, 1999, 2023, 2044, 2043,
173127
- /* 520 */ 1919, 2048, 2049, 2050, 2046, 2051, 2053, 1981, 1935, 2056,
173128
- /* 530 */ 2057, 1966, 2047, 2061, 1941, 2060, 2052, 2054, 2055, 2058,
173129
- /* 540 */ 2003, 2012, 2007, 2059, 2015, 2008, 2062, 2071, 2073, 2074,
173130
- /* 550 */ 2072, 2075, 2065, 1962, 1964, 2079, 2060, 2082, 2084, 2085,
173131
- /* 560 */ 2087, 2086, 2089, 2088, 2091, 2093, 2099, 2094, 2095, 2096,
173132
- /* 570 */ 2097, 2100, 2101, 2102, 1998, 1984, 1985, 2000, 2103, 2098,
173133
- /* 580 */ 2109, 2117, 2128,
173134
-};
173135
-#define YY_REDUCE_COUNT (411)
173136
-#define YY_REDUCE_MIN (-275)
173137
-#define YY_REDUCE_MAX (1798)
173956
+ /* 0 */ 2029, 1801, 2043, 1380, 1380, 33, 391, 1496, 1569, 1642,
173957
+ /* 10 */ 702, 702, 702, 193, 33, 33, 33, 33, 33, 0,
173958
+ /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702,
173959
+ /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 406, 406,
173960
+ /* 40 */ 111, 111, 218, 447, 547, 598, 598, 260, 260, 260,
173961
+ /* 50 */ 260, 40, 112, 320, 340, 445, 489, 593, 637, 741,
173962
+ /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177,
173963
+ /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
173964
+ /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554,
173965
+ /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702,
173966
+ /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173967
+ /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173968
+ /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173969
+ /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173970
+ /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198,
173971
+ /* 150 */ 183, 99, 236, 292, 598, 793, 167, 598, 598, 880,
173972
+ /* 160 */ 880, 598, 857, 150, 195, 195, 195, 264, 113, 113,
173973
+ /* 170 */ 2207, 2207, 854, 854, 854, 751, 765, 765, 765, 765,
173974
+ /* 180 */ 1096, 1096, 725, 292, 882, 904, 598, 598, 598, 598,
173975
+ /* 190 */ 598, 598, 598, 598, 598, 598, 598, 598, 598, 598,
173976
+ /* 200 */ 598, 598, 598, 598, 598, 1273, 1032, 1032, 598, 147,
173977
+ /* 210 */ 1098, 1098, 603, 603, 1276, 1276, 363, 2207, 2207, 2207,
173978
+ /* 220 */ 2207, 2207, 2207, 2207, 469, 617, 617, 801, 336, 461,
173979
+ /* 230 */ 804, 864, 615, 891, 913, 598, 598, 598, 598, 598,
173980
+ /* 240 */ 598, 598, 598, 598, 598, 653, 598, 598, 598, 598,
173981
+ /* 250 */ 598, 598, 598, 598, 598, 598, 598, 598, 1105, 1105,
173982
+ /* 260 */ 1105, 598, 598, 598, 1194, 598, 598, 598, 1215, 1249,
173983
+ /* 270 */ 598, 1353, 598, 598, 598, 598, 598, 598, 598, 598,
173984
+ /* 280 */ 677, 449, 902, 1338, 1338, 1338, 1338, 1248, 902, 902,
173985
+ /* 290 */ 326, 1151, 1047, 755, 749, 1371, 960, 1371, 1007, 1162,
173986
+ /* 300 */ 749, 749, 1162, 749, 960, 1007, 1274, 738, 215, 1300,
173987
+ /* 310 */ 1300, 1300, 1395, 1395, 1395, 1395, 1368, 1368, 1033, 1414,
173988
+ /* 320 */ 1387, 1361, 1759, 1759, 1685, 1685, 1792, 1792, 1685, 1683,
173989
+ /* 330 */ 1686, 1814, 1797, 1825, 1825, 1825, 1825, 1685, 1836, 1707,
173990
+ /* 340 */ 1686, 1686, 1707, 1814, 1797, 1707, 1797, 1707, 1685, 1836,
173991
+ /* 350 */ 1710, 1807, 1685, 1836, 1854, 1685, 1836, 1685, 1836, 1854,
173992
+ /* 360 */ 1769, 1769, 1769, 1822, 1870, 1870, 1854, 1769, 1766, 1769,
173993
+ /* 370 */ 1822, 1769, 1769, 1729, 1873, 1785, 1785, 1854, 1685, 1823,
173994
+ /* 380 */ 1823, 1840, 1840, 1778, 1782, 1909, 1685, 1779, 1778, 1789,
173995
+ /* 390 */ 1800, 1707, 1919, 1939, 1939, 1948, 1948, 1948, 2207, 2207,
173996
+ /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207,
173997
+ /* 410 */ 2207, 2207, 2207, 69, 1037, 79, 1088, 651, 1196, 1415,
173998
+ /* 420 */ 1501, 1439, 1369, 1452, 911, 1211, 1524, 1469, 1551, 1567,
173999
+ /* 430 */ 1570, 1624, 1640, 1644, 1499, 1440, 1572, 1464, 1597, 275,
174000
+ /* 440 */ 782, 1586, 1648, 1678, 1553, 1682, 1687, 1388, 1502, 1696,
174001
+ /* 450 */ 1706, 1588, 1486, 1971, 1975, 1957, 1820, 1972, 1973, 1965,
174002
+ /* 460 */ 1967, 1851, 1841, 1861, 1969, 1969, 1974, 1852, 1976, 1855,
174003
+ /* 470 */ 1981, 1998, 1858, 1871, 1969, 1872, 1942, 1968, 1969, 1856,
174004
+ /* 480 */ 1952, 1953, 1955, 1956, 1881, 1896, 1980, 1874, 2014, 2015,
174005
+ /* 490 */ 1997, 1905, 1860, 1954, 1999, 1964, 1950, 1994, 1894, 1921,
174006
+ /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047,
174007
+ /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057,
174008
+ /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1959,
174009
+ /* 530 */ 2069, 2071, 1978, 2062, 2075, 1958, 2073, 2070, 2072, 2076,
174010
+ /* 540 */ 2078, 2010, 2027, 2022, 2074, 2031, 2019, 2081, 2082, 2094,
174011
+ /* 550 */ 2093, 2095, 2096, 2085, 1983, 1986, 2100, 2073, 2101, 2104,
174012
+ /* 560 */ 2107, 2109, 2108, 2110, 2111, 2114, 2121, 2115, 2116, 2117,
174013
+ /* 570 */ 2118, 2122, 2123, 2124, 2007, 2004, 2005, 2006, 2125, 2128,
174014
+ /* 580 */ 2137, 2138, 2152,
174015
+};
174016
+#define YY_REDUCE_COUNT (412)
174017
+#define YY_REDUCE_MIN (-276)
174018
+#define YY_REDUCE_MAX (1775)
173138174019
static const short yy_reduce_ofst[] = {
173139
- /* 0 */ -71, 194, 343, 835, -180, -177, 838, -194, -188, -185,
173140
- /* 10 */ -183, 82, 183, -65, 133, 245, 346, 407, 458, -178,
173141
- /* 20 */ 75, -275, -4, 310, 312, 489, 575, 596, 463, 686,
173142
- /* 30 */ 707, 725, 780, 1098, 856, 778, 1059, 1090, 708, 887,
173143
- /* 40 */ 86, 448, 980, 630, 680, 681, 684, 796, 801, 796,
173144
- /* 50 */ 801, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173145
- /* 60 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173146
- /* 70 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173147
- /* 80 */ -261, -261, -261, -261, -261, -261, -261, -261, 391, 886,
173148
- /* 90 */ 888, 1013, 1016, 1081, 1087, 1151, 1159, 1177, 1185, 1188,
173149
- /* 100 */ 1190, 1194, 1197, 1203, 1247, 1260, 1264, 1267, 1269, 1273,
173150
- /* 110 */ 1315, 1322, 1335, 1337, 1356, 1362, 1418, 1425, 1453, 1457,
173151
- /* 120 */ 1465, 1473, 1487, 1495, 1507, 1517, 1521, 1534, 1543, 1546,
173152
- /* 130 */ 1549, 1552, 1554, 1560, 1581, 1590, 1593, 1595, 1621, 1623,
173153
- /* 140 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173154
- /* 150 */ -261, -186, -117, 260, 263, 460, 631, -74, 497, -181,
173155
- /* 160 */ -261, 939, 176, 274, 338, 676, -261, -261, -261, -261,
173156
- /* 170 */ -212, -212, -212, -184, 149, 777, 1061, 1103, 265, 419,
173157
- /* 180 */ -254, 670, 677, 677, -11, -129, 184, 488, 736, 789,
173158
- /* 190 */ 805, 844, 403, 529, 579, 668, 783, 841, 1158, 1112,
173159
- /* 200 */ 806, 861, 1095, 846, 839, 1031, -189, 1077, 1080, 1116,
173160
- /* 210 */ 1084, 1156, 1139, 1221, 46, 1099, 1037, 1118, 1171, 1214,
173161
- /* 220 */ 1210, 1258, -210, -190, -176, -115, 117, 262, 376, 490,
173162
- /* 230 */ 511, 520, 618, 639, 743, 901, 907, 958, 1014, 1055,
173163
- /* 240 */ 1108, 1193, 1244, 720, 1248, 1277, 1324, 1347, 1417, 1431,
173164
- /* 250 */ 1432, 1440, 1451, 1452, 1463, 1478, 1286, 1350, 1369, 1490,
173165
- /* 260 */ 1498, 1501, 773, 1509, 1513, 1528, 1292, 1367, 1535, 1536,
173166
- /* 270 */ 1477, 1542, 376, 1547, 1550, 1555, 1559, 1568, 1571, 1441,
173167
- /* 280 */ 1443, 1474, 1511, 1516, 1519, 1522, 773, 1474, 1474, 1503,
173168
- /* 290 */ 1567, 1594, 1484, 1527, 1556, 1570, 1557, 1524, 1573, 1545,
173169
- /* 300 */ 1548, 1576, 1561, 1587, 1540, 1575, 1606, 1611, 1622, 1624,
173170
- /* 310 */ 1626, 1582, 1597, 1598, 1599, 1601, 1603, 1563, 1608, 1605,
173171
- /* 320 */ 1604, 1564, 1566, 1655, 1660, 1578, 1579, 1665, 1586, 1607,
173172
- /* 330 */ 1610, 1642, 1641, 1645, 1646, 1647, 1679, 1688, 1644, 1618,
173173
- /* 340 */ 1619, 1648, 1628, 1659, 1649, 1663, 1650, 1700, 1702, 1612,
173174
- /* 350 */ 1615, 1706, 1708, 1689, 1709, 1712, 1713, 1715, 1691, 1698,
173175
- /* 360 */ 1699, 1701, 1693, 1704, 1707, 1705, 1714, 1703, 1718, 1710,
173176
- /* 370 */ 1720, 1721, 1632, 1634, 1664, 1666, 1729, 1751, 1635, 1636,
173177
- /* 380 */ 1692, 1694, 1716, 1722, 1684, 1763, 1685, 1723, 1724, 1727,
173178
- /* 390 */ 1730, 1768, 1783, 1784, 1793, 1794, 1796, 1683, 1686, 1690,
173179
- /* 400 */ 1782, 1779, 1780, 1781, 1785, 1788, 1774, 1775, 1786, 1787,
173180
- /* 410 */ 1789, 1798,
174020
+ /* 0 */ -66, 217, -63, -177, -180, 161, 364, 64, -183, 162,
174021
+ /* 10 */ 223, 367, 414, -173, 473, 514, 525, 622, 626, -207,
174022
+ /* 20 */ 351, -276, -38, 693, 811, 831, 833, 888, -188, 945,
174023
+ /* 30 */ 947, 416, 558, 951, 867, 287, 1078, 1080, -186, 224,
174024
+ /* 40 */ -132, 42, 964, 269, 417, 796, 810, -237, -231, -237,
174025
+ /* 50 */ -231, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174026
+ /* 60 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174027
+ /* 70 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174028
+ /* 80 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, 895,
174029
+ /* 90 */ 925, 967, 980, 1100, 1143, 1169, 1203, 1225, 1228, 1242,
174030
+ /* 100 */ 1247, 1250, 1253, 1255, 1261, 1267, 1272, 1275, 1283, 1286,
174031
+ /* 110 */ 1288, 1292, 1333, 1335, 1347, 1349, 1352, 1354, 1360, 1366,
174032
+ /* 120 */ 1381, 1391, 1406, 1408, 1413, 1416, 1418, 1422, 1425, 1427,
174033
+ /* 130 */ 1463, 1465, 1472, 1478, 1480, 1491, 1498, 1500, 1517, 1519,
174034
+ /* 140 */ 1528, 1536, -45, -45, -45, -45, -45, -45, -45, -45,
174035
+ /* 150 */ -45, -45, -45, 312, -158, 285, -219, 9, 166, 370,
174036
+ /* 160 */ 545, 707, -45, 930, 601, 963, 1067, 792, -45, -45,
174037
+ /* 170 */ -45, -45, -204, -204, -204, 369, -171, -129, 632, 678,
174038
+ /* 180 */ 202, 352, -270, 412, 627, 627, -9, 122, 415, 419,
174039
+ /* 190 */ -56, 248, 583, 920, 6, 261, 459, 795, 1049, 813,
174040
+ /* 200 */ 1062, 1082, -161, 778, 1063, 797, 870, 1003, 1128, 443,
174041
+ /* 210 */ 1031, 1072, 1191, 1192, 957, 1120, 105, 1149, 523, 933,
174042
+ /* 220 */ 1218, 1238, 1254, 1251, -138, 96, 117, 146, 181, 277,
174043
+ /* 230 */ 280, 421, 480, 712, 830, 850, 1085, 1099, 1129, 1209,
174044
+ /* 240 */ 1323, 1331, 1336, 1364, 1407, 368, 1412, 1433, 1438, 1474,
174045
+ /* 250 */ 1481, 1505, 1506, 1526, 1538, 1544, 1545, 1546, 722, 764,
174046
+ /* 260 */ 856, 1547, 1548, 1550, 1188, 1554, 1557, 1561, 1298, 1260,
174047
+ /* 270 */ 1562, 1456, 1564, 280, 1568, 1571, 1573, 1574, 1575, 1576,
174048
+ /* 280 */ 1457, 1477, 1520, 1514, 1515, 1516, 1518, 1188, 1520, 1520,
174049
+ /* 290 */ 1530, 1563, 1584, 1482, 1504, 1510, 1534, 1513, 1488, 1537,
174050
+ /* 300 */ 1512, 1521, 1539, 1522, 1541, 1493, 1583, 1559, 1565, 1585,
174051
+ /* 310 */ 1587, 1589, 1529, 1531, 1532, 1549, 1558, 1566, 1535, 1577,
174052
+ /* 320 */ 1582, 1622, 1533, 1540, 1627, 1628, 1552, 1555, 1633, 1560,
174053
+ /* 330 */ 1578, 1581, 1607, 1606, 1608, 1609, 1611, 1649, 1655, 1612,
174054
+ /* 340 */ 1590, 1591, 1613, 1594, 1621, 1614, 1623, 1616, 1666, 1668,
174055
+ /* 350 */ 1579, 1593, 1672, 1675, 1656, 1676, 1679, 1680, 1688, 1660,
174056
+ /* 360 */ 1667, 1670, 1671, 1663, 1669, 1673, 1674, 1689, 1681, 1692,
174057
+ /* 370 */ 1677, 1693, 1694, 1592, 1599, 1617, 1620, 1700, 1713, 1596,
174058
+ /* 380 */ 1598, 1658, 1659, 1691, 1684, 1654, 1735, 1664, 1697, 1690,
174059
+ /* 390 */ 1701, 1703, 1748, 1758, 1760, 1768, 1770, 1772, 1657, 1661,
174060
+ /* 400 */ 1665, 1761, 1754, 1757, 1762, 1763, 1764, 1750, 1751, 1765,
174061
+ /* 410 */ 1771, 1767, 1775,
173181174062
};
173182174063
static const YYACTIONTYPE yy_default[] = {
173183174064
/* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254,
173184174065
/* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397,
173185174066
/* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173186174067
/* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254,
173187174068
/* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254,
173188174069
/* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254,
173189
- /* 60 */ 1492, 1493, 1254, 1254, 1254, 1543, 1545, 1508, 1420, 1419,
173190
- /* 70 */ 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, 1486,
173191
- /* 80 */ 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, 1254,
174070
+ /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420,
174071
+ /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488,
174072
+ /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254,
173192174073
/* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173193174074
/* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173194174075
/* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173195174076
/* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173196174077
/* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173197
- /* 140 */ 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, 1456, 1458,
173198
- /* 150 */ 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, 1254, 1254,
173199
- /* 160 */ 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, 1473, 1472,
173200
- /* 170 */ 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, 1254, 1254,
173201
- /* 180 */ 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174078
+ /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457,
174079
+ /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254,
174080
+ /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461,
174081
+ /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254,
174082
+ /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173202174083
/* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173203
- /* 200 */ 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, 1578, 1578,
173204
- /* 210 */ 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, 1358, 1358,
173205
- /* 220 */ 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173206
- /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, 1546, 1254,
173207
- /* 240 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174084
+ /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287,
174085
+ /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358,
174086
+ /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254,
174087
+ /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548,
174088
+ /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173208174089
/* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173209
- /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, 1254, 1254,
173210
- /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, 1254,
173211
- /* 280 */ 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, 1357,
173212
- /* 290 */ 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, 1423,
173213
- /* 300 */ 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, 1397,
173214
- /* 310 */ 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, 1357,
173215
- /* 320 */ 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, 1638,
173216
- /* 330 */ 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, 1638,
173217
- /* 340 */ 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, 1525,
173218
- /* 350 */ 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, 1330,
173219
- /* 360 */ 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, 1319,
173220
- /* 370 */ 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, 1588,
173221
- /* 380 */ 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, 1401,
173222
- /* 390 */ 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, 1558,
173223
- /* 400 */ 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, 1288,
173224
- /* 410 */ 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, 1254,
173225
- /* 420 */ 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173226
- /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1564,
173227
- /* 440 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173228
- /* 450 */ 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, 1254,
173229
- /* 460 */ 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, 1254,
173230
- /* 470 */ 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, 1254,
173231
- /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, 1254,
173232
- /* 490 */ 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, 1254,
174090
+ /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254,
174091
+ /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608,
174092
+ /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342,
174093
+ /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410,
174094
+ /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397,
174095
+ /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364,
174096
+ /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509,
174097
+ /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410,
174098
+ /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272,
174099
+ /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499,
174100
+ /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330,
174101
+ /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588,
174102
+ /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403,
174103
+ /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660,
174104
+ /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288,
174105
+ /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618,
174106
+ /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254,
174107
+ /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174108
+ /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174109
+ /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254,
174110
+ /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254,
174111
+ /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254,
174112
+ /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254,
174113
+ /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254,
173233174114
/* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173234
- /* 510 */ 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174115
+ /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173235174116
/* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173236
- /* 530 */ 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, 1254,
174117
+ /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254,
173237174118
/* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173238
- /* 550 */ 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, 1254,
173239
- /* 560 */ 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174119
+ /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254,
174120
+ /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173240174121
/* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254,
173241174122
/* 580 */ 1266, 1254, 1254,
173242174123
};
173243174124
/********** End of lemon-generated parsing tables *****************************/
173244174125
@@ -173258,56 +174139,57 @@
173258174139
*/
173259174140
#ifdef YYFALLBACK
173260174141
static const YYCODETYPE yyFallback[] = {
173261174142
0, /* $ => nothing */
173262174143
0, /* SEMI => nothing */
173263
- 59, /* EXPLAIN => ID */
173264
- 59, /* QUERY => ID */
173265
- 59, /* PLAN => ID */
173266
- 59, /* BEGIN => ID */
174144
+ 60, /* EXPLAIN => ID */
174145
+ 60, /* QUERY => ID */
174146
+ 60, /* PLAN => ID */
174147
+ 60, /* BEGIN => ID */
173267174148
0, /* TRANSACTION => nothing */
173268
- 59, /* DEFERRED => ID */
173269
- 59, /* IMMEDIATE => ID */
173270
- 59, /* EXCLUSIVE => ID */
174149
+ 60, /* DEFERRED => ID */
174150
+ 60, /* IMMEDIATE => ID */
174151
+ 60, /* EXCLUSIVE => ID */
173271174152
0, /* COMMIT => nothing */
173272
- 59, /* END => ID */
173273
- 59, /* ROLLBACK => ID */
173274
- 59, /* SAVEPOINT => ID */
173275
- 59, /* RELEASE => ID */
174153
+ 60, /* END => ID */
174154
+ 60, /* ROLLBACK => ID */
174155
+ 60, /* SAVEPOINT => ID */
174156
+ 60, /* RELEASE => ID */
173276174157
0, /* TO => nothing */
173277174158
0, /* TABLE => nothing */
173278174159
0, /* CREATE => nothing */
173279
- 59, /* IF => ID */
174160
+ 60, /* IF => ID */
173280174161
0, /* NOT => nothing */
173281174162
0, /* EXISTS => nothing */
173282
- 59, /* TEMP => ID */
174163
+ 60, /* TEMP => ID */
173283174164
0, /* LP => nothing */
173284174165
0, /* RP => nothing */
173285174166
0, /* AS => nothing */
173286174167
0, /* COMMA => nothing */
173287
- 59, /* WITHOUT => ID */
173288
- 59, /* ABORT => ID */
173289
- 59, /* ACTION => ID */
173290
- 59, /* AFTER => ID */
173291
- 59, /* ANALYZE => ID */
173292
- 59, /* ASC => ID */
173293
- 59, /* ATTACH => ID */
173294
- 59, /* BEFORE => ID */
173295
- 59, /* BY => ID */
173296
- 59, /* CASCADE => ID */
173297
- 59, /* CAST => ID */
173298
- 59, /* CONFLICT => ID */
173299
- 59, /* DATABASE => ID */
173300
- 59, /* DESC => ID */
173301
- 59, /* DETACH => ID */
173302
- 59, /* EACH => ID */
173303
- 59, /* FAIL => ID */
174168
+ 60, /* WITHOUT => ID */
174169
+ 60, /* ABORT => ID */
174170
+ 60, /* ACTION => ID */
174171
+ 60, /* AFTER => ID */
174172
+ 60, /* ANALYZE => ID */
174173
+ 60, /* ASC => ID */
174174
+ 60, /* ATTACH => ID */
174175
+ 60, /* BEFORE => ID */
174176
+ 60, /* BY => ID */
174177
+ 60, /* CASCADE => ID */
174178
+ 60, /* CAST => ID */
174179
+ 60, /* CONFLICT => ID */
174180
+ 60, /* DATABASE => ID */
174181
+ 60, /* DESC => ID */
174182
+ 60, /* DETACH => ID */
174183
+ 60, /* EACH => ID */
174184
+ 60, /* FAIL => ID */
173304174185
0, /* OR => nothing */
173305174186
0, /* AND => nothing */
173306174187
0, /* IS => nothing */
173307
- 59, /* MATCH => ID */
173308
- 59, /* LIKE_KW => ID */
174188
+ 0, /* ISNOT => nothing */
174189
+ 60, /* MATCH => ID */
174190
+ 60, /* LIKE_KW => ID */
173309174191
0, /* BETWEEN => nothing */
173310174192
0, /* IN => nothing */
173311174193
0, /* ISNULL => nothing */
173312174194
0, /* NOTNULL => nothing */
173313174195
0, /* NE => nothing */
@@ -173316,51 +174198,51 @@
173316174198
0, /* LE => nothing */
173317174199
0, /* LT => nothing */
173318174200
0, /* GE => nothing */
173319174201
0, /* ESCAPE => nothing */
173320174202
0, /* ID => nothing */
173321
- 59, /* COLUMNKW => ID */
173322
- 59, /* DO => ID */
173323
- 59, /* FOR => ID */
173324
- 59, /* IGNORE => ID */
173325
- 59, /* INITIALLY => ID */
173326
- 59, /* INSTEAD => ID */
173327
- 59, /* NO => ID */
173328
- 59, /* KEY => ID */
173329
- 59, /* OF => ID */
173330
- 59, /* OFFSET => ID */
173331
- 59, /* PRAGMA => ID */
173332
- 59, /* RAISE => ID */
173333
- 59, /* RECURSIVE => ID */
173334
- 59, /* REPLACE => ID */
173335
- 59, /* RESTRICT => ID */
173336
- 59, /* ROW => ID */
173337
- 59, /* ROWS => ID */
173338
- 59, /* TRIGGER => ID */
173339
- 59, /* VACUUM => ID */
173340
- 59, /* VIEW => ID */
173341
- 59, /* VIRTUAL => ID */
173342
- 59, /* WITH => ID */
173343
- 59, /* NULLS => ID */
173344
- 59, /* FIRST => ID */
173345
- 59, /* LAST => ID */
173346
- 59, /* CURRENT => ID */
173347
- 59, /* FOLLOWING => ID */
173348
- 59, /* PARTITION => ID */
173349
- 59, /* PRECEDING => ID */
173350
- 59, /* RANGE => ID */
173351
- 59, /* UNBOUNDED => ID */
173352
- 59, /* EXCLUDE => ID */
173353
- 59, /* GROUPS => ID */
173354
- 59, /* OTHERS => ID */
173355
- 59, /* TIES => ID */
173356
- 59, /* GENERATED => ID */
173357
- 59, /* ALWAYS => ID */
173358
- 59, /* MATERIALIZED => ID */
173359
- 59, /* REINDEX => ID */
173360
- 59, /* RENAME => ID */
173361
- 59, /* CTIME_KW => ID */
174203
+ 60, /* COLUMNKW => ID */
174204
+ 60, /* DO => ID */
174205
+ 60, /* FOR => ID */
174206
+ 60, /* IGNORE => ID */
174207
+ 60, /* INITIALLY => ID */
174208
+ 60, /* INSTEAD => ID */
174209
+ 60, /* NO => ID */
174210
+ 60, /* KEY => ID */
174211
+ 60, /* OF => ID */
174212
+ 60, /* OFFSET => ID */
174213
+ 60, /* PRAGMA => ID */
174214
+ 60, /* RAISE => ID */
174215
+ 60, /* RECURSIVE => ID */
174216
+ 60, /* REPLACE => ID */
174217
+ 60, /* RESTRICT => ID */
174218
+ 60, /* ROW => ID */
174219
+ 60, /* ROWS => ID */
174220
+ 60, /* TRIGGER => ID */
174221
+ 60, /* VACUUM => ID */
174222
+ 60, /* VIEW => ID */
174223
+ 60, /* VIRTUAL => ID */
174224
+ 60, /* WITH => ID */
174225
+ 60, /* NULLS => ID */
174226
+ 60, /* FIRST => ID */
174227
+ 60, /* LAST => ID */
174228
+ 60, /* CURRENT => ID */
174229
+ 60, /* FOLLOWING => ID */
174230
+ 60, /* PARTITION => ID */
174231
+ 60, /* PRECEDING => ID */
174232
+ 60, /* RANGE => ID */
174233
+ 60, /* UNBOUNDED => ID */
174234
+ 60, /* EXCLUDE => ID */
174235
+ 60, /* GROUPS => ID */
174236
+ 60, /* OTHERS => ID */
174237
+ 60, /* TIES => ID */
174238
+ 60, /* GENERATED => ID */
174239
+ 60, /* ALWAYS => ID */
174240
+ 60, /* MATERIALIZED => ID */
174241
+ 60, /* REINDEX => ID */
174242
+ 60, /* RENAME => ID */
174243
+ 60, /* CTIME_KW => ID */
173362174244
0, /* ANY => nothing */
173363174245
0, /* BITAND => nothing */
173364174246
0, /* BITOR => nothing */
173365174247
0, /* LSHIFT => nothing */
173366174248
0, /* RSHIFT => nothing */
@@ -173427,14 +174309,13 @@
173427174309
0, /* FILTER => nothing */
173428174310
0, /* COLUMN => nothing */
173429174311
0, /* AGG_FUNCTION => nothing */
173430174312
0, /* AGG_COLUMN => nothing */
173431174313
0, /* TRUEFALSE => nothing */
173432
- 0, /* ISNOT => nothing */
173433174314
0, /* FUNCTION => nothing */
173434
- 0, /* UMINUS => nothing */
173435174315
0, /* UPLUS => nothing */
174316
+ 0, /* UMINUS => nothing */
173436174317
0, /* TRUTH => nothing */
173437174318
0, /* REGISTER => nothing */
173438174319
0, /* VECTOR => nothing */
173439174320
0, /* SELECT_COLUMN => nothing */
173440174321
0, /* IF_NULL_ROW => nothing */
@@ -173571,139 +174452,139 @@
173571174452
/* 41 */ "EACH",
173572174453
/* 42 */ "FAIL",
173573174454
/* 43 */ "OR",
173574174455
/* 44 */ "AND",
173575174456
/* 45 */ "IS",
173576
- /* 46 */ "MATCH",
173577
- /* 47 */ "LIKE_KW",
173578
- /* 48 */ "BETWEEN",
173579
- /* 49 */ "IN",
173580
- /* 50 */ "ISNULL",
173581
- /* 51 */ "NOTNULL",
173582
- /* 52 */ "NE",
173583
- /* 53 */ "EQ",
173584
- /* 54 */ "GT",
173585
- /* 55 */ "LE",
173586
- /* 56 */ "LT",
173587
- /* 57 */ "GE",
173588
- /* 58 */ "ESCAPE",
173589
- /* 59 */ "ID",
173590
- /* 60 */ "COLUMNKW",
173591
- /* 61 */ "DO",
173592
- /* 62 */ "FOR",
173593
- /* 63 */ "IGNORE",
173594
- /* 64 */ "INITIALLY",
173595
- /* 65 */ "INSTEAD",
173596
- /* 66 */ "NO",
173597
- /* 67 */ "KEY",
173598
- /* 68 */ "OF",
173599
- /* 69 */ "OFFSET",
173600
- /* 70 */ "PRAGMA",
173601
- /* 71 */ "RAISE",
173602
- /* 72 */ "RECURSIVE",
173603
- /* 73 */ "REPLACE",
173604
- /* 74 */ "RESTRICT",
173605
- /* 75 */ "ROW",
173606
- /* 76 */ "ROWS",
173607
- /* 77 */ "TRIGGER",
173608
- /* 78 */ "VACUUM",
173609
- /* 79 */ "VIEW",
173610
- /* 80 */ "VIRTUAL",
173611
- /* 81 */ "WITH",
173612
- /* 82 */ "NULLS",
173613
- /* 83 */ "FIRST",
173614
- /* 84 */ "LAST",
173615
- /* 85 */ "CURRENT",
173616
- /* 86 */ "FOLLOWING",
173617
- /* 87 */ "PARTITION",
173618
- /* 88 */ "PRECEDING",
173619
- /* 89 */ "RANGE",
173620
- /* 90 */ "UNBOUNDED",
173621
- /* 91 */ "EXCLUDE",
173622
- /* 92 */ "GROUPS",
173623
- /* 93 */ "OTHERS",
173624
- /* 94 */ "TIES",
173625
- /* 95 */ "GENERATED",
173626
- /* 96 */ "ALWAYS",
173627
- /* 97 */ "MATERIALIZED",
173628
- /* 98 */ "REINDEX",
173629
- /* 99 */ "RENAME",
173630
- /* 100 */ "CTIME_KW",
173631
- /* 101 */ "ANY",
173632
- /* 102 */ "BITAND",
173633
- /* 103 */ "BITOR",
173634
- /* 104 */ "LSHIFT",
173635
- /* 105 */ "RSHIFT",
173636
- /* 106 */ "PLUS",
173637
- /* 107 */ "MINUS",
173638
- /* 108 */ "STAR",
173639
- /* 109 */ "SLASH",
173640
- /* 110 */ "REM",
173641
- /* 111 */ "CONCAT",
173642
- /* 112 */ "PTR",
173643
- /* 113 */ "COLLATE",
173644
- /* 114 */ "BITNOT",
173645
- /* 115 */ "ON",
173646
- /* 116 */ "INDEXED",
173647
- /* 117 */ "STRING",
173648
- /* 118 */ "JOIN_KW",
173649
- /* 119 */ "CONSTRAINT",
173650
- /* 120 */ "DEFAULT",
173651
- /* 121 */ "NULL",
173652
- /* 122 */ "PRIMARY",
173653
- /* 123 */ "UNIQUE",
173654
- /* 124 */ "CHECK",
173655
- /* 125 */ "REFERENCES",
173656
- /* 126 */ "AUTOINCR",
173657
- /* 127 */ "INSERT",
173658
- /* 128 */ "DELETE",
173659
- /* 129 */ "UPDATE",
173660
- /* 130 */ "SET",
173661
- /* 131 */ "DEFERRABLE",
173662
- /* 132 */ "FOREIGN",
173663
- /* 133 */ "DROP",
173664
- /* 134 */ "UNION",
173665
- /* 135 */ "ALL",
173666
- /* 136 */ "EXCEPT",
173667
- /* 137 */ "INTERSECT",
173668
- /* 138 */ "SELECT",
173669
- /* 139 */ "VALUES",
173670
- /* 140 */ "DISTINCT",
173671
- /* 141 */ "DOT",
173672
- /* 142 */ "FROM",
173673
- /* 143 */ "JOIN",
173674
- /* 144 */ "USING",
173675
- /* 145 */ "ORDER",
173676
- /* 146 */ "GROUP",
173677
- /* 147 */ "HAVING",
173678
- /* 148 */ "LIMIT",
173679
- /* 149 */ "WHERE",
173680
- /* 150 */ "RETURNING",
173681
- /* 151 */ "INTO",
173682
- /* 152 */ "NOTHING",
173683
- /* 153 */ "FLOAT",
173684
- /* 154 */ "BLOB",
173685
- /* 155 */ "INTEGER",
173686
- /* 156 */ "VARIABLE",
173687
- /* 157 */ "CASE",
173688
- /* 158 */ "WHEN",
173689
- /* 159 */ "THEN",
173690
- /* 160 */ "ELSE",
173691
- /* 161 */ "INDEX",
173692
- /* 162 */ "ALTER",
173693
- /* 163 */ "ADD",
173694
- /* 164 */ "WINDOW",
173695
- /* 165 */ "OVER",
173696
- /* 166 */ "FILTER",
173697
- /* 167 */ "COLUMN",
173698
- /* 168 */ "AGG_FUNCTION",
173699
- /* 169 */ "AGG_COLUMN",
173700
- /* 170 */ "TRUEFALSE",
173701
- /* 171 */ "ISNOT",
174457
+ /* 46 */ "ISNOT",
174458
+ /* 47 */ "MATCH",
174459
+ /* 48 */ "LIKE_KW",
174460
+ /* 49 */ "BETWEEN",
174461
+ /* 50 */ "IN",
174462
+ /* 51 */ "ISNULL",
174463
+ /* 52 */ "NOTNULL",
174464
+ /* 53 */ "NE",
174465
+ /* 54 */ "EQ",
174466
+ /* 55 */ "GT",
174467
+ /* 56 */ "LE",
174468
+ /* 57 */ "LT",
174469
+ /* 58 */ "GE",
174470
+ /* 59 */ "ESCAPE",
174471
+ /* 60 */ "ID",
174472
+ /* 61 */ "COLUMNKW",
174473
+ /* 62 */ "DO",
174474
+ /* 63 */ "FOR",
174475
+ /* 64 */ "IGNORE",
174476
+ /* 65 */ "INITIALLY",
174477
+ /* 66 */ "INSTEAD",
174478
+ /* 67 */ "NO",
174479
+ /* 68 */ "KEY",
174480
+ /* 69 */ "OF",
174481
+ /* 70 */ "OFFSET",
174482
+ /* 71 */ "PRAGMA",
174483
+ /* 72 */ "RAISE",
174484
+ /* 73 */ "RECURSIVE",
174485
+ /* 74 */ "REPLACE",
174486
+ /* 75 */ "RESTRICT",
174487
+ /* 76 */ "ROW",
174488
+ /* 77 */ "ROWS",
174489
+ /* 78 */ "TRIGGER",
174490
+ /* 79 */ "VACUUM",
174491
+ /* 80 */ "VIEW",
174492
+ /* 81 */ "VIRTUAL",
174493
+ /* 82 */ "WITH",
174494
+ /* 83 */ "NULLS",
174495
+ /* 84 */ "FIRST",
174496
+ /* 85 */ "LAST",
174497
+ /* 86 */ "CURRENT",
174498
+ /* 87 */ "FOLLOWING",
174499
+ /* 88 */ "PARTITION",
174500
+ /* 89 */ "PRECEDING",
174501
+ /* 90 */ "RANGE",
174502
+ /* 91 */ "UNBOUNDED",
174503
+ /* 92 */ "EXCLUDE",
174504
+ /* 93 */ "GROUPS",
174505
+ /* 94 */ "OTHERS",
174506
+ /* 95 */ "TIES",
174507
+ /* 96 */ "GENERATED",
174508
+ /* 97 */ "ALWAYS",
174509
+ /* 98 */ "MATERIALIZED",
174510
+ /* 99 */ "REINDEX",
174511
+ /* 100 */ "RENAME",
174512
+ /* 101 */ "CTIME_KW",
174513
+ /* 102 */ "ANY",
174514
+ /* 103 */ "BITAND",
174515
+ /* 104 */ "BITOR",
174516
+ /* 105 */ "LSHIFT",
174517
+ /* 106 */ "RSHIFT",
174518
+ /* 107 */ "PLUS",
174519
+ /* 108 */ "MINUS",
174520
+ /* 109 */ "STAR",
174521
+ /* 110 */ "SLASH",
174522
+ /* 111 */ "REM",
174523
+ /* 112 */ "CONCAT",
174524
+ /* 113 */ "PTR",
174525
+ /* 114 */ "COLLATE",
174526
+ /* 115 */ "BITNOT",
174527
+ /* 116 */ "ON",
174528
+ /* 117 */ "INDEXED",
174529
+ /* 118 */ "STRING",
174530
+ /* 119 */ "JOIN_KW",
174531
+ /* 120 */ "CONSTRAINT",
174532
+ /* 121 */ "DEFAULT",
174533
+ /* 122 */ "NULL",
174534
+ /* 123 */ "PRIMARY",
174535
+ /* 124 */ "UNIQUE",
174536
+ /* 125 */ "CHECK",
174537
+ /* 126 */ "REFERENCES",
174538
+ /* 127 */ "AUTOINCR",
174539
+ /* 128 */ "INSERT",
174540
+ /* 129 */ "DELETE",
174541
+ /* 130 */ "UPDATE",
174542
+ /* 131 */ "SET",
174543
+ /* 132 */ "DEFERRABLE",
174544
+ /* 133 */ "FOREIGN",
174545
+ /* 134 */ "DROP",
174546
+ /* 135 */ "UNION",
174547
+ /* 136 */ "ALL",
174548
+ /* 137 */ "EXCEPT",
174549
+ /* 138 */ "INTERSECT",
174550
+ /* 139 */ "SELECT",
174551
+ /* 140 */ "VALUES",
174552
+ /* 141 */ "DISTINCT",
174553
+ /* 142 */ "DOT",
174554
+ /* 143 */ "FROM",
174555
+ /* 144 */ "JOIN",
174556
+ /* 145 */ "USING",
174557
+ /* 146 */ "ORDER",
174558
+ /* 147 */ "GROUP",
174559
+ /* 148 */ "HAVING",
174560
+ /* 149 */ "LIMIT",
174561
+ /* 150 */ "WHERE",
174562
+ /* 151 */ "RETURNING",
174563
+ /* 152 */ "INTO",
174564
+ /* 153 */ "NOTHING",
174565
+ /* 154 */ "FLOAT",
174566
+ /* 155 */ "BLOB",
174567
+ /* 156 */ "INTEGER",
174568
+ /* 157 */ "VARIABLE",
174569
+ /* 158 */ "CASE",
174570
+ /* 159 */ "WHEN",
174571
+ /* 160 */ "THEN",
174572
+ /* 161 */ "ELSE",
174573
+ /* 162 */ "INDEX",
174574
+ /* 163 */ "ALTER",
174575
+ /* 164 */ "ADD",
174576
+ /* 165 */ "WINDOW",
174577
+ /* 166 */ "OVER",
174578
+ /* 167 */ "FILTER",
174579
+ /* 168 */ "COLUMN",
174580
+ /* 169 */ "AGG_FUNCTION",
174581
+ /* 170 */ "AGG_COLUMN",
174582
+ /* 171 */ "TRUEFALSE",
173702174583
/* 172 */ "FUNCTION",
173703
- /* 173 */ "UMINUS",
173704
- /* 174 */ "UPLUS",
174584
+ /* 173 */ "UPLUS",
174585
+ /* 174 */ "UMINUS",
173705174586
/* 175 */ "TRUTH",
173706174587
/* 176 */ "REGISTER",
173707174588
/* 177 */ "VECTOR",
173708174589
/* 178 */ "SELECT_COLUMN",
173709174590
/* 179 */ "IF_NULL_ROW",
@@ -174134,11 +175015,11 @@
174134175015
/* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
174135175016
/* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
174136175017
/* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
174137175018
/* 278 */ "trigger_cmd ::= scanpt select scanpt",
174138175019
/* 279 */ "expr ::= RAISE LP IGNORE RP",
174139
- /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
175020
+ /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP",
174140175021
/* 281 */ "raisetype ::= ROLLBACK",
174141175022
/* 282 */ "raisetype ::= ABORT",
174142175023
/* 283 */ "raisetype ::= FAIL",
174143175024
/* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
174144175025
/* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
@@ -175059,11 +175940,11 @@
175059175940
293, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
175060175941
293, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
175061175942
293, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
175062175943
293, /* (278) trigger_cmd ::= scanpt select scanpt */
175063175944
218, /* (279) expr ::= RAISE LP IGNORE RP */
175064
- 218, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
175945
+ 218, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
175065175946
237, /* (281) raisetype ::= ROLLBACK */
175066175947
237, /* (282) raisetype ::= ABORT */
175067175948
237, /* (283) raisetype ::= FAIL */
175068175949
191, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
175069175950
191, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -175473,11 +176354,11 @@
175473176354
-9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
175474176355
-8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
175475176356
-6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
175476176357
-3, /* (278) trigger_cmd ::= scanpt select scanpt */
175477176358
-4, /* (279) expr ::= RAISE LP IGNORE RP */
175478
- -6, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
176359
+ -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
175479176360
-1, /* (281) raisetype ::= ROLLBACK */
175480176361
-1, /* (282) raisetype ::= ABORT */
175481176362
-1, /* (283) raisetype ::= FAIL */
175482176363
-4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
175483176364
-6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -176560,12 +177441,21 @@
176560177441
case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
176561177442
{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/}
176562177443
break;
176563177444
case 216: /* expr ::= PLUS|MINUS expr */
176564177445
{
176565
- yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy454, 0);
176566
- /*A-overwrites-B*/
177446
+ Expr *p = yymsp[0].minor.yy454;
177447
+ u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS);
177448
+ assert( TK_UPLUS>TK_PLUS );
177449
+ assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) );
177450
+ if( p && p->op==TK_UPLUS ){
177451
+ p->op = op;
177452
+ yymsp[-1].minor.yy454 = p;
177453
+ }else{
177454
+ yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0);
177455
+ /*A-overwrites-B*/
177456
+ }
176567177457
}
176568177458
break;
176569177459
case 217: /* expr ::= expr PTR expr */
176570177460
{
176571177461
ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454);
@@ -176849,13 +177739,13 @@
176849177739
if( yymsp[-3].minor.yy454 ){
176850177740
yymsp[-3].minor.yy454->affExpr = OE_Ignore;
176851177741
}
176852177742
}
176853177743
break;
176854
- case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
177744
+ case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */
176855177745
{
176856
- yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
177746
+ yymsp[-5].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy454, 0);
176857177747
if( yymsp[-5].minor.yy454 ) {
176858177748
yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
176859177749
}
176860177750
}
176861177751
break;
@@ -202282,11 +203172,11 @@
202282203172
}else{
202283203173
iScore += 1000;
202284203174
}
202285203175
mCover |= mPhrase;
202286203176
202287
- for(j=0; j<pPhrase->nToken; j++){
203177
+ for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
202288203178
mHighlight |= (mPos>>j);
202289203179
}
202290203180
202291203181
if( 0==(*pCsr & 0x0FE) ) break;
202292203182
fts3GetDeltaPosition(&pCsr, &iCsr);
@@ -208175,17 +209065,10 @@
208175209065
}
208176209066
if( !eErr ) sqlite3_result_int64(ctx, cnt);
208177209067
jsonParseFree(p);
208178209068
}
208179209069
208180
-/* True if the string is all digits */
208181
-static int jsonAllDigits(const char *z, int n){
208182
- int i;
208183
- for(i=0; i<n && sqlite3Isdigit(z[i]); i++){}
208184
- return i==n;
208185
-}
208186
-
208187209070
/* True if the string is all alphanumerics and underscores */
208188209071
static int jsonAllAlphanum(const char *z, int n){
208189209072
int i;
208190209073
for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){}
208191209074
return i==n;
@@ -208244,14 +209127,20 @@
208244209127
** convenience.
208245209128
**
208246209129
** NUMBER ==> $[NUMBER] // PG compatible
208247209130
** LABEL ==> $.LABEL // PG compatible
208248209131
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
209132
+ **
209133
+ ** Updated 2024-05-27: If the NUMBER is negative, then PG counts from
209134
+ ** the right of the array. Hence for negative NUMBER:
209135
+ **
209136
+ ** NUMBER ==> $[#NUMBER] // PG compatible
208249209137
*/
208250209138
jsonStringInit(&jx, ctx);
208251
- if( jsonAllDigits(zPath, nPath) ){
209139
+ if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
208252209140
jsonAppendRawNZ(&jx, "[", 1);
209141
+ if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1);
208253209142
jsonAppendRaw(&jx, zPath, nPath);
208254209143
jsonAppendRawNZ(&jx, "]", 2);
208255209144
}else if( jsonAllAlphanum(zPath, nPath) ){
208256209145
jsonAppendRawNZ(&jx, ".", 1);
208257209146
jsonAppendRaw(&jx, zPath, nPath);
@@ -216631,11 +217520,11 @@
216631217520
const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
216632217521
const char *zName; /* SQL Collation sequence name (eg. "japanese") */
216633217522
UCollator *pUCollator; /* ICU library collation object */
216634217523
int rc; /* Return code from sqlite3_create_collation_x() */
216635217524
216636
- assert(nArg==2);
217525
+ assert(nArg==2 || nArg==3);
216637217526
(void)nArg; /* Unused parameter */
216638217527
zLocale = (const char *)sqlite3_value_text(apArg[0]);
216639217528
zName = (const char *)sqlite3_value_text(apArg[1]);
216640217529
216641217530
if( !zLocale || !zName ){
@@ -216646,11 +217535,43 @@
216646217535
if( !U_SUCCESS(status) ){
216647217536
icuFunctionError(p, "ucol_open", status);
216648217537
return;
216649217538
}
216650217539
assert(p);
216651
-
217540
+ if(nArg==3){
217541
+ const char *zOption = (const char*)sqlite3_value_text(apArg[2]);
217542
+ static const struct {
217543
+ const char *zName;
217544
+ UColAttributeValue val;
217545
+ } aStrength[] = {
217546
+ { "PRIMARY", UCOL_PRIMARY },
217547
+ { "SECONDARY", UCOL_SECONDARY },
217548
+ { "TERTIARY", UCOL_TERTIARY },
217549
+ { "DEFAULT", UCOL_DEFAULT_STRENGTH },
217550
+ { "QUARTERNARY", UCOL_QUATERNARY },
217551
+ { "IDENTICAL", UCOL_IDENTICAL },
217552
+ };
217553
+ unsigned int i;
217554
+ for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
217555
+ if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
217556
+ ucol_setStrength(pUCollator, aStrength[i].val);
217557
+ break;
217558
+ }
217559
+ }
217560
+ if( i>=sizeof(aStrength)/sizeof(aStrength[0]) ){
217561
+ sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p));
217562
+ sqlite3_str_appendf(pStr,
217563
+ "unknown collation strength \"%s\" - should be one of:",
217564
+ zOption);
217565
+ for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
217566
+ sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
217567
+ }
217568
+ sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
217569
+ sqlite3_free(sqlite3_str_finish(pStr));
217570
+ return;
217571
+ }
217572
+ }
216652217573
rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
216653217574
icuCollationColl, icuCollationDel
216654217575
);
216655217576
if( rc!=SQLITE_OK ){
216656217577
ucol_close(pUCollator);
@@ -216669,10 +217590,11 @@
216669217590
unsigned int enc; /* Optimal text encoding */
216670217591
unsigned char iContext; /* sqlite3_user_data() context */
216671217592
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
216672217593
} scalars[] = {
216673217594
{"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
217595
+ {"icu_load_collation",3,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
216674217596
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
216675217597
{"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
216676217598
{"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
216677217599
{"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
216678217600
{"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
@@ -228072,18 +228994,18 @@
228072228994
** sufficient either for the 'T' or 'P' byte and the varint that follows
228073228995
** it, or for the two single byte values otherwise. */
228074228996
p->rc = sessionInputBuffer(&p->in, 2);
228075228997
if( p->rc!=SQLITE_OK ) return p->rc;
228076228998
228999
+ sessionDiscardData(&p->in);
229000
+ p->in.iCurrent = p->in.iNext;
229001
+
228077229002
/* If the iterator is already at the end of the changeset, return DONE. */
228078229003
if( p->in.iNext>=p->in.nData ){
228079229004
return SQLITE_DONE;
228080229005
}
228081229006
228082
- sessionDiscardData(&p->in);
228083
- p->in.iCurrent = p->in.iNext;
228084
-
228085229007
op = p->in.aData[p->in.iNext++];
228086229008
while( op=='T' || op=='P' ){
228087229009
if( pbNew ) *pbNew = 1;
228088229010
p->bPatchset = (op=='P');
228089229011
if( sessionChangesetReadTblhdr(p) ) return p->rc;
@@ -229814,10 +230736,11 @@
229814230736
*/
229815230737
struct sqlite3_changegroup {
229816230738
int rc; /* Error code */
229817230739
int bPatch; /* True to accumulate patchsets */
229818230740
SessionTable *pList; /* List of tables in current patch */
230741
+ SessionBuffer rec;
229819230742
229820230743
sqlite3 *db; /* Configured by changegroup_schema() */
229821230744
char *zDb; /* Configured by changegroup_schema() */
229822230745
};
229823230746
@@ -230112,112 +231035,132 @@
230112231035
230113231036
return rc;
230114231037
}
230115231038
230116231039
/*
230117
-** Add all changes in the changeset traversed by the iterator passed as
230118
-** the first argument to the changegroup hash tables.
231040
+** Locate or create a SessionTable object that may be used to add the
231041
+** change currently pointed to by iterator pIter to changegroup pGrp.
231042
+** If successful, set output variable (*ppTab) to point to the table
231043
+** object and return SQLITE_OK. Otherwise, if some error occurs, return
231044
+** an SQLite error code and leave (*ppTab) set to NULL.
230119231045
*/
230120
-static int sessionChangesetToHash(
230121
- sqlite3_changeset_iter *pIter, /* Iterator to read from */
230122
- sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
230123
- int bRebase /* True if hash table is for rebasing */
231046
+static int sessionChangesetFindTable(
231047
+ sqlite3_changegroup *pGrp,
231048
+ const char *zTab,
231049
+ sqlite3_changeset_iter *pIter,
231050
+ SessionTable **ppTab
230124231051
){
230125
- u8 *aRec;
230126
- int nRec;
230127231052
int rc = SQLITE_OK;
231053
+ SessionTable *pTab = 0;
231054
+ int nTab = (int)strlen(zTab);
231055
+ u8 *abPK = 0;
231056
+ int nCol = 0;
231057
+
231058
+ *ppTab = 0;
231059
+ sqlite3changeset_pk(pIter, &abPK, &nCol);
231060
+
231061
+ /* Search the list for an existing table */
231062
+ for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
231063
+ if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break;
231064
+ }
231065
+
231066
+ /* If one was not found above, create a new table now */
231067
+ if( !pTab ){
231068
+ SessionTable **ppNew;
231069
+
231070
+ pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nTab+1);
231071
+ if( !pTab ){
231072
+ return SQLITE_NOMEM;
231073
+ }
231074
+ memset(pTab, 0, sizeof(SessionTable));
231075
+ pTab->nCol = nCol;
231076
+ pTab->abPK = (u8*)&pTab[1];
231077
+ memcpy(pTab->abPK, abPK, nCol);
231078
+ pTab->zName = (char*)&pTab->abPK[nCol];
231079
+ memcpy(pTab->zName, zTab, nTab+1);
231080
+
231081
+ if( pGrp->db ){
231082
+ pTab->nCol = 0;
231083
+ rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
231084
+ if( rc ){
231085
+ assert( pTab->azCol==0 );
231086
+ sqlite3_free(pTab);
231087
+ return rc;
231088
+ }
231089
+ }
231090
+
231091
+ /* The new object must be linked on to the end of the list, not
231092
+ ** simply added to the start of it. This is to ensure that the
231093
+ ** tables within the output of sqlite3changegroup_output() are in
231094
+ ** the right order. */
231095
+ for(ppNew=&pGrp->pList; *ppNew; ppNew=&(*ppNew)->pNext);
231096
+ *ppNew = pTab;
231097
+ }
231098
+
231099
+ /* Check that the table is compatible. */
231100
+ if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
231101
+ rc = SQLITE_SCHEMA;
231102
+ }
231103
+
231104
+ *ppTab = pTab;
231105
+ return rc;
231106
+}
231107
+
231108
+/*
231109
+** Add the change currently indicated by iterator pIter to the hash table
231110
+** belonging to changegroup pGrp.
231111
+*/
231112
+static int sessionOneChangeToHash(
231113
+ sqlite3_changegroup *pGrp,
231114
+ sqlite3_changeset_iter *pIter,
231115
+ int bRebase
231116
+){
231117
+ int rc = SQLITE_OK;
231118
+ int nCol = 0;
231119
+ int op = 0;
231120
+ int iHash = 0;
231121
+ int bIndirect = 0;
231122
+ SessionChange *pChange = 0;
231123
+ SessionChange *pExist = 0;
231124
+ SessionChange **pp = 0;
230128231125
SessionTable *pTab = 0;
230129
- SessionBuffer rec = {0, 0, 0};
230130
-
230131
- while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
230132
- const char *zNew;
230133
- int nCol;
230134
- int op;
230135
- int iHash;
230136
- int bIndirect;
230137
- SessionChange *pChange;
230138
- SessionChange *pExist = 0;
230139
- SessionChange **pp;
230140
-
230141
- /* Ensure that only changesets, or only patchsets, but not a mixture
230142
- ** of both, are being combined. It is an error to try to combine a
230143
- ** changeset and a patchset. */
230144
- if( pGrp->pList==0 ){
230145
- pGrp->bPatch = pIter->bPatchset;
230146
- }else if( pIter->bPatchset!=pGrp->bPatch ){
230147
- rc = SQLITE_ERROR;
230148
- break;
230149
- }
230150
-
230151
- sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect);
230152
- if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){
230153
- /* Search the list for a matching table */
230154
- int nNew = (int)strlen(zNew);
230155
- u8 *abPK;
230156
-
230157
- sqlite3changeset_pk(pIter, &abPK, 0);
230158
- for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
230159
- if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
230160
- }
230161
- if( !pTab ){
230162
- SessionTable **ppTab;
230163
-
230164
- pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
230165
- if( !pTab ){
230166
- rc = SQLITE_NOMEM;
230167
- break;
230168
- }
230169
- memset(pTab, 0, sizeof(SessionTable));
230170
- pTab->nCol = nCol;
230171
- pTab->abPK = (u8*)&pTab[1];
230172
- memcpy(pTab->abPK, abPK, nCol);
230173
- pTab->zName = (char*)&pTab->abPK[nCol];
230174
- memcpy(pTab->zName, zNew, nNew+1);
230175
-
230176
- if( pGrp->db ){
230177
- pTab->nCol = 0;
230178
- rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
230179
- if( rc ){
230180
- assert( pTab->azCol==0 );
230181
- sqlite3_free(pTab);
230182
- break;
230183
- }
230184
- }
230185
-
230186
- /* The new object must be linked on to the end of the list, not
230187
- ** simply added to the start of it. This is to ensure that the
230188
- ** tables within the output of sqlite3changegroup_output() are in
230189
- ** the right order. */
230190
- for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext);
230191
- *ppTab = pTab;
230192
- }
230193
-
230194
- if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
230195
- rc = SQLITE_SCHEMA;
230196
- break;
230197
- }
230198
- }
230199
-
230200
- if( nCol<pTab->nCol ){
230201
- assert( pGrp->db );
230202
- rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, &rec);
230203
- if( rc ) break;
230204
- aRec = rec.aBuf;
230205
- nRec = rec.nBuf;
230206
- }
230207
-
230208
- if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
230209
- rc = SQLITE_NOMEM;
230210
- break;
230211
- }
231126
+ u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
231127
+ int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
231128
+
231129
+ /* Ensure that only changesets, or only patchsets, but not a mixture
231130
+ ** of both, are being combined. It is an error to try to combine a
231131
+ ** changeset and a patchset. */
231132
+ if( pGrp->pList==0 ){
231133
+ pGrp->bPatch = pIter->bPatchset;
231134
+ }else if( pIter->bPatchset!=pGrp->bPatch ){
231135
+ rc = SQLITE_ERROR;
231136
+ }
231137
+
231138
+ if( rc==SQLITE_OK ){
231139
+ const char *zTab = 0;
231140
+ sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
231141
+ rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab);
231142
+ }
231143
+
231144
+ if( rc==SQLITE_OK && nCol<pTab->nCol ){
231145
+ SessionBuffer *pBuf = &pGrp->rec;
231146
+ rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf);
231147
+ aRec = pBuf->aBuf;
231148
+ nRec = pBuf->nBuf;
231149
+ assert( pGrp->db );
231150
+ }
231151
+
231152
+ if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){
231153
+ rc = SQLITE_NOMEM;
231154
+ }
231155
+
231156
+ if( rc==SQLITE_OK ){
231157
+ /* Search for existing entry. If found, remove it from the hash table.
231158
+ ** Code below may link it back in. */
230212231159
iHash = sessionChangeHash(
230213231160
pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
230214231161
);
230215
-
230216
- /* Search for existing entry. If found, remove it from the hash table.
230217
- ** Code below may link it back in.
230218
- */
230219231162
for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
230220231163
int bPkOnly1 = 0;
230221231164
int bPkOnly2 = 0;
230222231165
if( pIter->bPatchset ){
230223231166
bPkOnly1 = (*pp)->op==SQLITE_DELETE;
@@ -230228,23 +231171,45 @@
230228231171
*pp = (*pp)->pNext;
230229231172
pTab->nEntry--;
230230231173
break;
230231231174
}
230232231175
}
231176
+ }
230233231177
231178
+ if( rc==SQLITE_OK ){
230234231179
rc = sessionChangeMerge(pTab, bRebase,
230235231180
pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
230236231181
);
230237
- if( rc ) break;
230238
- if( pChange ){
230239
- pChange->pNext = pTab->apChange[iHash];
230240
- pTab->apChange[iHash] = pChange;
230241
- pTab->nEntry++;
230242
- }
231182
+ }
231183
+ if( rc==SQLITE_OK && pChange ){
231184
+ pChange->pNext = pTab->apChange[iHash];
231185
+ pTab->apChange[iHash] = pChange;
231186
+ pTab->nEntry++;
230243231187
}
230244231188
230245
- sqlite3_free(rec.aBuf);
231189
+ if( rc==SQLITE_OK ) rc = pIter->rc;
231190
+ return rc;
231191
+}
231192
+
231193
+/*
231194
+** Add all changes in the changeset traversed by the iterator passed as
231195
+** the first argument to the changegroup hash tables.
231196
+*/
231197
+static int sessionChangesetToHash(
231198
+ sqlite3_changeset_iter *pIter, /* Iterator to read from */
231199
+ sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
231200
+ int bRebase /* True if hash table is for rebasing */
231201
+){
231202
+ u8 *aRec;
231203
+ int nRec;
231204
+ int rc = SQLITE_OK;
231205
+
231206
+ while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
231207
+ rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
231208
+ if( rc!=SQLITE_OK ) break;
231209
+ }
231210
+
230246231211
if( rc==SQLITE_OK ) rc = pIter->rc;
230247231212
return rc;
230248231213
}
230249231214
230250231215
/*
@@ -230367,10 +231332,27 @@
230367231332
rc = sessionChangesetToHash(pIter, pGrp, 0);
230368231333
}
230369231334
sqlite3changeset_finalize(pIter);
230370231335
return rc;
230371231336
}
231337
+
231338
+/*
231339
+** Add a single change to a changeset-group.
231340
+*/
231341
+SQLITE_API int sqlite3changegroup_add_change(
231342
+ sqlite3_changegroup *pGrp,
231343
+ sqlite3_changeset_iter *pIter
231344
+){
231345
+ if( pIter->in.iCurrent==pIter->in.iNext
231346
+ || pIter->rc!=SQLITE_OK
231347
+ || pIter->bInvert
231348
+ ){
231349
+ /* Iterator does not point to any valid entry or is an INVERT iterator. */
231350
+ return SQLITE_ERROR;
231351
+ }
231352
+ return sessionOneChangeToHash(pGrp, pIter, 0);
231353
+}
230372231354
230373231355
/*
230374231356
** Obtain a buffer containing a changeset representing the concatenation
230375231357
** of all changesets added to the group so far.
230376231358
*/
@@ -230417,10 +231399,11 @@
230417231399
*/
230418231400
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
230419231401
if( pGrp ){
230420231402
sqlite3_free(pGrp->zDb);
230421231403
sessionDeleteTable(0, pGrp->pList);
231404
+ sqlite3_free(pGrp->rec.aBuf);
230422231405
sqlite3_free(pGrp);
230423231406
}
230424231407
}
230425231408
230426231409
/*
@@ -230818,10 +231801,11 @@
230818231801
** Destroy a rebaser object
230819231802
*/
230820231803
SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
230821231804
if( p ){
230822231805
sessionDeleteTable(0, p->grp.pList);
231806
+ sqlite3_free(p->grp.rec.aBuf);
230823231807
sqlite3_free(p);
230824231808
}
230825231809
}
230826231810
230827231811
/*
@@ -230915,12 +231899,12 @@
230915231899
230916231900
/*
230917231901
** EXTENSION API FUNCTIONS
230918231902
**
230919231903
** xUserData(pFts):
230920
-** Return a copy of the context pointer the extension function was
230921
-** registered with.
231904
+** Return a copy of the pUserData pointer passed to the xCreateFunction()
231905
+** API when the extension function was registered.
230922231906
**
230923231907
** xColumnTotalSize(pFts, iCol, pnToken):
230924231908
** If parameter iCol is less than zero, set output variable *pnToken
230925231909
** to the total number of tokens in the FTS5 table. Or, if iCol is
230926231910
** non-negative but less than the number of columns in the table, return
@@ -231097,10 +232081,14 @@
231097232081
** This API can be quite slow if used with an FTS5 table created with the
231098232082
** "detail=none" or "detail=column" option. If the FTS5 table is created
231099232083
** with either "detail=none" or "detail=column" and "content=" option
231100232084
** (i.e. if it is a contentless table), then this API always iterates
231101232085
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
232086
+**
232087
+** In all cases, matches are visited in (column ASC, offset ASC) order.
232088
+** i.e. all those in column 0, sorted by offset, followed by those in
232089
+** column 1, etc.
231102232090
**
231103232091
** xPhraseNext()
231104232092
** See xPhraseFirst above.
231105232093
**
231106232094
** xPhraseFirstColumn()
@@ -231628,10 +232616,19 @@
231628232616
** Interface to code in fts5_config.c. fts5_config.c contains contains code
231629232617
** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
231630232618
*/
231631232619
231632232620
typedef struct Fts5Config Fts5Config;
232621
+typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
232622
+
232623
+struct Fts5TokenizerConfig {
232624
+ Fts5Tokenizer *pTok;
232625
+ fts5_tokenizer *pTokApi;
232626
+ const char **azArg;
232627
+ int nArg;
232628
+ int ePattern; /* FTS_PATTERN_XXX constant */
232629
+};
231633232630
231634232631
/*
231635232632
** An instance of the following structure encodes all information that can
231636232633
** be gleaned from the CREATE VIRTUAL TABLE statement.
231637232634
**
@@ -231670,10 +232667,11 @@
231670232667
** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
231671232668
**
231672232669
*/
231673232670
struct Fts5Config {
231674232671
sqlite3 *db; /* Database handle */
232672
+ Fts5Global *pGlobal; /* Global fts5 object for handle db */
231675232673
char *zDb; /* Database holding FTS index (e.g. "main") */
231676232674
char *zName; /* Name of FTS index */
231677232675
int nCol; /* Number of columns */
231678232676
char **azCol; /* Column names */
231679232677
u8 *abUnindexed; /* True for unindexed columns */
@@ -231685,14 +232683,12 @@
231685232683
char *zContentRowid; /* "content_rowid=" option value */
231686232684
int bColumnsize; /* "columnsize=" option value (dflt==1) */
231687232685
int bTokendata; /* "tokendata=" option value (dflt==0) */
231688232686
int eDetail; /* FTS5_DETAIL_XXX value */
231689232687
char *zContentExprlist;
231690
- Fts5Tokenizer *pTok;
231691
- fts5_tokenizer *pTokApi;
232688
+ Fts5TokenizerConfig t;
231692232689
int bLock; /* True when table is preparing statement */
231693
- int ePattern; /* FTS_PATTERN_XXX constant */
231694232690
231695232691
/* Values loaded from the %_config table */
231696232692
int iVersion; /* fts5 file format 'version' */
231697232693
int iCookie; /* Incremented when %_config is modified */
231698232694
int pgsz; /* Approximate page size used in %_data */
@@ -232083,17 +233079,11 @@
232083233079
sqlite3_vtab base; /* Base class used by SQLite core */
232084233080
Fts5Config *pConfig; /* Virtual table configuration */
232085233081
Fts5Index *pIndex; /* Full-text index */
232086233082
};
232087233083
232088
-static int sqlite3Fts5GetTokenizer(
232089
- Fts5Global*,
232090
- const char **azArg,
232091
- int nArg,
232092
- Fts5Config*,
232093
- char **pzErr
232094
-);
233084
+static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
232095233085
232096233086
static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
232097233087
232098233088
static int sqlite3Fts5FlushToDisk(Fts5Table*);
232099233089
@@ -232352,10 +233342,11 @@
232352233342
static int sqlite3Fts5TokenizerInit(fts5_api*);
232353233343
static int sqlite3Fts5TokenizerPattern(
232354233344
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
232355233345
Fts5Tokenizer *pTok
232356233346
);
233347
+static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
232357233348
/*
232358233349
** End of interface to code in fts5_tokenizer.c.
232359233350
**************************************************************************/
232360233351
232361233352
/**************************************************************************
@@ -235303,11 +236294,10 @@
235303236294
** an error occurs, an SQLite error code is returned and an error message
235304236295
** may be left in *pzErr. It is the responsibility of the caller to
235305236296
** eventually free any such error message using sqlite3_free().
235306236297
*/
235307236298
static int fts5ConfigParseSpecial(
235308
- Fts5Global *pGlobal,
235309236299
Fts5Config *pConfig, /* Configuration object to update */
235310236300
const char *zCmd, /* Special command to parse */
235311236301
const char *zArg, /* Argument to parse */
235312236302
char **pzErr /* OUT: Error message */
235313236303
){
@@ -235367,16 +236357,15 @@
235367236357
}
235368236358
235369236359
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
235370236360
const char *p = (const char*)zArg;
235371236361
sqlite3_int64 nArg = strlen(zArg) + 1;
235372
- char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
235373
- char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
235374
- char *pSpace = pDel;
236362
+ char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
235375236363
235376
- if( azArg && pSpace ){
235377
- if( pConfig->pTok ){
236364
+ if( azArg ){
236365
+ char *pSpace = (char*)&azArg[nArg];
236366
+ if( pConfig->t.azArg ){
235378236367
*pzErr = sqlite3_mprintf("multiple tokenize=... directives");
235379236368
rc = SQLITE_ERROR;
235380236369
}else{
235381236370
for(nArg=0; p && *p; nArg++){
235382236371
const char *p2 = fts5ConfigSkipWhitespace(p);
@@ -235395,20 +236384,18 @@
235395236384
}
235396236385
if( p==0 ){
235397236386
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
235398236387
rc = SQLITE_ERROR;
235399236388
}else{
235400
- rc = sqlite3Fts5GetTokenizer(pGlobal,
235401
- (const char**)azArg, (int)nArg, pConfig,
235402
- pzErr
235403
- );
236389
+ pConfig->t.azArg = (const char**)azArg;
236390
+ pConfig->t.nArg = nArg;
236391
+ azArg = 0;
235404236392
}
235405236393
}
235406236394
}
235407
-
235408236395
sqlite3_free(azArg);
235409
- sqlite3_free(pDel);
236396
+
235410236397
return rc;
235411236398
}
235412236399
235413236400
if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
235414236401
if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
@@ -235481,20 +236468,10 @@
235481236468
235482236469
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
235483236470
return SQLITE_ERROR;
235484236471
}
235485236472
235486
-/*
235487
-** Allocate an instance of the default tokenizer ("simple") at
235488
-** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
235489
-** code if an error occurs.
235490
-*/
235491
-static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
235492
- assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
235493
- return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
235494
-}
235495
-
235496236473
/*
235497236474
** Gobble up the first bareword or quoted word from the input buffer zIn.
235498236475
** Return a pointer to the character immediately following the last in
235499236476
** the gobbled word if successful, or a NULL pointer otherwise (failed
235500236477
** to find close-quote character).
@@ -235623,10 +236600,11 @@
235623236600
sqlite3_int64 nByte;
235624236601
235625236602
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
235626236603
if( pRet==0 ) return SQLITE_NOMEM;
235627236604
memset(pRet, 0, sizeof(Fts5Config));
236605
+ pRet->pGlobal = pGlobal;
235628236606
pRet->db = db;
235629236607
pRet->iCookie = -1;
235630236608
235631236609
nByte = nArg * (sizeof(char*) + sizeof(u8));
235632236610
pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -235671,11 +236649,11 @@
235671236649
if( z==0 ){
235672236650
*pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
235673236651
rc = SQLITE_ERROR;
235674236652
}else{
235675236653
if( bOption ){
235676
- rc = fts5ConfigParseSpecial(pGlobal, pRet,
236654
+ rc = fts5ConfigParseSpecial(pRet,
235677236655
ALWAYS(zOne)?zOne:"",
235678236656
zTwo?zTwo:"",
235679236657
pzErr
235680236658
);
235681236659
}else{
@@ -235709,17 +236687,10 @@
235709236687
"contentless_delete=1 is incompatible with columnsize=0"
235710236688
);
235711236689
rc = SQLITE_ERROR;
235712236690
}
235713236691
235714
- /* If a tokenizer= option was successfully parsed, the tokenizer has
235715
- ** already been allocated. Otherwise, allocate an instance of the default
235716
- ** tokenizer (unicode61) now. */
235717
- if( rc==SQLITE_OK && pRet->pTok==0 ){
235718
- rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
235719
- }
235720
-
235721236692
/* If no zContent option was specified, fill in the default values. */
235722236693
if( rc==SQLITE_OK && pRet->zContent==0 ){
235723236694
const char *zTail = 0;
235724236695
assert( pRet->eContent==FTS5_CONTENT_NORMAL
235725236696
|| pRet->eContent==FTS5_CONTENT_NONE
@@ -235757,13 +236728,14 @@
235757236728
** Free the configuration object passed as the only argument.
235758236729
*/
235759236730
static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
235760236731
if( pConfig ){
235761236732
int i;
235762
- if( pConfig->pTok ){
235763
- pConfig->pTokApi->xDelete(pConfig->pTok);
236733
+ if( pConfig->t.pTok ){
236734
+ pConfig->t.pTokApi->xDelete(pConfig->t.pTok);
235764236735
}
236736
+ sqlite3_free((char*)pConfig->t.azArg);
235765236737
sqlite3_free(pConfig->zDb);
235766236738
sqlite3_free(pConfig->zName);
235767236739
for(i=0; i<pConfig->nCol; i++){
235768236740
sqlite3_free(pConfig->azCol[i]);
235769236741
}
@@ -235834,14 +236806,22 @@
235834236806
int flags, /* FTS5_TOKENIZE_* flags */
235835236807
const char *pText, int nText, /* Text to tokenize */
235836236808
void *pCtx, /* Context passed to xToken() */
235837236809
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
235838236810
){
235839
- if( pText==0 ) return SQLITE_OK;
235840
- return pConfig->pTokApi->xTokenize(
235841
- pConfig->pTok, pCtx, flags, pText, nText, xToken
235842
- );
236811
+ int rc = SQLITE_OK;
236812
+ if( pText ){
236813
+ if( pConfig->t.pTok==0 ){
236814
+ rc = sqlite3Fts5LoadTokenizer(pConfig);
236815
+ }
236816
+ if( rc==SQLITE_OK ){
236817
+ rc = pConfig->t.pTokApi->xTokenize(
236818
+ pConfig->t.pTok, pCtx, flags, pText, nText, xToken
236819
+ );
236820
+ }
236821
+ }
236822
+ return rc;
235843236823
}
235844236824
235845236825
/*
235846236826
** Argument pIn points to the first character in what is expected to be
235847236827
** a comma-separated list of SQL literals followed by a ')' character.
@@ -236434,11 +237414,15 @@
236434237414
}else{
236435237415
sqlite3Fts5ParseNodeFree(sParse.pExpr);
236436237416
}
236437237417
236438237418
sqlite3_free(sParse.apPhrase);
236439
- *pzErr = sParse.zErr;
237419
+ if( 0==*pzErr ){
237420
+ *pzErr = sParse.zErr;
237421
+ }else{
237422
+ sqlite3_free(sParse.zErr);
237423
+ }
236440237424
return sParse.rc;
236441237425
}
236442237426
236443237427
/*
236444237428
** Assuming that buffer z is at least nByte bytes in size and contains a
@@ -237981,10 +238965,11 @@
237981238965
** no token characters at all. (e.g ... MATCH '""'). */
237982238966
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
237983238967
}else if( sCtx.pPhrase->nTerm ){
237984238968
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
237985238969
}
238970
+ assert( pParse->apPhrase!=0 );
237986238971
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
237987238972
}
237988238973
237989238974
return sCtx.pPhrase;
237990238975
}
@@ -238000,11 +238985,11 @@
238000238985
){
238001238986
int rc = SQLITE_OK; /* Return code */
238002238987
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
238003238988
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
238004238989
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
238005
- if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
238990
+ if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
238006238991
rc = SQLITE_RANGE;
238007238992
}else{
238008238993
pOrig = pExpr->apExprPhrase[iPhrase];
238009238994
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
238010238995
}
@@ -238575,10 +239560,12 @@
238575239560
|| pPrev->eType==FTS5_TERM
238576239561
|| pPrev->eType==FTS5_EOF
238577239562
);
238578239563
238579239564
if( pRight->eType==FTS5_EOF ){
239565
+ assert( pParse->apPhrase!=0 );
239566
+ assert( pParse->nPhrase>0 );
238580239567
assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
238581239568
sqlite3Fts5ParseNodeFree(pRight);
238582239569
pRet = pLeft;
238583239570
pParse->nPhrase--;
238584239571
}
@@ -249406,12 +250393,16 @@
249406250393
if( rc==SQLITE_OK ){
249407250394
rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
249408250395
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
249409250396
}
249410250397
if( rc==SQLITE_OK ){
250398
+ pConfig->pzErrmsg = pzErr;
249411250399
pTab->p.pConfig = pConfig;
249412250400
pTab->pGlobal = pGlobal;
250401
+ if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
250402
+ rc = sqlite3Fts5LoadTokenizer(pConfig);
250403
+ }
249413250404
}
249414250405
249415250406
/* Open the index sub-system */
249416250407
if( rc==SQLITE_OK ){
249417250408
rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
@@ -249429,24 +250420,22 @@
249429250420
rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
249430250421
}
249431250422
249432250423
/* Load the initial configuration */
249433250424
if( rc==SQLITE_OK ){
249434
- assert( pConfig->pzErrmsg==0 );
249435
- pConfig->pzErrmsg = pzErr;
249436250425
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
249437250426
sqlite3Fts5IndexRollback(pTab->p.pIndex);
249438
- pConfig->pzErrmsg = 0;
249439250427
}
249440250428
249441250429
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
249442250430
rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1);
249443250431
}
249444250432
if( rc==SQLITE_OK ){
249445250433
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
249446250434
}
249447250435
250436
+ if( pConfig ) pConfig->pzErrmsg = 0;
249448250437
if( rc!=SQLITE_OK ){
249449250438
fts5FreeVtab(pTab);
249450250439
pTab = 0;
249451250440
}else if( bCreate ){
249452250441
fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
@@ -249510,14 +250499,14 @@
249510250499
Fts5Config *pConfig,
249511250500
struct sqlite3_index_constraint *p
249512250501
){
249513250502
assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
249514250503
assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
249515
- if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
250504
+ if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
249516250505
return 1;
249517250506
}
249518
- if( pConfig->ePattern==FTS5_PATTERN_LIKE
250507
+ if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
249519250508
&& (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
249520250509
){
249521250510
return 1;
249522250511
}
249523250512
return 0;
@@ -249560,15 +250549,15 @@
249560250549
** A > or >= against the rowid: ">"
249561250550
**
249562250551
** This function ensures that there is at most one "r" or "=". And that if
249563250552
** there exists an "=" then there is no "<" or ">".
249564250553
**
250554
+** If an unusable MATCH operator is present in the WHERE clause, then
250555
+** SQLITE_CONSTRAINT is returned.
250556
+**
249565250557
** Costs are assigned as follows:
249566250558
**
249567
-** a) If an unusable MATCH operator is present in the WHERE clause, the
249568
-** cost is unconditionally set to 1e50 (a really big number).
249569
-**
249570250559
** a) If a MATCH operator is present, the cost depends on the other
249571250560
** constraints also present. As follows:
249572250561
**
249573250562
** * No other constraints: cost=1000.0
249574250563
** * One rowid range constraint: cost=750.0
@@ -249596,11 +250585,11 @@
249596250585
int iCons = 0;
249597250586
249598250587
int bSeenEq = 0;
249599250588
int bSeenGt = 0;
249600250589
int bSeenLt = 0;
249601
- int bSeenMatch = 0;
250590
+ int nSeenMatch = 0;
249602250591
int bSeenRank = 0;
249603250592
249604250593
249605250594
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
249606250595
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
@@ -249627,22 +250616,19 @@
249627250616
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
249628250617
){
249629250618
/* A MATCH operator or equivalent */
249630250619
if( p->usable==0 || iCol<0 ){
249631250620
/* As there exists an unusable MATCH constraint this is an
249632
- ** unusable plan. Set a prohibitively high cost. */
249633
- pInfo->estimatedCost = 1e50;
249634
- assert( iIdxStr < pInfo->nConstraint*6 + 1 );
249635
- idxStr[iIdxStr] = 0;
249636
- return SQLITE_OK;
250621
+ ** unusable plan. Return SQLITE_CONSTRAINT. */
250622
+ return SQLITE_CONSTRAINT;
249637250623
}else{
249638250624
if( iCol==nCol+1 ){
249639250625
if( bSeenRank ) continue;
249640250626
idxStr[iIdxStr++] = 'r';
249641250627
bSeenRank = 1;
249642250628
}else if( iCol>=0 ){
249643
- bSeenMatch = 1;
250629
+ nSeenMatch++;
249644250630
idxStr[iIdxStr++] = 'M';
249645250631
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
249646250632
idxStr += strlen(&idxStr[iIdxStr]);
249647250633
assert( idxStr[iIdxStr]=='\0' );
249648250634
}
@@ -249655,10 +250641,11 @@
249655250641
idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
249656250642
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
249657250643
idxStr += strlen(&idxStr[iIdxStr]);
249658250644
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
249659250645
assert( idxStr[iIdxStr]=='\0' );
250646
+ nSeenMatch++;
249660250647
}else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
249661250648
idxStr[iIdxStr++] = '=';
249662250649
bSeenEq = 1;
249663250650
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
249664250651
}
@@ -249691,11 +250678,11 @@
249691250678
**
249692250679
** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
249693250680
*/
249694250681
if( pInfo->nOrderBy==1 ){
249695250682
int iSort = pInfo->aOrderBy[0].iColumn;
249696
- if( iSort==(pConfig->nCol+1) && bSeenMatch ){
250683
+ if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
249697250684
idxFlags |= FTS5_BI_ORDER_RANK;
249698250685
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
249699250686
idxFlags |= FTS5_BI_ORDER_ROWID;
249700250687
}
249701250688
if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
@@ -249706,18 +250693,21 @@
249706250693
}
249707250694
}
249708250695
249709250696
/* Calculate the estimated cost based on the flags set in idxFlags. */
249710250697
if( bSeenEq ){
249711
- pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
249712
- if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
250698
+ pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
250699
+ if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
249713250700
}else if( bSeenLt && bSeenGt ){
249714
- pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
250701
+ pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
249715250702
}else if( bSeenLt || bSeenGt ){
249716
- pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
250703
+ pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
249717250704
}else{
249718
- pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
250705
+ pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
250706
+ }
250707
+ for(i=1; i<nSeenMatch; i++){
250708
+ pInfo->estimatedCost *= 0.4;
249719250709
}
249720250710
249721250711
pInfo->idxNum = idxFlags;
249722250712
return SQLITE_OK;
249723250713
}
@@ -249989,10 +250979,11 @@
249989250979
"%s", sqlite3_errmsg(pConfig->db)
249990250980
);
249991250981
}
249992250982
}else{
249993250983
rc = SQLITE_OK;
250984
+ CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
249994250985
}
249995250986
break;
249996250987
}
249997250988
}
249998250989
}
@@ -250462,13 +251453,17 @@
250462251453
*/
250463251454
static i64 fts5CursorRowid(Fts5Cursor *pCsr){
250464251455
assert( pCsr->ePlan==FTS5_PLAN_MATCH
250465251456
|| pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
250466251457
|| pCsr->ePlan==FTS5_PLAN_SOURCE
251458
+ || pCsr->ePlan==FTS5_PLAN_SCAN
251459
+ || pCsr->ePlan==FTS5_PLAN_ROWID
250467251460
);
250468251461
if( pCsr->pSorter ){
250469251462
return pCsr->pSorter->iRowid;
251463
+ }else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
251464
+ return sqlite3_column_int64(pCsr->pStmt, 0);
250470251465
}else{
250471251466
return sqlite3Fts5ExprRowid(pCsr->pExpr);
250472251467
}
250473251468
}
250474251469
@@ -250481,24 +251476,14 @@
250481251476
static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
250482251477
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
250483251478
int ePlan = pCsr->ePlan;
250484251479
250485251480
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
250486
- switch( ePlan ){
250487
- case FTS5_PLAN_SPECIAL:
250488
- *pRowid = 0;
250489
- break;
250490
-
250491
- case FTS5_PLAN_SOURCE:
250492
- case FTS5_PLAN_MATCH:
250493
- case FTS5_PLAN_SORTED_MATCH:
250494
- *pRowid = fts5CursorRowid(pCsr);
250495
- break;
250496
-
250497
- default:
250498
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
250499
- break;
251481
+ if( ePlan==FTS5_PLAN_SPECIAL ){
251482
+ *pRowid = 0;
251483
+ }else{
251484
+ *pRowid = fts5CursorRowid(pCsr);
250500251485
}
250501251486
250502251487
return SQLITE_OK;
250503251488
}
250504251489
@@ -250729,10 +251714,11 @@
250729251714
"'delete' may not be used with a contentless_delete=1 table"
250730251715
);
250731251716
rc = SQLITE_ERROR;
250732251717
}else{
250733251718
rc = fts5SpecialDelete(pTab, apVal);
251719
+ bUpdateOrDelete = 1;
250734251720
}
250735251721
}else{
250736251722
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
250737251723
}
250738251724
}else{
@@ -251889,11 +252875,11 @@
251889252875
}
251890252876
251891252877
return rc;
251892252878
}
251893252879
251894
-static int sqlite3Fts5GetTokenizer(
252880
+int fts5GetTokenizer(
251895252881
Fts5Global *pGlobal,
251896252882
const char **azArg,
251897252883
int nArg,
251898252884
Fts5Config *pConfig,
251899252885
char **pzErr
@@ -251903,32 +252889,45 @@
251903252889
251904252890
pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
251905252891
if( pMod==0 ){
251906252892
assert( nArg>0 );
251907252893
rc = SQLITE_ERROR;
251908
- *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
252894
+ if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
251909252895
}else{
251910252896
rc = pMod->x.xCreate(
251911
- pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
252897
+ pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
251912252898
);
251913
- pConfig->pTokApi = &pMod->x;
252899
+ pConfig->t.pTokApi = &pMod->x;
251914252900
if( rc!=SQLITE_OK ){
251915
- if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
252901
+ if( pzErr && rc!=SQLITE_NOMEM ){
252902
+ *pzErr = sqlite3_mprintf("error in tokenizer constructor");
252903
+ }
251916252904
}else{
251917
- pConfig->ePattern = sqlite3Fts5TokenizerPattern(
251918
- pMod->x.xCreate, pConfig->pTok
252905
+ pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
252906
+ pMod->x.xCreate, pConfig->t.pTok
251919252907
);
251920252908
}
251921252909
}
251922252910
251923252911
if( rc!=SQLITE_OK ){
251924
- pConfig->pTokApi = 0;
251925
- pConfig->pTok = 0;
252912
+ pConfig->t.pTokApi = 0;
252913
+ pConfig->t.pTok = 0;
251926252914
}
251927252915
251928252916
return rc;
251929252917
}
252918
+
252919
+/*
252920
+** Attempt to instantiate the tokenizer.
252921
+*/
252922
+static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
252923
+ return fts5GetTokenizer(
252924
+ pConfig->pGlobal, pConfig->t.azArg, pConfig->t.nArg,
252925
+ pConfig, pConfig->pzErrmsg
252926
+ );
252927
+}
252928
+
251930252929
251931252930
static void fts5ModuleDestroy(void *pCtx){
251932252931
Fts5TokenizerModule *pTok, *pNextTok;
251933252932
Fts5Auxiliary *pAux, *pNextAux;
251934252933
Fts5Global *pGlobal = (Fts5Global*)pCtx;
@@ -251969,11 +252968,11 @@
251969252968
int nArg, /* Number of args */
251970252969
sqlite3_value **apUnused /* Function arguments */
251971252970
){
251972252971
assert( nArg==0 );
251973252972
UNUSED_PARAM2(nArg, apUnused);
251974
- sqlite3_result_text(pCtx, "fts5: 2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3", -1, SQLITE_TRANSIENT);
252973
+ sqlite3_result_text(pCtx, "fts5: 2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38", -1, SQLITE_TRANSIENT);
251975252974
}
251976252975
251977252976
/*
251978252977
** Return true if zName is the extension on one of the shadow tables used
251979252978
** by this module.
@@ -252004,21 +253003,27 @@
252004253003
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
252005253004
int rc;
252006253005
252007253006
assert( pzErr!=0 && *pzErr==0 );
252008253007
UNUSED_PARAM(isQuick);
253008
+ assert( pTab->p.pConfig->pzErrmsg==0 );
253009
+ pTab->p.pConfig->pzErrmsg = pzErr;
252009253010
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
252010
- if( (rc&0xff)==SQLITE_CORRUPT ){
252011
- *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
252012
- zSchema, zTabname);
252013
- rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
252014
- }else if( rc!=SQLITE_OK ){
252015
- *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
252016
- " FTS5 table %s.%s: %s",
252017
- zSchema, zTabname, sqlite3_errstr(rc));
252018
- }
253011
+ if( *pzErr==0 && rc!=SQLITE_OK ){
253012
+ if( (rc&0xff)==SQLITE_CORRUPT ){
253013
+ *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
253014
+ zSchema, zTabname);
253015
+ rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
253016
+ }else{
253017
+ *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
253018
+ " FTS5 table %s.%s: %s",
253019
+ zSchema, zTabname, sqlite3_errstr(rc));
253020
+ }
253021
+ }
253022
+
252019253023
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
253024
+ pTab->p.pConfig->pzErrmsg = 0;
252020253025
252021253026
return rc;
252022253027
}
252023253028
252024253029
static int fts5Init(sqlite3 *db){
@@ -254796,10 +255801,20 @@
254796255801
return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
254797255802
}
254798255803
}
254799255804
return FTS5_PATTERN_NONE;
254800255805
}
255806
+
255807
+/*
255808
+** Return true if the tokenizer described by p->azArg[] is the trigram
255809
+** tokenizer. This tokenizer needs to be loaded before xBestIndex is
255810
+** called for the first time in order to correctly handle LIKE/GLOB.
255811
+*/
255812
+static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
255813
+ return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
255814
+}
255815
+
254801255816
254802255817
/*
254803255818
** Register all built-in tokenizers with FTS5.
254804255819
*/
254805255820
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -256016,10 +257031,11 @@
256016257031
Fts5IndexIter *pIter; /* Term/rowid iterator object */
256017257032
void *pStruct; /* From sqlite3Fts5StructureRef() */
256018257033
256019257034
int nLeTerm; /* Size of zLeTerm in bytes */
256020257035
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
257036
+ int colUsed; /* Copy of sqlite3_index_info.colUsed */
256021257037
256022257038
/* These are used by 'col' tables only */
256023257039
int iCol;
256024257040
i64 *aCnt;
256025257041
i64 *aDoc;
@@ -256042,13 +257058,15 @@
256042257058
#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
256043257059
256044257060
/*
256045257061
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
256046257062
*/
256047
-#define FTS5_VOCAB_TERM_EQ 0x01
256048
-#define FTS5_VOCAB_TERM_GE 0x02
256049
-#define FTS5_VOCAB_TERM_LE 0x04
257063
+#define FTS5_VOCAB_TERM_EQ 0x0100
257064
+#define FTS5_VOCAB_TERM_GE 0x0200
257065
+#define FTS5_VOCAB_TERM_LE 0x0400
257066
+
257067
+#define FTS5_VOCAB_COLUSED_MASK 0xFF
256050257068
256051257069
256052257070
/*
256053257071
** Translate a string containing an fts5vocab table type to an
256054257072
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
@@ -256221,14 +257239,16 @@
256221257239
){
256222257240
int i;
256223257241
int iTermEq = -1;
256224257242
int iTermGe = -1;
256225257243
int iTermLe = -1;
256226
- int idxNum = 0;
257244
+ int idxNum = (int)pInfo->colUsed;
256227257245
int nArg = 0;
256228257246
256229257247
UNUSED_PARAM(pUnused);
257248
+
257249
+ assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
256230257250
256231257251
for(i=0; i<pInfo->nConstraint; i++){
256232257252
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
256233257253
if( p->usable==0 ) continue;
256234257254
if( p->iColumn==0 ){ /* term column */
@@ -256317,11 +257337,11 @@
256317257337
rc = sqlite3_finalize(pStmt);
256318257338
pStmt = 0;
256319257339
if( rc==SQLITE_OK ){
256320257340
pVTab->zErrMsg = sqlite3_mprintf(
256321257341
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
256322
- );
257342
+ );
256323257343
rc = SQLITE_ERROR;
256324257344
}
256325257345
}else{
256326257346
rc = sqlite3Fts5FlushToDisk(pFts5);
256327257347
}
@@ -256477,13 +257497,23 @@
256477257497
pPos = pCsr->pIter->pData;
256478257498
nPos = pCsr->pIter->nData;
256479257499
256480257500
switch( pTab->eType ){
256481257501
case FTS5_VOCAB_ROW:
256482
- if( eDetail==FTS5_DETAIL_FULL ){
256483
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
256484
- pCsr->aCnt[0]++;
257502
+ /* Do not bother counting the number of instances if the "cnt"
257503
+ ** column is not being read (according to colUsed). */
257504
+ if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
257505
+ while( iPos<nPos ){
257506
+ u32 ii;
257507
+ fts5FastGetVarint32(pPos, iPos, ii);
257508
+ if( ii==1 ){
257509
+ /* New column in the position list */
257510
+ fts5FastGetVarint32(pPos, iPos, ii);
257511
+ }else{
257512
+ /* An instance - increment pCsr->aCnt[] */
257513
+ pCsr->aCnt[0]++;
257514
+ }
256485257515
}
256486257516
}
256487257517
pCsr->aDoc[0]++;
256488257518
break;
256489257519
@@ -256577,10 +257607,11 @@
256577257607
256578257608
fts5VocabResetCursor(pCsr);
256579257609
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
256580257610
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
256581257611
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
257612
+ pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
256582257613
256583257614
if( pEq ){
256584257615
zTerm = (const char *)sqlite3_value_text(pEq);
256585257616
nTerm = sqlite3_value_bytes(pEq);
256586257617
f = FTS5INDEX_QUERY_NOTOKENDATA;
256587257618
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.46.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** a49296de0061931badaf3db6b965131a78b1.
22 */
23 #define SQLITE_CORE 1
24 #define SQLITE_AMALGAMATION 1
25 #ifndef SQLITE_PRIVATE
26 # define SQLITE_PRIVATE static
@@ -254,14 +254,17 @@
254 #endif
255
256 /*
257 ** Macro to disable warnings about missing "break" at the end of a "case".
258 */
259 #if GCC_VERSION>=7000000
260 # define deliberate_fall_through __attribute__((fallthrough));
261 #else
262 # define deliberate_fall_through
 
 
 
263 #endif
264
265 /*
266 ** For MinGW, check to see if we can include the header file containing its
267 ** version information, among other things. Normally, this internal MinGW
@@ -457,13 +460,13 @@
457 **
458 ** See also: [sqlite3_libversion()],
459 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
460 ** [sqlite_version()] and [sqlite_source_id()].
461 */
462 #define SQLITE_VERSION "3.46.0"
463 #define SQLITE_VERSION_NUMBER 3046000
464 #define SQLITE_SOURCE_ID "2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3"
465
466 /*
467 ** CAPI3REF: Run-Time Library Version Numbers
468 ** KEYWORDS: sqlite3_version sqlite3_sourceid
469 **
@@ -1083,12 +1086,12 @@
1083 ** xUnlock() downgrades the database file lock to either SHARED or NONE.
1084 ** If the lock is already at or below the requested lock state, then the call
1085 ** to xUnlock() is a no-op.
1086 ** The xCheckReservedLock() method checks whether any database connection,
1087 ** either in this process or in some other process, is holding a RESERVED,
1088 ** PENDING, or EXCLUSIVE lock on the file. It returns true
1089 ** if such a lock exists and false otherwise.
1090 **
1091 ** The xFileControl() method is a generic interface that allows custom
1092 ** VFS implementations to directly control an open file using the
1093 ** [sqlite3_file_control()] interface. The second "op" argument is an
1094 ** integer opcode. The third argument is a generic pointer intended to
@@ -3881,12 +3884,12 @@
3881 ** the default shared cache setting provided by
3882 ** [sqlite3_enable_shared_cache()].)^
3883 **
3884 ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
3885 ** <dd>The database connection comes up in "extended result code mode".
3886 ** In other words, the database behaves has if
3887 ** [sqlite3_extended_result_codes(db,1)] where called on the database
3888 ** connection as soon as the connection is created. In addition to setting
3889 ** the extended result code mode, this flag also causes [sqlite3_open_v2()]
3890 ** to return an extended result code.</dd>
3891 **
3892 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -7197,10 +7200,16 @@
7197 ** is not invoked when conflicting rows are deleted because of an
7198 ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
7199 ** invoked when rows are deleted using the [truncate optimization].
7200 ** The exceptions defined in this paragraph might change in a future
7201 ** release of SQLite.
 
 
 
 
 
 
7202 **
7203 ** The update hook implementation must not do anything that will modify
7204 ** the database connection that invoked the update hook. Any actions
7205 ** to modify the database connection must be deferred until after the
7206 ** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8668,11 +8677,11 @@
8668 ** by enclosing in double-quotes) so as not to confuse the parser.
8669 **
8670 ** The sqlite3_keyword_count() interface returns the number of distinct
8671 ** keywords understood by SQLite.
8672 **
8673 ** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
8674 ** makes *Z point to that keyword expressed as UTF8 and writes the number
8675 ** of bytes in the keyword into *L. The string that *Z points to is not
8676 ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
8677 ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
8678 ** or L are NULL or invalid pointers then calls to
@@ -10247,27 +10256,48 @@
10247 ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
10248 ** is doing a GROUP BY.
10249 ** <li value="2"><p>
10250 ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
10251 ** that the query planner does not need the rows returned in any particular
10252 ** order, as long as rows with the same values in all "aOrderBy" columns
10253 ** are adjacent.)^ ^(Furthermore, only a single row for each particular
10254 ** combination of values in the columns identified by the "aOrderBy" field
10255 ** needs to be returned.)^ ^It is always ok for two or more rows with the same
10256 ** values in all "aOrderBy" columns to be returned, as long as all such rows
10257 ** are adjacent. ^The virtual table may, if it chooses, omit extra rows
10258 ** that have the same value for all columns identified by "aOrderBy".
10259 ** ^However omitting the extra rows is optional.
10260 ** This mode is used for a DISTINCT query.
10261 ** <li value="3"><p>
10262 ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
10263 ** that the query planner needs only distinct rows but it does need the
10264 ** rows to be sorted.)^ ^The virtual table implementation is free to omit
10265 ** rows that are identical in all aOrderBy columns, if it wants to, but
10266 ** it is not required to omit any rows. This mode is used for queries
 
 
 
 
 
10267 ** that have both DISTINCT and ORDER BY clauses.
10268 ** </ol>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10269 **
10270 ** ^For the purposes of comparing virtual table output values to see if the
10271 ** values are same value for sorting purposes, two NULL values are considered
10272 ** to be the same. In other words, the comparison operator is "IS"
10273 ** (or "IS NOT DISTINCT FROM") and not "==".
@@ -11116,12 +11146,10 @@
11116 #endif
11117
11118 #if defined(__wasi__)
11119 # undef SQLITE_WASI
11120 # define SQLITE_WASI 1
11121 # undef SQLITE_OMIT_WAL
11122 # define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
11123 # ifndef SQLITE_OMIT_LOAD_EXTENSION
11124 # define SQLITE_OMIT_LOAD_EXTENSION
11125 # endif
11126 # ifndef SQLITE_THREADSAFE
11127 # define SQLITE_THREADSAFE 0
@@ -12308,10 +12336,34 @@
12308 **
12309 ** In all cases, if an error occurs the state of the final contents of the
12310 ** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
12311 */
12312 SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12313
12314 /*
12315 ** CAPI3REF: Obtain A Composite Changeset From A Changegroup
12316 ** METHOD: sqlite3_changegroup
12317 **
@@ -13113,12 +13165,12 @@
13113
13114 /*
13115 ** EXTENSION API FUNCTIONS
13116 **
13117 ** xUserData(pFts):
13118 ** Return a copy of the context pointer the extension function was
13119 ** registered with.
13120 **
13121 ** xColumnTotalSize(pFts, iCol, pnToken):
13122 ** If parameter iCol is less than zero, set output variable *pnToken
13123 ** to the total number of tokens in the FTS5 table. Or, if iCol is
13124 ** non-negative but less than the number of columns in the table, return
@@ -13295,10 +13347,14 @@
13295 ** This API can be quite slow if used with an FTS5 table created with the
13296 ** "detail=none" or "detail=column" option. If the FTS5 table is created
13297 ** with either "detail=none" or "detail=column" and "content=" option
13298 ** (i.e. if it is a contentless table), then this API always iterates
13299 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
 
 
 
 
13300 **
13301 ** xPhraseNext()
13302 ** See xPhraseFirst above.
13303 **
13304 ** xPhraseFirstColumn()
@@ -14479,139 +14535,139 @@
14479 #define TK_EACH 41
14480 #define TK_FAIL 42
14481 #define TK_OR 43
14482 #define TK_AND 44
14483 #define TK_IS 45
14484 #define TK_MATCH 46
14485 #define TK_LIKE_KW 47
14486 #define TK_BETWEEN 48
14487 #define TK_IN 49
14488 #define TK_ISNULL 50
14489 #define TK_NOTNULL 51
14490 #define TK_NE 52
14491 #define TK_EQ 53
14492 #define TK_GT 54
14493 #define TK_LE 55
14494 #define TK_LT 56
14495 #define TK_GE 57
14496 #define TK_ESCAPE 58
14497 #define TK_ID 59
14498 #define TK_COLUMNKW 60
14499 #define TK_DO 61
14500 #define TK_FOR 62
14501 #define TK_IGNORE 63
14502 #define TK_INITIALLY 64
14503 #define TK_INSTEAD 65
14504 #define TK_NO 66
14505 #define TK_KEY 67
14506 #define TK_OF 68
14507 #define TK_OFFSET 69
14508 #define TK_PRAGMA 70
14509 #define TK_RAISE 71
14510 #define TK_RECURSIVE 72
14511 #define TK_REPLACE 73
14512 #define TK_RESTRICT 74
14513 #define TK_ROW 75
14514 #define TK_ROWS 76
14515 #define TK_TRIGGER 77
14516 #define TK_VACUUM 78
14517 #define TK_VIEW 79
14518 #define TK_VIRTUAL 80
14519 #define TK_WITH 81
14520 #define TK_NULLS 82
14521 #define TK_FIRST 83
14522 #define TK_LAST 84
14523 #define TK_CURRENT 85
14524 #define TK_FOLLOWING 86
14525 #define TK_PARTITION 87
14526 #define TK_PRECEDING 88
14527 #define TK_RANGE 89
14528 #define TK_UNBOUNDED 90
14529 #define TK_EXCLUDE 91
14530 #define TK_GROUPS 92
14531 #define TK_OTHERS 93
14532 #define TK_TIES 94
14533 #define TK_GENERATED 95
14534 #define TK_ALWAYS 96
14535 #define TK_MATERIALIZED 97
14536 #define TK_REINDEX 98
14537 #define TK_RENAME 99
14538 #define TK_CTIME_KW 100
14539 #define TK_ANY 101
14540 #define TK_BITAND 102
14541 #define TK_BITOR 103
14542 #define TK_LSHIFT 104
14543 #define TK_RSHIFT 105
14544 #define TK_PLUS 106
14545 #define TK_MINUS 107
14546 #define TK_STAR 108
14547 #define TK_SLASH 109
14548 #define TK_REM 110
14549 #define TK_CONCAT 111
14550 #define TK_PTR 112
14551 #define TK_COLLATE 113
14552 #define TK_BITNOT 114
14553 #define TK_ON 115
14554 #define TK_INDEXED 116
14555 #define TK_STRING 117
14556 #define TK_JOIN_KW 118
14557 #define TK_CONSTRAINT 119
14558 #define TK_DEFAULT 120
14559 #define TK_NULL 121
14560 #define TK_PRIMARY 122
14561 #define TK_UNIQUE 123
14562 #define TK_CHECK 124
14563 #define TK_REFERENCES 125
14564 #define TK_AUTOINCR 126
14565 #define TK_INSERT 127
14566 #define TK_DELETE 128
14567 #define TK_UPDATE 129
14568 #define TK_SET 130
14569 #define TK_DEFERRABLE 131
14570 #define TK_FOREIGN 132
14571 #define TK_DROP 133
14572 #define TK_UNION 134
14573 #define TK_ALL 135
14574 #define TK_EXCEPT 136
14575 #define TK_INTERSECT 137
14576 #define TK_SELECT 138
14577 #define TK_VALUES 139
14578 #define TK_DISTINCT 140
14579 #define TK_DOT 141
14580 #define TK_FROM 142
14581 #define TK_JOIN 143
14582 #define TK_USING 144
14583 #define TK_ORDER 145
14584 #define TK_GROUP 146
14585 #define TK_HAVING 147
14586 #define TK_LIMIT 148
14587 #define TK_WHERE 149
14588 #define TK_RETURNING 150
14589 #define TK_INTO 151
14590 #define TK_NOTHING 152
14591 #define TK_FLOAT 153
14592 #define TK_BLOB 154
14593 #define TK_INTEGER 155
14594 #define TK_VARIABLE 156
14595 #define TK_CASE 157
14596 #define TK_WHEN 158
14597 #define TK_THEN 159
14598 #define TK_ELSE 160
14599 #define TK_INDEX 161
14600 #define TK_ALTER 162
14601 #define TK_ADD 163
14602 #define TK_WINDOW 164
14603 #define TK_OVER 165
14604 #define TK_FILTER 166
14605 #define TK_COLUMN 167
14606 #define TK_AGG_FUNCTION 168
14607 #define TK_AGG_COLUMN 169
14608 #define TK_TRUEFALSE 170
14609 #define TK_ISNOT 171
14610 #define TK_FUNCTION 172
14611 #define TK_UMINUS 173
14612 #define TK_UPLUS 174
14613 #define TK_TRUTH 175
14614 #define TK_REGISTER 176
14615 #define TK_VECTOR 177
14616 #define TK_SELECT_COLUMN 178
14617 #define TK_IF_NULL_ROW 179
@@ -15148,11 +15204,11 @@
15148 ** 0x00000008 WhereLoop inserts
15149 **
15150 ** 0x00000010 Display sqlite3_index_info xBestIndex calls
15151 ** 0x00000020 Range an equality scan metrics
15152 ** 0x00000040 IN operator decisions
15153 ** 0x00000080 WhereLoop cost adjustements
15154 ** 0x00000100
15155 ** 0x00000200 Covering index decisions
15156 ** 0x00000400 OR optimization
15157 ** 0x00000800 Index scanner
15158 ** 0x00001000 More details associated with code generation
@@ -16610,20 +16666,20 @@
16610 #define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
16611 #define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
16612 #define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
16613 #define OP_Program 48 /* jump0 */
16614 #define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
16615 #define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
16616 #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
16617 #define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
16618 #define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
16619 #define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
16620 #define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
16621 #define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
16622 #define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
16623 #define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
16624 #define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
16625 #define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
16626 #define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
16627 #define OP_IncrVacuum 62 /* jump */
16628 #define OP_VNext 63 /* jump */
16629 #define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
@@ -16662,27 +16718,27 @@
16662 #define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
16663 #define OP_Count 98 /* synopsis: r[P2]=count() */
16664 #define OP_ReadCookie 99
16665 #define OP_SetCookie 100
16666 #define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
16667 #define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
16668 #define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
16669 #define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
16670 #define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
16671 #define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
16672 #define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
16673 #define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
16674 #define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
16675 #define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
16676 #define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
16677 #define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
16678 #define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
16679 #define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
16680 #define OP_OpenDup 115
16681 #define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
16682 #define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
16683 #define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
16684 #define OP_SorterOpen 119
16685 #define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
16686 #define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
16687 #define OP_Close 122
16688 #define OP_ColumnsUsed 123
@@ -16713,12 +16769,12 @@
16713 #define OP_SqlExec 148
16714 #define OP_ParseSchema 149
16715 #define OP_LoadAnalysis 150
16716 #define OP_DropTable 151
16717 #define OP_DropIndex 152
16718 #define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
16719 #define OP_DropTrigger 154
16720 #define OP_IntegrityCk 155
16721 #define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
16722 #define OP_Param 157
16723 #define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
16724 #define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
@@ -16770,24 +16826,24 @@
16770 /* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
16771 /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
16772 /* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
16773 /* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
16774 /* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
16775 /* 48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
16776 /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
16777 /* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
16778 /* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
16779 /* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
16780 /* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
16781 /* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
16782 /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
16783 /* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
16784 /* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
16785 /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
16786 /* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
16787 /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
16788 /* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
16789 /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
16790 /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
16791 /* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
16792 /* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
16793
@@ -17826,11 +17882,11 @@
17826 #define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
17827 #define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
17828 #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
17829 #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
17830 /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
17831 #define SQLITE_PushDown 0x00001000 /* The push-down optimization */
17832 #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
17833 #define SQLITE_SkipScan 0x00004000 /* Skip-scans */
17834 #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
17835 #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
17836 #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
@@ -19232,10 +19288,11 @@
19232 unsigned notCte :1; /* This item may not match a CTE */
19233 unsigned isUsing :1; /* u3.pUsing is valid */
19234 unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
19235 unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
19236 unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
 
19237 } fg;
19238 int iCursor; /* The VDBE cursor number used to access this table */
19239 union {
19240 Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
19241 IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
@@ -19307,11 +19364,11 @@
19307 #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
19308 #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
19309 #define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
19310 #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
19311 #define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
19312 /* 0x2000 not currently used */
19313 #define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
19314 /* 0x8000 not currently used */
19315
19316 /* Allowed return values from sqlite3WhereIsDistinct()
19317 */
@@ -19379,11 +19436,11 @@
19379 #define NC_UEList 0x000080 /* True if uNC.pEList is used */
19380 #define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
19381 #define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
19382 #define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
19383 #define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
19384 #define NC_Complex 0x002000 /* True if a function or subquery seen */
19385 #define NC_AllowWin 0x004000 /* Window functions are allowed here */
19386 #define NC_HasWin 0x008000 /* One or more window functions seen */
19387 #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
19388 #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
19389 #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
@@ -19500,15 +19557,16 @@
19500 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
19501 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
19502 #define SF_View 0x0200000 /* SELECT statement is a view */
19503 #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
19504 #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
19505 #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
19506 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
19507 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
19508 #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
19509 #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
 
19510
19511 /* True if S exists and has SF_NestedFrom */
19512 #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
19513
19514 /*
@@ -19537,11 +19595,15 @@
19537 ** of the query. This destination implies "LIMIT 1".
19538 **
19539 ** SRT_Set The result must be a single column. Store each
19540 ** row of result as the key in table pDest->iSDParm.
19541 ** Apply the affinity pDest->affSdst before storing
19542 ** results. Used to implement "IN (SELECT ...)".
 
 
 
 
19543 **
19544 ** SRT_EphemTab Create an temporary table pDest->iSDParm and store
19545 ** the result there. The cursor is left open after
19546 ** returning. This is like SRT_Table except that
19547 ** this destination uses OP_OpenEphemeral to create
@@ -20040,11 +20102,11 @@
20040 int iRetReg; /* Register array for holding a row of RETURNING */
20041 char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
20042 };
20043
20044 /*
20045 ** An objected used to accumulate the text of a string where we
20046 ** do not necessarily know how big the string will be in the end.
20047 */
20048 struct sqlite3_str {
20049 sqlite3 *db; /* Optional database for lookaside. Can be NULL */
20050 char *zText; /* The string collected so far */
@@ -20054,11 +20116,11 @@
20054 u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
20055 u8 printfFlags; /* SQLITE_PRINTF flags below */
20056 };
20057 #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
20058 #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
20059 #define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
20060
20061 #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
20062
20063 /*
20064 ** The following object is the header for an "RCStr" or "reference-counted
@@ -20775,11 +20837,11 @@
20775 SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
20776 SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
20777 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
20778 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
20779 SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
20780 SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
20781 SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
20782 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
20783 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
20784 SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
20785 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
@@ -20943,10 +21005,11 @@
20943 SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
20944 SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
20945 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
20946 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
20947 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
 
20948 SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
20949 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
20950 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
20951 #endif
20952 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
@@ -21001,16 +21064,15 @@
21001 SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
21002 SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
21003 SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
21004 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
21005 SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
21006 SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
21007 SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
21008 #ifdef SQLITE_ENABLE_CURSOR_HINTS
21009 SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
21010 #endif
21011 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
21012 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
21013 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
21014 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
21015 SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
21016 SQLITE_PRIVATE void sqlite3GenerateRowDelete(
@@ -21187,11 +21249,13 @@
21187 SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
21188 SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
21189 SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
21190 SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
21191 SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
 
21192 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
 
21193 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
21194 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
21195
21196 #if defined(SQLITE_NEED_ERR_NAME)
21197 SQLITE_PRIVATE const char *sqlite3ErrName(int);
@@ -24830,12 +24894,12 @@
24830 } aXformType[] = {
24831 /* 0 */ { 6, "second", 4.6427e+14, 1.0 },
24832 /* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
24833 /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
24834 /* 3 */ { 3, "day", 5373485.0, 86400.0 },
24835 /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
24836 /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
24837 };
24838
24839 /*
24840 ** If the DateTime p is raw number, try to figure out if it is
24841 ** a julian day number of a unix timestamp. Set the p value
@@ -31939,11 +32003,11 @@
31939 sqlite3_str_appendall(pAccum, pItem->zName);
31940 }else if( pItem->zAlias ){
31941 sqlite3_str_appendall(pAccum, pItem->zAlias);
31942 }else{
31943 Select *pSel = pItem->pSelect;
31944 assert( pSel!=0 );
31945 if( pSel->selFlags & SF_NestedFrom ){
31946 sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
31947 }else if( pSel->selFlags & SF_MultiValue ){
31948 assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
31949 sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
@@ -32722,12 +32786,14 @@
32722 char zLine[1000];
32723 sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
32724 x.printfFlags |= SQLITE_PRINTF_INTERNAL;
32725 sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
32726 if( pItem->pTab ){
32727 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
32728 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
 
 
32729 }
32730 if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
32731 sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
32732 }else if( pItem->fg.jointype & JT_LEFT ){
32733 sqlite3_str_appendf(&x, " LEFT-JOIN");
@@ -32763,16 +32829,18 @@
32763 if( pItem->fg.isUsing ) n++;
32764 if( pItem->fg.isUsing ){
32765 sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
32766 }
32767 if( pItem->pSelect ){
 
32768 if( pItem->pTab ){
32769 Table *pTab = pItem->pTab;
32770 sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
32771 }
32772 assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
32773 sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
 
32774 }
32775 if( pItem->fg.isTabFunc ){
32776 sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
32777 }
32778 sqlite3TreeViewPop(&pView);
@@ -32872,11 +32940,11 @@
32872 }
32873 if( p->pLimit ){
32874 sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
32875 sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
32876 if( p->pLimit->pRight ){
32877 sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
32878 sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
32879 sqlite3TreeViewPop(&pView);
32880 }
32881 sqlite3TreeViewPop(&pView);
32882 }
@@ -33344,11 +33412,12 @@
33344 case OE_Abort: zType = "abort"; break;
33345 case OE_Fail: zType = "fail"; break;
33346 case OE_Ignore: zType = "ignore"; break;
33347 }
33348 assert( !ExprHasProperty(pExpr, EP_IntValue) );
33349 sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
 
33350 break;
33351 }
33352 #endif
33353 case TK_MATCH: {
33354 sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
@@ -33424,13 +33493,14 @@
33424 }else{
33425 int i;
33426 sqlite3TreeViewLine(pView, "%s", zLabel);
33427 for(i=0; i<pList->nExpr; i++){
33428 int j = pList->a[i].u.x.iOrderByCol;
 
33429 char *zName = pList->a[i].zEName;
33430 int moreToFollow = i<pList->nExpr - 1;
33431 if( j || zName ){
33432 sqlite3TreeViewPush(&pView, moreToFollow);
33433 moreToFollow = 0;
33434 sqlite3TreeViewLine(pView, 0);
33435 if( zName ){
33436 switch( pList->a[i].fg.eEName ){
@@ -33447,17 +33517,22 @@
33447 fprintf(stdout, "SPAN(\"%s\") ", zName);
33448 break;
33449 }
33450 }
33451 if( j ){
33452 fprintf(stdout, "iOrderByCol=%d", j);
 
 
 
 
 
33453 }
33454 fprintf(stdout, "\n");
33455 fflush(stdout);
33456 }
33457 sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
33458 if( j || zName ){
33459 sqlite3TreeViewPop(&pView);
33460 }
33461 }
33462 }
33463 }
@@ -35864,14 +35939,17 @@
35864
35865 /*
35866 ** Decode a floating-point value into an approximate decimal
35867 ** representation.
35868 **
35869 ** Round the decimal representation to n significant digits if
35870 ** n is positive. Or round to -n signficant digits after the
35871 ** decimal point if n is negative. No rounding is performed if
35872 ** n is zero.
 
 
 
35873 **
35874 ** The significant digits of the decimal representation are
35875 ** stored in p->z[] which is a often (but not always) a pointer
35876 ** into the middle of p->zBuf[]. There are p->n significant digits.
35877 ** The p->z[] array is *not* zero-terminated.
@@ -35880,10 +35958,12 @@
35880 int i;
35881 u64 v;
35882 int e, exp = 0;
35883 p->isSpecial = 0;
35884 p->z = p->zBuf;
 
 
35885
35886 /* Convert negative numbers to positive. Deal with Infinity, 0.0, and
35887 ** NaN. */
35888 if( r<0.0 ){
35889 p->sign = '-';
@@ -37167,20 +37247,20 @@
37167 /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
37168 /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
37169 /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
37170 /* 48 */ "Program" OpHelp(""),
37171 /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
37172 /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
37173 /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
37174 /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
37175 /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
37176 /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
37177 /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
37178 /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
37179 /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
37180 /* 58 */ "ElseEq" OpHelp(""),
37181 /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
37182 /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
37183 /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
37184 /* 62 */ "IncrVacuum" OpHelp(""),
37185 /* 63 */ "VNext" OpHelp(""),
37186 /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
@@ -37219,27 +37299,27 @@
37219 /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
37220 /* 98 */ "Count" OpHelp("r[P2]=count()"),
37221 /* 99 */ "ReadCookie" OpHelp(""),
37222 /* 100 */ "SetCookie" OpHelp(""),
37223 /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
37224 /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
37225 /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
37226 /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
37227 /* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
37228 /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
37229 /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
37230 /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
37231 /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
37232 /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
37233 /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
37234 /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
37235 /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
37236 /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
37237 /* 115 */ "OpenDup" OpHelp(""),
37238 /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
37239 /* 117 */ "String8" OpHelp("r[P2]='P4'"),
37240 /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
37241 /* 119 */ "SorterOpen" OpHelp(""),
37242 /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
37243 /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
37244 /* 122 */ "Close" OpHelp(""),
37245 /* 123 */ "ColumnsUsed" OpHelp(""),
@@ -37270,12 +37350,12 @@
37270 /* 148 */ "SqlExec" OpHelp(""),
37271 /* 149 */ "ParseSchema" OpHelp(""),
37272 /* 150 */ "LoadAnalysis" OpHelp(""),
37273 /* 151 */ "DropTable" OpHelp(""),
37274 /* 152 */ "DropIndex" OpHelp(""),
37275 /* 153 */ "Real" OpHelp("r[P2]=P4"),
37276 /* 154 */ "DropTrigger" OpHelp(""),
37277 /* 155 */ "IntegrityCk" OpHelp(""),
37278 /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
37279 /* 157 */ "Param" OpHelp(""),
37280 /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
37281 /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
@@ -40577,30 +40657,26 @@
40577 */
40578 #define DOTLOCK_SUFFIX ".lock"
40579
40580 /*
40581 ** This routine checks if there is a RESERVED lock held on the specified
40582 ** file by this or any other process. If such a lock is held, set *pResOut
40583 ** to a non-zero value otherwise *pResOut is set to zero. The return value
40584 ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
40585 **
40586 ** In dotfile locking, either a lock exists or it does not. So in this
40587 ** variation of CheckReservedLock(), *pResOut is set to true if any lock
40588 ** is held on the file and false if the file is unlocked.
40589 */
40590 static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
40591 int rc = SQLITE_OK;
40592 int reserved = 0;
40593 unixFile *pFile = (unixFile*)id;
40594
40595 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
40596
40597 assert( pFile );
40598 reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
40599 OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
40600 *pResOut = reserved;
40601 return rc;
 
 
40602 }
40603
40604 /*
40605 ** Lock the file with the lock specified by parameter eFileLock - one
40606 ** of the following:
@@ -42285,11 +42361,11 @@
42285 }
42286 }
42287
42288 /* Forward declaration */
42289 static int unixGetTempname(int nBuf, char *zBuf);
42290 #ifndef SQLITE_OMIT_WAL
42291 static int unixFcntlExternalReader(unixFile*, int*);
42292 #endif
42293
42294 /*
42295 ** Information and control of an open file handle.
@@ -42412,11 +42488,11 @@
42412 return proxyFileControl(id,op,pArg);
42413 }
42414 #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
42415
42416 case SQLITE_FCNTL_EXTERNAL_READER: {
42417 #ifndef SQLITE_OMIT_WAL
42418 return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
42419 #else
42420 *(int*)pArg = 0;
42421 return SQLITE_OK;
42422 #endif
@@ -42585,11 +42661,11 @@
42585 #endif
42586 }
42587
42588 #endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
42589
42590 #ifndef SQLITE_OMIT_WAL
42591
42592 /*
42593 ** Object used to represent an shared memory buffer.
42594 **
42595 ** When multiple threads all reference the same wal-index, each thread
@@ -64135,11 +64211,11 @@
64135 /*
64136 ** Return the file handle for the journal file (if it exists).
64137 ** This will be either the rollback journal or the WAL file.
64138 */
64139 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
64140 #if SQLITE_OMIT_WAL
64141 return pPager->jfd;
64142 #else
64143 return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
64144 #endif
64145 }
@@ -75626,10 +75702,16 @@
75626 }
75627 }
75628 memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
75629 pCur->curFlags |= BTCF_ValidOvfl;
75630 }else{
 
 
 
 
 
 
75631 /* If the overflow page-list cache has been allocated and the
75632 ** entry for the first required overflow page is valid, skip
75633 ** directly to it.
75634 */
75635 if( pCur->aOverflow[offset/ovflSize] ){
@@ -76106,10 +76188,27 @@
76106 *pRes = 1;
76107 rc = SQLITE_OK;
76108 }
76109 return rc;
76110 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76111
76112 /* Move the cursor to the last entry in the table. Return SQLITE_OK
76113 ** on success. Set *pRes to 0 if the cursor actually points to something
76114 ** or set *pRes to 1 if the table is empty.
76115 */
@@ -76135,22 +76234,11 @@
76135 assert( cursorOwnsBtShared(pCur) );
76136 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
76137
76138 /* If the cursor already points to the last entry, this is a no-op. */
76139 if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
76140 #ifdef SQLITE_DEBUG
76141 /* This block serves to assert() that the cursor really does point
76142 ** to the last entry in the b-tree. */
76143 int ii;
76144 for(ii=0; ii<pCur->iPage; ii++){
76145 assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
76146 }
76147 assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
76148 testcase( pCur->ix!=pCur->pPage->nCell-1 );
76149 /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
76150 assert( pCur->pPage->leaf );
76151 #endif
76152 *pRes = 0;
76153 return SQLITE_OK;
76154 }
76155 return btreeLast(pCur, pRes);
76156 }
@@ -76199,10 +76287,11 @@
76199 *pRes = 0;
76200 return SQLITE_OK;
76201 }
76202 if( pCur->info.nKey<intKey ){
76203 if( (pCur->curFlags & BTCF_AtLast)!=0 ){
 
76204 *pRes = -1;
76205 return SQLITE_OK;
76206 }
76207 /* If the requested key is one more than the previous key, then
76208 ** try to get there using sqlite3BtreeNext() rather than a full
@@ -78037,11 +78126,12 @@
78037 assert( i<iEnd );
78038 j = get2byte(&aData[hdr+5]);
78039 if( j>(u32)usableSize ){ j = 0; }
78040 memcpy(&pTmp[j], &aData[j], usableSize - j);
78041
78042 for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
 
78043 pSrcEnd = pCArray->apEnd[k];
78044
78045 pData = pEnd;
78046 while( 1/*exit by break*/ ){
78047 u8 *pCell = pCArray->apCell[i];
@@ -78120,11 +78210,12 @@
78120 int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
78121 int k; /* Current slot in pCArray->apEnd[] */
78122 u8 *pEnd; /* Maximum extent of cell data */
78123 assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
78124 if( iEnd<=iFirst ) return 0;
78125 for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
 
78126 pEnd = pCArray->apEnd[k];
78127 while( 1 /*Exit by break*/ ){
78128 int sz, rc;
78129 u8 *pSlot;
78130 assert( pCArray->szCell[i]!=0 );
@@ -78405,10 +78496,11 @@
78405 b.pRef = pPage;
78406 b.apCell = &pCell;
78407 b.szCell = &szCell;
78408 b.apEnd[0] = pPage->aDataEnd;
78409 b.ixNx[0] = 2;
 
78410 rc = rebuildPage(&b, 0, 1, pNew);
78411 if( NEVER(rc) ){
78412 releasePage(pNew);
78413 return rc;
78414 }
@@ -78640,11 +78732,13 @@
78640 u8 abDone[NB+2]; /* True after i'th new page is populated */
78641 Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */
78642 CellArray b; /* Parsed information on cells being balanced */
78643
78644 memset(abDone, 0, sizeof(abDone));
78645 memset(&b, 0, sizeof(b));
 
 
78646 pBt = pParent->pBt;
78647 assert( sqlite3_mutex_held(pBt->mutex) );
78648 assert( sqlite3PagerIswriteable(pParent->pDbPage) );
78649
78650 /* At this point pParent may have at most one overflow cell. And if
@@ -79231,11 +79325,12 @@
79231 }
79232 }
79233 iOvflSpace += sz;
79234 assert( sz<=pBt->maxLocal+23 );
79235 assert( iOvflSpace <= (int)pBt->pageSize );
79236 for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
 
79237 pSrcEnd = b.apEnd[k];
79238 if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
79239 rc = SQLITE_CORRUPT_BKPT;
79240 goto balance_cleanup;
79241 }
@@ -80004,11 +80099,11 @@
80004 dropCell(pPage, idx, info.nSize, &rc);
80005 if( rc ) goto end_insert;
80006 }else if( loc<0 && pPage->nCell>0 ){
80007 assert( pPage->leaf );
80008 idx = ++pCur->ix;
80009 pCur->curFlags &= ~BTCF_ValidNKey;
80010 }else{
80011 assert( pPage->leaf );
80012 }
80013 rc = insertCellFast(pPage, idx, newCell, szNew);
80014 assert( pPage->nOverflow==0 || rc==SQLITE_OK );
@@ -80034,11 +80129,11 @@
80034 ** larger than the largest existing key, it is possible to insert the
80035 ** row without seeking the cursor. This can be a big performance boost.
80036 */
80037 if( pPage->nOverflow ){
80038 assert( rc==SQLITE_OK );
80039 pCur->curFlags &= ~(BTCF_ValidNKey);
80040 rc = balance(pCur);
80041
80042 /* Must make sure nOverflow is reset to zero even if the balance()
80043 ** fails. Internal data structure corruption will result otherwise.
80044 ** Also, set the cursor state to invalid. This stops saveCursorPosition()
@@ -84658,21 +84753,21 @@
84658 int nRec, /* Size of buffer pRec in bytes */
84659 int iCol, /* Column to extract */
84660 sqlite3_value **ppVal /* OUT: Extracted value */
84661 ){
84662 u32 t = 0; /* a column type code */
84663 int nHdr; /* Size of the header in the record */
84664 int iHdr; /* Next unread header byte */
84665 int iField; /* Next unread data byte */
84666 int szField = 0; /* Size of the current data field */
84667 int i; /* Column index */
84668 u8 *a = (u8*)pRec; /* Typecast byte array */
84669 Mem *pMem = *ppVal; /* Write result into this Mem object */
84670
84671 assert( iCol>0 );
84672 iHdr = getVarint32(a, nHdr);
84673 if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
84674 iField = nHdr;
84675 for(i=0; i<=iCol; i++){
84676 iHdr += getVarint32(&a[iHdr], t);
84677 testcase( iHdr==nHdr );
84678 testcase( iHdr==nHdr+1 );
@@ -88119,11 +88214,11 @@
88119 }
88120 }
88121
88122 /* Check for immediate foreign key violations. */
88123 if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
88124 sqlite3VdbeCheckFk(p, 0);
88125 }
88126
88127 /* If the auto-commit flag is set and this is the only active writer
88128 ** VM, then we do either a commit or rollback of the current transaction.
88129 **
@@ -90100,11 +90195,12 @@
90100 */
90101 SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
90102 assert( iVar>0 );
90103 if( v ){
90104 Mem *pMem = &v->aVar[iVar-1];
90105 assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
 
90106 if( 0==(pMem->flags & MEM_Null) ){
90107 sqlite3_value *pRet = sqlite3ValueNew(v->db);
90108 if( pRet ){
90109 sqlite3VdbeMemCopy((Mem *)pRet, pMem);
90110 sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
@@ -90120,11 +90216,12 @@
90120 ** to sqlite3_reoptimize() that re-preparing the statement may result
90121 ** in a better query plan.
90122 */
90123 SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
90124 assert( iVar>0 );
90125 assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
 
90126 if( iVar>=32 ){
90127 v->expmask |= 0x80000000;
90128 }else{
90129 v->expmask |= ((u32)1 << (iVar-1));
90130 }
@@ -94190,11 +94287,13 @@
94190
94191 /* Opcode: EndCoroutine P1 * * * *
94192 **
94193 ** The instruction at the address in register P1 is a Yield.
94194 ** Jump to the P2 parameter of that Yield.
94195 ** After the jump, register P1 becomes undefined.
 
 
94196 **
94197 ** See also: InitCoroutine
94198 */
94199 case OP_EndCoroutine: { /* in1 */
94200 VdbeOp *pCaller;
@@ -94202,12 +94301,12 @@
94202 assert( pIn1->flags==MEM_Int );
94203 assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
94204 pCaller = &aOp[pIn1->u.i];
94205 assert( pCaller->opcode==OP_Yield );
94206 assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
 
94207 pOp = &aOp[pCaller->p2 - 1];
94208 pIn1->flags = MEM_Undefined;
94209 break;
94210 }
94211
94212 /* Opcode: Yield P1 P2 * * *
94213 **
@@ -94250,11 +94349,11 @@
94250 if( (pIn3->flags & MEM_Null)==0 ) break;
94251 /* Fall through into OP_Halt */
94252 /* no break */ deliberate_fall_through
94253 }
94254
94255 /* Opcode: Halt P1 P2 * P4 P5
94256 **
94257 ** Exit immediately. All open cursors, etc are closed
94258 ** automatically.
94259 **
94260 ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
@@ -94263,22 +94362,26 @@
94263 ** whether or not to rollback the current transaction. Do not rollback
94264 ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
94265 ** then back out all changes that have occurred during this execution of the
94266 ** VDBE, but do not rollback the transaction.
94267 **
94268 ** If P4 is not null then it is an error message string.
 
94269 **
94270 ** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
 
94271 **
94272 ** 0: (no change)
 
 
94273 ** 1: NOT NULL constraint failed: P4
94274 ** 2: UNIQUE constraint failed: P4
94275 ** 3: CHECK constraint failed: P4
94276 ** 4: FOREIGN KEY constraint failed: P4
94277 **
94278 ** If P5 is not zero and P4 is NULL, then everything after the ":" is
94279 ** omitted.
94280 **
94281 ** There is an implied "Halt 0 0 0" instruction inserted at the very end of
94282 ** every program. So a jump past the last instruction of the program
94283 ** is the same as executing Halt.
94284 */
@@ -94287,10 +94390,13 @@
94287 int pcx;
94288
94289 #ifdef SQLITE_DEBUG
94290 if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
94291 #endif
 
 
 
94292
94293 /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
94294 ** something is wrong with the code generator. Raise an assertion in order
94295 ** to bring this to the attention of fuzzers and other testing tools. */
94296 assert( pOp->p1!=SQLITE_INTERNAL );
@@ -94317,11 +94423,16 @@
94317 }
94318 p->rc = pOp->p1;
94319 p->errorAction = (u8)pOp->p2;
94320 assert( pOp->p5<=4 );
94321 if( p->rc ){
94322 if( pOp->p5 ){
 
 
 
 
 
94323 static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
94324 "FOREIGN KEY" };
94325 testcase( pOp->p5==1 );
94326 testcase( pOp->p5==2 );
94327 testcase( pOp->p5==3 );
@@ -97360,27 +97471,27 @@
97360 wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
97361 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
97362 if( pDb->pSchema->file_format < p->minWriteFileFormat ){
97363 p->minWriteFileFormat = pDb->pSchema->file_format;
97364 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97365 }else{
97366 wrFlag = 0;
97367 }
97368 if( pOp->p5 & OPFLAG_P2ISREG ){
97369 assert( p2>0 );
97370 assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
97371 assert( pOp->opcode==OP_OpenWrite );
97372 pIn2 = &aMem[p2];
97373 assert( memIsValid(pIn2) );
97374 assert( (pIn2->flags & MEM_Int)!=0 );
97375 sqlite3VdbeMemIntegerify(pIn2);
97376 p2 = (int)pIn2->u.i;
97377 /* The p2 value always comes from a prior OP_CreateBtree opcode and
97378 ** that opcode will always set the p2 value to 2 or more or else fail.
97379 ** If there were a failure, the prepared statement would have halted
97380 ** before reaching this instruction. */
97381 assert( p2>=2 );
97382 }
97383 if( pOp->p4type==P4_KEYINFO ){
97384 pKeyInfo = pOp->p4.pKeyInfo;
97385 assert( pKeyInfo->enc==ENC(db) );
97386 assert( pKeyInfo->db==db );
@@ -97620,11 +97731,12 @@
97620 ** row output from the sorter so that the row can be decomposed into
97621 ** individual columns using the OP_Column opcode. The OP_Column opcode
97622 ** is the only cursor opcode that works with a pseudo-table.
97623 **
97624 ** P3 is the number of fields in the records that will be stored by
97625 ** the pseudo-table.
 
97626 */
97627 case OP_OpenPseudo: {
97628 VdbeCursor *pCx;
97629
97630 assert( pOp->p1>=0 );
@@ -98331,10 +98443,11 @@
98331 if( r.nField>0 ){
98332 /* Key values in an array of registers */
98333 r.pKeyInfo = pC->pKeyInfo;
98334 r.default_rc = 0;
98335 #ifdef SQLITE_DEBUG
 
98336 for(ii=0; ii<r.nField; ii++){
98337 assert( memIsValid(&r.aMem[ii]) );
98338 assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
98339 if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
98340 }
@@ -102038,18 +102151,33 @@
102038 }
102039 #endif
102040
102041 /* Opcode: Noop * * * * *
102042 **
102043 ** Do nothing. This instruction is often useful as a jump
102044 ** destination.
102045 */
102046 /*
102047 ** The magic Explain opcode are only inserted when explain==2 (which
102048 ** is to say when the EXPLAIN QUERY PLAN syntax is used.)
102049 ** This opcode records information from the optimizer. It is the
102050 ** the same as a no-op. This opcodesnever appears in a real VM program.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102051 */
102052 default: { /* This is really OP_Noop, OP_Explain */
102053 assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
102054
102055 break;
@@ -105778,14 +105906,14 @@
105778 break;
105779 }
105780
105781 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
105782 case 9: /* nexec */
105783 sqlite3_result_int(ctx, pOp->nExec);
105784 break;
105785 case 10: /* ncycle */
105786 sqlite3_result_int(ctx, pOp->nCycle);
105787 break;
105788 #else
105789 case 9: /* nexec */
105790 case 10: /* ncycle */
105791 sqlite3_result_int(ctx, 0);
@@ -106874,11 +107002,11 @@
106874 ** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab.
106875 */
106876 static SQLITE_NOINLINE int isValidSchemaTableName(
106877 const char *zTab, /* Name as it appears in the SQL */
106878 Table *pTab, /* The schema table we are trying to match */
106879 Schema *pSchema /* non-NULL if a database qualifier is present */
106880 ){
106881 const char *zLegacy;
106882 assert( pTab!=0 );
106883 assert( pTab->tnum==1 );
106884 if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0;
@@ -106885,11 +107013,11 @@
106885 zLegacy = pTab->zName;
106886 if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
106887 if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
106888 return 1;
106889 }
106890 if( pSchema==0 ) return 0;
106891 if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
106892 if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
106893 }else{
106894 if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
106895 }
@@ -107068,11 +107196,11 @@
107068 if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){
107069 continue;
107070 }
107071 }else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
107072 if( pTab->tnum!=1 ) continue;
107073 if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
107074 }
107075 assert( ExprUseYTab(pExpr) );
107076 if( IN_RENAME_OBJECT && pItem->zAlias ){
107077 sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
107078 }
@@ -107174,11 +107302,12 @@
107174 int op = pParse->eTriggerOp;
107175 assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
107176 if( pParse->bReturning ){
107177 if( (pNC->ncFlags & NC_UBaseReg)!=0
107178 && ALWAYS(zTab==0
107179 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
 
107180 ){
107181 pExpr->iTable = op!=TK_DELETE;
107182 pTab = pParse->pTriggerTab;
107183 }
107184 }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
@@ -107278,10 +107407,15 @@
107278 && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
107279 && sqlite3IsRowid(zCol)
107280 && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
107281 ){
107282 cnt = cntTab;
 
 
 
 
 
107283 if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
107284 pExpr->affExpr = SQLITE_AFF_INTEGER;
107285 }
107286
107287 /*
@@ -107468,12 +107602,16 @@
107468 ** (See ticket [b92e5e8ec2cdbaa1]).
107469 **
107470 ** If a generated column is referenced, set bits for every column
107471 ** of the table.
107472 */
107473 if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){
107474 pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
 
 
 
 
107475 }
107476
107477 pExpr->op = eNewExprOp;
107478 lookupname_end:
107479 if( cnt==1 ){
@@ -107921,15 +108059,13 @@
107921 #else
107922 pNC->ncFlags &= ~NC_AllowAgg;
107923 #endif
107924 }
107925 }
107926 #ifndef SQLITE_OMIT_WINDOWFUNC
107927 else if( ExprHasProperty(pExpr, EP_WinFunc) ){
107928 is_agg = 1;
107929 }
107930 #endif
107931 sqlite3WalkExprList(pWalker, pList);
107932 if( is_agg ){
107933 if( pExpr->pLeft ){
107934 assert( pExpr->pLeft->op==TK_ORDER );
107935 assert( ExprUseXList(pExpr->pLeft) );
@@ -107995,18 +108131,20 @@
107995 int nRef = pNC->nRef;
107996 testcase( pNC->ncFlags & NC_IsCheck );
107997 testcase( pNC->ncFlags & NC_PartIdx );
107998 testcase( pNC->ncFlags & NC_IdxExpr );
107999 testcase( pNC->ncFlags & NC_GenCol );
 
108000 if( pNC->ncFlags & NC_SelfRef ){
108001 notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
108002 }else{
108003 sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
108004 }
108005 assert( pNC->nRef>=nRef );
108006 if( nRef!=pNC->nRef ){
108007 ExprSetProperty(pExpr, EP_VarSelect);
 
108008 }
108009 pNC->ncFlags |= NC_Subquery;
108010 }
108011 break;
108012 }
@@ -108141,11 +108279,11 @@
108141 NameContext nc; /* Name context for resolving pE */
108142 sqlite3 *db; /* Database connection */
108143 int rc; /* Return code from subprocedures */
108144 u8 savedSuppErr; /* Saved value of db->suppressErr */
108145
108146 assert( sqlite3ExprIsInteger(pE, &i)==0 );
108147 pEList = pSelect->pEList;
108148
108149 /* Resolve all names in the ORDER BY term expression
108150 */
108151 memset(&nc, 0, sizeof(nc));
@@ -108240,11 +108378,11 @@
108240 int iCol = -1;
108241 Expr *pE, *pDup;
108242 if( pItem->fg.done ) continue;
108243 pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
108244 if( NEVER(pE==0) ) continue;
108245 if( sqlite3ExprIsInteger(pE, &iCol) ){
108246 if( iCol<=0 || iCol>pEList->nExpr ){
108247 resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
108248 return 1;
108249 }
108250 }else{
@@ -108425,11 +108563,11 @@
108425 ** copy of the iCol-th result-set expression. */
108426 pItem->u.x.iOrderByCol = (u16)iCol;
108427 continue;
108428 }
108429 }
108430 if( sqlite3ExprIsInteger(pE2, &iCol) ){
108431 /* The ORDER BY term is an integer constant. Again, set the column
108432 ** number so that sqlite3ResolveOrderGroupBy() will convert the
108433 ** order-by term to a copy of the result-set expression */
108434 if( iCol<1 || iCol>0xffff ){
108435 resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
@@ -108528,10 +108666,11 @@
108528 /* Recursively resolve names in all subqueries in the FROM clause
108529 */
108530 if( pOuterNC ) pOuterNC->nNestedSelect++;
108531 for(i=0; i<p->pSrc->nSrc; i++){
108532 SrcItem *pItem = &p->pSrc->a[i];
 
108533 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
108534 int nRef = pOuterNC ? pOuterNC->nRef : 0;
108535 const char *zSavedContext = pParse->zAuthContext;
108536
108537 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
@@ -109004,11 +109143,13 @@
109004 || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
109005 pExpr = pExpr->pLeft;
109006 op = pExpr->op;
109007 continue;
109008 }
109009 if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
 
 
109010 }
109011 return pExpr->affExpr;
109012 }
109013
109014 /*
@@ -110287,10 +110428,11 @@
110287 ** Recursively delete an expression tree.
110288 */
110289 static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
110290 assert( p!=0 );
110291 assert( db!=0 );
 
110292 assert( !ExprUseUValue(p) || p->u.iValue>=0 );
110293 assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
110294 assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
110295 assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
110296 #ifdef SQLITE_DEBUG
@@ -110302,11 +110444,10 @@
110302 }
110303 #endif
110304 if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
110305 /* The Expr.x union is never used at the same time as Expr.pRight */
110306 assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
110307 if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
110308 if( p->pRight ){
110309 assert( !ExprHasProperty(p, EP_WinFunc) );
110310 sqlite3ExprDeleteNN(db, p->pRight);
110311 }else if( ExprUseXSelect(p) ){
110312 assert( !ExprHasProperty(p, EP_WinFunc) );
@@ -110316,10 +110457,23 @@
110316 #ifndef SQLITE_OMIT_WINDOWFUNC
110317 if( ExprHasProperty(p, EP_WinFunc) ){
110318 sqlite3WindowDelete(db, p->y.pWin);
110319 }
110320 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
110321 }
110322 }
110323 if( !ExprHasProperty(p, EP_Static) ){
110324 sqlite3DbNNFreeNN(db, p);
110325 }
@@ -110349,15 +110503,15 @@
110349 ** This is similar to sqlite3ExprDelete() except that the delete is
110350 ** deferred until the pParse is deleted.
110351 **
110352 ** The pExpr might be deleted immediately on an OOM error.
110353 **
110354 ** The deferred delete is (currently) implemented by adding the
110355 ** pExpr to the pParse->pConstExpr list with a register number of 0.
110356 */
110357 SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
110358 sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
110359 }
110360
110361 /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
110362 ** expression.
110363 */
@@ -111312,11 +111466,11 @@
111312 || ExprHasProperty(pExpr, EP_WinFunc)
111313 ){
111314 pWalker->eCode = 0;
111315 return WRC_Abort;
111316 }
111317 return WRC_Continue;
111318 }
111319
111320
111321 /*
111322 ** These routines are Walker callbacks used to check expressions to
@@ -111419,20 +111573,19 @@
111419 testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
111420 testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
111421 return WRC_Continue;
111422 }
111423 }
111424 static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
111425 Walker w;
111426 w.eCode = initFlag;
111427 w.pParse = pParse;
111428 w.xExprCallback = exprNodeIsConstant;
111429 w.xSelectCallback = sqlite3SelectWalkFail;
111430 #ifdef SQLITE_DEBUG
111431 w.xSelectCallback2 = sqlite3SelectWalkAssert2;
111432 #endif
111433 w.u.iCur = iCur;
111434 sqlite3WalkExpr(&w, p);
111435 return w.eCode;
111436 }
111437
111438 /*
@@ -111448,11 +111601,11 @@
111448 ** function calls will be considered to be non-constant. If pParse is
111449 ** not NULL, then a function call might be constant, depending on the
111450 ** function and on its parameters.
111451 */
111452 SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
111453 return exprIsConst(pParse, p, 1, 0);
111454 }
111455
111456 /*
111457 ** Walk an expression tree. Return non-zero if
111458 **
@@ -111465,21 +111618,54 @@
111465 ** When this routine returns true, it indicates that the expression
111466 ** can be added to the pParse->pConstExpr list and evaluated once when
111467 ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
111468 */
111469 static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
111470 return exprIsConst(pParse, p, 2, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111471 }
111472
111473 /*
111474 ** Walk an expression tree. Return non-zero if the expression is constant
111475 ** for any single row of the table with cursor iCur. In other words, the
111476 ** expression must not refer to any non-deterministic function nor any
111477 ** table other than iCur.
 
 
 
111478 */
111479 SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
111480 return exprIsConst(0, p, 3, iCur);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111481 }
111482
111483 /*
111484 ** Check pExpr to see if it is an constraint on the single data source
111485 ** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr
@@ -111493,11 +111679,14 @@
111493 **
111494 ** To be an single-source constraint, the following must be true:
111495 **
111496 ** (1) pExpr cannot refer to any table other than pSrc->iCursor.
111497 **
111498 ** (2) pExpr cannot use subqueries or non-deterministic functions.
 
 
 
111499 **
111500 ** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
111501 ** (Is there some way to relax this constraint?)
111502 **
111503 ** (4) If pSrc is the right operand of a LEFT JOIN, then...
@@ -111522,11 +111711,12 @@
111522 ** on push-down.
111523 */
111524 SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(
111525 Expr *pExpr, /* The constraint */
111526 const SrcList *pSrcList, /* Complete FROM clause */
111527 int iSrc /* Which element of pSrcList to use */
 
111528 ){
111529 const SrcItem *pSrc = &pSrcList->a[iSrc];
111530 if( pSrc->fg.jointype & JT_LTORJ ){
111531 return 0; /* rule (3) */
111532 }
@@ -111547,11 +111737,12 @@
111547 }
111548 break;
111549 }
111550 }
111551 }
111552 return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
 
111553 }
111554
111555
111556 /*
111557 ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
@@ -111632,11 +111823,11 @@
111632 ** is considered a variable but a single-quoted string (ex: 'abc') is
111633 ** a constant.
111634 */
111635 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
111636 assert( isInit==0 || isInit==1 );
111637 return exprIsConst(0, p, 4+isInit, 0);
111638 }
111639
111640 #ifdef SQLITE_ENABLE_CURSOR_HINTS
111641 /*
111642 ** Walk an expression tree. Return 1 if the expression contains a
@@ -111658,12 +111849,16 @@
111658 /*
111659 ** If the expression p codes a constant integer that is small enough
111660 ** to fit in a 32-bit integer, return 1 and put the value of the integer
111661 ** in *pValue. If the expression is not an integer or if it is too big
111662 ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
 
 
 
 
111663 */
111664 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
111665 int rc = 0;
111666 if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
111667
111668 /* If an expression is an integer literal that fits in a signed 32-bit
111669 ** integer, then the EP_IntValue flag will have already been set */
@@ -111674,21 +111869,41 @@
111674 *pValue = p->u.iValue;
111675 return 1;
111676 }
111677 switch( p->op ){
111678 case TK_UPLUS: {
111679 rc = sqlite3ExprIsInteger(p->pLeft, pValue);
111680 break;
111681 }
111682 case TK_UMINUS: {
111683 int v = 0;
111684 if( sqlite3ExprIsInteger(p->pLeft, &v) ){
111685 assert( ((unsigned int)v)!=0x80000000 );
111686 *pValue = -v;
111687 rc = 1;
111688 }
111689 break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111690 }
111691 default: break;
111692 }
111693 return rc;
111694 }
@@ -112379,19 +112594,34 @@
112379 if( ALWAYS(pEList->nExpr==nVal) ){
112380 Select *pCopy;
112381 SelectDest dest;
112382 int i;
112383 int rc;
 
112384 sqlite3SelectDestInit(&dest, SRT_Set, iTab);
112385 dest.zAffSdst = exprINAffinity(pParse, pExpr);
112386 pSelect->iLimit = 0;
 
 
 
 
 
 
112387 testcase( pSelect->selFlags & SF_Distinct );
112388 testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
112389 pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
112390 rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
112391 sqlite3SelectDelete(pParse->db, pCopy);
112392 sqlite3DbFree(pParse->db, dest.zAffSdst);
 
 
 
 
 
 
 
 
112393 if( rc ){
112394 sqlite3KeyInfoUnref(pKeyInfo);
112395 return;
112396 }
112397 assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
@@ -112830,10 +113060,19 @@
112830 addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
112831 }else{
112832 sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
112833 if( destIfFalse==destIfNull ){
112834 /* Combine Step 3 and Step 5 into a single opcode */
 
 
 
 
 
 
 
 
 
112835 sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
112836 rLhs, nVector); VdbeCoverage(v);
112837 goto sqlite3ExprCodeIN_finished;
112838 }
112839 /* Ordinary Step 3, for the case where FALSE and NULL are distinct */
@@ -113112,17 +113351,21 @@
113112 /*
113113 ** Convert a scalar expression node to a TK_REGISTER referencing
113114 ** register iReg. The caller must ensure that iReg already contains
113115 ** the correct value for the expression.
113116 */
113117 static void exprToRegister(Expr *pExpr, int iReg){
113118 Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
113119 if( NEVER(p==0) ) return;
113120 p->op2 = p->op;
113121 p->op = TK_REGISTER;
113122 p->iTable = iReg;
113123 ExprClearProperty(p, EP_Skip);
 
 
 
 
113124 }
113125
113126 /*
113127 ** Evaluate an expression (either a vector or a scalar expression) and store
113128 ** the result in contiguous temporary registers. Return the index of
@@ -113950,12 +114193,13 @@
113950 }
113951 case TK_COLLATE: {
113952 if( !ExprHasProperty(pExpr, EP_Collate) ){
113953 /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
113954 ** "SOFT-COLLATE" that is added to constraints that are pushed down
113955 ** from outer queries into sub-queries by the push-down optimization.
113956 ** Clear subtypes as subtypes may not cross a subquery boundary.
 
113957 */
113958 assert( pExpr->pLeft );
113959 sqlite3ExprCode(pParse, pExpr->pLeft, target);
113960 sqlite3VdbeAddOp1(v, OP_ClrSubtype, target);
113961 return target;
@@ -114120,11 +114364,11 @@
114120 if( db->mallocFailed ){
114121 sqlite3ExprDelete(db, pDel);
114122 break;
114123 }
114124 testcase( pX->op==TK_COLUMN );
114125 exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114126 testcase( regFree1==0 );
114127 memset(&opCompare, 0, sizeof(opCompare));
114128 opCompare.op = TK_EQ;
114129 opCompare.pLeft = pDel;
114130 pTest = &opCompare;
@@ -114174,19 +114418,18 @@
114174 if( pExpr->affExpr==OE_Abort ){
114175 sqlite3MayAbort(pParse);
114176 }
114177 assert( !ExprHasProperty(pExpr, EP_IntValue) );
114178 if( pExpr->affExpr==OE_Ignore ){
114179 sqlite3VdbeAddOp4(
114180 v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
114181 VdbeCoverage(v);
114182 }else{
114183 sqlite3HaltConstraint(pParse,
 
114184 pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
114185 pExpr->affExpr, pExpr->u.zToken, 0, 0);
114186 }
114187
114188 break;
114189 }
114190 #endif
114191 }
114192 sqlite3ReleaseTempReg(pParse, regFree1);
@@ -114471,11 +114714,11 @@
114471 compLeft.pLeft = pDel;
114472 compLeft.pRight = pExpr->x.pList->a[0].pExpr;
114473 compRight.op = TK_LE;
114474 compRight.pLeft = pDel;
114475 compRight.pRight = pExpr->x.pList->a[1].pExpr;
114476 exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114477 if( xJump ){
114478 xJump(pParse, &exprAnd, dest, jumpIfNull);
114479 }else{
114480 /* Mark the expression is being from the ON or USING clause of a join
114481 ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
@@ -115549,24 +115792,22 @@
115549 if( pExpr->op!=TK_AGG_FUNCTION ){
115550 if( iAgg<pAggInfo->nColumn
115551 && pAggInfo->aCol[iAgg].pCExpr==pExpr
115552 ){
115553 pExpr = sqlite3ExprDup(db, pExpr, 0);
115554 if( pExpr ){
115555 pAggInfo->aCol[iAgg].pCExpr = pExpr;
115556 sqlite3ExprDeferredDelete(pParse, pExpr);
115557 }
115558 }
115559 }else{
115560 assert( pExpr->op==TK_AGG_FUNCTION );
115561 if( ALWAYS(iAgg<pAggInfo->nFunc)
115562 && pAggInfo->aFunc[iAgg].pFExpr==pExpr
115563 ){
115564 pExpr = sqlite3ExprDup(db, pExpr, 0);
115565 if( pExpr ){
115566 pAggInfo->aFunc[iAgg].pFExpr = pExpr;
115567 sqlite3ExprDeferredDelete(pParse, pExpr);
115568 }
115569 }
115570 }
115571 }
115572 return WRC_Continue;
@@ -124153,13 +124394,10 @@
124153 if( p->tabFlags & TF_HasGenerated ){
124154 sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
124155 sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
124156 db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
124157 }
124158 sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
124159 sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)",
124160 db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
124161 }
124162
124163 /* Add the table to the in-memory representation of the database.
124164 */
124165 if( db->init.busy ){
@@ -124293,12 +124531,13 @@
124293 #endif /* SQLITE_OMIT_VIEW */
124294
124295 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
124296 /*
124297 ** The Table structure pTable is really a VIEW. Fill in the names of
124298 ** the columns of the view in the pTable structure. Return the number
124299 ** of errors. If an error is seen leave an error message in pParse->zErrMsg.
 
124300 */
124301 static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
124302 Table *pSelTab; /* A fake table from which we get the result set */
124303 Select *pSel; /* Copy of the SELECT that implements the view */
124304 int nErr = 0; /* Number of errors encountered */
@@ -124417,11 +124656,11 @@
124417 pTable->pSchema->schemaFlags |= DB_UnresetViews;
124418 if( db->mallocFailed ){
124419 sqlite3DeleteColumnNames(db, pTable);
124420 }
124421 #endif /* SQLITE_OMIT_VIEW */
124422 return nErr;
124423 }
124424 SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
124425 assert( pTable!=0 );
124426 if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0;
124427 return viewGetColumnNames(pParse, pTable);
@@ -130715,10 +130954,12 @@
130715 StrAccum *pAccum = &pGCC->str;
130716 if( pAccum->accError==SQLITE_TOOBIG ){
130717 sqlite3_result_error_toobig(context);
130718 }else if( pAccum->accError==SQLITE_NOMEM ){
130719 sqlite3_result_error_nomem(context);
 
 
130720 }else{
130721 const char *zText = sqlite3_str_value(pAccum);
130722 sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
130723 }
130724 }
@@ -131054,10 +131295,11 @@
131054 UNUSED_PARAMETER(argc);
131055 assert( argc==3 );
131056 x = sqlite3_value_double(argv[0]);
131057 y = sqlite3_value_int(argv[1]);
131058 z = sqlite3_value_int(argv[2]);
 
131059 sqlite3FpDecode(&s, x, y, z);
131060 if( s.isSpecial==2 ){
131061 sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
131062 }else{
131063 sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP);
@@ -132595,11 +132837,12 @@
132595 if( action==OE_Restrict ){
132596 int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
132597 SrcList *pSrc;
132598 Expr *pRaise;
132599
132600 pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
 
132601 if( pRaise ){
132602 pRaise->affExpr = OE_Abort;
132603 }
132604 pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
132605 if( pSrc ){
@@ -135934,11 +136177,14 @@
135934 ** further downstream. */
135935 return 0; /* Corrupt schema - two indexes on the same btree */
135936 }
135937 }
135938 #ifndef SQLITE_OMIT_CHECK
135939 if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
 
 
 
135940 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
135941 }
135942 #endif
135943 #ifndef SQLITE_OMIT_FOREIGN_KEY
135944 /* Disallow the transfer optimization if the destination table contains
@@ -140282,11 +140528,11 @@
140282 pParse->nMem = 6;
140283
140284 /* Set the maximum error count */
140285 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140286 if( zRight ){
140287 if( sqlite3GetInt32(zRight, &mxErr) ){
140288 if( mxErr<=0 ){
140289 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140290 }
140291 }else{
140292 pObjTab = sqlite3LocateTable(pParse, 0, zRight,
@@ -141490,10 +141736,11 @@
141490 /* Clear all content from pragma virtual table cursor. */
141491 static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
141492 int i;
141493 sqlite3_finalize(pCsr->pPragma);
141494 pCsr->pPragma = 0;
 
141495 for(i=0; i<ArraySize(pCsr->azArg); i++){
141496 sqlite3_free(pCsr->azArg[i]);
141497 pCsr->azArg[i] = 0;
141498 }
141499 }
@@ -142290,11 +142537,17 @@
142290 SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
142291 Parse *pParse, /* Destroy when this Parser finishes */
142292 void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
142293 void *pPtr /* Pointer to object to be cleaned up */
142294 ){
142295 ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
 
 
 
 
 
 
142296 if( pCleanup ){
142297 pCleanup->pNext = pParse->pCleanup;
142298 pParse->pCleanup = pCleanup;
142299 pCleanup->pPtr = pPtr;
142300 pCleanup->xCleanup = xCleanup;
@@ -144116,16 +144369,22 @@
144116 ** ORDER BY in this case since the order of entries in the set
144117 ** does not matter. But there might be a LIMIT clause, in which
144118 ** case the order does matter */
144119 pushOntoSorter(
144120 pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
 
144121 }else{
144122 int r1 = sqlite3GetTempReg(pParse);
144123 assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
144124 sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
144125 r1, pDest->zAffSdst, nResultCol);
144126 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
 
 
 
 
 
144127 sqlite3ReleaseTempReg(pParse, r1);
144128 }
144129 break;
144130 }
144131
@@ -145063,12 +145322,11 @@
145063 Expr *p;
145064 struct ExprList_item *a;
145065 NameContext sNC;
145066
145067 assert( pSelect!=0 );
145068 testcase( (pSelect->selFlags & SF_Resolved)==0 );
145069 assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT );
145070 assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
145071 assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
145072 if( db->mallocFailed || IN_RENAME_OBJECT ) return;
145073 while( pSelect->pPrior ) pSelect = pSelect->pPrior;
145074 a = pSelect->pEList->a;
@@ -145075,21 +145333,26 @@
145075 memset(&sNC, 0, sizeof(sNC));
145076 sNC.pSrcList = pSelect->pSrc;
145077 for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
145078 const char *zType;
145079 i64 n;
 
 
145080 pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
145081 p = a[i].pExpr;
145082 /* pCol->szEst = ... // Column size est for SELECT tables never used */
145083 pCol->affinity = sqlite3ExprAffinity(p);
 
 
 
 
 
145084 if( pCol->affinity<=SQLITE_AFF_NONE ){
145085 pCol->affinity = aff;
145086 }
145087 if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
145088 int m = 0;
145089 Select *pS2;
145090 for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
145091 m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
145092 }
145093 if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
145094 pCol->affinity = SQLITE_AFF_BLOB;
145095 }else
@@ -145115,16 +145378,16 @@
145115 }
145116 }
145117 }
145118 }
145119 if( zType ){
145120 i64 m = sqlite3Strlen30(zType);
145121 n = sqlite3Strlen30(pCol->zCnName);
145122 pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
145123 pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
145124 if( pCol->zCnName ){
145125 memcpy(&pCol->zCnName[n+1], zType, m+1);
145126 pCol->colFlags |= COLFLAG_HASTYPE;
145127 }
145128 }
145129 pColl = sqlite3ExprCollSeq(pParse, p);
145130 if( pColl ){
@@ -145227,11 +145490,11 @@
145227 assert( pLimit->op==TK_LIMIT );
145228 assert( pLimit->pLeft!=0 );
145229 p->iLimit = iLimit = ++pParse->nMem;
145230 v = sqlite3GetVdbe(pParse);
145231 assert( v!=0 );
145232 if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
145233 sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
145234 VdbeComment((v, "LIMIT counter"));
145235 if( n==0 ){
145236 sqlite3VdbeGoto(v, iBreak);
145237 }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
@@ -145707,11 +145970,11 @@
145707 testcase( rc!=SQLITE_OK );
145708 pDelete = p->pPrior;
145709 p->pPrior = pPrior;
145710 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
145711 if( p->pLimit
145712 && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
145713 && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
145714 ){
145715 p->nSelectRow = sqlite3LogEst((u64)nLimit);
145716 }
145717 if( addr ){
@@ -146051,10 +146314,15 @@
146051 r1 = sqlite3GetTempReg(pParse);
146052 sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
146053 r1, pDest->zAffSdst, pIn->nSdst);
146054 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
146055 pIn->iSdst, pIn->nSdst);
 
 
 
 
 
146056 sqlite3ReleaseTempReg(pParse, r1);
146057 break;
146058 }
146059
146060 /* If this is a scalar select that is part of an expression, then
@@ -147798,10 +148066,22 @@
147798 ** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
147799 ** WHERE x=5 AND y=10;
147800 **
147801 ** The hope is that the terms added to the inner query will make it more
147802 ** efficient.
 
 
 
 
 
 
 
 
 
 
 
 
147803 **
147804 ** Do not attempt this optimization if:
147805 **
147806 ** (1) (** This restriction was removed on 2017-09-29. We used to
147807 ** disallow this optimization for aggregate subqueries, but now
@@ -147864,14 +148144,14 @@
147864 ** (9b) The subquery is to the right of the ON/USING clause
147865 **
147866 ** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
147867 ** clause and the subquery.
147868 **
147869 ** Without this restriction, the push-down optimization might move
147870 ** the ON/USING filter expression from the left side of a RIGHT JOIN
147871 ** over to the right side, which leads to incorrect answers. See
147872 ** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
147873 **
147874 ** (10) The inner query is not the right-hand table of a RIGHT JOIN.
147875 **
147876 ** (11) The subquery is not a VALUES clause
147877 **
@@ -147999,11 +148279,11 @@
147999 return 0; /* Restriction (12) */
148000 }
148001 }
148002 #endif
148003
148004 if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
148005 nChng++;
148006 pSubq->selFlags |= SF_PushDown;
148007 while( pSubq ){
148008 SubstContext x;
148009 pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -149134,12 +149414,11 @@
149134 SrcItem *pFrom;
149135
149136 if( p->selFlags & SF_HasTypeInfo ) return;
149137 p->selFlags |= SF_HasTypeInfo;
149138 pParse = pWalker->pParse;
149139 testcase( (p->selFlags & SF_Resolved)==0 );
149140 assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT );
149141 pTabList = p->pSrc;
149142 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
149143 Table *pTab = pFrom->pTab;
149144 assert( pTab!=0 );
149145 if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
@@ -150259,17 +150538,20 @@
150259 ** (5) The ORDER BY isn't going to accomplish anything because
150260 ** one of:
150261 ** (a) The outer query has a different ORDER BY clause
150262 ** (b) The subquery is part of a join
150263 ** See forum post 062d576715d277c8
 
 
 
150264 **
150265 ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
150266 */
150267 if( pSub->pOrderBy!=0
150268 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
150269 && pSub->pLimit==0 /* Condition (1) */
150270 && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
150271 && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
150272 && OptimizationEnabled(db, SQLITE_OmitOrderBy)
150273 ){
150274 TREETRACE(0x800,pParse,p,
150275 ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
@@ -150428,11 +150710,11 @@
150428 sqlite3TreeViewSelect(0, p, 0);
150429 }
150430 #endif
150431 assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
150432 }else{
150433 TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
150434 }
150435
150436 /* Convert unused result columns of the subquery into simple NULL
150437 ** expressions, to avoid unneeded searching and computation.
150438 */
@@ -150571,16 +150853,22 @@
150571 ** written the query must use a temp-table for at least one of the ORDER
150572 ** BY and DISTINCT, and an index or separate temp-table for the other.
150573 */
150574 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
150575 && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
 
150576 #ifndef SQLITE_OMIT_WINDOWFUNC
150577 && p->pWin==0
150578 #endif
150579 ){
150580 p->selFlags &= ~SF_Distinct;
150581 pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
 
 
 
 
 
150582 p->selFlags |= SF_Aggregate;
150583 /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
150584 ** the sDistinct.isTnct is still set. Hence, isTnct represents the
150585 ** original setting of the SF_Distinct flag, not the current setting */
150586 assert( sDistinct.isTnct );
@@ -151039,16 +151327,29 @@
151039 if( groupBySort ){
151040 sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
151041 sortOut, sortPTab);
151042 }
151043 for(j=0; j<pGroupBy->nExpr; j++){
 
 
151044 if( groupBySort ){
151045 sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
151046 }else{
151047 pAggInfo->directMode = 1;
151048 sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
151049 }
 
 
 
 
 
 
 
 
 
 
 
151050 }
151051 sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
151052 (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
151053 addr1 = sqlite3VdbeCurrentAddr(v);
151054 sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
@@ -151060,13 +151361,13 @@
151060 ** This code copies current group by terms in b0,b1,b2,...
151061 ** over to a0,a1,a2. It then calls the output subroutine
151062 ** and resets the aggregate accumulator registers in preparation
151063 ** for the next GROUP BY batch.
151064 */
151065 sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
151066 sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
151067 VdbeComment((v, "output one row"));
 
151068 sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
151069 VdbeComment((v, "check abort flag"));
151070 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
151071 VdbeComment((v, "reset accumulator"));
151072
@@ -152495,10 +152796,76 @@
152495 }
152496 }
152497 }
152498 return pNew;
152499 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152500
152501 /*
152502 ** Generate code for the RETURNING trigger. Unlike other triggers
152503 ** that invoke a subprogram in the bytecode, the code for RETURNING
152504 ** is generated in-line.
@@ -152532,10 +152899,11 @@
152532 memset(&sFrom, 0, sizeof(sFrom));
152533 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
152534 sSelect.pSrc = &sFrom;
152535 sFrom.nSrc = 1;
152536 sFrom.a[0].pTab = pTab;
 
152537 sFrom.a[0].iCursor = -1;
152538 sqlite3SelectPrep(pParse, &sSelect, 0);
152539 if( pParse->nErr==0 ){
152540 assert( db->mallocFailed==0 );
152541 sqlite3GenerateColumnNames(pParse, &sSelect);
@@ -152558,10 +152926,11 @@
152558 && ALWAYS(!db->mallocFailed)
152559 ){
152560 int i;
152561 int nCol = pNew->nExpr;
152562 int reg = pParse->nMem+1;
 
152563 pParse->nMem += nCol+2;
152564 pReturning->iRetReg = reg;
152565 for(i=0; i<nCol; i++){
152566 Expr *pCol = pNew->a[i].pExpr;
152567 assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
@@ -153959,10 +154328,13 @@
153959 }else{
153960 sqlite3VdbeAddOp2(v, OP_Null, 0, k);
153961 }
153962 }
153963 if( chngRowid==0 && pPk==0 ){
 
 
 
153964 sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
153965 }
153966 }
153967
153968 /* Populate the array of registers beginning at regNew with the new
@@ -155985,11 +156357,14 @@
155985 */
155986 z = (const unsigned char*)zCreateTable;
155987 for(i=0; aKeyword[i]; i++){
155988 int tokenType = 0;
155989 do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
155990 if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT;
 
 
 
155991 }
155992
155993 sqlite3_mutex_enter(db->mutex);
155994 pCtx = db->pVtabCtx;
155995 if( !pCtx || pCtx->bDeclared ){
@@ -156709,10 +157084,12 @@
156709 u16 nLTerm; /* Number of entries in aLTerm[] */
156710 u16 nSkip; /* Number of NULL aLTerm[] entries */
156711 /**** whereLoopXfer() copies fields above ***********************/
156712 # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
156713 u16 nLSlot; /* Number of slots allocated for aLTerm[] */
 
 
156714 WhereTerm **aLTerm; /* WhereTerms used */
156715 WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
156716 WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
156717 };
156718
@@ -157031,10 +157408,11 @@
157031 u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
157032 unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
157033 unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
157034 unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
157035 unsigned sorted :1; /* True if really sorted (not just grouped) */
 
157036 LogEst nRowOut; /* Estimated number of output rows */
157037 int iTop; /* The very beginning of the WHERE loop */
157038 int iEndWhere; /* End of the WHERE clause itself */
157039 WhereLoop *pLoops; /* List of all WhereLoop objects */
157040 WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
@@ -157388,11 +157766,12 @@
157388 }
157389 #endif
157390 zMsg = sqlite3StrAccumFinish(&str);
157391 sqlite3ExplainBreakpoint("",zMsg);
157392 ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
157393 pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
 
157394 }
157395 return ret;
157396 }
157397
157398 /*
@@ -157630,10 +158009,43 @@
157630 zAff[i] = SQLITE_AFF_BLOB;
157631 }
157632 }
157633 }
157634
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157635
157636 /*
157637 ** pX is an expression of the form: (vector) IN (SELECT ...)
157638 ** In other words, it is a vector IN operator with a SELECT clause on the
157639 ** LHS. But not all terms in the vector are indexable and the terms might
@@ -157693,10 +158105,11 @@
157693 assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
157694 iField = pLoop->aLTerm[i]->u.x.iField - 1;
157695 if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
157696 pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
157697 pOrigRhs->a[iField].pExpr = 0;
 
157698 if( pOrigLhs ){
157699 assert( pOrigLhs->a[iField].pExpr!=0 );
157700 pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
157701 pOrigLhs->a[iField].pExpr = 0;
157702 }
@@ -157715,22 +158128,20 @@
157715 Expr *p = pLhs->a[0].pExpr;
157716 pLhs->a[0].pExpr = 0;
157717 sqlite3ExprDelete(db, pNew->pLeft);
157718 pNew->pLeft = p;
157719 }
157720 if( pSelect->pOrderBy ){
157721 /* If the SELECT statement has an ORDER BY clause, zero the
157722 ** iOrderByCol variables. These are set to non-zero when an
157723 ** ORDER BY term exactly matches one of the terms of the
157724 ** result-set. Since the result-set of the SELECT statement may
157725 ** have been modified or reordered, these variables are no longer
157726 ** set correctly. Since setting them is just an optimization,
157727 ** it's easiest just to zero them here. */
157728 ExprList *pOrderBy = pSelect->pOrderBy;
157729 for(i=0; i<pOrderBy->nExpr; i++){
157730 pOrderBy->a[i].u.x.iOrderByCol = 0;
157731 }
157732 }
157733
157734 #if 0
157735 printf("For indexing, change the IN expr:\n");
157736 sqlite3TreeViewExpr(0, pX, 0);
@@ -157740,10 +158151,151 @@
157740 }
157741 }
157742 return pNew;
157743 }
157744
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157745
157746 /*
157747 ** Generate code for a single equality term of the WHERE clause. An equality
157748 ** term can be either X=expr or X IN (...). pTerm is the term to be
157749 ** coded.
@@ -157765,138 +158317,24 @@
157765 int iEq, /* Index of the equality term within this level */
157766 int bRev, /* True for reverse-order IN operations */
157767 int iTarget /* Attempt to leave results in this register */
157768 ){
157769 Expr *pX = pTerm->pExpr;
157770 Vdbe *v = pParse->pVdbe;
157771 int iReg; /* Register holding results */
157772
157773 assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
157774 assert( iTarget>0 );
157775 if( pX->op==TK_EQ || pX->op==TK_IS ){
157776 iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
157777 }else if( pX->op==TK_ISNULL ){
157778 iReg = iTarget;
157779 sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
157780 #ifndef SQLITE_OMIT_SUBQUERY
157781 }else{
157782 int eType = IN_INDEX_NOOP;
157783 int iTab;
157784 struct InLoop *pIn;
157785 WhereLoop *pLoop = pLevel->pWLoop;
157786 int i;
157787 int nEq = 0;
157788 int *aiMap = 0;
157789
157790 if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
157791 && pLoop->u.btree.pIndex!=0
157792 && pLoop->u.btree.pIndex->aSortOrder[iEq]
157793 ){
157794 testcase( iEq==0 );
157795 testcase( bRev );
157796 bRev = !bRev;
157797 }
157798 assert( pX->op==TK_IN );
157799 iReg = iTarget;
157800
157801 for(i=0; i<iEq; i++){
157802 if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
157803 disableTerm(pLevel, pTerm);
157804 return iTarget;
157805 }
157806 }
157807 for(i=iEq;i<pLoop->nLTerm; i++){
157808 assert( pLoop->aLTerm[i]!=0 );
157809 if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
157810 }
157811
157812 iTab = 0;
157813 if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
157814 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
157815 }else{
157816 Expr *pExpr = pTerm->pExpr;
157817 if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
157818 sqlite3 *db = pParse->db;
157819 pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
157820 if( !db->mallocFailed ){
157821 aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
157822 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
157823 pExpr->iTable = iTab;
157824 }
157825 sqlite3ExprDelete(db, pX);
157826 }else{
157827 int n = sqlite3ExprVectorSize(pX->pLeft);
157828 aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
157829 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
157830 }
157831 pX = pExpr;
157832 }
157833
157834 if( eType==IN_INDEX_INDEX_DESC ){
157835 testcase( bRev );
157836 bRev = !bRev;
157837 }
157838 sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
157839 VdbeCoverageIf(v, bRev);
157840 VdbeCoverageIf(v, !bRev);
157841
157842 assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
157843 pLoop->wsFlags |= WHERE_IN_ABLE;
157844 if( pLevel->u.in.nIn==0 ){
157845 pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
157846 }
157847 if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
157848 pLoop->wsFlags |= WHERE_IN_EARLYOUT;
157849 }
157850
157851 i = pLevel->u.in.nIn;
157852 pLevel->u.in.nIn += nEq;
157853 pLevel->u.in.aInLoop =
157854 sqlite3WhereRealloc(pTerm->pWC->pWInfo,
157855 pLevel->u.in.aInLoop,
157856 sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
157857 pIn = pLevel->u.in.aInLoop;
157858 if( pIn ){
157859 int iMap = 0; /* Index in aiMap[] */
157860 pIn += i;
157861 for(i=iEq;i<pLoop->nLTerm; i++){
157862 if( pLoop->aLTerm[i]->pExpr==pX ){
157863 int iOut = iReg + i - iEq;
157864 if( eType==IN_INDEX_ROWID ){
157865 pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
157866 }else{
157867 int iCol = aiMap ? aiMap[iMap++] : 0;
157868 pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
157869 }
157870 sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
157871 if( i==iEq ){
157872 pIn->iCur = iTab;
157873 pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
157874 if( iEq>0 ){
157875 pIn->iBase = iReg - i;
157876 pIn->nPrefix = i;
157877 }else{
157878 pIn->nPrefix = 0;
157879 }
157880 }else{
157881 pIn->eEndLoopOp = OP_Noop;
157882 }
157883 pIn++;
157884 }
157885 }
157886 testcase( iEq>0
157887 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
157888 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
157889 if( iEq>0
157890 && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
157891 ){
157892 sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
157893 }
157894 }else{
157895 pLevel->u.in.nIn = 0;
157896 }
157897 sqlite3DbFree(pParse->db, aiMap);
157898 #endif
157899 }
157900
157901 /* As an optimization, try to disable the WHERE clause term that is
157902 ** driving the index as it will always be true. The correct answer is
@@ -158506,10 +158944,31 @@
158506 }
158507 pLevel->regFilter = 0;
158508 pLevel->addrBrk = 0;
158509 }
158510 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158511
158512 /*
158513 ** Generate code for the start of the iLevel-th loop in the WHERE clause
158514 ** implementation described by pWInfo.
158515 */
@@ -158585,11 +159044,11 @@
158585 || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
158586 );
158587 if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
158588 pLevel->iLeftJoin = ++pParse->nMem;
158589 sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
158590 VdbeComment((v, "init LEFT JOIN no-match flag"));
158591 }
158592
158593 /* Compute a safe address to jump to if we discover that the table for
158594 ** this loop is empty and can never contribute content. */
158595 for(j=iLevel; j>0; j--){
@@ -159254,11 +159713,13 @@
159254 ** a LEFT JOIN: */
159255 assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
159256 }
159257
159258 /* Record the instruction used to terminate the loop. */
159259 if( pLoop->wsFlags & WHERE_ONEROW ){
 
 
159260 pLevel->op = OP_Noop;
159261 }else if( bRev ){
159262 pLevel->op = OP_Prev;
159263 }else{
159264 pLevel->op = OP_Next;
@@ -159644,10 +160105,16 @@
159644 ** iLoop==2: Code remaining expressions that do not contain correlated
159645 ** sub-queries.
159646 ** iLoop==3: Code all remaining expressions.
159647 **
159648 ** An effort is made to skip unnecessary iterations of the loop.
 
 
 
 
 
 
159649 */
159650 iLoop = (pIdx ? 1 : 2);
159651 do{
159652 int iNext = 0; /* Next value for iLoop */
159653 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
@@ -159894,11 +160361,20 @@
159894 ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
159895 sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
159896 pRJ->regReturn);
159897 for(k=0; k<iLevel; k++){
159898 int iIdxCur;
 
 
 
159899 mAll |= pWInfo->a[k].pWLoop->maskSelf;
 
 
 
 
 
 
159900 sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
159901 iIdxCur = pWInfo->a[k].iIdxCur;
159902 if( iIdxCur ){
159903 sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
159904 }
@@ -160063,11 +160539,16 @@
160063 static int allowedOp(int op){
160064 assert( TK_GT>TK_EQ && TK_GT<TK_GE );
160065 assert( TK_LT>TK_EQ && TK_LT<TK_GE );
160066 assert( TK_LE>TK_EQ && TK_LE<TK_GE );
160067 assert( TK_GE==TK_EQ+4 );
160068 return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
 
 
 
 
 
160069 }
160070
160071 /*
160072 ** Commute a comparison operator. Expressions of the form "X op Y"
160073 ** are converted into "Y op X".
@@ -160096,19 +160577,20 @@
160096 ** Translate from TK_xx operator to WO_xx bitmask.
160097 */
160098 static u16 operatorMask(int op){
160099 u16 c;
160100 assert( allowedOp(op) );
160101 if( op==TK_IN ){
 
 
 
160102 c = WO_IN;
160103 }else if( op==TK_ISNULL ){
160104 c = WO_ISNULL;
160105 }else if( op==TK_IS ){
 
160106 c = WO_IS;
160107 }else{
160108 assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
160109 c = (u16)(WO_EQ<<(op-TK_EQ));
160110 }
160111 assert( op!=TK_ISNULL || c==WO_ISNULL );
160112 assert( op!=TK_IN || c==WO_IN );
160113 assert( op!=TK_EQ || c==WO_EQ );
160114 assert( op!=TK_LT || c==WO_LT );
@@ -160391,10 +160873,17 @@
160391 *ppLeft = pCol;
160392 return 1;
160393 }
160394 }
160395 }
 
 
 
 
 
 
 
160396 }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
160397 int res = 0;
160398 Expr *pLeft = pExpr->pLeft;
160399 Expr *pRight = pExpr->pRight;
160400 assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
@@ -161532,11 +162021,11 @@
161532 Parse *pParse = pWC->pWInfo->pParse;
161533 sqlite3 *db = pParse->db;
161534 Expr *pNew;
161535 int iVal = 0;
161536
161537 if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
161538 Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
161539 if( pVal==0 ) return;
161540 ExprSetProperty(pVal, EP_IntValue);
161541 pVal->u.iValue = iVal;
161542 pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
@@ -161600,10 +162089,11 @@
161600 ** will only be added if each of the child terms passes the
161601 ** (leftCursor==iCsr) test below. */
161602 continue;
161603 }
161604 if( pWC->a[ii].leftCursor!=iCsr ) return;
 
161605 }
161606
161607 /* Check condition (5). Return early if it is not met. */
161608 if( pOrderBy ){
161609 for(ii=0; ii<pOrderBy->nExpr; ii++){
@@ -161614,16 +162104,18 @@
161614 }
161615 }
161616
161617 /* All conditions are met. Add the terms to the where-clause object. */
161618 assert( p->pLimit->op==TK_LIMIT );
161619 whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
161620 iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
161621 if( p->iOffset>0 ){
161622 whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
161623 iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
161624 }
 
 
 
 
161625 }
161626 }
161627
161628 /*
161629 ** Initialize a preallocated WhereClause structure.
@@ -162136,10 +162628,46 @@
162136 if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
162137 return p;
162138 }
162139 return 0;
162140 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162141
162142 /*
162143 ** Advance to the next WhereTerm that matches according to the criteria
162144 ** established when the pScan object was initialized by whereScanInit().
162145 ** Return NULL if there are no more matching WhereTerms.
@@ -162187,20 +162715,28 @@
162187 }
162188 }
162189 if( (pTerm->eOperator & pScan->opMask)!=0 ){
162190 /* Verify the affinity and collating sequence match */
162191 if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
162192 CollSeq *pColl;
162193 Parse *pParse = pWC->pWInfo->pParse;
162194 pX = pTerm->pExpr;
162195 if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
162196 continue;
 
 
 
 
 
 
 
 
 
 
162197 }
162198 assert(pX->pLeft);
162199 pColl = sqlite3ExprCompareCollSeq(pParse, pX);
162200 if( pColl==0 ) pColl = pParse->db->pDfltColl;
162201 if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
162202 continue;
162203 }
162204 }
162205 if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
162206 && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
@@ -162631,10 +163167,44 @@
162631 return 0;
162632 }
162633 return 1;
162634 }
162635
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162636
162637
162638 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
162639 /*
162640 ** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -162645,10 +163215,12 @@
162645 const WhereTerm *pTerm, /* WHERE clause term to check */
162646 const SrcItem *pSrc, /* Table we are trying to access */
162647 const Bitmask notReady /* Tables in outer loops of the join */
162648 ){
162649 char aff;
 
 
162650 if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
162651 if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
162652 assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
162653 if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
162654 && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
@@ -162655,15 +163227,16 @@
162655 ){
162656 return 0; /* See https://sqlite.org/forum/forumpost/51e6959f61 */
162657 }
162658 if( (pTerm->prereqRight & notReady)!=0 ) return 0;
162659 assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
162660 if( pTerm->u.x.leftColumn<0 ) return 0;
162661 aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
 
162662 if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
162663 testcase( pTerm->pExpr->op==TK_IS );
162664 return 1;
162665 }
162666 #endif
162667
162668
162669 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -162777,11 +163350,11 @@
162777 Expr *pExpr = pTerm->pExpr;
162778 /* Make the automatic index a partial index if there are terms in the
162779 ** WHERE clause (or the ON clause of a LEFT join) that constrain which
162780 ** rows of the target table (pSrc) that can be used. */
162781 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
162782 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
162783 ){
162784 pPartial = sqlite3ExprAnd(pParse, pPartial,
162785 sqlite3ExprDup(pParse->db, pExpr, 0));
162786 }
162787 if( termCanDriveIndex(pTerm, pSrc, notReady) ){
@@ -163046,11 +163619,11 @@
163046 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
163047 pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
163048 for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
163049 Expr *pExpr = pTerm->pExpr;
163050 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
163051 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
163052 ){
163053 sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
163054 }
163055 }
163056 if( pLoop->wsFlags & WHERE_IPK ){
@@ -163100,10 +163673,24 @@
163100 pParse->pIdxPartExpr = saved_pIdxPartExpr;
163101 }
163102
163103
163104 #ifndef SQLITE_OMIT_VIRTUALTABLE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163105 /*
163106 ** Allocate and populate an sqlite3_index_info structure. It is the
163107 ** responsibility of the caller to eventually release the structure
163108 ** by passing the pointer returned by this function to freeIndexInfo().
163109 */
@@ -163126,10 +163713,11 @@
163126 sqlite3_index_info *pIdxInfo;
163127 u16 mNoOmit = 0;
163128 const Table *pTab;
163129 int eDistinct = 0;
163130 ExprList *pOrderBy = pWInfo->pOrderBy;
 
163131
163132 assert( pSrc!=0 );
163133 pTab = pSrc->pTab;
163134 assert( pTab!=0 );
163135 assert( IsVirtual(pTab) );
@@ -163136,32 +163724,34 @@
163136
163137 /* Find all WHERE clause constraints referring to this virtual table.
163138 ** Mark each term with the TERM_OK flag. Set nTerm to the number of
163139 ** terms found.
163140 */
163141 for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
163142 pTerm->wtFlags &= ~TERM_OK;
163143 if( pTerm->leftCursor != pSrc->iCursor ) continue;
163144 if( pTerm->prereqRight & mUnusable ) continue;
163145 assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
163146 testcase( pTerm->eOperator & WO_IN );
163147 testcase( pTerm->eOperator & WO_ISNULL );
163148 testcase( pTerm->eOperator & WO_IS );
163149 testcase( pTerm->eOperator & WO_ALL );
163150 if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
163151 if( pTerm->wtFlags & TERM_VNULL ) continue;
163152
163153 assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
163154 assert( pTerm->u.x.leftColumn>=XN_ROWID );
163155 assert( pTerm->u.x.leftColumn<pTab->nCol );
163156 if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
163157 && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
163158 ){
163159 continue;
163160 }
163161 nTerm++;
163162 pTerm->wtFlags |= TERM_OK;
 
 
163163 }
163164
163165 /* If the ORDER BY clause contains only columns in the current
163166 ** virtual table then allocate space for the aOrderBy part of
163167 ** the sqlite3_index_info structure.
@@ -163207,11 +163797,11 @@
163207 /* No matches cause a break out of the loop */
163208 break;
163209 }
163210 if( i==n ){
163211 nOrderBy = n;
163212 if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){
163213 eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
163214 }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
163215 eDistinct = 1;
163216 }
163217 }
@@ -163236,53 +163826,56 @@
163236 pIdxInfo->aConstraintUsage = pUsage;
163237 pHidden->pWC = pWC;
163238 pHidden->pParse = pParse;
163239 pHidden->eDistinct = eDistinct;
163240 pHidden->mIn = 0;
163241 for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
163242 u16 op;
163243 if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
163244 pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
163245 pIdxCons[j].iTermOffset = i;
163246 op = pTerm->eOperator & WO_ALL;
163247 if( op==WO_IN ){
163248 if( (pTerm->wtFlags & TERM_SLICE)==0 ){
163249 pHidden->mIn |= SMASKBIT32(j);
163250 }
163251 op = WO_EQ;
163252 }
163253 if( op==WO_AUX ){
163254 pIdxCons[j].op = pTerm->eMatchOp;
163255 }else if( op & (WO_ISNULL|WO_IS) ){
163256 if( op==WO_ISNULL ){
163257 pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
163258 }else{
163259 pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
163260 }
163261 }else{
163262 pIdxCons[j].op = (u8)op;
163263 /* The direct assignment in the previous line is possible only because
163264 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
163265 ** following asserts verify this fact. */
163266 assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
163267 assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
163268 assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
163269 assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
163270 assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
163271 assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
163272
163273 if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
163274 && sqlite3ExprIsVector(pTerm->pExpr->pRight)
163275 ){
163276 testcase( j!=i );
163277 if( j<16 ) mNoOmit |= (1 << j);
163278 if( op==WO_LT ) pIdxCons[j].op = WO_LE;
163279 if( op==WO_GT ) pIdxCons[j].op = WO_GE;
163280 }
163281 }
163282
163283 j++;
 
 
 
163284 }
163285 assert( j==nTerm );
163286 pIdxInfo->nConstraint = j;
163287 for(i=j=0; i<nOrderBy; i++){
163288 Expr *pExpr = pOrderBy->a[i].pExpr;
@@ -163297,10 +163890,21 @@
163297 pIdxInfo->nOrderBy = j;
163298
163299 *pmNoOmit = mNoOmit;
163300 return pIdxInfo;
163301 }
 
 
 
 
 
 
 
 
 
 
 
163302
163303 /*
163304 ** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
163305 ** and possibly modified by xBestIndex methods.
163306 */
@@ -163313,10 +163917,11 @@
163313 assert( pHidden->pParse->db==db );
163314 for(i=0; i<pIdxInfo->nConstraint; i++){
163315 sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
163316 pHidden->aRhs[i] = 0;
163317 }
 
163318 sqlite3DbFree(db, pIdxInfo);
163319 }
163320
163321 /*
163322 ** The table object reference passed as the second argument to this function
@@ -164664,11 +165269,11 @@
164664 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
164665 ){
164666 Expr *pRight = pTerm->pExpr->pRight;
164667 int k = 0;
164668 testcase( pTerm->pExpr->op==TK_IS );
164669 if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
164670 k = 10;
164671 }else{
164672 k = 20;
164673 }
164674 if( iReduce<k ){
@@ -164961,11 +165566,11 @@
164961 assert( saved_nEq==pNew->u.btree.nEq );
164962 if( iCol==XN_ROWID
164963 || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
164964 ){
164965 if( iCol==XN_ROWID || pProbe->uniqNotNull
164966 || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
164967 ){
164968 pNew->wsFlags |= WHERE_ONEROW;
164969 }else{
164970 pNew->wsFlags |= WHERE_UNQ_WANTED;
164971 }
@@ -165087,14 +165692,17 @@
165087 }
165088 }
165089 }
165090 }
165091
165092 /* Set rCostIdx to the cost of visiting selected rows in index. Add
165093 ** it to pNew->rRun, which is currently set to the cost of the index
165094 ** seek only. Then, if this is a non-covering index, add the cost of
165095 ** visiting the rows in the main table. */
 
 
 
165096 assert( pSrc->pTab->szTabRow>0 );
165097 if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
165098 /* The pProbe->szIdxRow is low for an IPK table since the interior
165099 ** pages are small. Thus szIdxRow gives a good estimate of seek cost.
165100 ** But the leaf pages are full-size, so pProbe->szIdxRow would badly
@@ -165101,11 +165709,19 @@
165101 ** under-estimate the scanning cost. */
165102 rCostIdx = pNew->nOut + 16;
165103 }else{
165104 rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
165105 }
165106 pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
 
 
 
 
 
 
 
 
165107 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
165108 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
165109 }
165110 ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
165111
@@ -165836,10 +166452,25 @@
165836 static int isLimitTerm(WhereTerm *pTerm){
165837 assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
165838 return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
165839 && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
165840 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165841
165842 /*
165843 ** Argument pIdxInfo is already populated with all constraints that may
165844 ** be used by the virtual table identified by pBuilder->pNew->iTab. This
165845 ** function marks a subset of those constraints usable, invokes the
@@ -165887,11 +166518,11 @@
165887
165888 /* Set the usable flag on the subset of constraints identified by
165889 ** arguments mUsable and mExclude. */
165890 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
165891 for(i=0; i<nConstraint; i++, pIdxCons++){
165892 WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
165893 pIdxCons->usable = 0;
165894 if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
165895 && (pTerm->eOperator & mExclude)==0
165896 && (pbRetryLimit || !isLimitTerm(pTerm))
165897 ){
@@ -165918,10 +166549,11 @@
165918 /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
165919 ** that the particular combination of parameters provided is unusable.
165920 ** Make no entries in the loop table.
165921 */
165922 WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
 
165923 return SQLITE_OK;
165924 }
165925 return rc;
165926 }
165927
@@ -165935,22 +166567,21 @@
165935 if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
165936 WhereTerm *pTerm;
165937 int j = pIdxCons->iTermOffset;
165938 if( iTerm>=nConstraint
165939 || j<0
165940 || j>=pWC->nTerm
165941 || pNew->aLTerm[iTerm]!=0
165942 || pIdxCons->usable==0
165943 ){
165944 sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
165945 testcase( pIdxInfo->needToFreeIdxStr );
165946 return SQLITE_ERROR;
165947 }
165948 testcase( iTerm==nConstraint-1 );
165949 testcase( j==0 );
165950 testcase( j==pWC->nTerm-1 );
165951 pTerm = &pWC->a[j];
165952 pNew->prereq |= pTerm->prereqRight;
165953 assert( iTerm<pNew->nLSlot );
165954 pNew->aLTerm[iTerm] = pTerm;
165955 if( iTerm>mxTerm ) mxTerm = iTerm;
165956 testcase( iTerm==15 );
@@ -165977,22 +166608,25 @@
165977 pIdxInfo->orderByConsumed = 0;
165978 pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
165979 *pbIn = 1; assert( (mExclude & WO_IN)==0 );
165980 }
165981
 
 
165982 assert( pbRetryLimit || !isLimitTerm(pTerm) );
165983 if( isLimitTerm(pTerm) && *pbIn ){
 
 
 
165984 /* If there is an IN(...) term handled as an == (separate call to
165985 ** xFilter for each value on the RHS of the IN) and a LIMIT or
165986 ** OFFSET term handled as well, the plan is unusable. Set output
165987 ** variable *pbRetryLimit to true to tell the caller to retry with
165988 ** LIMIT and OFFSET disabled. */
165989 if( pIdxInfo->needToFreeIdxStr ){
165990 sqlite3_free(pIdxInfo->idxStr);
165991 pIdxInfo->idxStr = 0;
165992 pIdxInfo->needToFreeIdxStr = 0;
165993 }
165994 *pbRetryLimit = 1;
165995 return SQLITE_OK;
165996 }
165997 }
165998 }
@@ -166001,11 +166635,11 @@
166001 for(i=0; i<=mxTerm; i++){
166002 if( pNew->aLTerm[i]==0 ){
166003 /* The non-zero argvIdx values must be contiguous. Raise an
166004 ** error if they are not */
166005 sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
166006 testcase( pIdxInfo->needToFreeIdxStr );
166007 return SQLITE_ERROR;
166008 }
166009 }
166010 assert( pNew->nLTerm<=pNew->nLSlot );
166011 pNew->u.vtab.idxNum = pIdxInfo->idxNum;
@@ -166056,11 +166690,11 @@
166056 HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
166057 const char *zRet = 0;
166058 if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
166059 CollSeq *pC = 0;
166060 int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
166061 Expr *pX = pHidden->pWC->a[iTerm].pExpr;
166062 if( pX->pLeft ){
166063 pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
166064 }
166065 zRet = (pC ? pC->zName : sqlite3StrBINARY);
166066 }
@@ -166102,11 +166736,13 @@
166102 int rc = SQLITE_OK;
166103 if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
166104 rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
166105 }else{
166106 if( pH->aRhs[iCons]==0 ){
166107 WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
 
 
166108 rc = sqlite3ValueFromExpr(
166109 pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
166110 SQLITE_AFF_BLOB, &pH->aRhs[iCons]
166111 );
166112 testcase( rc!=SQLITE_OK );
@@ -166258,13 +166894,12 @@
166258 while( rc==SQLITE_OK ){
166259 int i;
166260 Bitmask mNext = ALLBITS;
166261 assert( mNext>0 );
166262 for(i=0; i<nConstraint; i++){
166263 Bitmask mThis = (
166264 pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
166265 );
166266 if( mThis>mPrev && mThis<mNext ) mNext = mThis;
166267 }
166268 mPrev = mNext;
166269 if( mNext==ALLBITS ) break;
166270 if( mNext==mBest || mNext==mBestNoIn ) continue;
@@ -166296,11 +166931,10 @@
166296 rc = whereLoopAddVirtualOne(
166297 pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
166298 }
166299 }
166300
166301 if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
166302 freeIndexInfo(pParse->db, p);
166303 WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
166304 return rc;
166305 }
166306 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166673,11 +167307,11 @@
166673 nColumn = pIndex->nColumn;
166674 assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
166675 assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
166676 || !HasRowid(pIndex->pTable));
166677 /* All relevant terms of the index must also be non-NULL in order
166678 ** for isOrderDistinct to be true. So the isOrderDistint value
166679 ** computed here might be a false positive. Corrections will be
166680 ** made at tag-20210426-1 below */
166681 isOrderDistinct = IsUniqueIndex(pIndex)
166682 && (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
166683 }
@@ -166964,10 +167598,87 @@
166964 if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
166965 }
166966 rSortCost += estLog(nRow);
166967 return rSortCost;
166968 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166969
166970 /*
166971 ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
166972 ** attempts to find the lowest cost path that visits each WhereLoop
166973 ** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -167000,17 +167711,29 @@
167000 char *pSpace; /* Temporary memory used by this routine */
167001 int nSpace; /* Bytes of space allocated at pSpace */
167002
167003 pParse = pWInfo->pParse;
167004 nLoop = pWInfo->nLevel;
167005 /* TUNING: For simple queries, only the best path is tracked.
167006 ** For 2-way joins, the 5 best paths are followed.
167007 ** For joins of 3 or more tables, track the 10 best paths */
167008 mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
167009 assert( nLoop<=pWInfo->pTabList->nSrc );
167010 WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
167011 nRowEst, pParse->nQueryLoop));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167012
167013 /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
167014 ** case the purpose of this call is to estimate the number of rows returned
167015 ** by the overall query. Once this estimate has been obtained, the caller
167016 ** will invoke this function a second time, passing the estimate as the
@@ -167089,11 +167812,14 @@
167089 continue;
167090 }
167091
167092 /* At this point, pWLoop is a candidate to be the next loop.
167093 ** Compute its cost */
167094 rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
 
 
 
167095 rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
167096 nOut = pFrom->nRow + pWLoop->nOut;
167097 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
167098 isOrdered = pFrom->isOrdered;
167099 if( isOrdered<0 ){
@@ -167134,10 +167860,11 @@
167134 **
167135 ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
167136 ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
167137 ** of legal values for isOrdered, -1..64.
167138 */
 
167139 for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
167140 if( pTo->maskLoop==maskNew
167141 && ((pTo->isOrdered^isOrdered)&0x80)==0
167142 ){
167143 testcase( jj==nTo-1 );
@@ -167250,20 +167977,32 @@
167250 }
167251 }
167252
167253 #ifdef WHERETRACE_ENABLED /* >=2 */
167254 if( sqlite3WhereTrace & 0x02 ){
 
 
167255 sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
167256 for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167257 sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
167258 wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
167259 pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
167260 if( pTo->isOrdered>0 ){
167261 sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
167262 }else{
167263 sqlite3DebugPrintf("\n");
167264 }
 
 
 
 
 
 
 
 
 
 
167265 }
167266 }
167267 #endif
167268
167269 /* Swap the roles of aFrom and aTo for the next generation */
@@ -167354,17 +168093,93 @@
167354 pWInfo->revMask = revMask;
167355 }
167356 }
167357 }
167358
167359
167360 pWInfo->nRowOut = pFrom->nRow;
167361
167362 /* Free temporary memory and return success */
167363 sqlite3StackFreeNN(pParse->db, pSpace);
167364 return SQLITE_OK;
167365 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167366
167367 /*
167368 ** Most queries use only a single table (they are not joins) and have
167369 ** simple == constraints against indexed fields. This routine attempts
167370 ** to plan those simple cases using much less ceremony than the
@@ -167530,10 +168345,14 @@
167530 ** might move from the right side to the left side of the RIGHT JOIN.
167531 ** Note: Due to (2), this condition can only arise if the table is
167532 ** the right-most table of a subquery that was flattened into the
167533 ** main query and that subquery was the right-hand operand of an
167534 ** inner join that held an ON or USING clause.
 
 
 
 
167535 **
167536 ** For example, given:
167537 **
167538 ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
167539 ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
@@ -167668,12 +168487,65 @@
167668 pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
167669 (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
167670 }
167671 }
167672 nSearch += pLoop->nOut;
 
167673 }
167674 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167675
167676 /*
167677 ** The index pIdx is used by a query and contains one or more expressions.
167678 ** In other words pIdx is an index on an expression. iIdxCur is the cursor
167679 ** number for the index and iDataCur is the cursor number for the corresponding
@@ -167696,37 +168568,23 @@
167696 assert( pIdx->bHasExpr );
167697 pTab = pIdx->pTable;
167698 for(i=0; i<pIdx->nColumn; i++){
167699 Expr *pExpr;
167700 int j = pIdx->aiColumn[i];
167701 int bMaybeNullRow;
167702 if( j==XN_EXPR ){
167703 pExpr = pIdx->aColExpr->a[i].pExpr;
167704 testcase( pTabItem->fg.jointype & JT_LEFT );
167705 testcase( pTabItem->fg.jointype & JT_RIGHT );
167706 testcase( pTabItem->fg.jointype & JT_LTORJ );
167707 bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
167708 }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
167709 pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
167710 bMaybeNullRow = 0;
167711 }else{
167712 continue;
167713 }
167714 if( sqlite3ExprIsConstant(0,pExpr) ) continue;
167715 if( pExpr->op==TK_FUNCTION ){
167716 /* Functions that might set a subtype should not be replaced by the
167717 ** value taken from an expression index since the index omits the
167718 ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
167719 int n;
167720 FuncDef *pDef;
167721 sqlite3 *db = pParse->db;
167722 assert( ExprUseXList(pExpr) );
167723 n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
167724 pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
167725 if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
167726 continue;
167727 }
167728 }
167729 p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
167730 if( p==0 ) break;
167731 p->pIENext = pParse->pIdxEpr;
167732 #ifdef WHERETRACE_ENABLED
@@ -167737,11 +168595,11 @@
167737 #endif
167738 p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
167739 p->iDataCur = pTabItem->iCursor;
167740 p->iIdxCur = iIdxCur;
167741 p->iIdxCol = i;
167742 p->bMaybeNullRow = bMaybeNullRow;
167743 if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
167744 p->aff = pIdx->zColAff[i];
167745 }
167746 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
167747 p->zIdxName = pIdx->zName;
@@ -167905,10 +168763,11 @@
167905 /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
167906 testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
167907 if( pOrderBy && pOrderBy->nExpr>=BMS ){
167908 pOrderBy = 0;
167909 wctrlFlags &= ~WHERE_WANT_DISTINCT;
 
167910 }
167911
167912 /* The number of tables in the FROM clause is limited by the number of
167913 ** bits in a Bitmask
167914 */
@@ -168144,11 +169003,12 @@
168144 WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
168145
168146 wherePathSolver(pWInfo, 0);
168147 if( db->mallocFailed ) goto whereBeginError;
168148 if( pWInfo->pOrderBy ){
168149 wherePathSolver(pWInfo, pWInfo->nRowOut+1);
 
168150 if( db->mallocFailed ) goto whereBeginError;
168151 }
168152
168153 /* TUNING: Assume that a DISTINCT clause on a subquery reduces
168154 ** the output size by a factor of 8 (LogEst -30).
@@ -168204,14 +169064,14 @@
168204 ** some C-compiler optimizers from in-lining the
168205 ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to
168206 ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
168207 */
168208 notReady = ~(Bitmask)0;
168209 if( pWInfo->nLevel>=2
168210 && pResultSet!=0 /* these two combine to guarantee */
168211 && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
168212 && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
168213 ){
168214 notReady = whereOmitNoopJoin(pWInfo, notReady);
168215 nTabList = pWInfo->nLevel;
168216 assert( nTabList>0 );
168217 }
@@ -168693,11 +169553,19 @@
168693 if( pLevel->iLeftJoin ){
168694 int ws = pLoop->wsFlags;
168695 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
168696 assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
168697 if( (ws & WHERE_IDX_ONLY)==0 ){
168698 assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
 
 
 
 
 
 
 
 
168699 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
168700 }
168701 if( (ws & WHERE_INDEXED)
168702 || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx)
168703 ){
@@ -169793,11 +170661,11 @@
169793 }
169794 if( bIntToNull ){
169795 int iDummy;
169796 Expr *pSub;
169797 pSub = sqlite3ExprSkipCollateAndLikely(pDup);
169798 if( sqlite3ExprIsInteger(pSub, &iDummy) ){
169799 pSub->op = TK_NULL;
169800 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
169801 pSub->u.zToken = 0;
169802 }
169803 }
@@ -172270,139 +173138,139 @@
172270 #define TK_EACH 41
172271 #define TK_FAIL 42
172272 #define TK_OR 43
172273 #define TK_AND 44
172274 #define TK_IS 45
172275 #define TK_MATCH 46
172276 #define TK_LIKE_KW 47
172277 #define TK_BETWEEN 48
172278 #define TK_IN 49
172279 #define TK_ISNULL 50
172280 #define TK_NOTNULL 51
172281 #define TK_NE 52
172282 #define TK_EQ 53
172283 #define TK_GT 54
172284 #define TK_LE 55
172285 #define TK_LT 56
172286 #define TK_GE 57
172287 #define TK_ESCAPE 58
172288 #define TK_ID 59
172289 #define TK_COLUMNKW 60
172290 #define TK_DO 61
172291 #define TK_FOR 62
172292 #define TK_IGNORE 63
172293 #define TK_INITIALLY 64
172294 #define TK_INSTEAD 65
172295 #define TK_NO 66
172296 #define TK_KEY 67
172297 #define TK_OF 68
172298 #define TK_OFFSET 69
172299 #define TK_PRAGMA 70
172300 #define TK_RAISE 71
172301 #define TK_RECURSIVE 72
172302 #define TK_REPLACE 73
172303 #define TK_RESTRICT 74
172304 #define TK_ROW 75
172305 #define TK_ROWS 76
172306 #define TK_TRIGGER 77
172307 #define TK_VACUUM 78
172308 #define TK_VIEW 79
172309 #define TK_VIRTUAL 80
172310 #define TK_WITH 81
172311 #define TK_NULLS 82
172312 #define TK_FIRST 83
172313 #define TK_LAST 84
172314 #define TK_CURRENT 85
172315 #define TK_FOLLOWING 86
172316 #define TK_PARTITION 87
172317 #define TK_PRECEDING 88
172318 #define TK_RANGE 89
172319 #define TK_UNBOUNDED 90
172320 #define TK_EXCLUDE 91
172321 #define TK_GROUPS 92
172322 #define TK_OTHERS 93
172323 #define TK_TIES 94
172324 #define TK_GENERATED 95
172325 #define TK_ALWAYS 96
172326 #define TK_MATERIALIZED 97
172327 #define TK_REINDEX 98
172328 #define TK_RENAME 99
172329 #define TK_CTIME_KW 100
172330 #define TK_ANY 101
172331 #define TK_BITAND 102
172332 #define TK_BITOR 103
172333 #define TK_LSHIFT 104
172334 #define TK_RSHIFT 105
172335 #define TK_PLUS 106
172336 #define TK_MINUS 107
172337 #define TK_STAR 108
172338 #define TK_SLASH 109
172339 #define TK_REM 110
172340 #define TK_CONCAT 111
172341 #define TK_PTR 112
172342 #define TK_COLLATE 113
172343 #define TK_BITNOT 114
172344 #define TK_ON 115
172345 #define TK_INDEXED 116
172346 #define TK_STRING 117
172347 #define TK_JOIN_KW 118
172348 #define TK_CONSTRAINT 119
172349 #define TK_DEFAULT 120
172350 #define TK_NULL 121
172351 #define TK_PRIMARY 122
172352 #define TK_UNIQUE 123
172353 #define TK_CHECK 124
172354 #define TK_REFERENCES 125
172355 #define TK_AUTOINCR 126
172356 #define TK_INSERT 127
172357 #define TK_DELETE 128
172358 #define TK_UPDATE 129
172359 #define TK_SET 130
172360 #define TK_DEFERRABLE 131
172361 #define TK_FOREIGN 132
172362 #define TK_DROP 133
172363 #define TK_UNION 134
172364 #define TK_ALL 135
172365 #define TK_EXCEPT 136
172366 #define TK_INTERSECT 137
172367 #define TK_SELECT 138
172368 #define TK_VALUES 139
172369 #define TK_DISTINCT 140
172370 #define TK_DOT 141
172371 #define TK_FROM 142
172372 #define TK_JOIN 143
172373 #define TK_USING 144
172374 #define TK_ORDER 145
172375 #define TK_GROUP 146
172376 #define TK_HAVING 147
172377 #define TK_LIMIT 148
172378 #define TK_WHERE 149
172379 #define TK_RETURNING 150
172380 #define TK_INTO 151
172381 #define TK_NOTHING 152
172382 #define TK_FLOAT 153
172383 #define TK_BLOB 154
172384 #define TK_INTEGER 155
172385 #define TK_VARIABLE 156
172386 #define TK_CASE 157
172387 #define TK_WHEN 158
172388 #define TK_THEN 159
172389 #define TK_ELSE 160
172390 #define TK_INDEX 161
172391 #define TK_ALTER 162
172392 #define TK_ADD 163
172393 #define TK_WINDOW 164
172394 #define TK_OVER 165
172395 #define TK_FILTER 166
172396 #define TK_COLUMN 167
172397 #define TK_AGG_FUNCTION 168
172398 #define TK_AGG_COLUMN 169
172399 #define TK_TRUEFALSE 170
172400 #define TK_ISNOT 171
172401 #define TK_FUNCTION 172
172402 #define TK_UMINUS 173
172403 #define TK_UPLUS 174
172404 #define TK_TRUTH 175
172405 #define TK_REGISTER 176
172406 #define TK_VECTOR 177
172407 #define TK_SELECT_COLUMN 178
172408 #define TK_IF_NULL_ROW 179
@@ -172476,11 +173344,11 @@
172476 #endif
172477 /************* Begin control #defines *****************************************/
172478 #define YYCODETYPE unsigned short int
172479 #define YYNOCODE 322
172480 #define YYACTIONTYPE unsigned short int
172481 #define YYWILDCARD 101
172482 #define sqlite3ParserTOKENTYPE Token
172483 typedef union {
172484 int yyinit;
172485 sqlite3ParserTOKENTYPE yy0;
172486 ExprList* yy14;
@@ -172613,450 +173481,456 @@
172613 ** yy_reduce_ofst[] For each state, the offset into yy_action for
172614 ** shifting non-terminals after a reduce.
172615 ** yy_default[] Default action for each state.
172616 **
172617 *********** Begin parsing tables **********************************************/
172618 #define YY_ACTTAB_COUNT (2142)
172619 static const YYACTIONTYPE yy_action[] = {
172620 /* 0 */ 576, 128, 125, 232, 1622, 549, 576, 1290, 1281, 576,
172621 /* 10 */ 328, 576, 1300, 212, 576, 128, 125, 232, 578, 412,
172622 /* 20 */ 578, 391, 1542, 51, 51, 523, 405, 1293, 529, 51,
172623 /* 30 */ 51, 983, 51, 51, 81, 81, 1107, 61, 61, 984,
172624 /* 40 */ 1107, 1292, 380, 135, 136, 90, 1228, 1228, 1063, 1066,
172625 /* 50 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 1577, 412,
172626 /* 60 */ 287, 287, 7, 287, 287, 422, 1050, 1050, 1064, 1067,
172627 /* 70 */ 289, 556, 492, 573, 524, 561, 573, 497, 561, 482,
172628 /* 80 */ 530, 262, 229, 135, 136, 90, 1228, 1228, 1063, 1066,
172629 /* 90 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 128, 125,
172630 /* 100 */ 232, 1506, 132, 132, 132, 132, 131, 131, 130, 130,
172631 /* 110 */ 130, 129, 126, 450, 1204, 1255, 1, 1, 582, 2,
172632 /* 120 */ 1259, 1571, 420, 1582, 379, 320, 1174, 153, 1174, 1584,
172633 /* 130 */ 412, 378, 1582, 543, 1341, 330, 111, 570, 570, 570,
172634 /* 140 */ 293, 1054, 132, 132, 132, 132, 131, 131, 130, 130,
172635 /* 150 */ 130, 129, 126, 450, 135, 136, 90, 1228, 1228, 1063,
172636 /* 160 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 287,
172637 /* 170 */ 287, 1204, 1205, 1204, 255, 287, 287, 510, 507, 506,
172638 /* 180 */ 137, 455, 573, 212, 561, 447, 446, 505, 573, 1616,
172639 /* 190 */ 561, 134, 134, 134, 134, 127, 400, 243, 132, 132,
172640 /* 200 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
172641 /* 210 */ 282, 471, 345, 132, 132, 132, 132, 131, 131, 130,
172642 /* 220 */ 130, 130, 129, 126, 450, 574, 155, 936, 936, 454,
172643 /* 230 */ 227, 521, 1236, 412, 1236, 134, 134, 134, 134, 132,
172644 /* 240 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
172645 /* 250 */ 450, 130, 130, 130, 129, 126, 450, 135, 136, 90,
172646 /* 260 */ 1228, 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134,
172647 /* 270 */ 134, 134, 128, 125, 232, 450, 576, 412, 397, 1249,
172648 /* 280 */ 180, 92, 93, 132, 132, 132, 132, 131, 131, 130,
172649 /* 290 */ 130, 130, 129, 126, 450, 381, 387, 1204, 383, 81,
172650 /* 300 */ 81, 135, 136, 90, 1228, 1228, 1063, 1066, 1053, 1053,
172651 /* 310 */ 133, 133, 134, 134, 134, 134, 132, 132, 132, 132,
172652 /* 320 */ 131, 131, 130, 130, 130, 129, 126, 450, 131, 131,
172653 /* 330 */ 130, 130, 130, 129, 126, 450, 556, 1204, 302, 319,
172654 /* 340 */ 567, 121, 568, 480, 4, 555, 1149, 1657, 1628, 1657,
172655 /* 350 */ 45, 128, 125, 232, 1204, 1205, 1204, 1250, 571, 1169,
172656 /* 360 */ 132, 132, 132, 132, 131, 131, 130, 130, 130, 129,
172657 /* 370 */ 126, 450, 1169, 287, 287, 1169, 1019, 576, 422, 1019,
172658 /* 380 */ 412, 451, 1602, 582, 2, 1259, 573, 44, 561, 95,
172659 /* 390 */ 320, 110, 153, 565, 1204, 1205, 1204, 522, 522, 1341,
172660 /* 400 */ 81, 81, 7, 44, 135, 136, 90, 1228, 1228, 1063,
172661 /* 410 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 295,
172662 /* 420 */ 1149, 1658, 1040, 1658, 1204, 1147, 319, 567, 119, 119,
172663 /* 430 */ 343, 466, 331, 343, 287, 287, 120, 556, 451, 577,
172664 /* 440 */ 451, 1169, 1169, 1028, 319, 567, 438, 573, 210, 561,
172665 /* 450 */ 1339, 1451, 546, 531, 1169, 1169, 1598, 1169, 1169, 416,
172666 /* 460 */ 319, 567, 243, 132, 132, 132, 132, 131, 131, 130,
172667 /* 470 */ 130, 130, 129, 126, 450, 1028, 1028, 1030, 1031, 35,
172668 /* 480 */ 44, 1204, 1205, 1204, 472, 287, 287, 1328, 412, 1307,
172669 /* 490 */ 372, 1595, 359, 225, 454, 1204, 195, 1328, 573, 1147,
172670 /* 500 */ 561, 1333, 1333, 274, 576, 1188, 576, 340, 46, 196,
172671 /* 510 */ 537, 217, 135, 136, 90, 1228, 1228, 1063, 1066, 1053,
172672 /* 520 */ 1053, 133, 133, 134, 134, 134, 134, 19, 19, 19,
172673 /* 530 */ 19, 412, 581, 1204, 1259, 511, 1204, 319, 567, 320,
172674 /* 540 */ 944, 153, 425, 491, 430, 943, 1204, 488, 1341, 1450,
172675 /* 550 */ 532, 1277, 1204, 1205, 1204, 135, 136, 90, 1228, 1228,
172676 /* 560 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172677 /* 570 */ 575, 132, 132, 132, 132, 131, 131, 130, 130, 130,
172678 /* 580 */ 129, 126, 450, 287, 287, 528, 287, 287, 372, 1595,
172679 /* 590 */ 1204, 1205, 1204, 1204, 1205, 1204, 573, 486, 561, 573,
172680 /* 600 */ 889, 561, 412, 1204, 1205, 1204, 886, 40, 22, 22,
172681 /* 610 */ 220, 243, 525, 1449, 132, 132, 132, 132, 131, 131,
172682 /* 620 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172683 /* 630 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172684 /* 640 */ 134, 412, 180, 454, 1204, 879, 255, 287, 287, 510,
172685 /* 650 */ 507, 506, 372, 1595, 1568, 1331, 1331, 576, 889, 505,
172686 /* 660 */ 573, 44, 561, 559, 1207, 135, 136, 90, 1228, 1228,
172687 /* 670 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172688 /* 680 */ 81, 81, 422, 576, 377, 132, 132, 132, 132, 131,
172689 /* 690 */ 131, 130, 130, 130, 129, 126, 450, 297, 287, 287,
172690 /* 700 */ 460, 1204, 1205, 1204, 1204, 534, 19, 19, 448, 448,
172691 /* 710 */ 448, 573, 412, 561, 230, 436, 1187, 535, 319, 567,
172692 /* 720 */ 363, 432, 1207, 1435, 132, 132, 132, 132, 131, 131,
172693 /* 730 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172694 /* 740 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172695 /* 750 */ 134, 412, 211, 949, 1169, 1041, 1110, 1110, 494, 547,
172696 /* 760 */ 547, 1204, 1205, 1204, 7, 539, 1570, 1169, 376, 576,
172697 /* 770 */ 1169, 5, 1204, 486, 3, 135, 136, 90, 1228, 1228,
172698 /* 780 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172699 /* 790 */ 576, 513, 19, 19, 427, 132, 132, 132, 132, 131,
172700 /* 800 */ 131, 130, 130, 130, 129, 126, 450, 305, 1204, 433,
172701 /* 810 */ 225, 1204, 385, 19, 19, 273, 290, 371, 516, 366,
172702 /* 820 */ 515, 260, 412, 538, 1568, 549, 1024, 362, 437, 1204,
172703 /* 830 */ 1205, 1204, 902, 1552, 132, 132, 132, 132, 131, 131,
172704 /* 840 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172705 /* 850 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172706 /* 860 */ 134, 412, 1435, 514, 1281, 1204, 1205, 1204, 1204, 1205,
172707 /* 870 */ 1204, 903, 48, 342, 1568, 1568, 1279, 1627, 1568, 911,
172708 /* 880 */ 576, 129, 126, 450, 110, 135, 136, 90, 1228, 1228,
172709 /* 890 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
172710 /* 900 */ 265, 576, 459, 19, 19, 132, 132, 132, 132, 131,
172711 /* 910 */ 131, 130, 130, 130, 129, 126, 450, 1345, 204, 576,
172712 /* 920 */ 459, 458, 50, 47, 19, 19, 49, 434, 1105, 573,
172713 /* 930 */ 497, 561, 412, 428, 108, 1224, 1569, 1554, 376, 205,
172714 /* 940 */ 550, 550, 81, 81, 132, 132, 132, 132, 131, 131,
172715 /* 950 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
172716 /* 960 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172717 /* 970 */ 134, 480, 576, 1204, 576, 1541, 412, 1435, 969, 315,
172718 /* 980 */ 1659, 398, 284, 497, 969, 893, 1569, 1569, 376, 376,
172719 /* 990 */ 1569, 461, 376, 1224, 459, 80, 80, 81, 81, 497,
172720 /* 1000 */ 374, 114, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133,
172721 /* 1010 */ 133, 134, 134, 134, 134, 132, 132, 132, 132, 131,
172722 /* 1020 */ 131, 130, 130, 130, 129, 126, 450, 1204, 1505, 576,
172723 /* 1030 */ 1204, 1205, 1204, 1366, 316, 486, 281, 281, 497, 431,
172724 /* 1040 */ 557, 288, 288, 402, 1340, 471, 345, 298, 429, 573,
172725 /* 1050 */ 576, 561, 81, 81, 573, 374, 561, 971, 386, 132,
172726 /* 1060 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
172727 /* 1070 */ 450, 231, 117, 81, 81, 287, 287, 231, 287, 287,
172728 /* 1080 */ 576, 1511, 576, 1336, 1204, 1205, 1204, 139, 573, 556,
172729 /* 1090 */ 561, 573, 412, 561, 441, 456, 969, 213, 558, 1511,
172730 /* 1100 */ 1513, 1550, 969, 143, 143, 145, 145, 1368, 314, 478,
172731 /* 1110 */ 444, 970, 412, 850, 851, 852, 135, 136, 90, 1228,
172732 /* 1120 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172733 /* 1130 */ 134, 357, 412, 397, 1148, 304, 135, 136, 90, 1228,
172734 /* 1140 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172735 /* 1150 */ 134, 1575, 323, 6, 862, 7, 135, 124, 90, 1228,
172736 /* 1160 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
172737 /* 1170 */ 134, 409, 408, 1511, 212, 132, 132, 132, 132, 131,
172738 /* 1180 */ 131, 130, 130, 130, 129, 126, 450, 411, 118, 1204,
172739 /* 1190 */ 116, 10, 352, 265, 355, 132, 132, 132, 132, 131,
172740 /* 1200 */ 131, 130, 130, 130, 129, 126, 450, 576, 324, 306,
172741 /* 1210 */ 576, 306, 1250, 469, 158, 132, 132, 132, 132, 131,
172742 /* 1220 */ 131, 130, 130, 130, 129, 126, 450, 207, 1224, 1126,
172743 /* 1230 */ 65, 65, 470, 66, 66, 412, 447, 446, 882, 531,
172744 /* 1240 */ 335, 258, 257, 256, 1127, 1233, 1204, 1205, 1204, 327,
172745 /* 1250 */ 1235, 874, 159, 576, 16, 480, 1085, 1040, 1234, 1128,
172746 /* 1260 */ 136, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133, 133,
172747 /* 1270 */ 134, 134, 134, 134, 1029, 576, 81, 81, 1028, 1040,
172748 /* 1280 */ 922, 576, 463, 1236, 576, 1236, 1224, 502, 107, 1435,
172749 /* 1290 */ 923, 6, 576, 410, 1498, 882, 1029, 480, 21, 21,
172750 /* 1300 */ 1028, 332, 1380, 334, 53, 53, 497, 81, 81, 874,
172751 /* 1310 */ 1028, 1028, 1030, 445, 259, 19, 19, 533, 132, 132,
172752 /* 1320 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
172753 /* 1330 */ 551, 301, 1028, 1028, 1030, 107, 532, 545, 121, 568,
172754 /* 1340 */ 1188, 4, 1126, 1576, 449, 576, 462, 7, 1282, 418,
172755 /* 1350 */ 462, 350, 1435, 576, 518, 571, 544, 1127, 121, 568,
172756 /* 1360 */ 442, 4, 1188, 464, 533, 1180, 1223, 9, 67, 67,
172757 /* 1370 */ 487, 576, 1128, 303, 410, 571, 54, 54, 451, 576,
172758 /* 1380 */ 123, 944, 576, 417, 576, 333, 943, 1379, 576, 236,
172759 /* 1390 */ 565, 576, 1574, 564, 68, 68, 7, 576, 451, 362,
172760 /* 1400 */ 419, 182, 69, 69, 541, 70, 70, 71, 71, 540,
172761 /* 1410 */ 565, 72, 72, 484, 55, 55, 473, 1180, 296, 1040,
172762 /* 1420 */ 56, 56, 296, 493, 541, 119, 119, 410, 1573, 542,
172763 /* 1430 */ 569, 418, 7, 120, 1244, 451, 577, 451, 465, 1040,
172764 /* 1440 */ 1028, 576, 1557, 552, 476, 119, 119, 527, 259, 121,
172765 /* 1450 */ 568, 240, 4, 120, 576, 451, 577, 451, 576, 477,
172766 /* 1460 */ 1028, 576, 156, 576, 57, 57, 571, 576, 286, 229,
172767 /* 1470 */ 410, 336, 1028, 1028, 1030, 1031, 35, 59, 59, 219,
172768 /* 1480 */ 983, 60, 60, 220, 73, 73, 74, 74, 984, 451,
172769 /* 1490 */ 75, 75, 1028, 1028, 1030, 1031, 35, 96, 216, 291,
172770 /* 1500 */ 552, 565, 1188, 318, 395, 395, 394, 276, 392, 576,
172771 /* 1510 */ 485, 859, 474, 1311, 410, 541, 576, 417, 1530, 1144,
172772 /* 1520 */ 540, 399, 1188, 292, 237, 1153, 326, 38, 23, 576,
172773 /* 1530 */ 1040, 576, 20, 20, 325, 299, 119, 119, 164, 76,
172774 /* 1540 */ 76, 1529, 121, 568, 120, 4, 451, 577, 451, 203,
172775 /* 1550 */ 576, 1028, 141, 141, 142, 142, 576, 322, 39, 571,
172776 /* 1560 */ 341, 1021, 110, 264, 239, 901, 900, 423, 242, 908,
172777 /* 1570 */ 909, 370, 173, 77, 77, 43, 479, 1310, 264, 62,
172778 /* 1580 */ 62, 369, 451, 1028, 1028, 1030, 1031, 35, 1601, 1192,
172779 /* 1590 */ 453, 1092, 238, 291, 565, 163, 1309, 110, 395, 395,
172780 /* 1600 */ 394, 276, 392, 986, 987, 859, 481, 346, 264, 110,
172781 /* 1610 */ 1032, 489, 576, 1188, 503, 1088, 261, 261, 237, 576,
172782 /* 1620 */ 326, 121, 568, 1040, 4, 347, 1376, 413, 325, 119,
172783 /* 1630 */ 119, 948, 319, 567, 351, 78, 78, 120, 571, 451,
172784 /* 1640 */ 577, 451, 79, 79, 1028, 354, 356, 576, 360, 1092,
172785 /* 1650 */ 110, 576, 974, 942, 264, 123, 457, 358, 239, 576,
172786 /* 1660 */ 519, 451, 939, 1104, 123, 1104, 173, 576, 1032, 43,
172787 /* 1670 */ 63, 63, 1324, 565, 168, 168, 1028, 1028, 1030, 1031,
172788 /* 1680 */ 35, 576, 169, 169, 1308, 872, 238, 157, 1589, 576,
172789 /* 1690 */ 86, 86, 365, 89, 568, 375, 4, 1103, 941, 1103,
172790 /* 1700 */ 123, 576, 1040, 1389, 64, 64, 1188, 1434, 119, 119,
172791 /* 1710 */ 571, 576, 82, 82, 563, 576, 120, 165, 451, 577,
172792 /* 1720 */ 451, 413, 1362, 1028, 144, 144, 319, 567, 576, 1374,
172793 /* 1730 */ 562, 498, 279, 451, 83, 83, 1439, 576, 166, 166,
172794 /* 1740 */ 576, 1289, 554, 576, 1280, 565, 576, 12, 576, 1268,
172795 /* 1750 */ 457, 146, 146, 1267, 576, 1028, 1028, 1030, 1031, 35,
172796 /* 1760 */ 140, 140, 1269, 167, 167, 1609, 160, 160, 1359, 150,
172797 /* 1770 */ 150, 149, 149, 311, 1040, 576, 312, 147, 147, 313,
172798 /* 1780 */ 119, 119, 222, 235, 576, 1188, 396, 576, 120, 576,
172799 /* 1790 */ 451, 577, 451, 1192, 453, 1028, 508, 291, 148, 148,
172800 /* 1800 */ 1421, 1612, 395, 395, 394, 276, 392, 85, 85, 859,
172801 /* 1810 */ 87, 87, 84, 84, 553, 576, 294, 576, 1426, 338,
172802 /* 1820 */ 339, 1425, 237, 300, 326, 1416, 1409, 1028, 1028, 1030,
172803 /* 1830 */ 1031, 35, 325, 344, 403, 483, 226, 1307, 52, 52,
172804 /* 1840 */ 58, 58, 368, 1371, 1502, 566, 1501, 121, 568, 221,
172805 /* 1850 */ 4, 208, 268, 209, 390, 1244, 1549, 1188, 1372, 1370,
172806 /* 1860 */ 1369, 1547, 239, 184, 571, 233, 421, 1241, 95, 218,
172807 /* 1870 */ 173, 1507, 193, 43, 91, 94, 178, 186, 467, 188,
172808 /* 1880 */ 468, 1422, 13, 189, 190, 191, 501, 451, 245, 108,
172809 /* 1890 */ 238, 401, 1428, 1427, 1430, 475, 404, 1496, 197, 565,
172810 /* 1900 */ 14, 490, 249, 101, 1518, 496, 349, 280, 251, 201,
172811 /* 1910 */ 353, 499, 252, 406, 1270, 253, 517, 1327, 1326, 435,
172812 /* 1920 */ 1325, 1318, 103, 893, 1296, 413, 227, 407, 1040, 1626,
172813 /* 1930 */ 319, 567, 1625, 1297, 119, 119, 439, 367, 1317, 1295,
172814 /* 1940 */ 1624, 526, 120, 440, 451, 577, 451, 1594, 309, 1028,
172815 /* 1950 */ 310, 373, 266, 267, 457, 1580, 1579, 443, 138, 1394,
172816 /* 1960 */ 552, 1393, 11, 1483, 384, 115, 317, 1350, 109, 536,
172817 /* 1970 */ 42, 579, 382, 214, 1349, 388, 1198, 389, 275, 277,
172818 /* 1980 */ 278, 1028, 1028, 1030, 1031, 35, 580, 1265, 414, 1260,
172819 /* 1990 */ 170, 415, 183, 1534, 1535, 1533, 171, 154, 307, 1532,
172820 /* 2000 */ 846, 223, 224, 88, 452, 215, 172, 321, 234, 1102,
172821 /* 2010 */ 152, 1188, 1100, 329, 185, 174, 1223, 925, 187, 241,
172822 /* 2020 */ 337, 244, 1116, 192, 175, 176, 424, 426, 97, 194,
172823 /* 2030 */ 98, 99, 100, 177, 1119, 1115, 246, 247, 161, 24,
172824 /* 2040 */ 248, 348, 1238, 264, 1108, 250, 495, 199, 198, 15,
172825 /* 2050 */ 861, 500, 369, 254, 504, 509, 512, 200, 102, 25,
172826 /* 2060 */ 179, 361, 26, 364, 104, 891, 308, 162, 105, 904,
172827 /* 2070 */ 520, 106, 1185, 1069, 1155, 17, 228, 27, 1154, 283,
172828 /* 2080 */ 285, 263, 978, 202, 972, 123, 28, 1175, 29, 30,
172829 /* 2090 */ 1179, 1171, 31, 1173, 1160, 41, 32, 206, 548, 33,
172830 /* 2100 */ 110, 1178, 1083, 8, 112, 1070, 113, 1068, 1072, 34,
172831 /* 2110 */ 1073, 560, 1125, 269, 1124, 270, 36, 18, 1194, 1033,
172832 /* 2120 */ 873, 151, 122, 37, 393, 271, 272, 572, 181, 1193,
172833 /* 2130 */ 1256, 1256, 1256, 935, 1256, 1256, 1256, 1256, 1256, 1256,
172834 /* 2140 */ 1256, 1617,
 
 
 
 
 
 
172835 };
172836 static const YYCODETYPE yy_lookahead[] = {
172837 /* 0 */ 194, 276, 277, 278, 216, 194, 194, 217, 194, 194,
172838 /* 10 */ 194, 194, 224, 194, 194, 276, 277, 278, 204, 19,
172839 /* 20 */ 206, 202, 297, 217, 218, 205, 207, 217, 205, 217,
172840 /* 30 */ 218, 31, 217, 218, 217, 218, 29, 217, 218, 39,
172841 /* 40 */ 33, 217, 220, 43, 44, 45, 46, 47, 48, 49,
172842 /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 312, 19,
172843 /* 60 */ 240, 241, 316, 240, 241, 194, 46, 47, 48, 49,
172844 /* 70 */ 22, 254, 65, 253, 254, 255, 253, 194, 255, 194,
172845 /* 80 */ 263, 258, 259, 43, 44, 45, 46, 47, 48, 49,
172846 /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 276, 277,
172847 /* 100 */ 278, 285, 102, 103, 104, 105, 106, 107, 108, 109,
172848 /* 110 */ 110, 111, 112, 113, 59, 186, 187, 188, 189, 190,
172849 /* 120 */ 191, 310, 239, 317, 318, 196, 86, 198, 88, 317,
172850 /* 130 */ 19, 319, 317, 318, 205, 264, 25, 211, 212, 213,
172851 /* 140 */ 205, 121, 102, 103, 104, 105, 106, 107, 108, 109,
172852 /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48,
172853 /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 240,
172854 /* 170 */ 241, 116, 117, 118, 119, 240, 241, 122, 123, 124,
172855 /* 180 */ 69, 298, 253, 194, 255, 106, 107, 132, 253, 141,
172856 /* 190 */ 255, 54, 55, 56, 57, 58, 207, 268, 102, 103,
172857 /* 200 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
172858 /* 210 */ 214, 128, 129, 102, 103, 104, 105, 106, 107, 108,
172859 /* 220 */ 109, 110, 111, 112, 113, 134, 25, 136, 137, 300,
172860 /* 230 */ 165, 166, 153, 19, 155, 54, 55, 56, 57, 102,
172861 /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
172862 /* 250 */ 113, 108, 109, 110, 111, 112, 113, 43, 44, 45,
172863 /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
172864 /* 270 */ 56, 57, 276, 277, 278, 113, 194, 19, 22, 23,
172865 /* 280 */ 194, 67, 24, 102, 103, 104, 105, 106, 107, 108,
172866 /* 290 */ 109, 110, 111, 112, 113, 220, 250, 59, 252, 217,
172867 /* 300 */ 218, 43, 44, 45, 46, 47, 48, 49, 50, 51,
172868 /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105,
172869 /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 106, 107,
172870 /* 330 */ 108, 109, 110, 111, 112, 113, 254, 59, 205, 138,
172871 /* 340 */ 139, 19, 20, 194, 22, 263, 22, 23, 231, 25,
172872 /* 350 */ 72, 276, 277, 278, 116, 117, 118, 101, 36, 76,
172873 /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
172874 /* 370 */ 112, 113, 89, 240, 241, 92, 73, 194, 194, 73,
172875 /* 380 */ 19, 59, 188, 189, 190, 191, 253, 81, 255, 151,
172876 /* 390 */ 196, 25, 198, 71, 116, 117, 118, 311, 312, 205,
172877 /* 400 */ 217, 218, 316, 81, 43, 44, 45, 46, 47, 48,
172878 /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 270,
172879 /* 420 */ 22, 23, 100, 25, 59, 101, 138, 139, 106, 107,
172880 /* 430 */ 127, 128, 129, 127, 240, 241, 114, 254, 116, 117,
172881 /* 440 */ 118, 76, 76, 121, 138, 139, 263, 253, 264, 255,
172882 /* 450 */ 205, 275, 87, 19, 89, 89, 194, 92, 92, 199,
172883 /* 460 */ 138, 139, 268, 102, 103, 104, 105, 106, 107, 108,
172884 /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157,
172885 /* 480 */ 81, 116, 117, 118, 129, 240, 241, 224, 19, 226,
172886 /* 490 */ 314, 315, 23, 25, 300, 59, 22, 234, 253, 101,
172887 /* 500 */ 255, 236, 237, 26, 194, 183, 194, 152, 72, 22,
172888 /* 510 */ 145, 150, 43, 44, 45, 46, 47, 48, 49, 50,
172889 /* 520 */ 51, 52, 53, 54, 55, 56, 57, 217, 218, 217,
172890 /* 530 */ 218, 19, 189, 59, 191, 23, 59, 138, 139, 196,
172891 /* 540 */ 135, 198, 232, 283, 232, 140, 59, 287, 205, 275,
172892 /* 550 */ 116, 205, 116, 117, 118, 43, 44, 45, 46, 47,
172893 /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172894 /* 570 */ 194, 102, 103, 104, 105, 106, 107, 108, 109, 110,
172895 /* 580 */ 111, 112, 113, 240, 241, 194, 240, 241, 314, 315,
172896 /* 590 */ 116, 117, 118, 116, 117, 118, 253, 194, 255, 253,
172897 /* 600 */ 59, 255, 19, 116, 117, 118, 23, 22, 217, 218,
172898 /* 610 */ 142, 268, 205, 275, 102, 103, 104, 105, 106, 107,
172899 /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172900 /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172901 /* 640 */ 57, 19, 194, 300, 59, 23, 119, 240, 241, 122,
172902 /* 650 */ 123, 124, 314, 315, 194, 236, 237, 194, 117, 132,
172903 /* 660 */ 253, 81, 255, 205, 59, 43, 44, 45, 46, 47,
172904 /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172905 /* 680 */ 217, 218, 194, 194, 194, 102, 103, 104, 105, 106,
172906 /* 690 */ 107, 108, 109, 110, 111, 112, 113, 294, 240, 241,
172907 /* 700 */ 120, 116, 117, 118, 59, 194, 217, 218, 211, 212,
172908 /* 710 */ 213, 253, 19, 255, 194, 19, 23, 254, 138, 139,
172909 /* 720 */ 24, 232, 117, 194, 102, 103, 104, 105, 106, 107,
172910 /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172911 /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172912 /* 750 */ 57, 19, 264, 108, 76, 23, 127, 128, 129, 311,
172913 /* 760 */ 312, 116, 117, 118, 316, 87, 306, 89, 308, 194,
172914 /* 770 */ 92, 22, 59, 194, 22, 43, 44, 45, 46, 47,
172915 /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172916 /* 790 */ 194, 95, 217, 218, 265, 102, 103, 104, 105, 106,
172917 /* 800 */ 107, 108, 109, 110, 111, 112, 113, 232, 59, 113,
172918 /* 810 */ 25, 59, 194, 217, 218, 119, 120, 121, 122, 123,
172919 /* 820 */ 124, 125, 19, 145, 194, 194, 23, 131, 232, 116,
172920 /* 830 */ 117, 118, 35, 194, 102, 103, 104, 105, 106, 107,
172921 /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172922 /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172923 /* 860 */ 57, 19, 194, 66, 194, 116, 117, 118, 116, 117,
172924 /* 870 */ 118, 74, 242, 294, 194, 194, 206, 23, 194, 25,
172925 /* 880 */ 194, 111, 112, 113, 25, 43, 44, 45, 46, 47,
172926 /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
172927 /* 900 */ 24, 194, 194, 217, 218, 102, 103, 104, 105, 106,
172928 /* 910 */ 107, 108, 109, 110, 111, 112, 113, 241, 232, 194,
172929 /* 920 */ 212, 213, 242, 242, 217, 218, 242, 130, 11, 253,
172930 /* 930 */ 194, 255, 19, 265, 149, 59, 306, 194, 308, 232,
172931 /* 940 */ 309, 310, 217, 218, 102, 103, 104, 105, 106, 107,
172932 /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
172933 /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172934 /* 970 */ 57, 194, 194, 59, 194, 239, 19, 194, 25, 254,
172935 /* 980 */ 303, 304, 23, 194, 25, 126, 306, 306, 308, 308,
172936 /* 990 */ 306, 271, 308, 117, 286, 217, 218, 217, 218, 194,
172937 /* 1000 */ 194, 159, 45, 46, 47, 48, 49, 50, 51, 52,
172938 /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106,
172939 /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 59, 239, 194,
172940 /* 1030 */ 116, 117, 118, 260, 254, 194, 240, 241, 194, 233,
172941 /* 1040 */ 205, 240, 241, 205, 239, 128, 129, 270, 265, 253,
172942 /* 1050 */ 194, 255, 217, 218, 253, 194, 255, 143, 280, 102,
172943 /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
172944 /* 1070 */ 113, 118, 159, 217, 218, 240, 241, 118, 240, 241,
172945 /* 1080 */ 194, 194, 194, 239, 116, 117, 118, 22, 253, 254,
172946 /* 1090 */ 255, 253, 19, 255, 233, 194, 143, 24, 263, 212,
172947 /* 1100 */ 213, 194, 143, 217, 218, 217, 218, 261, 262, 271,
172948 /* 1110 */ 254, 143, 19, 7, 8, 9, 43, 44, 45, 46,
172949 /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172950 /* 1130 */ 57, 16, 19, 22, 23, 294, 43, 44, 45, 46,
172951 /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172952 /* 1150 */ 57, 312, 194, 214, 21, 316, 43, 44, 45, 46,
172953 /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
172954 /* 1170 */ 57, 106, 107, 286, 194, 102, 103, 104, 105, 106,
172955 /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 207, 158, 59,
172956 /* 1190 */ 160, 22, 77, 24, 79, 102, 103, 104, 105, 106,
172957 /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 194, 194, 229,
172958 /* 1210 */ 194, 231, 101, 80, 22, 102, 103, 104, 105, 106,
172959 /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 288, 59, 12,
172960 /* 1230 */ 217, 218, 293, 217, 218, 19, 106, 107, 59, 19,
172961 /* 1240 */ 16, 127, 128, 129, 27, 115, 116, 117, 118, 194,
172962 /* 1250 */ 120, 59, 22, 194, 24, 194, 123, 100, 128, 42,
172963 /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
172964 /* 1270 */ 54, 55, 56, 57, 117, 194, 217, 218, 121, 100,
172965 /* 1280 */ 63, 194, 245, 153, 194, 155, 117, 19, 115, 194,
172966 /* 1290 */ 73, 214, 194, 256, 161, 116, 117, 194, 217, 218,
172967 /* 1300 */ 121, 77, 194, 79, 217, 218, 194, 217, 218, 117,
172968 /* 1310 */ 153, 154, 155, 254, 46, 217, 218, 144, 102, 103,
172969 /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
172970 /* 1330 */ 232, 270, 153, 154, 155, 115, 116, 66, 19, 20,
172971 /* 1340 */ 183, 22, 12, 312, 254, 194, 262, 316, 209, 210,
172972 /* 1350 */ 266, 239, 194, 194, 108, 36, 85, 27, 19, 20,
172973 /* 1360 */ 265, 22, 183, 245, 144, 94, 25, 48, 217, 218,
172974 /* 1370 */ 293, 194, 42, 270, 256, 36, 217, 218, 59, 194,
172975 /* 1380 */ 25, 135, 194, 115, 194, 161, 140, 194, 194, 15,
172976 /* 1390 */ 71, 194, 312, 63, 217, 218, 316, 194, 59, 131,
172977 /* 1400 */ 301, 302, 217, 218, 85, 217, 218, 217, 218, 90,
172978 /* 1410 */ 71, 217, 218, 19, 217, 218, 245, 146, 262, 100,
172979 /* 1420 */ 217, 218, 266, 265, 85, 106, 107, 256, 312, 90,
172980 /* 1430 */ 209, 210, 316, 114, 60, 116, 117, 118, 194, 100,
172981 /* 1440 */ 121, 194, 194, 145, 115, 106, 107, 19, 46, 19,
172982 /* 1450 */ 20, 24, 22, 114, 194, 116, 117, 118, 194, 245,
172983 /* 1460 */ 121, 194, 164, 194, 217, 218, 36, 194, 258, 259,
172984 /* 1470 */ 256, 194, 153, 154, 155, 156, 157, 217, 218, 150,
172985 /* 1480 */ 31, 217, 218, 142, 217, 218, 217, 218, 39, 59,
172986 /* 1490 */ 217, 218, 153, 154, 155, 156, 157, 149, 150, 5,
172987 /* 1500 */ 145, 71, 183, 245, 10, 11, 12, 13, 14, 194,
172988 /* 1510 */ 116, 17, 129, 227, 256, 85, 194, 115, 194, 23,
172989 /* 1520 */ 90, 25, 183, 99, 30, 97, 32, 22, 22, 194,
172990 /* 1530 */ 100, 194, 217, 218, 40, 152, 106, 107, 23, 217,
172991 /* 1540 */ 218, 194, 19, 20, 114, 22, 116, 117, 118, 257,
172992 /* 1550 */ 194, 121, 217, 218, 217, 218, 194, 133, 53, 36,
172993 /* 1560 */ 23, 23, 25, 25, 70, 120, 121, 61, 141, 7,
172994 /* 1570 */ 8, 121, 78, 217, 218, 81, 23, 227, 25, 217,
172995 /* 1580 */ 218, 131, 59, 153, 154, 155, 156, 157, 0, 1,
172996 /* 1590 */ 2, 59, 98, 5, 71, 23, 227, 25, 10, 11,
172997 /* 1600 */ 12, 13, 14, 83, 84, 17, 23, 23, 25, 25,
172998 /* 1610 */ 59, 194, 194, 183, 23, 23, 25, 25, 30, 194,
172999 /* 1620 */ 32, 19, 20, 100, 22, 194, 194, 133, 40, 106,
173000 /* 1630 */ 107, 108, 138, 139, 194, 217, 218, 114, 36, 116,
173001 /* 1640 */ 117, 118, 217, 218, 121, 194, 194, 194, 23, 117,
173002 /* 1650 */ 25, 194, 23, 23, 25, 25, 162, 194, 70, 194,
173003 /* 1660 */ 145, 59, 23, 153, 25, 155, 78, 194, 117, 81,
173004 /* 1670 */ 217, 218, 194, 71, 217, 218, 153, 154, 155, 156,
173005 /* 1680 */ 157, 194, 217, 218, 194, 23, 98, 25, 321, 194,
173006 /* 1690 */ 217, 218, 194, 19, 20, 194, 22, 153, 23, 155,
173007 /* 1700 */ 25, 194, 100, 194, 217, 218, 183, 194, 106, 107,
173008 /* 1710 */ 36, 194, 217, 218, 237, 194, 114, 243, 116, 117,
173009 /* 1720 */ 118, 133, 194, 121, 217, 218, 138, 139, 194, 194,
173010 /* 1730 */ 194, 290, 289, 59, 217, 218, 194, 194, 217, 218,
173011 /* 1740 */ 194, 194, 140, 194, 194, 71, 194, 244, 194, 194,
173012 /* 1750 */ 162, 217, 218, 194, 194, 153, 154, 155, 156, 157,
173013 /* 1760 */ 217, 218, 194, 217, 218, 194, 217, 218, 257, 217,
173014 /* 1770 */ 218, 217, 218, 257, 100, 194, 257, 217, 218, 257,
173015 /* 1780 */ 106, 107, 215, 299, 194, 183, 192, 194, 114, 194,
173016 /* 1790 */ 116, 117, 118, 1, 2, 121, 221, 5, 217, 218,
173017 /* 1800 */ 273, 197, 10, 11, 12, 13, 14, 217, 218, 17,
173018 /* 1810 */ 217, 218, 217, 218, 140, 194, 246, 194, 273, 295,
173019 /* 1820 */ 247, 273, 30, 247, 32, 269, 269, 153, 154, 155,
173020 /* 1830 */ 156, 157, 40, 246, 273, 295, 230, 226, 217, 218,
173021 /* 1840 */ 217, 218, 220, 261, 220, 282, 220, 19, 20, 244,
173022 /* 1850 */ 22, 250, 141, 250, 246, 60, 201, 183, 261, 261,
173023 /* 1860 */ 261, 201, 70, 299, 36, 299, 201, 38, 151, 150,
173024 /* 1870 */ 78, 285, 22, 81, 296, 296, 43, 235, 18, 238,
173025 /* 1880 */ 201, 274, 272, 238, 238, 238, 18, 59, 200, 149,
173026 /* 1890 */ 98, 247, 274, 274, 235, 247, 247, 247, 235, 71,
173027 /* 1900 */ 272, 201, 200, 158, 292, 62, 291, 201, 200, 22,
173028 /* 1910 */ 201, 222, 200, 222, 201, 200, 115, 219, 219, 64,
173029 /* 1920 */ 219, 228, 22, 126, 221, 133, 165, 222, 100, 225,
173030 /* 1930 */ 138, 139, 225, 219, 106, 107, 24, 219, 228, 219,
173031 /* 1940 */ 219, 307, 114, 113, 116, 117, 118, 315, 284, 121,
173032 /* 1950 */ 284, 222, 201, 91, 162, 320, 320, 82, 148, 267,
173033 /* 1960 */ 145, 267, 22, 279, 201, 158, 281, 251, 147, 146,
173034 /* 1970 */ 25, 203, 250, 249, 251, 248, 13, 247, 195, 195,
173035 /* 1980 */ 6, 153, 154, 155, 156, 157, 193, 193, 305, 193,
173036 /* 1990 */ 208, 305, 302, 214, 214, 214, 208, 223, 223, 214,
173037 /* 2000 */ 4, 215, 215, 214, 3, 22, 208, 163, 15, 23,
173038 /* 2010 */ 16, 183, 23, 139, 151, 130, 25, 20, 142, 24,
173039 /* 2020 */ 16, 144, 1, 142, 130, 130, 61, 37, 53, 151,
173040 /* 2030 */ 53, 53, 53, 130, 116, 1, 34, 141, 5, 22,
173041 /* 2040 */ 115, 161, 75, 25, 68, 141, 41, 115, 68, 24,
173042 /* 2050 */ 20, 19, 131, 125, 67, 67, 96, 22, 22, 22,
173043 /* 2060 */ 37, 23, 22, 24, 22, 59, 67, 23, 149, 28,
173044 /* 2070 */ 22, 25, 23, 23, 23, 22, 141, 34, 97, 23,
173045 /* 2080 */ 23, 34, 116, 22, 143, 25, 34, 75, 34, 34,
173046 /* 2090 */ 75, 88, 34, 86, 23, 22, 34, 25, 24, 34,
173047 /* 2100 */ 25, 93, 23, 44, 142, 23, 142, 23, 23, 22,
173048 /* 2110 */ 11, 25, 23, 25, 23, 22, 22, 22, 1, 23,
173049 /* 2120 */ 23, 23, 22, 22, 15, 141, 141, 25, 25, 1,
173050 /* 2130 */ 322, 322, 322, 135, 322, 322, 322, 322, 322, 322,
173051 /* 2140 */ 322, 141, 322, 322, 322, 322, 322, 322, 322, 322,
173052 /* 2150 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173053 /* 2160 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173054 /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173055 /* 2180 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173056 /* 2190 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173057 /* 2200 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173058 /* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173059 /* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173060 /* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173061 /* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173062 /* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
@@ -173064,181 +173938,188 @@
173064 /* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173065 /* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173066 /* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173067 /* 2300 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173068 /* 2310 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173069 /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322,
 
 
 
 
 
 
 
173070 };
173071 #define YY_SHIFT_COUNT (582)
173072 #define YY_SHIFT_MIN (0)
173073 #define YY_SHIFT_MAX (2128)
173074 static const unsigned short int yy_shift_ofst[] = {
173075 /* 0 */ 1792, 1588, 1494, 322, 322, 399, 306, 1319, 1339, 1430,
173076 /* 10 */ 1828, 1828, 1828, 580, 399, 399, 399, 399, 399, 0,
173077 /* 20 */ 0, 214, 1093, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173078 /* 30 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1130, 1130,
173079 /* 40 */ 365, 365, 55, 278, 436, 713, 713, 201, 201, 201,
173080 /* 50 */ 201, 40, 111, 258, 361, 469, 512, 583, 622, 693,
173081 /* 60 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093,
173082 /* 70 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
173083 /* 80 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1523, 1602,
173084 /* 90 */ 1674, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173085 /* 100 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173086 /* 110 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173087 /* 120 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173088 /* 130 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
173089 /* 140 */ 137, 181, 181, 181, 181, 181, 181, 181, 96, 222,
173090 /* 150 */ 143, 477, 713, 1133, 1268, 713, 713, 79, 79, 713,
173091 /* 160 */ 770, 83, 65, 65, 65, 288, 162, 162, 2142, 2142,
173092 /* 170 */ 696, 696, 696, 238, 474, 474, 474, 474, 1217, 1217,
173093 /* 180 */ 678, 477, 324, 398, 713, 713, 713, 713, 713, 713,
173094 /* 190 */ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
173095 /* 200 */ 713, 713, 713, 1220, 366, 366, 713, 917, 283, 283,
173096 /* 210 */ 434, 434, 605, 605, 1298, 2142, 2142, 2142, 2142, 2142,
173097 /* 220 */ 2142, 2142, 1179, 1157, 1157, 487, 527, 585, 645, 749,
173098 /* 230 */ 914, 968, 752, 713, 713, 713, 713, 713, 713, 713,
173099 /* 240 */ 713, 713, 713, 303, 713, 713, 713, 713, 713, 713,
173100 /* 250 */ 713, 713, 713, 713, 713, 713, 797, 797, 797, 713,
173101 /* 260 */ 713, 713, 959, 713, 713, 713, 1169, 1271, 713, 713,
173102 /* 270 */ 1330, 713, 713, 713, 713, 713, 713, 713, 713, 629,
173103 /* 280 */ 7, 91, 876, 876, 876, 876, 953, 91, 91, 1246,
173104 /* 290 */ 1065, 1106, 1374, 1329, 1348, 468, 1348, 1394, 785, 1329,
173105 /* 300 */ 1329, 785, 1329, 468, 1394, 859, 854, 1402, 1449, 1449,
173106 /* 310 */ 1449, 1173, 1173, 1173, 1173, 1355, 1355, 1030, 1341, 405,
173107 /* 320 */ 1230, 1795, 1795, 1711, 1711, 1829, 1829, 1711, 1717, 1719,
173108 /* 330 */ 1850, 1833, 1860, 1860, 1860, 1860, 1711, 1868, 1740, 1719,
173109 /* 340 */ 1719, 1740, 1850, 1833, 1740, 1833, 1740, 1711, 1868, 1745,
173110 /* 350 */ 1843, 1711, 1868, 1887, 1711, 1868, 1711, 1868, 1887, 1801,
173111 /* 360 */ 1801, 1801, 1855, 1900, 1900, 1887, 1801, 1797, 1801, 1855,
173112 /* 370 */ 1801, 1801, 1761, 1912, 1830, 1830, 1887, 1711, 1862, 1862,
173113 /* 380 */ 1875, 1875, 1810, 1815, 1940, 1711, 1807, 1810, 1821, 1823,
173114 /* 390 */ 1740, 1945, 1963, 1963, 1974, 1974, 1974, 2142, 2142, 2142,
173115 /* 400 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
173116 /* 410 */ 2142, 2142, 20, 1224, 256, 1111, 1115, 1114, 1192, 1496,
173117 /* 420 */ 1424, 1505, 1427, 355, 1383, 1537, 1506, 1538, 1553, 1583,
173118 /* 430 */ 1584, 1591, 1625, 541, 1445, 1562, 1450, 1572, 1515, 1428,
173119 /* 440 */ 1532, 1592, 1629, 1520, 1630, 1639, 1510, 1544, 1662, 1675,
173120 /* 450 */ 1551, 48, 1996, 2001, 1983, 1844, 1993, 1994, 1986, 1989,
173121 /* 460 */ 1874, 1863, 1885, 1991, 1991, 1995, 1876, 1997, 1877, 2004,
173122 /* 470 */ 2021, 1881, 1894, 1991, 1895, 1965, 1990, 1991, 1878, 1975,
173123 /* 480 */ 1977, 1978, 1979, 1903, 1918, 2002, 1896, 2034, 2033, 2017,
173124 /* 490 */ 1925, 1880, 1976, 2018, 1980, 1967, 2005, 1904, 1932, 2025,
173125 /* 500 */ 2030, 2032, 1921, 1928, 2035, 1987, 2036, 2037, 2038, 2040,
173126 /* 510 */ 1988, 2006, 2039, 1960, 2041, 2042, 1999, 2023, 2044, 2043,
173127 /* 520 */ 1919, 2048, 2049, 2050, 2046, 2051, 2053, 1981, 1935, 2056,
173128 /* 530 */ 2057, 1966, 2047, 2061, 1941, 2060, 2052, 2054, 2055, 2058,
173129 /* 540 */ 2003, 2012, 2007, 2059, 2015, 2008, 2062, 2071, 2073, 2074,
173130 /* 550 */ 2072, 2075, 2065, 1962, 1964, 2079, 2060, 2082, 2084, 2085,
173131 /* 560 */ 2087, 2086, 2089, 2088, 2091, 2093, 2099, 2094, 2095, 2096,
173132 /* 570 */ 2097, 2100, 2101, 2102, 1998, 1984, 1985, 2000, 2103, 2098,
173133 /* 580 */ 2109, 2117, 2128,
173134 };
173135 #define YY_REDUCE_COUNT (411)
173136 #define YY_REDUCE_MIN (-275)
173137 #define YY_REDUCE_MAX (1798)
173138 static const short yy_reduce_ofst[] = {
173139 /* 0 */ -71, 194, 343, 835, -180, -177, 838, -194, -188, -185,
173140 /* 10 */ -183, 82, 183, -65, 133, 245, 346, 407, 458, -178,
173141 /* 20 */ 75, -275, -4, 310, 312, 489, 575, 596, 463, 686,
173142 /* 30 */ 707, 725, 780, 1098, 856, 778, 1059, 1090, 708, 887,
173143 /* 40 */ 86, 448, 980, 630, 680, 681, 684, 796, 801, 796,
173144 /* 50 */ 801, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173145 /* 60 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173146 /* 70 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173147 /* 80 */ -261, -261, -261, -261, -261, -261, -261, -261, 391, 886,
173148 /* 90 */ 888, 1013, 1016, 1081, 1087, 1151, 1159, 1177, 1185, 1188,
173149 /* 100 */ 1190, 1194, 1197, 1203, 1247, 1260, 1264, 1267, 1269, 1273,
173150 /* 110 */ 1315, 1322, 1335, 1337, 1356, 1362, 1418, 1425, 1453, 1457,
173151 /* 120 */ 1465, 1473, 1487, 1495, 1507, 1517, 1521, 1534, 1543, 1546,
173152 /* 130 */ 1549, 1552, 1554, 1560, 1581, 1590, 1593, 1595, 1621, 1623,
173153 /* 140 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
173154 /* 150 */ -261, -186, -117, 260, 263, 460, 631, -74, 497, -181,
173155 /* 160 */ -261, 939, 176, 274, 338, 676, -261, -261, -261, -261,
173156 /* 170 */ -212, -212, -212, -184, 149, 777, 1061, 1103, 265, 419,
173157 /* 180 */ -254, 670, 677, 677, -11, -129, 184, 488, 736, 789,
173158 /* 190 */ 805, 844, 403, 529, 579, 668, 783, 841, 1158, 1112,
173159 /* 200 */ 806, 861, 1095, 846, 839, 1031, -189, 1077, 1080, 1116,
173160 /* 210 */ 1084, 1156, 1139, 1221, 46, 1099, 1037, 1118, 1171, 1214,
173161 /* 220 */ 1210, 1258, -210, -190, -176, -115, 117, 262, 376, 490,
173162 /* 230 */ 511, 520, 618, 639, 743, 901, 907, 958, 1014, 1055,
173163 /* 240 */ 1108, 1193, 1244, 720, 1248, 1277, 1324, 1347, 1417, 1431,
173164 /* 250 */ 1432, 1440, 1451, 1452, 1463, 1478, 1286, 1350, 1369, 1490,
173165 /* 260 */ 1498, 1501, 773, 1509, 1513, 1528, 1292, 1367, 1535, 1536,
173166 /* 270 */ 1477, 1542, 376, 1547, 1550, 1555, 1559, 1568, 1571, 1441,
173167 /* 280 */ 1443, 1474, 1511, 1516, 1519, 1522, 773, 1474, 1474, 1503,
173168 /* 290 */ 1567, 1594, 1484, 1527, 1556, 1570, 1557, 1524, 1573, 1545,
173169 /* 300 */ 1548, 1576, 1561, 1587, 1540, 1575, 1606, 1611, 1622, 1624,
173170 /* 310 */ 1626, 1582, 1597, 1598, 1599, 1601, 1603, 1563, 1608, 1605,
173171 /* 320 */ 1604, 1564, 1566, 1655, 1660, 1578, 1579, 1665, 1586, 1607,
173172 /* 330 */ 1610, 1642, 1641, 1645, 1646, 1647, 1679, 1688, 1644, 1618,
173173 /* 340 */ 1619, 1648, 1628, 1659, 1649, 1663, 1650, 1700, 1702, 1612,
173174 /* 350 */ 1615, 1706, 1708, 1689, 1709, 1712, 1713, 1715, 1691, 1698,
173175 /* 360 */ 1699, 1701, 1693, 1704, 1707, 1705, 1714, 1703, 1718, 1710,
173176 /* 370 */ 1720, 1721, 1632, 1634, 1664, 1666, 1729, 1751, 1635, 1636,
173177 /* 380 */ 1692, 1694, 1716, 1722, 1684, 1763, 1685, 1723, 1724, 1727,
173178 /* 390 */ 1730, 1768, 1783, 1784, 1793, 1794, 1796, 1683, 1686, 1690,
173179 /* 400 */ 1782, 1779, 1780, 1781, 1785, 1788, 1774, 1775, 1786, 1787,
173180 /* 410 */ 1789, 1798,
173181 };
173182 static const YYACTIONTYPE yy_default[] = {
173183 /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254,
173184 /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397,
173185 /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173186 /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254,
173187 /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254,
173188 /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254,
173189 /* 60 */ 1492, 1493, 1254, 1254, 1254, 1543, 1545, 1508, 1420, 1419,
173190 /* 70 */ 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, 1486,
173191 /* 80 */ 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, 1254,
173192 /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173193 /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173194 /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173195 /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173196 /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173197 /* 140 */ 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, 1456, 1458,
173198 /* 150 */ 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, 1254, 1254,
173199 /* 160 */ 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, 1473, 1472,
173200 /* 170 */ 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, 1254, 1254,
173201 /* 180 */ 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173202 /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173203 /* 200 */ 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, 1578, 1578,
173204 /* 210 */ 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, 1358, 1358,
173205 /* 220 */ 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173206 /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, 1546, 1254,
173207 /* 240 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173208 /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173209 /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, 1254, 1254,
173210 /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, 1254,
173211 /* 280 */ 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, 1357,
173212 /* 290 */ 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, 1423,
173213 /* 300 */ 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, 1397,
173214 /* 310 */ 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, 1357,
173215 /* 320 */ 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, 1638,
173216 /* 330 */ 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, 1638,
173217 /* 340 */ 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, 1525,
173218 /* 350 */ 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, 1330,
173219 /* 360 */ 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, 1319,
173220 /* 370 */ 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, 1588,
173221 /* 380 */ 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, 1401,
173222 /* 390 */ 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, 1558,
173223 /* 400 */ 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, 1288,
173224 /* 410 */ 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, 1254,
173225 /* 420 */ 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173226 /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1564,
173227 /* 440 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173228 /* 450 */ 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, 1254,
173229 /* 460 */ 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, 1254,
173230 /* 470 */ 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, 1254,
173231 /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, 1254,
173232 /* 490 */ 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, 1254,
173233 /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173234 /* 510 */ 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173235 /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173236 /* 530 */ 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, 1254,
173237 /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173238 /* 550 */ 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, 1254,
173239 /* 560 */ 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
173240 /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254,
173241 /* 580 */ 1266, 1254, 1254,
173242 };
173243 /********** End of lemon-generated parsing tables *****************************/
173244
@@ -173258,56 +174139,57 @@
173258 */
173259 #ifdef YYFALLBACK
173260 static const YYCODETYPE yyFallback[] = {
173261 0, /* $ => nothing */
173262 0, /* SEMI => nothing */
173263 59, /* EXPLAIN => ID */
173264 59, /* QUERY => ID */
173265 59, /* PLAN => ID */
173266 59, /* BEGIN => ID */
173267 0, /* TRANSACTION => nothing */
173268 59, /* DEFERRED => ID */
173269 59, /* IMMEDIATE => ID */
173270 59, /* EXCLUSIVE => ID */
173271 0, /* COMMIT => nothing */
173272 59, /* END => ID */
173273 59, /* ROLLBACK => ID */
173274 59, /* SAVEPOINT => ID */
173275 59, /* RELEASE => ID */
173276 0, /* TO => nothing */
173277 0, /* TABLE => nothing */
173278 0, /* CREATE => nothing */
173279 59, /* IF => ID */
173280 0, /* NOT => nothing */
173281 0, /* EXISTS => nothing */
173282 59, /* TEMP => ID */
173283 0, /* LP => nothing */
173284 0, /* RP => nothing */
173285 0, /* AS => nothing */
173286 0, /* COMMA => nothing */
173287 59, /* WITHOUT => ID */
173288 59, /* ABORT => ID */
173289 59, /* ACTION => ID */
173290 59, /* AFTER => ID */
173291 59, /* ANALYZE => ID */
173292 59, /* ASC => ID */
173293 59, /* ATTACH => ID */
173294 59, /* BEFORE => ID */
173295 59, /* BY => ID */
173296 59, /* CASCADE => ID */
173297 59, /* CAST => ID */
173298 59, /* CONFLICT => ID */
173299 59, /* DATABASE => ID */
173300 59, /* DESC => ID */
173301 59, /* DETACH => ID */
173302 59, /* EACH => ID */
173303 59, /* FAIL => ID */
173304 0, /* OR => nothing */
173305 0, /* AND => nothing */
173306 0, /* IS => nothing */
173307 59, /* MATCH => ID */
173308 59, /* LIKE_KW => ID */
 
173309 0, /* BETWEEN => nothing */
173310 0, /* IN => nothing */
173311 0, /* ISNULL => nothing */
173312 0, /* NOTNULL => nothing */
173313 0, /* NE => nothing */
@@ -173316,51 +174198,51 @@
173316 0, /* LE => nothing */
173317 0, /* LT => nothing */
173318 0, /* GE => nothing */
173319 0, /* ESCAPE => nothing */
173320 0, /* ID => nothing */
173321 59, /* COLUMNKW => ID */
173322 59, /* DO => ID */
173323 59, /* FOR => ID */
173324 59, /* IGNORE => ID */
173325 59, /* INITIALLY => ID */
173326 59, /* INSTEAD => ID */
173327 59, /* NO => ID */
173328 59, /* KEY => ID */
173329 59, /* OF => ID */
173330 59, /* OFFSET => ID */
173331 59, /* PRAGMA => ID */
173332 59, /* RAISE => ID */
173333 59, /* RECURSIVE => ID */
173334 59, /* REPLACE => ID */
173335 59, /* RESTRICT => ID */
173336 59, /* ROW => ID */
173337 59, /* ROWS => ID */
173338 59, /* TRIGGER => ID */
173339 59, /* VACUUM => ID */
173340 59, /* VIEW => ID */
173341 59, /* VIRTUAL => ID */
173342 59, /* WITH => ID */
173343 59, /* NULLS => ID */
173344 59, /* FIRST => ID */
173345 59, /* LAST => ID */
173346 59, /* CURRENT => ID */
173347 59, /* FOLLOWING => ID */
173348 59, /* PARTITION => ID */
173349 59, /* PRECEDING => ID */
173350 59, /* RANGE => ID */
173351 59, /* UNBOUNDED => ID */
173352 59, /* EXCLUDE => ID */
173353 59, /* GROUPS => ID */
173354 59, /* OTHERS => ID */
173355 59, /* TIES => ID */
173356 59, /* GENERATED => ID */
173357 59, /* ALWAYS => ID */
173358 59, /* MATERIALIZED => ID */
173359 59, /* REINDEX => ID */
173360 59, /* RENAME => ID */
173361 59, /* CTIME_KW => ID */
173362 0, /* ANY => nothing */
173363 0, /* BITAND => nothing */
173364 0, /* BITOR => nothing */
173365 0, /* LSHIFT => nothing */
173366 0, /* RSHIFT => nothing */
@@ -173427,14 +174309,13 @@
173427 0, /* FILTER => nothing */
173428 0, /* COLUMN => nothing */
173429 0, /* AGG_FUNCTION => nothing */
173430 0, /* AGG_COLUMN => nothing */
173431 0, /* TRUEFALSE => nothing */
173432 0, /* ISNOT => nothing */
173433 0, /* FUNCTION => nothing */
173434 0, /* UMINUS => nothing */
173435 0, /* UPLUS => nothing */
 
173436 0, /* TRUTH => nothing */
173437 0, /* REGISTER => nothing */
173438 0, /* VECTOR => nothing */
173439 0, /* SELECT_COLUMN => nothing */
173440 0, /* IF_NULL_ROW => nothing */
@@ -173571,139 +174452,139 @@
173571 /* 41 */ "EACH",
173572 /* 42 */ "FAIL",
173573 /* 43 */ "OR",
173574 /* 44 */ "AND",
173575 /* 45 */ "IS",
173576 /* 46 */ "MATCH",
173577 /* 47 */ "LIKE_KW",
173578 /* 48 */ "BETWEEN",
173579 /* 49 */ "IN",
173580 /* 50 */ "ISNULL",
173581 /* 51 */ "NOTNULL",
173582 /* 52 */ "NE",
173583 /* 53 */ "EQ",
173584 /* 54 */ "GT",
173585 /* 55 */ "LE",
173586 /* 56 */ "LT",
173587 /* 57 */ "GE",
173588 /* 58 */ "ESCAPE",
173589 /* 59 */ "ID",
173590 /* 60 */ "COLUMNKW",
173591 /* 61 */ "DO",
173592 /* 62 */ "FOR",
173593 /* 63 */ "IGNORE",
173594 /* 64 */ "INITIALLY",
173595 /* 65 */ "INSTEAD",
173596 /* 66 */ "NO",
173597 /* 67 */ "KEY",
173598 /* 68 */ "OF",
173599 /* 69 */ "OFFSET",
173600 /* 70 */ "PRAGMA",
173601 /* 71 */ "RAISE",
173602 /* 72 */ "RECURSIVE",
173603 /* 73 */ "REPLACE",
173604 /* 74 */ "RESTRICT",
173605 /* 75 */ "ROW",
173606 /* 76 */ "ROWS",
173607 /* 77 */ "TRIGGER",
173608 /* 78 */ "VACUUM",
173609 /* 79 */ "VIEW",
173610 /* 80 */ "VIRTUAL",
173611 /* 81 */ "WITH",
173612 /* 82 */ "NULLS",
173613 /* 83 */ "FIRST",
173614 /* 84 */ "LAST",
173615 /* 85 */ "CURRENT",
173616 /* 86 */ "FOLLOWING",
173617 /* 87 */ "PARTITION",
173618 /* 88 */ "PRECEDING",
173619 /* 89 */ "RANGE",
173620 /* 90 */ "UNBOUNDED",
173621 /* 91 */ "EXCLUDE",
173622 /* 92 */ "GROUPS",
173623 /* 93 */ "OTHERS",
173624 /* 94 */ "TIES",
173625 /* 95 */ "GENERATED",
173626 /* 96 */ "ALWAYS",
173627 /* 97 */ "MATERIALIZED",
173628 /* 98 */ "REINDEX",
173629 /* 99 */ "RENAME",
173630 /* 100 */ "CTIME_KW",
173631 /* 101 */ "ANY",
173632 /* 102 */ "BITAND",
173633 /* 103 */ "BITOR",
173634 /* 104 */ "LSHIFT",
173635 /* 105 */ "RSHIFT",
173636 /* 106 */ "PLUS",
173637 /* 107 */ "MINUS",
173638 /* 108 */ "STAR",
173639 /* 109 */ "SLASH",
173640 /* 110 */ "REM",
173641 /* 111 */ "CONCAT",
173642 /* 112 */ "PTR",
173643 /* 113 */ "COLLATE",
173644 /* 114 */ "BITNOT",
173645 /* 115 */ "ON",
173646 /* 116 */ "INDEXED",
173647 /* 117 */ "STRING",
173648 /* 118 */ "JOIN_KW",
173649 /* 119 */ "CONSTRAINT",
173650 /* 120 */ "DEFAULT",
173651 /* 121 */ "NULL",
173652 /* 122 */ "PRIMARY",
173653 /* 123 */ "UNIQUE",
173654 /* 124 */ "CHECK",
173655 /* 125 */ "REFERENCES",
173656 /* 126 */ "AUTOINCR",
173657 /* 127 */ "INSERT",
173658 /* 128 */ "DELETE",
173659 /* 129 */ "UPDATE",
173660 /* 130 */ "SET",
173661 /* 131 */ "DEFERRABLE",
173662 /* 132 */ "FOREIGN",
173663 /* 133 */ "DROP",
173664 /* 134 */ "UNION",
173665 /* 135 */ "ALL",
173666 /* 136 */ "EXCEPT",
173667 /* 137 */ "INTERSECT",
173668 /* 138 */ "SELECT",
173669 /* 139 */ "VALUES",
173670 /* 140 */ "DISTINCT",
173671 /* 141 */ "DOT",
173672 /* 142 */ "FROM",
173673 /* 143 */ "JOIN",
173674 /* 144 */ "USING",
173675 /* 145 */ "ORDER",
173676 /* 146 */ "GROUP",
173677 /* 147 */ "HAVING",
173678 /* 148 */ "LIMIT",
173679 /* 149 */ "WHERE",
173680 /* 150 */ "RETURNING",
173681 /* 151 */ "INTO",
173682 /* 152 */ "NOTHING",
173683 /* 153 */ "FLOAT",
173684 /* 154 */ "BLOB",
173685 /* 155 */ "INTEGER",
173686 /* 156 */ "VARIABLE",
173687 /* 157 */ "CASE",
173688 /* 158 */ "WHEN",
173689 /* 159 */ "THEN",
173690 /* 160 */ "ELSE",
173691 /* 161 */ "INDEX",
173692 /* 162 */ "ALTER",
173693 /* 163 */ "ADD",
173694 /* 164 */ "WINDOW",
173695 /* 165 */ "OVER",
173696 /* 166 */ "FILTER",
173697 /* 167 */ "COLUMN",
173698 /* 168 */ "AGG_FUNCTION",
173699 /* 169 */ "AGG_COLUMN",
173700 /* 170 */ "TRUEFALSE",
173701 /* 171 */ "ISNOT",
173702 /* 172 */ "FUNCTION",
173703 /* 173 */ "UMINUS",
173704 /* 174 */ "UPLUS",
173705 /* 175 */ "TRUTH",
173706 /* 176 */ "REGISTER",
173707 /* 177 */ "VECTOR",
173708 /* 178 */ "SELECT_COLUMN",
173709 /* 179 */ "IF_NULL_ROW",
@@ -174134,11 +175015,11 @@
174134 /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
174135 /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
174136 /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
174137 /* 278 */ "trigger_cmd ::= scanpt select scanpt",
174138 /* 279 */ "expr ::= RAISE LP IGNORE RP",
174139 /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
174140 /* 281 */ "raisetype ::= ROLLBACK",
174141 /* 282 */ "raisetype ::= ABORT",
174142 /* 283 */ "raisetype ::= FAIL",
174143 /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
174144 /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
@@ -175059,11 +175940,11 @@
175059 293, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
175060 293, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
175061 293, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
175062 293, /* (278) trigger_cmd ::= scanpt select scanpt */
175063 218, /* (279) expr ::= RAISE LP IGNORE RP */
175064 218, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
175065 237, /* (281) raisetype ::= ROLLBACK */
175066 237, /* (282) raisetype ::= ABORT */
175067 237, /* (283) raisetype ::= FAIL */
175068 191, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
175069 191, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -175473,11 +176354,11 @@
175473 -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
175474 -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
175475 -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
175476 -3, /* (278) trigger_cmd ::= scanpt select scanpt */
175477 -4, /* (279) expr ::= RAISE LP IGNORE RP */
175478 -6, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
175479 -1, /* (281) raisetype ::= ROLLBACK */
175480 -1, /* (282) raisetype ::= ABORT */
175481 -1, /* (283) raisetype ::= FAIL */
175482 -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
175483 -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -176560,12 +177441,21 @@
176560 case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
176561 {yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/}
176562 break;
176563 case 216: /* expr ::= PLUS|MINUS expr */
176564 {
176565 yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy454, 0);
176566 /*A-overwrites-B*/
 
 
 
 
 
 
 
 
 
176567 }
176568 break;
176569 case 217: /* expr ::= expr PTR expr */
176570 {
176571 ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454);
@@ -176849,13 +177739,13 @@
176849 if( yymsp[-3].minor.yy454 ){
176850 yymsp[-3].minor.yy454->affExpr = OE_Ignore;
176851 }
176852 }
176853 break;
176854 case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
176855 {
176856 yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
176857 if( yymsp[-5].minor.yy454 ) {
176858 yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
176859 }
176860 }
176861 break;
@@ -202282,11 +203172,11 @@
202282 }else{
202283 iScore += 1000;
202284 }
202285 mCover |= mPhrase;
202286
202287 for(j=0; j<pPhrase->nToken; j++){
202288 mHighlight |= (mPos>>j);
202289 }
202290
202291 if( 0==(*pCsr & 0x0FE) ) break;
202292 fts3GetDeltaPosition(&pCsr, &iCsr);
@@ -208175,17 +209065,10 @@
208175 }
208176 if( !eErr ) sqlite3_result_int64(ctx, cnt);
208177 jsonParseFree(p);
208178 }
208179
208180 /* True if the string is all digits */
208181 static int jsonAllDigits(const char *z, int n){
208182 int i;
208183 for(i=0; i<n && sqlite3Isdigit(z[i]); i++){}
208184 return i==n;
208185 }
208186
208187 /* True if the string is all alphanumerics and underscores */
208188 static int jsonAllAlphanum(const char *z, int n){
208189 int i;
208190 for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){}
208191 return i==n;
@@ -208244,14 +209127,20 @@
208244 ** convenience.
208245 **
208246 ** NUMBER ==> $[NUMBER] // PG compatible
208247 ** LABEL ==> $.LABEL // PG compatible
208248 ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
 
 
 
 
 
208249 */
208250 jsonStringInit(&jx, ctx);
208251 if( jsonAllDigits(zPath, nPath) ){
208252 jsonAppendRawNZ(&jx, "[", 1);
 
208253 jsonAppendRaw(&jx, zPath, nPath);
208254 jsonAppendRawNZ(&jx, "]", 2);
208255 }else if( jsonAllAlphanum(zPath, nPath) ){
208256 jsonAppendRawNZ(&jx, ".", 1);
208257 jsonAppendRaw(&jx, zPath, nPath);
@@ -216631,11 +217520,11 @@
216631 const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
216632 const char *zName; /* SQL Collation sequence name (eg. "japanese") */
216633 UCollator *pUCollator; /* ICU library collation object */
216634 int rc; /* Return code from sqlite3_create_collation_x() */
216635
216636 assert(nArg==2);
216637 (void)nArg; /* Unused parameter */
216638 zLocale = (const char *)sqlite3_value_text(apArg[0]);
216639 zName = (const char *)sqlite3_value_text(apArg[1]);
216640
216641 if( !zLocale || !zName ){
@@ -216646,11 +217535,43 @@
216646 if( !U_SUCCESS(status) ){
216647 icuFunctionError(p, "ucol_open", status);
216648 return;
216649 }
216650 assert(p);
216651
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216652 rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
216653 icuCollationColl, icuCollationDel
216654 );
216655 if( rc!=SQLITE_OK ){
216656 ucol_close(pUCollator);
@@ -216669,10 +217590,11 @@
216669 unsigned int enc; /* Optimal text encoding */
216670 unsigned char iContext; /* sqlite3_user_data() context */
216671 void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
216672 } scalars[] = {
216673 {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
 
216674 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
216675 {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
216676 {"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
216677 {"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
216678 {"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
@@ -228072,18 +228994,18 @@
228072 ** sufficient either for the 'T' or 'P' byte and the varint that follows
228073 ** it, or for the two single byte values otherwise. */
228074 p->rc = sessionInputBuffer(&p->in, 2);
228075 if( p->rc!=SQLITE_OK ) return p->rc;
228076
 
 
 
228077 /* If the iterator is already at the end of the changeset, return DONE. */
228078 if( p->in.iNext>=p->in.nData ){
228079 return SQLITE_DONE;
228080 }
228081
228082 sessionDiscardData(&p->in);
228083 p->in.iCurrent = p->in.iNext;
228084
228085 op = p->in.aData[p->in.iNext++];
228086 while( op=='T' || op=='P' ){
228087 if( pbNew ) *pbNew = 1;
228088 p->bPatchset = (op=='P');
228089 if( sessionChangesetReadTblhdr(p) ) return p->rc;
@@ -229814,10 +230736,11 @@
229814 */
229815 struct sqlite3_changegroup {
229816 int rc; /* Error code */
229817 int bPatch; /* True to accumulate patchsets */
229818 SessionTable *pList; /* List of tables in current patch */
 
229819
229820 sqlite3 *db; /* Configured by changegroup_schema() */
229821 char *zDb; /* Configured by changegroup_schema() */
229822 };
229823
@@ -230112,112 +231035,132 @@
230112
230113 return rc;
230114 }
230115
230116 /*
230117 ** Add all changes in the changeset traversed by the iterator passed as
230118 ** the first argument to the changegroup hash tables.
 
 
 
230119 */
230120 static int sessionChangesetToHash(
230121 sqlite3_changeset_iter *pIter, /* Iterator to read from */
230122 sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
230123 int bRebase /* True if hash table is for rebasing */
 
230124 ){
230125 u8 *aRec;
230126 int nRec;
230127 int rc = SQLITE_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230128 SessionTable *pTab = 0;
230129 SessionBuffer rec = {0, 0, 0};
230130
230131 while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
230132 const char *zNew;
230133 int nCol;
230134 int op;
230135 int iHash;
230136 int bIndirect;
230137 SessionChange *pChange;
230138 SessionChange *pExist = 0;
230139 SessionChange **pp;
230140
230141 /* Ensure that only changesets, or only patchsets, but not a mixture
230142 ** of both, are being combined. It is an error to try to combine a
230143 ** changeset and a patchset. */
230144 if( pGrp->pList==0 ){
230145 pGrp->bPatch = pIter->bPatchset;
230146 }else if( pIter->bPatchset!=pGrp->bPatch ){
230147 rc = SQLITE_ERROR;
230148 break;
230149 }
230150
230151 sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect);
230152 if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){
230153 /* Search the list for a matching table */
230154 int nNew = (int)strlen(zNew);
230155 u8 *abPK;
230156
230157 sqlite3changeset_pk(pIter, &abPK, 0);
230158 for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
230159 if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
230160 }
230161 if( !pTab ){
230162 SessionTable **ppTab;
230163
230164 pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
230165 if( !pTab ){
230166 rc = SQLITE_NOMEM;
230167 break;
230168 }
230169 memset(pTab, 0, sizeof(SessionTable));
230170 pTab->nCol = nCol;
230171 pTab->abPK = (u8*)&pTab[1];
230172 memcpy(pTab->abPK, abPK, nCol);
230173 pTab->zName = (char*)&pTab->abPK[nCol];
230174 memcpy(pTab->zName, zNew, nNew+1);
230175
230176 if( pGrp->db ){
230177 pTab->nCol = 0;
230178 rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
230179 if( rc ){
230180 assert( pTab->azCol==0 );
230181 sqlite3_free(pTab);
230182 break;
230183 }
230184 }
230185
230186 /* The new object must be linked on to the end of the list, not
230187 ** simply added to the start of it. This is to ensure that the
230188 ** tables within the output of sqlite3changegroup_output() are in
230189 ** the right order. */
230190 for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext);
230191 *ppTab = pTab;
230192 }
230193
230194 if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
230195 rc = SQLITE_SCHEMA;
230196 break;
230197 }
230198 }
230199
230200 if( nCol<pTab->nCol ){
230201 assert( pGrp->db );
230202 rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, &rec);
230203 if( rc ) break;
230204 aRec = rec.aBuf;
230205 nRec = rec.nBuf;
230206 }
230207
230208 if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
230209 rc = SQLITE_NOMEM;
230210 break;
230211 }
230212 iHash = sessionChangeHash(
230213 pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
230214 );
230215
230216 /* Search for existing entry. If found, remove it from the hash table.
230217 ** Code below may link it back in.
230218 */
230219 for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
230220 int bPkOnly1 = 0;
230221 int bPkOnly2 = 0;
230222 if( pIter->bPatchset ){
230223 bPkOnly1 = (*pp)->op==SQLITE_DELETE;
@@ -230228,23 +231171,45 @@
230228 *pp = (*pp)->pNext;
230229 pTab->nEntry--;
230230 break;
230231 }
230232 }
 
230233
 
230234 rc = sessionChangeMerge(pTab, bRebase,
230235 pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
230236 );
230237 if( rc ) break;
230238 if( pChange ){
230239 pChange->pNext = pTab->apChange[iHash];
230240 pTab->apChange[iHash] = pChange;
230241 pTab->nEntry++;
230242 }
230243 }
230244
230245 sqlite3_free(rec.aBuf);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230246 if( rc==SQLITE_OK ) rc = pIter->rc;
230247 return rc;
230248 }
230249
230250 /*
@@ -230367,10 +231332,27 @@
230367 rc = sessionChangesetToHash(pIter, pGrp, 0);
230368 }
230369 sqlite3changeset_finalize(pIter);
230370 return rc;
230371 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230372
230373 /*
230374 ** Obtain a buffer containing a changeset representing the concatenation
230375 ** of all changesets added to the group so far.
230376 */
@@ -230417,10 +231399,11 @@
230417 */
230418 SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
230419 if( pGrp ){
230420 sqlite3_free(pGrp->zDb);
230421 sessionDeleteTable(0, pGrp->pList);
 
230422 sqlite3_free(pGrp);
230423 }
230424 }
230425
230426 /*
@@ -230818,10 +231801,11 @@
230818 ** Destroy a rebaser object
230819 */
230820 SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
230821 if( p ){
230822 sessionDeleteTable(0, p->grp.pList);
 
230823 sqlite3_free(p);
230824 }
230825 }
230826
230827 /*
@@ -230915,12 +231899,12 @@
230915
230916 /*
230917 ** EXTENSION API FUNCTIONS
230918 **
230919 ** xUserData(pFts):
230920 ** Return a copy of the context pointer the extension function was
230921 ** registered with.
230922 **
230923 ** xColumnTotalSize(pFts, iCol, pnToken):
230924 ** If parameter iCol is less than zero, set output variable *pnToken
230925 ** to the total number of tokens in the FTS5 table. Or, if iCol is
230926 ** non-negative but less than the number of columns in the table, return
@@ -231097,10 +232081,14 @@
231097 ** This API can be quite slow if used with an FTS5 table created with the
231098 ** "detail=none" or "detail=column" option. If the FTS5 table is created
231099 ** with either "detail=none" or "detail=column" and "content=" option
231100 ** (i.e. if it is a contentless table), then this API always iterates
231101 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
 
 
 
 
231102 **
231103 ** xPhraseNext()
231104 ** See xPhraseFirst above.
231105 **
231106 ** xPhraseFirstColumn()
@@ -231628,10 +232616,19 @@
231628 ** Interface to code in fts5_config.c. fts5_config.c contains contains code
231629 ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
231630 */
231631
231632 typedef struct Fts5Config Fts5Config;
 
 
 
 
 
 
 
 
 
231633
231634 /*
231635 ** An instance of the following structure encodes all information that can
231636 ** be gleaned from the CREATE VIRTUAL TABLE statement.
231637 **
@@ -231670,10 +232667,11 @@
231670 ** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
231671 **
231672 */
231673 struct Fts5Config {
231674 sqlite3 *db; /* Database handle */
 
231675 char *zDb; /* Database holding FTS index (e.g. "main") */
231676 char *zName; /* Name of FTS index */
231677 int nCol; /* Number of columns */
231678 char **azCol; /* Column names */
231679 u8 *abUnindexed; /* True for unindexed columns */
@@ -231685,14 +232683,12 @@
231685 char *zContentRowid; /* "content_rowid=" option value */
231686 int bColumnsize; /* "columnsize=" option value (dflt==1) */
231687 int bTokendata; /* "tokendata=" option value (dflt==0) */
231688 int eDetail; /* FTS5_DETAIL_XXX value */
231689 char *zContentExprlist;
231690 Fts5Tokenizer *pTok;
231691 fts5_tokenizer *pTokApi;
231692 int bLock; /* True when table is preparing statement */
231693 int ePattern; /* FTS_PATTERN_XXX constant */
231694
231695 /* Values loaded from the %_config table */
231696 int iVersion; /* fts5 file format 'version' */
231697 int iCookie; /* Incremented when %_config is modified */
231698 int pgsz; /* Approximate page size used in %_data */
@@ -232083,17 +233079,11 @@
232083 sqlite3_vtab base; /* Base class used by SQLite core */
232084 Fts5Config *pConfig; /* Virtual table configuration */
232085 Fts5Index *pIndex; /* Full-text index */
232086 };
232087
232088 static int sqlite3Fts5GetTokenizer(
232089 Fts5Global*,
232090 const char **azArg,
232091 int nArg,
232092 Fts5Config*,
232093 char **pzErr
232094 );
232095
232096 static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
232097
232098 static int sqlite3Fts5FlushToDisk(Fts5Table*);
232099
@@ -232352,10 +233342,11 @@
232352 static int sqlite3Fts5TokenizerInit(fts5_api*);
232353 static int sqlite3Fts5TokenizerPattern(
232354 int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
232355 Fts5Tokenizer *pTok
232356 );
 
232357 /*
232358 ** End of interface to code in fts5_tokenizer.c.
232359 **************************************************************************/
232360
232361 /**************************************************************************
@@ -235303,11 +236294,10 @@
235303 ** an error occurs, an SQLite error code is returned and an error message
235304 ** may be left in *pzErr. It is the responsibility of the caller to
235305 ** eventually free any such error message using sqlite3_free().
235306 */
235307 static int fts5ConfigParseSpecial(
235308 Fts5Global *pGlobal,
235309 Fts5Config *pConfig, /* Configuration object to update */
235310 const char *zCmd, /* Special command to parse */
235311 const char *zArg, /* Argument to parse */
235312 char **pzErr /* OUT: Error message */
235313 ){
@@ -235367,16 +236357,15 @@
235367 }
235368
235369 if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
235370 const char *p = (const char*)zArg;
235371 sqlite3_int64 nArg = strlen(zArg) + 1;
235372 char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
235373 char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
235374 char *pSpace = pDel;
235375
235376 if( azArg && pSpace ){
235377 if( pConfig->pTok ){
 
235378 *pzErr = sqlite3_mprintf("multiple tokenize=... directives");
235379 rc = SQLITE_ERROR;
235380 }else{
235381 for(nArg=0; p && *p; nArg++){
235382 const char *p2 = fts5ConfigSkipWhitespace(p);
@@ -235395,20 +236384,18 @@
235395 }
235396 if( p==0 ){
235397 *pzErr = sqlite3_mprintf("parse error in tokenize directive");
235398 rc = SQLITE_ERROR;
235399 }else{
235400 rc = sqlite3Fts5GetTokenizer(pGlobal,
235401 (const char**)azArg, (int)nArg, pConfig,
235402 pzErr
235403 );
235404 }
235405 }
235406 }
235407
235408 sqlite3_free(azArg);
235409 sqlite3_free(pDel);
235410 return rc;
235411 }
235412
235413 if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
235414 if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
@@ -235481,20 +236468,10 @@
235481
235482 *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
235483 return SQLITE_ERROR;
235484 }
235485
235486 /*
235487 ** Allocate an instance of the default tokenizer ("simple") at
235488 ** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
235489 ** code if an error occurs.
235490 */
235491 static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
235492 assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
235493 return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
235494 }
235495
235496 /*
235497 ** Gobble up the first bareword or quoted word from the input buffer zIn.
235498 ** Return a pointer to the character immediately following the last in
235499 ** the gobbled word if successful, or a NULL pointer otherwise (failed
235500 ** to find close-quote character).
@@ -235623,10 +236600,11 @@
235623 sqlite3_int64 nByte;
235624
235625 *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
235626 if( pRet==0 ) return SQLITE_NOMEM;
235627 memset(pRet, 0, sizeof(Fts5Config));
 
235628 pRet->db = db;
235629 pRet->iCookie = -1;
235630
235631 nByte = nArg * (sizeof(char*) + sizeof(u8));
235632 pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -235671,11 +236649,11 @@
235671 if( z==0 ){
235672 *pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
235673 rc = SQLITE_ERROR;
235674 }else{
235675 if( bOption ){
235676 rc = fts5ConfigParseSpecial(pGlobal, pRet,
235677 ALWAYS(zOne)?zOne:"",
235678 zTwo?zTwo:"",
235679 pzErr
235680 );
235681 }else{
@@ -235709,17 +236687,10 @@
235709 "contentless_delete=1 is incompatible with columnsize=0"
235710 );
235711 rc = SQLITE_ERROR;
235712 }
235713
235714 /* If a tokenizer= option was successfully parsed, the tokenizer has
235715 ** already been allocated. Otherwise, allocate an instance of the default
235716 ** tokenizer (unicode61) now. */
235717 if( rc==SQLITE_OK && pRet->pTok==0 ){
235718 rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
235719 }
235720
235721 /* If no zContent option was specified, fill in the default values. */
235722 if( rc==SQLITE_OK && pRet->zContent==0 ){
235723 const char *zTail = 0;
235724 assert( pRet->eContent==FTS5_CONTENT_NORMAL
235725 || pRet->eContent==FTS5_CONTENT_NONE
@@ -235757,13 +236728,14 @@
235757 ** Free the configuration object passed as the only argument.
235758 */
235759 static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
235760 if( pConfig ){
235761 int i;
235762 if( pConfig->pTok ){
235763 pConfig->pTokApi->xDelete(pConfig->pTok);
235764 }
 
235765 sqlite3_free(pConfig->zDb);
235766 sqlite3_free(pConfig->zName);
235767 for(i=0; i<pConfig->nCol; i++){
235768 sqlite3_free(pConfig->azCol[i]);
235769 }
@@ -235834,14 +236806,22 @@
235834 int flags, /* FTS5_TOKENIZE_* flags */
235835 const char *pText, int nText, /* Text to tokenize */
235836 void *pCtx, /* Context passed to xToken() */
235837 int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
235838 ){
235839 if( pText==0 ) return SQLITE_OK;
235840 return pConfig->pTokApi->xTokenize(
235841 pConfig->pTok, pCtx, flags, pText, nText, xToken
235842 );
 
 
 
 
 
 
 
 
235843 }
235844
235845 /*
235846 ** Argument pIn points to the first character in what is expected to be
235847 ** a comma-separated list of SQL literals followed by a ')' character.
@@ -236434,11 +237414,15 @@
236434 }else{
236435 sqlite3Fts5ParseNodeFree(sParse.pExpr);
236436 }
236437
236438 sqlite3_free(sParse.apPhrase);
236439 *pzErr = sParse.zErr;
 
 
 
 
236440 return sParse.rc;
236441 }
236442
236443 /*
236444 ** Assuming that buffer z is at least nByte bytes in size and contains a
@@ -237981,10 +238965,11 @@
237981 ** no token characters at all. (e.g ... MATCH '""'). */
237982 sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
237983 }else if( sCtx.pPhrase->nTerm ){
237984 sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
237985 }
 
237986 pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
237987 }
237988
237989 return sCtx.pPhrase;
237990 }
@@ -238000,11 +238985,11 @@
238000 ){
238001 int rc = SQLITE_OK; /* Return code */
238002 Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
238003 Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
238004 TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
238005 if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
238006 rc = SQLITE_RANGE;
238007 }else{
238008 pOrig = pExpr->apExprPhrase[iPhrase];
238009 pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
238010 }
@@ -238575,10 +239560,12 @@
238575 || pPrev->eType==FTS5_TERM
238576 || pPrev->eType==FTS5_EOF
238577 );
238578
238579 if( pRight->eType==FTS5_EOF ){
 
 
238580 assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
238581 sqlite3Fts5ParseNodeFree(pRight);
238582 pRet = pLeft;
238583 pParse->nPhrase--;
238584 }
@@ -249406,12 +250393,16 @@
249406 if( rc==SQLITE_OK ){
249407 rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
249408 assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
249409 }
249410 if( rc==SQLITE_OK ){
 
249411 pTab->p.pConfig = pConfig;
249412 pTab->pGlobal = pGlobal;
 
 
 
249413 }
249414
249415 /* Open the index sub-system */
249416 if( rc==SQLITE_OK ){
249417 rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
@@ -249429,24 +250420,22 @@
249429 rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
249430 }
249431
249432 /* Load the initial configuration */
249433 if( rc==SQLITE_OK ){
249434 assert( pConfig->pzErrmsg==0 );
249435 pConfig->pzErrmsg = pzErr;
249436 rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
249437 sqlite3Fts5IndexRollback(pTab->p.pIndex);
249438 pConfig->pzErrmsg = 0;
249439 }
249440
249441 if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
249442 rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1);
249443 }
249444 if( rc==SQLITE_OK ){
249445 rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
249446 }
249447
 
249448 if( rc!=SQLITE_OK ){
249449 fts5FreeVtab(pTab);
249450 pTab = 0;
249451 }else if( bCreate ){
249452 fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
@@ -249510,14 +250499,14 @@
249510 Fts5Config *pConfig,
249511 struct sqlite3_index_constraint *p
249512 ){
249513 assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
249514 assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
249515 if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
249516 return 1;
249517 }
249518 if( pConfig->ePattern==FTS5_PATTERN_LIKE
249519 && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
249520 ){
249521 return 1;
249522 }
249523 return 0;
@@ -249560,15 +250549,15 @@
249560 ** A > or >= against the rowid: ">"
249561 **
249562 ** This function ensures that there is at most one "r" or "=". And that if
249563 ** there exists an "=" then there is no "<" or ">".
249564 **
 
 
 
249565 ** Costs are assigned as follows:
249566 **
249567 ** a) If an unusable MATCH operator is present in the WHERE clause, the
249568 ** cost is unconditionally set to 1e50 (a really big number).
249569 **
249570 ** a) If a MATCH operator is present, the cost depends on the other
249571 ** constraints also present. As follows:
249572 **
249573 ** * No other constraints: cost=1000.0
249574 ** * One rowid range constraint: cost=750.0
@@ -249596,11 +250585,11 @@
249596 int iCons = 0;
249597
249598 int bSeenEq = 0;
249599 int bSeenGt = 0;
249600 int bSeenLt = 0;
249601 int bSeenMatch = 0;
249602 int bSeenRank = 0;
249603
249604
249605 assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
249606 assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
@@ -249627,22 +250616,19 @@
249627 || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
249628 ){
249629 /* A MATCH operator or equivalent */
249630 if( p->usable==0 || iCol<0 ){
249631 /* As there exists an unusable MATCH constraint this is an
249632 ** unusable plan. Set a prohibitively high cost. */
249633 pInfo->estimatedCost = 1e50;
249634 assert( iIdxStr < pInfo->nConstraint*6 + 1 );
249635 idxStr[iIdxStr] = 0;
249636 return SQLITE_OK;
249637 }else{
249638 if( iCol==nCol+1 ){
249639 if( bSeenRank ) continue;
249640 idxStr[iIdxStr++] = 'r';
249641 bSeenRank = 1;
249642 }else if( iCol>=0 ){
249643 bSeenMatch = 1;
249644 idxStr[iIdxStr++] = 'M';
249645 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
249646 idxStr += strlen(&idxStr[iIdxStr]);
249647 assert( idxStr[iIdxStr]=='\0' );
249648 }
@@ -249655,10 +250641,11 @@
249655 idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
249656 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
249657 idxStr += strlen(&idxStr[iIdxStr]);
249658 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
249659 assert( idxStr[iIdxStr]=='\0' );
 
249660 }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
249661 idxStr[iIdxStr++] = '=';
249662 bSeenEq = 1;
249663 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
249664 }
@@ -249691,11 +250678,11 @@
249691 **
249692 ** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
249693 */
249694 if( pInfo->nOrderBy==1 ){
249695 int iSort = pInfo->aOrderBy[0].iColumn;
249696 if( iSort==(pConfig->nCol+1) && bSeenMatch ){
249697 idxFlags |= FTS5_BI_ORDER_RANK;
249698 }else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
249699 idxFlags |= FTS5_BI_ORDER_ROWID;
249700 }
249701 if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
@@ -249706,18 +250693,21 @@
249706 }
249707 }
249708
249709 /* Calculate the estimated cost based on the flags set in idxFlags. */
249710 if( bSeenEq ){
249711 pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
249712 if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
249713 }else if( bSeenLt && bSeenGt ){
249714 pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
249715 }else if( bSeenLt || bSeenGt ){
249716 pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
249717 }else{
249718 pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
 
 
 
249719 }
249720
249721 pInfo->idxNum = idxFlags;
249722 return SQLITE_OK;
249723 }
@@ -249989,10 +250979,11 @@
249989 "%s", sqlite3_errmsg(pConfig->db)
249990 );
249991 }
249992 }else{
249993 rc = SQLITE_OK;
 
249994 }
249995 break;
249996 }
249997 }
249998 }
@@ -250462,13 +251453,17 @@
250462 */
250463 static i64 fts5CursorRowid(Fts5Cursor *pCsr){
250464 assert( pCsr->ePlan==FTS5_PLAN_MATCH
250465 || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
250466 || pCsr->ePlan==FTS5_PLAN_SOURCE
 
 
250467 );
250468 if( pCsr->pSorter ){
250469 return pCsr->pSorter->iRowid;
 
 
250470 }else{
250471 return sqlite3Fts5ExprRowid(pCsr->pExpr);
250472 }
250473 }
250474
@@ -250481,24 +251476,14 @@
250481 static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
250482 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
250483 int ePlan = pCsr->ePlan;
250484
250485 assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
250486 switch( ePlan ){
250487 case FTS5_PLAN_SPECIAL:
250488 *pRowid = 0;
250489 break;
250490
250491 case FTS5_PLAN_SOURCE:
250492 case FTS5_PLAN_MATCH:
250493 case FTS5_PLAN_SORTED_MATCH:
250494 *pRowid = fts5CursorRowid(pCsr);
250495 break;
250496
250497 default:
250498 *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
250499 break;
250500 }
250501
250502 return SQLITE_OK;
250503 }
250504
@@ -250729,10 +251714,11 @@
250729 "'delete' may not be used with a contentless_delete=1 table"
250730 );
250731 rc = SQLITE_ERROR;
250732 }else{
250733 rc = fts5SpecialDelete(pTab, apVal);
 
250734 }
250735 }else{
250736 rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
250737 }
250738 }else{
@@ -251889,11 +252875,11 @@
251889 }
251890
251891 return rc;
251892 }
251893
251894 static int sqlite3Fts5GetTokenizer(
251895 Fts5Global *pGlobal,
251896 const char **azArg,
251897 int nArg,
251898 Fts5Config *pConfig,
251899 char **pzErr
@@ -251903,32 +252889,45 @@
251903
251904 pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
251905 if( pMod==0 ){
251906 assert( nArg>0 );
251907 rc = SQLITE_ERROR;
251908 *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
251909 }else{
251910 rc = pMod->x.xCreate(
251911 pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
251912 );
251913 pConfig->pTokApi = &pMod->x;
251914 if( rc!=SQLITE_OK ){
251915 if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
 
 
251916 }else{
251917 pConfig->ePattern = sqlite3Fts5TokenizerPattern(
251918 pMod->x.xCreate, pConfig->pTok
251919 );
251920 }
251921 }
251922
251923 if( rc!=SQLITE_OK ){
251924 pConfig->pTokApi = 0;
251925 pConfig->pTok = 0;
251926 }
251927
251928 return rc;
251929 }
 
 
 
 
 
 
 
 
 
 
 
251930
251931 static void fts5ModuleDestroy(void *pCtx){
251932 Fts5TokenizerModule *pTok, *pNextTok;
251933 Fts5Auxiliary *pAux, *pNextAux;
251934 Fts5Global *pGlobal = (Fts5Global*)pCtx;
@@ -251969,11 +252968,11 @@
251969 int nArg, /* Number of args */
251970 sqlite3_value **apUnused /* Function arguments */
251971 ){
251972 assert( nArg==0 );
251973 UNUSED_PARAM2(nArg, apUnused);
251974 sqlite3_result_text(pCtx, "fts5: 2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3", -1, SQLITE_TRANSIENT);
251975 }
251976
251977 /*
251978 ** Return true if zName is the extension on one of the shadow tables used
251979 ** by this module.
@@ -252004,21 +253003,27 @@
252004 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
252005 int rc;
252006
252007 assert( pzErr!=0 && *pzErr==0 );
252008 UNUSED_PARAM(isQuick);
 
 
252009 rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
252010 if( (rc&0xff)==SQLITE_CORRUPT ){
252011 *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
252012 zSchema, zTabname);
252013 rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
252014 }else if( rc!=SQLITE_OK ){
252015 *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
252016 " FTS5 table %s.%s: %s",
252017 zSchema, zTabname, sqlite3_errstr(rc));
252018 }
 
 
 
252019 sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
 
252020
252021 return rc;
252022 }
252023
252024 static int fts5Init(sqlite3 *db){
@@ -254796,10 +255801,20 @@
254796 return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
254797 }
254798 }
254799 return FTS5_PATTERN_NONE;
254800 }
 
 
 
 
 
 
 
 
 
 
254801
254802 /*
254803 ** Register all built-in tokenizers with FTS5.
254804 */
254805 static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -256016,10 +257031,11 @@
256016 Fts5IndexIter *pIter; /* Term/rowid iterator object */
256017 void *pStruct; /* From sqlite3Fts5StructureRef() */
256018
256019 int nLeTerm; /* Size of zLeTerm in bytes */
256020 char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
 
256021
256022 /* These are used by 'col' tables only */
256023 int iCol;
256024 i64 *aCnt;
256025 i64 *aDoc;
@@ -256042,13 +257058,15 @@
256042 #define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
256043
256044 /*
256045 ** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
256046 */
256047 #define FTS5_VOCAB_TERM_EQ 0x01
256048 #define FTS5_VOCAB_TERM_GE 0x02
256049 #define FTS5_VOCAB_TERM_LE 0x04
 
 
256050
256051
256052 /*
256053 ** Translate a string containing an fts5vocab table type to an
256054 ** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
@@ -256221,14 +257239,16 @@
256221 ){
256222 int i;
256223 int iTermEq = -1;
256224 int iTermGe = -1;
256225 int iTermLe = -1;
256226 int idxNum = 0;
256227 int nArg = 0;
256228
256229 UNUSED_PARAM(pUnused);
 
 
256230
256231 for(i=0; i<pInfo->nConstraint; i++){
256232 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
256233 if( p->usable==0 ) continue;
256234 if( p->iColumn==0 ){ /* term column */
@@ -256317,11 +257337,11 @@
256317 rc = sqlite3_finalize(pStmt);
256318 pStmt = 0;
256319 if( rc==SQLITE_OK ){
256320 pVTab->zErrMsg = sqlite3_mprintf(
256321 "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
256322 );
256323 rc = SQLITE_ERROR;
256324 }
256325 }else{
256326 rc = sqlite3Fts5FlushToDisk(pFts5);
256327 }
@@ -256477,13 +257497,23 @@
256477 pPos = pCsr->pIter->pData;
256478 nPos = pCsr->pIter->nData;
256479
256480 switch( pTab->eType ){
256481 case FTS5_VOCAB_ROW:
256482 if( eDetail==FTS5_DETAIL_FULL ){
256483 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
256484 pCsr->aCnt[0]++;
 
 
 
 
 
 
 
 
 
 
256485 }
256486 }
256487 pCsr->aDoc[0]++;
256488 break;
256489
@@ -256577,10 +257607,11 @@
256577
256578 fts5VocabResetCursor(pCsr);
256579 if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
256580 if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
256581 if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
 
256582
256583 if( pEq ){
256584 zTerm = (const char *)sqlite3_value_text(pEq);
256585 nTerm = sqlite3_value_bytes(pEq);
256586 f = FTS5INDEX_QUERY_NOTOKENDATA;
256587
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.47.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** baa83b460c677c210c7fa3f20314d7e05f30.
22 */
23 #define SQLITE_CORE 1
24 #define SQLITE_AMALGAMATION 1
25 #ifndef SQLITE_PRIVATE
26 # define SQLITE_PRIVATE static
@@ -254,14 +254,17 @@
254 #endif
255
256 /*
257 ** Macro to disable warnings about missing "break" at the end of a "case".
258 */
259 #if defined(__has_attribute)
260 # if __has_attribute(fallthrough)
261 # define deliberate_fall_through __attribute__((fallthrough));
262 # endif
263 #endif
264 #if !defined(deliberate_fall_through)
265 # define deliberate_fall_through
266 #endif
267
268 /*
269 ** For MinGW, check to see if we can include the header file containing its
270 ** version information, among other things. Normally, this internal MinGW
@@ -457,13 +460,13 @@
460 **
461 ** See also: [sqlite3_libversion()],
462 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
463 ** [sqlite_version()] and [sqlite_source_id()].
464 */
465 #define SQLITE_VERSION "3.47.0"
466 #define SQLITE_VERSION_NUMBER 3047000
467 #define SQLITE_SOURCE_ID "2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38"
468
469 /*
470 ** CAPI3REF: Run-Time Library Version Numbers
471 ** KEYWORDS: sqlite3_version sqlite3_sourceid
472 **
@@ -1083,12 +1086,12 @@
1086 ** xUnlock() downgrades the database file lock to either SHARED or NONE.
1087 ** If the lock is already at or below the requested lock state, then the call
1088 ** to xUnlock() is a no-op.
1089 ** The xCheckReservedLock() method checks whether any database connection,
1090 ** either in this process or in some other process, is holding a RESERVED,
1091 ** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
1092 ** pointer parameter, true if such a lock exists and false otherwise.
1093 **
1094 ** The xFileControl() method is a generic interface that allows custom
1095 ** VFS implementations to directly control an open file using the
1096 ** [sqlite3_file_control()] interface. The second "op" argument is an
1097 ** integer opcode. The third argument is a generic pointer intended to
@@ -3881,12 +3884,12 @@
3884 ** the default shared cache setting provided by
3885 ** [sqlite3_enable_shared_cache()].)^
3886 **
3887 ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
3888 ** <dd>The database connection comes up in "extended result code mode".
3889 ** In other words, the database behaves as if
3890 ** [sqlite3_extended_result_codes(db,1)] were called on the database
3891 ** connection as soon as the connection is created. In addition to setting
3892 ** the extended result code mode, this flag also causes [sqlite3_open_v2()]
3893 ** to return an extended result code.</dd>
3894 **
3895 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -7197,10 +7200,16 @@
7200 ** is not invoked when conflicting rows are deleted because of an
7201 ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
7202 ** invoked when rows are deleted using the [truncate optimization].
7203 ** The exceptions defined in this paragraph might change in a future
7204 ** release of SQLite.
7205 **
7206 ** Whether the update hook is invoked before or after the
7207 ** corresponding change is currently unspecified and may differ
7208 ** depending on the type of change. Do not rely on the order of the
7209 ** hook call with regards to the final result of the operation which
7210 ** triggers the hook.
7211 **
7212 ** The update hook implementation must not do anything that will modify
7213 ** the database connection that invoked the update hook. Any actions
7214 ** to modify the database connection must be deferred until after the
7215 ** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8668,11 +8677,11 @@
8677 ** by enclosing in double-quotes) so as not to confuse the parser.
8678 **
8679 ** The sqlite3_keyword_count() interface returns the number of distinct
8680 ** keywords understood by SQLite.
8681 **
8682 ** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
8683 ** makes *Z point to that keyword expressed as UTF8 and writes the number
8684 ** of bytes in the keyword into *L. The string that *Z points to is not
8685 ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
8686 ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
8687 ** or L are NULL or invalid pointers then calls to
@@ -10247,27 +10256,48 @@
10256 ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
10257 ** is doing a GROUP BY.
10258 ** <li value="2"><p>
10259 ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
10260 ** that the query planner does not need the rows returned in any particular
10261 ** order, as long as rows with the same values in all columns identified
10262 ** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
10263 ** contain the same values for all columns identified by "colUsed", all but
10264 ** one such row may optionally be omitted from the result.)^
10265 ** The virtual table is not required to omit rows that are duplicates
10266 ** over the "colUsed" columns, but if the virtual table can do that without
10267 ** too much extra effort, it could potentially help the query to run faster.
 
10268 ** This mode is used for a DISTINCT query.
10269 ** <li value="3"><p>
10270 ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
10271 ** virtual table must return rows in the order defined by "aOrderBy" as
10272 ** if the sqlite3_vtab_distinct() interface had returned 0. However if
10273 ** two or more rows in the result have the same values for all columns
10274 ** identified by "colUsed", then all but one such row may optionally be
10275 ** omitted.)^ Like when the return value is 2, the virtual table
10276 ** is not required to omit rows that are duplicates over the "colUsed"
10277 ** columns, but if the virtual table can do that without
10278 ** too much extra effort, it could potentially help the query to run faster.
10279 ** This mode is used for queries
10280 ** that have both DISTINCT and ORDER BY clauses.
10281 ** </ol>
10282 **
10283 ** <p>The following table summarizes the conditions under which the
10284 ** virtual table is allowed to set the "orderByConsumed" flag based on
10285 ** the value returned by sqlite3_vtab_distinct(). This table is a
10286 ** restatement of the previous four paragraphs:
10287 **
10288 ** <table border=1 cellspacing=0 cellpadding=10 width="90%">
10289 ** <tr>
10290 ** <td valign="top">sqlite3_vtab_distinct() return value
10291 ** <td valign="top">Rows are returned in aOrderBy order
10292 ** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
10293 ** <td valign="top">Duplicates over all colUsed columns may be omitted
10294 ** <tr><td>0<td>yes<td>yes<td>no
10295 ** <tr><td>1<td>no<td>yes<td>no
10296 ** <tr><td>2<td>no<td>yes<td>yes
10297 ** <tr><td>3<td>yes<td>yes<td>yes
10298 ** </table>
10299 **
10300 ** ^For the purposes of comparing virtual table output values to see if the
10301 ** values are same value for sorting purposes, two NULL values are considered
10302 ** to be the same. In other words, the comparison operator is "IS"
10303 ** (or "IS NOT DISTINCT FROM") and not "==".
@@ -11116,12 +11146,10 @@
11146 #endif
11147
11148 #if defined(__wasi__)
11149 # undef SQLITE_WASI
11150 # define SQLITE_WASI 1
 
 
11151 # ifndef SQLITE_OMIT_LOAD_EXTENSION
11152 # define SQLITE_OMIT_LOAD_EXTENSION
11153 # endif
11154 # ifndef SQLITE_THREADSAFE
11155 # define SQLITE_THREADSAFE 0
@@ -12308,10 +12336,34 @@
12336 **
12337 ** In all cases, if an error occurs the state of the final contents of the
12338 ** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
12339 */
12340 SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
12341
12342 /*
12343 ** CAPI3REF: Add A Single Change To A Changegroup
12344 ** METHOD: sqlite3_changegroup
12345 **
12346 ** This function adds the single change currently indicated by the iterator
12347 ** passed as the second argument to the changegroup object. The rules for
12348 ** adding the change are just as described for [sqlite3changegroup_add()].
12349 **
12350 ** If the change is successfully added to the changegroup, SQLITE_OK is
12351 ** returned. Otherwise, an SQLite error code is returned.
12352 **
12353 ** The iterator must point to a valid entry when this function is called.
12354 ** If it does not, SQLITE_ERROR is returned and no change is added to the
12355 ** changegroup. Additionally, the iterator must not have been opened with
12356 ** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
12357 ** returned.
12358 */
12359 SQLITE_API int sqlite3changegroup_add_change(
12360 sqlite3_changegroup*,
12361 sqlite3_changeset_iter*
12362 );
12363
12364
12365
12366 /*
12367 ** CAPI3REF: Obtain A Composite Changeset From A Changegroup
12368 ** METHOD: sqlite3_changegroup
12369 **
@@ -13113,12 +13165,12 @@
13165
13166 /*
13167 ** EXTENSION API FUNCTIONS
13168 **
13169 ** xUserData(pFts):
13170 ** Return a copy of the pUserData pointer passed to the xCreateFunction()
13171 ** API when the extension function was registered.
13172 **
13173 ** xColumnTotalSize(pFts, iCol, pnToken):
13174 ** If parameter iCol is less than zero, set output variable *pnToken
13175 ** to the total number of tokens in the FTS5 table. Or, if iCol is
13176 ** non-negative but less than the number of columns in the table, return
@@ -13295,10 +13347,14 @@
13347 ** This API can be quite slow if used with an FTS5 table created with the
13348 ** "detail=none" or "detail=column" option. If the FTS5 table is created
13349 ** with either "detail=none" or "detail=column" and "content=" option
13350 ** (i.e. if it is a contentless table), then this API always iterates
13351 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
13352 **
13353 ** In all cases, matches are visited in (column ASC, offset ASC) order.
13354 ** i.e. all those in column 0, sorted by offset, followed by those in
13355 ** column 1, etc.
13356 **
13357 ** xPhraseNext()
13358 ** See xPhraseFirst above.
13359 **
13360 ** xPhraseFirstColumn()
@@ -14479,139 +14535,139 @@
14535 #define TK_EACH 41
14536 #define TK_FAIL 42
14537 #define TK_OR 43
14538 #define TK_AND 44
14539 #define TK_IS 45
14540 #define TK_ISNOT 46
14541 #define TK_MATCH 47
14542 #define TK_LIKE_KW 48
14543 #define TK_BETWEEN 49
14544 #define TK_IN 50
14545 #define TK_ISNULL 51
14546 #define TK_NOTNULL 52
14547 #define TK_NE 53
14548 #define TK_EQ 54
14549 #define TK_GT 55
14550 #define TK_LE 56
14551 #define TK_LT 57
14552 #define TK_GE 58
14553 #define TK_ESCAPE 59
14554 #define TK_ID 60
14555 #define TK_COLUMNKW 61
14556 #define TK_DO 62
14557 #define TK_FOR 63
14558 #define TK_IGNORE 64
14559 #define TK_INITIALLY 65
14560 #define TK_INSTEAD 66
14561 #define TK_NO 67
14562 #define TK_KEY 68
14563 #define TK_OF 69
14564 #define TK_OFFSET 70
14565 #define TK_PRAGMA 71
14566 #define TK_RAISE 72
14567 #define TK_RECURSIVE 73
14568 #define TK_REPLACE 74
14569 #define TK_RESTRICT 75
14570 #define TK_ROW 76
14571 #define TK_ROWS 77
14572 #define TK_TRIGGER 78
14573 #define TK_VACUUM 79
14574 #define TK_VIEW 80
14575 #define TK_VIRTUAL 81
14576 #define TK_WITH 82
14577 #define TK_NULLS 83
14578 #define TK_FIRST 84
14579 #define TK_LAST 85
14580 #define TK_CURRENT 86
14581 #define TK_FOLLOWING 87
14582 #define TK_PARTITION 88
14583 #define TK_PRECEDING 89
14584 #define TK_RANGE 90
14585 #define TK_UNBOUNDED 91
14586 #define TK_EXCLUDE 92
14587 #define TK_GROUPS 93
14588 #define TK_OTHERS 94
14589 #define TK_TIES 95
14590 #define TK_GENERATED 96
14591 #define TK_ALWAYS 97
14592 #define TK_MATERIALIZED 98
14593 #define TK_REINDEX 99
14594 #define TK_RENAME 100
14595 #define TK_CTIME_KW 101
14596 #define TK_ANY 102
14597 #define TK_BITAND 103
14598 #define TK_BITOR 104
14599 #define TK_LSHIFT 105
14600 #define TK_RSHIFT 106
14601 #define TK_PLUS 107
14602 #define TK_MINUS 108
14603 #define TK_STAR 109
14604 #define TK_SLASH 110
14605 #define TK_REM 111
14606 #define TK_CONCAT 112
14607 #define TK_PTR 113
14608 #define TK_COLLATE 114
14609 #define TK_BITNOT 115
14610 #define TK_ON 116
14611 #define TK_INDEXED 117
14612 #define TK_STRING 118
14613 #define TK_JOIN_KW 119
14614 #define TK_CONSTRAINT 120
14615 #define TK_DEFAULT 121
14616 #define TK_NULL 122
14617 #define TK_PRIMARY 123
14618 #define TK_UNIQUE 124
14619 #define TK_CHECK 125
14620 #define TK_REFERENCES 126
14621 #define TK_AUTOINCR 127
14622 #define TK_INSERT 128
14623 #define TK_DELETE 129
14624 #define TK_UPDATE 130
14625 #define TK_SET 131
14626 #define TK_DEFERRABLE 132
14627 #define TK_FOREIGN 133
14628 #define TK_DROP 134
14629 #define TK_UNION 135
14630 #define TK_ALL 136
14631 #define TK_EXCEPT 137
14632 #define TK_INTERSECT 138
14633 #define TK_SELECT 139
14634 #define TK_VALUES 140
14635 #define TK_DISTINCT 141
14636 #define TK_DOT 142
14637 #define TK_FROM 143
14638 #define TK_JOIN 144
14639 #define TK_USING 145
14640 #define TK_ORDER 146
14641 #define TK_GROUP 147
14642 #define TK_HAVING 148
14643 #define TK_LIMIT 149
14644 #define TK_WHERE 150
14645 #define TK_RETURNING 151
14646 #define TK_INTO 152
14647 #define TK_NOTHING 153
14648 #define TK_FLOAT 154
14649 #define TK_BLOB 155
14650 #define TK_INTEGER 156
14651 #define TK_VARIABLE 157
14652 #define TK_CASE 158
14653 #define TK_WHEN 159
14654 #define TK_THEN 160
14655 #define TK_ELSE 161
14656 #define TK_INDEX 162
14657 #define TK_ALTER 163
14658 #define TK_ADD 164
14659 #define TK_WINDOW 165
14660 #define TK_OVER 166
14661 #define TK_FILTER 167
14662 #define TK_COLUMN 168
14663 #define TK_AGG_FUNCTION 169
14664 #define TK_AGG_COLUMN 170
14665 #define TK_TRUEFALSE 171
14666 #define TK_FUNCTION 172
14667 #define TK_UPLUS 173
14668 #define TK_UMINUS 174
14669 #define TK_TRUTH 175
14670 #define TK_REGISTER 176
14671 #define TK_VECTOR 177
14672 #define TK_SELECT_COLUMN 178
14673 #define TK_IF_NULL_ROW 179
@@ -15148,11 +15204,11 @@
15204 ** 0x00000008 WhereLoop inserts
15205 **
15206 ** 0x00000010 Display sqlite3_index_info xBestIndex calls
15207 ** 0x00000020 Range an equality scan metrics
15208 ** 0x00000040 IN operator decisions
15209 ** 0x00000080 WhereLoop cost adjustments
15210 ** 0x00000100
15211 ** 0x00000200 Covering index decisions
15212 ** 0x00000400 OR optimization
15213 ** 0x00000800 Index scanner
15214 ** 0x00001000 More details associated with code generation
@@ -16610,20 +16666,20 @@
16666 #define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
16667 #define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
16668 #define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
16669 #define OP_Program 48 /* jump0 */
16670 #define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
16671 #define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
16672 #define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
16673 #define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
16674 #define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
16675 #define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
16676 #define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
16677 #define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
16678 #define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
16679 #define OP_Ge 58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
16680 #define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
16681 #define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
16682 #define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
16683 #define OP_IncrVacuum 62 /* jump */
16684 #define OP_VNext 63 /* jump */
16685 #define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
@@ -16662,27 +16718,27 @@
16718 #define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
16719 #define OP_Count 98 /* synopsis: r[P2]=count() */
16720 #define OP_ReadCookie 99
16721 #define OP_SetCookie 100
16722 #define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
16723 #define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */
16724 #define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
16725 #define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
16726 #define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
16727 #define OP_ShiftRight 106 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
16728 #define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
16729 #define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
16730 #define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
16731 #define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
16732 #define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
16733 #define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
16734 #define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
16735 #define OP_OpenDup 114
16736 #define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
16737 #define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
16738 #define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */
16739 #define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
16740 #define OP_SorterOpen 119
16741 #define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
16742 #define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
16743 #define OP_Close 122
16744 #define OP_ColumnsUsed 123
@@ -16713,12 +16769,12 @@
16769 #define OP_SqlExec 148
16770 #define OP_ParseSchema 149
16771 #define OP_LoadAnalysis 150
16772 #define OP_DropTable 151
16773 #define OP_DropIndex 152
16774 #define OP_DropTrigger 153
16775 #define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
16776 #define OP_IntegrityCk 155
16777 #define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
16778 #define OP_Param 157
16779 #define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
16780 #define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
@@ -16770,24 +16826,24 @@
16826 /* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
16827 /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
16828 /* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
16829 /* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
16830 /* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
16831 /* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
16832 /* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\
16833 /* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
16834 /* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
16835 /* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
16836 /* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
16837 /* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\
16838 /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
16839 /* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\
16840 /* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
16841 /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
16842 /* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
16843 /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
16844 /* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\
16845 /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
16846 /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
16847 /* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
16848 /* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
16849
@@ -17826,11 +17882,11 @@
17882 #define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
17883 #define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
17884 #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
17885 #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
17886 /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
17887 #define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
17888 #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
17889 #define SQLITE_SkipScan 0x00004000 /* Skip-scans */
17890 #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
17891 #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
17892 #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
@@ -19232,10 +19288,11 @@
19288 unsigned notCte :1; /* This item may not match a CTE */
19289 unsigned isUsing :1; /* u3.pUsing is valid */
19290 unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
19291 unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
19292 unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
19293 unsigned rowidUsed :1; /* The ROWID of this table is referenced */
19294 } fg;
19295 int iCursor; /* The VDBE cursor number used to access this table */
19296 union {
19297 Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
19298 IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
@@ -19307,11 +19364,11 @@
19364 #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
19365 #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
19366 #define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
19367 #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
19368 #define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
19369 #define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
19370 #define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
19371 /* 0x8000 not currently used */
19372
19373 /* Allowed return values from sqlite3WhereIsDistinct()
19374 */
@@ -19379,11 +19436,11 @@
19436 #define NC_UEList 0x000080 /* True if uNC.pEList is used */
19437 #define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
19438 #define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
19439 #define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
19440 #define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
19441 /* 0x002000 // available for reuse */
19442 #define NC_AllowWin 0x004000 /* Window functions are allowed here */
19443 #define NC_HasWin 0x008000 /* One or more window functions seen */
19444 #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
19445 #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
19446 #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
@@ -19500,15 +19557,16 @@
19557 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
19558 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
19559 #define SF_View 0x0200000 /* SELECT statement is a view */
19560 #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
19561 #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
19562 #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
19563 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
19564 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
19565 #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
19566 #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
19567 #define SF_Correlated 0x20000000 /* True if references the outer context */
19568
19569 /* True if S exists and has SF_NestedFrom */
19570 #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
19571
19572 /*
@@ -19537,11 +19595,15 @@
19595 ** of the query. This destination implies "LIMIT 1".
19596 **
19597 ** SRT_Set The result must be a single column. Store each
19598 ** row of result as the key in table pDest->iSDParm.
19599 ** Apply the affinity pDest->affSdst before storing
19600 ** results. if pDest->iSDParm2 is positive, then it is
19601 ** a regsiter holding a Bloom filter for the IN operator
19602 ** that should be populated in addition to the
19603 ** pDest->iSDParm table. This SRT is used to
19604 ** implement "IN (SELECT ...)".
19605 **
19606 ** SRT_EphemTab Create an temporary table pDest->iSDParm and store
19607 ** the result there. The cursor is left open after
19608 ** returning. This is like SRT_Table except that
19609 ** this destination uses OP_OpenEphemeral to create
@@ -20040,11 +20102,11 @@
20102 int iRetReg; /* Register array for holding a row of RETURNING */
20103 char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
20104 };
20105
20106 /*
20107 ** An object used to accumulate the text of a string where we
20108 ** do not necessarily know how big the string will be in the end.
20109 */
20110 struct sqlite3_str {
20111 sqlite3 *db; /* Optional database for lookaside. Can be NULL */
20112 char *zText; /* The string collected so far */
@@ -20054,11 +20116,11 @@
20116 u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
20117 u8 printfFlags; /* SQLITE_PRINTF flags below */
20118 };
20119 #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
20120 #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
20121 #define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
20122
20123 #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
20124
20125 /*
20126 ** The following object is the header for an "RCStr" or "reference-counted
@@ -20775,11 +20837,11 @@
20837 SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
20838 SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
20839 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
20840 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
20841 SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
20842 SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*);
20843 SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
20844 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
20845 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
20846 SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
20847 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
@@ -20943,10 +21005,11 @@
21005 SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
21006 SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
21007 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
21008 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
21009 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
21010 SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
21011 SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
21012 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
21013 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
21014 #endif
21015 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
@@ -21001,16 +21064,15 @@
21064 SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
21065 SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
21066 SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
21067 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
21068 SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
21069 SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
 
21070 #ifdef SQLITE_ENABLE_CURSOR_HINTS
21071 SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
21072 #endif
21073 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
21074 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
21075 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
21076 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
21077 SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
21078 SQLITE_PRIVATE void sqlite3GenerateRowDelete(
@@ -21187,11 +21249,13 @@
21249 SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
21250 SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
21251 SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
21252 SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
21253 SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
21254 #if !defined(SQLITE_OMIT_BLOB_LITERAL)
21255 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
21256 #endif
21257 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
21258 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
21259
21260 #if defined(SQLITE_NEED_ERR_NAME)
21261 SQLITE_PRIVATE const char *sqlite3ErrName(int);
@@ -24830,12 +24894,12 @@
24894 } aXformType[] = {
24895 /* 0 */ { 6, "second", 4.6427e+14, 1.0 },
24896 /* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
24897 /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
24898 /* 3 */ { 3, "day", 5373485.0, 86400.0 },
24899 /* 4 */ { 5, "month", 176546.0, 2592000.0 },
24900 /* 5 */ { 4, "year", 14713.0, 31536000.0 },
24901 };
24902
24903 /*
24904 ** If the DateTime p is raw number, try to figure out if it is
24905 ** a julian day number of a unix timestamp. Set the p value
@@ -31939,11 +32003,11 @@
32003 sqlite3_str_appendall(pAccum, pItem->zName);
32004 }else if( pItem->zAlias ){
32005 sqlite3_str_appendall(pAccum, pItem->zAlias);
32006 }else{
32007 Select *pSel = pItem->pSelect;
32008 assert( pSel!=0 ); /* Because of tag-20240424-1 */
32009 if( pSel->selFlags & SF_NestedFrom ){
32010 sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
32011 }else if( pSel->selFlags & SF_MultiValue ){
32012 assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
32013 sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
@@ -32722,12 +32786,14 @@
32786 char zLine[1000];
32787 sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
32788 x.printfFlags |= SQLITE_PRINTF_INTERNAL;
32789 sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
32790 if( pItem->pTab ){
32791 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
32792 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
32793 pItem->colUsed,
32794 pItem->fg.rowidUsed ? "+rowid" : "");
32795 }
32796 if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
32797 sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
32798 }else if( pItem->fg.jointype & JT_LEFT ){
32799 sqlite3_str_appendf(&x, " LEFT-JOIN");
@@ -32763,16 +32829,18 @@
32829 if( pItem->fg.isUsing ) n++;
32830 if( pItem->fg.isUsing ){
32831 sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
32832 }
32833 if( pItem->pSelect ){
32834 sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
32835 if( pItem->pTab ){
32836 Table *pTab = pItem->pTab;
32837 sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
32838 }
32839 assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
32840 sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
32841 sqlite3TreeViewPop(&pView);
32842 }
32843 if( pItem->fg.isTabFunc ){
32844 sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
32845 }
32846 sqlite3TreeViewPop(&pView);
@@ -32872,11 +32940,11 @@
32940 }
32941 if( p->pLimit ){
32942 sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
32943 sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
32944 if( p->pLimit->pRight ){
32945 sqlite3TreeViewItem(pView, "OFFSET", 0);
32946 sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
32947 sqlite3TreeViewPop(&pView);
32948 }
32949 sqlite3TreeViewPop(&pView);
32950 }
@@ -33344,11 +33412,12 @@
33412 case OE_Abort: zType = "abort"; break;
33413 case OE_Fail: zType = "fail"; break;
33414 case OE_Ignore: zType = "ignore"; break;
33415 }
33416 assert( !ExprHasProperty(pExpr, EP_IntValue) );
33417 sqlite3TreeViewLine(pView, "RAISE %s", zType);
33418 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
33419 break;
33420 }
33421 #endif
33422 case TK_MATCH: {
33423 sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
@@ -33424,13 +33493,14 @@
33493 }else{
33494 int i;
33495 sqlite3TreeViewLine(pView, "%s", zLabel);
33496 for(i=0; i<pList->nExpr; i++){
33497 int j = pList->a[i].u.x.iOrderByCol;
33498 u8 sortFlags = pList->a[i].fg.sortFlags;
33499 char *zName = pList->a[i].zEName;
33500 int moreToFollow = i<pList->nExpr - 1;
33501 if( j || zName || sortFlags ){
33502 sqlite3TreeViewPush(&pView, moreToFollow);
33503 moreToFollow = 0;
33504 sqlite3TreeViewLine(pView, 0);
33505 if( zName ){
33506 switch( pList->a[i].fg.eEName ){
@@ -33447,17 +33517,22 @@
33517 fprintf(stdout, "SPAN(\"%s\") ", zName);
33518 break;
33519 }
33520 }
33521 if( j ){
33522 fprintf(stdout, "iOrderByCol=%d ", j);
33523 }
33524 if( sortFlags & KEYINFO_ORDER_DESC ){
33525 fprintf(stdout, "DESC ");
33526 }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
33527 fprintf(stdout, "NULLS-LAST");
33528 }
33529 fprintf(stdout, "\n");
33530 fflush(stdout);
33531 }
33532 sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
33533 if( j || zName || sortFlags ){
33534 sqlite3TreeViewPop(&pView);
33535 }
33536 }
33537 }
33538 }
@@ -35864,14 +35939,17 @@
35939
35940 /*
35941 ** Decode a floating-point value into an approximate decimal
35942 ** representation.
35943 **
35944 ** If iRound<=0 then round to -iRound significant digits to the
35945 ** the left of the decimal point, or to a maximum of mxRound total
35946 ** significant digits.
35947 **
35948 ** If iRound>0 round to min(iRound,mxRound) significant digits total.
35949 **
35950 ** mxRound must be positive.
35951 **
35952 ** The significant digits of the decimal representation are
35953 ** stored in p->z[] which is a often (but not always) a pointer
35954 ** into the middle of p->zBuf[]. There are p->n significant digits.
35955 ** The p->z[] array is *not* zero-terminated.
@@ -35880,10 +35958,12 @@
35958 int i;
35959 u64 v;
35960 int e, exp = 0;
35961 p->isSpecial = 0;
35962 p->z = p->zBuf;
35963
35964 assert( mxRound>0 );
35965
35966 /* Convert negative numbers to positive. Deal with Infinity, 0.0, and
35967 ** NaN. */
35968 if( r<0.0 ){
35969 p->sign = '-';
@@ -37167,20 +37247,20 @@
37247 /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
37248 /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
37249 /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
37250 /* 48 */ "Program" OpHelp(""),
37251 /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
37252 /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
37253 /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
37254 /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
37255 /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
37256 /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
37257 /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
37258 /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
37259 /* 57 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
37260 /* 58 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
37261 /* 59 */ "ElseEq" OpHelp(""),
37262 /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
37263 /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
37264 /* 62 */ "IncrVacuum" OpHelp(""),
37265 /* 63 */ "VNext" OpHelp(""),
37266 /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
@@ -37219,27 +37299,27 @@
37299 /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
37300 /* 98 */ "Count" OpHelp("r[P2]=count()"),
37301 /* 99 */ "ReadCookie" OpHelp(""),
37302 /* 100 */ "SetCookie" OpHelp(""),
37303 /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
37304 /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
37305 /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
37306 /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
37307 /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
37308 /* 106 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
37309 /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
37310 /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
37311 /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
37312 /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
37313 /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
37314 /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
37315 /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
37316 /* 114 */ "OpenDup" OpHelp(""),
37317 /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
37318 /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
37319 /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"),
37320 /* 118 */ "String8" OpHelp("r[P2]='P4'"),
37321 /* 119 */ "SorterOpen" OpHelp(""),
37322 /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
37323 /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
37324 /* 122 */ "Close" OpHelp(""),
37325 /* 123 */ "ColumnsUsed" OpHelp(""),
@@ -37270,12 +37350,12 @@
37350 /* 148 */ "SqlExec" OpHelp(""),
37351 /* 149 */ "ParseSchema" OpHelp(""),
37352 /* 150 */ "LoadAnalysis" OpHelp(""),
37353 /* 151 */ "DropTable" OpHelp(""),
37354 /* 152 */ "DropIndex" OpHelp(""),
37355 /* 153 */ "DropTrigger" OpHelp(""),
37356 /* 154 */ "Real" OpHelp("r[P2]=P4"),
37357 /* 155 */ "IntegrityCk" OpHelp(""),
37358 /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
37359 /* 157 */ "Param" OpHelp(""),
37360 /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
37361 /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
@@ -40577,30 +40657,26 @@
40657 */
40658 #define DOTLOCK_SUFFIX ".lock"
40659
40660 /*
40661 ** This routine checks if there is a RESERVED lock held on the specified
40662 ** file by this or any other process. If the caller holds a SHARED
40663 ** or greater lock when it is called, then it is assumed that no other
40664 ** client may hold RESERVED. Or, if the caller holds no lock, then it
40665 ** is assumed another client holds RESERVED if the lock-file exists.
 
 
 
40666 */
40667 static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
 
 
40668 unixFile *pFile = (unixFile*)id;
 
40669 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
40670
40671 if( pFile->eFileLock>=SHARED_LOCK ){
40672 *pResOut = 0;
40673 }else{
40674 *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
40675 }
40676 OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
40677 return SQLITE_OK;
40678 }
40679
40680 /*
40681 ** Lock the file with the lock specified by parameter eFileLock - one
40682 ** of the following:
@@ -42285,11 +42361,11 @@
42361 }
42362 }
42363
42364 /* Forward declaration */
42365 static int unixGetTempname(int nBuf, char *zBuf);
42366 #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
42367 static int unixFcntlExternalReader(unixFile*, int*);
42368 #endif
42369
42370 /*
42371 ** Information and control of an open file handle.
@@ -42412,11 +42488,11 @@
42488 return proxyFileControl(id,op,pArg);
42489 }
42490 #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
42491
42492 case SQLITE_FCNTL_EXTERNAL_READER: {
42493 #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
42494 return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
42495 #else
42496 *(int*)pArg = 0;
42497 return SQLITE_OK;
42498 #endif
@@ -42585,11 +42661,11 @@
42661 #endif
42662 }
42663
42664 #endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
42665
42666 #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
42667
42668 /*
42669 ** Object used to represent an shared memory buffer.
42670 **
42671 ** When multiple threads all reference the same wal-index, each thread
@@ -64135,11 +64211,11 @@
64211 /*
64212 ** Return the file handle for the journal file (if it exists).
64213 ** This will be either the rollback journal or the WAL file.
64214 */
64215 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
64216 #ifdef SQLITE_OMIT_WAL
64217 return pPager->jfd;
64218 #else
64219 return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
64220 #endif
64221 }
@@ -75626,10 +75702,16 @@
75702 }
75703 }
75704 memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
75705 pCur->curFlags |= BTCF_ValidOvfl;
75706 }else{
75707 /* Sanity check the validity of the overflow page cache */
75708 assert( pCur->aOverflow[0]==nextPage
75709 || pCur->aOverflow[0]==0
75710 || CORRUPT_DB );
75711 assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
75712
75713 /* If the overflow page-list cache has been allocated and the
75714 ** entry for the first required overflow page is valid, skip
75715 ** directly to it.
75716 */
75717 if( pCur->aOverflow[offset/ovflSize] ){
@@ -76106,10 +76188,27 @@
76188 *pRes = 1;
76189 rc = SQLITE_OK;
76190 }
76191 return rc;
76192 }
76193
76194 #ifdef SQLITE_DEBUG
76195 /* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
76196 ** this flags are true for a consistent database.
76197 **
76198 ** This routine is is called from within assert() statements only.
76199 ** It is an internal verification routine and does not appear in production
76200 ** builds.
76201 */
76202 static int cursorIsAtLastEntry(BtCursor *pCur){
76203 int ii;
76204 for(ii=0; ii<pCur->iPage; ii++){
76205 if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
76206 }
76207 return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
76208 }
76209 #endif
76210
76211 /* Move the cursor to the last entry in the table. Return SQLITE_OK
76212 ** on success. Set *pRes to 0 if the cursor actually points to something
76213 ** or set *pRes to 1 if the table is empty.
76214 */
@@ -76135,22 +76234,11 @@
76234 assert( cursorOwnsBtShared(pCur) );
76235 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
76236
76237 /* If the cursor already points to the last entry, this is a no-op. */
76238 if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
76239 assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
 
 
 
 
 
 
 
 
 
 
 
76240 *pRes = 0;
76241 return SQLITE_OK;
76242 }
76243 return btreeLast(pCur, pRes);
76244 }
@@ -76199,10 +76287,11 @@
76287 *pRes = 0;
76288 return SQLITE_OK;
76289 }
76290 if( pCur->info.nKey<intKey ){
76291 if( (pCur->curFlags & BTCF_AtLast)!=0 ){
76292 assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
76293 *pRes = -1;
76294 return SQLITE_OK;
76295 }
76296 /* If the requested key is one more than the previous key, then
76297 ** try to get there using sqlite3BtreeNext() rather than a full
@@ -78037,11 +78126,12 @@
78126 assert( i<iEnd );
78127 j = get2byte(&aData[hdr+5]);
78128 if( j>(u32)usableSize ){ j = 0; }
78129 memcpy(&pTmp[j], &aData[j], usableSize - j);
78130
78131 assert( pCArray->ixNx[NB*2-1]>i );
78132 for(k=0; pCArray->ixNx[k]<=i; k++){}
78133 pSrcEnd = pCArray->apEnd[k];
78134
78135 pData = pEnd;
78136 while( 1/*exit by break*/ ){
78137 u8 *pCell = pCArray->apCell[i];
@@ -78120,11 +78210,12 @@
78210 int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
78211 int k; /* Current slot in pCArray->apEnd[] */
78212 u8 *pEnd; /* Maximum extent of cell data */
78213 assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
78214 if( iEnd<=iFirst ) return 0;
78215 assert( pCArray->ixNx[NB*2-1]>i );
78216 for(k=0; pCArray->ixNx[k]<=i ; k++){}
78217 pEnd = pCArray->apEnd[k];
78218 while( 1 /*Exit by break*/ ){
78219 int sz, rc;
78220 u8 *pSlot;
78221 assert( pCArray->szCell[i]!=0 );
@@ -78405,10 +78496,11 @@
78496 b.pRef = pPage;
78497 b.apCell = &pCell;
78498 b.szCell = &szCell;
78499 b.apEnd[0] = pPage->aDataEnd;
78500 b.ixNx[0] = 2;
78501 b.ixNx[NB*2-1] = 0x7fffffff;
78502 rc = rebuildPage(&b, 0, 1, pNew);
78503 if( NEVER(rc) ){
78504 releasePage(pNew);
78505 return rc;
78506 }
@@ -78640,11 +78732,13 @@
78732 u8 abDone[NB+2]; /* True after i'th new page is populated */
78733 Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */
78734 CellArray b; /* Parsed information on cells being balanced */
78735
78736 memset(abDone, 0, sizeof(abDone));
78737 assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
78738 memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
78739 b.ixNx[NB*2-1] = 0x7fffffff;
78740 pBt = pParent->pBt;
78741 assert( sqlite3_mutex_held(pBt->mutex) );
78742 assert( sqlite3PagerIswriteable(pParent->pDbPage) );
78743
78744 /* At this point pParent may have at most one overflow cell. And if
@@ -79231,11 +79325,12 @@
79325 }
79326 }
79327 iOvflSpace += sz;
79328 assert( sz<=pBt->maxLocal+23 );
79329 assert( iOvflSpace <= (int)pBt->pageSize );
79330 assert( b.ixNx[NB*2-1]>j );
79331 for(k=0; b.ixNx[k]<=j; k++){}
79332 pSrcEnd = b.apEnd[k];
79333 if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
79334 rc = SQLITE_CORRUPT_BKPT;
79335 goto balance_cleanup;
79336 }
@@ -80004,11 +80099,11 @@
80099 dropCell(pPage, idx, info.nSize, &rc);
80100 if( rc ) goto end_insert;
80101 }else if( loc<0 && pPage->nCell>0 ){
80102 assert( pPage->leaf );
80103 idx = ++pCur->ix;
80104 pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
80105 }else{
80106 assert( pPage->leaf );
80107 }
80108 rc = insertCellFast(pPage, idx, newCell, szNew);
80109 assert( pPage->nOverflow==0 || rc==SQLITE_OK );
@@ -80034,11 +80129,11 @@
80129 ** larger than the largest existing key, it is possible to insert the
80130 ** row without seeking the cursor. This can be a big performance boost.
80131 */
80132 if( pPage->nOverflow ){
80133 assert( rc==SQLITE_OK );
80134 pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
80135 rc = balance(pCur);
80136
80137 /* Must make sure nOverflow is reset to zero even if the balance()
80138 ** fails. Internal data structure corruption will result otherwise.
80139 ** Also, set the cursor state to invalid. This stops saveCursorPosition()
@@ -84658,21 +84753,21 @@
84753 int nRec, /* Size of buffer pRec in bytes */
84754 int iCol, /* Column to extract */
84755 sqlite3_value **ppVal /* OUT: Extracted value */
84756 ){
84757 u32 t = 0; /* a column type code */
84758 u32 nHdr; /* Size of the header in the record */
84759 u32 iHdr; /* Next unread header byte */
84760 i64 iField; /* Next unread data byte */
84761 u32 szField = 0; /* Size of the current data field */
84762 int i; /* Column index */
84763 u8 *a = (u8*)pRec; /* Typecast byte array */
84764 Mem *pMem = *ppVal; /* Write result into this Mem object */
84765
84766 assert( iCol>0 );
84767 iHdr = getVarint32(a, nHdr);
84768 if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
84769 iField = nHdr;
84770 for(i=0; i<=iCol; i++){
84771 iHdr += getVarint32(&a[iHdr], t);
84772 testcase( iHdr==nHdr );
84773 testcase( iHdr==nHdr+1 );
@@ -88119,11 +88214,11 @@
88214 }
88215 }
88216
88217 /* Check for immediate foreign key violations. */
88218 if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
88219 (void)sqlite3VdbeCheckFk(p, 0);
88220 }
88221
88222 /* If the auto-commit flag is set and this is the only active writer
88223 ** VM, then we do either a commit or rollback of the current transaction.
88224 **
@@ -90100,11 +90195,12 @@
90195 */
90196 SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
90197 assert( iVar>0 );
90198 if( v ){
90199 Mem *pMem = &v->aVar[iVar-1];
90200 assert( (v->db->flags & SQLITE_EnableQPSG)==0
90201 || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
90202 if( 0==(pMem->flags & MEM_Null) ){
90203 sqlite3_value *pRet = sqlite3ValueNew(v->db);
90204 if( pRet ){
90205 sqlite3VdbeMemCopy((Mem *)pRet, pMem);
90206 sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
@@ -90120,11 +90216,12 @@
90216 ** to sqlite3_reoptimize() that re-preparing the statement may result
90217 ** in a better query plan.
90218 */
90219 SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
90220 assert( iVar>0 );
90221 assert( (v->db->flags & SQLITE_EnableQPSG)==0
90222 || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
90223 if( iVar>=32 ){
90224 v->expmask |= 0x80000000;
90225 }else{
90226 v->expmask |= ((u32)1 << (iVar-1));
90227 }
@@ -94190,11 +94287,13 @@
94287
94288 /* Opcode: EndCoroutine P1 * * * *
94289 **
94290 ** The instruction at the address in register P1 is a Yield.
94291 ** Jump to the P2 parameter of that Yield.
94292 ** After the jump, the value register P1 is left with a value
94293 ** such that subsequent OP_Yields go back to the this same
94294 ** OP_EndCoroutine instruction.
94295 **
94296 ** See also: InitCoroutine
94297 */
94298 case OP_EndCoroutine: { /* in1 */
94299 VdbeOp *pCaller;
@@ -94202,12 +94301,12 @@
94301 assert( pIn1->flags==MEM_Int );
94302 assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
94303 pCaller = &aOp[pIn1->u.i];
94304 assert( pCaller->opcode==OP_Yield );
94305 assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
94306 pIn1->u.i = (int)(pOp - p->aOp) - 1;
94307 pOp = &aOp[pCaller->p2 - 1];
 
94308 break;
94309 }
94310
94311 /* Opcode: Yield P1 P2 * * *
94312 **
@@ -94250,11 +94349,11 @@
94349 if( (pIn3->flags & MEM_Null)==0 ) break;
94350 /* Fall through into OP_Halt */
94351 /* no break */ deliberate_fall_through
94352 }
94353
94354 /* Opcode: Halt P1 P2 P3 P4 P5
94355 **
94356 ** Exit immediately. All open cursors, etc are closed
94357 ** automatically.
94358 **
94359 ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
@@ -94263,22 +94362,26 @@
94362 ** whether or not to rollback the current transaction. Do not rollback
94363 ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
94364 ** then back out all changes that have occurred during this execution of the
94365 ** VDBE, but do not rollback the transaction.
94366 **
94367 ** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
94368 ** text of an error message.
94369 **
94370 ** If P3 is zero and P4 is not null then the error message string is held
94371 ** in P4.
94372 **
94373 ** P5 is a value between 1 and 4, inclusive, then the P4 error message
94374 ** string is modified as follows:
94375 **
94376 ** 1: NOT NULL constraint failed: P4
94377 ** 2: UNIQUE constraint failed: P4
94378 ** 3: CHECK constraint failed: P4
94379 ** 4: FOREIGN KEY constraint failed: P4
94380 **
94381 ** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
94382 ** the ":" is omitted.
94383 **
94384 ** There is an implied "Halt 0 0 0" instruction inserted at the very end of
94385 ** every program. So a jump past the last instruction of the program
94386 ** is the same as executing Halt.
94387 */
@@ -94287,10 +94390,13 @@
94390 int pcx;
94391
94392 #ifdef SQLITE_DEBUG
94393 if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
94394 #endif
94395 assert( pOp->p4type==P4_NOTUSED
94396 || pOp->p4type==P4_STATIC
94397 || pOp->p4type==P4_DYNAMIC );
94398
94399 /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
94400 ** something is wrong with the code generator. Raise an assertion in order
94401 ** to bring this to the attention of fuzzers and other testing tools. */
94402 assert( pOp->p1!=SQLITE_INTERNAL );
@@ -94317,11 +94423,16 @@
94423 }
94424 p->rc = pOp->p1;
94425 p->errorAction = (u8)pOp->p2;
94426 assert( pOp->p5<=4 );
94427 if( p->rc ){
94428 if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
94429 const char *zErr;
94430 assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
94431 zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
94432 sqlite3VdbeError(p, "%s", zErr);
94433 }else if( pOp->p5 ){
94434 static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
94435 "FOREIGN KEY" };
94436 testcase( pOp->p5==1 );
94437 testcase( pOp->p5==2 );
94438 testcase( pOp->p5==3 );
@@ -97360,27 +97471,27 @@
97471 wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
97472 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
97473 if( pDb->pSchema->file_format < p->minWriteFileFormat ){
97474 p->minWriteFileFormat = pDb->pSchema->file_format;
97475 }
97476 if( pOp->p5 & OPFLAG_P2ISREG ){
97477 assert( p2>0 );
97478 assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
97479 pIn2 = &aMem[p2];
97480 assert( memIsValid(pIn2) );
97481 assert( (pIn2->flags & MEM_Int)!=0 );
97482 sqlite3VdbeMemIntegerify(pIn2);
97483 p2 = (int)pIn2->u.i;
97484 /* The p2 value always comes from a prior OP_CreateBtree opcode and
97485 ** that opcode will always set the p2 value to 2 or more or else fail.
97486 ** If there were a failure, the prepared statement would have halted
97487 ** before reaching this instruction. */
97488 assert( p2>=2 );
97489 }
97490 }else{
97491 wrFlag = 0;
97492 assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97493 }
97494 if( pOp->p4type==P4_KEYINFO ){
97495 pKeyInfo = pOp->p4.pKeyInfo;
97496 assert( pKeyInfo->enc==ENC(db) );
97497 assert( pKeyInfo->db==db );
@@ -97620,11 +97731,12 @@
97731 ** row output from the sorter so that the row can be decomposed into
97732 ** individual columns using the OP_Column opcode. The OP_Column opcode
97733 ** is the only cursor opcode that works with a pseudo-table.
97734 **
97735 ** P3 is the number of fields in the records that will be stored by
97736 ** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
97737 ** will return NULL for every column.
97738 */
97739 case OP_OpenPseudo: {
97740 VdbeCursor *pCx;
97741
97742 assert( pOp->p1>=0 );
@@ -98331,10 +98443,11 @@
98443 if( r.nField>0 ){
98444 /* Key values in an array of registers */
98445 r.pKeyInfo = pC->pKeyInfo;
98446 r.default_rc = 0;
98447 #ifdef SQLITE_DEBUG
98448 (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
98449 for(ii=0; ii<r.nField; ii++){
98450 assert( memIsValid(&r.aMem[ii]) );
98451 assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
98452 if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
98453 }
@@ -102038,18 +102151,33 @@
102151 }
102152 #endif
102153
102154 /* Opcode: Noop * * * * *
102155 **
102156 ** Do nothing. Continue downward to the next opcode.
 
102157 */
102158 /* Opcode: Explain P1 P2 P3 P4 *
102159 **
102160 ** This is the same as OP_Noop during normal query execution. The
102161 ** purpose of this opcode is to hold information about the query
102162 ** plan for the purpose of EXPLAIN QUERY PLAN output.
102163 **
102164 ** The P4 value is human-readable text that describes the query plan
102165 ** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
102166 **
102167 ** The P1 value is the ID of the current element and P2 is the parent
102168 ** element for the case of nested query plan elements. If P2 is zero
102169 ** then this element is a top-level element.
102170 **
102171 ** For loop elements, P3 is the estimated code of each invocation of this
102172 ** element.
102173 **
102174 ** As with all opcodes, the meanings of the parameters for OP_Explain
102175 ** are subject to change from one release to the next. Applications
102176 ** should not attempt to interpret or use any of the information
102177 ** contined in the OP_Explain opcode. The information provided by this
102178 ** opcode is intended for testing and debugging use only.
102179 */
102180 default: { /* This is really OP_Noop, OP_Explain */
102181 assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
102182
102183 break;
@@ -105778,14 +105906,14 @@
105906 break;
105907 }
105908
105909 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
105910 case 9: /* nexec */
105911 sqlite3_result_int64(ctx, pOp->nExec);
105912 break;
105913 case 10: /* ncycle */
105914 sqlite3_result_int64(ctx, pOp->nCycle);
105915 break;
105916 #else
105917 case 9: /* nexec */
105918 case 10: /* ncycle */
105919 sqlite3_result_int(ctx, 0);
@@ -106874,11 +107002,11 @@
107002 ** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab.
107003 */
107004 static SQLITE_NOINLINE int isValidSchemaTableName(
107005 const char *zTab, /* Name as it appears in the SQL */
107006 Table *pTab, /* The schema table we are trying to match */
107007 const char *zDb /* non-NULL if a database qualifier is present */
107008 ){
107009 const char *zLegacy;
107010 assert( pTab!=0 );
107011 assert( pTab->tnum==1 );
107012 if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0;
@@ -106885,11 +107013,11 @@
107013 zLegacy = pTab->zName;
107014 if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
107015 if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
107016 return 1;
107017 }
107018 if( zDb==0 ) return 0;
107019 if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
107020 if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
107021 }else{
107022 if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
107023 }
@@ -107068,11 +107196,11 @@
107196 if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){
107197 continue;
107198 }
107199 }else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
107200 if( pTab->tnum!=1 ) continue;
107201 if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
107202 }
107203 assert( ExprUseYTab(pExpr) );
107204 if( IN_RENAME_OBJECT && pItem->zAlias ){
107205 sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
107206 }
@@ -107174,11 +107302,12 @@
107302 int op = pParse->eTriggerOp;
107303 assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
107304 if( pParse->bReturning ){
107305 if( (pNC->ncFlags & NC_UBaseReg)!=0
107306 && ALWAYS(zTab==0
107307 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0
107308 || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0))
107309 ){
107310 pExpr->iTable = op!=TK_DELETE;
107311 pTab = pParse->pTriggerTab;
107312 }
107313 }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
@@ -107278,10 +107407,15 @@
107407 && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
107408 && sqlite3IsRowid(zCol)
107409 && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
107410 ){
107411 cnt = cntTab;
107412 #if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
107413 if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
107414 eNewExprOp = TK_NULL;
107415 }
107416 #endif
107417 if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
107418 pExpr->affExpr = SQLITE_AFF_INTEGER;
107419 }
107420
107421 /*
@@ -107468,12 +107602,16 @@
107602 ** (See ticket [b92e5e8ec2cdbaa1]).
107603 **
107604 ** If a generated column is referenced, set bits for every column
107605 ** of the table.
107606 */
107607 if( pMatch ){
107608 if( pExpr->iColumn>=0 ){
107609 pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
107610 }else{
107611 pMatch->fg.rowidUsed = 1;
107612 }
107613 }
107614
107615 pExpr->op = eNewExprOp;
107616 lookupname_end:
107617 if( cnt==1 ){
@@ -107921,15 +108059,13 @@
108059 #else
108060 pNC->ncFlags &= ~NC_AllowAgg;
108061 #endif
108062 }
108063 }
108064 else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){
 
108065 is_agg = 1;
108066 }
 
108067 sqlite3WalkExprList(pWalker, pList);
108068 if( is_agg ){
108069 if( pExpr->pLeft ){
108070 assert( pExpr->pLeft->op==TK_ORDER );
108071 assert( ExprUseXList(pExpr->pLeft) );
@@ -107995,18 +108131,20 @@
108131 int nRef = pNC->nRef;
108132 testcase( pNC->ncFlags & NC_IsCheck );
108133 testcase( pNC->ncFlags & NC_PartIdx );
108134 testcase( pNC->ncFlags & NC_IdxExpr );
108135 testcase( pNC->ncFlags & NC_GenCol );
108136 assert( pExpr->x.pSelect );
108137 if( pNC->ncFlags & NC_SelfRef ){
108138 notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
108139 }else{
108140 sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
108141 }
108142 assert( pNC->nRef>=nRef );
108143 if( nRef!=pNC->nRef ){
108144 ExprSetProperty(pExpr, EP_VarSelect);
108145 pExpr->x.pSelect->selFlags |= SF_Correlated;
108146 }
108147 pNC->ncFlags |= NC_Subquery;
108148 }
108149 break;
108150 }
@@ -108141,11 +108279,11 @@
108279 NameContext nc; /* Name context for resolving pE */
108280 sqlite3 *db; /* Database connection */
108281 int rc; /* Return code from subprocedures */
108282 u8 savedSuppErr; /* Saved value of db->suppressErr */
108283
108284 assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
108285 pEList = pSelect->pEList;
108286
108287 /* Resolve all names in the ORDER BY term expression
108288 */
108289 memset(&nc, 0, sizeof(nc));
@@ -108240,11 +108378,11 @@
108378 int iCol = -1;
108379 Expr *pE, *pDup;
108380 if( pItem->fg.done ) continue;
108381 pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
108382 if( NEVER(pE==0) ) continue;
108383 if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
108384 if( iCol<=0 || iCol>pEList->nExpr ){
108385 resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
108386 return 1;
108387 }
108388 }else{
@@ -108425,11 +108563,11 @@
108563 ** copy of the iCol-th result-set expression. */
108564 pItem->u.x.iOrderByCol = (u16)iCol;
108565 continue;
108566 }
108567 }
108568 if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
108569 /* The ORDER BY term is an integer constant. Again, set the column
108570 ** number so that sqlite3ResolveOrderGroupBy() will convert the
108571 ** order-by term to a copy of the result-set expression */
108572 if( iCol<1 || iCol>0xffff ){
108573 resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
@@ -108528,10 +108666,11 @@
108666 /* Recursively resolve names in all subqueries in the FROM clause
108667 */
108668 if( pOuterNC ) pOuterNC->nNestedSelect++;
108669 for(i=0; i<p->pSrc->nSrc; i++){
108670 SrcItem *pItem = &p->pSrc->a[i];
108671 assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
108672 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
108673 int nRef = pOuterNC ? pOuterNC->nRef : 0;
108674 const char *zSavedContext = pParse->zAuthContext;
108675
108676 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
@@ -109004,11 +109143,13 @@
109143 || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
109144 pExpr = pExpr->pLeft;
109145 op = pExpr->op;
109146 continue;
109147 }
109148 if( op!=TK_REGISTER ) break;
109149 op = pExpr->op2;
109150 if( NEVER( op==TK_REGISTER ) ) break;
109151 }
109152 return pExpr->affExpr;
109153 }
109154
109155 /*
@@ -110287,10 +110428,11 @@
110428 ** Recursively delete an expression tree.
110429 */
110430 static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
110431 assert( p!=0 );
110432 assert( db!=0 );
110433 exprDeleteRestart:
110434 assert( !ExprUseUValue(p) || p->u.iValue>=0 );
110435 assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
110436 assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
110437 assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
110438 #ifdef SQLITE_DEBUG
@@ -110302,11 +110444,10 @@
110444 }
110445 #endif
110446 if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
110447 /* The Expr.x union is never used at the same time as Expr.pRight */
110448 assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
 
110449 if( p->pRight ){
110450 assert( !ExprHasProperty(p, EP_WinFunc) );
110451 sqlite3ExprDeleteNN(db, p->pRight);
110452 }else if( ExprUseXSelect(p) ){
110453 assert( !ExprHasProperty(p, EP_WinFunc) );
@@ -110316,10 +110457,23 @@
110457 #ifndef SQLITE_OMIT_WINDOWFUNC
110458 if( ExprHasProperty(p, EP_WinFunc) ){
110459 sqlite3WindowDelete(db, p->y.pWin);
110460 }
110461 #endif
110462 }
110463 if( p->pLeft && p->op!=TK_SELECT_COLUMN ){
110464 Expr *pLeft = p->pLeft;
110465 if( !ExprHasProperty(p, EP_Static)
110466 && !ExprHasProperty(pLeft, EP_Static)
110467 ){
110468 /* Avoid unnecessary recursion on unary operators */
110469 sqlite3DbNNFreeNN(db, p);
110470 p = pLeft;
110471 goto exprDeleteRestart;
110472 }else{
110473 sqlite3ExprDeleteNN(db, pLeft);
110474 }
110475 }
110476 }
110477 if( !ExprHasProperty(p, EP_Static) ){
110478 sqlite3DbNNFreeNN(db, p);
110479 }
@@ -110349,15 +110503,15 @@
110503 ** This is similar to sqlite3ExprDelete() except that the delete is
110504 ** deferred until the pParse is deleted.
110505 **
110506 ** The pExpr might be deleted immediately on an OOM error.
110507 **
110508 ** Return 0 if the delete was successfully deferred. Return non-zero
110509 ** if the delete happened immediately because of an OOM.
110510 */
110511 SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
110512 return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
110513 }
110514
110515 /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
110516 ** expression.
110517 */
@@ -111312,11 +111466,11 @@
111466 || ExprHasProperty(pExpr, EP_WinFunc)
111467 ){
111468 pWalker->eCode = 0;
111469 return WRC_Abort;
111470 }
111471 return WRC_Prune;
111472 }
111473
111474
111475 /*
111476 ** These routines are Walker callbacks used to check expressions to
@@ -111419,20 +111573,19 @@
111573 testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
111574 testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
111575 return WRC_Continue;
111576 }
111577 }
111578 static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
111579 Walker w;
111580 w.eCode = initFlag;
111581 w.pParse = pParse;
111582 w.xExprCallback = exprNodeIsConstant;
111583 w.xSelectCallback = sqlite3SelectWalkFail;
111584 #ifdef SQLITE_DEBUG
111585 w.xSelectCallback2 = sqlite3SelectWalkAssert2;
111586 #endif
 
111587 sqlite3WalkExpr(&w, p);
111588 return w.eCode;
111589 }
111590
111591 /*
@@ -111448,11 +111601,11 @@
111601 ** function calls will be considered to be non-constant. If pParse is
111602 ** not NULL, then a function call might be constant, depending on the
111603 ** function and on its parameters.
111604 */
111605 SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
111606 return exprIsConst(pParse, p, 1);
111607 }
111608
111609 /*
111610 ** Walk an expression tree. Return non-zero if
111611 **
@@ -111465,21 +111618,54 @@
111618 ** When this routine returns true, it indicates that the expression
111619 ** can be added to the pParse->pConstExpr list and evaluated once when
111620 ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
111621 */
111622 static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
111623 return exprIsConst(pParse, p, 2);
111624 }
111625
111626 /*
111627 ** This routine examines sub-SELECT statements as an expression is being
111628 ** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
111629 ** constant as long as they are uncorrelated - meaning that they do not
111630 ** contain any terms from outer contexts.
111631 */
111632 static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
111633 assert( pSelect!=0 );
111634 assert( pWalker->eCode==3 || pWalker->eCode==0 );
111635 if( (pSelect->selFlags & SF_Correlated)!=0 ){
111636 pWalker->eCode = 0;
111637 return WRC_Abort;
111638 }
111639 return WRC_Prune;
111640 }
111641
111642 /*
111643 ** Walk an expression tree. Return non-zero if the expression is constant
111644 ** for any single row of the table with cursor iCur. In other words, the
111645 ** expression must not refer to any non-deterministic function nor any
111646 ** table other than iCur.
111647 **
111648 ** Consider uncorrelated subqueries to be constants if the bAllowSubq
111649 ** parameter is true.
111650 */
111651 static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
111652 Walker w;
111653 w.eCode = 3;
111654 w.pParse = 0;
111655 w.xExprCallback = exprNodeIsConstant;
111656 if( bAllowSubq ){
111657 w.xSelectCallback = exprSelectWalkTableConstant;
111658 }else{
111659 w.xSelectCallback = sqlite3SelectWalkFail;
111660 #ifdef SQLITE_DEBUG
111661 w.xSelectCallback2 = sqlite3SelectWalkAssert2;
111662 #endif
111663 }
111664 w.u.iCur = iCur;
111665 sqlite3WalkExpr(&w, p);
111666 return w.eCode;
111667 }
111668
111669 /*
111670 ** Check pExpr to see if it is an constraint on the single data source
111671 ** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr
@@ -111493,11 +111679,14 @@
111679 **
111680 ** To be an single-source constraint, the following must be true:
111681 **
111682 ** (1) pExpr cannot refer to any table other than pSrc->iCursor.
111683 **
111684 ** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
111685 ** true and the subquery is non-correlated
111686 **
111687 ** (2b) pExpr cannot use non-deterministic functions.
111688 **
111689 ** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
111690 ** (Is there some way to relax this constraint?)
111691 **
111692 ** (4) If pSrc is the right operand of a LEFT JOIN, then...
@@ -111522,11 +111711,12 @@
111711 ** on push-down.
111712 */
111713 SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(
111714 Expr *pExpr, /* The constraint */
111715 const SrcList *pSrcList, /* Complete FROM clause */
111716 int iSrc, /* Which element of pSrcList to use */
111717 int bAllowSubq /* Allow non-correlated subqueries */
111718 ){
111719 const SrcItem *pSrc = &pSrcList->a[iSrc];
111720 if( pSrc->fg.jointype & JT_LTORJ ){
111721 return 0; /* rule (3) */
111722 }
@@ -111547,11 +111737,12 @@
111737 }
111738 break;
111739 }
111740 }
111741 }
111742 /* Rules (1), (2a), and (2b) handled by the following: */
111743 return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
111744 }
111745
111746
111747 /*
111748 ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
@@ -111632,11 +111823,11 @@
111823 ** is considered a variable but a single-quoted string (ex: 'abc') is
111824 ** a constant.
111825 */
111826 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
111827 assert( isInit==0 || isInit==1 );
111828 return exprIsConst(0, p, 4+isInit);
111829 }
111830
111831 #ifdef SQLITE_ENABLE_CURSOR_HINTS
111832 /*
111833 ** Walk an expression tree. Return 1 if the expression contains a
@@ -111658,12 +111849,16 @@
111849 /*
111850 ** If the expression p codes a constant integer that is small enough
111851 ** to fit in a 32-bit integer, return 1 and put the value of the integer
111852 ** in *pValue. If the expression is not an integer or if it is too big
111853 ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
111854 **
111855 ** If the pParse pointer is provided, then allow the expression p to be
111856 ** a parameter (TK_VARIABLE) that is bound to an integer.
111857 ** But if pParse is NULL, then p must be a pure integer literal.
111858 */
111859 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
111860 int rc = 0;
111861 if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
111862
111863 /* If an expression is an integer literal that fits in a signed 32-bit
111864 ** integer, then the EP_IntValue flag will have already been set */
@@ -111674,21 +111869,41 @@
111869 *pValue = p->u.iValue;
111870 return 1;
111871 }
111872 switch( p->op ){
111873 case TK_UPLUS: {
111874 rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
111875 break;
111876 }
111877 case TK_UMINUS: {
111878 int v = 0;
111879 if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
111880 assert( ((unsigned int)v)!=0x80000000 );
111881 *pValue = -v;
111882 rc = 1;
111883 }
111884 break;
111885 }
111886 case TK_VARIABLE: {
111887 sqlite3_value *pVal;
111888 if( pParse==0 ) break;
111889 if( NEVER(pParse->pVdbe==0) ) break;
111890 if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
111891 sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
111892 pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
111893 SQLITE_AFF_BLOB);
111894 if( pVal ){
111895 if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
111896 sqlite3_int64 vv = sqlite3_value_int64(pVal);
111897 if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
111898 *pValue = (int)vv;
111899 rc = 1;
111900 }
111901 }
111902 sqlite3ValueFree(pVal);
111903 }
111904 break;
111905 }
111906 default: break;
111907 }
111908 return rc;
111909 }
@@ -112379,19 +112594,34 @@
112594 if( ALWAYS(pEList->nExpr==nVal) ){
112595 Select *pCopy;
112596 SelectDest dest;
112597 int i;
112598 int rc;
112599 int addrBloom = 0;
112600 sqlite3SelectDestInit(&dest, SRT_Set, iTab);
112601 dest.zAffSdst = exprINAffinity(pParse, pExpr);
112602 pSelect->iLimit = 0;
112603 if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
112604 int regBloom = ++pParse->nMem;
112605 addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
112606 VdbeComment((v, "Bloom filter"));
112607 dest.iSDParm2 = regBloom;
112608 }
112609 testcase( pSelect->selFlags & SF_Distinct );
112610 testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
112611 pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
112612 rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
112613 sqlite3SelectDelete(pParse->db, pCopy);
112614 sqlite3DbFree(pParse->db, dest.zAffSdst);
112615 if( addrBloom ){
112616 sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
112617 if( dest.iSDParm2==0 ){
112618 sqlite3VdbeChangeToNoop(v, addrBloom);
112619 }else{
112620 sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
112621 }
112622 }
112623 if( rc ){
112624 sqlite3KeyInfoUnref(pKeyInfo);
112625 return;
112626 }
112627 assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
@@ -112830,10 +113060,19 @@
113060 addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
113061 }else{
113062 sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
113063 if( destIfFalse==destIfNull ){
113064 /* Combine Step 3 and Step 5 into a single opcode */
113065 if( ExprHasProperty(pExpr, EP_Subrtn) ){
113066 const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
113067 assert( pOp->opcode==OP_Once || pParse->nErr );
113068 if( pOp->opcode==OP_Once && pOp->p3>0 ){
113069 assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
113070 sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
113071 rLhs, nVector); VdbeCoverage(v);
113072 }
113073 }
113074 sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
113075 rLhs, nVector); VdbeCoverage(v);
113076 goto sqlite3ExprCodeIN_finished;
113077 }
113078 /* Ordinary Step 3, for the case where FALSE and NULL are distinct */
@@ -113112,17 +113351,21 @@
113351 /*
113352 ** Convert a scalar expression node to a TK_REGISTER referencing
113353 ** register iReg. The caller must ensure that iReg already contains
113354 ** the correct value for the expression.
113355 */
113356 SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
113357 Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
113358 if( NEVER(p==0) ) return;
113359 if( p->op==TK_REGISTER ){
113360 assert( p->iTable==iReg );
113361 }else{
113362 p->op2 = p->op;
113363 p->op = TK_REGISTER;
113364 p->iTable = iReg;
113365 ExprClearProperty(p, EP_Skip);
113366 }
113367 }
113368
113369 /*
113370 ** Evaluate an expression (either a vector or a scalar expression) and store
113371 ** the result in contiguous temporary registers. Return the index of
@@ -113950,12 +114193,13 @@
114193 }
114194 case TK_COLLATE: {
114195 if( !ExprHasProperty(pExpr, EP_Collate) ){
114196 /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
114197 ** "SOFT-COLLATE" that is added to constraints that are pushed down
114198 ** from outer queries into sub-queries by the WHERE-clause push-down
114199 ** optimization. Clear subtypes as subtypes may not cross a subquery
114200 ** boundary.
114201 */
114202 assert( pExpr->pLeft );
114203 sqlite3ExprCode(pParse, pExpr->pLeft, target);
114204 sqlite3VdbeAddOp1(v, OP_ClrSubtype, target);
114205 return target;
@@ -114120,11 +114364,11 @@
114364 if( db->mallocFailed ){
114365 sqlite3ExprDelete(db, pDel);
114366 break;
114367 }
114368 testcase( pX->op==TK_COLUMN );
114369 sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114370 testcase( regFree1==0 );
114371 memset(&opCompare, 0, sizeof(opCompare));
114372 opCompare.op = TK_EQ;
114373 opCompare.pLeft = pDel;
114374 pTest = &opCompare;
@@ -114174,19 +114418,18 @@
114418 if( pExpr->affExpr==OE_Abort ){
114419 sqlite3MayAbort(pParse);
114420 }
114421 assert( !ExprHasProperty(pExpr, EP_IntValue) );
114422 if( pExpr->affExpr==OE_Ignore ){
114423 sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
 
114424 VdbeCoverage(v);
114425 }else{
114426 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
114427 sqlite3VdbeAddOp3(v, OP_Halt,
114428 pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
114429 pExpr->affExpr, r1);
114430 }
 
114431 break;
114432 }
114433 #endif
114434 }
114435 sqlite3ReleaseTempReg(pParse, regFree1);
@@ -114471,11 +114714,11 @@
114714 compLeft.pLeft = pDel;
114715 compLeft.pRight = pExpr->x.pList->a[0].pExpr;
114716 compRight.op = TK_LE;
114717 compRight.pLeft = pDel;
114718 compRight.pRight = pExpr->x.pList->a[1].pExpr;
114719 sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
114720 if( xJump ){
114721 xJump(pParse, &exprAnd, dest, jumpIfNull);
114722 }else{
114723 /* Mark the expression is being from the ON or USING clause of a join
114724 ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
@@ -115549,24 +115792,22 @@
115792 if( pExpr->op!=TK_AGG_FUNCTION ){
115793 if( iAgg<pAggInfo->nColumn
115794 && pAggInfo->aCol[iAgg].pCExpr==pExpr
115795 ){
115796 pExpr = sqlite3ExprDup(db, pExpr, 0);
115797 if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
115798 pAggInfo->aCol[iAgg].pCExpr = pExpr;
 
115799 }
115800 }
115801 }else{
115802 assert( pExpr->op==TK_AGG_FUNCTION );
115803 if( ALWAYS(iAgg<pAggInfo->nFunc)
115804 && pAggInfo->aFunc[iAgg].pFExpr==pExpr
115805 ){
115806 pExpr = sqlite3ExprDup(db, pExpr, 0);
115807 if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
115808 pAggInfo->aFunc[iAgg].pFExpr = pExpr;
 
115809 }
115810 }
115811 }
115812 }
115813 return WRC_Continue;
@@ -124153,13 +124394,10 @@
124394 if( p->tabFlags & TF_HasGenerated ){
124395 sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
124396 sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
124397 db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
124398 }
 
 
 
124399 }
124400
124401 /* Add the table to the in-memory representation of the database.
124402 */
124403 if( db->init.busy ){
@@ -124293,12 +124531,13 @@
124531 #endif /* SQLITE_OMIT_VIEW */
124532
124533 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
124534 /*
124535 ** The Table structure pTable is really a VIEW. Fill in the names of
124536 ** the columns of the view in the pTable structure. Return non-zero if
124537 ** there are errors. If an error is seen an error message is left
124538 ** in pParse->zErrMsg.
124539 */
124540 static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
124541 Table *pSelTab; /* A fake table from which we get the result set */
124542 Select *pSel; /* Copy of the SELECT that implements the view */
124543 int nErr = 0; /* Number of errors encountered */
@@ -124417,11 +124656,11 @@
124656 pTable->pSchema->schemaFlags |= DB_UnresetViews;
124657 if( db->mallocFailed ){
124658 sqlite3DeleteColumnNames(db, pTable);
124659 }
124660 #endif /* SQLITE_OMIT_VIEW */
124661 return nErr + pParse->nErr;
124662 }
124663 SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
124664 assert( pTable!=0 );
124665 if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0;
124666 return viewGetColumnNames(pParse, pTable);
@@ -130715,10 +130954,12 @@
130954 StrAccum *pAccum = &pGCC->str;
130955 if( pAccum->accError==SQLITE_TOOBIG ){
130956 sqlite3_result_error_toobig(context);
130957 }else if( pAccum->accError==SQLITE_NOMEM ){
130958 sqlite3_result_error_nomem(context);
130959 }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
130960 sqlite3_result_text(context, "", 1, SQLITE_STATIC);
130961 }else{
130962 const char *zText = sqlite3_str_value(pAccum);
130963 sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
130964 }
130965 }
@@ -131054,10 +131295,11 @@
131295 UNUSED_PARAMETER(argc);
131296 assert( argc==3 );
131297 x = sqlite3_value_double(argv[0]);
131298 y = sqlite3_value_int(argv[1]);
131299 z = sqlite3_value_int(argv[2]);
131300 if( z<=0 ) z = 1;
131301 sqlite3FpDecode(&s, x, y, z);
131302 if( s.isSpecial==2 ){
131303 sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
131304 }else{
131305 sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP);
@@ -132595,11 +132837,12 @@
132837 if( action==OE_Restrict ){
132838 int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
132839 SrcList *pSrc;
132840 Expr *pRaise;
132841
132842 pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
132843 pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
132844 if( pRaise ){
132845 pRaise->affExpr = OE_Abort;
132846 }
132847 pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
132848 if( pSrc ){
@@ -135934,11 +136177,14 @@
136177 ** further downstream. */
136178 return 0; /* Corrupt schema - two indexes on the same btree */
136179 }
136180 }
136181 #ifndef SQLITE_OMIT_CHECK
136182 if( pDest->pCheck
136183 && (db->mDbFlags & DBFLAG_Vacuum)==0
136184 && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
136185 ){
136186 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
136187 }
136188 #endif
136189 #ifndef SQLITE_OMIT_FOREIGN_KEY
136190 /* Disallow the transfer optimization if the destination table contains
@@ -140282,11 +140528,11 @@
140528 pParse->nMem = 6;
140529
140530 /* Set the maximum error count */
140531 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140532 if( zRight ){
140533 if( sqlite3GetInt32(pValue->z, &mxErr) ){
140534 if( mxErr<=0 ){
140535 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
140536 }
140537 }else{
140538 pObjTab = sqlite3LocateTable(pParse, 0, zRight,
@@ -141490,10 +141736,11 @@
141736 /* Clear all content from pragma virtual table cursor. */
141737 static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
141738 int i;
141739 sqlite3_finalize(pCsr->pPragma);
141740 pCsr->pPragma = 0;
141741 pCsr->iRowid = 0;
141742 for(i=0; i<ArraySize(pCsr->azArg); i++){
141743 sqlite3_free(pCsr->azArg[i]);
141744 pCsr->azArg[i] = 0;
141745 }
141746 }
@@ -142290,11 +142537,17 @@
142537 SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
142538 Parse *pParse, /* Destroy when this Parser finishes */
142539 void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
142540 void *pPtr /* Pointer to object to be cleaned up */
142541 ){
142542 ParseCleanup *pCleanup;
142543 if( sqlite3FaultSim(300) ){
142544 pCleanup = 0;
142545 sqlite3OomFault(pParse->db);
142546 }else{
142547 pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
142548 }
142549 if( pCleanup ){
142550 pCleanup->pNext = pParse->pCleanup;
142551 pParse->pCleanup = pCleanup;
142552 pCleanup->pPtr = pPtr;
142553 pCleanup->xCleanup = xCleanup;
@@ -144116,16 +144369,22 @@
144369 ** ORDER BY in this case since the order of entries in the set
144370 ** does not matter. But there might be a LIMIT clause, in which
144371 ** case the order does matter */
144372 pushOntoSorter(
144373 pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
144374 pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
144375 }else{
144376 int r1 = sqlite3GetTempReg(pParse);
144377 assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
144378 sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
144379 r1, pDest->zAffSdst, nResultCol);
144380 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
144381 if( pDest->iSDParm2 ){
144382 sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
144383 regResult, nResultCol);
144384 ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
144385 }
144386 sqlite3ReleaseTempReg(pParse, r1);
144387 }
144388 break;
144389 }
144390
@@ -145063,12 +145322,11 @@
145322 Expr *p;
145323 struct ExprList_item *a;
145324 NameContext sNC;
145325
145326 assert( pSelect!=0 );
145327 assert( (pSelect->selFlags & SF_Resolved)!=0 );
 
145328 assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
145329 assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
145330 if( db->mallocFailed || IN_RENAME_OBJECT ) return;
145331 while( pSelect->pPrior ) pSelect = pSelect->pPrior;
145332 a = pSelect->pEList->a;
@@ -145075,21 +145333,26 @@
145333 memset(&sNC, 0, sizeof(sNC));
145334 sNC.pSrcList = pSelect->pSrc;
145335 for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
145336 const char *zType;
145337 i64 n;
145338 int m = 0;
145339 Select *pS2 = pSelect;
145340 pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
145341 p = a[i].pExpr;
145342 /* pCol->szEst = ... // Column size est for SELECT tables never used */
145343 pCol->affinity = sqlite3ExprAffinity(p);
145344 while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
145345 m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
145346 pS2 = pS2->pNext;
145347 pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
145348 }
145349 if( pCol->affinity<=SQLITE_AFF_NONE ){
145350 pCol->affinity = aff;
145351 }
145352 if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
145353 for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
 
 
145354 m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
145355 }
145356 if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
145357 pCol->affinity = SQLITE_AFF_BLOB;
145358 }else
@@ -145115,16 +145378,16 @@
145378 }
145379 }
145380 }
145381 }
145382 if( zType ){
145383 const i64 k = sqlite3Strlen30(zType);
145384 n = sqlite3Strlen30(pCol->zCnName);
145385 pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2);
145386 pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
145387 if( pCol->zCnName ){
145388 memcpy(&pCol->zCnName[n+1], zType, k+1);
145389 pCol->colFlags |= COLFLAG_HASTYPE;
145390 }
145391 }
145392 pColl = sqlite3ExprCollSeq(pParse, p);
145393 if( pColl ){
@@ -145227,11 +145490,11 @@
145490 assert( pLimit->op==TK_LIMIT );
145491 assert( pLimit->pLeft!=0 );
145492 p->iLimit = iLimit = ++pParse->nMem;
145493 v = sqlite3GetVdbe(pParse);
145494 assert( v!=0 );
145495 if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
145496 sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
145497 VdbeComment((v, "LIMIT counter"));
145498 if( n==0 ){
145499 sqlite3VdbeGoto(v, iBreak);
145500 }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
@@ -145707,11 +145970,11 @@
145970 testcase( rc!=SQLITE_OK );
145971 pDelete = p->pPrior;
145972 p->pPrior = pPrior;
145973 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
145974 if( p->pLimit
145975 && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
145976 && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
145977 ){
145978 p->nSelectRow = sqlite3LogEst((u64)nLimit);
145979 }
145980 if( addr ){
@@ -146051,10 +146314,15 @@
146314 r1 = sqlite3GetTempReg(pParse);
146315 sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
146316 r1, pDest->zAffSdst, pIn->nSdst);
146317 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
146318 pIn->iSdst, pIn->nSdst);
146319 if( pDest->iSDParm2>0 ){
146320 sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
146321 pIn->iSdst, pIn->nSdst);
146322 ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
146323 }
146324 sqlite3ReleaseTempReg(pParse, r1);
146325 break;
146326 }
146327
146328 /* If this is a scalar select that is part of an expression, then
@@ -147798,10 +148066,22 @@
148066 ** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
148067 ** WHERE x=5 AND y=10;
148068 **
148069 ** The hope is that the terms added to the inner query will make it more
148070 ** efficient.
148071 **
148072 ** NAME AMBIGUITY
148073 **
148074 ** This optimization is called the "WHERE-clause push-down optimization".
148075 **
148076 ** Do not confuse this optimization with another unrelated optimization
148077 ** with a similar name: The "MySQL push-down optimization" causes WHERE
148078 ** clause terms that can be evaluated using only the index and without
148079 ** reference to the table are run first, so that if they are false,
148080 ** unnecessary table seeks are avoided.
148081 **
148082 ** RULES
148083 **
148084 ** Do not attempt this optimization if:
148085 **
148086 ** (1) (** This restriction was removed on 2017-09-29. We used to
148087 ** disallow this optimization for aggregate subqueries, but now
@@ -147864,14 +148144,14 @@
148144 ** (9b) The subquery is to the right of the ON/USING clause
148145 **
148146 ** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
148147 ** clause and the subquery.
148148 **
148149 ** Without this restriction, the WHERE-clause push-down optimization
148150 ** might move the ON/USING filter expression from the left side of a
148151 ** RIGHT JOIN over to the right side, which leads to incorrect answers.
148152 ** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
148153 **
148154 ** (10) The inner query is not the right-hand table of a RIGHT JOIN.
148155 **
148156 ** (11) The subquery is not a VALUES clause
148157 **
@@ -147999,11 +148279,11 @@
148279 return 0; /* Restriction (12) */
148280 }
148281 }
148282 #endif
148283
148284 if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
148285 nChng++;
148286 pSubq->selFlags |= SF_PushDown;
148287 while( pSubq ){
148288 SubstContext x;
148289 pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -149134,12 +149414,11 @@
149414 SrcItem *pFrom;
149415
149416 if( p->selFlags & SF_HasTypeInfo ) return;
149417 p->selFlags |= SF_HasTypeInfo;
149418 pParse = pWalker->pParse;
149419 assert( (p->selFlags & SF_Resolved) );
 
149420 pTabList = p->pSrc;
149421 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
149422 Table *pTab = pFrom->pTab;
149423 assert( pTab!=0 );
149424 if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
@@ -150259,17 +150538,20 @@
150538 ** (5) The ORDER BY isn't going to accomplish anything because
150539 ** one of:
150540 ** (a) The outer query has a different ORDER BY clause
150541 ** (b) The subquery is part of a join
150542 ** See forum post 062d576715d277c8
150543 ** (6) The subquery is not a recursive CTE. ORDER BY has a different
150544 ** meaning for recursive CTEs and this optimization does not
150545 ** apply.
150546 **
150547 ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
150548 */
150549 if( pSub->pOrderBy!=0
150550 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
150551 && pSub->pLimit==0 /* Condition (1) */
150552 && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */
150553 && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
150554 && OptimizationEnabled(db, SQLITE_OmitOrderBy)
150555 ){
150556 TREETRACE(0x800,pParse,p,
150557 ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
@@ -150428,11 +150710,11 @@
150710 sqlite3TreeViewSelect(0, p, 0);
150711 }
150712 #endif
150713 assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
150714 }else{
150715 TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
150716 }
150717
150718 /* Convert unused result columns of the subquery into simple NULL
150719 ** expressions, to avoid unneeded searching and computation.
150720 */
@@ -150571,16 +150853,22 @@
150853 ** written the query must use a temp-table for at least one of the ORDER
150854 ** BY and DISTINCT, and an index or separate temp-table for the other.
150855 */
150856 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
150857 && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
150858 && OptimizationEnabled(db, SQLITE_GroupByOrder)
150859 #ifndef SQLITE_OMIT_WINDOWFUNC
150860 && p->pWin==0
150861 #endif
150862 ){
150863 p->selFlags &= ~SF_Distinct;
150864 pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
150865 if( pGroupBy ){
150866 for(i=0; i<pGroupBy->nExpr; i++){
150867 pGroupBy->a[i].u.x.iOrderByCol = i+1;
150868 }
150869 }
150870 p->selFlags |= SF_Aggregate;
150871 /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
150872 ** the sDistinct.isTnct is still set. Hence, isTnct represents the
150873 ** original setting of the SF_Distinct flag, not the current setting */
150874 assert( sDistinct.isTnct );
@@ -151039,16 +151327,29 @@
151327 if( groupBySort ){
151328 sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
151329 sortOut, sortPTab);
151330 }
151331 for(j=0; j<pGroupBy->nExpr; j++){
151332 int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
151333
151334 if( groupBySort ){
151335 sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
151336 }else{
151337 pAggInfo->directMode = 1;
151338 sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
151339 }
151340
151341 if( iOrderByCol ){
151342 Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
151343 Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
151344 if( ALWAYS(pBase!=0)
151345 && pBase->op!=TK_AGG_COLUMN
151346 && pBase->op!=TK_REGISTER
151347 ){
151348 sqlite3ExprToRegister(pX, iAMem+j);
151349 }
151350 }
151351 }
151352 sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
151353 (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
151354 addr1 = sqlite3VdbeCurrentAddr(v);
151355 sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
@@ -151060,13 +151361,13 @@
151361 ** This code copies current group by terms in b0,b1,b2,...
151362 ** over to a0,a1,a2. It then calls the output subroutine
151363 ** and resets the aggregate accumulator registers in preparation
151364 ** for the next GROUP BY batch.
151365 */
 
151366 sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
151367 VdbeComment((v, "output one row"));
151368 sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
151369 sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
151370 VdbeComment((v, "check abort flag"));
151371 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
151372 VdbeComment((v, "reset accumulator"));
151373
@@ -152495,10 +152796,76 @@
152796 }
152797 }
152798 }
152799 return pNew;
152800 }
152801
152802 /* If the Expr node is a subquery or an EXISTS operator or an IN operator that
152803 ** uses a subquery, and if the subquery is SF_Correlated, then mark the
152804 ** expression as EP_VarSelect.
152805 */
152806 static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){
152807 UNUSED_PARAMETER(NotUsed);
152808 if( ExprUseXSelect(pExpr)
152809 && (pExpr->x.pSelect->selFlags & SF_Correlated)!=0
152810 ){
152811 testcase( ExprHasProperty(pExpr, EP_VarSelect) );
152812 ExprSetProperty(pExpr, EP_VarSelect);
152813 }
152814 return WRC_Continue;
152815 }
152816
152817
152818 /*
152819 ** If the SELECT references the table pWalker->u.pTab, then do two things:
152820 **
152821 ** (1) Mark the SELECT as as SF_Correlated.
152822 ** (2) Set pWalker->eCode to non-zero so that the caller will know
152823 ** that (1) has happened.
152824 */
152825 static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
152826 int i;
152827 SrcList *pSrc;
152828 assert( pSelect!=0 );
152829 pSrc = pSelect->pSrc;
152830 assert( pSrc!=0 );
152831 for(i=0; i<pSrc->nSrc; i++){
152832 if( pSrc->a[i].pTab==pWalker->u.pTab ){
152833 testcase( pSelect->selFlags & SF_Correlated );
152834 pSelect->selFlags |= SF_Correlated;
152835 pWalker->eCode = 1;
152836 break;
152837 }
152838 }
152839 return WRC_Continue;
152840 }
152841
152842 /*
152843 ** Scan the expression list that is the argument to RETURNING looking
152844 ** for subqueries that depend on the table which is being modified in the
152845 ** statement that is hosting the RETURNING clause (pTab). Mark all such
152846 ** subqueries as SF_Correlated. If the subqueries are part of an
152847 ** expression, mark the expression as EP_VarSelect.
152848 **
152849 ** https://sqlite.org/forum/forumpost/2c83569ce8945d39
152850 */
152851 static void sqlite3ProcessReturningSubqueries(
152852 ExprList *pEList,
152853 Table *pTab
152854 ){
152855 Walker w;
152856 memset(&w, 0, sizeof(w));
152857 w.xExprCallback = sqlite3ExprWalkNoop;
152858 w.xSelectCallback = sqlite3ReturningSubqueryCorrelated;
152859 w.u.pTab = pTab;
152860 sqlite3WalkExprList(&w, pEList);
152861 if( w.eCode ){
152862 w.xExprCallback = sqlite3ReturningSubqueryVarSelect;
152863 w.xSelectCallback = sqlite3SelectWalkNoop;
152864 sqlite3WalkExprList(&w, pEList);
152865 }
152866 }
152867
152868 /*
152869 ** Generate code for the RETURNING trigger. Unlike other triggers
152870 ** that invoke a subprogram in the bytecode, the code for RETURNING
152871 ** is generated in-line.
@@ -152532,10 +152899,11 @@
152899 memset(&sFrom, 0, sizeof(sFrom));
152900 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
152901 sSelect.pSrc = &sFrom;
152902 sFrom.nSrc = 1;
152903 sFrom.a[0].pTab = pTab;
152904 sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
152905 sFrom.a[0].iCursor = -1;
152906 sqlite3SelectPrep(pParse, &sSelect, 0);
152907 if( pParse->nErr==0 ){
152908 assert( db->mallocFailed==0 );
152909 sqlite3GenerateColumnNames(pParse, &sSelect);
@@ -152558,10 +152926,11 @@
152926 && ALWAYS(!db->mallocFailed)
152927 ){
152928 int i;
152929 int nCol = pNew->nExpr;
152930 int reg = pParse->nMem+1;
152931 sqlite3ProcessReturningSubqueries(pNew, pTab);
152932 pParse->nMem += nCol+2;
152933 pReturning->iRetReg = reg;
152934 for(i=0; i<nCol; i++){
152935 Expr *pCol = pNew->a[i].pExpr;
152936 assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
@@ -153959,10 +154328,13 @@
154328 }else{
154329 sqlite3VdbeAddOp2(v, OP_Null, 0, k);
154330 }
154331 }
154332 if( chngRowid==0 && pPk==0 ){
154333 #ifdef SQLITE_ALLOW_ROWID_IN_VIEW
154334 if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
154335 #endif
154336 sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
154337 }
154338 }
154339
154340 /* Populate the array of registers beginning at regNew with the new
@@ -155985,11 +156357,14 @@
156357 */
156358 z = (const unsigned char*)zCreateTable;
156359 for(i=0; aKeyword[i]; i++){
156360 int tokenType = 0;
156361 do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
156362 if( tokenType!=aKeyword[i] ){
156363 sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
156364 return SQLITE_ERROR;
156365 }
156366 }
156367
156368 sqlite3_mutex_enter(db->mutex);
156369 pCtx = db->pVtabCtx;
156370 if( !pCtx || pCtx->bDeclared ){
@@ -156709,10 +157084,12 @@
157084 u16 nLTerm; /* Number of entries in aLTerm[] */
157085 u16 nSkip; /* Number of NULL aLTerm[] entries */
157086 /**** whereLoopXfer() copies fields above ***********************/
157087 # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
157088 u16 nLSlot; /* Number of slots allocated for aLTerm[] */
157089 LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not
157090 ** initialized unless pWInfo->nOutStarDelta>0 */
157091 WhereTerm **aLTerm; /* WhereTerms used */
157092 WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
157093 WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
157094 };
157095
@@ -157031,10 +157408,11 @@
157408 u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
157409 unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
157410 unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
157411 unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
157412 unsigned sorted :1; /* True if really sorted (not just grouped) */
157413 LogEst nOutStarDelta; /* Artifical nOut reduction for star-query */
157414 LogEst nRowOut; /* Estimated number of output rows */
157415 int iTop; /* The very beginning of the WHERE loop */
157416 int iEndWhere; /* End of the WHERE clause itself */
157417 WhereLoop *pLoops; /* List of all WhereLoop objects */
157418 WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
@@ -157388,11 +157766,12 @@
157766 }
157767 #endif
157768 zMsg = sqlite3StrAccumFinish(&str);
157769 sqlite3ExplainBreakpoint("",zMsg);
157770 ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
157771 pParse->addrExplain, pLoop->rRun,
157772 zMsg, P4_DYNAMIC);
157773 }
157774 return ret;
157775 }
157776
157777 /*
@@ -157630,10 +158009,43 @@
158009 zAff[i] = SQLITE_AFF_BLOB;
158010 }
158011 }
158012 }
158013
158014 /*
158015 ** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
158016 ** columns might have been rearranged in the result set. This routine
158017 ** fixes them up.
158018 **
158019 ** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values
158020 ** contain the *old* locations of each expression. This is a temporary
158021 ** use of u.x.iOrderByCol, not its intended use. The caller must reset
158022 ** u.x.iOrderByCol back to zero for all entries in pEList before the
158023 ** caller returns.
158024 **
158025 ** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
158026 ** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based
158027 ** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero.
158028 */
158029 static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
158030 int i, j;
158031 if( pOrderBy==0 ) return;
158032 for(i=0; i<pOrderBy->nExpr; i++){
158033 int t = pOrderBy->a[i].u.x.iOrderByCol;
158034 if( t==0 ) continue;
158035 for(j=0; j<pEList->nExpr; j++){
158036 if( pEList->a[j].u.x.iOrderByCol==t ){
158037 pOrderBy->a[i].u.x.iOrderByCol = j+1;
158038 break;
158039 }
158040 }
158041 if( j>=pEList->nExpr ){
158042 pOrderBy->a[i].u.x.iOrderByCol = 0;
158043 }
158044 }
158045 }
158046
158047
158048 /*
158049 ** pX is an expression of the form: (vector) IN (SELECT ...)
158050 ** In other words, it is a vector IN operator with a SELECT clause on the
158051 ** LHS. But not all terms in the vector are indexable and the terms might
@@ -157693,10 +158105,11 @@
158105 assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
158106 iField = pLoop->aLTerm[i]->u.x.iField - 1;
158107 if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
158108 pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
158109 pOrigRhs->a[iField].pExpr = 0;
158110 if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
158111 if( pOrigLhs ){
158112 assert( pOrigLhs->a[iField].pExpr!=0 );
158113 pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
158114 pOrigLhs->a[iField].pExpr = 0;
158115 }
@@ -157715,22 +158128,20 @@
158128 Expr *p = pLhs->a[0].pExpr;
158129 pLhs->a[0].pExpr = 0;
158130 sqlite3ExprDelete(db, pNew->pLeft);
158131 pNew->pLeft = p;
158132 }
158133
158134 /* If either the ORDER BY clause or the GROUP BY clause contains
158135 ** references to result-set columns, those references might now be
158136 ** obsolete. So fix them up.
158137 */
158138 assert( pRhs!=0 || db->mallocFailed );
158139 if( pRhs ){
158140 adjustOrderByCol(pSelect->pOrderBy, pRhs);
158141 adjustOrderByCol(pSelect->pGroupBy, pRhs);
158142 for(i=0; i<pRhs->nExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
 
 
158143 }
158144
158145 #if 0
158146 printf("For indexing, change the IN expr:\n");
158147 sqlite3TreeViewExpr(0, pX, 0);
@@ -157740,10 +158151,151 @@
158151 }
158152 }
158153 return pNew;
158154 }
158155
158156
158157 #ifndef SQLITE_OMIT_SUBQUERY
158158 /*
158159 ** Generate code for a single X IN (....) term of the WHERE clause.
158160 **
158161 ** This is a special-case of codeEqualityTerm() that works for IN operators
158162 ** only. It is broken out into a subroutine because this case is
158163 ** uncommon and by splitting it off into a subroutine, the common case
158164 ** runs faster.
158165 **
158166 ** The current value for the constraint is left in register iTarget.
158167 ** This routine sets up a loop that will iterate over all values of X.
158168 */
158169 static SQLITE_NOINLINE void codeINTerm(
158170 Parse *pParse, /* The parsing context */
158171 WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
158172 WhereLevel *pLevel, /* The level of the FROM clause we are working on */
158173 int iEq, /* Index of the equality term within this level */
158174 int bRev, /* True for reverse-order IN operations */
158175 int iTarget /* Attempt to leave results in this register */
158176 ){
158177 Expr *pX = pTerm->pExpr;
158178 int eType = IN_INDEX_NOOP;
158179 int iTab;
158180 struct InLoop *pIn;
158181 WhereLoop *pLoop = pLevel->pWLoop;
158182 Vdbe *v = pParse->pVdbe;
158183 int i;
158184 int nEq = 0;
158185 int *aiMap = 0;
158186
158187 if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
158188 && pLoop->u.btree.pIndex!=0
158189 && pLoop->u.btree.pIndex->aSortOrder[iEq]
158190 ){
158191 testcase( iEq==0 );
158192 testcase( bRev );
158193 bRev = !bRev;
158194 }
158195 assert( pX->op==TK_IN );
158196
158197 for(i=0; i<iEq; i++){
158198 if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
158199 disableTerm(pLevel, pTerm);
158200 return;
158201 }
158202 }
158203 for(i=iEq;i<pLoop->nLTerm; i++){
158204 assert( pLoop->aLTerm[i]!=0 );
158205 if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
158206 }
158207
158208 iTab = 0;
158209 if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
158210 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
158211 }else{
158212 Expr *pExpr = pTerm->pExpr;
158213 if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
158214 sqlite3 *db = pParse->db;
158215 pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
158216 if( !db->mallocFailed ){
158217 aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
158218 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
158219 pExpr->iTable = iTab;
158220 }
158221 sqlite3ExprDelete(db, pX);
158222 }else{
158223 int n = sqlite3ExprVectorSize(pX->pLeft);
158224 aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
158225 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
158226 }
158227 pX = pExpr;
158228 }
158229
158230 if( eType==IN_INDEX_INDEX_DESC ){
158231 testcase( bRev );
158232 bRev = !bRev;
158233 }
158234 sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
158235 VdbeCoverageIf(v, bRev);
158236 VdbeCoverageIf(v, !bRev);
158237
158238 assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
158239 pLoop->wsFlags |= WHERE_IN_ABLE;
158240 if( pLevel->u.in.nIn==0 ){
158241 pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
158242 }
158243 if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
158244 pLoop->wsFlags |= WHERE_IN_EARLYOUT;
158245 }
158246
158247 i = pLevel->u.in.nIn;
158248 pLevel->u.in.nIn += nEq;
158249 pLevel->u.in.aInLoop =
158250 sqlite3WhereRealloc(pTerm->pWC->pWInfo,
158251 pLevel->u.in.aInLoop,
158252 sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
158253 pIn = pLevel->u.in.aInLoop;
158254 if( pIn ){
158255 int iMap = 0; /* Index in aiMap[] */
158256 pIn += i;
158257 for(i=iEq;i<pLoop->nLTerm; i++){
158258 if( pLoop->aLTerm[i]->pExpr==pX ){
158259 int iOut = iTarget + i - iEq;
158260 if( eType==IN_INDEX_ROWID ){
158261 pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
158262 }else{
158263 int iCol = aiMap ? aiMap[iMap++] : 0;
158264 pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
158265 }
158266 sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
158267 if( i==iEq ){
158268 pIn->iCur = iTab;
158269 pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
158270 if( iEq>0 ){
158271 pIn->iBase = iTarget - i;
158272 pIn->nPrefix = i;
158273 }else{
158274 pIn->nPrefix = 0;
158275 }
158276 }else{
158277 pIn->eEndLoopOp = OP_Noop;
158278 }
158279 pIn++;
158280 }
158281 }
158282 testcase( iEq>0
158283 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
158284 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
158285 if( iEq>0
158286 && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
158287 ){
158288 sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
158289 }
158290 }else{
158291 pLevel->u.in.nIn = 0;
158292 }
158293 sqlite3DbFree(pParse->db, aiMap);
158294 }
158295 #endif
158296
158297
158298 /*
158299 ** Generate code for a single equality term of the WHERE clause. An equality
158300 ** term can be either X=expr or X IN (...). pTerm is the term to be
158301 ** coded.
@@ -157765,138 +158317,24 @@
158317 int iEq, /* Index of the equality term within this level */
158318 int bRev, /* True for reverse-order IN operations */
158319 int iTarget /* Attempt to leave results in this register */
158320 ){
158321 Expr *pX = pTerm->pExpr;
 
158322 int iReg; /* Register holding results */
158323
158324 assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
158325 assert( iTarget>0 );
158326 if( pX->op==TK_EQ || pX->op==TK_IS ){
158327 iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
158328 }else if( pX->op==TK_ISNULL ){
158329 iReg = iTarget;
158330 sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
158331 #ifndef SQLITE_OMIT_SUBQUERY
158332 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158333 assert( pX->op==TK_IN );
158334 iReg = iTarget;
158335 codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158336 #endif
158337 }
158338
158339 /* As an optimization, try to disable the WHERE clause term that is
158340 ** driving the index as it will always be true. The correct answer is
@@ -158506,10 +158944,31 @@
158944 }
158945 pLevel->regFilter = 0;
158946 pLevel->addrBrk = 0;
158947 }
158948 }
158949
158950 /*
158951 ** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
158952 ** operator. Return true if level pLoop is guaranteed to visit only one
158953 ** row for each key generated for the index.
158954 */
158955 static int whereLoopIsOneRow(WhereLoop *pLoop){
158956 if( pLoop->u.btree.pIndex->onError
158957 && pLoop->nSkip==0
158958 && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
158959 ){
158960 int ii;
158961 for(ii=0; ii<pLoop->u.btree.nEq; ii++){
158962 if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){
158963 return 0;
158964 }
158965 }
158966 return 1;
158967 }
158968 return 0;
158969 }
158970
158971 /*
158972 ** Generate code for the start of the iLevel-th loop in the WHERE clause
158973 ** implementation described by pWInfo.
158974 */
@@ -158585,11 +159044,11 @@
159044 || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
159045 );
159046 if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
159047 pLevel->iLeftJoin = ++pParse->nMem;
159048 sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
159049 VdbeComment((v, "init LEFT JOIN match flag"));
159050 }
159051
159052 /* Compute a safe address to jump to if we discover that the table for
159053 ** this loop is empty and can never contribute content. */
159054 for(j=iLevel; j>0; j--){
@@ -159254,11 +159713,13 @@
159713 ** a LEFT JOIN: */
159714 assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
159715 }
159716
159717 /* Record the instruction used to terminate the loop. */
159718 if( (pLoop->wsFlags & WHERE_ONEROW)
159719 || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
159720 ){
159721 pLevel->op = OP_Noop;
159722 }else if( bRev ){
159723 pLevel->op = OP_Prev;
159724 }else{
159725 pLevel->op = OP_Next;
@@ -159644,10 +160105,16 @@
160105 ** iLoop==2: Code remaining expressions that do not contain correlated
160106 ** sub-queries.
160107 ** iLoop==3: Code all remaining expressions.
160108 **
160109 ** An effort is made to skip unnecessary iterations of the loop.
160110 **
160111 ** This optimization of causing simple query restrictions to occur before
160112 ** more complex one is call the "push-down" optimization in MySQL. Here
160113 ** in SQLite, the name is "MySQL push-down", since there is also another
160114 ** totally unrelated optimization called "WHERE-clause push-down".
160115 ** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
160116 */
160117 iLoop = (pIdx ? 1 : 2);
160118 do{
160119 int iNext = 0; /* Next value for iLoop */
160120 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
@@ -159894,11 +160361,20 @@
160361 ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
160362 sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
160363 pRJ->regReturn);
160364 for(k=0; k<iLevel; k++){
160365 int iIdxCur;
160366 SrcItem *pRight;
160367 assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom );
160368 pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
160369 mAll |= pWInfo->a[k].pWLoop->maskSelf;
160370 if( pRight->fg.viaCoroutine ){
160371 sqlite3VdbeAddOp3(
160372 v, OP_Null, 0, pRight->regResult,
160373 pRight->regResult + pRight->pSelect->pEList->nExpr-1
160374 );
160375 }
160376 sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
160377 iIdxCur = pWInfo->a[k].iIdxCur;
160378 if( iIdxCur ){
160379 sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
160380 }
@@ -160063,11 +160539,16 @@
160539 static int allowedOp(int op){
160540 assert( TK_GT>TK_EQ && TK_GT<TK_GE );
160541 assert( TK_LT>TK_EQ && TK_LT<TK_GE );
160542 assert( TK_LE>TK_EQ && TK_LE<TK_GE );
160543 assert( TK_GE==TK_EQ+4 );
160544 assert( TK_IN<TK_EQ );
160545 assert( TK_IS<TK_EQ );
160546 assert( TK_ISNULL<TK_EQ );
160547 if( op>TK_GE ) return 0;
160548 if( op>=TK_EQ ) return 1;
160549 return op==TK_IN || op==TK_ISNULL || op==TK_IS;
160550 }
160551
160552 /*
160553 ** Commute a comparison operator. Expressions of the form "X op Y"
160554 ** are converted into "Y op X".
@@ -160096,19 +160577,20 @@
160577 ** Translate from TK_xx operator to WO_xx bitmask.
160578 */
160579 static u16 operatorMask(int op){
160580 u16 c;
160581 assert( allowedOp(op) );
160582 if( op>=TK_EQ ){
160583 assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
160584 c = (u16)(WO_EQ<<(op-TK_EQ));
160585 }else if( op==TK_IN ){
160586 c = WO_IN;
160587 }else if( op==TK_ISNULL ){
160588 c = WO_ISNULL;
160589 }else{
160590 assert( op==TK_IS );
160591 c = WO_IS;
 
 
 
160592 }
160593 assert( op!=TK_ISNULL || c==WO_ISNULL );
160594 assert( op!=TK_IN || c==WO_IN );
160595 assert( op!=TK_EQ || c==WO_EQ );
160596 assert( op!=TK_LT || c==WO_LT );
@@ -160391,10 +160873,17 @@
160873 *ppLeft = pCol;
160874 return 1;
160875 }
160876 }
160877 }
160878 }else if( pExpr->op>=TK_EQ ){
160879 /* Comparison operators are a common case. Save a few comparisons for
160880 ** that common case by terminating early. */
160881 assert( TK_NE < TK_EQ );
160882 assert( TK_ISNOT < TK_EQ );
160883 assert( TK_NOTNULL < TK_EQ );
160884 return 0;
160885 }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
160886 int res = 0;
160887 Expr *pLeft = pExpr->pLeft;
160888 Expr *pRight = pExpr->pRight;
160889 assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
@@ -161532,11 +162021,11 @@
162021 Parse *pParse = pWC->pWInfo->pParse;
162022 sqlite3 *db = pParse->db;
162023 Expr *pNew;
162024 int iVal = 0;
162025
162026 if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
162027 Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
162028 if( pVal==0 ) return;
162029 ExprSetProperty(pVal, EP_IntValue);
162030 pVal->u.iValue = iVal;
162031 pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
@@ -161600,10 +162089,11 @@
162089 ** will only be added if each of the child terms passes the
162090 ** (leftCursor==iCsr) test below. */
162091 continue;
162092 }
162093 if( pWC->a[ii].leftCursor!=iCsr ) return;
162094 if( pWC->a[ii].prereqRight!=0 ) return;
162095 }
162096
162097 /* Check condition (5). Return early if it is not met. */
162098 if( pOrderBy ){
162099 for(ii=0; ii<pOrderBy->nExpr; ii++){
@@ -161614,16 +162104,18 @@
162104 }
162105 }
162106
162107 /* All conditions are met. Add the terms to the where-clause object. */
162108 assert( p->pLimit->op==TK_LIMIT );
162109 if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){
 
 
162110 whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
162111 iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
162112 }
162113 if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){
162114 whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
162115 iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
162116 }
162117 }
162118 }
162119
162120 /*
162121 ** Initialize a preallocated WhereClause structure.
@@ -162136,10 +162628,46 @@
162628 if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
162629 return p;
162630 }
162631 return 0;
162632 }
162633
162634 /*
162635 ** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
162636 ** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
162637 ** This function checks to see if the term is compatible with an index
162638 ** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
162639 ** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
162640 ** or "NOCASE") used by the comparison in pTerm. If it is not compatible
162641 ** with affinity idxaff, NULL is returned.
162642 */
162643 static SQLITE_NOINLINE const char *indexInAffinityOk(
162644 Parse *pParse,
162645 WhereTerm *pTerm,
162646 u8 idxaff
162647 ){
162648 Expr *pX = pTerm->pExpr;
162649 Expr inexpr;
162650
162651 assert( pTerm->eOperator & WO_IN );
162652
162653 if( sqlite3ExprIsVector(pX->pLeft) ){
162654 int iField = pTerm->u.x.iField - 1;
162655 inexpr.flags = 0;
162656 inexpr.op = TK_EQ;
162657 inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
162658 assert( ExprUseXSelect(pX) );
162659 inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
162660 pX = &inexpr;
162661 }
162662
162663 if( sqlite3IndexAffinityOk(pX, idxaff) ){
162664 CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
162665 return pRet ? pRet->zName : sqlite3StrBINARY;
162666 }
162667 return 0;
162668 }
162669
162670 /*
162671 ** Advance to the next WhereTerm that matches according to the criteria
162672 ** established when the pScan object was initialized by whereScanInit().
162673 ** Return NULL if there are no more matching WhereTerms.
@@ -162187,20 +162715,28 @@
162715 }
162716 }
162717 if( (pTerm->eOperator & pScan->opMask)!=0 ){
162718 /* Verify the affinity and collating sequence match */
162719 if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
162720 const char *zCollName;
162721 Parse *pParse = pWC->pWInfo->pParse;
162722 pX = pTerm->pExpr;
162723
162724 if( (pTerm->eOperator & WO_IN) ){
162725 zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
162726 if( !zCollName ) continue;
162727 }else{
162728 CollSeq *pColl;
162729 if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
162730 continue;
162731 }
162732 assert(pX->pLeft);
162733 pColl = sqlite3ExprCompareCollSeq(pParse, pX);
162734 zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
162735 }
162736
162737 if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
 
 
162738 continue;
162739 }
162740 }
162741 if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
162742 && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
@@ -162631,10 +163167,44 @@
163167 return 0;
163168 }
163169 return 1;
163170 }
163171
163172 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
163173 /*
163174 ** Return true if column iCol of table pTab seem like it might be a
163175 ** good column to use as part of a query-time index.
163176 **
163177 ** Current algorithm (subject to improvement!):
163178 **
163179 ** 1. If iCol is already the left-most column of some other index,
163180 ** then return false.
163181 **
163182 ** 2. If iCol is part of an existing index that has an aiRowLogEst of
163183 ** more than 20, then return false.
163184 **
163185 ** 3. If no disqualifying conditions above are found, return true.
163186 */
163187 static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
163188 const Table *pTab,
163189 int iCol
163190 ){
163191 const Index *pIdx;
163192 for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
163193 int j;
163194 for(j=0; j<pIdx->nKeyCol; j++){
163195 if( pIdx->aiColumn[j]==iCol ){
163196 if( j==0 ) return 0;
163197 if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
163198 break;
163199 }
163200 }
163201 }
163202 return 1;
163203 }
163204 #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
163205
163206
163207
163208 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
163209 /*
163210 ** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -162645,10 +163215,12 @@
163215 const WhereTerm *pTerm, /* WHERE clause term to check */
163216 const SrcItem *pSrc, /* Table we are trying to access */
163217 const Bitmask notReady /* Tables in outer loops of the join */
163218 ){
163219 char aff;
163220 int leftCol;
163221
163222 if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
163223 if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
163224 assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
163225 if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
163226 && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
@@ -162655,15 +163227,16 @@
163227 ){
163228 return 0; /* See https://sqlite.org/forum/forumpost/51e6959f61 */
163229 }
163230 if( (pTerm->prereqRight & notReady)!=0 ) return 0;
163231 assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
163232 leftCol = pTerm->u.x.leftColumn;
163233 if( leftCol<0 ) return 0;
163234 aff = pSrc->pTab->aCol[leftCol].affinity;
163235 if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
163236 testcase( pTerm->pExpr->op==TK_IS );
163237 return columnIsGoodIndexCandidate(pSrc->pTab, leftCol);
163238 }
163239 #endif
163240
163241
163242 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -162777,11 +163350,11 @@
163350 Expr *pExpr = pTerm->pExpr;
163351 /* Make the automatic index a partial index if there are terms in the
163352 ** WHERE clause (or the ON clause of a LEFT join) that constrain which
163353 ** rows of the target table (pSrc) that can be used. */
163354 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
163355 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
163356 ){
163357 pPartial = sqlite3ExprAnd(pParse, pPartial,
163358 sqlite3ExprDup(pParse->db, pExpr, 0));
163359 }
163360 if( termCanDriveIndex(pTerm, pSrc, notReady) ){
@@ -163046,11 +163619,11 @@
163619 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
163620 pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
163621 for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
163622 Expr *pExpr = pTerm->pExpr;
163623 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
163624 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
163625 ){
163626 sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
163627 }
163628 }
163629 if( pLoop->wsFlags & WHERE_IPK ){
@@ -163100,10 +163673,24 @@
163673 pParse->pIdxPartExpr = saved_pIdxPartExpr;
163674 }
163675
163676
163677 #ifndef SQLITE_OMIT_VIRTUALTABLE
163678 /*
163679 ** Return term iTerm of the WhereClause passed as the first argument. Terms
163680 ** are numbered from 0 upwards, starting with the terms in pWC->a[], then
163681 ** those in pWC->pOuter->a[] (if any), and so on.
163682 */
163683 static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
163684 WhereClause *p;
163685 for(p=pWC; p; p=p->pOuter){
163686 if( iTerm<p->nTerm ) return &p->a[iTerm];
163687 iTerm -= p->nTerm;
163688 }
163689 return 0;
163690 }
163691
163692 /*
163693 ** Allocate and populate an sqlite3_index_info structure. It is the
163694 ** responsibility of the caller to eventually release the structure
163695 ** by passing the pointer returned by this function to freeIndexInfo().
163696 */
@@ -163126,10 +163713,11 @@
163713 sqlite3_index_info *pIdxInfo;
163714 u16 mNoOmit = 0;
163715 const Table *pTab;
163716 int eDistinct = 0;
163717 ExprList *pOrderBy = pWInfo->pOrderBy;
163718 WhereClause *p;
163719
163720 assert( pSrc!=0 );
163721 pTab = pSrc->pTab;
163722 assert( pTab!=0 );
163723 assert( IsVirtual(pTab) );
@@ -163136,32 +163724,34 @@
163724
163725 /* Find all WHERE clause constraints referring to this virtual table.
163726 ** Mark each term with the TERM_OK flag. Set nTerm to the number of
163727 ** terms found.
163728 */
163729 for(p=pWC, nTerm=0; p; p=p->pOuter){
163730 for(i=0, pTerm=p->a; i<p->nTerm; i++, pTerm++){
163731 pTerm->wtFlags &= ~TERM_OK;
163732 if( pTerm->leftCursor != pSrc->iCursor ) continue;
163733 if( pTerm->prereqRight & mUnusable ) continue;
163734 assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
163735 testcase( pTerm->eOperator & WO_IN );
163736 testcase( pTerm->eOperator & WO_ISNULL );
163737 testcase( pTerm->eOperator & WO_IS );
163738 testcase( pTerm->eOperator & WO_ALL );
163739 if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
163740 if( pTerm->wtFlags & TERM_VNULL ) continue;
163741
163742 assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
163743 assert( pTerm->u.x.leftColumn>=XN_ROWID );
163744 assert( pTerm->u.x.leftColumn<pTab->nCol );
163745 if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
163746 && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
163747 ){
163748 continue;
163749 }
163750 nTerm++;
163751 pTerm->wtFlags |= TERM_OK;
163752 }
163753 }
163754
163755 /* If the ORDER BY clause contains only columns in the current
163756 ** virtual table then allocate space for the aOrderBy part of
163757 ** the sqlite3_index_info structure.
@@ -163207,11 +163797,11 @@
163797 /* No matches cause a break out of the loop */
163798 break;
163799 }
163800 if( i==n ){
163801 nOrderBy = n;
163802 if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
163803 eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
163804 }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
163805 eDistinct = 1;
163806 }
163807 }
@@ -163236,53 +163826,56 @@
163826 pIdxInfo->aConstraintUsage = pUsage;
163827 pHidden->pWC = pWC;
163828 pHidden->pParse = pParse;
163829 pHidden->eDistinct = eDistinct;
163830 pHidden->mIn = 0;
163831 for(p=pWC, i=j=0; p; p=p->pOuter){
163832 int nLast = i+p->nTerm;;
163833 for(pTerm=p->a; i<nLast; i++, pTerm++){
163834 u16 op;
163835 if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
163836 pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
163837 pIdxCons[j].iTermOffset = i;
163838 op = pTerm->eOperator & WO_ALL;
163839 if( op==WO_IN ){
163840 if( (pTerm->wtFlags & TERM_SLICE)==0 ){
163841 pHidden->mIn |= SMASKBIT32(j);
163842 }
163843 op = WO_EQ;
163844 }
163845 if( op==WO_AUX ){
163846 pIdxCons[j].op = pTerm->eMatchOp;
163847 }else if( op & (WO_ISNULL|WO_IS) ){
163848 if( op==WO_ISNULL ){
163849 pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
163850 }else{
163851 pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
163852 }
163853 }else{
163854 pIdxCons[j].op = (u8)op;
163855 /* The direct assignment in the previous line is possible only because
163856 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
163857 ** following asserts verify this fact. */
163858 assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
163859 assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
163860 assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
163861 assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
163862 assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
163863 assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
163864
163865 if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
163866 && sqlite3ExprIsVector(pTerm->pExpr->pRight)
163867 ){
163868 testcase( j!=i );
163869 if( j<16 ) mNoOmit |= (1 << j);
163870 if( op==WO_LT ) pIdxCons[j].op = WO_LE;
163871 if( op==WO_GT ) pIdxCons[j].op = WO_GE;
163872 }
163873 }
163874
163875 j++;
163876 }
163877 }
163878 assert( j==nTerm );
163879 pIdxInfo->nConstraint = j;
163880 for(i=j=0; i<nOrderBy; i++){
163881 Expr *pExpr = pOrderBy->a[i].pExpr;
@@ -163297,10 +163890,21 @@
163890 pIdxInfo->nOrderBy = j;
163891
163892 *pmNoOmit = mNoOmit;
163893 return pIdxInfo;
163894 }
163895
163896 /*
163897 ** Free and zero the sqlite3_index_info.idxStr value if needed.
163898 */
163899 static void freeIdxStr(sqlite3_index_info *pIdxInfo){
163900 if( pIdxInfo->needToFreeIdxStr ){
163901 sqlite3_free(pIdxInfo->idxStr);
163902 pIdxInfo->idxStr = 0;
163903 pIdxInfo->needToFreeIdxStr = 0;
163904 }
163905 }
163906
163907 /*
163908 ** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
163909 ** and possibly modified by xBestIndex methods.
163910 */
@@ -163313,10 +163917,11 @@
163917 assert( pHidden->pParse->db==db );
163918 for(i=0; i<pIdxInfo->nConstraint; i++){
163919 sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
163920 pHidden->aRhs[i] = 0;
163921 }
163922 freeIdxStr(pIdxInfo);
163923 sqlite3DbFree(db, pIdxInfo);
163924 }
163925
163926 /*
163927 ** The table object reference passed as the second argument to this function
@@ -164664,11 +165269,11 @@
165269 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
165270 ){
165271 Expr *pRight = pTerm->pExpr->pRight;
165272 int k = 0;
165273 testcase( pTerm->pExpr->op==TK_IS );
165274 if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
165275 k = 10;
165276 }else{
165277 k = 20;
165278 }
165279 if( iReduce<k ){
@@ -164961,11 +165566,11 @@
165566 assert( saved_nEq==pNew->u.btree.nEq );
165567 if( iCol==XN_ROWID
165568 || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
165569 ){
165570 if( iCol==XN_ROWID || pProbe->uniqNotNull
165571 || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
165572 ){
165573 pNew->wsFlags |= WHERE_ONEROW;
165574 }else{
165575 pNew->wsFlags |= WHERE_UNQ_WANTED;
165576 }
@@ -165087,14 +165692,17 @@
165692 }
165693 }
165694 }
165695 }
165696
165697 /* Set rCostIdx to the estimated cost of visiting selected rows in the
165698 ** index. The estimate is the sum of two values:
165699 ** 1. The cost of doing one search-by-key to find the first matching
165700 ** entry
165701 ** 2. Stepping forward in the index pNew->nOut times to find all
165702 ** additional matching entries.
165703 */
165704 assert( pSrc->pTab->szTabRow>0 );
165705 if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
165706 /* The pProbe->szIdxRow is low for an IPK table since the interior
165707 ** pages are small. Thus szIdxRow gives a good estimate of seek cost.
165708 ** But the leaf pages are full-size, so pProbe->szIdxRow would badly
@@ -165101,11 +165709,19 @@
165709 ** under-estimate the scanning cost. */
165710 rCostIdx = pNew->nOut + 16;
165711 }else{
165712 rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
165713 }
165714 rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
165715
165716 /* Estimate the cost of running the loop. If all data is coming
165717 ** from the index, then this is just the cost of doing the index
165718 ** lookup and scan. But if some data is coming out of the main table,
165719 ** we also have to add in the cost of doing pNew->nOut searches to
165720 ** locate the row in the main table that corresponds to the index entry.
165721 */
165722 pNew->rRun = rCostIdx;
165723 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
165724 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
165725 }
165726 ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
165727
@@ -165836,10 +166452,25 @@
166452 static int isLimitTerm(WhereTerm *pTerm){
166453 assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
166454 return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
166455 && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
166456 }
166457
166458 /*
166459 ** Return true if the first nCons constraints in the pUsage array are
166460 ** marked as in-use (have argvIndex>0). False otherwise.
166461 */
166462 static int allConstraintsUsed(
166463 struct sqlite3_index_constraint_usage *aUsage,
166464 int nCons
166465 ){
166466 int ii;
166467 for(ii=0; ii<nCons; ii++){
166468 if( aUsage[ii].argvIndex<=0 ) return 0;
166469 }
166470 return 1;
166471 }
166472
166473 /*
166474 ** Argument pIdxInfo is already populated with all constraints that may
166475 ** be used by the virtual table identified by pBuilder->pNew->iTab. This
166476 ** function marks a subset of those constraints usable, invokes the
@@ -165887,11 +166518,11 @@
166518
166519 /* Set the usable flag on the subset of constraints identified by
166520 ** arguments mUsable and mExclude. */
166521 pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
166522 for(i=0; i<nConstraint; i++, pIdxCons++){
166523 WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
166524 pIdxCons->usable = 0;
166525 if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
166526 && (pTerm->eOperator & mExclude)==0
166527 && (pbRetryLimit || !isLimitTerm(pTerm))
166528 ){
@@ -165918,10 +166549,11 @@
166549 /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
166550 ** that the particular combination of parameters provided is unusable.
166551 ** Make no entries in the loop table.
166552 */
166553 WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
166554 freeIdxStr(pIdxInfo);
166555 return SQLITE_OK;
166556 }
166557 return rc;
166558 }
166559
@@ -165935,22 +166567,21 @@
166567 if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
166568 WhereTerm *pTerm;
166569 int j = pIdxCons->iTermOffset;
166570 if( iTerm>=nConstraint
166571 || j<0
166572 || (pTerm = termFromWhereClause(pWC, j))==0
166573 || pNew->aLTerm[iTerm]!=0
166574 || pIdxCons->usable==0
166575 ){
166576 sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
166577 freeIdxStr(pIdxInfo);
166578 return SQLITE_ERROR;
166579 }
166580 testcase( iTerm==nConstraint-1 );
166581 testcase( j==0 );
166582 testcase( j==pWC->nTerm-1 );
 
166583 pNew->prereq |= pTerm->prereqRight;
166584 assert( iTerm<pNew->nLSlot );
166585 pNew->aLTerm[iTerm] = pTerm;
166586 if( iTerm>mxTerm ) mxTerm = iTerm;
166587 testcase( iTerm==15 );
@@ -165977,22 +166608,25 @@
166608 pIdxInfo->orderByConsumed = 0;
166609 pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
166610 *pbIn = 1; assert( (mExclude & WO_IN)==0 );
166611 }
166612
166613 /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
166614 ** terms. And if there are any, they should follow all other terms. */
166615 assert( pbRetryLimit || !isLimitTerm(pTerm) );
166616 assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
166617 assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
166618
166619 if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
166620 /* If there is an IN(...) term handled as an == (separate call to
166621 ** xFilter for each value on the RHS of the IN) and a LIMIT or
166622 ** OFFSET term handled as well, the plan is unusable. Similarly,
166623 ** if there is a LIMIT/OFFSET and there are other unused terms,
166624 ** the plan cannot be used. In these cases set variable *pbRetryLimit
166625 ** to true to tell the caller to retry with LIMIT and OFFSET
166626 ** disabled. */
166627 freeIdxStr(pIdxInfo);
 
 
166628 *pbRetryLimit = 1;
166629 return SQLITE_OK;
166630 }
166631 }
166632 }
@@ -166001,11 +166635,11 @@
166635 for(i=0; i<=mxTerm; i++){
166636 if( pNew->aLTerm[i]==0 ){
166637 /* The non-zero argvIdx values must be contiguous. Raise an
166638 ** error if they are not */
166639 sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
166640 freeIdxStr(pIdxInfo);
166641 return SQLITE_ERROR;
166642 }
166643 }
166644 assert( pNew->nLTerm<=pNew->nLSlot );
166645 pNew->u.vtab.idxNum = pIdxInfo->idxNum;
@@ -166056,11 +166690,11 @@
166690 HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
166691 const char *zRet = 0;
166692 if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
166693 CollSeq *pC = 0;
166694 int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
166695 Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
166696 if( pX->pLeft ){
166697 pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
166698 }
166699 zRet = (pC ? pC->zName : sqlite3StrBINARY);
166700 }
@@ -166102,11 +166736,13 @@
166736 int rc = SQLITE_OK;
166737 if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
166738 rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
166739 }else{
166740 if( pH->aRhs[iCons]==0 ){
166741 WhereTerm *pTerm = termFromWhereClause(
166742 pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
166743 );
166744 rc = sqlite3ValueFromExpr(
166745 pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
166746 SQLITE_AFF_BLOB, &pH->aRhs[iCons]
166747 );
166748 testcase( rc!=SQLITE_OK );
@@ -166258,13 +166894,12 @@
166894 while( rc==SQLITE_OK ){
166895 int i;
166896 Bitmask mNext = ALLBITS;
166897 assert( mNext>0 );
166898 for(i=0; i<nConstraint; i++){
166899 int iTerm = p->aConstraint[i].iTermOffset;
166900 Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
 
166901 if( mThis>mPrev && mThis<mNext ) mNext = mThis;
166902 }
166903 mPrev = mNext;
166904 if( mNext==ALLBITS ) break;
166905 if( mNext==mBest || mNext==mBestNoIn ) continue;
@@ -166296,11 +166931,10 @@
166931 rc = whereLoopAddVirtualOne(
166932 pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
166933 }
166934 }
166935
 
166936 freeIndexInfo(pParse->db, p);
166937 WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
166938 return rc;
166939 }
166940 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166673,11 +167307,11 @@
167307 nColumn = pIndex->nColumn;
167308 assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
167309 assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
167310 || !HasRowid(pIndex->pTable));
167311 /* All relevant terms of the index must also be non-NULL in order
167312 ** for isOrderDistinct to be true. So the isOrderDistinct value
167313 ** computed here might be a false positive. Corrections will be
167314 ** made at tag-20210426-1 below */
167315 isOrderDistinct = IsUniqueIndex(pIndex)
167316 && (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
167317 }
@@ -166964,10 +167598,87 @@
167598 if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
167599 }
167600 rSortCost += estLog(nRow);
167601 return rSortCost;
167602 }
167603
167604 /*
167605 ** Compute the maximum number of paths in the solver algorithm, for
167606 ** queries that have three or more terms in the FROM clause. Queries with
167607 ** two or fewer FROM clause terms are handled by the caller.
167608 **
167609 ** Query planning is NP-hard. We must limit the number of paths at
167610 ** each step of the solver search algorithm to avoid exponential behavior.
167611 **
167612 ** The value returned is a tuning parameter. Currently the value is:
167613 **
167614 ** 18 for star queries
167615 ** 12 otherwise
167616 **
167617 ** For the purposes of SQLite, a star-query is defined as a query
167618 ** with a large central table that is joined against four or more
167619 ** smaller tables. The central table is called the "fact" table.
167620 ** The smaller tables that get joined are "dimension tables".
167621 **
167622 ** SIDE EFFECT: (and really the whole point of this subroutine)
167623 **
167624 ** If pWInfo describes a star-query, then the cost on WhereLoops for the
167625 ** fact table is reduced. This heuristic helps keep fact tables in
167626 ** outer loops. Without this heuristic, paths with fact tables in outer
167627 ** loops tend to get pruned by the mxChoice limit on the number of paths,
167628 ** resulting in poor query plans. The total amount of heuristic cost
167629 ** adjustment is stored in pWInfo->nOutStarDelta and the cost adjustment
167630 ** for each WhereLoop is stored in its rStarDelta field.
167631 */
167632 static int computeMxChoice(WhereInfo *pWInfo, LogEst nRowEst){
167633 int nLoop = pWInfo->nLevel; /* Number of terms in the join */
167634 if( nRowEst==0 && nLoop>=5 ){
167635 /* Check to see if we are dealing with a star schema and if so, reduce
167636 ** the cost of fact tables relative to dimension tables, as a heuristic
167637 ** to help keep the fact tables in outer loops.
167638 */
167639 int iLoop; /* Counter over join terms */
167640 Bitmask m; /* Bitmask for current loop */
167641 assert( pWInfo->nOutStarDelta==0 );
167642 for(iLoop=0, m=1; iLoop<nLoop; iLoop++, m<<=1){
167643 WhereLoop *pWLoop; /* For looping over WhereLoops */
167644 int nDep = 0; /* Number of dimension tables */
167645 LogEst rDelta; /* Heuristic cost adjustment */
167646 Bitmask mSeen = 0; /* Mask of dimension tables */
167647 for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167648 if( (pWLoop->prereq & m)!=0 && (pWLoop->maskSelf & mSeen)==0 ){
167649 nDep++;
167650 mSeen |= pWLoop->maskSelf;
167651 }
167652 }
167653 if( nDep<=3 ) continue;
167654 rDelta = 15*(nDep-3);
167655 #ifdef WHERETRACE_ENABLED /* 0x4 */
167656 if( sqlite3WhereTrace&0x4 ){
167657 SrcItem *pItem = pWInfo->pTabList->a + iLoop;
167658 sqlite3DebugPrintf("Fact-table %s: %d dimensions, cost reduced %d\n",
167659 pItem->zAlias ? pItem->zAlias : pItem->pTab->zName,
167660 nDep, rDelta);
167661 }
167662 #endif
167663 if( pWInfo->nOutStarDelta==0 ){
167664 for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167665 pWLoop->rStarDelta = 0;
167666 }
167667 }
167668 pWInfo->nOutStarDelta += rDelta;
167669 for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
167670 if( pWLoop->maskSelf==m ){
167671 pWLoop->rRun -= rDelta;
167672 pWLoop->nOut -= rDelta;
167673 pWLoop->rStarDelta = rDelta;
167674 }
167675 }
167676 }
167677 }
167678 return pWInfo->nOutStarDelta>0 ? 18 : 12;
167679 }
167680
167681 /*
167682 ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
167683 ** attempts to find the lowest cost path that visits each WhereLoop
167684 ** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -167000,17 +167711,29 @@
167711 char *pSpace; /* Temporary memory used by this routine */
167712 int nSpace; /* Bytes of space allocated at pSpace */
167713
167714 pParse = pWInfo->pParse;
167715 nLoop = pWInfo->nLevel;
 
 
 
 
 
167716 WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
167717 nRowEst, pParse->nQueryLoop));
167718 /* TUNING: mxChoice is the maximum number of possible paths to preserve
167719 ** at each step. Based on the number of loops in the FROM clause:
167720 **
167721 ** nLoop mxChoice
167722 ** ----- --------
167723 ** 1 1 // the most common case
167724 ** 2 5
167725 ** 3+ 12 or 18 // see computeMxChoice()
167726 */
167727 if( nLoop<=1 ){
167728 mxChoice = 1;
167729 }else if( nLoop==2 ){
167730 mxChoice = 5;
167731 }else{
167732 mxChoice = computeMxChoice(pWInfo, nRowEst);
167733 }
167734 assert( nLoop<=pWInfo->pTabList->nSrc );
167735
167736 /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
167737 ** case the purpose of this call is to estimate the number of rows returned
167738 ** by the overall query. Once this estimate has been obtained, the caller
167739 ** will invoke this function a second time, passing the estimate as the
@@ -167089,11 +167812,14 @@
167812 continue;
167813 }
167814
167815 /* At this point, pWLoop is a candidate to be the next loop.
167816 ** Compute its cost */
167817 rUnsorted = pWLoop->rRun + pFrom->nRow;
167818 if( pWLoop->rSetup ){
167819 rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup, rUnsorted);
167820 }
167821 rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
167822 nOut = pFrom->nRow + pWLoop->nOut;
167823 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
167824 isOrdered = pFrom->isOrdered;
167825 if( isOrdered<0 ){
@@ -167134,10 +167860,11 @@
167860 **
167861 ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
167862 ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
167863 ** of legal values for isOrdered, -1..64.
167864 */
167865 testcase( nTo==0 );
167866 for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
167867 if( pTo->maskLoop==maskNew
167868 && ((pTo->isOrdered^isOrdered)&0x80)==0
167869 ){
167870 testcase( jj==nTo-1 );
@@ -167250,20 +167977,32 @@
167977 }
167978 }
167979
167980 #ifdef WHERETRACE_ENABLED /* >=2 */
167981 if( sqlite3WhereTrace & 0x02 ){
167982 LogEst rMin, rFloor = 0;
167983 int nDone = 0;
167984 sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
167985 while( nDone<nTo ){
167986 rMin = 0x7fff;
167987 for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167988 if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost;
167989 }
167990 for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
167991 if( pTo->rCost==rMin ){
167992 sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
167993 wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
167994 pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
167995 if( pTo->isOrdered>0 ){
167996 sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
167997 }else{
167998 sqlite3DebugPrintf("\n");
167999 }
168000 nDone++;
168001 }
168002 }
168003 rFloor = rMin;
168004 }
168005 }
168006 #endif
168007
168008 /* Swap the roles of aFrom and aTo for the next generation */
@@ -167354,17 +168093,93 @@
168093 pWInfo->revMask = revMask;
168094 }
168095 }
168096 }
168097
168098 pWInfo->nRowOut = pFrom->nRow + pWInfo->nOutStarDelta;
 
168099
168100 /* Free temporary memory and return success */
168101 sqlite3StackFreeNN(pParse->db, pSpace);
168102 return SQLITE_OK;
168103 }
168104
168105 /*
168106 ** This routine implements a heuristic designed to improve query planning.
168107 ** This routine is called in between the first and second call to
168108 ** wherePathSolver(). Hence the name "Interstage" "Heuristic".
168109 **
168110 ** The first call to wherePathSolver() (hereafter just "solver()") computes
168111 ** the best path without regard to the order of the outputs. The second call
168112 ** to the solver() builds upon the first call to try to find an alternative
168113 ** path that satisfies the ORDER BY clause.
168114 **
168115 ** This routine looks at the results of the first solver() run, and for
168116 ** every FROM clause term in the resulting query plan that uses an equality
168117 ** constraint against an index, disable other WhereLoops for that same
168118 ** FROM clause term that would try to do a full-table scan. This prevents
168119 ** an index search from being converted into a full-table scan in order to
168120 ** satisfy an ORDER BY clause, since even though we might get slightly better
168121 ** performance using the full-scan without sorting if the output size
168122 ** estimates are very precise, we might also get severe performance
168123 ** degradation using the full-scan if the output size estimate is too large.
168124 ** It is better to err on the side of caution.
168125 **
168126 ** Except, if the first solver() call generated a full-table scan in an outer
168127 ** loop then stop this analysis at the first full-scan, since the second
168128 ** solver() run might try to swap that full-scan for another in order to
168129 ** get the output into the correct order. In other words, we allow a
168130 ** rewrite like this:
168131 **
168132 ** First Solver() Second Solver()
168133 ** |-- SCAN t1 |-- SCAN t2
168134 ** |-- SEARCH t2 `-- SEARCH t1
168135 ** `-- SORT USING B-TREE
168136 **
168137 ** The purpose of this routine is to disallow rewrites such as:
168138 **
168139 ** First Solver() Second Solver()
168140 ** |-- SEARCH t1 |-- SCAN t2 <--- bad!
168141 ** |-- SEARCH t2 `-- SEARCH t1
168142 ** `-- SORT USING B-TREE
168143 **
168144 ** See test cases in test/whereN.test for the real-world query that
168145 ** originally provoked this heuristic.
168146 */
168147 static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
168148 int i;
168149 #ifdef WHERETRACE_ENABLED
168150 int once = 0;
168151 #endif
168152 for(i=0; i<pWInfo->nLevel; i++){
168153 WhereLoop *p = pWInfo->a[i].pWLoop;
168154 if( p==0 ) break;
168155 if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
168156 if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
168157 u8 iTab = p->iTab;
168158 WhereLoop *pLoop;
168159 for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
168160 if( pLoop->iTab!=iTab ) continue;
168161 if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
168162 /* Auto-index and index-constrained loops allowed to remain */
168163 continue;
168164 }
168165 #ifdef WHERETRACE_ENABLED
168166 if( sqlite3WhereTrace & 0x80 ){
168167 if( once==0 ){
168168 sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n");
168169 once = 1;
168170 }
168171 sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC);
168172 }
168173 #endif /* WHERETRACE_ENABLED */
168174 pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */
168175 }
168176 }else{
168177 break;
168178 }
168179 }
168180 }
168181
168182 /*
168183 ** Most queries use only a single table (they are not joins) and have
168184 ** simple == constraints against indexed fields. This routine attempts
168185 ** to plan those simple cases using much less ceremony than the
@@ -167530,10 +168345,14 @@
168345 ** might move from the right side to the left side of the RIGHT JOIN.
168346 ** Note: Due to (2), this condition can only arise if the table is
168347 ** the right-most table of a subquery that was flattened into the
168348 ** main query and that subquery was the right-hand operand of an
168349 ** inner join that held an ON or USING clause.
168350 ** 6) The ORDER BY clause has 63 or fewer terms
168351 ** 7) The omit-noop-join optimization is enabled.
168352 **
168353 ** Items (1), (6), and (7) are checked by the caller.
168354 **
168355 ** For example, given:
168356 **
168357 ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
168358 ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
@@ -167668,12 +168487,65 @@
168487 pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
168488 (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
168489 }
168490 }
168491 nSearch += pLoop->nOut;
168492 if( pWInfo->nOutStarDelta ) nSearch += pLoop->rStarDelta;
168493 }
168494 }
168495
168496 /*
168497 ** Expression Node callback for sqlite3ExprCanReturnSubtype().
168498 **
168499 ** Only a function call is able to return a subtype. So if the node
168500 ** is not a function call, return WRC_Prune immediately.
168501 **
168502 ** A function call is able to return a subtype if it has the
168503 ** SQLITE_RESULT_SUBTYPE property.
168504 **
168505 ** Assume that every function is able to pass-through a subtype from
168506 ** one of its argument (using sqlite3_result_value()). Most functions
168507 ** are not this way, but we don't have a mechanism to distinguish those
168508 ** that are from those that are not, so assume they all work this way.
168509 ** That means that if one of its arguments is another function and that
168510 ** other function is able to return a subtype, then this function is
168511 ** able to return a subtype.
168512 */
168513 static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
168514 int n;
168515 FuncDef *pDef;
168516 sqlite3 *db;
168517 if( pExpr->op!=TK_FUNCTION ){
168518 return WRC_Prune;
168519 }
168520 assert( ExprUseXList(pExpr) );
168521 db = pWalker->pParse->db;
168522 n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
168523 pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
168524 if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
168525 pWalker->eCode = 1;
168526 return WRC_Prune;
168527 }
168528 return WRC_Continue;
168529 }
168530
168531 /*
168532 ** Return TRUE if expression pExpr is able to return a subtype.
168533 **
168534 ** A TRUE return does not guarantee that a subtype will be returned.
168535 ** It only indicates that a subtype return is possible. False positives
168536 ** are acceptable as they only disable an optimization. False negatives,
168537 ** on the other hand, can lead to incorrect answers.
168538 */
168539 static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
168540 Walker w;
168541 memset(&w, 0, sizeof(w));
168542 w.pParse = pParse;
168543 w.xExprCallback = exprNodeCanReturnSubtype;
168544 sqlite3WalkExpr(&w, pExpr);
168545 return w.eCode;
168546 }
168547
168548 /*
168549 ** The index pIdx is used by a query and contains one or more expressions.
168550 ** In other words pIdx is an index on an expression. iIdxCur is the cursor
168551 ** number for the index and iDataCur is the cursor number for the corresponding
@@ -167696,37 +168568,23 @@
168568 assert( pIdx->bHasExpr );
168569 pTab = pIdx->pTable;
168570 for(i=0; i<pIdx->nColumn; i++){
168571 Expr *pExpr;
168572 int j = pIdx->aiColumn[i];
 
168573 if( j==XN_EXPR ){
168574 pExpr = pIdx->aColExpr->a[i].pExpr;
 
 
 
 
168575 }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
168576 pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
 
168577 }else{
168578 continue;
168579 }
168580 if( sqlite3ExprIsConstant(0,pExpr) ) continue;
168581 if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
168582 /* Functions that might set a subtype should not be replaced by the
168583 ** value taken from an expression index since the index omits the
168584 ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
168585 continue;
 
 
 
 
 
 
 
 
168586 }
168587 p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
168588 if( p==0 ) break;
168589 p->pIENext = pParse->pIdxEpr;
168590 #ifdef WHERETRACE_ENABLED
@@ -167737,11 +168595,11 @@
168595 #endif
168596 p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
168597 p->iDataCur = pTabItem->iCursor;
168598 p->iIdxCur = iIdxCur;
168599 p->iIdxCol = i;
168600 p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
168601 if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
168602 p->aff = pIdx->zColAff[i];
168603 }
168604 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
168605 p->zIdxName = pIdx->zName;
@@ -167905,10 +168763,11 @@
168763 /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
168764 testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
168765 if( pOrderBy && pOrderBy->nExpr>=BMS ){
168766 pOrderBy = 0;
168767 wctrlFlags &= ~WHERE_WANT_DISTINCT;
168768 wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */
168769 }
168770
168771 /* The number of tables in the FROM clause is limited by the number of
168772 ** bits in a Bitmask
168773 */
@@ -168144,11 +169003,12 @@
169003 WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
169004
169005 wherePathSolver(pWInfo, 0);
169006 if( db->mallocFailed ) goto whereBeginError;
169007 if( pWInfo->pOrderBy ){
169008 whereInterstageHeuristic(pWInfo);
169009 wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1);
169010 if( db->mallocFailed ) goto whereBeginError;
169011 }
169012
169013 /* TUNING: Assume that a DISTINCT clause on a subquery reduces
169014 ** the output size by a factor of 8 (LogEst -30).
@@ -168204,14 +169064,14 @@
169064 ** some C-compiler optimizers from in-lining the
169065 ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to
169066 ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
169067 */
169068 notReady = ~(Bitmask)0;
169069 if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */
169070 && pResultSet!=0 /* Condition (1) */
169071 && 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */
169072 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */
169073 ){
169074 notReady = whereOmitNoopJoin(pWInfo, notReady);
169075 nTabList = pWInfo->nLevel;
169076 assert( nTabList>0 );
169077 }
@@ -168693,11 +169553,19 @@
169553 if( pLevel->iLeftJoin ){
169554 int ws = pLoop->wsFlags;
169555 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
169556 assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
169557 if( (ws & WHERE_IDX_ONLY)==0 ){
169558 SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
169559 assert( pLevel->iTabCur==pSrc->iCursor );
169560 if( pSrc->fg.viaCoroutine ){
169561 int m, n;
169562 n = pSrc->regResult;
169563 assert( pSrc->pTab!=0 );
169564 m = pSrc->pTab->nCol;
169565 sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
169566 }
169567 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
169568 }
169569 if( (ws & WHERE_INDEXED)
169570 || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx)
169571 ){
@@ -169793,11 +170661,11 @@
170661 }
170662 if( bIntToNull ){
170663 int iDummy;
170664 Expr *pSub;
170665 pSub = sqlite3ExprSkipCollateAndLikely(pDup);
170666 if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
170667 pSub->op = TK_NULL;
170668 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
170669 pSub->u.zToken = 0;
170670 }
170671 }
@@ -172270,139 +173138,139 @@
173138 #define TK_EACH 41
173139 #define TK_FAIL 42
173140 #define TK_OR 43
173141 #define TK_AND 44
173142 #define TK_IS 45
173143 #define TK_ISNOT 46
173144 #define TK_MATCH 47
173145 #define TK_LIKE_KW 48
173146 #define TK_BETWEEN 49
173147 #define TK_IN 50
173148 #define TK_ISNULL 51
173149 #define TK_NOTNULL 52
173150 #define TK_NE 53
173151 #define TK_EQ 54
173152 #define TK_GT 55
173153 #define TK_LE 56
173154 #define TK_LT 57
173155 #define TK_GE 58
173156 #define TK_ESCAPE 59
173157 #define TK_ID 60
173158 #define TK_COLUMNKW 61
173159 #define TK_DO 62
173160 #define TK_FOR 63
173161 #define TK_IGNORE 64
173162 #define TK_INITIALLY 65
173163 #define TK_INSTEAD 66
173164 #define TK_NO 67
173165 #define TK_KEY 68
173166 #define TK_OF 69
173167 #define TK_OFFSET 70
173168 #define TK_PRAGMA 71
173169 #define TK_RAISE 72
173170 #define TK_RECURSIVE 73
173171 #define TK_REPLACE 74
173172 #define TK_RESTRICT 75
173173 #define TK_ROW 76
173174 #define TK_ROWS 77
173175 #define TK_TRIGGER 78
173176 #define TK_VACUUM 79
173177 #define TK_VIEW 80
173178 #define TK_VIRTUAL 81
173179 #define TK_WITH 82
173180 #define TK_NULLS 83
173181 #define TK_FIRST 84
173182 #define TK_LAST 85
173183 #define TK_CURRENT 86
173184 #define TK_FOLLOWING 87
173185 #define TK_PARTITION 88
173186 #define TK_PRECEDING 89
173187 #define TK_RANGE 90
173188 #define TK_UNBOUNDED 91
173189 #define TK_EXCLUDE 92
173190 #define TK_GROUPS 93
173191 #define TK_OTHERS 94
173192 #define TK_TIES 95
173193 #define TK_GENERATED 96
173194 #define TK_ALWAYS 97
173195 #define TK_MATERIALIZED 98
173196 #define TK_REINDEX 99
173197 #define TK_RENAME 100
173198 #define TK_CTIME_KW 101
173199 #define TK_ANY 102
173200 #define TK_BITAND 103
173201 #define TK_BITOR 104
173202 #define TK_LSHIFT 105
173203 #define TK_RSHIFT 106
173204 #define TK_PLUS 107
173205 #define TK_MINUS 108
173206 #define TK_STAR 109
173207 #define TK_SLASH 110
173208 #define TK_REM 111
173209 #define TK_CONCAT 112
173210 #define TK_PTR 113
173211 #define TK_COLLATE 114
173212 #define TK_BITNOT 115
173213 #define TK_ON 116
173214 #define TK_INDEXED 117
173215 #define TK_STRING 118
173216 #define TK_JOIN_KW 119
173217 #define TK_CONSTRAINT 120
173218 #define TK_DEFAULT 121
173219 #define TK_NULL 122
173220 #define TK_PRIMARY 123
173221 #define TK_UNIQUE 124
173222 #define TK_CHECK 125
173223 #define TK_REFERENCES 126
173224 #define TK_AUTOINCR 127
173225 #define TK_INSERT 128
173226 #define TK_DELETE 129
173227 #define TK_UPDATE 130
173228 #define TK_SET 131
173229 #define TK_DEFERRABLE 132
173230 #define TK_FOREIGN 133
173231 #define TK_DROP 134
173232 #define TK_UNION 135
173233 #define TK_ALL 136
173234 #define TK_EXCEPT 137
173235 #define TK_INTERSECT 138
173236 #define TK_SELECT 139
173237 #define TK_VALUES 140
173238 #define TK_DISTINCT 141
173239 #define TK_DOT 142
173240 #define TK_FROM 143
173241 #define TK_JOIN 144
173242 #define TK_USING 145
173243 #define TK_ORDER 146
173244 #define TK_GROUP 147
173245 #define TK_HAVING 148
173246 #define TK_LIMIT 149
173247 #define TK_WHERE 150
173248 #define TK_RETURNING 151
173249 #define TK_INTO 152
173250 #define TK_NOTHING 153
173251 #define TK_FLOAT 154
173252 #define TK_BLOB 155
173253 #define TK_INTEGER 156
173254 #define TK_VARIABLE 157
173255 #define TK_CASE 158
173256 #define TK_WHEN 159
173257 #define TK_THEN 160
173258 #define TK_ELSE 161
173259 #define TK_INDEX 162
173260 #define TK_ALTER 163
173261 #define TK_ADD 164
173262 #define TK_WINDOW 165
173263 #define TK_OVER 166
173264 #define TK_FILTER 167
173265 #define TK_COLUMN 168
173266 #define TK_AGG_FUNCTION 169
173267 #define TK_AGG_COLUMN 170
173268 #define TK_TRUEFALSE 171
173269 #define TK_FUNCTION 172
173270 #define TK_UPLUS 173
173271 #define TK_UMINUS 174
173272 #define TK_TRUTH 175
173273 #define TK_REGISTER 176
173274 #define TK_VECTOR 177
173275 #define TK_SELECT_COLUMN 178
173276 #define TK_IF_NULL_ROW 179
@@ -172476,11 +173344,11 @@
173344 #endif
173345 /************* Begin control #defines *****************************************/
173346 #define YYCODETYPE unsigned short int
173347 #define YYNOCODE 322
173348 #define YYACTIONTYPE unsigned short int
173349 #define YYWILDCARD 102
173350 #define sqlite3ParserTOKENTYPE Token
173351 typedef union {
173352 int yyinit;
173353 sqlite3ParserTOKENTYPE yy0;
173354 ExprList* yy14;
@@ -172613,450 +173481,456 @@
173481 ** yy_reduce_ofst[] For each state, the offset into yy_action for
173482 ** shifting non-terminals after a reduce.
173483 ** yy_default[] Default action for each state.
173484 **
173485 *********** Begin parsing tables **********************************************/
173486 #define YY_ACTTAB_COUNT (2207)
173487 static const YYACTIONTYPE yy_action[] = {
173488 /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289,
173489 /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413,
173490 /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82,
173491 /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984,
173492 /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063,
173493 /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413,
173494 /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130,
173495 /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290,
173496 /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063,
173497 /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296,
173498 /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132,
173499 /* 110 */ 132, 132, 131, 128, 451, 44, 1050, 1050, 1064, 1067,
173500 /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174,
173501 /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 498, 1341,
173502 /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132,
173503 /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 1105, 1228,
173504 /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136,
173505 /* 170 */ 136, 1204, 320, 567, 288, 288, 283, 288, 288, 523,
173506 /* 180 */ 523, 1250, 139, 1541, 7, 214, 503, 573, 1169, 562,
173507 /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 401, 547,
173508 /* 200 */ 487, 1169, 245, 1568, 1169, 245, 133, 133, 132, 132,
173509 /* 210 */ 132, 131, 128, 451, 261, 134, 134, 134, 134, 133,
173510 /* 220 */ 133, 132, 132, 132, 131, 128, 451, 451, 1204, 1205,
173511 /* 230 */ 1204, 130, 127, 234, 455, 413, 182, 455, 130, 127,
173512 /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132,
173513 /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 576, 137,
173514 /* 260 */ 138, 91, 261, 1228, 1228, 1063, 1066, 1053, 1053, 135,
173515 /* 270 */ 135, 136, 136, 136, 136, 44, 472, 346, 1204, 472,
173516 /* 280 */ 346, 51, 51, 418, 93, 157, 134, 134, 134, 134,
173517 /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 166, 363,
173518 /* 300 */ 298, 134, 134, 134, 134, 133, 133, 132, 132, 132,
173519 /* 310 */ 131, 128, 451, 1293, 461, 1570, 423, 377, 275, 134,
173520 /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128,
173521 /* 330 */ 451, 418, 320, 567, 1292, 1204, 1205, 1204, 257, 413,
173522 /* 340 */ 483, 511, 508, 507, 94, 132, 132, 132, 131, 128,
173523 /* 350 */ 451, 506, 1204, 548, 548, 388, 576, 384, 7, 413,
173524 /* 360 */ 550, 229, 522, 137, 138, 91, 530, 1228, 1228, 1063,
173525 /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 51,
173526 /* 380 */ 51, 1582, 380, 137, 138, 91, 331, 1228, 1228, 1063,
173527 /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 320,
173528 /* 400 */ 567, 288, 288, 320, 567, 1602, 582, 2, 1259, 1204,
173529 /* 410 */ 1205, 1204, 1628, 321, 573, 155, 562, 576, 1511, 264,
173530 /* 420 */ 231, 520, 1341, 134, 134, 134, 134, 133, 133, 132,
173531 /* 430 */ 132, 132, 131, 128, 451, 519, 1511, 1513, 1333, 1333,
173532 /* 440 */ 82, 82, 498, 134, 134, 134, 134, 133, 133, 132,
173533 /* 450 */ 132, 132, 131, 128, 451, 1435, 257, 288, 288, 511,
173534 /* 460 */ 508, 507, 944, 1568, 413, 1019, 1204, 943, 360, 506,
173535 /* 470 */ 573, 1598, 562, 44, 575, 551, 551, 557, 1107, 1582,
173536 /* 480 */ 544, 576, 1107, 40, 417, 245, 531, 1505, 137, 138,
173537 /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
173538 /* 500 */ 136, 136, 136, 136, 81, 81, 1281, 1204, 413, 553,
173539 /* 510 */ 1511, 48, 512, 448, 447, 493, 578, 455, 578, 344,
173540 /* 520 */ 45, 1204, 1233, 1204, 1205, 1204, 428, 1235, 158, 882,
173541 /* 530 */ 320, 567, 137, 138, 91, 1234, 1228, 1228, 1063, 1066,
173542 /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134,
173543 /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
173544 /* 560 */ 1236, 576, 1236, 329, 1204, 1205, 1204, 387, 492, 403,
173545 /* 570 */ 1040, 382, 489, 123, 568, 1569, 4, 377, 1204, 1205,
173546 /* 580 */ 1204, 570, 570, 570, 82, 82, 882, 1029, 1331, 1331,
173547 /* 590 */ 571, 1028, 134, 134, 134, 134, 133, 133, 132, 132,
173548 /* 600 */ 132, 131, 128, 451, 288, 288, 1281, 1204, 576, 423,
173549 /* 610 */ 576, 1568, 413, 423, 452, 378, 886, 573, 1279, 562,
173550 /* 620 */ 46, 557, 532, 1028, 1028, 1030, 565, 130, 127, 234,
173551 /* 630 */ 556, 82, 82, 82, 82, 479, 137, 138, 91, 462,
173552 /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173553 /* 650 */ 136, 136, 1188, 487, 1506, 1040, 413, 6, 1204, 50,
173554 /* 660 */ 879, 121, 121, 948, 1204, 1205, 1204, 358, 557, 122,
173555 /* 670 */ 316, 452, 577, 452, 535, 1204, 1028, 439, 303, 212,
173556 /* 680 */ 137, 138, 91, 213, 1228, 1228, 1063, 1066, 1053, 1053,
173557 /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134,
173558 /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028,
173559 /* 710 */ 1030, 1031, 35, 288, 288, 1204, 1205, 1204, 1040, 1339,
173560 /* 720 */ 533, 123, 568, 1569, 4, 377, 573, 1019, 562, 353,
173561 /* 730 */ 1277, 356, 1204, 1205, 1204, 1029, 488, 1188, 571, 1028,
173562 /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173563 /* 750 */ 128, 451, 576, 343, 288, 288, 449, 449, 449, 971,
173564 /* 760 */ 413, 1627, 452, 911, 1187, 288, 288, 573, 464, 562,
173565 /* 770 */ 238, 1028, 1028, 1030, 565, 82, 82, 498, 573, 411,
173566 /* 780 */ 562, 344, 467, 332, 137, 138, 91, 197, 1228, 1228,
173567 /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173568 /* 800 */ 1188, 528, 1169, 1040, 413, 1110, 1110, 495, 1041, 121,
173569 /* 810 */ 121, 1204, 317, 540, 862, 1169, 1244, 122, 1169, 452,
173570 /* 820 */ 577, 452, 1340, 198, 1028, 1204, 481, 526, 137, 138,
173571 /* 830 */ 91, 560, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
173572 /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133,
173573 /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031,
173574 /* 860 */ 35, 1204, 288, 288, 1204, 477, 288, 288, 1204, 1205,
173575 /* 870 */ 1204, 539, 481, 437, 470, 573, 1451, 562, 364, 573,
173576 /* 880 */ 1153, 562, 1204, 1205, 1204, 1188, 5, 576, 134, 134,
173577 /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
173578 /* 900 */ 221, 214, 302, 96, 1149, 1657, 232, 1657, 413, 392,
173579 /* 910 */ 19, 19, 1024, 949, 406, 373, 1595, 1085, 1204, 1205,
173580 /* 920 */ 1204, 1204, 1205, 1204, 1204, 426, 1149, 1658, 413, 1658,
173581 /* 930 */ 1659, 399, 137, 138, 91, 3, 1228, 1228, 1063, 1066,
173582 /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 304, 1311,
173583 /* 950 */ 514, 1204, 137, 138, 91, 1498, 1228, 1228, 1063, 1066,
173584 /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 131,
173585 /* 970 */ 128, 451, 375, 1204, 274, 291, 372, 517, 367, 516,
173586 /* 980 */ 262, 1204, 1205, 1204, 1147, 227, 363, 448, 447, 1435,
173587 /* 990 */ 1568, 1310, 134, 134, 134, 134, 133, 133, 132, 132,
173588 /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 487, 1204, 1205,
173589 /* 1010 */ 1204, 442, 134, 134, 134, 134, 133, 133, 132, 132,
173590 /* 1020 */ 132, 131, 128, 451, 386, 576, 485, 576, 19, 19,
173591 /* 1030 */ 1204, 1205, 1204, 1345, 1236, 970, 1236, 574, 47, 936,
173592 /* 1040 */ 936, 473, 413, 431, 1552, 573, 1125, 562, 19, 19,
173593 /* 1050 */ 19, 19, 49, 336, 850, 851, 852, 111, 1368, 315,
173594 /* 1060 */ 429, 576, 413, 433, 341, 306, 137, 138, 91, 115,
173595 /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173596 /* 1080 */ 136, 136, 576, 1309, 82, 82, 137, 138, 91, 529,
173597 /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
173598 /* 1100 */ 136, 136, 1569, 222, 377, 19, 19, 305, 1126, 1169,
173599 /* 1110 */ 398, 1148, 22, 22, 498, 333, 1569, 335, 377, 576,
173600 /* 1120 */ 438, 445, 1169, 1127, 486, 1169, 134, 134, 134, 134,
173601 /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576,
173602 /* 1140 */ 902, 576, 145, 145, 6, 576, 134, 134, 134, 134,
173603 /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 214, 1336,
173604 /* 1160 */ 922, 576, 19, 19, 19, 19, 1282, 419, 19, 19,
173605 /* 1170 */ 923, 412, 515, 141, 576, 1169, 413, 206, 465, 207,
173606 /* 1180 */ 903, 215, 1575, 552, 147, 147, 7, 227, 1169, 411,
173607 /* 1190 */ 1250, 1169, 120, 307, 117, 307, 413, 66, 66, 334,
173608 /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053,
173609 /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 285, 209, 969,
173610 /* 1220 */ 137, 138, 91, 471, 1228, 1228, 1063, 1066, 1053, 1053,
173611 /* 1230 */ 135, 135, 136, 136, 136, 136, 435, 10, 1450, 267,
173612 /* 1240 */ 137, 126, 91, 1435, 1228, 1228, 1063, 1066, 1053, 1053,
173613 /* 1250 */ 135, 135, 136, 136, 136, 136, 1435, 1435, 410, 409,
173614 /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173615 /* 1270 */ 128, 451, 576, 969, 576, 1224, 498, 373, 1595, 1554,
173616 /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173617 /* 1290 */ 128, 451, 532, 457, 576, 82, 82, 82, 82, 111,
173618 /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
173619 /* 1310 */ 128, 451, 109, 233, 430, 1576, 546, 67, 67, 7,
173620 /* 1320 */ 413, 351, 550, 1550, 260, 259, 258, 494, 443, 569,
173621 /* 1330 */ 419, 983, 446, 1224, 450, 545, 1207, 576, 969, 984,
173622 /* 1340 */ 413, 475, 1449, 1574, 1180, 138, 91, 7, 1228, 1228,
173623 /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173624 /* 1360 */ 21, 21, 267, 576, 300, 1126, 91, 233, 1228, 1228,
173625 /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
173626 /* 1380 */ 1127, 373, 1595, 161, 1573, 16, 53, 53, 7, 108,
173627 /* 1390 */ 533, 38, 969, 125, 1207, 1128, 1180, 576, 1224, 123,
173628 /* 1400 */ 568, 893, 4, 324, 134, 134, 134, 134, 133, 133,
173629 /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 576,
173630 /* 1420 */ 68, 68, 576, 39, 134, 134, 134, 134, 133, 133,
173631 /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 160, 1571, 1223,
173632 /* 1440 */ 452, 576, 54, 54, 576, 69, 69, 576, 1366, 576,
173633 /* 1450 */ 420, 184, 565, 463, 297, 576, 1224, 463, 297, 70,
173634 /* 1460 */ 70, 576, 44, 474, 71, 71, 576, 72, 72, 576,
173635 /* 1470 */ 73, 73, 55, 55, 411, 874, 242, 576, 56, 56,
173636 /* 1480 */ 576, 1040, 576, 478, 57, 57, 576, 121, 121, 59,
173637 /* 1490 */ 59, 23, 60, 60, 411, 122, 319, 452, 577, 452,
173638 /* 1500 */ 74, 74, 1028, 75, 75, 76, 76, 411, 290, 20,
173639 /* 1510 */ 20, 108, 287, 231, 553, 123, 568, 325, 4, 320,
173640 /* 1520 */ 567, 97, 218, 944, 1144, 328, 400, 576, 943, 576,
173641 /* 1530 */ 1380, 424, 571, 874, 1028, 1028, 1030, 1031, 35, 293,
173642 /* 1540 */ 534, 576, 1104, 576, 1104, 9, 576, 342, 576, 111,
173643 /* 1550 */ 77, 77, 143, 143, 576, 205, 452, 222, 1379, 889,
173644 /* 1560 */ 576, 901, 900, 1188, 144, 144, 78, 78, 565, 62,
173645 /* 1570 */ 62, 79, 79, 323, 1021, 576, 266, 63, 63, 908,
173646 /* 1580 */ 909, 1589, 542, 80, 80, 576, 371, 541, 123, 568,
173647 /* 1590 */ 480, 4, 266, 482, 244, 266, 370, 1040, 64, 64,
173648 /* 1600 */ 576, 466, 576, 121, 121, 571, 1557, 576, 170, 170,
173649 /* 1610 */ 576, 122, 576, 452, 577, 452, 576, 889, 1028, 576,
173650 /* 1620 */ 165, 576, 111, 171, 171, 87, 87, 337, 1616, 452,
173651 /* 1630 */ 65, 65, 1530, 83, 83, 146, 146, 986, 987, 84,
173652 /* 1640 */ 84, 565, 168, 168, 148, 148, 1092, 347, 1032, 111,
173653 /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 1103, 576, 1103, 576,
173654 /* 1660 */ 543, 123, 568, 504, 4, 263, 576, 361, 1529, 111,
173655 /* 1670 */ 1040, 1088, 576, 263, 576, 490, 121, 121, 571, 1188,
173656 /* 1680 */ 142, 142, 169, 169, 122, 576, 452, 577, 452, 162,
173657 /* 1690 */ 162, 1028, 576, 563, 576, 152, 152, 151, 151, 348,
173658 /* 1700 */ 1376, 974, 452, 266, 1092, 942, 1032, 125, 149, 149,
173659 /* 1710 */ 939, 576, 125, 576, 565, 150, 150, 86, 86, 872,
173660 /* 1720 */ 352, 159, 576, 1028, 1028, 1030, 1031, 35, 542, 941,
173661 /* 1730 */ 576, 125, 355, 541, 88, 88, 85, 85, 357, 359,
173662 /* 1740 */ 1324, 1308, 366, 1040, 376, 52, 52, 499, 1389, 121,
173663 /* 1750 */ 121, 1434, 1188, 58, 58, 1362, 1374, 122, 1439, 452,
173664 /* 1760 */ 577, 452, 1289, 167, 1028, 1280, 280, 1268, 1267, 1269,
173665 /* 1770 */ 1609, 1359, 312, 313, 12, 314, 397, 1421, 224, 1416,
173666 /* 1780 */ 295, 237, 1409, 339, 340, 1426, 301, 345, 484, 228,
173667 /* 1790 */ 1371, 1307, 1372, 1370, 1425, 404, 1028, 1028, 1030, 1031,
173668 /* 1800 */ 35, 1601, 1192, 454, 509, 369, 292, 1502, 210, 1501,
173669 /* 1810 */ 1369, 396, 396, 395, 277, 393, 211, 566, 859, 1612,
173670 /* 1820 */ 1244, 123, 568, 391, 4, 1188, 223, 270, 1549, 1547,
173671 /* 1830 */ 1241, 239, 186, 327, 422, 96, 195, 220, 571, 235,
173672 /* 1840 */ 180, 326, 188, 468, 190, 1507, 191, 192, 92, 193,
173673 /* 1850 */ 469, 95, 1422, 13, 502, 247, 1430, 109, 199, 402,
173674 /* 1860 */ 476, 405, 452, 1496, 1428, 1427, 14, 491, 251, 102,
173675 /* 1870 */ 497, 1518, 241, 281, 565, 253, 203, 354, 500, 254,
173676 /* 1880 */ 175, 1270, 407, 43, 350, 518, 1327, 436, 255, 1326,
173677 /* 1890 */ 1325, 1318, 104, 893, 1626, 229, 408, 440, 1625, 441,
173678 /* 1900 */ 240, 310, 1296, 1040, 311, 1317, 527, 1594, 1297, 121,
173679 /* 1910 */ 121, 368, 1295, 1624, 268, 269, 1580, 122, 1579, 452,
173680 /* 1920 */ 577, 452, 374, 444, 1028, 1394, 1393, 140, 553, 90,
173681 /* 1930 */ 568, 11, 4, 1483, 383, 414, 385, 110, 116, 216,
173682 /* 1940 */ 320, 567, 1350, 555, 42, 318, 571, 537, 1349, 389,
173683 /* 1950 */ 390, 579, 1198, 276, 279, 278, 1028, 1028, 1030, 1031,
173684 /* 1960 */ 35, 580, 415, 1265, 458, 1260, 416, 185, 1534, 172,
173685 /* 1970 */ 452, 1535, 173, 156, 308, 846, 1533, 1532, 453, 217,
173686 /* 1980 */ 225, 89, 565, 174, 322, 1188, 226, 236, 1102, 154,
173687 /* 1990 */ 1100, 330, 176, 187, 1223, 189, 925, 338, 243, 1116,
173688 /* 2000 */ 246, 194, 177, 178, 425, 427, 98, 99, 196, 100,
173689 /* 2010 */ 101, 1040, 179, 1119, 248, 1115, 249, 121, 121, 24,
173690 /* 2020 */ 163, 250, 349, 1108, 266, 122, 1238, 452, 577, 452,
173691 /* 2030 */ 1192, 454, 1028, 200, 292, 496, 252, 201, 861, 396,
173692 /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256,
173693 /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239,
173694 /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326,
173695 /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309,
173696 /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155,
173697 /* 2090 */ 17, 1154, 284, 1188, 286, 978, 265, 204, 125, 1171,
173698 /* 2100 */ 241, 230, 972, 1175, 28, 1160, 29, 1179, 175, 1173,
173699 /* 2110 */ 30, 43, 31, 1178, 241, 32, 41, 549, 8, 33,
173700 /* 2120 */ 208, 111, 175, 1083, 1070, 43, 113, 1068, 240, 114,
173701 /* 2130 */ 1072, 34, 1073, 561, 1124, 118, 271, 36, 18, 1194,
173702 /* 2140 */ 1033, 873, 240, 935, 124, 37, 272, 273, 1617, 572,
173703 /* 2150 */ 183, 153, 394, 1193, 1256, 1256, 1256, 1256, 1256, 1256,
173704 /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567,
173705 /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256,
173706 /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256,
173707 /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
173708 /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458,
173709 };
173710 static const YYCODETYPE yy_lookahead[] = {
173711 /* 0 */ 276, 277, 278, 240, 241, 224, 194, 226, 194, 240,
173712 /* 10 */ 241, 194, 216, 220, 194, 234, 253, 194, 255, 19,
173713 /* 20 */ 224, 297, 253, 194, 255, 205, 212, 213, 205, 217,
173714 /* 30 */ 218, 31, 205, 194, 217, 218, 194, 217, 218, 39,
173715 /* 40 */ 217, 218, 312, 43, 44, 45, 316, 47, 48, 49,
173716 /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19,
173717 /* 60 */ 240, 241, 194, 240, 241, 194, 254, 240, 241, 276,
173718 /* 70 */ 277, 278, 233, 253, 254, 255, 253, 254, 255, 217,
173719 /* 80 */ 253, 239, 255, 43, 44, 45, 263, 47, 48, 49,
173720 /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 270,
173721 /* 100 */ 286, 22, 23, 103, 104, 105, 106, 107, 108, 109,
173722 /* 110 */ 110, 111, 112, 113, 114, 82, 47, 48, 49, 50,
173723 /* 120 */ 186, 187, 188, 189, 190, 191, 189, 87, 191, 89,
173724 /* 130 */ 196, 19, 198, 196, 317, 198, 319, 25, 194, 205,
173725 /* 140 */ 298, 270, 205, 103, 104, 105, 106, 107, 108, 109,
173726 /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 11, 47,
173727 /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
173728 /* 170 */ 58, 60, 139, 140, 240, 241, 214, 240, 241, 311,
173729 /* 180 */ 312, 102, 70, 239, 316, 194, 19, 253, 77, 255,
173730 /* 190 */ 253, 122, 255, 55, 56, 57, 58, 59, 207, 88,
173731 /* 200 */ 194, 90, 268, 194, 93, 268, 107, 108, 109, 110,
173732 /* 210 */ 111, 112, 113, 114, 47, 103, 104, 105, 106, 107,
173733 /* 220 */ 108, 109, 110, 111, 112, 113, 114, 114, 117, 118,
173734 /* 230 */ 119, 276, 277, 278, 300, 19, 194, 300, 276, 277,
173735 /* 240 */ 278, 103, 104, 105, 106, 107, 108, 109, 110, 111,
173736 /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 194, 43,
173737 /* 260 */ 44, 45, 47, 47, 48, 49, 50, 51, 52, 53,
173738 /* 270 */ 54, 55, 56, 57, 58, 82, 129, 130, 60, 129,
173739 /* 280 */ 130, 217, 218, 116, 68, 25, 103, 104, 105, 106,
173740 /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 23, 132,
173741 /* 300 */ 294, 103, 104, 105, 106, 107, 108, 109, 110, 111,
173742 /* 310 */ 112, 113, 114, 217, 121, 306, 194, 308, 26, 103,
173743 /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
173744 /* 330 */ 114, 116, 139, 140, 217, 117, 118, 119, 120, 19,
173745 /* 340 */ 194, 123, 124, 125, 24, 109, 110, 111, 112, 113,
173746 /* 350 */ 114, 133, 60, 311, 312, 250, 194, 252, 316, 19,
173747 /* 360 */ 194, 166, 167, 43, 44, 45, 205, 47, 48, 49,
173748 /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 217,
173749 /* 380 */ 218, 317, 318, 43, 44, 45, 264, 47, 48, 49,
173750 /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 139,
173751 /* 400 */ 140, 240, 241, 139, 140, 188, 189, 190, 191, 117,
173752 /* 410 */ 118, 119, 231, 196, 253, 198, 255, 194, 194, 258,
173753 /* 420 */ 259, 146, 205, 103, 104, 105, 106, 107, 108, 109,
173754 /* 430 */ 110, 111, 112, 113, 114, 109, 212, 213, 236, 237,
173755 /* 440 */ 217, 218, 194, 103, 104, 105, 106, 107, 108, 109,
173756 /* 450 */ 110, 111, 112, 113, 114, 194, 120, 240, 241, 123,
173757 /* 460 */ 124, 125, 136, 194, 19, 74, 60, 141, 23, 133,
173758 /* 470 */ 253, 194, 255, 82, 194, 309, 310, 254, 29, 317,
173759 /* 480 */ 318, 194, 33, 22, 199, 268, 263, 239, 43, 44,
173760 /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54,
173761 /* 500 */ 55, 56, 57, 58, 217, 218, 194, 60, 19, 146,
173762 /* 510 */ 286, 242, 23, 107, 108, 66, 204, 300, 206, 128,
173763 /* 520 */ 73, 60, 116, 117, 118, 119, 265, 121, 165, 60,
173764 /* 530 */ 139, 140, 43, 44, 45, 129, 47, 48, 49, 50,
173765 /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104,
173766 /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
173767 /* 560 */ 154, 194, 156, 194, 117, 118, 119, 280, 283, 205,
173768 /* 570 */ 101, 220, 287, 19, 20, 306, 22, 308, 117, 118,
173769 /* 580 */ 119, 211, 212, 213, 217, 218, 117, 118, 236, 237,
173770 /* 590 */ 36, 122, 103, 104, 105, 106, 107, 108, 109, 110,
173771 /* 600 */ 111, 112, 113, 114, 240, 241, 194, 60, 194, 194,
173772 /* 610 */ 194, 194, 19, 194, 60, 194, 23, 253, 206, 255,
173773 /* 620 */ 73, 254, 19, 154, 155, 156, 72, 276, 277, 278,
173774 /* 630 */ 263, 217, 218, 217, 218, 271, 43, 44, 45, 271,
173775 /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173776 /* 650 */ 57, 58, 183, 194, 285, 101, 19, 214, 60, 242,
173777 /* 660 */ 23, 107, 108, 109, 117, 118, 119, 16, 254, 115,
173778 /* 670 */ 254, 117, 118, 119, 194, 60, 122, 263, 205, 264,
173779 /* 680 */ 43, 44, 45, 264, 47, 48, 49, 50, 51, 52,
173780 /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106,
173781 /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155,
173782 /* 710 */ 156, 157, 158, 240, 241, 117, 118, 119, 101, 205,
173783 /* 720 */ 117, 19, 20, 306, 22, 308, 253, 74, 255, 78,
173784 /* 730 */ 205, 80, 117, 118, 119, 118, 293, 183, 36, 122,
173785 /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173786 /* 750 */ 113, 114, 194, 294, 240, 241, 211, 212, 213, 144,
173787 /* 760 */ 19, 23, 60, 25, 23, 240, 241, 253, 245, 255,
173788 /* 770 */ 15, 154, 155, 156, 72, 217, 218, 194, 253, 256,
173789 /* 780 */ 255, 128, 129, 130, 43, 44, 45, 22, 47, 48,
173790 /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173791 /* 800 */ 183, 19, 77, 101, 19, 128, 129, 130, 23, 107,
173792 /* 810 */ 108, 60, 254, 88, 21, 90, 61, 115, 93, 117,
173793 /* 820 */ 118, 119, 239, 22, 122, 60, 194, 205, 43, 44,
173794 /* 830 */ 45, 205, 47, 48, 49, 50, 51, 52, 53, 54,
173795 /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108,
173796 /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157,
173797 /* 860 */ 158, 60, 240, 241, 60, 116, 240, 241, 117, 118,
173798 /* 870 */ 119, 146, 194, 19, 81, 253, 275, 255, 24, 253,
173799 /* 880 */ 98, 255, 117, 118, 119, 183, 22, 194, 103, 104,
173800 /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
173801 /* 900 */ 151, 194, 270, 152, 22, 23, 194, 25, 19, 202,
173802 /* 910 */ 217, 218, 23, 109, 207, 314, 315, 124, 117, 118,
173803 /* 920 */ 119, 117, 118, 119, 60, 232, 22, 23, 19, 25,
173804 /* 930 */ 303, 304, 43, 44, 45, 22, 47, 48, 49, 50,
173805 /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 270, 227,
173806 /* 950 */ 96, 60, 43, 44, 45, 162, 47, 48, 49, 50,
173807 /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 112,
173808 /* 970 */ 113, 114, 194, 60, 120, 121, 122, 123, 124, 125,
173809 /* 980 */ 126, 117, 118, 119, 102, 25, 132, 107, 108, 194,
173810 /* 990 */ 194, 227, 103, 104, 105, 106, 107, 108, 109, 110,
173811 /* 1000 */ 111, 112, 113, 114, 194, 194, 102, 194, 117, 118,
173812 /* 1010 */ 119, 233, 103, 104, 105, 106, 107, 108, 109, 110,
173813 /* 1020 */ 111, 112, 113, 114, 194, 194, 19, 194, 217, 218,
173814 /* 1030 */ 117, 118, 119, 241, 154, 144, 156, 135, 242, 137,
173815 /* 1040 */ 138, 130, 19, 232, 194, 253, 23, 255, 217, 218,
173816 /* 1050 */ 217, 218, 242, 16, 7, 8, 9, 25, 261, 262,
173817 /* 1060 */ 265, 194, 19, 232, 153, 232, 43, 44, 45, 160,
173818 /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173819 /* 1080 */ 57, 58, 194, 227, 217, 218, 43, 44, 45, 194,
173820 /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
173821 /* 1100 */ 57, 58, 306, 143, 308, 217, 218, 294, 12, 77,
173822 /* 1110 */ 22, 23, 217, 218, 194, 78, 306, 80, 308, 194,
173823 /* 1120 */ 232, 254, 90, 27, 117, 93, 103, 104, 105, 106,
173824 /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 194,
173825 /* 1140 */ 35, 194, 217, 218, 214, 194, 103, 104, 105, 106,
173826 /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 194, 239,
173827 /* 1160 */ 64, 194, 217, 218, 217, 218, 209, 210, 217, 218,
173828 /* 1170 */ 74, 207, 67, 22, 194, 77, 19, 232, 245, 232,
173829 /* 1180 */ 75, 24, 312, 232, 217, 218, 316, 25, 90, 256,
173830 /* 1190 */ 102, 93, 159, 229, 161, 231, 19, 217, 218, 162,
173831 /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52,
173832 /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 23, 288, 25,
173833 /* 1220 */ 43, 44, 45, 293, 47, 48, 49, 50, 51, 52,
173834 /* 1230 */ 53, 54, 55, 56, 57, 58, 131, 22, 275, 24,
173835 /* 1240 */ 43, 44, 45, 194, 47, 48, 49, 50, 51, 52,
173836 /* 1250 */ 53, 54, 55, 56, 57, 58, 194, 194, 107, 108,
173837 /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173838 /* 1270 */ 113, 114, 194, 25, 194, 60, 194, 314, 315, 194,
173839 /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173840 /* 1290 */ 113, 114, 19, 194, 194, 217, 218, 217, 218, 25,
173841 /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
173842 /* 1310 */ 113, 114, 150, 119, 265, 312, 67, 217, 218, 316,
173843 /* 1320 */ 19, 239, 194, 194, 128, 129, 130, 265, 265, 209,
173844 /* 1330 */ 210, 31, 254, 118, 254, 86, 60, 194, 144, 39,
173845 /* 1340 */ 19, 130, 275, 312, 95, 44, 45, 316, 47, 48,
173846 /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173847 /* 1360 */ 217, 218, 24, 194, 153, 12, 45, 119, 47, 48,
173848 /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
173849 /* 1380 */ 27, 314, 315, 22, 312, 24, 217, 218, 316, 116,
173850 /* 1390 */ 117, 22, 144, 25, 118, 42, 147, 194, 60, 19,
173851 /* 1400 */ 20, 127, 22, 194, 103, 104, 105, 106, 107, 108,
173852 /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 194,
173853 /* 1420 */ 217, 218, 194, 54, 103, 104, 105, 106, 107, 108,
173854 /* 1430 */ 109, 110, 111, 112, 113, 114, 194, 22, 310, 25,
173855 /* 1440 */ 60, 194, 217, 218, 194, 217, 218, 194, 260, 194,
173856 /* 1450 */ 301, 302, 72, 262, 262, 194, 118, 266, 266, 217,
173857 /* 1460 */ 218, 194, 82, 245, 217, 218, 194, 217, 218, 194,
173858 /* 1470 */ 217, 218, 217, 218, 256, 60, 24, 194, 217, 218,
173859 /* 1480 */ 194, 101, 194, 245, 217, 218, 194, 107, 108, 217,
173860 /* 1490 */ 218, 22, 217, 218, 256, 115, 245, 117, 118, 119,
173861 /* 1500 */ 217, 218, 122, 217, 218, 217, 218, 256, 22, 217,
173862 /* 1510 */ 218, 116, 258, 259, 146, 19, 20, 194, 22, 139,
173863 /* 1520 */ 140, 150, 151, 136, 23, 194, 25, 194, 141, 194,
173864 /* 1530 */ 194, 62, 36, 118, 154, 155, 156, 157, 158, 100,
173865 /* 1540 */ 145, 194, 154, 194, 156, 49, 194, 23, 194, 25,
173866 /* 1550 */ 217, 218, 217, 218, 194, 257, 60, 143, 194, 60,
173867 /* 1560 */ 194, 121, 122, 183, 217, 218, 217, 218, 72, 217,
173868 /* 1570 */ 218, 217, 218, 134, 23, 194, 25, 217, 218, 7,
173869 /* 1580 */ 8, 321, 86, 217, 218, 194, 122, 91, 19, 20,
173870 /* 1590 */ 23, 22, 25, 23, 142, 25, 132, 101, 217, 218,
173871 /* 1600 */ 194, 194, 194, 107, 108, 36, 194, 194, 217, 218,
173872 /* 1610 */ 194, 115, 194, 117, 118, 119, 194, 118, 122, 194,
173873 /* 1620 */ 23, 194, 25, 217, 218, 217, 218, 194, 142, 60,
173874 /* 1630 */ 217, 218, 194, 217, 218, 217, 218, 84, 85, 217,
173875 /* 1640 */ 218, 72, 217, 218, 217, 218, 60, 23, 60, 25,
173876 /* 1650 */ 154, 155, 156, 157, 158, 86, 154, 194, 156, 194,
173877 /* 1660 */ 91, 19, 20, 23, 22, 25, 194, 23, 194, 25,
173878 /* 1670 */ 101, 23, 194, 25, 194, 194, 107, 108, 36, 183,
173879 /* 1680 */ 217, 218, 217, 218, 115, 194, 117, 118, 119, 217,
173880 /* 1690 */ 218, 122, 194, 237, 194, 217, 218, 217, 218, 194,
173881 /* 1700 */ 194, 23, 60, 25, 118, 23, 118, 25, 217, 218,
173882 /* 1710 */ 23, 194, 25, 194, 72, 217, 218, 217, 218, 23,
173883 /* 1720 */ 194, 25, 194, 154, 155, 156, 157, 158, 86, 23,
173884 /* 1730 */ 194, 25, 194, 91, 217, 218, 217, 218, 194, 194,
173885 /* 1740 */ 194, 194, 194, 101, 194, 217, 218, 290, 194, 107,
173886 /* 1750 */ 108, 194, 183, 217, 218, 194, 194, 115, 194, 117,
173887 /* 1760 */ 118, 119, 194, 243, 122, 194, 289, 194, 194, 194,
173888 /* 1770 */ 194, 257, 257, 257, 244, 257, 192, 273, 215, 269,
173889 /* 1780 */ 246, 299, 269, 295, 247, 273, 247, 246, 295, 230,
173890 /* 1790 */ 261, 226, 261, 261, 273, 273, 154, 155, 156, 157,
173891 /* 1800 */ 158, 0, 1, 2, 221, 220, 5, 220, 250, 220,
173892 /* 1810 */ 261, 10, 11, 12, 13, 14, 250, 282, 17, 197,
173893 /* 1820 */ 61, 19, 20, 246, 22, 183, 244, 142, 201, 201,
173894 /* 1830 */ 38, 30, 299, 32, 201, 152, 22, 151, 36, 299,
173895 /* 1840 */ 43, 40, 235, 18, 238, 285, 238, 238, 296, 238,
173896 /* 1850 */ 201, 296, 274, 272, 18, 200, 235, 150, 235, 247,
173897 /* 1860 */ 247, 247, 60, 247, 274, 274, 272, 201, 200, 159,
173898 /* 1870 */ 63, 292, 71, 201, 72, 200, 22, 201, 222, 200,
173899 /* 1880 */ 79, 201, 222, 82, 291, 116, 219, 65, 200, 219,
173900 /* 1890 */ 219, 228, 22, 127, 225, 166, 222, 24, 225, 114,
173901 /* 1900 */ 99, 284, 221, 101, 284, 228, 307, 315, 219, 107,
173902 /* 1910 */ 108, 219, 219, 219, 201, 92, 320, 115, 320, 117,
173903 /* 1920 */ 118, 119, 222, 83, 122, 267, 267, 149, 146, 19,
173904 /* 1930 */ 20, 22, 22, 279, 250, 134, 201, 148, 159, 249,
173905 /* 1940 */ 139, 140, 251, 141, 25, 281, 36, 147, 251, 248,
173906 /* 1950 */ 247, 203, 13, 195, 6, 195, 154, 155, 156, 157,
173907 /* 1960 */ 158, 193, 305, 193, 163, 193, 305, 302, 214, 208,
173908 /* 1970 */ 60, 214, 208, 223, 223, 4, 214, 214, 3, 22,
173909 /* 1980 */ 215, 214, 72, 208, 164, 183, 215, 15, 23, 16,
173910 /* 1990 */ 23, 140, 131, 152, 25, 143, 20, 16, 24, 1,
173911 /* 2000 */ 145, 143, 131, 131, 62, 37, 54, 54, 152, 54,
173912 /* 2010 */ 54, 101, 131, 117, 34, 1, 142, 107, 108, 22,
173913 /* 2020 */ 5, 116, 162, 69, 25, 115, 76, 117, 118, 119,
173914 /* 2030 */ 1, 2, 122, 69, 5, 41, 142, 116, 20, 10,
173915 /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126,
173916 /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30,
173917 /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40,
173918 /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68,
173919 /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23,
173920 /* 2090 */ 22, 98, 23, 183, 23, 117, 34, 22, 25, 89,
173921 /* 2100 */ 71, 142, 144, 76, 34, 23, 34, 76, 79, 87,
173922 /* 2110 */ 34, 82, 34, 94, 71, 34, 22, 24, 44, 34,
173923 /* 2120 */ 25, 25, 79, 23, 23, 82, 143, 23, 99, 143,
173924 /* 2130 */ 23, 22, 11, 25, 23, 25, 22, 22, 22, 1,
173925 /* 2140 */ 23, 23, 99, 136, 22, 22, 142, 142, 142, 25,
173926 /* 2150 */ 25, 23, 15, 1, 322, 322, 322, 322, 322, 322,
173927 /* 2160 */ 322, 322, 322, 134, 322, 322, 322, 322, 139, 140,
173928 /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 134, 322, 322,
173929 /* 2180 */ 322, 322, 139, 140, 322, 322, 322, 322, 322, 322,
173930 /* 2190 */ 322, 322, 163, 322, 322, 322, 322, 322, 322, 322,
173931 /* 2200 */ 322, 322, 322, 322, 322, 322, 163, 322, 322, 322,
173932 /* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173933 /* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173934 /* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173935 /* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173936 /* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
@@ -173064,181 +173938,188 @@
173938 /* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173939 /* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173940 /* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173941 /* 2300 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173942 /* 2310 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173943 /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173944 /* 2330 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
173945 /* 2340 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173946 /* 2350 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173947 /* 2360 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173948 /* 2370 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173949 /* 2380 */ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
173950 /* 2390 */ 186, 186, 186,
173951 };
173952 #define YY_SHIFT_COUNT (582)
173953 #define YY_SHIFT_MIN (0)
173954 #define YY_SHIFT_MAX (2152)
173955 static const unsigned short int yy_shift_ofst[] = {
173956 /* 0 */ 2029, 1801, 2043, 1380, 1380, 33, 391, 1496, 1569, 1642,
173957 /* 10 */ 702, 702, 702, 193, 33, 33, 33, 33, 33, 0,
173958 /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702,
173959 /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 406, 406,
173960 /* 40 */ 111, 111, 218, 447, 547, 598, 598, 260, 260, 260,
173961 /* 50 */ 260, 40, 112, 320, 340, 445, 489, 593, 637, 741,
173962 /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177,
173963 /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
173964 /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554,
173965 /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702,
173966 /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173967 /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173968 /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173969 /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
173970 /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198,
173971 /* 150 */ 183, 99, 236, 292, 598, 793, 167, 598, 598, 880,
173972 /* 160 */ 880, 598, 857, 150, 195, 195, 195, 264, 113, 113,
173973 /* 170 */ 2207, 2207, 854, 854, 854, 751, 765, 765, 765, 765,
173974 /* 180 */ 1096, 1096, 725, 292, 882, 904, 598, 598, 598, 598,
173975 /* 190 */ 598, 598, 598, 598, 598, 598, 598, 598, 598, 598,
173976 /* 200 */ 598, 598, 598, 598, 598, 1273, 1032, 1032, 598, 147,
173977 /* 210 */ 1098, 1098, 603, 603, 1276, 1276, 363, 2207, 2207, 2207,
173978 /* 220 */ 2207, 2207, 2207, 2207, 469, 617, 617, 801, 336, 461,
173979 /* 230 */ 804, 864, 615, 891, 913, 598, 598, 598, 598, 598,
173980 /* 240 */ 598, 598, 598, 598, 598, 653, 598, 598, 598, 598,
173981 /* 250 */ 598, 598, 598, 598, 598, 598, 598, 598, 1105, 1105,
173982 /* 260 */ 1105, 598, 598, 598, 1194, 598, 598, 598, 1215, 1249,
173983 /* 270 */ 598, 1353, 598, 598, 598, 598, 598, 598, 598, 598,
173984 /* 280 */ 677, 449, 902, 1338, 1338, 1338, 1338, 1248, 902, 902,
173985 /* 290 */ 326, 1151, 1047, 755, 749, 1371, 960, 1371, 1007, 1162,
173986 /* 300 */ 749, 749, 1162, 749, 960, 1007, 1274, 738, 215, 1300,
173987 /* 310 */ 1300, 1300, 1395, 1395, 1395, 1395, 1368, 1368, 1033, 1414,
173988 /* 320 */ 1387, 1361, 1759, 1759, 1685, 1685, 1792, 1792, 1685, 1683,
173989 /* 330 */ 1686, 1814, 1797, 1825, 1825, 1825, 1825, 1685, 1836, 1707,
173990 /* 340 */ 1686, 1686, 1707, 1814, 1797, 1707, 1797, 1707, 1685, 1836,
173991 /* 350 */ 1710, 1807, 1685, 1836, 1854, 1685, 1836, 1685, 1836, 1854,
173992 /* 360 */ 1769, 1769, 1769, 1822, 1870, 1870, 1854, 1769, 1766, 1769,
173993 /* 370 */ 1822, 1769, 1769, 1729, 1873, 1785, 1785, 1854, 1685, 1823,
173994 /* 380 */ 1823, 1840, 1840, 1778, 1782, 1909, 1685, 1779, 1778, 1789,
173995 /* 390 */ 1800, 1707, 1919, 1939, 1939, 1948, 1948, 1948, 2207, 2207,
173996 /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207,
173997 /* 410 */ 2207, 2207, 2207, 69, 1037, 79, 1088, 651, 1196, 1415,
173998 /* 420 */ 1501, 1439, 1369, 1452, 911, 1211, 1524, 1469, 1551, 1567,
173999 /* 430 */ 1570, 1624, 1640, 1644, 1499, 1440, 1572, 1464, 1597, 275,
174000 /* 440 */ 782, 1586, 1648, 1678, 1553, 1682, 1687, 1388, 1502, 1696,
174001 /* 450 */ 1706, 1588, 1486, 1971, 1975, 1957, 1820, 1972, 1973, 1965,
174002 /* 460 */ 1967, 1851, 1841, 1861, 1969, 1969, 1974, 1852, 1976, 1855,
174003 /* 470 */ 1981, 1998, 1858, 1871, 1969, 1872, 1942, 1968, 1969, 1856,
174004 /* 480 */ 1952, 1953, 1955, 1956, 1881, 1896, 1980, 1874, 2014, 2015,
174005 /* 490 */ 1997, 1905, 1860, 1954, 1999, 1964, 1950, 1994, 1894, 1921,
174006 /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047,
174007 /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057,
174008 /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1959,
174009 /* 530 */ 2069, 2071, 1978, 2062, 2075, 1958, 2073, 2070, 2072, 2076,
174010 /* 540 */ 2078, 2010, 2027, 2022, 2074, 2031, 2019, 2081, 2082, 2094,
174011 /* 550 */ 2093, 2095, 2096, 2085, 1983, 1986, 2100, 2073, 2101, 2104,
174012 /* 560 */ 2107, 2109, 2108, 2110, 2111, 2114, 2121, 2115, 2116, 2117,
174013 /* 570 */ 2118, 2122, 2123, 2124, 2007, 2004, 2005, 2006, 2125, 2128,
174014 /* 580 */ 2137, 2138, 2152,
174015 };
174016 #define YY_REDUCE_COUNT (412)
174017 #define YY_REDUCE_MIN (-276)
174018 #define YY_REDUCE_MAX (1775)
174019 static const short yy_reduce_ofst[] = {
174020 /* 0 */ -66, 217, -63, -177, -180, 161, 364, 64, -183, 162,
174021 /* 10 */ 223, 367, 414, -173, 473, 514, 525, 622, 626, -207,
174022 /* 20 */ 351, -276, -38, 693, 811, 831, 833, 888, -188, 945,
174023 /* 30 */ 947, 416, 558, 951, 867, 287, 1078, 1080, -186, 224,
174024 /* 40 */ -132, 42, 964, 269, 417, 796, 810, -237, -231, -237,
174025 /* 50 */ -231, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174026 /* 60 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174027 /* 70 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
174028 /* 80 */ -45, -45, -45, -45, -45, -45, -45, -45, -45, 895,
174029 /* 90 */ 925, 967, 980, 1100, 1143, 1169, 1203, 1225, 1228, 1242,
174030 /* 100 */ 1247, 1250, 1253, 1255, 1261, 1267, 1272, 1275, 1283, 1286,
174031 /* 110 */ 1288, 1292, 1333, 1335, 1347, 1349, 1352, 1354, 1360, 1366,
174032 /* 120 */ 1381, 1391, 1406, 1408, 1413, 1416, 1418, 1422, 1425, 1427,
174033 /* 130 */ 1463, 1465, 1472, 1478, 1480, 1491, 1498, 1500, 1517, 1519,
174034 /* 140 */ 1528, 1536, -45, -45, -45, -45, -45, -45, -45, -45,
174035 /* 150 */ -45, -45, -45, 312, -158, 285, -219, 9, 166, 370,
174036 /* 160 */ 545, 707, -45, 930, 601, 963, 1067, 792, -45, -45,
174037 /* 170 */ -45, -45, -204, -204, -204, 369, -171, -129, 632, 678,
174038 /* 180 */ 202, 352, -270, 412, 627, 627, -9, 122, 415, 419,
174039 /* 190 */ -56, 248, 583, 920, 6, 261, 459, 795, 1049, 813,
174040 /* 200 */ 1062, 1082, -161, 778, 1063, 797, 870, 1003, 1128, 443,
174041 /* 210 */ 1031, 1072, 1191, 1192, 957, 1120, 105, 1149, 523, 933,
174042 /* 220 */ 1218, 1238, 1254, 1251, -138, 96, 117, 146, 181, 277,
174043 /* 230 */ 280, 421, 480, 712, 830, 850, 1085, 1099, 1129, 1209,
174044 /* 240 */ 1323, 1331, 1336, 1364, 1407, 368, 1412, 1433, 1438, 1474,
174045 /* 250 */ 1481, 1505, 1506, 1526, 1538, 1544, 1545, 1546, 722, 764,
174046 /* 260 */ 856, 1547, 1548, 1550, 1188, 1554, 1557, 1561, 1298, 1260,
174047 /* 270 */ 1562, 1456, 1564, 280, 1568, 1571, 1573, 1574, 1575, 1576,
174048 /* 280 */ 1457, 1477, 1520, 1514, 1515, 1516, 1518, 1188, 1520, 1520,
174049 /* 290 */ 1530, 1563, 1584, 1482, 1504, 1510, 1534, 1513, 1488, 1537,
174050 /* 300 */ 1512, 1521, 1539, 1522, 1541, 1493, 1583, 1559, 1565, 1585,
174051 /* 310 */ 1587, 1589, 1529, 1531, 1532, 1549, 1558, 1566, 1535, 1577,
174052 /* 320 */ 1582, 1622, 1533, 1540, 1627, 1628, 1552, 1555, 1633, 1560,
174053 /* 330 */ 1578, 1581, 1607, 1606, 1608, 1609, 1611, 1649, 1655, 1612,
174054 /* 340 */ 1590, 1591, 1613, 1594, 1621, 1614, 1623, 1616, 1666, 1668,
174055 /* 350 */ 1579, 1593, 1672, 1675, 1656, 1676, 1679, 1680, 1688, 1660,
174056 /* 360 */ 1667, 1670, 1671, 1663, 1669, 1673, 1674, 1689, 1681, 1692,
174057 /* 370 */ 1677, 1693, 1694, 1592, 1599, 1617, 1620, 1700, 1713, 1596,
174058 /* 380 */ 1598, 1658, 1659, 1691, 1684, 1654, 1735, 1664, 1697, 1690,
174059 /* 390 */ 1701, 1703, 1748, 1758, 1760, 1768, 1770, 1772, 1657, 1661,
174060 /* 400 */ 1665, 1761, 1754, 1757, 1762, 1763, 1764, 1750, 1751, 1765,
174061 /* 410 */ 1771, 1767, 1775,
174062 };
174063 static const YYACTIONTYPE yy_default[] = {
174064 /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254,
174065 /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397,
174066 /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174067 /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254,
174068 /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254,
174069 /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254,
174070 /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420,
174071 /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488,
174072 /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254,
174073 /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174074 /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174075 /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174076 /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174077 /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174078 /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457,
174079 /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254,
174080 /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461,
174081 /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254,
174082 /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174083 /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174084 /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287,
174085 /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358,
174086 /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254,
174087 /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548,
174088 /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174089 /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174090 /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254,
174091 /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608,
174092 /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342,
174093 /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410,
174094 /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397,
174095 /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364,
174096 /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509,
174097 /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410,
174098 /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272,
174099 /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499,
174100 /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330,
174101 /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588,
174102 /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403,
174103 /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660,
174104 /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288,
174105 /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618,
174106 /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254,
174107 /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174108 /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174109 /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254,
174110 /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254,
174111 /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254,
174112 /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254,
174113 /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254,
174114 /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174115 /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174116 /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174117 /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254,
174118 /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174119 /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254,
174120 /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
174121 /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254,
174122 /* 580 */ 1266, 1254, 1254,
174123 };
174124 /********** End of lemon-generated parsing tables *****************************/
174125
@@ -173258,56 +174139,57 @@
174139 */
174140 #ifdef YYFALLBACK
174141 static const YYCODETYPE yyFallback[] = {
174142 0, /* $ => nothing */
174143 0, /* SEMI => nothing */
174144 60, /* EXPLAIN => ID */
174145 60, /* QUERY => ID */
174146 60, /* PLAN => ID */
174147 60, /* BEGIN => ID */
174148 0, /* TRANSACTION => nothing */
174149 60, /* DEFERRED => ID */
174150 60, /* IMMEDIATE => ID */
174151 60, /* EXCLUSIVE => ID */
174152 0, /* COMMIT => nothing */
174153 60, /* END => ID */
174154 60, /* ROLLBACK => ID */
174155 60, /* SAVEPOINT => ID */
174156 60, /* RELEASE => ID */
174157 0, /* TO => nothing */
174158 0, /* TABLE => nothing */
174159 0, /* CREATE => nothing */
174160 60, /* IF => ID */
174161 0, /* NOT => nothing */
174162 0, /* EXISTS => nothing */
174163 60, /* TEMP => ID */
174164 0, /* LP => nothing */
174165 0, /* RP => nothing */
174166 0, /* AS => nothing */
174167 0, /* COMMA => nothing */
174168 60, /* WITHOUT => ID */
174169 60, /* ABORT => ID */
174170 60, /* ACTION => ID */
174171 60, /* AFTER => ID */
174172 60, /* ANALYZE => ID */
174173 60, /* ASC => ID */
174174 60, /* ATTACH => ID */
174175 60, /* BEFORE => ID */
174176 60, /* BY => ID */
174177 60, /* CASCADE => ID */
174178 60, /* CAST => ID */
174179 60, /* CONFLICT => ID */
174180 60, /* DATABASE => ID */
174181 60, /* DESC => ID */
174182 60, /* DETACH => ID */
174183 60, /* EACH => ID */
174184 60, /* FAIL => ID */
174185 0, /* OR => nothing */
174186 0, /* AND => nothing */
174187 0, /* IS => nothing */
174188 0, /* ISNOT => nothing */
174189 60, /* MATCH => ID */
174190 60, /* LIKE_KW => ID */
174191 0, /* BETWEEN => nothing */
174192 0, /* IN => nothing */
174193 0, /* ISNULL => nothing */
174194 0, /* NOTNULL => nothing */
174195 0, /* NE => nothing */
@@ -173316,51 +174198,51 @@
174198 0, /* LE => nothing */
174199 0, /* LT => nothing */
174200 0, /* GE => nothing */
174201 0, /* ESCAPE => nothing */
174202 0, /* ID => nothing */
174203 60, /* COLUMNKW => ID */
174204 60, /* DO => ID */
174205 60, /* FOR => ID */
174206 60, /* IGNORE => ID */
174207 60, /* INITIALLY => ID */
174208 60, /* INSTEAD => ID */
174209 60, /* NO => ID */
174210 60, /* KEY => ID */
174211 60, /* OF => ID */
174212 60, /* OFFSET => ID */
174213 60, /* PRAGMA => ID */
174214 60, /* RAISE => ID */
174215 60, /* RECURSIVE => ID */
174216 60, /* REPLACE => ID */
174217 60, /* RESTRICT => ID */
174218 60, /* ROW => ID */
174219 60, /* ROWS => ID */
174220 60, /* TRIGGER => ID */
174221 60, /* VACUUM => ID */
174222 60, /* VIEW => ID */
174223 60, /* VIRTUAL => ID */
174224 60, /* WITH => ID */
174225 60, /* NULLS => ID */
174226 60, /* FIRST => ID */
174227 60, /* LAST => ID */
174228 60, /* CURRENT => ID */
174229 60, /* FOLLOWING => ID */
174230 60, /* PARTITION => ID */
174231 60, /* PRECEDING => ID */
174232 60, /* RANGE => ID */
174233 60, /* UNBOUNDED => ID */
174234 60, /* EXCLUDE => ID */
174235 60, /* GROUPS => ID */
174236 60, /* OTHERS => ID */
174237 60, /* TIES => ID */
174238 60, /* GENERATED => ID */
174239 60, /* ALWAYS => ID */
174240 60, /* MATERIALIZED => ID */
174241 60, /* REINDEX => ID */
174242 60, /* RENAME => ID */
174243 60, /* CTIME_KW => ID */
174244 0, /* ANY => nothing */
174245 0, /* BITAND => nothing */
174246 0, /* BITOR => nothing */
174247 0, /* LSHIFT => nothing */
174248 0, /* RSHIFT => nothing */
@@ -173427,14 +174309,13 @@
174309 0, /* FILTER => nothing */
174310 0, /* COLUMN => nothing */
174311 0, /* AGG_FUNCTION => nothing */
174312 0, /* AGG_COLUMN => nothing */
174313 0, /* TRUEFALSE => nothing */
 
174314 0, /* FUNCTION => nothing */
 
174315 0, /* UPLUS => nothing */
174316 0, /* UMINUS => nothing */
174317 0, /* TRUTH => nothing */
174318 0, /* REGISTER => nothing */
174319 0, /* VECTOR => nothing */
174320 0, /* SELECT_COLUMN => nothing */
174321 0, /* IF_NULL_ROW => nothing */
@@ -173571,139 +174452,139 @@
174452 /* 41 */ "EACH",
174453 /* 42 */ "FAIL",
174454 /* 43 */ "OR",
174455 /* 44 */ "AND",
174456 /* 45 */ "IS",
174457 /* 46 */ "ISNOT",
174458 /* 47 */ "MATCH",
174459 /* 48 */ "LIKE_KW",
174460 /* 49 */ "BETWEEN",
174461 /* 50 */ "IN",
174462 /* 51 */ "ISNULL",
174463 /* 52 */ "NOTNULL",
174464 /* 53 */ "NE",
174465 /* 54 */ "EQ",
174466 /* 55 */ "GT",
174467 /* 56 */ "LE",
174468 /* 57 */ "LT",
174469 /* 58 */ "GE",
174470 /* 59 */ "ESCAPE",
174471 /* 60 */ "ID",
174472 /* 61 */ "COLUMNKW",
174473 /* 62 */ "DO",
174474 /* 63 */ "FOR",
174475 /* 64 */ "IGNORE",
174476 /* 65 */ "INITIALLY",
174477 /* 66 */ "INSTEAD",
174478 /* 67 */ "NO",
174479 /* 68 */ "KEY",
174480 /* 69 */ "OF",
174481 /* 70 */ "OFFSET",
174482 /* 71 */ "PRAGMA",
174483 /* 72 */ "RAISE",
174484 /* 73 */ "RECURSIVE",
174485 /* 74 */ "REPLACE",
174486 /* 75 */ "RESTRICT",
174487 /* 76 */ "ROW",
174488 /* 77 */ "ROWS",
174489 /* 78 */ "TRIGGER",
174490 /* 79 */ "VACUUM",
174491 /* 80 */ "VIEW",
174492 /* 81 */ "VIRTUAL",
174493 /* 82 */ "WITH",
174494 /* 83 */ "NULLS",
174495 /* 84 */ "FIRST",
174496 /* 85 */ "LAST",
174497 /* 86 */ "CURRENT",
174498 /* 87 */ "FOLLOWING",
174499 /* 88 */ "PARTITION",
174500 /* 89 */ "PRECEDING",
174501 /* 90 */ "RANGE",
174502 /* 91 */ "UNBOUNDED",
174503 /* 92 */ "EXCLUDE",
174504 /* 93 */ "GROUPS",
174505 /* 94 */ "OTHERS",
174506 /* 95 */ "TIES",
174507 /* 96 */ "GENERATED",
174508 /* 97 */ "ALWAYS",
174509 /* 98 */ "MATERIALIZED",
174510 /* 99 */ "REINDEX",
174511 /* 100 */ "RENAME",
174512 /* 101 */ "CTIME_KW",
174513 /* 102 */ "ANY",
174514 /* 103 */ "BITAND",
174515 /* 104 */ "BITOR",
174516 /* 105 */ "LSHIFT",
174517 /* 106 */ "RSHIFT",
174518 /* 107 */ "PLUS",
174519 /* 108 */ "MINUS",
174520 /* 109 */ "STAR",
174521 /* 110 */ "SLASH",
174522 /* 111 */ "REM",
174523 /* 112 */ "CONCAT",
174524 /* 113 */ "PTR",
174525 /* 114 */ "COLLATE",
174526 /* 115 */ "BITNOT",
174527 /* 116 */ "ON",
174528 /* 117 */ "INDEXED",
174529 /* 118 */ "STRING",
174530 /* 119 */ "JOIN_KW",
174531 /* 120 */ "CONSTRAINT",
174532 /* 121 */ "DEFAULT",
174533 /* 122 */ "NULL",
174534 /* 123 */ "PRIMARY",
174535 /* 124 */ "UNIQUE",
174536 /* 125 */ "CHECK",
174537 /* 126 */ "REFERENCES",
174538 /* 127 */ "AUTOINCR",
174539 /* 128 */ "INSERT",
174540 /* 129 */ "DELETE",
174541 /* 130 */ "UPDATE",
174542 /* 131 */ "SET",
174543 /* 132 */ "DEFERRABLE",
174544 /* 133 */ "FOREIGN",
174545 /* 134 */ "DROP",
174546 /* 135 */ "UNION",
174547 /* 136 */ "ALL",
174548 /* 137 */ "EXCEPT",
174549 /* 138 */ "INTERSECT",
174550 /* 139 */ "SELECT",
174551 /* 140 */ "VALUES",
174552 /* 141 */ "DISTINCT",
174553 /* 142 */ "DOT",
174554 /* 143 */ "FROM",
174555 /* 144 */ "JOIN",
174556 /* 145 */ "USING",
174557 /* 146 */ "ORDER",
174558 /* 147 */ "GROUP",
174559 /* 148 */ "HAVING",
174560 /* 149 */ "LIMIT",
174561 /* 150 */ "WHERE",
174562 /* 151 */ "RETURNING",
174563 /* 152 */ "INTO",
174564 /* 153 */ "NOTHING",
174565 /* 154 */ "FLOAT",
174566 /* 155 */ "BLOB",
174567 /* 156 */ "INTEGER",
174568 /* 157 */ "VARIABLE",
174569 /* 158 */ "CASE",
174570 /* 159 */ "WHEN",
174571 /* 160 */ "THEN",
174572 /* 161 */ "ELSE",
174573 /* 162 */ "INDEX",
174574 /* 163 */ "ALTER",
174575 /* 164 */ "ADD",
174576 /* 165 */ "WINDOW",
174577 /* 166 */ "OVER",
174578 /* 167 */ "FILTER",
174579 /* 168 */ "COLUMN",
174580 /* 169 */ "AGG_FUNCTION",
174581 /* 170 */ "AGG_COLUMN",
174582 /* 171 */ "TRUEFALSE",
174583 /* 172 */ "FUNCTION",
174584 /* 173 */ "UPLUS",
174585 /* 174 */ "UMINUS",
174586 /* 175 */ "TRUTH",
174587 /* 176 */ "REGISTER",
174588 /* 177 */ "VECTOR",
174589 /* 178 */ "SELECT_COLUMN",
174590 /* 179 */ "IF_NULL_ROW",
@@ -174134,11 +175015,11 @@
175015 /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
175016 /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
175017 /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
175018 /* 278 */ "trigger_cmd ::= scanpt select scanpt",
175019 /* 279 */ "expr ::= RAISE LP IGNORE RP",
175020 /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP",
175021 /* 281 */ "raisetype ::= ROLLBACK",
175022 /* 282 */ "raisetype ::= ABORT",
175023 /* 283 */ "raisetype ::= FAIL",
175024 /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
175025 /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
@@ -175059,11 +175940,11 @@
175940 293, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
175941 293, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
175942 293, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
175943 293, /* (278) trigger_cmd ::= scanpt select scanpt */
175944 218, /* (279) expr ::= RAISE LP IGNORE RP */
175945 218, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
175946 237, /* (281) raisetype ::= ROLLBACK */
175947 237, /* (282) raisetype ::= ABORT */
175948 237, /* (283) raisetype ::= FAIL */
175949 191, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
175950 191, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -175473,11 +176354,11 @@
176354 -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
176355 -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
176356 -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
176357 -3, /* (278) trigger_cmd ::= scanpt select scanpt */
176358 -4, /* (279) expr ::= RAISE LP IGNORE RP */
176359 -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
176360 -1, /* (281) raisetype ::= ROLLBACK */
176361 -1, /* (282) raisetype ::= ABORT */
176362 -1, /* (283) raisetype ::= FAIL */
176363 -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
176364 -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
@@ -176560,12 +177441,21 @@
177441 case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
177442 {yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/}
177443 break;
177444 case 216: /* expr ::= PLUS|MINUS expr */
177445 {
177446 Expr *p = yymsp[0].minor.yy454;
177447 u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS);
177448 assert( TK_UPLUS>TK_PLUS );
177449 assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) );
177450 if( p && p->op==TK_UPLUS ){
177451 p->op = op;
177452 yymsp[-1].minor.yy454 = p;
177453 }else{
177454 yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0);
177455 /*A-overwrites-B*/
177456 }
177457 }
177458 break;
177459 case 217: /* expr ::= expr PTR expr */
177460 {
177461 ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454);
@@ -176849,13 +177739,13 @@
177739 if( yymsp[-3].minor.yy454 ){
177740 yymsp[-3].minor.yy454->affExpr = OE_Ignore;
177741 }
177742 }
177743 break;
177744 case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */
177745 {
177746 yymsp[-5].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy454, 0);
177747 if( yymsp[-5].minor.yy454 ) {
177748 yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
177749 }
177750 }
177751 break;
@@ -202282,11 +203172,11 @@
203172 }else{
203173 iScore += 1000;
203174 }
203175 mCover |= mPhrase;
203176
203177 for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
203178 mHighlight |= (mPos>>j);
203179 }
203180
203181 if( 0==(*pCsr & 0x0FE) ) break;
203182 fts3GetDeltaPosition(&pCsr, &iCsr);
@@ -208175,17 +209065,10 @@
209065 }
209066 if( !eErr ) sqlite3_result_int64(ctx, cnt);
209067 jsonParseFree(p);
209068 }
209069
 
 
 
 
 
 
 
209070 /* True if the string is all alphanumerics and underscores */
209071 static int jsonAllAlphanum(const char *z, int n){
209072 int i;
209073 for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){}
209074 return i==n;
@@ -208244,14 +209127,20 @@
209127 ** convenience.
209128 **
209129 ** NUMBER ==> $[NUMBER] // PG compatible
209130 ** LABEL ==> $.LABEL // PG compatible
209131 ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
209132 **
209133 ** Updated 2024-05-27: If the NUMBER is negative, then PG counts from
209134 ** the right of the array. Hence for negative NUMBER:
209135 **
209136 ** NUMBER ==> $[#NUMBER] // PG compatible
209137 */
209138 jsonStringInit(&jx, ctx);
209139 if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
209140 jsonAppendRawNZ(&jx, "[", 1);
209141 if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1);
209142 jsonAppendRaw(&jx, zPath, nPath);
209143 jsonAppendRawNZ(&jx, "]", 2);
209144 }else if( jsonAllAlphanum(zPath, nPath) ){
209145 jsonAppendRawNZ(&jx, ".", 1);
209146 jsonAppendRaw(&jx, zPath, nPath);
@@ -216631,11 +217520,11 @@
217520 const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
217521 const char *zName; /* SQL Collation sequence name (eg. "japanese") */
217522 UCollator *pUCollator; /* ICU library collation object */
217523 int rc; /* Return code from sqlite3_create_collation_x() */
217524
217525 assert(nArg==2 || nArg==3);
217526 (void)nArg; /* Unused parameter */
217527 zLocale = (const char *)sqlite3_value_text(apArg[0]);
217528 zName = (const char *)sqlite3_value_text(apArg[1]);
217529
217530 if( !zLocale || !zName ){
@@ -216646,11 +217535,43 @@
217535 if( !U_SUCCESS(status) ){
217536 icuFunctionError(p, "ucol_open", status);
217537 return;
217538 }
217539 assert(p);
217540 if(nArg==3){
217541 const char *zOption = (const char*)sqlite3_value_text(apArg[2]);
217542 static const struct {
217543 const char *zName;
217544 UColAttributeValue val;
217545 } aStrength[] = {
217546 { "PRIMARY", UCOL_PRIMARY },
217547 { "SECONDARY", UCOL_SECONDARY },
217548 { "TERTIARY", UCOL_TERTIARY },
217549 { "DEFAULT", UCOL_DEFAULT_STRENGTH },
217550 { "QUARTERNARY", UCOL_QUATERNARY },
217551 { "IDENTICAL", UCOL_IDENTICAL },
217552 };
217553 unsigned int i;
217554 for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
217555 if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
217556 ucol_setStrength(pUCollator, aStrength[i].val);
217557 break;
217558 }
217559 }
217560 if( i>=sizeof(aStrength)/sizeof(aStrength[0]) ){
217561 sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p));
217562 sqlite3_str_appendf(pStr,
217563 "unknown collation strength \"%s\" - should be one of:",
217564 zOption);
217565 for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
217566 sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
217567 }
217568 sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
217569 sqlite3_free(sqlite3_str_finish(pStr));
217570 return;
217571 }
217572 }
217573 rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
217574 icuCollationColl, icuCollationDel
217575 );
217576 if( rc!=SQLITE_OK ){
217577 ucol_close(pUCollator);
@@ -216669,10 +217590,11 @@
217590 unsigned int enc; /* Optimal text encoding */
217591 unsigned char iContext; /* sqlite3_user_data() context */
217592 void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
217593 } scalars[] = {
217594 {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
217595 {"icu_load_collation",3,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
217596 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
217597 {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
217598 {"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
217599 {"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
217600 {"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
@@ -228072,18 +228994,18 @@
228994 ** sufficient either for the 'T' or 'P' byte and the varint that follows
228995 ** it, or for the two single byte values otherwise. */
228996 p->rc = sessionInputBuffer(&p->in, 2);
228997 if( p->rc!=SQLITE_OK ) return p->rc;
228998
228999 sessionDiscardData(&p->in);
229000 p->in.iCurrent = p->in.iNext;
229001
229002 /* If the iterator is already at the end of the changeset, return DONE. */
229003 if( p->in.iNext>=p->in.nData ){
229004 return SQLITE_DONE;
229005 }
229006
 
 
 
229007 op = p->in.aData[p->in.iNext++];
229008 while( op=='T' || op=='P' ){
229009 if( pbNew ) *pbNew = 1;
229010 p->bPatchset = (op=='P');
229011 if( sessionChangesetReadTblhdr(p) ) return p->rc;
@@ -229814,10 +230736,11 @@
230736 */
230737 struct sqlite3_changegroup {
230738 int rc; /* Error code */
230739 int bPatch; /* True to accumulate patchsets */
230740 SessionTable *pList; /* List of tables in current patch */
230741 SessionBuffer rec;
230742
230743 sqlite3 *db; /* Configured by changegroup_schema() */
230744 char *zDb; /* Configured by changegroup_schema() */
230745 };
230746
@@ -230112,112 +231035,132 @@
231035
231036 return rc;
231037 }
231038
231039 /*
231040 ** Locate or create a SessionTable object that may be used to add the
231041 ** change currently pointed to by iterator pIter to changegroup pGrp.
231042 ** If successful, set output variable (*ppTab) to point to the table
231043 ** object and return SQLITE_OK. Otherwise, if some error occurs, return
231044 ** an SQLite error code and leave (*ppTab) set to NULL.
231045 */
231046 static int sessionChangesetFindTable(
231047 sqlite3_changegroup *pGrp,
231048 const char *zTab,
231049 sqlite3_changeset_iter *pIter,
231050 SessionTable **ppTab
231051 ){
 
 
231052 int rc = SQLITE_OK;
231053 SessionTable *pTab = 0;
231054 int nTab = (int)strlen(zTab);
231055 u8 *abPK = 0;
231056 int nCol = 0;
231057
231058 *ppTab = 0;
231059 sqlite3changeset_pk(pIter, &abPK, &nCol);
231060
231061 /* Search the list for an existing table */
231062 for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
231063 if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break;
231064 }
231065
231066 /* If one was not found above, create a new table now */
231067 if( !pTab ){
231068 SessionTable **ppNew;
231069
231070 pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nTab+1);
231071 if( !pTab ){
231072 return SQLITE_NOMEM;
231073 }
231074 memset(pTab, 0, sizeof(SessionTable));
231075 pTab->nCol = nCol;
231076 pTab->abPK = (u8*)&pTab[1];
231077 memcpy(pTab->abPK, abPK, nCol);
231078 pTab->zName = (char*)&pTab->abPK[nCol];
231079 memcpy(pTab->zName, zTab, nTab+1);
231080
231081 if( pGrp->db ){
231082 pTab->nCol = 0;
231083 rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
231084 if( rc ){
231085 assert( pTab->azCol==0 );
231086 sqlite3_free(pTab);
231087 return rc;
231088 }
231089 }
231090
231091 /* The new object must be linked on to the end of the list, not
231092 ** simply added to the start of it. This is to ensure that the
231093 ** tables within the output of sqlite3changegroup_output() are in
231094 ** the right order. */
231095 for(ppNew=&pGrp->pList; *ppNew; ppNew=&(*ppNew)->pNext);
231096 *ppNew = pTab;
231097 }
231098
231099 /* Check that the table is compatible. */
231100 if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
231101 rc = SQLITE_SCHEMA;
231102 }
231103
231104 *ppTab = pTab;
231105 return rc;
231106 }
231107
231108 /*
231109 ** Add the change currently indicated by iterator pIter to the hash table
231110 ** belonging to changegroup pGrp.
231111 */
231112 static int sessionOneChangeToHash(
231113 sqlite3_changegroup *pGrp,
231114 sqlite3_changeset_iter *pIter,
231115 int bRebase
231116 ){
231117 int rc = SQLITE_OK;
231118 int nCol = 0;
231119 int op = 0;
231120 int iHash = 0;
231121 int bIndirect = 0;
231122 SessionChange *pChange = 0;
231123 SessionChange *pExist = 0;
231124 SessionChange **pp = 0;
231125 SessionTable *pTab = 0;
231126 u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
231127 int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
231128
231129 /* Ensure that only changesets, or only patchsets, but not a mixture
231130 ** of both, are being combined. It is an error to try to combine a
231131 ** changeset and a patchset. */
231132 if( pGrp->pList==0 ){
231133 pGrp->bPatch = pIter->bPatchset;
231134 }else if( pIter->bPatchset!=pGrp->bPatch ){
231135 rc = SQLITE_ERROR;
231136 }
231137
231138 if( rc==SQLITE_OK ){
231139 const char *zTab = 0;
231140 sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
231141 rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab);
231142 }
231143
231144 if( rc==SQLITE_OK && nCol<pTab->nCol ){
231145 SessionBuffer *pBuf = &pGrp->rec;
231146 rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf);
231147 aRec = pBuf->aBuf;
231148 nRec = pBuf->nBuf;
231149 assert( pGrp->db );
231150 }
231151
231152 if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){
231153 rc = SQLITE_NOMEM;
231154 }
231155
231156 if( rc==SQLITE_OK ){
231157 /* Search for existing entry. If found, remove it from the hash table.
231158 ** Code below may link it back in. */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231159 iHash = sessionChangeHash(
231160 pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
231161 );
 
 
 
 
231162 for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
231163 int bPkOnly1 = 0;
231164 int bPkOnly2 = 0;
231165 if( pIter->bPatchset ){
231166 bPkOnly1 = (*pp)->op==SQLITE_DELETE;
@@ -230228,23 +231171,45 @@
231171 *pp = (*pp)->pNext;
231172 pTab->nEntry--;
231173 break;
231174 }
231175 }
231176 }
231177
231178 if( rc==SQLITE_OK ){
231179 rc = sessionChangeMerge(pTab, bRebase,
231180 pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
231181 );
231182 }
231183 if( rc==SQLITE_OK && pChange ){
231184 pChange->pNext = pTab->apChange[iHash];
231185 pTab->apChange[iHash] = pChange;
231186 pTab->nEntry++;
 
231187 }
231188
231189 if( rc==SQLITE_OK ) rc = pIter->rc;
231190 return rc;
231191 }
231192
231193 /*
231194 ** Add all changes in the changeset traversed by the iterator passed as
231195 ** the first argument to the changegroup hash tables.
231196 */
231197 static int sessionChangesetToHash(
231198 sqlite3_changeset_iter *pIter, /* Iterator to read from */
231199 sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
231200 int bRebase /* True if hash table is for rebasing */
231201 ){
231202 u8 *aRec;
231203 int nRec;
231204 int rc = SQLITE_OK;
231205
231206 while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
231207 rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
231208 if( rc!=SQLITE_OK ) break;
231209 }
231210
231211 if( rc==SQLITE_OK ) rc = pIter->rc;
231212 return rc;
231213 }
231214
231215 /*
@@ -230367,10 +231332,27 @@
231332 rc = sessionChangesetToHash(pIter, pGrp, 0);
231333 }
231334 sqlite3changeset_finalize(pIter);
231335 return rc;
231336 }
231337
231338 /*
231339 ** Add a single change to a changeset-group.
231340 */
231341 SQLITE_API int sqlite3changegroup_add_change(
231342 sqlite3_changegroup *pGrp,
231343 sqlite3_changeset_iter *pIter
231344 ){
231345 if( pIter->in.iCurrent==pIter->in.iNext
231346 || pIter->rc!=SQLITE_OK
231347 || pIter->bInvert
231348 ){
231349 /* Iterator does not point to any valid entry or is an INVERT iterator. */
231350 return SQLITE_ERROR;
231351 }
231352 return sessionOneChangeToHash(pGrp, pIter, 0);
231353 }
231354
231355 /*
231356 ** Obtain a buffer containing a changeset representing the concatenation
231357 ** of all changesets added to the group so far.
231358 */
@@ -230417,10 +231399,11 @@
231399 */
231400 SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
231401 if( pGrp ){
231402 sqlite3_free(pGrp->zDb);
231403 sessionDeleteTable(0, pGrp->pList);
231404 sqlite3_free(pGrp->rec.aBuf);
231405 sqlite3_free(pGrp);
231406 }
231407 }
231408
231409 /*
@@ -230818,10 +231801,11 @@
231801 ** Destroy a rebaser object
231802 */
231803 SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
231804 if( p ){
231805 sessionDeleteTable(0, p->grp.pList);
231806 sqlite3_free(p->grp.rec.aBuf);
231807 sqlite3_free(p);
231808 }
231809 }
231810
231811 /*
@@ -230915,12 +231899,12 @@
231899
231900 /*
231901 ** EXTENSION API FUNCTIONS
231902 **
231903 ** xUserData(pFts):
231904 ** Return a copy of the pUserData pointer passed to the xCreateFunction()
231905 ** API when the extension function was registered.
231906 **
231907 ** xColumnTotalSize(pFts, iCol, pnToken):
231908 ** If parameter iCol is less than zero, set output variable *pnToken
231909 ** to the total number of tokens in the FTS5 table. Or, if iCol is
231910 ** non-negative but less than the number of columns in the table, return
@@ -231097,10 +232081,14 @@
232081 ** This API can be quite slow if used with an FTS5 table created with the
232082 ** "detail=none" or "detail=column" option. If the FTS5 table is created
232083 ** with either "detail=none" or "detail=column" and "content=" option
232084 ** (i.e. if it is a contentless table), then this API always iterates
232085 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
232086 **
232087 ** In all cases, matches are visited in (column ASC, offset ASC) order.
232088 ** i.e. all those in column 0, sorted by offset, followed by those in
232089 ** column 1, etc.
232090 **
232091 ** xPhraseNext()
232092 ** See xPhraseFirst above.
232093 **
232094 ** xPhraseFirstColumn()
@@ -231628,10 +232616,19 @@
232616 ** Interface to code in fts5_config.c. fts5_config.c contains contains code
232617 ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
232618 */
232619
232620 typedef struct Fts5Config Fts5Config;
232621 typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
232622
232623 struct Fts5TokenizerConfig {
232624 Fts5Tokenizer *pTok;
232625 fts5_tokenizer *pTokApi;
232626 const char **azArg;
232627 int nArg;
232628 int ePattern; /* FTS_PATTERN_XXX constant */
232629 };
232630
232631 /*
232632 ** An instance of the following structure encodes all information that can
232633 ** be gleaned from the CREATE VIRTUAL TABLE statement.
232634 **
@@ -231670,10 +232667,11 @@
232667 ** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
232668 **
232669 */
232670 struct Fts5Config {
232671 sqlite3 *db; /* Database handle */
232672 Fts5Global *pGlobal; /* Global fts5 object for handle db */
232673 char *zDb; /* Database holding FTS index (e.g. "main") */
232674 char *zName; /* Name of FTS index */
232675 int nCol; /* Number of columns */
232676 char **azCol; /* Column names */
232677 u8 *abUnindexed; /* True for unindexed columns */
@@ -231685,14 +232683,12 @@
232683 char *zContentRowid; /* "content_rowid=" option value */
232684 int bColumnsize; /* "columnsize=" option value (dflt==1) */
232685 int bTokendata; /* "tokendata=" option value (dflt==0) */
232686 int eDetail; /* FTS5_DETAIL_XXX value */
232687 char *zContentExprlist;
232688 Fts5TokenizerConfig t;
 
232689 int bLock; /* True when table is preparing statement */
 
232690
232691 /* Values loaded from the %_config table */
232692 int iVersion; /* fts5 file format 'version' */
232693 int iCookie; /* Incremented when %_config is modified */
232694 int pgsz; /* Approximate page size used in %_data */
@@ -232083,17 +233079,11 @@
233079 sqlite3_vtab base; /* Base class used by SQLite core */
233080 Fts5Config *pConfig; /* Virtual table configuration */
233081 Fts5Index *pIndex; /* Full-text index */
233082 };
233083
233084 static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
 
 
 
 
 
 
233085
233086 static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
233087
233088 static int sqlite3Fts5FlushToDisk(Fts5Table*);
233089
@@ -232352,10 +233342,11 @@
233342 static int sqlite3Fts5TokenizerInit(fts5_api*);
233343 static int sqlite3Fts5TokenizerPattern(
233344 int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
233345 Fts5Tokenizer *pTok
233346 );
233347 static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
233348 /*
233349 ** End of interface to code in fts5_tokenizer.c.
233350 **************************************************************************/
233351
233352 /**************************************************************************
@@ -235303,11 +236294,10 @@
236294 ** an error occurs, an SQLite error code is returned and an error message
236295 ** may be left in *pzErr. It is the responsibility of the caller to
236296 ** eventually free any such error message using sqlite3_free().
236297 */
236298 static int fts5ConfigParseSpecial(
 
236299 Fts5Config *pConfig, /* Configuration object to update */
236300 const char *zCmd, /* Special command to parse */
236301 const char *zArg, /* Argument to parse */
236302 char **pzErr /* OUT: Error message */
236303 ){
@@ -235367,16 +236357,15 @@
236357 }
236358
236359 if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
236360 const char *p = (const char*)zArg;
236361 sqlite3_int64 nArg = strlen(zArg) + 1;
236362 char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
 
 
236363
236364 if( azArg ){
236365 char *pSpace = (char*)&azArg[nArg];
236366 if( pConfig->t.azArg ){
236367 *pzErr = sqlite3_mprintf("multiple tokenize=... directives");
236368 rc = SQLITE_ERROR;
236369 }else{
236370 for(nArg=0; p && *p; nArg++){
236371 const char *p2 = fts5ConfigSkipWhitespace(p);
@@ -235395,20 +236384,18 @@
236384 }
236385 if( p==0 ){
236386 *pzErr = sqlite3_mprintf("parse error in tokenize directive");
236387 rc = SQLITE_ERROR;
236388 }else{
236389 pConfig->t.azArg = (const char**)azArg;
236390 pConfig->t.nArg = nArg;
236391 azArg = 0;
 
236392 }
236393 }
236394 }
 
236395 sqlite3_free(azArg);
236396
236397 return rc;
236398 }
236399
236400 if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
236401 if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
@@ -235481,20 +236468,10 @@
236468
236469 *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
236470 return SQLITE_ERROR;
236471 }
236472
 
 
 
 
 
 
 
 
 
 
236473 /*
236474 ** Gobble up the first bareword or quoted word from the input buffer zIn.
236475 ** Return a pointer to the character immediately following the last in
236476 ** the gobbled word if successful, or a NULL pointer otherwise (failed
236477 ** to find close-quote character).
@@ -235623,10 +236600,11 @@
236600 sqlite3_int64 nByte;
236601
236602 *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
236603 if( pRet==0 ) return SQLITE_NOMEM;
236604 memset(pRet, 0, sizeof(Fts5Config));
236605 pRet->pGlobal = pGlobal;
236606 pRet->db = db;
236607 pRet->iCookie = -1;
236608
236609 nByte = nArg * (sizeof(char*) + sizeof(u8));
236610 pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -235671,11 +236649,11 @@
236649 if( z==0 ){
236650 *pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
236651 rc = SQLITE_ERROR;
236652 }else{
236653 if( bOption ){
236654 rc = fts5ConfigParseSpecial(pRet,
236655 ALWAYS(zOne)?zOne:"",
236656 zTwo?zTwo:"",
236657 pzErr
236658 );
236659 }else{
@@ -235709,17 +236687,10 @@
236687 "contentless_delete=1 is incompatible with columnsize=0"
236688 );
236689 rc = SQLITE_ERROR;
236690 }
236691
 
 
 
 
 
 
 
236692 /* If no zContent option was specified, fill in the default values. */
236693 if( rc==SQLITE_OK && pRet->zContent==0 ){
236694 const char *zTail = 0;
236695 assert( pRet->eContent==FTS5_CONTENT_NORMAL
236696 || pRet->eContent==FTS5_CONTENT_NONE
@@ -235757,13 +236728,14 @@
236728 ** Free the configuration object passed as the only argument.
236729 */
236730 static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
236731 if( pConfig ){
236732 int i;
236733 if( pConfig->t.pTok ){
236734 pConfig->t.pTokApi->xDelete(pConfig->t.pTok);
236735 }
236736 sqlite3_free((char*)pConfig->t.azArg);
236737 sqlite3_free(pConfig->zDb);
236738 sqlite3_free(pConfig->zName);
236739 for(i=0; i<pConfig->nCol; i++){
236740 sqlite3_free(pConfig->azCol[i]);
236741 }
@@ -235834,14 +236806,22 @@
236806 int flags, /* FTS5_TOKENIZE_* flags */
236807 const char *pText, int nText, /* Text to tokenize */
236808 void *pCtx, /* Context passed to xToken() */
236809 int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
236810 ){
236811 int rc = SQLITE_OK;
236812 if( pText ){
236813 if( pConfig->t.pTok==0 ){
236814 rc = sqlite3Fts5LoadTokenizer(pConfig);
236815 }
236816 if( rc==SQLITE_OK ){
236817 rc = pConfig->t.pTokApi->xTokenize(
236818 pConfig->t.pTok, pCtx, flags, pText, nText, xToken
236819 );
236820 }
236821 }
236822 return rc;
236823 }
236824
236825 /*
236826 ** Argument pIn points to the first character in what is expected to be
236827 ** a comma-separated list of SQL literals followed by a ')' character.
@@ -236434,11 +237414,15 @@
237414 }else{
237415 sqlite3Fts5ParseNodeFree(sParse.pExpr);
237416 }
237417
237418 sqlite3_free(sParse.apPhrase);
237419 if( 0==*pzErr ){
237420 *pzErr = sParse.zErr;
237421 }else{
237422 sqlite3_free(sParse.zErr);
237423 }
237424 return sParse.rc;
237425 }
237426
237427 /*
237428 ** Assuming that buffer z is at least nByte bytes in size and contains a
@@ -237981,10 +238965,11 @@
238965 ** no token characters at all. (e.g ... MATCH '""'). */
238966 sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
238967 }else if( sCtx.pPhrase->nTerm ){
238968 sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
238969 }
238970 assert( pParse->apPhrase!=0 );
238971 pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
238972 }
238973
238974 return sCtx.pPhrase;
238975 }
@@ -238000,11 +238985,11 @@
238985 ){
238986 int rc = SQLITE_OK; /* Return code */
238987 Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
238988 Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
238989 TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
238990 if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
238991 rc = SQLITE_RANGE;
238992 }else{
238993 pOrig = pExpr->apExprPhrase[iPhrase];
238994 pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
238995 }
@@ -238575,10 +239560,12 @@
239560 || pPrev->eType==FTS5_TERM
239561 || pPrev->eType==FTS5_EOF
239562 );
239563
239564 if( pRight->eType==FTS5_EOF ){
239565 assert( pParse->apPhrase!=0 );
239566 assert( pParse->nPhrase>0 );
239567 assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
239568 sqlite3Fts5ParseNodeFree(pRight);
239569 pRet = pLeft;
239570 pParse->nPhrase--;
239571 }
@@ -249406,12 +250393,16 @@
250393 if( rc==SQLITE_OK ){
250394 rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
250395 assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
250396 }
250397 if( rc==SQLITE_OK ){
250398 pConfig->pzErrmsg = pzErr;
250399 pTab->p.pConfig = pConfig;
250400 pTab->pGlobal = pGlobal;
250401 if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
250402 rc = sqlite3Fts5LoadTokenizer(pConfig);
250403 }
250404 }
250405
250406 /* Open the index sub-system */
250407 if( rc==SQLITE_OK ){
250408 rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
@@ -249429,24 +250420,22 @@
250420 rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
250421 }
250422
250423 /* Load the initial configuration */
250424 if( rc==SQLITE_OK ){
 
 
250425 rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
250426 sqlite3Fts5IndexRollback(pTab->p.pIndex);
 
250427 }
250428
250429 if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
250430 rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1);
250431 }
250432 if( rc==SQLITE_OK ){
250433 rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
250434 }
250435
250436 if( pConfig ) pConfig->pzErrmsg = 0;
250437 if( rc!=SQLITE_OK ){
250438 fts5FreeVtab(pTab);
250439 pTab = 0;
250440 }else if( bCreate ){
250441 fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
@@ -249510,14 +250499,14 @@
250499 Fts5Config *pConfig,
250500 struct sqlite3_index_constraint *p
250501 ){
250502 assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
250503 assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
250504 if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
250505 return 1;
250506 }
250507 if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
250508 && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
250509 ){
250510 return 1;
250511 }
250512 return 0;
@@ -249560,15 +250549,15 @@
250549 ** A > or >= against the rowid: ">"
250550 **
250551 ** This function ensures that there is at most one "r" or "=". And that if
250552 ** there exists an "=" then there is no "<" or ">".
250553 **
250554 ** If an unusable MATCH operator is present in the WHERE clause, then
250555 ** SQLITE_CONSTRAINT is returned.
250556 **
250557 ** Costs are assigned as follows:
250558 **
 
 
 
250559 ** a) If a MATCH operator is present, the cost depends on the other
250560 ** constraints also present. As follows:
250561 **
250562 ** * No other constraints: cost=1000.0
250563 ** * One rowid range constraint: cost=750.0
@@ -249596,11 +250585,11 @@
250585 int iCons = 0;
250586
250587 int bSeenEq = 0;
250588 int bSeenGt = 0;
250589 int bSeenLt = 0;
250590 int nSeenMatch = 0;
250591 int bSeenRank = 0;
250592
250593
250594 assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
250595 assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
@@ -249627,22 +250616,19 @@
250616 || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
250617 ){
250618 /* A MATCH operator or equivalent */
250619 if( p->usable==0 || iCol<0 ){
250620 /* As there exists an unusable MATCH constraint this is an
250621 ** unusable plan. Return SQLITE_CONSTRAINT. */
250622 return SQLITE_CONSTRAINT;
 
 
 
250623 }else{
250624 if( iCol==nCol+1 ){
250625 if( bSeenRank ) continue;
250626 idxStr[iIdxStr++] = 'r';
250627 bSeenRank = 1;
250628 }else if( iCol>=0 ){
250629 nSeenMatch++;
250630 idxStr[iIdxStr++] = 'M';
250631 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
250632 idxStr += strlen(&idxStr[iIdxStr]);
250633 assert( idxStr[iIdxStr]=='\0' );
250634 }
@@ -249655,10 +250641,11 @@
250641 idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
250642 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
250643 idxStr += strlen(&idxStr[iIdxStr]);
250644 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
250645 assert( idxStr[iIdxStr]=='\0' );
250646 nSeenMatch++;
250647 }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
250648 idxStr[iIdxStr++] = '=';
250649 bSeenEq = 1;
250650 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
250651 }
@@ -249691,11 +250678,11 @@
250678 **
250679 ** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
250680 */
250681 if( pInfo->nOrderBy==1 ){
250682 int iSort = pInfo->aOrderBy[0].iColumn;
250683 if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
250684 idxFlags |= FTS5_BI_ORDER_RANK;
250685 }else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
250686 idxFlags |= FTS5_BI_ORDER_ROWID;
250687 }
250688 if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
@@ -249706,18 +250693,21 @@
250693 }
250694 }
250695
250696 /* Calculate the estimated cost based on the flags set in idxFlags. */
250697 if( bSeenEq ){
250698 pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
250699 if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
250700 }else if( bSeenLt && bSeenGt ){
250701 pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
250702 }else if( bSeenLt || bSeenGt ){
250703 pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
250704 }else{
250705 pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
250706 }
250707 for(i=1; i<nSeenMatch; i++){
250708 pInfo->estimatedCost *= 0.4;
250709 }
250710
250711 pInfo->idxNum = idxFlags;
250712 return SQLITE_OK;
250713 }
@@ -249989,10 +250979,11 @@
250979 "%s", sqlite3_errmsg(pConfig->db)
250980 );
250981 }
250982 }else{
250983 rc = SQLITE_OK;
250984 CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
250985 }
250986 break;
250987 }
250988 }
250989 }
@@ -250462,13 +251453,17 @@
251453 */
251454 static i64 fts5CursorRowid(Fts5Cursor *pCsr){
251455 assert( pCsr->ePlan==FTS5_PLAN_MATCH
251456 || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
251457 || pCsr->ePlan==FTS5_PLAN_SOURCE
251458 || pCsr->ePlan==FTS5_PLAN_SCAN
251459 || pCsr->ePlan==FTS5_PLAN_ROWID
251460 );
251461 if( pCsr->pSorter ){
251462 return pCsr->pSorter->iRowid;
251463 }else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
251464 return sqlite3_column_int64(pCsr->pStmt, 0);
251465 }else{
251466 return sqlite3Fts5ExprRowid(pCsr->pExpr);
251467 }
251468 }
251469
@@ -250481,24 +251476,14 @@
251476 static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
251477 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
251478 int ePlan = pCsr->ePlan;
251479
251480 assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
251481 if( ePlan==FTS5_PLAN_SPECIAL ){
251482 *pRowid = 0;
251483 }else{
251484 *pRowid = fts5CursorRowid(pCsr);
 
 
 
 
 
 
 
 
 
 
251485 }
251486
251487 return SQLITE_OK;
251488 }
251489
@@ -250729,10 +251714,11 @@
251714 "'delete' may not be used with a contentless_delete=1 table"
251715 );
251716 rc = SQLITE_ERROR;
251717 }else{
251718 rc = fts5SpecialDelete(pTab, apVal);
251719 bUpdateOrDelete = 1;
251720 }
251721 }else{
251722 rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
251723 }
251724 }else{
@@ -251889,11 +252875,11 @@
252875 }
252876
252877 return rc;
252878 }
252879
252880 int fts5GetTokenizer(
252881 Fts5Global *pGlobal,
252882 const char **azArg,
252883 int nArg,
252884 Fts5Config *pConfig,
252885 char **pzErr
@@ -251903,32 +252889,45 @@
252889
252890 pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
252891 if( pMod==0 ){
252892 assert( nArg>0 );
252893 rc = SQLITE_ERROR;
252894 if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
252895 }else{
252896 rc = pMod->x.xCreate(
252897 pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
252898 );
252899 pConfig->t.pTokApi = &pMod->x;
252900 if( rc!=SQLITE_OK ){
252901 if( pzErr && rc!=SQLITE_NOMEM ){
252902 *pzErr = sqlite3_mprintf("error in tokenizer constructor");
252903 }
252904 }else{
252905 pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
252906 pMod->x.xCreate, pConfig->t.pTok
252907 );
252908 }
252909 }
252910
252911 if( rc!=SQLITE_OK ){
252912 pConfig->t.pTokApi = 0;
252913 pConfig->t.pTok = 0;
252914 }
252915
252916 return rc;
252917 }
252918
252919 /*
252920 ** Attempt to instantiate the tokenizer.
252921 */
252922 static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
252923 return fts5GetTokenizer(
252924 pConfig->pGlobal, pConfig->t.azArg, pConfig->t.nArg,
252925 pConfig, pConfig->pzErrmsg
252926 );
252927 }
252928
252929
252930 static void fts5ModuleDestroy(void *pCtx){
252931 Fts5TokenizerModule *pTok, *pNextTok;
252932 Fts5Auxiliary *pAux, *pNextAux;
252933 Fts5Global *pGlobal = (Fts5Global*)pCtx;
@@ -251969,11 +252968,11 @@
252968 int nArg, /* Number of args */
252969 sqlite3_value **apUnused /* Function arguments */
252970 ){
252971 assert( nArg==0 );
252972 UNUSED_PARAM2(nArg, apUnused);
252973 sqlite3_result_text(pCtx, "fts5: 2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38", -1, SQLITE_TRANSIENT);
252974 }
252975
252976 /*
252977 ** Return true if zName is the extension on one of the shadow tables used
252978 ** by this module.
@@ -252004,21 +253003,27 @@
253003 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
253004 int rc;
253005
253006 assert( pzErr!=0 && *pzErr==0 );
253007 UNUSED_PARAM(isQuick);
253008 assert( pTab->p.pConfig->pzErrmsg==0 );
253009 pTab->p.pConfig->pzErrmsg = pzErr;
253010 rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
253011 if( *pzErr==0 && rc!=SQLITE_OK ){
253012 if( (rc&0xff)==SQLITE_CORRUPT ){
253013 *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
253014 zSchema, zTabname);
253015 rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
253016 }else{
253017 *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
253018 " FTS5 table %s.%s: %s",
253019 zSchema, zTabname, sqlite3_errstr(rc));
253020 }
253021 }
253022
253023 sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
253024 pTab->p.pConfig->pzErrmsg = 0;
253025
253026 return rc;
253027 }
253028
253029 static int fts5Init(sqlite3 *db){
@@ -254796,10 +255801,20 @@
255801 return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
255802 }
255803 }
255804 return FTS5_PATTERN_NONE;
255805 }
255806
255807 /*
255808 ** Return true if the tokenizer described by p->azArg[] is the trigram
255809 ** tokenizer. This tokenizer needs to be loaded before xBestIndex is
255810 ** called for the first time in order to correctly handle LIKE/GLOB.
255811 */
255812 static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
255813 return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
255814 }
255815
255816
255817 /*
255818 ** Register all built-in tokenizers with FTS5.
255819 */
255820 static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -256016,10 +257031,11 @@
257031 Fts5IndexIter *pIter; /* Term/rowid iterator object */
257032 void *pStruct; /* From sqlite3Fts5StructureRef() */
257033
257034 int nLeTerm; /* Size of zLeTerm in bytes */
257035 char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
257036 int colUsed; /* Copy of sqlite3_index_info.colUsed */
257037
257038 /* These are used by 'col' tables only */
257039 int iCol;
257040 i64 *aCnt;
257041 i64 *aDoc;
@@ -256042,13 +257058,15 @@
257058 #define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
257059
257060 /*
257061 ** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
257062 */
257063 #define FTS5_VOCAB_TERM_EQ 0x0100
257064 #define FTS5_VOCAB_TERM_GE 0x0200
257065 #define FTS5_VOCAB_TERM_LE 0x0400
257066
257067 #define FTS5_VOCAB_COLUSED_MASK 0xFF
257068
257069
257070 /*
257071 ** Translate a string containing an fts5vocab table type to an
257072 ** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
@@ -256221,14 +257239,16 @@
257239 ){
257240 int i;
257241 int iTermEq = -1;
257242 int iTermGe = -1;
257243 int iTermLe = -1;
257244 int idxNum = (int)pInfo->colUsed;
257245 int nArg = 0;
257246
257247 UNUSED_PARAM(pUnused);
257248
257249 assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
257250
257251 for(i=0; i<pInfo->nConstraint; i++){
257252 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
257253 if( p->usable==0 ) continue;
257254 if( p->iColumn==0 ){ /* term column */
@@ -256317,11 +257337,11 @@
257337 rc = sqlite3_finalize(pStmt);
257338 pStmt = 0;
257339 if( rc==SQLITE_OK ){
257340 pVTab->zErrMsg = sqlite3_mprintf(
257341 "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
257342 );
257343 rc = SQLITE_ERROR;
257344 }
257345 }else{
257346 rc = sqlite3Fts5FlushToDisk(pFts5);
257347 }
@@ -256477,13 +257497,23 @@
257497 pPos = pCsr->pIter->pData;
257498 nPos = pCsr->pIter->nData;
257499
257500 switch( pTab->eType ){
257501 case FTS5_VOCAB_ROW:
257502 /* Do not bother counting the number of instances if the "cnt"
257503 ** column is not being read (according to colUsed). */
257504 if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
257505 while( iPos<nPos ){
257506 u32 ii;
257507 fts5FastGetVarint32(pPos, iPos, ii);
257508 if( ii==1 ){
257509 /* New column in the position list */
257510 fts5FastGetVarint32(pPos, iPos, ii);
257511 }else{
257512 /* An instance - increment pCsr->aCnt[] */
257513 pCsr->aCnt[0]++;
257514 }
257515 }
257516 }
257517 pCsr->aDoc[0]++;
257518 break;
257519
@@ -256577,10 +257607,11 @@
257607
257608 fts5VocabResetCursor(pCsr);
257609 if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
257610 if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
257611 if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
257612 pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
257613
257614 if( pEq ){
257615 zTerm = (const char *)sqlite3_value_text(pEq);
257616 nTerm = sqlite3_value_bytes(pEq);
257617 f = FTS5INDEX_QUERY_NOTOKENDATA;
257618
+78 -25
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -144,13 +144,13 @@
144144
**
145145
** See also: [sqlite3_libversion()],
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149
-#define SQLITE_VERSION "3.46.0"
150
-#define SQLITE_VERSION_NUMBER 3046000
151
-#define SQLITE_SOURCE_ID "2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3"
149
+#define SQLITE_VERSION "3.47.0"
150
+#define SQLITE_VERSION_NUMBER 3047000
151
+#define SQLITE_SOURCE_ID "2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38"
152152
153153
/*
154154
** CAPI3REF: Run-Time Library Version Numbers
155155
** KEYWORDS: sqlite3_version sqlite3_sourceid
156156
**
@@ -770,12 +770,12 @@
770770
** xUnlock() downgrades the database file lock to either SHARED or NONE.
771771
** If the lock is already at or below the requested lock state, then the call
772772
** to xUnlock() is a no-op.
773773
** The xCheckReservedLock() method checks whether any database connection,
774774
** either in this process or in some other process, is holding a RESERVED,
775
-** PENDING, or EXCLUSIVE lock on the file. It returns true
776
-** if such a lock exists and false otherwise.
775
+** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
776
+** pointer parameter, true if such a lock exists and false otherwise.
777777
**
778778
** The xFileControl() method is a generic interface that allows custom
779779
** VFS implementations to directly control an open file using the
780780
** [sqlite3_file_control()] interface. The second "op" argument is an
781781
** integer opcode. The third argument is a generic pointer intended to
@@ -3568,12 +3568,12 @@
35683568
** the default shared cache setting provided by
35693569
** [sqlite3_enable_shared_cache()].)^
35703570
**
35713571
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
35723572
** <dd>The database connection comes up in "extended result code mode".
3573
-** In other words, the database behaves has if
3574
-** [sqlite3_extended_result_codes(db,1)] where called on the database
3573
+** In other words, the database behaves as if
3574
+** [sqlite3_extended_result_codes(db,1)] were called on the database
35753575
** connection as soon as the connection is created. In addition to setting
35763576
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
35773577
** to return an extended result code.</dd>
35783578
**
35793579
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -6884,10 +6884,16 @@
68846884
** is not invoked when conflicting rows are deleted because of an
68856885
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
68866886
** invoked when rows are deleted using the [truncate optimization].
68876887
** The exceptions defined in this paragraph might change in a future
68886888
** release of SQLite.
6889
+**
6890
+** Whether the update hook is invoked before or after the
6891
+** corresponding change is currently unspecified and may differ
6892
+** depending on the type of change. Do not rely on the order of the
6893
+** hook call with regards to the final result of the operation which
6894
+** triggers the hook.
68896895
**
68906896
** The update hook implementation must not do anything that will modify
68916897
** the database connection that invoked the update hook. Any actions
68926898
** to modify the database connection must be deferred until after the
68936899
** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8355,11 +8361,11 @@
83558361
** by enclosing in double-quotes) so as not to confuse the parser.
83568362
**
83578363
** The sqlite3_keyword_count() interface returns the number of distinct
83588364
** keywords understood by SQLite.
83598365
**
8360
-** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
8366
+** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
83618367
** makes *Z point to that keyword expressed as UTF8 and writes the number
83628368
** of bytes in the keyword into *L. The string that *Z points to is not
83638369
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
83648370
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
83658371
** or L are NULL or invalid pointers then calls to
@@ -9934,27 +9940,48 @@
99349940
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
99359941
** is doing a GROUP BY.
99369942
** <li value="2"><p>
99379943
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
99389944
** that the query planner does not need the rows returned in any particular
9939
-** order, as long as rows with the same values in all "aOrderBy" columns
9940
-** are adjacent.)^ ^(Furthermore, only a single row for each particular
9941
-** combination of values in the columns identified by the "aOrderBy" field
9942
-** needs to be returned.)^ ^It is always ok for two or more rows with the same
9943
-** values in all "aOrderBy" columns to be returned, as long as all such rows
9944
-** are adjacent. ^The virtual table may, if it chooses, omit extra rows
9945
-** that have the same value for all columns identified by "aOrderBy".
9946
-** ^However omitting the extra rows is optional.
9945
+** order, as long as rows with the same values in all columns identified
9946
+** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
9947
+** contain the same values for all columns identified by "colUsed", all but
9948
+** one such row may optionally be omitted from the result.)^
9949
+** The virtual table is not required to omit rows that are duplicates
9950
+** over the "colUsed" columns, but if the virtual table can do that without
9951
+** too much extra effort, it could potentially help the query to run faster.
99479952
** This mode is used for a DISTINCT query.
99489953
** <li value="3"><p>
9949
-** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
9950
-** that the query planner needs only distinct rows but it does need the
9951
-** rows to be sorted.)^ ^The virtual table implementation is free to omit
9952
-** rows that are identical in all aOrderBy columns, if it wants to, but
9953
-** it is not required to omit any rows. This mode is used for queries
9954
+** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
9955
+** virtual table must return rows in the order defined by "aOrderBy" as
9956
+** if the sqlite3_vtab_distinct() interface had returned 0. However if
9957
+** two or more rows in the result have the same values for all columns
9958
+** identified by "colUsed", then all but one such row may optionally be
9959
+** omitted.)^ Like when the return value is 2, the virtual table
9960
+** is not required to omit rows that are duplicates over the "colUsed"
9961
+** columns, but if the virtual table can do that without
9962
+** too much extra effort, it could potentially help the query to run faster.
9963
+** This mode is used for queries
99549964
** that have both DISTINCT and ORDER BY clauses.
99559965
** </ol>
9966
+**
9967
+** <p>The following table summarizes the conditions under which the
9968
+** virtual table is allowed to set the "orderByConsumed" flag based on
9969
+** the value returned by sqlite3_vtab_distinct(). This table is a
9970
+** restatement of the previous four paragraphs:
9971
+**
9972
+** <table border=1 cellspacing=0 cellpadding=10 width="90%">
9973
+** <tr>
9974
+** <td valign="top">sqlite3_vtab_distinct() return value
9975
+** <td valign="top">Rows are returned in aOrderBy order
9976
+** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
9977
+** <td valign="top">Duplicates over all colUsed columns may be omitted
9978
+** <tr><td>0<td>yes<td>yes<td>no
9979
+** <tr><td>1<td>no<td>yes<td>no
9980
+** <tr><td>2<td>no<td>yes<td>yes
9981
+** <tr><td>3<td>yes<td>yes<td>yes
9982
+** </table>
99569983
**
99579984
** ^For the purposes of comparing virtual table output values to see if the
99589985
** values are same value for sorting purposes, two NULL values are considered
99599986
** to be the same. In other words, the comparison operator is "IS"
99609987
** (or "IS NOT DISTINCT FROM") and not "==".
@@ -10803,12 +10830,10 @@
1080310830
#endif
1080410831
1080510832
#if defined(__wasi__)
1080610833
# undef SQLITE_WASI
1080710834
# define SQLITE_WASI 1
10808
-# undef SQLITE_OMIT_WAL
10809
-# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
1081010835
# ifndef SQLITE_OMIT_LOAD_EXTENSION
1081110836
# define SQLITE_OMIT_LOAD_EXTENSION
1081210837
# endif
1081310838
# ifndef SQLITE_THREADSAFE
1081410839
# define SQLITE_THREADSAFE 0
@@ -11995,10 +12020,34 @@
1199512020
**
1199612021
** In all cases, if an error occurs the state of the final contents of the
1199712022
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
1199812023
*/
1199912024
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
12025
+
12026
+/*
12027
+** CAPI3REF: Add A Single Change To A Changegroup
12028
+** METHOD: sqlite3_changegroup
12029
+**
12030
+** This function adds the single change currently indicated by the iterator
12031
+** passed as the second argument to the changegroup object. The rules for
12032
+** adding the change are just as described for [sqlite3changegroup_add()].
12033
+**
12034
+** If the change is successfully added to the changegroup, SQLITE_OK is
12035
+** returned. Otherwise, an SQLite error code is returned.
12036
+**
12037
+** The iterator must point to a valid entry when this function is called.
12038
+** If it does not, SQLITE_ERROR is returned and no change is added to the
12039
+** changegroup. Additionally, the iterator must not have been opened with
12040
+** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
12041
+** returned.
12042
+*/
12043
+SQLITE_API int sqlite3changegroup_add_change(
12044
+ sqlite3_changegroup*,
12045
+ sqlite3_changeset_iter*
12046
+);
12047
+
12048
+
1200012049
1200112050
/*
1200212051
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
1200312052
** METHOD: sqlite3_changegroup
1200412053
**
@@ -12800,12 +12849,12 @@
1280012849
1280112850
/*
1280212851
** EXTENSION API FUNCTIONS
1280312852
**
1280412853
** xUserData(pFts):
12805
-** Return a copy of the context pointer the extension function was
12806
-** registered with.
12854
+** Return a copy of the pUserData pointer passed to the xCreateFunction()
12855
+** API when the extension function was registered.
1280712856
**
1280812857
** xColumnTotalSize(pFts, iCol, pnToken):
1280912858
** If parameter iCol is less than zero, set output variable *pnToken
1281012859
** to the total number of tokens in the FTS5 table. Or, if iCol is
1281112860
** non-negative but less than the number of columns in the table, return
@@ -12982,10 +13031,14 @@
1298213031
** This API can be quite slow if used with an FTS5 table created with the
1298313032
** "detail=none" or "detail=column" option. If the FTS5 table is created
1298413033
** with either "detail=none" or "detail=column" and "content=" option
1298513034
** (i.e. if it is a contentless table), then this API always iterates
1298613035
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
13036
+**
13037
+** In all cases, matches are visited in (column ASC, offset ASC) order.
13038
+** i.e. all those in column 0, sorted by offset, followed by those in
13039
+** column 1, etc.
1298713040
**
1298813041
** xPhraseNext()
1298913042
** See xPhraseFirst above.
1299013043
**
1299113044
** xPhraseFirstColumn()
1299213045
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -144,13 +144,13 @@
144 **
145 ** See also: [sqlite3_libversion()],
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.46.0"
150 #define SQLITE_VERSION_NUMBER 3046000
151 #define SQLITE_SOURCE_ID "2024-03-26 11:14:52 a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -770,12 +770,12 @@
770 ** xUnlock() downgrades the database file lock to either SHARED or NONE.
771 ** If the lock is already at or below the requested lock state, then the call
772 ** to xUnlock() is a no-op.
773 ** The xCheckReservedLock() method checks whether any database connection,
774 ** either in this process or in some other process, is holding a RESERVED,
775 ** PENDING, or EXCLUSIVE lock on the file. It returns true
776 ** if such a lock exists and false otherwise.
777 **
778 ** The xFileControl() method is a generic interface that allows custom
779 ** VFS implementations to directly control an open file using the
780 ** [sqlite3_file_control()] interface. The second "op" argument is an
781 ** integer opcode. The third argument is a generic pointer intended to
@@ -3568,12 +3568,12 @@
3568 ** the default shared cache setting provided by
3569 ** [sqlite3_enable_shared_cache()].)^
3570 **
3571 ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
3572 ** <dd>The database connection comes up in "extended result code mode".
3573 ** In other words, the database behaves has if
3574 ** [sqlite3_extended_result_codes(db,1)] where called on the database
3575 ** connection as soon as the connection is created. In addition to setting
3576 ** the extended result code mode, this flag also causes [sqlite3_open_v2()]
3577 ** to return an extended result code.</dd>
3578 **
3579 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -6884,10 +6884,16 @@
6884 ** is not invoked when conflicting rows are deleted because of an
6885 ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
6886 ** invoked when rows are deleted using the [truncate optimization].
6887 ** The exceptions defined in this paragraph might change in a future
6888 ** release of SQLite.
 
 
 
 
 
 
6889 **
6890 ** The update hook implementation must not do anything that will modify
6891 ** the database connection that invoked the update hook. Any actions
6892 ** to modify the database connection must be deferred until after the
6893 ** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8355,11 +8361,11 @@
8355 ** by enclosing in double-quotes) so as not to confuse the parser.
8356 **
8357 ** The sqlite3_keyword_count() interface returns the number of distinct
8358 ** keywords understood by SQLite.
8359 **
8360 ** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
8361 ** makes *Z point to that keyword expressed as UTF8 and writes the number
8362 ** of bytes in the keyword into *L. The string that *Z points to is not
8363 ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
8364 ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
8365 ** or L are NULL or invalid pointers then calls to
@@ -9934,27 +9940,48 @@
9934 ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
9935 ** is doing a GROUP BY.
9936 ** <li value="2"><p>
9937 ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
9938 ** that the query planner does not need the rows returned in any particular
9939 ** order, as long as rows with the same values in all "aOrderBy" columns
9940 ** are adjacent.)^ ^(Furthermore, only a single row for each particular
9941 ** combination of values in the columns identified by the "aOrderBy" field
9942 ** needs to be returned.)^ ^It is always ok for two or more rows with the same
9943 ** values in all "aOrderBy" columns to be returned, as long as all such rows
9944 ** are adjacent. ^The virtual table may, if it chooses, omit extra rows
9945 ** that have the same value for all columns identified by "aOrderBy".
9946 ** ^However omitting the extra rows is optional.
9947 ** This mode is used for a DISTINCT query.
9948 ** <li value="3"><p>
9949 ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
9950 ** that the query planner needs only distinct rows but it does need the
9951 ** rows to be sorted.)^ ^The virtual table implementation is free to omit
9952 ** rows that are identical in all aOrderBy columns, if it wants to, but
9953 ** it is not required to omit any rows. This mode is used for queries
 
 
 
 
 
9954 ** that have both DISTINCT and ORDER BY clauses.
9955 ** </ol>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9956 **
9957 ** ^For the purposes of comparing virtual table output values to see if the
9958 ** values are same value for sorting purposes, two NULL values are considered
9959 ** to be the same. In other words, the comparison operator is "IS"
9960 ** (or "IS NOT DISTINCT FROM") and not "==".
@@ -10803,12 +10830,10 @@
10803 #endif
10804
10805 #if defined(__wasi__)
10806 # undef SQLITE_WASI
10807 # define SQLITE_WASI 1
10808 # undef SQLITE_OMIT_WAL
10809 # define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
10810 # ifndef SQLITE_OMIT_LOAD_EXTENSION
10811 # define SQLITE_OMIT_LOAD_EXTENSION
10812 # endif
10813 # ifndef SQLITE_THREADSAFE
10814 # define SQLITE_THREADSAFE 0
@@ -11995,10 +12020,34 @@
11995 **
11996 ** In all cases, if an error occurs the state of the final contents of the
11997 ** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
11998 */
11999 SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12000
12001 /*
12002 ** CAPI3REF: Obtain A Composite Changeset From A Changegroup
12003 ** METHOD: sqlite3_changegroup
12004 **
@@ -12800,12 +12849,12 @@
12800
12801 /*
12802 ** EXTENSION API FUNCTIONS
12803 **
12804 ** xUserData(pFts):
12805 ** Return a copy of the context pointer the extension function was
12806 ** registered with.
12807 **
12808 ** xColumnTotalSize(pFts, iCol, pnToken):
12809 ** If parameter iCol is less than zero, set output variable *pnToken
12810 ** to the total number of tokens in the FTS5 table. Or, if iCol is
12811 ** non-negative but less than the number of columns in the table, return
@@ -12982,10 +13031,14 @@
12982 ** This API can be quite slow if used with an FTS5 table created with the
12983 ** "detail=none" or "detail=column" option. If the FTS5 table is created
12984 ** with either "detail=none" or "detail=column" and "content=" option
12985 ** (i.e. if it is a contentless table), then this API always iterates
12986 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
 
 
 
 
12987 **
12988 ** xPhraseNext()
12989 ** See xPhraseFirst above.
12990 **
12991 ** xPhraseFirstColumn()
12992
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -144,13 +144,13 @@
144 **
145 ** See also: [sqlite3_libversion()],
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.47.0"
150 #define SQLITE_VERSION_NUMBER 3047000
151 #define SQLITE_SOURCE_ID "2024-07-03 20:19:33 baa83b460c677c210c7fa3f20314d7e05f305aed8a69026bc5fa106a3de4ea38"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -770,12 +770,12 @@
770 ** xUnlock() downgrades the database file lock to either SHARED or NONE.
771 ** If the lock is already at or below the requested lock state, then the call
772 ** to xUnlock() is a no-op.
773 ** The xCheckReservedLock() method checks whether any database connection,
774 ** either in this process or in some other process, is holding a RESERVED,
775 ** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
776 ** pointer parameter, true if such a lock exists and false otherwise.
777 **
778 ** The xFileControl() method is a generic interface that allows custom
779 ** VFS implementations to directly control an open file using the
780 ** [sqlite3_file_control()] interface. The second "op" argument is an
781 ** integer opcode. The third argument is a generic pointer intended to
@@ -3568,12 +3568,12 @@
3568 ** the default shared cache setting provided by
3569 ** [sqlite3_enable_shared_cache()].)^
3570 **
3571 ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
3572 ** <dd>The database connection comes up in "extended result code mode".
3573 ** In other words, the database behaves as if
3574 ** [sqlite3_extended_result_codes(db,1)] were called on the database
3575 ** connection as soon as the connection is created. In addition to setting
3576 ** the extended result code mode, this flag also causes [sqlite3_open_v2()]
3577 ** to return an extended result code.</dd>
3578 **
3579 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
@@ -6884,10 +6884,16 @@
6884 ** is not invoked when conflicting rows are deleted because of an
6885 ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
6886 ** invoked when rows are deleted using the [truncate optimization].
6887 ** The exceptions defined in this paragraph might change in a future
6888 ** release of SQLite.
6889 **
6890 ** Whether the update hook is invoked before or after the
6891 ** corresponding change is currently unspecified and may differ
6892 ** depending on the type of change. Do not rely on the order of the
6893 ** hook call with regards to the final result of the operation which
6894 ** triggers the hook.
6895 **
6896 ** The update hook implementation must not do anything that will modify
6897 ** the database connection that invoked the update hook. Any actions
6898 ** to modify the database connection must be deferred until after the
6899 ** completion of the [sqlite3_step()] call that triggered the update hook.
@@ -8355,11 +8361,11 @@
8361 ** by enclosing in double-quotes) so as not to confuse the parser.
8362 **
8363 ** The sqlite3_keyword_count() interface returns the number of distinct
8364 ** keywords understood by SQLite.
8365 **
8366 ** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
8367 ** makes *Z point to that keyword expressed as UTF8 and writes the number
8368 ** of bytes in the keyword into *L. The string that *Z points to is not
8369 ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
8370 ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
8371 ** or L are NULL or invalid pointers then calls to
@@ -9934,27 +9940,48 @@
9940 ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
9941 ** is doing a GROUP BY.
9942 ** <li value="2"><p>
9943 ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
9944 ** that the query planner does not need the rows returned in any particular
9945 ** order, as long as rows with the same values in all columns identified
9946 ** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
9947 ** contain the same values for all columns identified by "colUsed", all but
9948 ** one such row may optionally be omitted from the result.)^
9949 ** The virtual table is not required to omit rows that are duplicates
9950 ** over the "colUsed" columns, but if the virtual table can do that without
9951 ** too much extra effort, it could potentially help the query to run faster.
 
9952 ** This mode is used for a DISTINCT query.
9953 ** <li value="3"><p>
9954 ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
9955 ** virtual table must return rows in the order defined by "aOrderBy" as
9956 ** if the sqlite3_vtab_distinct() interface had returned 0. However if
9957 ** two or more rows in the result have the same values for all columns
9958 ** identified by "colUsed", then all but one such row may optionally be
9959 ** omitted.)^ Like when the return value is 2, the virtual table
9960 ** is not required to omit rows that are duplicates over the "colUsed"
9961 ** columns, but if the virtual table can do that without
9962 ** too much extra effort, it could potentially help the query to run faster.
9963 ** This mode is used for queries
9964 ** that have both DISTINCT and ORDER BY clauses.
9965 ** </ol>
9966 **
9967 ** <p>The following table summarizes the conditions under which the
9968 ** virtual table is allowed to set the "orderByConsumed" flag based on
9969 ** the value returned by sqlite3_vtab_distinct(). This table is a
9970 ** restatement of the previous four paragraphs:
9971 **
9972 ** <table border=1 cellspacing=0 cellpadding=10 width="90%">
9973 ** <tr>
9974 ** <td valign="top">sqlite3_vtab_distinct() return value
9975 ** <td valign="top">Rows are returned in aOrderBy order
9976 ** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
9977 ** <td valign="top">Duplicates over all colUsed columns may be omitted
9978 ** <tr><td>0<td>yes<td>yes<td>no
9979 ** <tr><td>1<td>no<td>yes<td>no
9980 ** <tr><td>2<td>no<td>yes<td>yes
9981 ** <tr><td>3<td>yes<td>yes<td>yes
9982 ** </table>
9983 **
9984 ** ^For the purposes of comparing virtual table output values to see if the
9985 ** values are same value for sorting purposes, two NULL values are considered
9986 ** to be the same. In other words, the comparison operator is "IS"
9987 ** (or "IS NOT DISTINCT FROM") and not "==".
@@ -10803,12 +10830,10 @@
10830 #endif
10831
10832 #if defined(__wasi__)
10833 # undef SQLITE_WASI
10834 # define SQLITE_WASI 1
 
 
10835 # ifndef SQLITE_OMIT_LOAD_EXTENSION
10836 # define SQLITE_OMIT_LOAD_EXTENSION
10837 # endif
10838 # ifndef SQLITE_THREADSAFE
10839 # define SQLITE_THREADSAFE 0
@@ -11995,10 +12020,34 @@
12020 **
12021 ** In all cases, if an error occurs the state of the final contents of the
12022 ** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
12023 */
12024 SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
12025
12026 /*
12027 ** CAPI3REF: Add A Single Change To A Changegroup
12028 ** METHOD: sqlite3_changegroup
12029 **
12030 ** This function adds the single change currently indicated by the iterator
12031 ** passed as the second argument to the changegroup object. The rules for
12032 ** adding the change are just as described for [sqlite3changegroup_add()].
12033 **
12034 ** If the change is successfully added to the changegroup, SQLITE_OK is
12035 ** returned. Otherwise, an SQLite error code is returned.
12036 **
12037 ** The iterator must point to a valid entry when this function is called.
12038 ** If it does not, SQLITE_ERROR is returned and no change is added to the
12039 ** changegroup. Additionally, the iterator must not have been opened with
12040 ** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
12041 ** returned.
12042 */
12043 SQLITE_API int sqlite3changegroup_add_change(
12044 sqlite3_changegroup*,
12045 sqlite3_changeset_iter*
12046 );
12047
12048
12049
12050 /*
12051 ** CAPI3REF: Obtain A Composite Changeset From A Changegroup
12052 ** METHOD: sqlite3_changegroup
12053 **
@@ -12800,12 +12849,12 @@
12849
12850 /*
12851 ** EXTENSION API FUNCTIONS
12852 **
12853 ** xUserData(pFts):
12854 ** Return a copy of the pUserData pointer passed to the xCreateFunction()
12855 ** API when the extension function was registered.
12856 **
12857 ** xColumnTotalSize(pFts, iCol, pnToken):
12858 ** If parameter iCol is less than zero, set output variable *pnToken
12859 ** to the total number of tokens in the FTS5 table. Or, if iCol is
12860 ** non-negative but less than the number of columns in the table, return
@@ -12982,10 +13031,14 @@
13031 ** This API can be quite slow if used with an FTS5 table created with the
13032 ** "detail=none" or "detail=column" option. If the FTS5 table is created
13033 ** with either "detail=none" or "detail=column" and "content=" option
13034 ** (i.e. if it is a contentless table), then this API always iterates
13035 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
13036 **
13037 ** In all cases, matches are visited in (column ASC, offset ASC) order.
13038 ** i.e. all those in column 0, sorted by offset, followed by those in
13039 ** column 1, etc.
13040 **
13041 ** xPhraseNext()
13042 ** See xPhraseFirst above.
13043 **
13044 ** xPhraseFirstColumn()
13045
+4 -2
--- src/add.c
+++ src/add.c
@@ -447,11 +447,11 @@
447447
if( isDir==1 ){
448448
vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
449449
}else if( isDir==0 ){
450450
fossil_warning("not found: %s", zName);
451451
}else{
452
- char *zTreeName = &zName[nRoot];
452
+ char *zTreeName = file_case_preferred_name(g.zLocalRoot,&zName[nRoot]);
453453
if( !forceFlag && glob_match(pIgnore, zTreeName) ){
454454
Blob ans;
455455
char cReply;
456456
char *prompt = mprintf("file \"%s\" matches \"ignore-glob\". "
457457
"Add it (a=all/y/N)? ", zTreeName);
@@ -468,10 +468,11 @@
468468
}
469469
db_multi_exec(
470470
"INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)",
471471
zTreeName
472472
);
473
+ fossil_free(zTreeName);
473474
}
474475
blob_reset(&fullName);
475476
}
476477
glob_free(pIgnore);
477478
glob_free(pClean);
@@ -1056,11 +1057,11 @@
10561057
fossil_fatal("no check-out in which to rename files");
10571058
}
10581059
if( g.argc<4 ){
10591060
usage("OLDNAME NEWNAME");
10601061
}
1061
- zDest = g.argv[g.argc-1];
1062
+ zDest = file_case_preferred_name(".",g.argv[g.argc-1]);
10621063
db_begin_transaction();
10631064
if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
10641065
moveFiles = 0;
10651066
}else if( softFlag ){
10661067
moveFiles = 0;
@@ -1142,14 +1143,15 @@
11421143
}
11431144
db_finalize(&q);
11441145
undo_reset();
11451146
db_end_transaction(0);
11461147
if( moveFiles ) process_files_to_move(dryRunFlag);
1148
+ fossil_free(zDest);
11471149
}
11481150
11491151
/*
11501152
** Function for stash_apply to be able to restore a file and indicate
11511153
** newly ADDED state.
11521154
*/
11531155
int stash_add_files_in_sfile(int vid){
11541156
return add_files_in_sfile(vid);
11551157
}
11561158
--- src/add.c
+++ src/add.c
@@ -447,11 +447,11 @@
447 if( isDir==1 ){
448 vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
449 }else if( isDir==0 ){
450 fossil_warning("not found: %s", zName);
451 }else{
452 char *zTreeName = &zName[nRoot];
453 if( !forceFlag && glob_match(pIgnore, zTreeName) ){
454 Blob ans;
455 char cReply;
456 char *prompt = mprintf("file \"%s\" matches \"ignore-glob\". "
457 "Add it (a=all/y/N)? ", zTreeName);
@@ -468,10 +468,11 @@
468 }
469 db_multi_exec(
470 "INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)",
471 zTreeName
472 );
 
473 }
474 blob_reset(&fullName);
475 }
476 glob_free(pIgnore);
477 glob_free(pClean);
@@ -1056,11 +1057,11 @@
1056 fossil_fatal("no check-out in which to rename files");
1057 }
1058 if( g.argc<4 ){
1059 usage("OLDNAME NEWNAME");
1060 }
1061 zDest = g.argv[g.argc-1];
1062 db_begin_transaction();
1063 if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
1064 moveFiles = 0;
1065 }else if( softFlag ){
1066 moveFiles = 0;
@@ -1142,14 +1143,15 @@
1142 }
1143 db_finalize(&q);
1144 undo_reset();
1145 db_end_transaction(0);
1146 if( moveFiles ) process_files_to_move(dryRunFlag);
 
1147 }
1148
1149 /*
1150 ** Function for stash_apply to be able to restore a file and indicate
1151 ** newly ADDED state.
1152 */
1153 int stash_add_files_in_sfile(int vid){
1154 return add_files_in_sfile(vid);
1155 }
1156
--- src/add.c
+++ src/add.c
@@ -447,11 +447,11 @@
447 if( isDir==1 ){
448 vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
449 }else if( isDir==0 ){
450 fossil_warning("not found: %s", zName);
451 }else{
452 char *zTreeName = file_case_preferred_name(g.zLocalRoot,&zName[nRoot]);
453 if( !forceFlag && glob_match(pIgnore, zTreeName) ){
454 Blob ans;
455 char cReply;
456 char *prompt = mprintf("file \"%s\" matches \"ignore-glob\". "
457 "Add it (a=all/y/N)? ", zTreeName);
@@ -468,10 +468,11 @@
468 }
469 db_multi_exec(
470 "INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)",
471 zTreeName
472 );
473 fossil_free(zTreeName);
474 }
475 blob_reset(&fullName);
476 }
477 glob_free(pIgnore);
478 glob_free(pClean);
@@ -1056,11 +1057,11 @@
1057 fossil_fatal("no check-out in which to rename files");
1058 }
1059 if( g.argc<4 ){
1060 usage("OLDNAME NEWNAME");
1061 }
1062 zDest = file_case_preferred_name(".",g.argv[g.argc-1]);
1063 db_begin_transaction();
1064 if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
1065 moveFiles = 0;
1066 }else if( softFlag ){
1067 moveFiles = 0;
@@ -1142,14 +1143,15 @@
1143 }
1144 db_finalize(&q);
1145 undo_reset();
1146 db_end_transaction(0);
1147 if( moveFiles ) process_files_to_move(dryRunFlag);
1148 fossil_free(zDest);
1149 }
1150
1151 /*
1152 ** Function for stash_apply to be able to restore a file and indicate
1153 ** newly ADDED state.
1154 */
1155 int stash_add_files_in_sfile(int vid){
1156 return add_files_in_sfile(vid);
1157 }
1158
+1 -1
--- src/alerts.c
+++ src/alerts.c
@@ -327,11 +327,11 @@
327327
login_insert_csrf_secret();
328328
329329
entry_attribute("Canonical Server URL", 40, "email-url",
330330
"eurl", "", 0);
331331
@ <p><b>Required.</b>
332
- @ This is URL used as the basename for hyperlinks included in
332
+ @ This URL is used as the basename for hyperlinks included in
333333
@ email alert text. Omit the trailing "/".
334334
@ Suggested value: "%h(g.zBaseURL)"
335335
@ (Property: "email-url")</p>
336336
@ <hr>
337337
338338
--- src/alerts.c
+++ src/alerts.c
@@ -327,11 +327,11 @@
327 login_insert_csrf_secret();
328
329 entry_attribute("Canonical Server URL", 40, "email-url",
330 "eurl", "", 0);
331 @ <p><b>Required.</b>
332 @ This is URL used as the basename for hyperlinks included in
333 @ email alert text. Omit the trailing "/".
334 @ Suggested value: "%h(g.zBaseURL)"
335 @ (Property: "email-url")</p>
336 @ <hr>
337
338
--- src/alerts.c
+++ src/alerts.c
@@ -327,11 +327,11 @@
327 login_insert_csrf_secret();
328
329 entry_attribute("Canonical Server URL", 40, "email-url",
330 "eurl", "", 0);
331 @ <p><b>Required.</b>
332 @ This URL is used as the basename for hyperlinks included in
333 @ email alert text. Omit the trailing "/".
334 @ Suggested value: "%h(g.zBaseURL)"
335 @ (Property: "email-url")</p>
336 @ <hr>
337
338
+18
--- src/bisect.c
+++ src/bisect.c
@@ -390,10 +390,12 @@
390390
** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
391391
**
392392
** Options:
393393
** -i|--interactive Prompt user for decisions rather than
394394
** using the return code from COMMAND
395
+** --ii Like -i but also pause after showing
396
+** the status after each step.
395397
*/
396398
static void bisect_run(void){
397399
const char *zCmd;
398400
int isInteractive = 0;
399401
int i;
@@ -404,10 +406,14 @@
404406
const char *zArg = g.argv[i];
405407
if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
406408
if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){
407409
isInteractive = 1;
408410
continue;
411
+ }
412
+ if( strcmp(zArg, "-ii")==0 ){
413
+ isInteractive = 2;
414
+ continue;
409415
}
410416
fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]);
411417
}
412418
zCmd = g.argv[i];
413419
if( db_int(0, "SELECT count(*) FROM vvar"
@@ -460,10 +466,22 @@
460466
blob_append(&cmd, " bisect bad", -1);
461467
}
462468
fossil_print("%s\n", blob_str(&cmd));
463469
fossil_system(blob_str(&cmd));
464470
blob_reset(&cmd);
471
+ if( isInteractive>=2 && db_lget_int("bisect-complete", 0)==0 ){
472
+ int n;
473
+ char *z;
474
+ Blob in;
475
+ int bContinue = 1;
476
+ prompt_user("Run testcase again? (Y)es or No: ", &in);
477
+ n = blob_size(&in);
478
+ z = blob_str(&in);
479
+ if( n>0 && sqlite3_strnicmp("no", z, n)==0 ) bContinue = 0;
480
+ blob_reset(&in);
481
+ if( !bContinue ) break;
482
+ }
465483
}
466484
}
467485
468486
/*
469487
** COMMAND: bisect
470488
--- src/bisect.c
+++ src/bisect.c
@@ -390,10 +390,12 @@
390 ** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
391 **
392 ** Options:
393 ** -i|--interactive Prompt user for decisions rather than
394 ** using the return code from COMMAND
 
 
395 */
396 static void bisect_run(void){
397 const char *zCmd;
398 int isInteractive = 0;
399 int i;
@@ -404,10 +406,14 @@
404 const char *zArg = g.argv[i];
405 if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
406 if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){
407 isInteractive = 1;
408 continue;
 
 
 
 
409 }
410 fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]);
411 }
412 zCmd = g.argv[i];
413 if( db_int(0, "SELECT count(*) FROM vvar"
@@ -460,10 +466,22 @@
460 blob_append(&cmd, " bisect bad", -1);
461 }
462 fossil_print("%s\n", blob_str(&cmd));
463 fossil_system(blob_str(&cmd));
464 blob_reset(&cmd);
 
 
 
 
 
 
 
 
 
 
 
 
465 }
466 }
467
468 /*
469 ** COMMAND: bisect
470
--- src/bisect.c
+++ src/bisect.c
@@ -390,10 +390,12 @@
390 ** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
391 **
392 ** Options:
393 ** -i|--interactive Prompt user for decisions rather than
394 ** using the return code from COMMAND
395 ** --ii Like -i but also pause after showing
396 ** the status after each step.
397 */
398 static void bisect_run(void){
399 const char *zCmd;
400 int isInteractive = 0;
401 int i;
@@ -404,10 +406,14 @@
406 const char *zArg = g.argv[i];
407 if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
408 if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){
409 isInteractive = 1;
410 continue;
411 }
412 if( strcmp(zArg, "-ii")==0 ){
413 isInteractive = 2;
414 continue;
415 }
416 fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]);
417 }
418 zCmd = g.argv[i];
419 if( db_int(0, "SELECT count(*) FROM vvar"
@@ -460,10 +466,22 @@
466 blob_append(&cmd, " bisect bad", -1);
467 }
468 fossil_print("%s\n", blob_str(&cmd));
469 fossil_system(blob_str(&cmd));
470 blob_reset(&cmd);
471 if( isInteractive>=2 && db_lget_int("bisect-complete", 0)==0 ){
472 int n;
473 char *z;
474 Blob in;
475 int bContinue = 1;
476 prompt_user("Run testcase again? (Y)es or No: ", &in);
477 n = blob_size(&in);
478 z = blob_str(&in);
479 if( n>0 && sqlite3_strnicmp("no", z, n)==0 ) bContinue = 0;
480 blob_reset(&in);
481 if( !bContinue ) break;
482 }
483 }
484 }
485
486 /*
487 ** COMMAND: bisect
488
+2 -8
--- src/branch.c
+++ src/branch.c
@@ -81,18 +81,14 @@
8181
Manifest *pParent; /* Parsed parent manifest */
8282
Blob mcksum; /* Self-checksum on the manifest */
8383
const char *zDateOvrd; /* Override date string */
8484
const char *zUserOvrd; /* Override user name */
8585
int isPrivate = 0; /* True if the branch should be private */
86
- int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
8786
8887
noSign = find_option("nosign","",0)!=0;
88
+ if( find_option("nosync",0,0) ) g.fNoSync = 1;
8989
zColor = find_option("bgcolor","c",1);
90
- if( fossil_strncmp(zColor, "auto", 4)==0 ) {
91
- bAutoColor = 1;
92
- zColor = 0;
93
- }
9490
isPrivate = find_option("private",0,0)!=0;
9591
zDateOvrd = find_option("date-override",0,1);
9692
zUserOvrd = find_option("user-override",0,1);
9793
verify_all_options();
9894
if( g.argc<5 ){
@@ -152,11 +148,10 @@
152148
manifest_destroy(pParent);
153149
154150
/* Add the symbolic branch name and the "branch" tag to identify
155151
** this as a new branch */
156152
if( content_is_private(rootid) ) isPrivate = 1;
157
- if( isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
158153
if( zColor!=0 ){
159154
blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
160155
}
161156
blob_appendf(&branch, "T *branch * %F\n", zBranch);
162157
blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -665,13 +660,12 @@
665660
** Create a new branch BRANCH-NAME off of check-in BASIS.
666661
**
667662
** Options:
668663
** --private Branch is private (i.e., remains local)
669664
** --bgcolor COLOR Use COLOR instead of automatic background
670
-** ("auto" lets Fossil choose it automatically,
671
-** even for private branches)
672665
** --nosign Do not sign contents on this branch
666
+** --nosync Do not auto-sync prior to creating the branch
673667
** --date-override DATE DATE to use instead of 'now'
674668
** --user-override USER USER to use instead of the current default
675669
**
676670
** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
677671
** year-month-day form, it may be truncated, the "T" may be
678672
--- src/branch.c
+++ src/branch.c
@@ -81,18 +81,14 @@
81 Manifest *pParent; /* Parsed parent manifest */
82 Blob mcksum; /* Self-checksum on the manifest */
83 const char *zDateOvrd; /* Override date string */
84 const char *zUserOvrd; /* Override user name */
85 int isPrivate = 0; /* True if the branch should be private */
86 int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
87
88 noSign = find_option("nosign","",0)!=0;
 
89 zColor = find_option("bgcolor","c",1);
90 if( fossil_strncmp(zColor, "auto", 4)==0 ) {
91 bAutoColor = 1;
92 zColor = 0;
93 }
94 isPrivate = find_option("private",0,0)!=0;
95 zDateOvrd = find_option("date-override",0,1);
96 zUserOvrd = find_option("user-override",0,1);
97 verify_all_options();
98 if( g.argc<5 ){
@@ -152,11 +148,10 @@
152 manifest_destroy(pParent);
153
154 /* Add the symbolic branch name and the "branch" tag to identify
155 ** this as a new branch */
156 if( content_is_private(rootid) ) isPrivate = 1;
157 if( isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
158 if( zColor!=0 ){
159 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
160 }
161 blob_appendf(&branch, "T *branch * %F\n", zBranch);
162 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -665,13 +660,12 @@
665 ** Create a new branch BRANCH-NAME off of check-in BASIS.
666 **
667 ** Options:
668 ** --private Branch is private (i.e., remains local)
669 ** --bgcolor COLOR Use COLOR instead of automatic background
670 ** ("auto" lets Fossil choose it automatically,
671 ** even for private branches)
672 ** --nosign Do not sign contents on this branch
 
673 ** --date-override DATE DATE to use instead of 'now'
674 ** --user-override USER USER to use instead of the current default
675 **
676 ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
677 ** year-month-day form, it may be truncated, the "T" may be
678
--- src/branch.c
+++ src/branch.c
@@ -81,18 +81,14 @@
81 Manifest *pParent; /* Parsed parent manifest */
82 Blob mcksum; /* Self-checksum on the manifest */
83 const char *zDateOvrd; /* Override date string */
84 const char *zUserOvrd; /* Override user name */
85 int isPrivate = 0; /* True if the branch should be private */
 
86
87 noSign = find_option("nosign","",0)!=0;
88 if( find_option("nosync",0,0) ) g.fNoSync = 1;
89 zColor = find_option("bgcolor","c",1);
 
 
 
 
90 isPrivate = find_option("private",0,0)!=0;
91 zDateOvrd = find_option("date-override",0,1);
92 zUserOvrd = find_option("user-override",0,1);
93 verify_all_options();
94 if( g.argc<5 ){
@@ -152,11 +148,10 @@
148 manifest_destroy(pParent);
149
150 /* Add the symbolic branch name and the "branch" tag to identify
151 ** this as a new branch */
152 if( content_is_private(rootid) ) isPrivate = 1;
 
153 if( zColor!=0 ){
154 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
155 }
156 blob_appendf(&branch, "T *branch * %F\n", zBranch);
157 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -665,13 +660,12 @@
660 ** Create a new branch BRANCH-NAME off of check-in BASIS.
661 **
662 ** Options:
663 ** --private Branch is private (i.e., remains local)
664 ** --bgcolor COLOR Use COLOR instead of automatic background
 
 
665 ** --nosign Do not sign contents on this branch
666 ** --nosync Do not auto-sync prior to creating the branch
667 ** --date-override DATE DATE to use instead of 'now'
668 ** --user-override USER USER to use instead of the current default
669 **
670 ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
671 ** year-month-day form, it may be truncated, the "T" may be
672
+13 -6
--- src/browse.c
+++ src/browse.c
@@ -860,17 +860,24 @@
860860
}
861861
db_finalize(&q);
862862
}else{
863863
Stmt q;
864864
db_prepare(&q,
865
+ "WITH mx(fnid,fid,mtime) AS (\n"
866
+ " SELECT fnid, fid, max(event.mtime)\n"
867
+ " FROM mlink, event\n"
868
+ " WHERE event.objid=mlink.mid\n"
869
+ " GROUP BY 1\n"
870
+ ")\n"
865871
"SELECT\n"
866
- " (SELECT name FROM filename WHERE filename.fnid=mlink.fnid),\n"
867
- " (SELECT uuid FROM blob WHERE blob.rid=mlink.fid),\n"
868
- " (SELECT size FROM blob WHERE blob.rid=mlink.fid),\n"
869
- " max(event.mtime)\n"
870
- " FROM mlink JOIN event ON event.objid=mlink.mid\n"
871
- " GROUP BY mlink.fnid\n"
872
+ " filename.name,\n"
873
+ " blob.uuid,\n"
874
+ " blob.size,\n"
875
+ " mx.mtime\n"
876
+ "FROM mx\n"
877
+ " LEFT JOIN filename ON filename.fnid=mx.fnid\n"
878
+ " LEFT JOIN blob ON blob.rid=mx.fid\n"
872879
" ORDER BY 1 COLLATE uintnocase;");
873880
while( db_step(&q)==SQLITE_ROW ){
874881
const char *zName = db_column_text(&q, 0);
875882
const char *zUuid = db_column_text(&q,1);
876883
int size = db_column_int(&q,2);
877884
--- src/browse.c
+++ src/browse.c
@@ -860,17 +860,24 @@
860 }
861 db_finalize(&q);
862 }else{
863 Stmt q;
864 db_prepare(&q,
 
 
 
 
 
 
865 "SELECT\n"
866 " (SELECT name FROM filename WHERE filename.fnid=mlink.fnid),\n"
867 " (SELECT uuid FROM blob WHERE blob.rid=mlink.fid),\n"
868 " (SELECT size FROM blob WHERE blob.rid=mlink.fid),\n"
869 " max(event.mtime)\n"
870 " FROM mlink JOIN event ON event.objid=mlink.mid\n"
871 " GROUP BY mlink.fnid\n"
 
872 " ORDER BY 1 COLLATE uintnocase;");
873 while( db_step(&q)==SQLITE_ROW ){
874 const char *zName = db_column_text(&q, 0);
875 const char *zUuid = db_column_text(&q,1);
876 int size = db_column_int(&q,2);
877
--- src/browse.c
+++ src/browse.c
@@ -860,17 +860,24 @@
860 }
861 db_finalize(&q);
862 }else{
863 Stmt q;
864 db_prepare(&q,
865 "WITH mx(fnid,fid,mtime) AS (\n"
866 " SELECT fnid, fid, max(event.mtime)\n"
867 " FROM mlink, event\n"
868 " WHERE event.objid=mlink.mid\n"
869 " GROUP BY 1\n"
870 ")\n"
871 "SELECT\n"
872 " filename.name,\n"
873 " blob.uuid,\n"
874 " blob.size,\n"
875 " mx.mtime\n"
876 "FROM mx\n"
877 " LEFT JOIN filename ON filename.fnid=mx.fnid\n"
878 " LEFT JOIN blob ON blob.rid=mx.fid\n"
879 " ORDER BY 1 COLLATE uintnocase;");
880 while( db_step(&q)==SQLITE_ROW ){
881 const char *zName = db_column_text(&q, 0);
882 const char *zUuid = db_column_text(&q,1);
883 int size = db_column_int(&q,2);
884
+3 -3
--- src/bundle.c
+++ src/bundle.c
@@ -146,11 +146,11 @@
146146
}
147147
148148
/*
149149
** Implement the "fossil bundle append BUNDLE FILE..." command. Add
150150
** the named files into the BUNDLE. Create the BUNDLE if it does not
151
-** alraedy exist.
151
+** already exist.
152152
*/
153153
static void bundle_append_cmd(void){
154154
Blob content, hash;
155155
int i;
156156
Stmt q;
@@ -539,11 +539,11 @@
539539
static void bundle_cat_cmd(void){
540540
int i;
541541
Blob x;
542542
verify_all_options();
543543
if( g.argc<5 ) usage("cat BUNDLE HASH...");
544
- bundle_attach_file(g.argv[3], "b1", 1);
544
+ bundle_attach_file(g.argv[3], "b1", 0);
545545
blob_zero(&x);
546546
for(i=4; i<g.argc; i++){
547547
int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548548
g.argv[i]);
549549
if( blobid==0 ){
@@ -569,11 +569,11 @@
569569
int forceFlag = find_option("force","f",0)!=0;
570570
int isPriv = find_option("publish",0,0)==0;
571571
char *zMissingDeltas;
572572
verify_all_options();
573573
if ( g.argc!=4 ) usage("import BUNDLE ?OPTIONS?");
574
- bundle_attach_file(g.argv[3], "b1", 1);
574
+ bundle_attach_file(g.argv[3], "b1", 0);
575575
576576
/* Only import a bundle that was generated from a repo with the same
577577
** project code, unless the --force flag is true */
578578
if( !forceFlag ){
579579
if( !db_exists("SELECT 1 FROM config, bconfig"
580580
--- src/bundle.c
+++ src/bundle.c
@@ -146,11 +146,11 @@
146 }
147
148 /*
149 ** Implement the "fossil bundle append BUNDLE FILE..." command. Add
150 ** the named files into the BUNDLE. Create the BUNDLE if it does not
151 ** alraedy exist.
152 */
153 static void bundle_append_cmd(void){
154 Blob content, hash;
155 int i;
156 Stmt q;
@@ -539,11 +539,11 @@
539 static void bundle_cat_cmd(void){
540 int i;
541 Blob x;
542 verify_all_options();
543 if( g.argc<5 ) usage("cat BUNDLE HASH...");
544 bundle_attach_file(g.argv[3], "b1", 1);
545 blob_zero(&x);
546 for(i=4; i<g.argc; i++){
547 int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548 g.argv[i]);
549 if( blobid==0 ){
@@ -569,11 +569,11 @@
569 int forceFlag = find_option("force","f",0)!=0;
570 int isPriv = find_option("publish",0,0)==0;
571 char *zMissingDeltas;
572 verify_all_options();
573 if ( g.argc!=4 ) usage("import BUNDLE ?OPTIONS?");
574 bundle_attach_file(g.argv[3], "b1", 1);
575
576 /* Only import a bundle that was generated from a repo with the same
577 ** project code, unless the --force flag is true */
578 if( !forceFlag ){
579 if( !db_exists("SELECT 1 FROM config, bconfig"
580
--- src/bundle.c
+++ src/bundle.c
@@ -146,11 +146,11 @@
146 }
147
148 /*
149 ** Implement the "fossil bundle append BUNDLE FILE..." command. Add
150 ** the named files into the BUNDLE. Create the BUNDLE if it does not
151 ** already exist.
152 */
153 static void bundle_append_cmd(void){
154 Blob content, hash;
155 int i;
156 Stmt q;
@@ -539,11 +539,11 @@
539 static void bundle_cat_cmd(void){
540 int i;
541 Blob x;
542 verify_all_options();
543 if( g.argc<5 ) usage("cat BUNDLE HASH...");
544 bundle_attach_file(g.argv[3], "b1", 0);
545 blob_zero(&x);
546 for(i=4; i<g.argc; i++){
547 int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548 g.argv[i]);
549 if( blobid==0 ){
@@ -569,11 +569,11 @@
569 int forceFlag = find_option("force","f",0)!=0;
570 int isPriv = find_option("publish",0,0)==0;
571 char *zMissingDeltas;
572 verify_all_options();
573 if ( g.argc!=4 ) usage("import BUNDLE ?OPTIONS?");
574 bundle_attach_file(g.argv[3], "b1", 0);
575
576 /* Only import a bundle that was generated from a repo with the same
577 ** project code, unless the --force flag is true */
578 if( !forceFlag ){
579 if( !db_exists("SELECT 1 FROM config, bconfig"
580
+41 -14
--- src/cgi.c
+++ src/cgi.c
@@ -1238,11 +1238,11 @@
12381238
}
12391239
fputs(z, pLog);
12401240
}
12411241
12421242
/* Forward declaration */
1243
-static NORETURN void malformed_request(const char *zMsg);
1243
+static NORETURN void malformed_request(const char *zMsg, ...);
12441244
12451245
/*
12461246
** Checks the QUERY_STRING environment variable, sets it up
12471247
** via add_param_list() and, if found, applies its "skin"
12481248
** setting. Returns 0 if no QUERY_STRING is set, 1 if it is,
@@ -1321,10 +1321,11 @@
13211321
char *zSemi;
13221322
int len;
13231323
const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
13241324
const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
13251325
const char *zPathInfo = cgi_parameter("PATH_INFO",0);
1326
+ const char *zContentLength = 0;
13261327
#ifdef _WIN32
13271328
const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0);
13281329
#endif
13291330
13301331
#ifdef FOSSIL_ENABLE_JSON
@@ -1418,11 +1419,19 @@
14181419
z = (char*)P("REMOTE_ADDR");
14191420
if( z ){
14201421
g.zIpAddr = fossil_strdup(z);
14211422
}
14221423
1423
- len = atoi(PD("CONTENT_LENGTH", "0"));
1424
+ zContentLength = P("CONTENT_LENGTH");
1425
+ if( zContentLength==0 ){
1426
+ len = 0;
1427
+ if( sqlite3_stricmp(PD("REQUEST_METHOD",""),"POST")==0 ){
1428
+ malformed_request("missing CONTENT_LENGTH on a POST method");
1429
+ }
1430
+ }else{
1431
+ len = atoi(zContentLength);
1432
+ }
14241433
zType = P("CONTENT_TYPE");
14251434
zSemi = zType ? strchr(zType, ';') : 0;
14261435
if( zSemi ){
14271436
g.zContentType = fossil_strndup(zType, (int)(zSemi-zType));
14281437
zType = g.zContentType;
@@ -1767,10 +1776,11 @@
17671776
"FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR",
17681777
"TEMP", "TMP", "FOSSIL_VFS",
17691778
"FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION",
17701779
"FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS",
17711780
"TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST",
1781
+ "CONTENT_TYPE", "CONTENT_LENGTH",
17721782
};
17731783
int i;
17741784
for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
17751785
}
17761786
@@ -1811,11 +1821,11 @@
18111821
case 2: {
18121822
cgi_debug("%s = %s\n", zName, zValue);
18131823
break;
18141824
}
18151825
case 3: {
1816
- if( strlen(zValue)>100 ){
1826
+ if( zValue!=0 && strlen(zValue)>100 ){
18171827
fprintf(out,"%s = %.100s...\n", zName, zValue);
18181828
}else{
18191829
fprintf(out,"%s = %s\n", zName, zValue);
18201830
}
18211831
break;
@@ -1911,15 +1921,26 @@
19111921
19121922
19131923
/*
19141924
** Send a reply indicating that the HTTP request was malformed
19151925
*/
1916
-static NORETURN void malformed_request(const char *zMsg){
1917
- cgi_set_status(501, "Not Implemented");
1918
- cgi_printf(
1919
- "<html><body><p>Bad Request: %s</p></body></html>\n", zMsg
1920
- );
1926
+static NORETURN void malformed_request(const char *zMsg, ...){
1927
+ va_list ap;
1928
+ char *z;
1929
+ va_start(ap, zMsg);
1930
+ z = vmprintf(zMsg, ap);
1931
+ va_end(ap);
1932
+ cgi_set_status(400, "Bad Request");
1933
+ zContentType = "text/plain";
1934
+ if( g.zReqType==0 ) g.zReqType = "WWW";
1935
+ if( g.zReqType[0]=='C' && PD("SERVER_SOFTWARE",0)!=0 ){
1936
+ const char *zServer = PD("SERVER_SOFTWARE","");
1937
+ cgi_printf("Bad CGI Request from \"%s\": %s\n",zServer,z);
1938
+ }else{
1939
+ cgi_printf("Bad %s Request: %s\n", g.zReqType, z);
1940
+ }
1941
+ fossil_free(z);
19211942
cgi_reply();
19221943
fossil_exit(0);
19231944
}
19241945
19251946
/*
@@ -2032,12 +2053,13 @@
20322053
char *z, *zToken;
20332054
int i;
20342055
const char *zScheme = "http";
20352056
char zLine[2000]; /* A single line of input. */
20362057
g.fullHttpReply = 1;
2058
+ g.zReqType = "HTTP";
20372059
if( cgi_fgets(zLine, sizeof(zLine))==0 ){
2038
- malformed_request("missing HTTP header");
2060
+ malformed_request("missing header");
20392061
}
20402062
blob_append(&g.httpHeader, zLine, -1);
20412063
cgi_trace(zLine);
20422064
zToken = extract_token(zLine, &z);
20432065
if( zToken==0 ){
@@ -2045,17 +2067,18 @@
20452067
}
20462068
if( fossil_strcmp(zToken,"GET")!=0
20472069
&& fossil_strcmp(zToken,"POST")!=0
20482070
&& fossil_strcmp(zToken,"HEAD")!=0
20492071
){
2050
- malformed_request("unsupported HTTP method");
2072
+ malformed_request("unsupported HTTP method: \"%s\" - Fossil only supports"
2073
+ "GET, POST, and HEAD", zToken);
20512074
}
20522075
cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
20532076
cgi_setenv("REQUEST_METHOD",zToken);
20542077
zToken = extract_token(z, &z);
20552078
if( zToken==0 ){
2056
- malformed_request("malformed URL in HTTP header");
2079
+ malformed_request("malformed URI in the HTTP header");
20572080
}
20582081
cgi_setenv("REQUEST_URI", zToken);
20592082
cgi_setenv("SCRIPT_NAME", "");
20602083
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
20612084
if( zToken[i] ) zToken[i++] = 0;
@@ -2163,10 +2186,11 @@
21632186
g.zIpAddr = fossil_strdup(zIpAddr);
21642187
}
21652188
}else{
21662189
fossil_fatal("missing SSH IP address");
21672190
}
2191
+ g.zReqType = "HTTP";
21682192
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
21692193
malformed_request("missing HTTP header");
21702194
}
21712195
cgi_trace(zLine);
21722196
zToken = extract_token(zLine, &z);
@@ -2774,13 +2798,16 @@
27742798
** have been consulted.
27752799
*/
27762800
void cgi_check_for_malice(void){
27772801
struct QParam * pParam;
27782802
int i;
2779
- for(i = 0; i < nUsedQP; ++i){
2803
+ for(i=0; i<nUsedQP; ++i){
27802804
pParam = &aParamQP[i];
2781
- if(0 == pParam->isFetched
2782
- && fossil_islower(pParam->zName[0])){
2805
+ if( 0==pParam->isFetched
2806
+ && pParam->zValue!=0
2807
+ && pParam->zName!=0
2808
+ && fossil_islower(pParam->zName[0])
2809
+ ){
27832810
cgi_value_spider_check(pParam->zValue, pParam->zName);
27842811
}
27852812
}
27862813
}
27872814
--- src/cgi.c
+++ src/cgi.c
@@ -1238,11 +1238,11 @@
1238 }
1239 fputs(z, pLog);
1240 }
1241
1242 /* Forward declaration */
1243 static NORETURN void malformed_request(const char *zMsg);
1244
1245 /*
1246 ** Checks the QUERY_STRING environment variable, sets it up
1247 ** via add_param_list() and, if found, applies its "skin"
1248 ** setting. Returns 0 if no QUERY_STRING is set, 1 if it is,
@@ -1321,10 +1321,11 @@
1321 char *zSemi;
1322 int len;
1323 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
1324 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
1325 const char *zPathInfo = cgi_parameter("PATH_INFO",0);
 
1326 #ifdef _WIN32
1327 const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0);
1328 #endif
1329
1330 #ifdef FOSSIL_ENABLE_JSON
@@ -1418,11 +1419,19 @@
1418 z = (char*)P("REMOTE_ADDR");
1419 if( z ){
1420 g.zIpAddr = fossil_strdup(z);
1421 }
1422
1423 len = atoi(PD("CONTENT_LENGTH", "0"));
 
 
 
 
 
 
 
 
1424 zType = P("CONTENT_TYPE");
1425 zSemi = zType ? strchr(zType, ';') : 0;
1426 if( zSemi ){
1427 g.zContentType = fossil_strndup(zType, (int)(zSemi-zType));
1428 zType = g.zContentType;
@@ -1767,10 +1776,11 @@
1767 "FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR",
1768 "TEMP", "TMP", "FOSSIL_VFS",
1769 "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION",
1770 "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS",
1771 "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST",
 
1772 };
1773 int i;
1774 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1775 }
1776
@@ -1811,11 +1821,11 @@
1811 case 2: {
1812 cgi_debug("%s = %s\n", zName, zValue);
1813 break;
1814 }
1815 case 3: {
1816 if( strlen(zValue)>100 ){
1817 fprintf(out,"%s = %.100s...\n", zName, zValue);
1818 }else{
1819 fprintf(out,"%s = %s\n", zName, zValue);
1820 }
1821 break;
@@ -1911,15 +1921,26 @@
1911
1912
1913 /*
1914 ** Send a reply indicating that the HTTP request was malformed
1915 */
1916 static NORETURN void malformed_request(const char *zMsg){
1917 cgi_set_status(501, "Not Implemented");
1918 cgi_printf(
1919 "<html><body><p>Bad Request: %s</p></body></html>\n", zMsg
1920 );
 
 
 
 
 
 
 
 
 
 
 
1921 cgi_reply();
1922 fossil_exit(0);
1923 }
1924
1925 /*
@@ -2032,12 +2053,13 @@
2032 char *z, *zToken;
2033 int i;
2034 const char *zScheme = "http";
2035 char zLine[2000]; /* A single line of input. */
2036 g.fullHttpReply = 1;
 
2037 if( cgi_fgets(zLine, sizeof(zLine))==0 ){
2038 malformed_request("missing HTTP header");
2039 }
2040 blob_append(&g.httpHeader, zLine, -1);
2041 cgi_trace(zLine);
2042 zToken = extract_token(zLine, &z);
2043 if( zToken==0 ){
@@ -2045,17 +2067,18 @@
2045 }
2046 if( fossil_strcmp(zToken,"GET")!=0
2047 && fossil_strcmp(zToken,"POST")!=0
2048 && fossil_strcmp(zToken,"HEAD")!=0
2049 ){
2050 malformed_request("unsupported HTTP method");
 
2051 }
2052 cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
2053 cgi_setenv("REQUEST_METHOD",zToken);
2054 zToken = extract_token(z, &z);
2055 if( zToken==0 ){
2056 malformed_request("malformed URL in HTTP header");
2057 }
2058 cgi_setenv("REQUEST_URI", zToken);
2059 cgi_setenv("SCRIPT_NAME", "");
2060 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
2061 if( zToken[i] ) zToken[i++] = 0;
@@ -2163,10 +2186,11 @@
2163 g.zIpAddr = fossil_strdup(zIpAddr);
2164 }
2165 }else{
2166 fossil_fatal("missing SSH IP address");
2167 }
 
2168 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
2169 malformed_request("missing HTTP header");
2170 }
2171 cgi_trace(zLine);
2172 zToken = extract_token(zLine, &z);
@@ -2774,13 +2798,16 @@
2774 ** have been consulted.
2775 */
2776 void cgi_check_for_malice(void){
2777 struct QParam * pParam;
2778 int i;
2779 for(i = 0; i < nUsedQP; ++i){
2780 pParam = &aParamQP[i];
2781 if(0 == pParam->isFetched
2782 && fossil_islower(pParam->zName[0])){
 
 
 
2783 cgi_value_spider_check(pParam->zValue, pParam->zName);
2784 }
2785 }
2786 }
2787
--- src/cgi.c
+++ src/cgi.c
@@ -1238,11 +1238,11 @@
1238 }
1239 fputs(z, pLog);
1240 }
1241
1242 /* Forward declaration */
1243 static NORETURN void malformed_request(const char *zMsg, ...);
1244
1245 /*
1246 ** Checks the QUERY_STRING environment variable, sets it up
1247 ** via add_param_list() and, if found, applies its "skin"
1248 ** setting. Returns 0 if no QUERY_STRING is set, 1 if it is,
@@ -1321,10 +1321,11 @@
1321 char *zSemi;
1322 int len;
1323 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
1324 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
1325 const char *zPathInfo = cgi_parameter("PATH_INFO",0);
1326 const char *zContentLength = 0;
1327 #ifdef _WIN32
1328 const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0);
1329 #endif
1330
1331 #ifdef FOSSIL_ENABLE_JSON
@@ -1418,11 +1419,19 @@
1419 z = (char*)P("REMOTE_ADDR");
1420 if( z ){
1421 g.zIpAddr = fossil_strdup(z);
1422 }
1423
1424 zContentLength = P("CONTENT_LENGTH");
1425 if( zContentLength==0 ){
1426 len = 0;
1427 if( sqlite3_stricmp(PD("REQUEST_METHOD",""),"POST")==0 ){
1428 malformed_request("missing CONTENT_LENGTH on a POST method");
1429 }
1430 }else{
1431 len = atoi(zContentLength);
1432 }
1433 zType = P("CONTENT_TYPE");
1434 zSemi = zType ? strchr(zType, ';') : 0;
1435 if( zSemi ){
1436 g.zContentType = fossil_strndup(zType, (int)(zSemi-zType));
1437 zType = g.zContentType;
@@ -1767,10 +1776,11 @@
1776 "FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR",
1777 "TEMP", "TMP", "FOSSIL_VFS",
1778 "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION",
1779 "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS",
1780 "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST",
1781 "CONTENT_TYPE", "CONTENT_LENGTH",
1782 };
1783 int i;
1784 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1785 }
1786
@@ -1811,11 +1821,11 @@
1821 case 2: {
1822 cgi_debug("%s = %s\n", zName, zValue);
1823 break;
1824 }
1825 case 3: {
1826 if( zValue!=0 && strlen(zValue)>100 ){
1827 fprintf(out,"%s = %.100s...\n", zName, zValue);
1828 }else{
1829 fprintf(out,"%s = %s\n", zName, zValue);
1830 }
1831 break;
@@ -1911,15 +1921,26 @@
1921
1922
1923 /*
1924 ** Send a reply indicating that the HTTP request was malformed
1925 */
1926 static NORETURN void malformed_request(const char *zMsg, ...){
1927 va_list ap;
1928 char *z;
1929 va_start(ap, zMsg);
1930 z = vmprintf(zMsg, ap);
1931 va_end(ap);
1932 cgi_set_status(400, "Bad Request");
1933 zContentType = "text/plain";
1934 if( g.zReqType==0 ) g.zReqType = "WWW";
1935 if( g.zReqType[0]=='C' && PD("SERVER_SOFTWARE",0)!=0 ){
1936 const char *zServer = PD("SERVER_SOFTWARE","");
1937 cgi_printf("Bad CGI Request from \"%s\": %s\n",zServer,z);
1938 }else{
1939 cgi_printf("Bad %s Request: %s\n", g.zReqType, z);
1940 }
1941 fossil_free(z);
1942 cgi_reply();
1943 fossil_exit(0);
1944 }
1945
1946 /*
@@ -2032,12 +2053,13 @@
2053 char *z, *zToken;
2054 int i;
2055 const char *zScheme = "http";
2056 char zLine[2000]; /* A single line of input. */
2057 g.fullHttpReply = 1;
2058 g.zReqType = "HTTP";
2059 if( cgi_fgets(zLine, sizeof(zLine))==0 ){
2060 malformed_request("missing header");
2061 }
2062 blob_append(&g.httpHeader, zLine, -1);
2063 cgi_trace(zLine);
2064 zToken = extract_token(zLine, &z);
2065 if( zToken==0 ){
@@ -2045,17 +2067,18 @@
2067 }
2068 if( fossil_strcmp(zToken,"GET")!=0
2069 && fossil_strcmp(zToken,"POST")!=0
2070 && fossil_strcmp(zToken,"HEAD")!=0
2071 ){
2072 malformed_request("unsupported HTTP method: \"%s\" - Fossil only supports"
2073 "GET, POST, and HEAD", zToken);
2074 }
2075 cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
2076 cgi_setenv("REQUEST_METHOD",zToken);
2077 zToken = extract_token(z, &z);
2078 if( zToken==0 ){
2079 malformed_request("malformed URI in the HTTP header");
2080 }
2081 cgi_setenv("REQUEST_URI", zToken);
2082 cgi_setenv("SCRIPT_NAME", "");
2083 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
2084 if( zToken[i] ) zToken[i++] = 0;
@@ -2163,10 +2186,11 @@
2186 g.zIpAddr = fossil_strdup(zIpAddr);
2187 }
2188 }else{
2189 fossil_fatal("missing SSH IP address");
2190 }
2191 g.zReqType = "HTTP";
2192 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
2193 malformed_request("missing HTTP header");
2194 }
2195 cgi_trace(zLine);
2196 zToken = extract_token(zLine, &z);
@@ -2774,13 +2798,16 @@
2798 ** have been consulted.
2799 */
2800 void cgi_check_for_malice(void){
2801 struct QParam * pParam;
2802 int i;
2803 for(i=0; i<nUsedQP; ++i){
2804 pParam = &aParamQP[i];
2805 if( 0==pParam->isFetched
2806 && pParam->zValue!=0
2807 && pParam->zName!=0
2808 && fossil_islower(pParam->zName[0])
2809 ){
2810 cgi_value_spider_check(pParam->zValue, pParam->zName);
2811 }
2812 }
2813 }
2814
+223 -86
--- src/chat.c
+++ src/chat.c
@@ -147,36 +147,19 @@
147147
**
148148
** Start up a browser-based chat session.
149149
**
150150
** This is the main page that humans use to access the chatroom. Simply
151151
** point a web-browser at /chat and the screen fills with the latest
152
-** chat messages, and waits for new one.
152
+** chat messages, and waits for new ones.
153153
**
154154
** Other /chat-OP pages are used by XHR requests from this page to
155155
** send new chat message, delete older messages, or poll for changes.
156156
*/
157157
void chat_webpage(void){
158158
char *zAlert;
159159
char *zProjectName;
160160
char * zInputPlaceholder0; /* Common text input placeholder value */
161
- const char *zPaperclip =
162
- "<svg height=\"8.0\" width=\"16.0\"><path "
163
- "stroke=\"rgb(100,100,100)\" "
164
- "d=\"M 15.93452,3.2530441 "
165
- "A 4.1499493,4.1265346 0 0 0 11.804809,6.5256284e-4 H 2.8582923 A "
166
- "2.8239899,2.8080565 0 0 0 0.68965668,0.96142476 2.874599,2.8583801 "
167
- "0 0 0 0.03119302,3.2388108 2.7632589,2.7476682 0 0 0 "
168
- "0.81132923,4.7689293 3.168132,3.1502569 0 0 0 3.0300653,5.66565 l "
169
- "7.7297897,-4e-7 a 1.6802234,1.6707433 0 0 0 0.0072,-3.3377933 H "
170
- "5.6138192 v 1.0105899 l 5.1460358,-0.00712 a 0.66804062,0.66427143 "
171
- "0 0 1 0,1.3237305 l -7.7226325,0.00712 A 2.0243655,2.0129437 0 0 1 "
172
- "1.0332029,3.0964741 1.8522944,1.8418435 0 0 1 2.8511351,1.0041257 h "
173
- "8.9465169 a 3.1478884,3.1301275 0 0 1 3.134859,2.4339559 3.0365483,"
174
- "3.0194156 0 0 1 -0.629835,2.4908908 3.0365483,3.0194156 0 0 1 "
175
- "-2.31178,1.0746415 l -7.5437026,-0.014233 -0.00716,1.0034736 "
176
- "7.5365456,0.00715 a 4.048731,4.0258875 0 0 0 3.957938,-4.7469259 z\""
177
- "/></svg>";
178161
179162
login_check_credentials();
180163
if( !g.perm.Chat ){
181164
login_needed(g.anon.Chat);
182165
return;
@@ -203,12 +186,14 @@
203186
@ data-placeholder="%h(zInputPlaceholder0)" \
204187
@ class="chat-input-field hidden"></div>
205188
@ <div id='chat-buttons-wrapper'>
206189
@ <span class='cbutton' id="chat-button-preview" \
207190
@ title="Preview message (Shift-Enter)">&#128065;</span>
191
+ @ <span class='cbutton' id="chat-button-search" \
192
+ @ title="Search chat history">&#x1f50d;</span>
208193
@ <span class='cbutton' id="chat-button-attach" \
209
- @ title="Attach file to message">%s(zPaperclip)</span>
194
+ @ title="Attach file to message">&#x1f4ce;</span>
210195
@ <span class='cbutton' id="chat-button-settings" \
211196
@ title="Configure chat">&#9881;</span>
212197
@ <span class='cbutton' id="chat-button-submit" \
213198
@ title="Send message (Ctrl-Enter)">&#128228;</span>
214199
@ </div>
@@ -233,17 +218,25 @@
233218
@ </div>
234219
@ <div id='chat-user-list'></div>
235220
@ </div>
236221
@ <div id='chat-preview' class='hidden chat-view'>
237222
@ <header>Preview: (<a href='%R/md_rules' target='_blank'>markdown reference</a>)</header>
238
- @ <div id='chat-preview-content' class='message-widget-content'></div>
239
- @ <div id='chat-preview-buttons'><button id='chat-preview-close'>Close Preview</button></div>
223
+ @ <div id='chat-preview-content'></div>
224
+ @ <div class='button-bar'><button class='action-close'>Close Preview</button></div>
240225
@ </div>
241226
@ <div id='chat-config' class='hidden chat-view'>
242227
@ <div id='chat-config-options'></div>
243228
/* ^^^populated client-side */
244
- @ <button>Close Settings</button>
229
+ @ <div class='button-bar'><button class='action-close'>Close Settings</button></div>
230
+ @ </div>
231
+ @ <div id='chat-search' class='hidden chat-view'>
232
+ @ <div id='chat-search-content'></div>
233
+ /* ^^^populated client-side */
234
+ @ <div class='button-bar'>
235
+ @ <button class='action-clear'>Clear results</button>
236
+ @ <button class='action-close'>Close Search</button>
237
+ @ </div>
245238
@ </div>
246239
@ <div id='chat-messages-wrapper' class='chat-view'>
247240
/* New chat messages get inserted immediately after this element */
248241
@ <span id='message-inject-point'></span>
249242
@ </div>
@@ -271,11 +264,12 @@
271264
@ </script>
272265
builtin_request_js("fossil.page.chat.js");
273266
style_finish_page();
274267
}
275268
276
-/* Definition of repository tables used by chat
269
+/*
270
+** Definition of repository tables used by chat
277271
*/
278272
static const char zChatSchema1[] =
279273
@ CREATE TABLE repository.chat(
280274
@ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
281275
@ mtime JULIANDAY, -- Time for this entry - Julianday Zulu
@@ -289,12 +283,42 @@
289283
@ );
290284
;
291285
292286
293287
/*
294
-** Make sure the repository data tables used by chat exist. Create them
295
-** if they do not.
288
+** Create or rebuild the /chat search index. Requires that the
289
+** repository.chat table exists. If bForce is true, it will drop the
290
+** chatfts1 table and recreate/reindex it. If bForce is 0, it will
291
+** only index the chat content if the chatfts1 table does not already
292
+** exist.
293
+*/
294
+void chat_rebuild_index(int bForce){
295
+ if( bForce!=0 ){
296
+ db_multi_exec("DROP TABLE IF EXISTS chatfts1");
297
+ }
298
+ if( bForce!=0 || !db_table_exists("repository", "chatfts1") ){
299
+ const int tokType = search_tokenizer_type(0);
300
+ const char *zTokenizer = search_tokenize_arg_for_type(
301
+ tokType==FTS5TOK_NONE ? FTS5TOK_PORTER : tokType
302
+ /* Special case: if fts search is disabled for the main repo
303
+ ** content, use a default tokenizer here. */
304
+ );
305
+ assert( zTokenizer && zTokenizer[0] );
306
+ db_multi_exec(
307
+ "CREATE VIRTUAL TABLE repository.chatfts1 USING fts5("
308
+ " xmsg, content=chat, content_rowid=msgid%s"
309
+ ");"
310
+ "INSERT INTO repository.chatfts1(chatfts1) VALUES('rebuild');",
311
+ zTokenizer/*safe-for-%s*/
312
+ );
313
+ }
314
+}
315
+
316
+/*
317
+** Make sure the repository data tables used by chat exist. Create
318
+** them if they do not. Set up TEMP triggers (if needed) to update the
319
+** chatfts1 table as the chat table is updated.
296320
*/
297321
static void chat_create_tables(void){
298322
if( !db_table_exists("repository","chat") ){
299323
db_multi_exec(zChatSchema1/*works-like:""*/);
300324
}else if( !db_table_has_column("repository","chat","lmtime") ){
@@ -301,10 +325,20 @@
301325
if( !db_table_has_column("repository","chat","mdel") ){
302326
db_multi_exec("ALTER TABLE chat ADD COLUMN mdel INT");
303327
}
304328
db_multi_exec("ALTER TABLE chat ADD COLUMN lmtime TEXT");
305329
}
330
+ chat_rebuild_index(0);
331
+ db_multi_exec(
332
+ "CREATE TEMP TRIGGER IF NOT EXISTS chat_ai AFTER INSERT ON chat BEGIN "
333
+ " INSERT INTO chatfts1(rowid, xmsg) VALUES(new.msgid, new.xmsg);"
334
+ "END;"
335
+ "CREATE TEMP TRIGGER IF NOT EXISTS chat_ad AFTER DELETE ON chat BEGIN "
336
+ " INSERT INTO chatfts1(chatfts1, rowid, xmsg) "
337
+ " VALUES('delete', old.msgid, old.xmsg);"
338
+ "END;"
339
+ );
306340
}
307341
308342
/*
309343
** Delete old content from the chat table.
310344
*/
@@ -452,28 +486,120 @@
452486
}
453487
454488
/*
455489
** COMMAND: test-chat-formatter
456490
**
457
-** Usage: %fossil test-chat-formatter STRING ...
491
+** Usage: %fossil test-chat-formatter ?OPTIONS? STRING ...
458492
**
459493
** Transform each argument string into HTML that will display the
460494
** chat message. This is used to test the formatter and to verify
461495
** that a malicious message text will not cause HTML or JS injection
462496
** into the chat display in a browser.
497
+**
498
+** Options:
499
+**
500
+** -w|--wiki Assume fossil wiki format instead of markdown
463501
*/
464502
void chat_test_formatter_cmd(void){
465503
int i;
466504
char *zOut;
505
+ int const isWiki = find_option("w","wiki",0)!=0;
467506
db_find_and_open_repository(0,0);
468507
g.perm.Hyperlink = 1;
469
- for(i=0; i<g.argc; i++){
470
- zOut = chat_format_to_html(g.argv[i], 0);
471
- fossil_print("[%d]: %s\n", i, zOut);
508
+ for(i=2; i<g.argc; i++){
509
+ zOut = chat_format_to_html(g.argv[i], isWiki);
510
+ fossil_print("[%d]: %s\n", i-1, zOut);
472511
fossil_free(zOut);
473512
}
474513
}
514
+
515
+/*
516
+** The SQL statement passed as the first argument should return zero or
517
+** more rows of data, each of which represents a single message from the
518
+** "chat" table. The rows returned should be similar to those returned
519
+** by:
520
+**
521
+** SELECT msgid,
522
+** datetime(mtime),
523
+** xfrom,
524
+** xmsg,
525
+** octet_length(file),"
526
+** fname,
527
+** fmime,
528
+** mdel,
529
+** lmtime
530
+** FROM chat;
531
+**
532
+** This function loops through all rows returned by statement p, adding
533
+** a record to the JSON stored in argument pJson for each. See comments
534
+** above function chat_poll_webpage() for a description of the JSON records
535
+** added to pJson.
536
+*/
537
+static int chat_poll_rowstojson(
538
+ Stmt *p, /* Statement to read rows from */
539
+ int bRaw, /* True to return raw format xmsg */
540
+ Blob *pJson /* Append json array entries here */
541
+){
542
+ int cnt = 0;
543
+ const char *zChatUser = db_get("chat-timeline-user",0);
544
+ while( db_step(p)==SQLITE_ROW ){
545
+ int isWiki = 0; /* True if chat message is x-fossil-wiki */
546
+ int id = db_column_int(p, 0);
547
+ const char *zDate = db_column_text(p, 1);
548
+ const char *zFrom = db_column_text(p, 2);
549
+ const char *zRawMsg = db_column_text(p, 3);
550
+ int nByte = db_column_int(p, 4);
551
+ const char *zFName = db_column_text(p, 5);
552
+ const char *zFMime = db_column_text(p, 6);
553
+ int iToDel = db_column_int(p, 7);
554
+ const char *zLMtime = db_column_text(p, 8);
555
+ char *zMsg;
556
+ if(cnt++){
557
+ blob_append(pJson, ",\n", 2);
558
+ }
559
+ blob_appendf(pJson, "{\"msgid\":%d,", id);
560
+ blob_appendf(pJson, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
561
+ if( zLMtime && zLMtime[0] ){
562
+ blob_appendf(pJson, "\"lmtime\":%!j,", zLMtime);
563
+ }
564
+ blob_append(pJson, "\"xfrom\":", -1);
565
+ if(zFrom){
566
+ blob_appendf(pJson, "%!j,", zFrom);
567
+ isWiki = fossil_strcmp(zFrom,zChatUser)==0;
568
+ }else{
569
+ /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */
570
+ blob_appendf(pJson, "null,");
571
+ isWiki = 0;
572
+ }
573
+ blob_appendf(pJson, "\"uclr\":%!j,",
574
+ isWiki ? "transparent" : user_color(zFrom ? zFrom : "nobody"));
575
+
576
+ if(bRaw){
577
+ blob_appendf(pJson, "\"xmsg\":%!j,", zRawMsg);
578
+ }else{
579
+ zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "", isWiki);
580
+ blob_appendf(pJson, "\"xmsg\":%!j,", zMsg);
581
+ fossil_free(zMsg);
582
+ }
583
+
584
+ if( nByte==0 ){
585
+ blob_appendf(pJson, "\"fsize\":0");
586
+ }else{
587
+ blob_appendf(pJson, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
588
+ nByte, zFName, zFMime);
589
+ }
590
+
591
+ if( iToDel ){
592
+ blob_appendf(pJson, ",\"mdel\":%d}", iToDel);
593
+ }else{
594
+ blob_append(pJson, "}", 1);
595
+ }
596
+ }
597
+ db_reset(p);
598
+
599
+ return cnt;
600
+}
475601
476602
/*
477603
** WEBPAGE: chat-poll hidden loadavg-exempt
478604
**
479605
** The chat page generated by /chat using an XHR to this page to
@@ -568,12 +694,10 @@
568694
void chat_poll_webpage(void){
569695
Blob json; /* The json to be constructed and returned */
570696
sqlite3_int64 dataVersion; /* Data version. Used for polling. */
571697
const int iDelay = 1000; /* Delay until next poll (milliseconds) */
572698
int nDelay; /* Maximum delay.*/
573
- const char *zChatUser; /* chat-timeline-user */
574
- int isWiki = 0; /* True if chat message is x-fossil-wiki */
575699
int msgid = atoi(PD("name","0"));
576700
const int msgBefore = atoi(PD("before","0"));
577701
int nLimit = msgBefore>0 ? atoi(PD("n","0")) : 0;
578702
const int bRaw = P("raw")!=0;
579703
@@ -583,11 +707,10 @@
583707
login_check_credentials();
584708
if( !g.perm.Chat ) {
585709
chat_emit_permissions_error(1);
586710
return;
587711
}
588
- zChatUser = db_get("chat-timeline-user",0);
589712
chat_create_tables();
590713
cgi_set_content_type("application/json");
591714
dataVersion = db_int64(0, "PRAGMA data_version");
592715
blob_append_sql(&sql,
593716
"SELECT msgid, datetime(mtime), xfrom, xmsg, octet_length(file),"
@@ -623,64 +746,11 @@
623746
}
624747
db_prepare(&q1, "%s", blob_sql_text(&sql));
625748
blob_reset(&sql);
626749
blob_init(&json, "{\"msgs\":[\n", -1);
627750
while( nDelay>0 ){
628
- int cnt = 0;
629
- while( db_step(&q1)==SQLITE_ROW ){
630
- int id = db_column_int(&q1, 0);
631
- const char *zDate = db_column_text(&q1, 1);
632
- const char *zFrom = db_column_text(&q1, 2);
633
- const char *zRawMsg = db_column_text(&q1, 3);
634
- int nByte = db_column_int(&q1, 4);
635
- const char *zFName = db_column_text(&q1, 5);
636
- const char *zFMime = db_column_text(&q1, 6);
637
- int iToDel = db_column_int(&q1, 7);
638
- const char *zLMtime = db_column_text(&q1, 8);
639
- char *zMsg;
640
- if(cnt++){
641
- blob_append(&json, ",\n", 2);
642
- }
643
- blob_appendf(&json, "{\"msgid\":%d,", id);
644
- blob_appendf(&json, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
645
- if( zLMtime && zLMtime[0] ){
646
- blob_appendf(&json, "\"lmtime\":%!j,", zLMtime);
647
- }
648
- blob_append(&json, "\"xfrom\":", -1);
649
- if(zFrom){
650
- blob_appendf(&json, "%!j,", zFrom);
651
- isWiki = fossil_strcmp(zFrom,zChatUser)==0;
652
- }else{
653
- /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */
654
- blob_appendf(&json, "null,");
655
- isWiki = 0;
656
- }
657
- blob_appendf(&json, "\"uclr\":%!j,",
658
- isWiki ? "transparent" : user_color(zFrom ? zFrom : "nobody"));
659
-
660
- if(bRaw){
661
- blob_appendf(&json, "\"xmsg\":%!j,", zRawMsg);
662
- }else{
663
- zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "", isWiki);
664
- blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
665
- fossil_free(zMsg);
666
- }
667
-
668
- if( nByte==0 ){
669
- blob_appendf(&json, "\"fsize\":0");
670
- }else{
671
- blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
672
- nByte, zFName, zFMime);
673
- }
674
-
675
- if( iToDel ){
676
- blob_appendf(&json, ",\"mdel\":%d}", iToDel);
677
- }else{
678
- blob_append(&json, "}", 1);
679
- }
680
- }
681
- db_reset(&q1);
751
+ int cnt = chat_poll_rowstojson(&q1, bRaw, &json);
682752
if( cnt || msgBefore>0 ){
683753
break;
684754
}
685755
sqlite3_sleep(iDelay); nDelay--;
686756
while( nDelay>0 ){
@@ -696,10 +766,77 @@
696766
blob_append(&json, "\n]}", 3);
697767
cgi_set_content(&json);
698768
return;
699769
}
700770
771
+
772
+/*
773
+** WEBPAGE: chat-query hidden loadavg-exempt
774
+*/
775
+void chat_query_webpage(void){
776
+ Blob json; /* The json to be constructed and returned */
777
+ Blob sql = empty_blob;
778
+ Stmt q1;
779
+ int nLimit = atoi(PD("n","500"));
780
+ int iFirst = atoi(PD("i","0"));
781
+ const char *zQuery = PD("q", "");
782
+ i64 iMin = 0;
783
+ i64 iMax = 0;
784
+
785
+ login_check_credentials();
786
+ if( !g.perm.Chat ) {
787
+ chat_emit_permissions_error(1);
788
+ return;
789
+ }
790
+ chat_create_tables();
791
+ cgi_set_content_type("application/json");
792
+
793
+ if( zQuery[0] ){
794
+ iMax = db_int64(0, "SELECT max(msgid) FROM chat");
795
+ iMin = db_int64(0, "SELECT min(msgid) FROM chat");
796
+ if( '#'==zQuery[0] ){
797
+ /* Assume we're looking for an exact msgid match. */
798
+ ++zQuery;
799
+ blob_append_sql(&sql,
800
+ "SELECT msgid, datetime(mtime), xfrom, "
801
+ " xmsg, octet_length(file), fname, fmime, mdel, lmtime "
802
+ " FROM chat WHERE msgid=+%Q",
803
+ zQuery
804
+ );
805
+ }else{
806
+ char * zPat = search_simplify_pattern(zQuery);
807
+ blob_append_sql(&sql,
808
+ "SELECT * FROM ("
809
+ "SELECT c.msgid, datetime(c.mtime), c.xfrom, "
810
+ " highlight(chatfts1, 0, '<span class=\"match\">', '</span>'), "
811
+ " octet_length(c.file), c.fname, c.fmime, c.mdel, c.lmtime "
812
+ " FROM chatfts1(%Q) f, chat c "
813
+ " WHERE f.rowid=c.msgid"
814
+ " ORDER BY f.rowid DESC LIMIT %d"
815
+ ") ORDER BY 1 ASC", zPat, nLimit
816
+ );
817
+ fossil_free(zPat);
818
+ }
819
+ }else{
820
+ blob_append_sql(&sql,
821
+ "SELECT msgid, datetime(mtime), xfrom, "
822
+ " xmsg, octet_length(file), fname, fmime, mdel, lmtime"
823
+ " FROM chat WHERE msgid>=%d LIMIT %d",
824
+ iFirst, nLimit
825
+ );
826
+ }
827
+
828
+ db_prepare(&q1, "%s", blob_sql_text(&sql));
829
+ blob_reset(&sql);
830
+ blob_init(&json, "{\"msgs\":[\n", -1);
831
+ chat_poll_rowstojson(&q1, 0, &json);
832
+ db_finalize(&q1);
833
+ blob_appendf(&json, "\n], \"first\":%lld, \"last\":%lld}", iMin, iMax);
834
+ cgi_set_content(&json);
835
+ return;
836
+}
837
+
701838
/*
702839
** WEBPAGE: chat-fetch-one hidden loadavg-exempt
703840
**
704841
** /chat-fetch-one/N
705842
**
706843
--- src/chat.c
+++ src/chat.c
@@ -147,36 +147,19 @@
147 **
148 ** Start up a browser-based chat session.
149 **
150 ** This is the main page that humans use to access the chatroom. Simply
151 ** point a web-browser at /chat and the screen fills with the latest
152 ** chat messages, and waits for new one.
153 **
154 ** Other /chat-OP pages are used by XHR requests from this page to
155 ** send new chat message, delete older messages, or poll for changes.
156 */
157 void chat_webpage(void){
158 char *zAlert;
159 char *zProjectName;
160 char * zInputPlaceholder0; /* Common text input placeholder value */
161 const char *zPaperclip =
162 "<svg height=\"8.0\" width=\"16.0\"><path "
163 "stroke=\"rgb(100,100,100)\" "
164 "d=\"M 15.93452,3.2530441 "
165 "A 4.1499493,4.1265346 0 0 0 11.804809,6.5256284e-4 H 2.8582923 A "
166 "2.8239899,2.8080565 0 0 0 0.68965668,0.96142476 2.874599,2.8583801 "
167 "0 0 0 0.03119302,3.2388108 2.7632589,2.7476682 0 0 0 "
168 "0.81132923,4.7689293 3.168132,3.1502569 0 0 0 3.0300653,5.66565 l "
169 "7.7297897,-4e-7 a 1.6802234,1.6707433 0 0 0 0.0072,-3.3377933 H "
170 "5.6138192 v 1.0105899 l 5.1460358,-0.00712 a 0.66804062,0.66427143 "
171 "0 0 1 0,1.3237305 l -7.7226325,0.00712 A 2.0243655,2.0129437 0 0 1 "
172 "1.0332029,3.0964741 1.8522944,1.8418435 0 0 1 2.8511351,1.0041257 h "
173 "8.9465169 a 3.1478884,3.1301275 0 0 1 3.134859,2.4339559 3.0365483,"
174 "3.0194156 0 0 1 -0.629835,2.4908908 3.0365483,3.0194156 0 0 1 "
175 "-2.31178,1.0746415 l -7.5437026,-0.014233 -0.00716,1.0034736 "
176 "7.5365456,0.00715 a 4.048731,4.0258875 0 0 0 3.957938,-4.7469259 z\""
177 "/></svg>";
178
179 login_check_credentials();
180 if( !g.perm.Chat ){
181 login_needed(g.anon.Chat);
182 return;
@@ -203,12 +186,14 @@
203 @ data-placeholder="%h(zInputPlaceholder0)" \
204 @ class="chat-input-field hidden"></div>
205 @ <div id='chat-buttons-wrapper'>
206 @ <span class='cbutton' id="chat-button-preview" \
207 @ title="Preview message (Shift-Enter)">&#128065;</span>
 
 
208 @ <span class='cbutton' id="chat-button-attach" \
209 @ title="Attach file to message">%s(zPaperclip)</span>
210 @ <span class='cbutton' id="chat-button-settings" \
211 @ title="Configure chat">&#9881;</span>
212 @ <span class='cbutton' id="chat-button-submit" \
213 @ title="Send message (Ctrl-Enter)">&#128228;</span>
214 @ </div>
@@ -233,17 +218,25 @@
233 @ </div>
234 @ <div id='chat-user-list'></div>
235 @ </div>
236 @ <div id='chat-preview' class='hidden chat-view'>
237 @ <header>Preview: (<a href='%R/md_rules' target='_blank'>markdown reference</a>)</header>
238 @ <div id='chat-preview-content' class='message-widget-content'></div>
239 @ <div id='chat-preview-buttons'><button id='chat-preview-close'>Close Preview</button></div>
240 @ </div>
241 @ <div id='chat-config' class='hidden chat-view'>
242 @ <div id='chat-config-options'></div>
243 /* ^^^populated client-side */
244 @ <button>Close Settings</button>
 
 
 
 
 
 
 
 
245 @ </div>
246 @ <div id='chat-messages-wrapper' class='chat-view'>
247 /* New chat messages get inserted immediately after this element */
248 @ <span id='message-inject-point'></span>
249 @ </div>
@@ -271,11 +264,12 @@
271 @ </script>
272 builtin_request_js("fossil.page.chat.js");
273 style_finish_page();
274 }
275
276 /* Definition of repository tables used by chat
 
277 */
278 static const char zChatSchema1[] =
279 @ CREATE TABLE repository.chat(
280 @ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
281 @ mtime JULIANDAY, -- Time for this entry - Julianday Zulu
@@ -289,12 +283,42 @@
289 @ );
290 ;
291
292
293 /*
294 ** Make sure the repository data tables used by chat exist. Create them
295 ** if they do not.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296 */
297 static void chat_create_tables(void){
298 if( !db_table_exists("repository","chat") ){
299 db_multi_exec(zChatSchema1/*works-like:""*/);
300 }else if( !db_table_has_column("repository","chat","lmtime") ){
@@ -301,10 +325,20 @@
301 if( !db_table_has_column("repository","chat","mdel") ){
302 db_multi_exec("ALTER TABLE chat ADD COLUMN mdel INT");
303 }
304 db_multi_exec("ALTER TABLE chat ADD COLUMN lmtime TEXT");
305 }
 
 
 
 
 
 
 
 
 
 
306 }
307
308 /*
309 ** Delete old content from the chat table.
310 */
@@ -452,28 +486,120 @@
452 }
453
454 /*
455 ** COMMAND: test-chat-formatter
456 **
457 ** Usage: %fossil test-chat-formatter STRING ...
458 **
459 ** Transform each argument string into HTML that will display the
460 ** chat message. This is used to test the formatter and to verify
461 ** that a malicious message text will not cause HTML or JS injection
462 ** into the chat display in a browser.
 
 
 
 
463 */
464 void chat_test_formatter_cmd(void){
465 int i;
466 char *zOut;
 
467 db_find_and_open_repository(0,0);
468 g.perm.Hyperlink = 1;
469 for(i=0; i<g.argc; i++){
470 zOut = chat_format_to_html(g.argv[i], 0);
471 fossil_print("[%d]: %s\n", i, zOut);
472 fossil_free(zOut);
473 }
474 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
476 /*
477 ** WEBPAGE: chat-poll hidden loadavg-exempt
478 **
479 ** The chat page generated by /chat using an XHR to this page to
@@ -568,12 +694,10 @@
568 void chat_poll_webpage(void){
569 Blob json; /* The json to be constructed and returned */
570 sqlite3_int64 dataVersion; /* Data version. Used for polling. */
571 const int iDelay = 1000; /* Delay until next poll (milliseconds) */
572 int nDelay; /* Maximum delay.*/
573 const char *zChatUser; /* chat-timeline-user */
574 int isWiki = 0; /* True if chat message is x-fossil-wiki */
575 int msgid = atoi(PD("name","0"));
576 const int msgBefore = atoi(PD("before","0"));
577 int nLimit = msgBefore>0 ? atoi(PD("n","0")) : 0;
578 const int bRaw = P("raw")!=0;
579
@@ -583,11 +707,10 @@
583 login_check_credentials();
584 if( !g.perm.Chat ) {
585 chat_emit_permissions_error(1);
586 return;
587 }
588 zChatUser = db_get("chat-timeline-user",0);
589 chat_create_tables();
590 cgi_set_content_type("application/json");
591 dataVersion = db_int64(0, "PRAGMA data_version");
592 blob_append_sql(&sql,
593 "SELECT msgid, datetime(mtime), xfrom, xmsg, octet_length(file),"
@@ -623,64 +746,11 @@
623 }
624 db_prepare(&q1, "%s", blob_sql_text(&sql));
625 blob_reset(&sql);
626 blob_init(&json, "{\"msgs\":[\n", -1);
627 while( nDelay>0 ){
628 int cnt = 0;
629 while( db_step(&q1)==SQLITE_ROW ){
630 int id = db_column_int(&q1, 0);
631 const char *zDate = db_column_text(&q1, 1);
632 const char *zFrom = db_column_text(&q1, 2);
633 const char *zRawMsg = db_column_text(&q1, 3);
634 int nByte = db_column_int(&q1, 4);
635 const char *zFName = db_column_text(&q1, 5);
636 const char *zFMime = db_column_text(&q1, 6);
637 int iToDel = db_column_int(&q1, 7);
638 const char *zLMtime = db_column_text(&q1, 8);
639 char *zMsg;
640 if(cnt++){
641 blob_append(&json, ",\n", 2);
642 }
643 blob_appendf(&json, "{\"msgid\":%d,", id);
644 blob_appendf(&json, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
645 if( zLMtime && zLMtime[0] ){
646 blob_appendf(&json, "\"lmtime\":%!j,", zLMtime);
647 }
648 blob_append(&json, "\"xfrom\":", -1);
649 if(zFrom){
650 blob_appendf(&json, "%!j,", zFrom);
651 isWiki = fossil_strcmp(zFrom,zChatUser)==0;
652 }else{
653 /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */
654 blob_appendf(&json, "null,");
655 isWiki = 0;
656 }
657 blob_appendf(&json, "\"uclr\":%!j,",
658 isWiki ? "transparent" : user_color(zFrom ? zFrom : "nobody"));
659
660 if(bRaw){
661 blob_appendf(&json, "\"xmsg\":%!j,", zRawMsg);
662 }else{
663 zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "", isWiki);
664 blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
665 fossil_free(zMsg);
666 }
667
668 if( nByte==0 ){
669 blob_appendf(&json, "\"fsize\":0");
670 }else{
671 blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
672 nByte, zFName, zFMime);
673 }
674
675 if( iToDel ){
676 blob_appendf(&json, ",\"mdel\":%d}", iToDel);
677 }else{
678 blob_append(&json, "}", 1);
679 }
680 }
681 db_reset(&q1);
682 if( cnt || msgBefore>0 ){
683 break;
684 }
685 sqlite3_sleep(iDelay); nDelay--;
686 while( nDelay>0 ){
@@ -696,10 +766,77 @@
696 blob_append(&json, "\n]}", 3);
697 cgi_set_content(&json);
698 return;
699 }
700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701 /*
702 ** WEBPAGE: chat-fetch-one hidden loadavg-exempt
703 **
704 ** /chat-fetch-one/N
705 **
706
--- src/chat.c
+++ src/chat.c
@@ -147,36 +147,19 @@
147 **
148 ** Start up a browser-based chat session.
149 **
150 ** This is the main page that humans use to access the chatroom. Simply
151 ** point a web-browser at /chat and the screen fills with the latest
152 ** chat messages, and waits for new ones.
153 **
154 ** Other /chat-OP pages are used by XHR requests from this page to
155 ** send new chat message, delete older messages, or poll for changes.
156 */
157 void chat_webpage(void){
158 char *zAlert;
159 char *zProjectName;
160 char * zInputPlaceholder0; /* Common text input placeholder value */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
162 login_check_credentials();
163 if( !g.perm.Chat ){
164 login_needed(g.anon.Chat);
165 return;
@@ -203,12 +186,14 @@
186 @ data-placeholder="%h(zInputPlaceholder0)" \
187 @ class="chat-input-field hidden"></div>
188 @ <div id='chat-buttons-wrapper'>
189 @ <span class='cbutton' id="chat-button-preview" \
190 @ title="Preview message (Shift-Enter)">&#128065;</span>
191 @ <span class='cbutton' id="chat-button-search" \
192 @ title="Search chat history">&#x1f50d;</span>
193 @ <span class='cbutton' id="chat-button-attach" \
194 @ title="Attach file to message">&#x1f4ce;</span>
195 @ <span class='cbutton' id="chat-button-settings" \
196 @ title="Configure chat">&#9881;</span>
197 @ <span class='cbutton' id="chat-button-submit" \
198 @ title="Send message (Ctrl-Enter)">&#128228;</span>
199 @ </div>
@@ -233,17 +218,25 @@
218 @ </div>
219 @ <div id='chat-user-list'></div>
220 @ </div>
221 @ <div id='chat-preview' class='hidden chat-view'>
222 @ <header>Preview: (<a href='%R/md_rules' target='_blank'>markdown reference</a>)</header>
223 @ <div id='chat-preview-content'></div>
224 @ <div class='button-bar'><button class='action-close'>Close Preview</button></div>
225 @ </div>
226 @ <div id='chat-config' class='hidden chat-view'>
227 @ <div id='chat-config-options'></div>
228 /* ^^^populated client-side */
229 @ <div class='button-bar'><button class='action-close'>Close Settings</button></div>
230 @ </div>
231 @ <div id='chat-search' class='hidden chat-view'>
232 @ <div id='chat-search-content'></div>
233 /* ^^^populated client-side */
234 @ <div class='button-bar'>
235 @ <button class='action-clear'>Clear results</button>
236 @ <button class='action-close'>Close Search</button>
237 @ </div>
238 @ </div>
239 @ <div id='chat-messages-wrapper' class='chat-view'>
240 /* New chat messages get inserted immediately after this element */
241 @ <span id='message-inject-point'></span>
242 @ </div>
@@ -271,11 +264,12 @@
264 @ </script>
265 builtin_request_js("fossil.page.chat.js");
266 style_finish_page();
267 }
268
269 /*
270 ** Definition of repository tables used by chat
271 */
272 static const char zChatSchema1[] =
273 @ CREATE TABLE repository.chat(
274 @ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
275 @ mtime JULIANDAY, -- Time for this entry - Julianday Zulu
@@ -289,12 +283,42 @@
283 @ );
284 ;
285
286
287 /*
288 ** Create or rebuild the /chat search index. Requires that the
289 ** repository.chat table exists. If bForce is true, it will drop the
290 ** chatfts1 table and recreate/reindex it. If bForce is 0, it will
291 ** only index the chat content if the chatfts1 table does not already
292 ** exist.
293 */
294 void chat_rebuild_index(int bForce){
295 if( bForce!=0 ){
296 db_multi_exec("DROP TABLE IF EXISTS chatfts1");
297 }
298 if( bForce!=0 || !db_table_exists("repository", "chatfts1") ){
299 const int tokType = search_tokenizer_type(0);
300 const char *zTokenizer = search_tokenize_arg_for_type(
301 tokType==FTS5TOK_NONE ? FTS5TOK_PORTER : tokType
302 /* Special case: if fts search is disabled for the main repo
303 ** content, use a default tokenizer here. */
304 );
305 assert( zTokenizer && zTokenizer[0] );
306 db_multi_exec(
307 "CREATE VIRTUAL TABLE repository.chatfts1 USING fts5("
308 " xmsg, content=chat, content_rowid=msgid%s"
309 ");"
310 "INSERT INTO repository.chatfts1(chatfts1) VALUES('rebuild');",
311 zTokenizer/*safe-for-%s*/
312 );
313 }
314 }
315
316 /*
317 ** Make sure the repository data tables used by chat exist. Create
318 ** them if they do not. Set up TEMP triggers (if needed) to update the
319 ** chatfts1 table as the chat table is updated.
320 */
321 static void chat_create_tables(void){
322 if( !db_table_exists("repository","chat") ){
323 db_multi_exec(zChatSchema1/*works-like:""*/);
324 }else if( !db_table_has_column("repository","chat","lmtime") ){
@@ -301,10 +325,20 @@
325 if( !db_table_has_column("repository","chat","mdel") ){
326 db_multi_exec("ALTER TABLE chat ADD COLUMN mdel INT");
327 }
328 db_multi_exec("ALTER TABLE chat ADD COLUMN lmtime TEXT");
329 }
330 chat_rebuild_index(0);
331 db_multi_exec(
332 "CREATE TEMP TRIGGER IF NOT EXISTS chat_ai AFTER INSERT ON chat BEGIN "
333 " INSERT INTO chatfts1(rowid, xmsg) VALUES(new.msgid, new.xmsg);"
334 "END;"
335 "CREATE TEMP TRIGGER IF NOT EXISTS chat_ad AFTER DELETE ON chat BEGIN "
336 " INSERT INTO chatfts1(chatfts1, rowid, xmsg) "
337 " VALUES('delete', old.msgid, old.xmsg);"
338 "END;"
339 );
340 }
341
342 /*
343 ** Delete old content from the chat table.
344 */
@@ -452,28 +486,120 @@
486 }
487
488 /*
489 ** COMMAND: test-chat-formatter
490 **
491 ** Usage: %fossil test-chat-formatter ?OPTIONS? STRING ...
492 **
493 ** Transform each argument string into HTML that will display the
494 ** chat message. This is used to test the formatter and to verify
495 ** that a malicious message text will not cause HTML or JS injection
496 ** into the chat display in a browser.
497 **
498 ** Options:
499 **
500 ** -w|--wiki Assume fossil wiki format instead of markdown
501 */
502 void chat_test_formatter_cmd(void){
503 int i;
504 char *zOut;
505 int const isWiki = find_option("w","wiki",0)!=0;
506 db_find_and_open_repository(0,0);
507 g.perm.Hyperlink = 1;
508 for(i=2; i<g.argc; i++){
509 zOut = chat_format_to_html(g.argv[i], isWiki);
510 fossil_print("[%d]: %s\n", i-1, zOut);
511 fossil_free(zOut);
512 }
513 }
514
515 /*
516 ** The SQL statement passed as the first argument should return zero or
517 ** more rows of data, each of which represents a single message from the
518 ** "chat" table. The rows returned should be similar to those returned
519 ** by:
520 **
521 ** SELECT msgid,
522 ** datetime(mtime),
523 ** xfrom,
524 ** xmsg,
525 ** octet_length(file),"
526 ** fname,
527 ** fmime,
528 ** mdel,
529 ** lmtime
530 ** FROM chat;
531 **
532 ** This function loops through all rows returned by statement p, adding
533 ** a record to the JSON stored in argument pJson for each. See comments
534 ** above function chat_poll_webpage() for a description of the JSON records
535 ** added to pJson.
536 */
537 static int chat_poll_rowstojson(
538 Stmt *p, /* Statement to read rows from */
539 int bRaw, /* True to return raw format xmsg */
540 Blob *pJson /* Append json array entries here */
541 ){
542 int cnt = 0;
543 const char *zChatUser = db_get("chat-timeline-user",0);
544 while( db_step(p)==SQLITE_ROW ){
545 int isWiki = 0; /* True if chat message is x-fossil-wiki */
546 int id = db_column_int(p, 0);
547 const char *zDate = db_column_text(p, 1);
548 const char *zFrom = db_column_text(p, 2);
549 const char *zRawMsg = db_column_text(p, 3);
550 int nByte = db_column_int(p, 4);
551 const char *zFName = db_column_text(p, 5);
552 const char *zFMime = db_column_text(p, 6);
553 int iToDel = db_column_int(p, 7);
554 const char *zLMtime = db_column_text(p, 8);
555 char *zMsg;
556 if(cnt++){
557 blob_append(pJson, ",\n", 2);
558 }
559 blob_appendf(pJson, "{\"msgid\":%d,", id);
560 blob_appendf(pJson, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
561 if( zLMtime && zLMtime[0] ){
562 blob_appendf(pJson, "\"lmtime\":%!j,", zLMtime);
563 }
564 blob_append(pJson, "\"xfrom\":", -1);
565 if(zFrom){
566 blob_appendf(pJson, "%!j,", zFrom);
567 isWiki = fossil_strcmp(zFrom,zChatUser)==0;
568 }else{
569 /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */
570 blob_appendf(pJson, "null,");
571 isWiki = 0;
572 }
573 blob_appendf(pJson, "\"uclr\":%!j,",
574 isWiki ? "transparent" : user_color(zFrom ? zFrom : "nobody"));
575
576 if(bRaw){
577 blob_appendf(pJson, "\"xmsg\":%!j,", zRawMsg);
578 }else{
579 zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "", isWiki);
580 blob_appendf(pJson, "\"xmsg\":%!j,", zMsg);
581 fossil_free(zMsg);
582 }
583
584 if( nByte==0 ){
585 blob_appendf(pJson, "\"fsize\":0");
586 }else{
587 blob_appendf(pJson, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
588 nByte, zFName, zFMime);
589 }
590
591 if( iToDel ){
592 blob_appendf(pJson, ",\"mdel\":%d}", iToDel);
593 }else{
594 blob_append(pJson, "}", 1);
595 }
596 }
597 db_reset(p);
598
599 return cnt;
600 }
601
602 /*
603 ** WEBPAGE: chat-poll hidden loadavg-exempt
604 **
605 ** The chat page generated by /chat using an XHR to this page to
@@ -568,12 +694,10 @@
694 void chat_poll_webpage(void){
695 Blob json; /* The json to be constructed and returned */
696 sqlite3_int64 dataVersion; /* Data version. Used for polling. */
697 const int iDelay = 1000; /* Delay until next poll (milliseconds) */
698 int nDelay; /* Maximum delay.*/
 
 
699 int msgid = atoi(PD("name","0"));
700 const int msgBefore = atoi(PD("before","0"));
701 int nLimit = msgBefore>0 ? atoi(PD("n","0")) : 0;
702 const int bRaw = P("raw")!=0;
703
@@ -583,11 +707,10 @@
707 login_check_credentials();
708 if( !g.perm.Chat ) {
709 chat_emit_permissions_error(1);
710 return;
711 }
 
712 chat_create_tables();
713 cgi_set_content_type("application/json");
714 dataVersion = db_int64(0, "PRAGMA data_version");
715 blob_append_sql(&sql,
716 "SELECT msgid, datetime(mtime), xfrom, xmsg, octet_length(file),"
@@ -623,64 +746,11 @@
746 }
747 db_prepare(&q1, "%s", blob_sql_text(&sql));
748 blob_reset(&sql);
749 blob_init(&json, "{\"msgs\":[\n", -1);
750 while( nDelay>0 ){
751 int cnt = chat_poll_rowstojson(&q1, bRaw, &json);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
752 if( cnt || msgBefore>0 ){
753 break;
754 }
755 sqlite3_sleep(iDelay); nDelay--;
756 while( nDelay>0 ){
@@ -696,10 +766,77 @@
766 blob_append(&json, "\n]}", 3);
767 cgi_set_content(&json);
768 return;
769 }
770
771
772 /*
773 ** WEBPAGE: chat-query hidden loadavg-exempt
774 */
775 void chat_query_webpage(void){
776 Blob json; /* The json to be constructed and returned */
777 Blob sql = empty_blob;
778 Stmt q1;
779 int nLimit = atoi(PD("n","500"));
780 int iFirst = atoi(PD("i","0"));
781 const char *zQuery = PD("q", "");
782 i64 iMin = 0;
783 i64 iMax = 0;
784
785 login_check_credentials();
786 if( !g.perm.Chat ) {
787 chat_emit_permissions_error(1);
788 return;
789 }
790 chat_create_tables();
791 cgi_set_content_type("application/json");
792
793 if( zQuery[0] ){
794 iMax = db_int64(0, "SELECT max(msgid) FROM chat");
795 iMin = db_int64(0, "SELECT min(msgid) FROM chat");
796 if( '#'==zQuery[0] ){
797 /* Assume we're looking for an exact msgid match. */
798 ++zQuery;
799 blob_append_sql(&sql,
800 "SELECT msgid, datetime(mtime), xfrom, "
801 " xmsg, octet_length(file), fname, fmime, mdel, lmtime "
802 " FROM chat WHERE msgid=+%Q",
803 zQuery
804 );
805 }else{
806 char * zPat = search_simplify_pattern(zQuery);
807 blob_append_sql(&sql,
808 "SELECT * FROM ("
809 "SELECT c.msgid, datetime(c.mtime), c.xfrom, "
810 " highlight(chatfts1, 0, '<span class=\"match\">', '</span>'), "
811 " octet_length(c.file), c.fname, c.fmime, c.mdel, c.lmtime "
812 " FROM chatfts1(%Q) f, chat c "
813 " WHERE f.rowid=c.msgid"
814 " ORDER BY f.rowid DESC LIMIT %d"
815 ") ORDER BY 1 ASC", zPat, nLimit
816 );
817 fossil_free(zPat);
818 }
819 }else{
820 blob_append_sql(&sql,
821 "SELECT msgid, datetime(mtime), xfrom, "
822 " xmsg, octet_length(file), fname, fmime, mdel, lmtime"
823 " FROM chat WHERE msgid>=%d LIMIT %d",
824 iFirst, nLimit
825 );
826 }
827
828 db_prepare(&q1, "%s", blob_sql_text(&sql));
829 blob_reset(&sql);
830 blob_init(&json, "{\"msgs\":[\n", -1);
831 chat_poll_rowstojson(&q1, 0, &json);
832 db_finalize(&q1);
833 blob_appendf(&json, "\n], \"first\":%lld, \"last\":%lld}", iMin, iMax);
834 cgi_set_content(&json);
835 return;
836 }
837
838 /*
839 ** WEBPAGE: chat-fetch-one hidden loadavg-exempt
840 **
841 ** /chat-fetch-one/N
842 **
843
+142 -20
--- src/checkin.c
+++ src/checkin.c
@@ -592,26 +592,107 @@
592592
/* The status command ends with warnings about ambiguous leaves (forks). */
593593
if( command==STATUS ){
594594
leaf_ambiguity_warning(vid, vid);
595595
}
596596
}
597
+
598
+/* zIn is a string that is guaranteed to be followed by \n. Return
599
+** a pointer to the next line after the \n. The returned value might
600
+** point to the \000 string terminator.
601
+*/
602
+static const char *next_line(const char *zIn){
603
+ const char *z = strchr(zIn, '\n');
604
+ assert( z!=0 );
605
+ return z+1;
606
+}
607
+
608
+/* zIn is a non-empty list of filenames in sorted order and separated
609
+** by \n. There might be a cluster of lines that have the same n-character
610
+** prefix. Return a pointer to the start of the last line of that
611
+** cluster. The return value might be zIn if the first line of zIn is
612
+** unique in its first n character.
613
+*/
614
+static const char *last_line(const char *zIn, int n){
615
+ const char *zLast = zIn;
616
+ const char *z;
617
+ while( 1 ){
618
+ z = next_line(zLast);
619
+ if( z[0]==0 || (n>0 && strncmp(zIn, z, n)!=0) ) break;
620
+ zLast = z;
621
+ }
622
+ return zLast;
623
+}
624
+
625
+/*
626
+** Print a section of a filelist hierarchy graph. This is a helper
627
+** routine for print_filelist_as_tree() below.
628
+*/
629
+static const char *print_filelist_section(
630
+ const char *zIn, /* List of filenames, separated by \n */
631
+ const char *zLast, /* Last filename in the list to print */
632
+ const char *zPrefix, /* Prefix so put before each output line */
633
+ int nDir /* Ignore this many characters of directory name */
634
+){
635
+ /* Unicode box-drawing characters: U+251C, U+2514, U+2502 */
636
+ const char *zENTRY = "\342\224\234\342\224\200\342\224\200 ";
637
+ const char *zLASTE = "\342\224\224\342\224\200\342\224\200 ";
638
+ const char *zCONTU = "\342\224\202 ";
639
+ const char *zBLANK = " ";
640
+
641
+ while( zIn<=zLast ){
642
+ int i;
643
+ for(i=nDir; zIn[i]!='\n' && zIn[i]!='/'; i++){}
644
+ if( zIn[i]=='/' ){
645
+ char *zSubPrefix;
646
+ const char *zSubLast = last_line(zIn, i+1);
647
+ zSubPrefix = mprintf("%s%s", zPrefix, zSubLast==zLast ? zBLANK : zCONTU);
648
+ fossil_print("%s%s%.*s\n", zPrefix, zSubLast==zLast ? zLASTE : zENTRY,
649
+ i-nDir, &zIn[nDir]);
650
+ zIn = print_filelist_section(zIn, zSubLast, zSubPrefix, i+1);
651
+ fossil_free(zSubPrefix);
652
+ }else{
653
+ fossil_print("%s%s%.*s\n", zPrefix, zIn==zLast ? zLASTE : zENTRY,
654
+ i-nDir, &zIn[nDir]);
655
+ zIn = next_line(zIn);
656
+ }
657
+ }
658
+ return zIn;
659
+}
660
+
661
+/*
662
+** Input blob pList is a list of filenames, one filename per line,
663
+** in sorted order and with / directory separators. Output this list
664
+** as a tree in a manner similar to the "tree" command on Linux.
665
+*/
666
+static void print_filelist_as_tree(Blob *pList){
667
+ char *zAll;
668
+ const char *zLast;
669
+ fossil_print("%s\n", g.zLocalRoot);
670
+ zAll = blob_str(pList);
671
+ if( zAll[0] ){
672
+ zLast = last_line(zAll, 0);
673
+ print_filelist_section(zAll, zLast, "", 0);
674
+ }
675
+}
597676
598677
/*
599678
** Take care of -r version of ls command
600679
*/
601680
static void ls_cmd_rev(
602681
const char *zRev, /* Revision string given */
603682
int verboseFlag, /* Verbose flag given */
604683
int showAge, /* Age flag given */
605
- int timeOrder /* Order by time flag given */
684
+ int timeOrder, /* Order by time flag given */
685
+ int treeFmt /* Show output in the tree format */
606686
){
607687
Stmt q;
608688
char *zOrderBy = "pathname COLLATE nocase";
609689
char *zName;
610690
Blob where;
611691
int rid;
612692
int i;
693
+ Blob out;
613694
614695
/* Handle given file names */
615696
blob_zero(&where);
616697
for(i=2; i<g.argc; i++){
617698
Blob fname;
@@ -649,24 +730,31 @@
649730
" FROM fileage, blob\n"
650731
" WHERE blob.rid=fileage.fid %s\n"
651732
" ORDER BY %s;", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
652733
);
653734
blob_reset(&where);
735
+ if( treeFmt ) blob_init(&out, 0, 0);
654736
655737
while( db_step(&q)==SQLITE_ROW ){
656738
const char *zTime = db_column_text(&q,0);
657739
const char *zFile = db_column_text(&q,1);
658740
int size = db_column_int(&q,2);
659
- if( verboseFlag ){
741
+ if( treeFmt ){
742
+ blob_appendf(&out, "%s\n", zFile);
743
+ }else if( verboseFlag ){
660744
fossil_print("%s %7d %s\n", zTime, size, zFile);
661745
}else if( showAge ){
662746
fossil_print("%s %s\n", zTime, zFile);
663747
}else{
664748
fossil_print("%s\n", zFile);
665749
}
666750
}
667751
db_finalize(&q);
752
+ if( treeFmt ){
753
+ print_filelist_as_tree(&out);
754
+ blob_reset(&out);
755
+ }
668756
}
669757
670758
/*
671759
** COMMAND: ls
672760
**
@@ -692,24 +780,26 @@
692780
** path and name (case insensitive sort if -r). If neither --age nor -r
693781
** are used, -t sorts by modification time, otherwise by commit time.
694782
**
695783
** Options:
696784
** --age Show when each file was committed
697
-** -v|--verbose Provide extra information about each file
698
-** -t Sort output in time order
785
+** --hash With -v, verify file status using hashing
786
+** rather than relying on file sizes and mtimes
699787
** -r VERSION The specific check-in to list
700788
** -R|--repository REPO Extract info from repository REPO
701
-** --hash With -v, verify file status using hashing
702
-** rather than relying on file sizes and mtimes
789
+** -t Sort output in time order
790
+** --tree Tree format
791
+** -v|--verbose Provide extra information about each file
703792
**
704
-** See also: [[changes]], [[extras]], [[status]]
793
+** See also: [[changes]], [[extras]], [[status]], [[tree]]
705794
*/
706795
void ls_cmd(void){
707796
int vid;
708797
Stmt q;
709798
int verboseFlag;
710799
int showAge;
800
+ int treeFmt;
711801
int timeOrder;
712802
char *zOrderBy = "pathname";
713803
Blob where;
714804
int i;
715805
int useHash = 0;
@@ -724,15 +814,19 @@
724814
zRev = find_option("r","r",1);
725815
timeOrder = find_option("t","t",0)!=0;
726816
if( verboseFlag ){
727817
useHash = find_option("hash",0,0)!=0;
728818
}
819
+ treeFmt = find_option("tree",0,0)!=0;
820
+ if( treeFmt ){
821
+ if( zRev==0 ) zRev = "current";
822
+ }
729823
730824
if( zRev!=0 ){
731825
db_find_and_open_repository(0, 0);
732826
verify_all_options();
733
- ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder);
827
+ ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder,treeFmt);
734828
return;
735829
}else if( find_option("R",0,1)!=0 ){
736830
fossil_fatal("the -r is required in addition to -R");
737831
}
738832
@@ -828,10 +922,35 @@
828922
}
829923
free(zFullName);
830924
}
831925
db_finalize(&q);
832926
}
927
+
928
+/*
929
+** COMMAND: tree
930
+**
931
+** Usage: %fossil tree ?OPTIONS? ?PATHS ...?
932
+**
933
+** List all files in the current check-out in after the fashion of the
934
+** "tree" command. If PATHS is included, only the named files
935
+** (or their children if directories) are shown.
936
+**
937
+** Options:
938
+** -r VERSION The specific check-in to list
939
+** -R|--repository REPO Extract info from repository REPO
940
+**
941
+** See also: [[ls]]
942
+*/
943
+void tree_cmd(void){
944
+ const char *zRev;
945
+
946
+ zRev = find_option("r","r",1);
947
+ if( zRev==0 ) zRev = "current";
948
+ db_find_and_open_repository(0, 0);
949
+ verify_all_options();
950
+ ls_cmd_rev(zRev,0,0,0,1);
951
+}
833952
834953
/*
835954
** COMMAND: extras
836955
**
837956
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
@@ -856,19 +975,21 @@
856975
** --dotfiles Include files beginning with a dot (".")
857976
** --header Identify the repository if there are extras
858977
** --ignore CSG Ignore files matching patterns from the argument
859978
** --rel-paths Display pathnames relative to the current working
860979
** directory
980
+** --tree Show output in the tree format
861981
**
862982
** See also: [[changes]], [[clean]], [[status]]
863983
*/
864984
void extras_cmd(void){
865985
Blob report = BLOB_INITIALIZER;
866986
const char *zIgnoreFlag = find_option("ignore",0,1);
867987
unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
868988
unsigned flags = C_EXTRA;
869989
int showHdr = find_option("header",0,0)!=0;
990
+ int treeFmt = find_option("tree",0,0)!=0;
870991
Glob *pIgnore;
871992
872993
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
873994
db_must_be_within_tree();
874995
@@ -875,10 +996,14 @@
875996
if( determine_cwd_relative_option() ){
876997
flags |= C_RELPATH;
877998
}
878999
8791000
if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
1001
+
1002
+ if( treeFmt ){
1003
+ flags &= ~C_RELPATH;
1004
+ }
8801005
8811006
/* We should be done with options.. */
8821007
verify_all_options();
8831008
8841009
if( zIgnoreFlag==0 ){
@@ -893,11 +1018,15 @@
8931018
if( blob_size(&report) ){
8941019
if( showHdr ){
8951020
fossil_print("Extras for %s at %s:\n", db_get("project-name","<unnamed>"),
8961021
g.zLocalRoot);
8971022
}
898
- blob_write_to_file(&report, "-");
1023
+ if( treeFmt ){
1024
+ print_filelist_as_tree(&report);
1025
+ }else{
1026
+ blob_write_to_file(&report, "-");
1027
+ }
8991028
}
9001029
blob_reset(&report);
9011030
}
9021031
9031032
/*
@@ -1373,11 +1502,12 @@
13731502
int i;
13741503
for(i=0; g.aCommitFile[i]!=0; ++i){}
13751504
diffFiles = fossil_malloc_zero((i+1) * sizeof(*diffFiles));
13761505
for(i=0; g.aCommitFile[i]!=0; ++i){
13771506
blob_append_sql(&sql,
1378
- "SELECT pathname, deleted, rid WHERE id=%d",
1507
+ "SELECT pathname, deleted, rid "
1508
+ "FROM vfile WHERE id=%d",
13791509
g.aCommitFile[i]);
13801510
db_prepare(&q, "%s", blob_sql_text(&sql));
13811511
blob_reset(&sql);
13821512
assert( db_step(&q)==SQLITE_ROW );
13831513
diffFiles[i].zName = fossil_strdup(db_column_text(&q, 0));
@@ -2180,12 +2310,10 @@
21802310
** --allow-older Allow a commit older than its ancestor
21812311
** --baseline Use a baseline manifest in the commit process
21822312
** --bgcolor COLOR Apply COLOR to this one check-in only
21832313
** --branch NEW-BRANCH-NAME Check in to this new branch
21842314
** --branchcolor COLOR Apply given COLOR to the branch
2185
-** ("auto" lets Fossil choose it automatically,
2186
-** even for private branches)
21872315
** --close Close the branch being committed
21882316
** --date-override DATETIME DATE to use instead of 'now'
21892317
** --delta Use a delta manifest in the commit process
21902318
** --hash Verify file status using hashing rather
21912319
** than relying on file mtimes
@@ -2204,10 +2332,11 @@
22042332
** input and assumes an answer of 'No' for every
22052333
** question.
22062334
** --no-warnings Omit all warnings about file contents
22072335
** --no-verify Do not run before-commit hooks
22082336
** --nosign Do not attempt to sign this commit with gpg
2337
+** --nosync Do not auto-sync prior to committing
22092338
** --override-lock Allow a check-in even though parent is locked
22102339
** --private Do not sync changes and their descendants
22112340
** --tag TAG-NAME Assign given tag TAG-NAME to the check-in
22122341
** --trace Debug tracing
22132342
** --user-override USER USER to use instead of the current default
@@ -2264,19 +2393,19 @@
22642393
int nConflict = 0; /* Number of unresolved merge conflicts */
22652394
int abortCommit = 0; /* Abort the commit due to text format conversions */
22662395
Blob ans; /* Answer to continuation prompts */
22672396
char cReply; /* First character of ans */
22682397
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2269
- int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
22702398
int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
22712399
int mxSize;
22722400
22732401
memset(&sCiInfo, 0, sizeof(sCiInfo));
22742402
url_proxy_options();
22752403
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
22762404
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
22772405
noSign = find_option("nosign",0,0)!=0;
2406
+ if( find_option("nosync",0,0) ) g.fNoSync = 1;
22782407
privateFlag = find_option("private",0,0)!=0;
22792408
forceDelta = find_option("delta",0,0)!=0;
22802409
forceBaseline = find_option("baseline",0,0)!=0;
22812410
db_must_be_within_tree();
22822411
if( db_get_boolean("dont-commit",0) ){
@@ -2306,14 +2435,10 @@
23062435
noVerify = find_option("no-verify",0,0)!=0;
23072436
bTrace = find_option("trace",0,0)!=0;
23082437
sCiInfo.zBranch = find_option("branch","b",1);
23092438
sCiInfo.zColor = find_option("bgcolor",0,1);
23102439
sCiInfo.zBrClr = find_option("branchcolor",0,1);
2311
- if ( fossil_strncmp(sCiInfo.zBrClr, "auto", 4)==0 ) {
2312
- bAutoBrClr = 1;
2313
- sCiInfo.zBrClr = 0;
2314
- }
23152440
sCiInfo.closeFlag = find_option("close",0,0)!=0;
23162441
sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
23172442
sCiInfo.zMimetype = find_option("mimetype",0,1);
23182443
sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
23192444
while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2351,13 +2476,10 @@
23512476
if( privateFlag && !privateParent ){
23522477
/* Apply default branch name ("private") and color ("orange") if not
23532478
** specified otherwise on the command-line, and if the parent is not
23542479
** already private. */
23552480
if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
2356
- if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 && !bAutoBrClr) {
2357
- sCiInfo.zBrClr = "#fec084";
2358
- }
23592481
}
23602482
23612483
/* Do not allow the creation of a new branch using an existing open
23622484
** branch name unless the --force flag is used */
23632485
if( sCiInfo.zBranch!=0
23642486
--- src/checkin.c
+++ src/checkin.c
@@ -592,26 +592,107 @@
592 /* The status command ends with warnings about ambiguous leaves (forks). */
593 if( command==STATUS ){
594 leaf_ambiguity_warning(vid, vid);
595 }
596 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
598 /*
599 ** Take care of -r version of ls command
600 */
601 static void ls_cmd_rev(
602 const char *zRev, /* Revision string given */
603 int verboseFlag, /* Verbose flag given */
604 int showAge, /* Age flag given */
605 int timeOrder /* Order by time flag given */
 
606 ){
607 Stmt q;
608 char *zOrderBy = "pathname COLLATE nocase";
609 char *zName;
610 Blob where;
611 int rid;
612 int i;
 
613
614 /* Handle given file names */
615 blob_zero(&where);
616 for(i=2; i<g.argc; i++){
617 Blob fname;
@@ -649,24 +730,31 @@
649 " FROM fileage, blob\n"
650 " WHERE blob.rid=fileage.fid %s\n"
651 " ORDER BY %s;", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
652 );
653 blob_reset(&where);
 
654
655 while( db_step(&q)==SQLITE_ROW ){
656 const char *zTime = db_column_text(&q,0);
657 const char *zFile = db_column_text(&q,1);
658 int size = db_column_int(&q,2);
659 if( verboseFlag ){
 
 
660 fossil_print("%s %7d %s\n", zTime, size, zFile);
661 }else if( showAge ){
662 fossil_print("%s %s\n", zTime, zFile);
663 }else{
664 fossil_print("%s\n", zFile);
665 }
666 }
667 db_finalize(&q);
 
 
 
 
668 }
669
670 /*
671 ** COMMAND: ls
672 **
@@ -692,24 +780,26 @@
692 ** path and name (case insensitive sort if -r). If neither --age nor -r
693 ** are used, -t sorts by modification time, otherwise by commit time.
694 **
695 ** Options:
696 ** --age Show when each file was committed
697 ** -v|--verbose Provide extra information about each file
698 ** -t Sort output in time order
699 ** -r VERSION The specific check-in to list
700 ** -R|--repository REPO Extract info from repository REPO
701 ** --hash With -v, verify file status using hashing
702 ** rather than relying on file sizes and mtimes
 
703 **
704 ** See also: [[changes]], [[extras]], [[status]]
705 */
706 void ls_cmd(void){
707 int vid;
708 Stmt q;
709 int verboseFlag;
710 int showAge;
 
711 int timeOrder;
712 char *zOrderBy = "pathname";
713 Blob where;
714 int i;
715 int useHash = 0;
@@ -724,15 +814,19 @@
724 zRev = find_option("r","r",1);
725 timeOrder = find_option("t","t",0)!=0;
726 if( verboseFlag ){
727 useHash = find_option("hash",0,0)!=0;
728 }
 
 
 
 
729
730 if( zRev!=0 ){
731 db_find_and_open_repository(0, 0);
732 verify_all_options();
733 ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder);
734 return;
735 }else if( find_option("R",0,1)!=0 ){
736 fossil_fatal("the -r is required in addition to -R");
737 }
738
@@ -828,10 +922,35 @@
828 }
829 free(zFullName);
830 }
831 db_finalize(&q);
832 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
833
834 /*
835 ** COMMAND: extras
836 **
837 ** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
@@ -856,19 +975,21 @@
856 ** --dotfiles Include files beginning with a dot (".")
857 ** --header Identify the repository if there are extras
858 ** --ignore CSG Ignore files matching patterns from the argument
859 ** --rel-paths Display pathnames relative to the current working
860 ** directory
 
861 **
862 ** See also: [[changes]], [[clean]], [[status]]
863 */
864 void extras_cmd(void){
865 Blob report = BLOB_INITIALIZER;
866 const char *zIgnoreFlag = find_option("ignore",0,1);
867 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
868 unsigned flags = C_EXTRA;
869 int showHdr = find_option("header",0,0)!=0;
 
870 Glob *pIgnore;
871
872 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
873 db_must_be_within_tree();
874
@@ -875,10 +996,14 @@
875 if( determine_cwd_relative_option() ){
876 flags |= C_RELPATH;
877 }
878
879 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
 
 
 
 
880
881 /* We should be done with options.. */
882 verify_all_options();
883
884 if( zIgnoreFlag==0 ){
@@ -893,11 +1018,15 @@
893 if( blob_size(&report) ){
894 if( showHdr ){
895 fossil_print("Extras for %s at %s:\n", db_get("project-name","<unnamed>"),
896 g.zLocalRoot);
897 }
898 blob_write_to_file(&report, "-");
 
 
 
 
899 }
900 blob_reset(&report);
901 }
902
903 /*
@@ -1373,11 +1502,12 @@
1373 int i;
1374 for(i=0; g.aCommitFile[i]!=0; ++i){}
1375 diffFiles = fossil_malloc_zero((i+1) * sizeof(*diffFiles));
1376 for(i=0; g.aCommitFile[i]!=0; ++i){
1377 blob_append_sql(&sql,
1378 "SELECT pathname, deleted, rid WHERE id=%d",
 
1379 g.aCommitFile[i]);
1380 db_prepare(&q, "%s", blob_sql_text(&sql));
1381 blob_reset(&sql);
1382 assert( db_step(&q)==SQLITE_ROW );
1383 diffFiles[i].zName = fossil_strdup(db_column_text(&q, 0));
@@ -2180,12 +2310,10 @@
2180 ** --allow-older Allow a commit older than its ancestor
2181 ** --baseline Use a baseline manifest in the commit process
2182 ** --bgcolor COLOR Apply COLOR to this one check-in only
2183 ** --branch NEW-BRANCH-NAME Check in to this new branch
2184 ** --branchcolor COLOR Apply given COLOR to the branch
2185 ** ("auto" lets Fossil choose it automatically,
2186 ** even for private branches)
2187 ** --close Close the branch being committed
2188 ** --date-override DATETIME DATE to use instead of 'now'
2189 ** --delta Use a delta manifest in the commit process
2190 ** --hash Verify file status using hashing rather
2191 ** than relying on file mtimes
@@ -2204,10 +2332,11 @@
2204 ** input and assumes an answer of 'No' for every
2205 ** question.
2206 ** --no-warnings Omit all warnings about file contents
2207 ** --no-verify Do not run before-commit hooks
2208 ** --nosign Do not attempt to sign this commit with gpg
 
2209 ** --override-lock Allow a check-in even though parent is locked
2210 ** --private Do not sync changes and their descendants
2211 ** --tag TAG-NAME Assign given tag TAG-NAME to the check-in
2212 ** --trace Debug tracing
2213 ** --user-override USER USER to use instead of the current default
@@ -2264,19 +2393,19 @@
2264 int nConflict = 0; /* Number of unresolved merge conflicts */
2265 int abortCommit = 0; /* Abort the commit due to text format conversions */
2266 Blob ans; /* Answer to continuation prompts */
2267 char cReply; /* First character of ans */
2268 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2269 int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
2270 int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
2271 int mxSize;
2272
2273 memset(&sCiInfo, 0, sizeof(sCiInfo));
2274 url_proxy_options();
2275 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2276 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2277 noSign = find_option("nosign",0,0)!=0;
 
2278 privateFlag = find_option("private",0,0)!=0;
2279 forceDelta = find_option("delta",0,0)!=0;
2280 forceBaseline = find_option("baseline",0,0)!=0;
2281 db_must_be_within_tree();
2282 if( db_get_boolean("dont-commit",0) ){
@@ -2306,14 +2435,10 @@
2306 noVerify = find_option("no-verify",0,0)!=0;
2307 bTrace = find_option("trace",0,0)!=0;
2308 sCiInfo.zBranch = find_option("branch","b",1);
2309 sCiInfo.zColor = find_option("bgcolor",0,1);
2310 sCiInfo.zBrClr = find_option("branchcolor",0,1);
2311 if ( fossil_strncmp(sCiInfo.zBrClr, "auto", 4)==0 ) {
2312 bAutoBrClr = 1;
2313 sCiInfo.zBrClr = 0;
2314 }
2315 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2316 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2317 sCiInfo.zMimetype = find_option("mimetype",0,1);
2318 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2319 while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2351,13 +2476,10 @@
2351 if( privateFlag && !privateParent ){
2352 /* Apply default branch name ("private") and color ("orange") if not
2353 ** specified otherwise on the command-line, and if the parent is not
2354 ** already private. */
2355 if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
2356 if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 && !bAutoBrClr) {
2357 sCiInfo.zBrClr = "#fec084";
2358 }
2359 }
2360
2361 /* Do not allow the creation of a new branch using an existing open
2362 ** branch name unless the --force flag is used */
2363 if( sCiInfo.zBranch!=0
2364
--- src/checkin.c
+++ src/checkin.c
@@ -592,26 +592,107 @@
592 /* The status command ends with warnings about ambiguous leaves (forks). */
593 if( command==STATUS ){
594 leaf_ambiguity_warning(vid, vid);
595 }
596 }
597
598 /* zIn is a string that is guaranteed to be followed by \n. Return
599 ** a pointer to the next line after the \n. The returned value might
600 ** point to the \000 string terminator.
601 */
602 static const char *next_line(const char *zIn){
603 const char *z = strchr(zIn, '\n');
604 assert( z!=0 );
605 return z+1;
606 }
607
608 /* zIn is a non-empty list of filenames in sorted order and separated
609 ** by \n. There might be a cluster of lines that have the same n-character
610 ** prefix. Return a pointer to the start of the last line of that
611 ** cluster. The return value might be zIn if the first line of zIn is
612 ** unique in its first n character.
613 */
614 static const char *last_line(const char *zIn, int n){
615 const char *zLast = zIn;
616 const char *z;
617 while( 1 ){
618 z = next_line(zLast);
619 if( z[0]==0 || (n>0 && strncmp(zIn, z, n)!=0) ) break;
620 zLast = z;
621 }
622 return zLast;
623 }
624
625 /*
626 ** Print a section of a filelist hierarchy graph. This is a helper
627 ** routine for print_filelist_as_tree() below.
628 */
629 static const char *print_filelist_section(
630 const char *zIn, /* List of filenames, separated by \n */
631 const char *zLast, /* Last filename in the list to print */
632 const char *zPrefix, /* Prefix so put before each output line */
633 int nDir /* Ignore this many characters of directory name */
634 ){
635 /* Unicode box-drawing characters: U+251C, U+2514, U+2502 */
636 const char *zENTRY = "\342\224\234\342\224\200\342\224\200 ";
637 const char *zLASTE = "\342\224\224\342\224\200\342\224\200 ";
638 const char *zCONTU = "\342\224\202 ";
639 const char *zBLANK = " ";
640
641 while( zIn<=zLast ){
642 int i;
643 for(i=nDir; zIn[i]!='\n' && zIn[i]!='/'; i++){}
644 if( zIn[i]=='/' ){
645 char *zSubPrefix;
646 const char *zSubLast = last_line(zIn, i+1);
647 zSubPrefix = mprintf("%s%s", zPrefix, zSubLast==zLast ? zBLANK : zCONTU);
648 fossil_print("%s%s%.*s\n", zPrefix, zSubLast==zLast ? zLASTE : zENTRY,
649 i-nDir, &zIn[nDir]);
650 zIn = print_filelist_section(zIn, zSubLast, zSubPrefix, i+1);
651 fossil_free(zSubPrefix);
652 }else{
653 fossil_print("%s%s%.*s\n", zPrefix, zIn==zLast ? zLASTE : zENTRY,
654 i-nDir, &zIn[nDir]);
655 zIn = next_line(zIn);
656 }
657 }
658 return zIn;
659 }
660
661 /*
662 ** Input blob pList is a list of filenames, one filename per line,
663 ** in sorted order and with / directory separators. Output this list
664 ** as a tree in a manner similar to the "tree" command on Linux.
665 */
666 static void print_filelist_as_tree(Blob *pList){
667 char *zAll;
668 const char *zLast;
669 fossil_print("%s\n", g.zLocalRoot);
670 zAll = blob_str(pList);
671 if( zAll[0] ){
672 zLast = last_line(zAll, 0);
673 print_filelist_section(zAll, zLast, "", 0);
674 }
675 }
676
677 /*
678 ** Take care of -r version of ls command
679 */
680 static void ls_cmd_rev(
681 const char *zRev, /* Revision string given */
682 int verboseFlag, /* Verbose flag given */
683 int showAge, /* Age flag given */
684 int timeOrder, /* Order by time flag given */
685 int treeFmt /* Show output in the tree format */
686 ){
687 Stmt q;
688 char *zOrderBy = "pathname COLLATE nocase";
689 char *zName;
690 Blob where;
691 int rid;
692 int i;
693 Blob out;
694
695 /* Handle given file names */
696 blob_zero(&where);
697 for(i=2; i<g.argc; i++){
698 Blob fname;
@@ -649,24 +730,31 @@
730 " FROM fileage, blob\n"
731 " WHERE blob.rid=fileage.fid %s\n"
732 " ORDER BY %s;", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
733 );
734 blob_reset(&where);
735 if( treeFmt ) blob_init(&out, 0, 0);
736
737 while( db_step(&q)==SQLITE_ROW ){
738 const char *zTime = db_column_text(&q,0);
739 const char *zFile = db_column_text(&q,1);
740 int size = db_column_int(&q,2);
741 if( treeFmt ){
742 blob_appendf(&out, "%s\n", zFile);
743 }else if( verboseFlag ){
744 fossil_print("%s %7d %s\n", zTime, size, zFile);
745 }else if( showAge ){
746 fossil_print("%s %s\n", zTime, zFile);
747 }else{
748 fossil_print("%s\n", zFile);
749 }
750 }
751 db_finalize(&q);
752 if( treeFmt ){
753 print_filelist_as_tree(&out);
754 blob_reset(&out);
755 }
756 }
757
758 /*
759 ** COMMAND: ls
760 **
@@ -692,24 +780,26 @@
780 ** path and name (case insensitive sort if -r). If neither --age nor -r
781 ** are used, -t sorts by modification time, otherwise by commit time.
782 **
783 ** Options:
784 ** --age Show when each file was committed
785 ** --hash With -v, verify file status using hashing
786 ** rather than relying on file sizes and mtimes
787 ** -r VERSION The specific check-in to list
788 ** -R|--repository REPO Extract info from repository REPO
789 ** -t Sort output in time order
790 ** --tree Tree format
791 ** -v|--verbose Provide extra information about each file
792 **
793 ** See also: [[changes]], [[extras]], [[status]], [[tree]]
794 */
795 void ls_cmd(void){
796 int vid;
797 Stmt q;
798 int verboseFlag;
799 int showAge;
800 int treeFmt;
801 int timeOrder;
802 char *zOrderBy = "pathname";
803 Blob where;
804 int i;
805 int useHash = 0;
@@ -724,15 +814,19 @@
814 zRev = find_option("r","r",1);
815 timeOrder = find_option("t","t",0)!=0;
816 if( verboseFlag ){
817 useHash = find_option("hash",0,0)!=0;
818 }
819 treeFmt = find_option("tree",0,0)!=0;
820 if( treeFmt ){
821 if( zRev==0 ) zRev = "current";
822 }
823
824 if( zRev!=0 ){
825 db_find_and_open_repository(0, 0);
826 verify_all_options();
827 ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder,treeFmt);
828 return;
829 }else if( find_option("R",0,1)!=0 ){
830 fossil_fatal("the -r is required in addition to -R");
831 }
832
@@ -828,10 +922,35 @@
922 }
923 free(zFullName);
924 }
925 db_finalize(&q);
926 }
927
928 /*
929 ** COMMAND: tree
930 **
931 ** Usage: %fossil tree ?OPTIONS? ?PATHS ...?
932 **
933 ** List all files in the current check-out in after the fashion of the
934 ** "tree" command. If PATHS is included, only the named files
935 ** (or their children if directories) are shown.
936 **
937 ** Options:
938 ** -r VERSION The specific check-in to list
939 ** -R|--repository REPO Extract info from repository REPO
940 **
941 ** See also: [[ls]]
942 */
943 void tree_cmd(void){
944 const char *zRev;
945
946 zRev = find_option("r","r",1);
947 if( zRev==0 ) zRev = "current";
948 db_find_and_open_repository(0, 0);
949 verify_all_options();
950 ls_cmd_rev(zRev,0,0,0,1);
951 }
952
953 /*
954 ** COMMAND: extras
955 **
956 ** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
@@ -856,19 +975,21 @@
975 ** --dotfiles Include files beginning with a dot (".")
976 ** --header Identify the repository if there are extras
977 ** --ignore CSG Ignore files matching patterns from the argument
978 ** --rel-paths Display pathnames relative to the current working
979 ** directory
980 ** --tree Show output in the tree format
981 **
982 ** See also: [[changes]], [[clean]], [[status]]
983 */
984 void extras_cmd(void){
985 Blob report = BLOB_INITIALIZER;
986 const char *zIgnoreFlag = find_option("ignore",0,1);
987 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
988 unsigned flags = C_EXTRA;
989 int showHdr = find_option("header",0,0)!=0;
990 int treeFmt = find_option("tree",0,0)!=0;
991 Glob *pIgnore;
992
993 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
994 db_must_be_within_tree();
995
@@ -875,10 +996,14 @@
996 if( determine_cwd_relative_option() ){
997 flags |= C_RELPATH;
998 }
999
1000 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
1001
1002 if( treeFmt ){
1003 flags &= ~C_RELPATH;
1004 }
1005
1006 /* We should be done with options.. */
1007 verify_all_options();
1008
1009 if( zIgnoreFlag==0 ){
@@ -893,11 +1018,15 @@
1018 if( blob_size(&report) ){
1019 if( showHdr ){
1020 fossil_print("Extras for %s at %s:\n", db_get("project-name","<unnamed>"),
1021 g.zLocalRoot);
1022 }
1023 if( treeFmt ){
1024 print_filelist_as_tree(&report);
1025 }else{
1026 blob_write_to_file(&report, "-");
1027 }
1028 }
1029 blob_reset(&report);
1030 }
1031
1032 /*
@@ -1373,11 +1502,12 @@
1502 int i;
1503 for(i=0; g.aCommitFile[i]!=0; ++i){}
1504 diffFiles = fossil_malloc_zero((i+1) * sizeof(*diffFiles));
1505 for(i=0; g.aCommitFile[i]!=0; ++i){
1506 blob_append_sql(&sql,
1507 "SELECT pathname, deleted, rid "
1508 "FROM vfile WHERE id=%d",
1509 g.aCommitFile[i]);
1510 db_prepare(&q, "%s", blob_sql_text(&sql));
1511 blob_reset(&sql);
1512 assert( db_step(&q)==SQLITE_ROW );
1513 diffFiles[i].zName = fossil_strdup(db_column_text(&q, 0));
@@ -2180,12 +2310,10 @@
2310 ** --allow-older Allow a commit older than its ancestor
2311 ** --baseline Use a baseline manifest in the commit process
2312 ** --bgcolor COLOR Apply COLOR to this one check-in only
2313 ** --branch NEW-BRANCH-NAME Check in to this new branch
2314 ** --branchcolor COLOR Apply given COLOR to the branch
 
 
2315 ** --close Close the branch being committed
2316 ** --date-override DATETIME DATE to use instead of 'now'
2317 ** --delta Use a delta manifest in the commit process
2318 ** --hash Verify file status using hashing rather
2319 ** than relying on file mtimes
@@ -2204,10 +2332,11 @@
2332 ** input and assumes an answer of 'No' for every
2333 ** question.
2334 ** --no-warnings Omit all warnings about file contents
2335 ** --no-verify Do not run before-commit hooks
2336 ** --nosign Do not attempt to sign this commit with gpg
2337 ** --nosync Do not auto-sync prior to committing
2338 ** --override-lock Allow a check-in even though parent is locked
2339 ** --private Do not sync changes and their descendants
2340 ** --tag TAG-NAME Assign given tag TAG-NAME to the check-in
2341 ** --trace Debug tracing
2342 ** --user-override USER USER to use instead of the current default
@@ -2264,19 +2393,19 @@
2393 int nConflict = 0; /* Number of unresolved merge conflicts */
2394 int abortCommit = 0; /* Abort the commit due to text format conversions */
2395 Blob ans; /* Answer to continuation prompts */
2396 char cReply; /* First character of ans */
2397 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
 
2398 int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
2399 int mxSize;
2400
2401 memset(&sCiInfo, 0, sizeof(sCiInfo));
2402 url_proxy_options();
2403 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2404 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2405 noSign = find_option("nosign",0,0)!=0;
2406 if( find_option("nosync",0,0) ) g.fNoSync = 1;
2407 privateFlag = find_option("private",0,0)!=0;
2408 forceDelta = find_option("delta",0,0)!=0;
2409 forceBaseline = find_option("baseline",0,0)!=0;
2410 db_must_be_within_tree();
2411 if( db_get_boolean("dont-commit",0) ){
@@ -2306,14 +2435,10 @@
2435 noVerify = find_option("no-verify",0,0)!=0;
2436 bTrace = find_option("trace",0,0)!=0;
2437 sCiInfo.zBranch = find_option("branch","b",1);
2438 sCiInfo.zColor = find_option("bgcolor",0,1);
2439 sCiInfo.zBrClr = find_option("branchcolor",0,1);
 
 
 
 
2440 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2441 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2442 sCiInfo.zMimetype = find_option("mimetype",0,1);
2443 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2444 while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2351,13 +2476,10 @@
2476 if( privateFlag && !privateParent ){
2477 /* Apply default branch name ("private") and color ("orange") if not
2478 ** specified otherwise on the command-line, and if the parent is not
2479 ** already private. */
2480 if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
 
 
 
2481 }
2482
2483 /* Do not allow the creation of a new branch using an existing open
2484 ** branch name unless the --force flag is used */
2485 if( sCiInfo.zBranch!=0
2486
+13 -1
--- src/clone.c
+++ src/clone.c
@@ -136,10 +136,11 @@
136136
** --ssl-identity FILENAME Use the SSL identity if requested by the server
137137
** --transport-command CMD Use CMD to move messages to the server and back
138138
** -u|--unversioned Also sync unversioned content
139139
** -v|--verbose Show more statistics in output
140140
** --workdir DIR Also open a check-out in DIR
141
+** --xverbose Extra debugging output
141142
**
142143
** See also: [[init]], [[open]]
143144
*/
144145
void clone_cmd(void){
145146
char *zPassword;
@@ -161,10 +162,11 @@
161162
if( find_option("save-http-password",0,0)!=0 ){
162163
urlFlags &= ~URL_PROMPT_PW;
163164
urlFlags |= URL_REMEMBER_PW;
164165
}
165166
if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
167
+ if( find_option("xverbose",0,0)!=0) syncFlags |= SYNC_XVERBOSE;
166168
if( find_option("unversioned","u",0)!=0 ){
167169
syncFlags |= SYNC_UNVERSIONED;
168170
if( syncFlags & SYNC_VERBOSE ){
169171
syncFlags |= SYNC_UV_TRACE;
170172
}
@@ -267,11 +269,21 @@
267269
verify_cancel();
268270
db_end_transaction(0);
269271
db_close(1);
270272
if( nErr ){
271273
file_delete(zRepo);
272
- fossil_fatal("server returned an error - clone aborted");
274
+ if( g.fHttpTrace ){
275
+ fossil_fatal(
276
+ "server returned an error - clone aborted\n\n%s",
277
+ http_last_trace_reply()
278
+ );
279
+ }else{
280
+ fossil_fatal(
281
+ "server returned an error - clone aborted\n"
282
+ "Rerun using --httptrace for more detail"
283
+ );
284
+ }
273285
}
274286
db_open_repository(zRepo);
275287
}
276288
db_begin_transaction();
277289
if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
278290
--- src/clone.c
+++ src/clone.c
@@ -136,10 +136,11 @@
136 ** --ssl-identity FILENAME Use the SSL identity if requested by the server
137 ** --transport-command CMD Use CMD to move messages to the server and back
138 ** -u|--unversioned Also sync unversioned content
139 ** -v|--verbose Show more statistics in output
140 ** --workdir DIR Also open a check-out in DIR
 
141 **
142 ** See also: [[init]], [[open]]
143 */
144 void clone_cmd(void){
145 char *zPassword;
@@ -161,10 +162,11 @@
161 if( find_option("save-http-password",0,0)!=0 ){
162 urlFlags &= ~URL_PROMPT_PW;
163 urlFlags |= URL_REMEMBER_PW;
164 }
165 if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
 
166 if( find_option("unversioned","u",0)!=0 ){
167 syncFlags |= SYNC_UNVERSIONED;
168 if( syncFlags & SYNC_VERBOSE ){
169 syncFlags |= SYNC_UV_TRACE;
170 }
@@ -267,11 +269,21 @@
267 verify_cancel();
268 db_end_transaction(0);
269 db_close(1);
270 if( nErr ){
271 file_delete(zRepo);
272 fossil_fatal("server returned an error - clone aborted");
 
 
 
 
 
 
 
 
 
 
273 }
274 db_open_repository(zRepo);
275 }
276 db_begin_transaction();
277 if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
278
--- src/clone.c
+++ src/clone.c
@@ -136,10 +136,11 @@
136 ** --ssl-identity FILENAME Use the SSL identity if requested by the server
137 ** --transport-command CMD Use CMD to move messages to the server and back
138 ** -u|--unversioned Also sync unversioned content
139 ** -v|--verbose Show more statistics in output
140 ** --workdir DIR Also open a check-out in DIR
141 ** --xverbose Extra debugging output
142 **
143 ** See also: [[init]], [[open]]
144 */
145 void clone_cmd(void){
146 char *zPassword;
@@ -161,10 +162,11 @@
162 if( find_option("save-http-password",0,0)!=0 ){
163 urlFlags &= ~URL_PROMPT_PW;
164 urlFlags |= URL_REMEMBER_PW;
165 }
166 if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
167 if( find_option("xverbose",0,0)!=0) syncFlags |= SYNC_XVERBOSE;
168 if( find_option("unversioned","u",0)!=0 ){
169 syncFlags |= SYNC_UNVERSIONED;
170 if( syncFlags & SYNC_VERBOSE ){
171 syncFlags |= SYNC_UV_TRACE;
172 }
@@ -267,11 +269,21 @@
269 verify_cancel();
270 db_end_transaction(0);
271 db_close(1);
272 if( nErr ){
273 file_delete(zRepo);
274 if( g.fHttpTrace ){
275 fossil_fatal(
276 "server returned an error - clone aborted\n\n%s",
277 http_last_trace_reply()
278 );
279 }else{
280 fossil_fatal(
281 "server returned an error - clone aborted\n"
282 "Rerun using --httptrace for more detail"
283 );
284 }
285 }
286 db_open_repository(zRepo);
287 }
288 db_begin_transaction();
289 if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
290
+2 -1
--- src/db.c
+++ src/db.c
@@ -3230,11 +3230,12 @@
32303230
** repository file from which to copy the initial settings. When a template
32313231
** repository is used, almost all of the settings accessible from the setup
32323232
** page, either directly or indirectly, will be copied. Normal users and
32333233
** their associated permissions will not be copied; however, the system
32343234
** default users "anonymous", "nobody", "reader", "developer", and their
3235
-** associated permissions will be copied.
3235
+** associated permissions will be copied. In case of SQL errors, rebuild the
3236
+** template repository and try again.
32363237
**
32373238
** Options:
32383239
** --template FILE Copy settings from repository file
32393240
** -A|--admin-user USERNAME Select given USERNAME as admin user
32403241
** --date-override DATETIME Use DATETIME as time of the initial check-in
32413242
--- src/db.c
+++ src/db.c
@@ -3230,11 +3230,12 @@
3230 ** repository file from which to copy the initial settings. When a template
3231 ** repository is used, almost all of the settings accessible from the setup
3232 ** page, either directly or indirectly, will be copied. Normal users and
3233 ** their associated permissions will not be copied; however, the system
3234 ** default users "anonymous", "nobody", "reader", "developer", and their
3235 ** associated permissions will be copied.
 
3236 **
3237 ** Options:
3238 ** --template FILE Copy settings from repository file
3239 ** -A|--admin-user USERNAME Select given USERNAME as admin user
3240 ** --date-override DATETIME Use DATETIME as time of the initial check-in
3241
--- src/db.c
+++ src/db.c
@@ -3230,11 +3230,12 @@
3230 ** repository file from which to copy the initial settings. When a template
3231 ** repository is used, almost all of the settings accessible from the setup
3232 ** page, either directly or indirectly, will be copied. Normal users and
3233 ** their associated permissions will not be copied; however, the system
3234 ** default users "anonymous", "nobody", "reader", "developer", and their
3235 ** associated permissions will be copied. In case of SQL errors, rebuild the
3236 ** template repository and try again.
3237 **
3238 ** Options:
3239 ** --template FILE Copy settings from repository file
3240 ** -A|--admin-user USERNAME Select given USERNAME as admin user
3241 ** --date-override DATETIME Use DATETIME as time of the initial check-in
3242
--- src/descendants.c
+++ src/descendants.c
@@ -247,11 +247,11 @@
247247
" AND event.objid=plink.pid"
248248
" ORDER BY mtime DESC"
249249
" )"
250250
" SELECT ancestor.rid FROM ancestor"
251251
" WHERE EXISTS(SELECT 1 FROM tagxref"
252
- " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
252
+ " WHERE tagid=%d AND tagxref.rid=+ancestor.rid"
253253
" AND value=%Q AND tagtype>0)"
254254
" LIMIT 1",
255255
rid, rid, TAG_BRANCH, zBranch
256256
);
257257
}
258258
--- src/descendants.c
+++ src/descendants.c
@@ -247,11 +247,11 @@
247 " AND event.objid=plink.pid"
248 " ORDER BY mtime DESC"
249 " )"
250 " SELECT ancestor.rid FROM ancestor"
251 " WHERE EXISTS(SELECT 1 FROM tagxref"
252 " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
253 " AND value=%Q AND tagtype>0)"
254 " LIMIT 1",
255 rid, rid, TAG_BRANCH, zBranch
256 );
257 }
258
--- src/descendants.c
+++ src/descendants.c
@@ -247,11 +247,11 @@
247 " AND event.objid=plink.pid"
248 " ORDER BY mtime DESC"
249 " )"
250 " SELECT ancestor.rid FROM ancestor"
251 " WHERE EXISTS(SELECT 1 FROM tagxref"
252 " WHERE tagid=%d AND tagxref.rid=+ancestor.rid"
253 " AND value=%Q AND tagtype>0)"
254 " LIMIT 1",
255 rid, rid, TAG_BRANCH, zBranch
256 );
257 }
258
+5 -4
--- src/dispatch.c
+++ src/dispatch.c
@@ -869,17 +869,18 @@
869869
@ </div>
870870
}
871871
}
872872
}else{
873873
int i;
874
+ const char *zWidth = "28ex";
874875
unsigned char occHelp[FOSSIL_MX_CMDIDX] = {0}; /* Help str occurrences */
875876
int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
876877
style_header("Help");
877878
878879
@ <a name='commands'></a>
879880
@ <h1>Available commands:</h1>
880
- @ <div class="columns" style="column-width: 12ex;">
881
+ @ <div class="columns" style="column-width: %s(zWidth);">
881882
@ <ul>
882883
/* Fill in help string buckets */
883884
for(i=0; i<MX_COMMAND; i++){
884885
if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
885886
bktHelp[aCommand[i].iHelp][occHelp[aCommand[i].iHelp]++] = i;
@@ -920,11 +921,11 @@
920921
921922
@ </ul></div>
922923
923924
@ <a name='webpages'></a>
924925
@ <h1>Available web UI pages:</h1>
925
- @ <div class="columns" style="column-width: 18ex;">
926
+ @ <div class="columns" style="column-width: %s(zWidth);">
926927
@ <ul>
927928
for(i=0; i<MX_COMMAND; i++){
928929
const char *z = aCommand[i].zName;
929930
if( '/'!=*z ) continue;
930931
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -936,11 +937,11 @@
936937
}
937938
@ </ul></div>
938939
939940
@ <a name='unsupported'></a>
940941
@ <h1>Unsupported commands:</h1>
941
- @ <div class="columns" style="column-width: 20ex;">
942
+ @ <div class="columns" style="column-width: %s(zWidth);">
942943
@ <ul>
943944
for(i=0; i<MX_COMMAND; i++){
944945
const char *z = aCommand[i].zName;
945946
if( strncmp(z,"test",4)!=0 ) continue;
946947
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -952,11 +953,11 @@
952953
}
953954
@ </ul></div>
954955
955956
@ <a name='settings'></a>
956957
@ <h1>Settings:</h1>
957
- @ <div class="columns" style="column-width: 20ex;">
958
+ @ <div class="columns" style="column-width: %s(zWidth);">
958959
@ <ul>
959960
for(i=0; i<MX_COMMAND; i++){
960961
const char *z = aCommand[i].zName;
961962
if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
962963
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
963964
--- src/dispatch.c
+++ src/dispatch.c
@@ -869,17 +869,18 @@
869 @ </div>
870 }
871 }
872 }else{
873 int i;
 
874 unsigned char occHelp[FOSSIL_MX_CMDIDX] = {0}; /* Help str occurrences */
875 int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
876 style_header("Help");
877
878 @ <a name='commands'></a>
879 @ <h1>Available commands:</h1>
880 @ <div class="columns" style="column-width: 12ex;">
881 @ <ul>
882 /* Fill in help string buckets */
883 for(i=0; i<MX_COMMAND; i++){
884 if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
885 bktHelp[aCommand[i].iHelp][occHelp[aCommand[i].iHelp]++] = i;
@@ -920,11 +921,11 @@
920
921 @ </ul></div>
922
923 @ <a name='webpages'></a>
924 @ <h1>Available web UI pages:</h1>
925 @ <div class="columns" style="column-width: 18ex;">
926 @ <ul>
927 for(i=0; i<MX_COMMAND; i++){
928 const char *z = aCommand[i].zName;
929 if( '/'!=*z ) continue;
930 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -936,11 +937,11 @@
936 }
937 @ </ul></div>
938
939 @ <a name='unsupported'></a>
940 @ <h1>Unsupported commands:</h1>
941 @ <div class="columns" style="column-width: 20ex;">
942 @ <ul>
943 for(i=0; i<MX_COMMAND; i++){
944 const char *z = aCommand[i].zName;
945 if( strncmp(z,"test",4)!=0 ) continue;
946 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -952,11 +953,11 @@
952 }
953 @ </ul></div>
954
955 @ <a name='settings'></a>
956 @ <h1>Settings:</h1>
957 @ <div class="columns" style="column-width: 20ex;">
958 @ <ul>
959 for(i=0; i<MX_COMMAND; i++){
960 const char *z = aCommand[i].zName;
961 if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
962 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
963
--- src/dispatch.c
+++ src/dispatch.c
@@ -869,17 +869,18 @@
869 @ </div>
870 }
871 }
872 }else{
873 int i;
874 const char *zWidth = "28ex";
875 unsigned char occHelp[FOSSIL_MX_CMDIDX] = {0}; /* Help str occurrences */
876 int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
877 style_header("Help");
878
879 @ <a name='commands'></a>
880 @ <h1>Available commands:</h1>
881 @ <div class="columns" style="column-width: %s(zWidth);">
882 @ <ul>
883 /* Fill in help string buckets */
884 for(i=0; i<MX_COMMAND; i++){
885 if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
886 bktHelp[aCommand[i].iHelp][occHelp[aCommand[i].iHelp]++] = i;
@@ -920,11 +921,11 @@
921
922 @ </ul></div>
923
924 @ <a name='webpages'></a>
925 @ <h1>Available web UI pages:</h1>
926 @ <div class="columns" style="column-width: %s(zWidth);">
927 @ <ul>
928 for(i=0; i<MX_COMMAND; i++){
929 const char *z = aCommand[i].zName;
930 if( '/'!=*z ) continue;
931 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -936,11 +937,11 @@
937 }
938 @ </ul></div>
939
940 @ <a name='unsupported'></a>
941 @ <h1>Unsupported commands:</h1>
942 @ <div class="columns" style="column-width: %s(zWidth);">
943 @ <ul>
944 for(i=0; i<MX_COMMAND; i++){
945 const char *z = aCommand[i].zName;
946 if( strncmp(z,"test",4)!=0 ) continue;
947 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
@@ -952,11 +953,11 @@
953 }
954 @ </ul></div>
955
956 @ <a name='settings'></a>
957 @ <h1>Settings:</h1>
958 @ <div class="columns" style="column-width: %s(zWidth);">
959 @ <ul>
960 for(i=0; i<MX_COMMAND; i++){
961 const char *z = aCommand[i].zName;
962 if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
963 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
964
+2
--- src/doc.c
+++ src/doc.c
@@ -153,10 +153,11 @@
153153
{ "igs", 3, "model/iges" },
154154
{ "ips", 3, "application/x-ipscript" },
155155
{ "ipx", 3, "application/x-ipix" },
156156
{ "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157157
{ "jar", 3, "application/java-archive" },
158
+ { "jp2", 3, "image/jp2" },
158159
{ "jpe", 3, "image/jpeg" },
159160
{ "jpeg", 4, "image/jpeg" },
160161
{ "jpg", 3, "image/jpeg" },
161162
{ "js", 2, "text/javascript" },
162163
/* application/javascript is commonly used for JS, but the
@@ -252,10 +253,11 @@
252253
{ "smi", 3, "application/smil" },
253254
{ "smil", 4, "application/smil" },
254255
{ "snd", 3, "audio/basic" },
255256
{ "sol", 3, "application/solids" },
256257
{ "spl", 3, "application/x-futuresplash" },
258
+ { "sql", 3, "application/sql" },
257259
{ "src", 3, "application/x-wais-source" },
258260
{ "step", 4, "application/STEP" },
259261
{ "stl", 3, "application/SLA" },
260262
{ "stp", 3, "application/STEP" },
261263
{ "sv4cpio", 7, "application/x-sv4cpio" },
262264
--- src/doc.c
+++ src/doc.c
@@ -153,10 +153,11 @@
153 { "igs", 3, "model/iges" },
154 { "ips", 3, "application/x-ipscript" },
155 { "ipx", 3, "application/x-ipix" },
156 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157 { "jar", 3, "application/java-archive" },
 
158 { "jpe", 3, "image/jpeg" },
159 { "jpeg", 4, "image/jpeg" },
160 { "jpg", 3, "image/jpeg" },
161 { "js", 2, "text/javascript" },
162 /* application/javascript is commonly used for JS, but the
@@ -252,10 +253,11 @@
252 { "smi", 3, "application/smil" },
253 { "smil", 4, "application/smil" },
254 { "snd", 3, "audio/basic" },
255 { "sol", 3, "application/solids" },
256 { "spl", 3, "application/x-futuresplash" },
 
257 { "src", 3, "application/x-wais-source" },
258 { "step", 4, "application/STEP" },
259 { "stl", 3, "application/SLA" },
260 { "stp", 3, "application/STEP" },
261 { "sv4cpio", 7, "application/x-sv4cpio" },
262
--- src/doc.c
+++ src/doc.c
@@ -153,10 +153,11 @@
153 { "igs", 3, "model/iges" },
154 { "ips", 3, "application/x-ipscript" },
155 { "ipx", 3, "application/x-ipix" },
156 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157 { "jar", 3, "application/java-archive" },
158 { "jp2", 3, "image/jp2" },
159 { "jpe", 3, "image/jpeg" },
160 { "jpeg", 4, "image/jpeg" },
161 { "jpg", 3, "image/jpeg" },
162 { "js", 2, "text/javascript" },
163 /* application/javascript is commonly used for JS, but the
@@ -252,10 +253,11 @@
253 { "smi", 3, "application/smil" },
254 { "smil", 4, "application/smil" },
255 { "snd", 3, "audio/basic" },
256 { "sol", 3, "application/solids" },
257 { "spl", 3, "application/x-futuresplash" },
258 { "sql", 3, "application/sql" },
259 { "src", 3, "application/x-wais-source" },
260 { "step", 4, "application/STEP" },
261 { "stl", 3, "application/SLA" },
262 { "stp", 3, "application/STEP" },
263 { "sv4cpio", 7, "application/x-sv4cpio" },
264
+1 -1
--- src/export.c
+++ src/export.c
@@ -1279,11 +1279,11 @@
12791279
blob_strlen(&manifest), blob_str(&manifest));
12801280
blob_reset(&manifest);
12811281
}
12821282
if( fManifest & MFESTFLG_UUID ){
12831283
int n = (int)strlen(zUuid);
1284
- fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
1284
+ fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n\n", n+1, zUuid);
12851285
}
12861286
if( fManifest & MFESTFLG_TAGS ){
12871287
Blob tagslist;
12881288
blob_init(&tagslist, 0, 0);
12891289
get_checkin_taglist(rid, &tagslist);
12901290
--- src/export.c
+++ src/export.c
@@ -1279,11 +1279,11 @@
1279 blob_strlen(&manifest), blob_str(&manifest));
1280 blob_reset(&manifest);
1281 }
1282 if( fManifest & MFESTFLG_UUID ){
1283 int n = (int)strlen(zUuid);
1284 fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
1285 }
1286 if( fManifest & MFESTFLG_TAGS ){
1287 Blob tagslist;
1288 blob_init(&tagslist, 0, 0);
1289 get_checkin_taglist(rid, &tagslist);
1290
--- src/export.c
+++ src/export.c
@@ -1279,11 +1279,11 @@
1279 blob_strlen(&manifest), blob_str(&manifest));
1280 blob_reset(&manifest);
1281 }
1282 if( fManifest & MFESTFLG_UUID ){
1283 int n = (int)strlen(zUuid);
1284 fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n\n", n+1, zUuid);
1285 }
1286 if( fManifest & MFESTFLG_TAGS ){
1287 Blob tagslist;
1288 blob_init(&tagslist, 0, 0);
1289 get_checkin_taglist(rid, &tagslist);
1290
+79 -1
--- src/file.c
+++ src/file.c
@@ -1290,10 +1290,79 @@
12901290
if( zOrigName==0 ) return 0;
12911291
blob_init(&x, 0, 0);
12921292
file_canonical_name(zOrigName, &x, 0);
12931293
return blob_str(&x);
12941294
}
1295
+
1296
+/*
1297
+** Convert zPath, which is a relative pathname rooted at zDir, into the
1298
+** case preferred by the underlying filesystem. Return the a copy
1299
+** of the converted path in memory obtained from fossil_malloc().
1300
+**
1301
+** For case-sensitive filesystems, such as on Linux, this routine is
1302
+** just fossil_strdup(). But for case-insenstiive but "case preserving"
1303
+** filesystems, such as on MacOS or Windows, we want the filename to be
1304
+** in the preserved casing. That's what this routine does.
1305
+*/
1306
+char *file_case_preferred_name(const char *zDir, const char *zPath){
1307
+ DIR *d;
1308
+ int i;
1309
+ char *zResult = 0;
1310
+ void *zNative = 0;
1311
+
1312
+ if( filenames_are_case_sensitive() ){
1313
+ return fossil_strdup(zPath);
1314
+ }
1315
+ for(i=0; zPath[i] && zPath[i]!='/' && zPath[i]!='\\'; i++){}
1316
+ zNative = fossil_utf8_to_path(zDir, 1);
1317
+ d = opendir(zNative);
1318
+ if( d ){
1319
+ struct dirent *pEntry;
1320
+ while( (pEntry = readdir(d))!=0 ){
1321
+ char *zUtf8 = fossil_path_to_utf8(pEntry->d_name);
1322
+ if( fossil_strnicmp(zUtf8, zPath, i)==0 && zUtf8[i]==0 ){
1323
+ if( zPath[i]==0 ){
1324
+ zResult = fossil_strdup(zUtf8);
1325
+ }else{
1326
+ char *zSubDir = mprintf("%s/%s", zDir, zUtf8);
1327
+ char *zSubPath = file_case_preferred_name(zSubDir, &zPath[i+1]);
1328
+ zResult = mprintf("%s/%s", zUtf8, zSubPath);
1329
+ fossil_free(zSubPath);
1330
+ fossil_free(zSubDir);
1331
+ }
1332
+ fossil_path_free(zUtf8);
1333
+ break;
1334
+ }
1335
+ fossil_path_free(zUtf8);
1336
+ }
1337
+ closedir(d);
1338
+ }
1339
+ fossil_path_free(zNative);
1340
+ if( zResult==0 ) zResult = fossil_strdup(zPath);
1341
+ return zResult;
1342
+}
1343
+
1344
+/*
1345
+** COMMAND: test-case-filename
1346
+**
1347
+** Usage: fossil test-case-filename DIRECTORY PATH PATH PATH ....
1348
+**
1349
+** All the PATH arguments (there must be one at least one) are pathnames
1350
+** relative to DIRECTORY. This test command prints the OS-preferred name
1351
+** for each PATH in filesystems where case is not significant.
1352
+*/
1353
+void test_preferred_fn(void){
1354
+ int i;
1355
+ if( g.argc<4 ){
1356
+ usage("DIRECTORY PATH ...");
1357
+ }
1358
+ for(i=3; i<g.argc; i++){
1359
+ char *z = file_case_preferred_name(g.argv[2], g.argv[i]);
1360
+ fossil_print("%s -> %s\n", g.argv[i], z);
1361
+ fossil_free(z);
1362
+ }
1363
+}
12951364
12961365
/*
12971366
** The input is the name of an executable, such as one might
12981367
** type on a command-line. This routine resolves that name into
12991368
** a full pathname. The result is obtained from fossil_malloc()
@@ -2340,10 +2409,13 @@
23402409
23412410
/*
23422411
** Count the number of objects (files and subdirectories) in a given
23432412
** directory. Return the count. Return -1 if the object is not a
23442413
** directory.
2414
+**
2415
+** This routine never counts the two "." and ".." special directory
2416
+** entries, even if the provided glob would match them.
23452417
*/
23462418
int file_directory_size(const char *zDir, const char *zGlob, int omitDotFiles){
23472419
void *zNative;
23482420
DIR *d;
23492421
int n = -1;
@@ -2352,11 +2424,17 @@
23522424
if( d ){
23532425
struct dirent *pEntry;
23542426
n = 0;
23552427
while( (pEntry=readdir(d))!=0 ){
23562428
if( pEntry->d_name[0]==0 ) continue;
2357
- if( omitDotFiles && pEntry->d_name[0]=='.' ) continue;
2429
+ if( pEntry->d_name[0]=='.' &&
2430
+ (omitDotFiles
2431
+ /* Skip the special "." and ".." entries. */
2432
+ || pEntry->d_name[1]==0
2433
+ || (pEntry->d_name[1]=='.' && pEntry->d_name[2]==0))){
2434
+ continue;
2435
+ }
23582436
if( zGlob ){
23592437
char *zUtf8 = fossil_path_to_utf8(pEntry->d_name);
23602438
int rc = sqlite3_strglob(zGlob, zUtf8);
23612439
fossil_path_free(zUtf8);
23622440
if( rc ) continue;
23632441
--- src/file.c
+++ src/file.c
@@ -1290,10 +1290,79 @@
1290 if( zOrigName==0 ) return 0;
1291 blob_init(&x, 0, 0);
1292 file_canonical_name(zOrigName, &x, 0);
1293 return blob_str(&x);
1294 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1295
1296 /*
1297 ** The input is the name of an executable, such as one might
1298 ** type on a command-line. This routine resolves that name into
1299 ** a full pathname. The result is obtained from fossil_malloc()
@@ -2340,10 +2409,13 @@
2340
2341 /*
2342 ** Count the number of objects (files and subdirectories) in a given
2343 ** directory. Return the count. Return -1 if the object is not a
2344 ** directory.
 
 
 
2345 */
2346 int file_directory_size(const char *zDir, const char *zGlob, int omitDotFiles){
2347 void *zNative;
2348 DIR *d;
2349 int n = -1;
@@ -2352,11 +2424,17 @@
2352 if( d ){
2353 struct dirent *pEntry;
2354 n = 0;
2355 while( (pEntry=readdir(d))!=0 ){
2356 if( pEntry->d_name[0]==0 ) continue;
2357 if( omitDotFiles && pEntry->d_name[0]=='.' ) continue;
 
 
 
 
 
 
2358 if( zGlob ){
2359 char *zUtf8 = fossil_path_to_utf8(pEntry->d_name);
2360 int rc = sqlite3_strglob(zGlob, zUtf8);
2361 fossil_path_free(zUtf8);
2362 if( rc ) continue;
2363
--- src/file.c
+++ src/file.c
@@ -1290,10 +1290,79 @@
1290 if( zOrigName==0 ) return 0;
1291 blob_init(&x, 0, 0);
1292 file_canonical_name(zOrigName, &x, 0);
1293 return blob_str(&x);
1294 }
1295
1296 /*
1297 ** Convert zPath, which is a relative pathname rooted at zDir, into the
1298 ** case preferred by the underlying filesystem. Return the a copy
1299 ** of the converted path in memory obtained from fossil_malloc().
1300 **
1301 ** For case-sensitive filesystems, such as on Linux, this routine is
1302 ** just fossil_strdup(). But for case-insenstiive but "case preserving"
1303 ** filesystems, such as on MacOS or Windows, we want the filename to be
1304 ** in the preserved casing. That's what this routine does.
1305 */
1306 char *file_case_preferred_name(const char *zDir, const char *zPath){
1307 DIR *d;
1308 int i;
1309 char *zResult = 0;
1310 void *zNative = 0;
1311
1312 if( filenames_are_case_sensitive() ){
1313 return fossil_strdup(zPath);
1314 }
1315 for(i=0; zPath[i] && zPath[i]!='/' && zPath[i]!='\\'; i++){}
1316 zNative = fossil_utf8_to_path(zDir, 1);
1317 d = opendir(zNative);
1318 if( d ){
1319 struct dirent *pEntry;
1320 while( (pEntry = readdir(d))!=0 ){
1321 char *zUtf8 = fossil_path_to_utf8(pEntry->d_name);
1322 if( fossil_strnicmp(zUtf8, zPath, i)==0 && zUtf8[i]==0 ){
1323 if( zPath[i]==0 ){
1324 zResult = fossil_strdup(zUtf8);
1325 }else{
1326 char *zSubDir = mprintf("%s/%s", zDir, zUtf8);
1327 char *zSubPath = file_case_preferred_name(zSubDir, &zPath[i+1]);
1328 zResult = mprintf("%s/%s", zUtf8, zSubPath);
1329 fossil_free(zSubPath);
1330 fossil_free(zSubDir);
1331 }
1332 fossil_path_free(zUtf8);
1333 break;
1334 }
1335 fossil_path_free(zUtf8);
1336 }
1337 closedir(d);
1338 }
1339 fossil_path_free(zNative);
1340 if( zResult==0 ) zResult = fossil_strdup(zPath);
1341 return zResult;
1342 }
1343
1344 /*
1345 ** COMMAND: test-case-filename
1346 **
1347 ** Usage: fossil test-case-filename DIRECTORY PATH PATH PATH ....
1348 **
1349 ** All the PATH arguments (there must be one at least one) are pathnames
1350 ** relative to DIRECTORY. This test command prints the OS-preferred name
1351 ** for each PATH in filesystems where case is not significant.
1352 */
1353 void test_preferred_fn(void){
1354 int i;
1355 if( g.argc<4 ){
1356 usage("DIRECTORY PATH ...");
1357 }
1358 for(i=3; i<g.argc; i++){
1359 char *z = file_case_preferred_name(g.argv[2], g.argv[i]);
1360 fossil_print("%s -> %s\n", g.argv[i], z);
1361 fossil_free(z);
1362 }
1363 }
1364
1365 /*
1366 ** The input is the name of an executable, such as one might
1367 ** type on a command-line. This routine resolves that name into
1368 ** a full pathname. The result is obtained from fossil_malloc()
@@ -2340,10 +2409,13 @@
2409
2410 /*
2411 ** Count the number of objects (files and subdirectories) in a given
2412 ** directory. Return the count. Return -1 if the object is not a
2413 ** directory.
2414 **
2415 ** This routine never counts the two "." and ".." special directory
2416 ** entries, even if the provided glob would match them.
2417 */
2418 int file_directory_size(const char *zDir, const char *zGlob, int omitDotFiles){
2419 void *zNative;
2420 DIR *d;
2421 int n = -1;
@@ -2352,11 +2424,17 @@
2424 if( d ){
2425 struct dirent *pEntry;
2426 n = 0;
2427 while( (pEntry=readdir(d))!=0 ){
2428 if( pEntry->d_name[0]==0 ) continue;
2429 if( pEntry->d_name[0]=='.' &&
2430 (omitDotFiles
2431 /* Skip the special "." and ".." entries. */
2432 || pEntry->d_name[1]==0
2433 || (pEntry->d_name[1]=='.' && pEntry->d_name[2]==0))){
2434 continue;
2435 }
2436 if( zGlob ){
2437 char *zUtf8 = fossil_path_to_utf8(pEntry->d_name);
2438 int rc = sqlite3_strglob(zGlob, zUtf8);
2439 fossil_path_free(zUtf8);
2440 if( rc ) continue;
2441
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -61,11 +61,11 @@
6161
if(!f.rx){
6262
f.rx = /(\s+|\s*,\s*)/;
6363
}
6464
return str ? str.split(f.rx) : [str];
6565
};
66
-
66
+
6767
dom.div = dom.createElemFactory('div');
6868
dom.p = dom.createElemFactory('p');
6969
dom.code = dom.createElemFactory('code');
7070
dom.pre = dom.createElemFactory('pre');
7171
dom.header = dom.createElemFactory('header');
@@ -549,11 +549,11 @@
549549
}
550550
if(!f.counter){
551551
old.parentNode.removeChild(old);
552552
}
553553
};
554
- dom.replaceNode.counter = 0;
554
+ dom.replaceNode.counter = 0;
555555
/**
556556
Two args == getter: (e,key), returns value
557557
558558
Three or more == setter: (e,key,val[...,keyN,valN]), returns
559559
e. If val===null or val===undefined then the attribute is
560560
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -61,11 +61,11 @@
61 if(!f.rx){
62 f.rx = /(\s+|\s*,\s*)/;
63 }
64 return str ? str.split(f.rx) : [str];
65 };
66
67 dom.div = dom.createElemFactory('div');
68 dom.p = dom.createElemFactory('p');
69 dom.code = dom.createElemFactory('code');
70 dom.pre = dom.createElemFactory('pre');
71 dom.header = dom.createElemFactory('header');
@@ -549,11 +549,11 @@
549 }
550 if(!f.counter){
551 old.parentNode.removeChild(old);
552 }
553 };
554 dom.replaceNode.counter = 0;
555 /**
556 Two args == getter: (e,key), returns value
557
558 Three or more == setter: (e,key,val[...,keyN,valN]), returns
559 e. If val===null or val===undefined then the attribute is
560
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -61,11 +61,11 @@
61 if(!f.rx){
62 f.rx = /(\s+|\s*,\s*)/;
63 }
64 return str ? str.split(f.rx) : [str];
65 };
66
67 dom.div = dom.createElemFactory('div');
68 dom.p = dom.createElemFactory('p');
69 dom.code = dom.createElemFactory('code');
70 dom.pre = dom.createElemFactory('pre');
71 dom.header = dom.createElemFactory('header');
@@ -549,11 +549,11 @@
549 }
550 if(!f.counter){
551 old.parentNode.removeChild(old);
552 }
553 };
554 dom.replaceNode.counter = 0;
555 /**
556 Two args == getter: (e,key), returns value
557
558 Three or more == setter: (e,key,val[...,keyN,valN]), returns
559 e. If val===null or val===undefined then the attribute is
560
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -234,11 +234,11 @@
234234
urlTransform() must refer to a function which accepts a relative path
235235
to the same site as fetch() is served from and an optional set of
236236
URL parameters to pass with it (in the form a of a string
237237
("a=b&c=d...") or an object of key/value pairs (which it converts
238238
to such a string), and returns the resulting URL or URI as a string.
239
-*/
239
+*/
240240
fossil.fetch.urlTransform = (u,p)=>fossil.repoUrl(u,p);
241241
fossil.fetch.beforesend = function(){};
242242
fossil.fetch.aftersend = function(){};
243243
fossil.fetch.timeout = 15000/* Default timeout, in ms. */;
244244
})(window.fossil);
245245
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -234,11 +234,11 @@
234 urlTransform() must refer to a function which accepts a relative path
235 to the same site as fetch() is served from and an optional set of
236 URL parameters to pass with it (in the form a of a string
237 ("a=b&c=d...") or an object of key/value pairs (which it converts
238 to such a string), and returns the resulting URL or URI as a string.
239 */
240 fossil.fetch.urlTransform = (u,p)=>fossil.repoUrl(u,p);
241 fossil.fetch.beforesend = function(){};
242 fossil.fetch.aftersend = function(){};
243 fossil.fetch.timeout = 15000/* Default timeout, in ms. */;
244 })(window.fossil);
245
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -234,11 +234,11 @@
234 urlTransform() must refer to a function which accepts a relative path
235 to the same site as fetch() is served from and an optional set of
236 URL parameters to pass with it (in the form a of a string
237 ("a=b&c=d...") or an object of key/value pairs (which it converts
238 to such a string), and returns the resulting URL or URI as a string.
239 */
240 fossil.fetch.urlTransform = (u,p)=>fossil.repoUrl(u,p);
241 fossil.fetch.beforesend = function(){};
242 fossil.fetch.aftersend = function(){};
243 fossil.fetch.timeout = 15000/* Default timeout, in ms. */;
244 })(window.fossil);
245
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -124,13 +124,14 @@
124124
window.addEventListener('resize', F.debounce(resized, 250), false);
125125
return resized;
126126
})();
127127
fossil.FRK = ForceResizeKludge/*for debugging*/;
128128
const Chat = ForceResizeKludge.chat = (function(){
129
- const cs = {
129
+ const cs = { // the "Chat" object (result of this function)
130130
verboseErrors: false /* if true then certain, mostly extraneous,
131131
error messages may be sent to the console. */,
132
+ playedBeep: false /* used for the beep-once setting */,
132133
e:{/*map of certain DOM elements.*/
133134
messageInjectPoint: E1('#message-inject-point'),
134135
pageTitle: E1('head title'),
135136
loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */,
136137
inputWrapper: E1("#chat-input-area"),
@@ -145,10 +146,12 @@
145146
inputFile: E1('#chat-input-file'),
146147
contentDiv: E1('div.content'),
147148
viewConfig: E1('#chat-config'),
148149
viewPreview: E1('#chat-preview'),
149150
previewContent: E1('#chat-preview-content'),
151
+ viewSearch: E1('#chat-search'),
152
+ searchContent: E1('#chat-search-content'),
150153
btnPreview: E1('#chat-button-preview'),
151154
views: document.querySelectorAll('.chat-view'),
152155
activeUserListWrapper: E1('#chat-user-list-wrapper'),
153156
activeUserList: E1('#chat-user-list')
154157
},
@@ -173,21 +176,31 @@
173176
activeUser: undefined,
174177
match: function(uname){
175178
return this.activeUser===uname || !this.activeUser;
176179
}
177180
},
178
- /** Gets (no args) or sets (1 arg) the current input text field value,
179
- taking into account single- vs multi-line input. The getter returns
180
- a string and the setter returns this object. */
181
- inputValue: function(){
181
+ /**
182
+ Gets (no args) or sets (1 arg) the current input text field
183
+ value, taking into account single- vs multi-line input. The
184
+ getter returns a trim()'d string and the setter returns this
185
+ object. As a special case, if arguments[0] is a boolean
186
+ value, it behaves like a getter and, if arguments[0]===true
187
+ it clears the input field before returning.
188
+ */
189
+ inputValue: function(/*string newValue | bool clearInputField*/){
182190
const e = this.inputElement();
183
- if(arguments.length){
191
+ if(arguments.length && 'boolean'!==typeof arguments[0]){
184192
if(e.isContentEditable) e.innerText = arguments[0];
185193
else e.value = arguments[0];
186194
return this;
187195
}
188
- return e.isContentEditable ? e.innerText : e.value;
196
+ const rc = e.isContentEditable ? e.innerText : e.value;
197
+ if( true===arguments[0] ){
198
+ if(e.isContentEditable) e.innerText = '';
199
+ else e.value = '';
200
+ }
201
+ return rc && rc.trim();
189202
},
190203
/** Asks the current user input field to take focus. Returns this. */
191204
inputFocus: function(){
192205
this.inputElement().focus();
193206
return this;
@@ -410,10 +423,13 @@
410423
/* When set to a URI, it is assumed to be an audio file,
411424
which gets played when new messages arrive. When true,
412425
the first entry in the audio file selection list will be
413426
used. */
414427
"audible-alert": true,
428
+ /*
429
+ */
430
+ "beep-once": false,
415431
/* When on, show the list of "active" users - those from
416432
whom we have messages in the currently-loaded history
417433
(noting that deletions are also messages). */
418434
"active-user-list": false,
419435
/* When on, the [active-user-list] setting includes the
@@ -434,11 +450,17 @@
434450
/** Plays a new-message notification sound IF the audible-alert
435451
setting is true, else this is a no-op. Returns this.
436452
*/
437453
playNewMessageSound: function f(){
438454
if(f.uri){
455
+ if(!cs.pageIsActive
456
+ /* ^^^ this could also arguably apply when chat is visible */
457
+ && this.playedBeep && this.settings.getBool('beep-once',false)){
458
+ return;
459
+ }
439460
try{
461
+ this.playedBeep = true;
440462
if(!f.audio) f.audio = new Audio(f.uri);
441463
f.audio.currentTime = 0;
442464
f.audio.play();
443465
}catch(e){
444466
console.error("Audio playblack failed.", f.uri, e);
@@ -451,10 +473,11 @@
451473
repository-relative path which responds with an audio
452474
file). Pass a falsy value to disable audio alerts. Returns
453475
this.
454476
*/
455477
setNewMessageSound: function f(uri){
478
+ this.playedBeep = false;
456479
delete this.playNewMessageSound.audio;
457480
this.playNewMessageSound.uri = uri;
458481
this.settings.set('audible-alert', uri);
459482
return this;
460483
},
@@ -502,11 +525,11 @@
502525
const uDate = self.usersLastSeen[u];
503526
if(self.filterState.activeUser===u){
504527
uSpan.classList.add('selected');
505528
}
506529
uSpan.dataset.uname = u;
507
- D.append(uSpan, u, "\n",
530
+ D.append(uSpan, u, "\n",
508531
D.append(
509532
D.addClass(D.span(),'timestamp'),
510533
localTimeString(uDate)//.substr(5/*chop off year*/)
511534
));
512535
if(uDate.$uColor){
@@ -780,19 +803,19 @@
780803
cs._newResponseError = function(response){
781804
return new Error([
782805
"HTTP status ", response.status,": ",response.url,": ",
783806
response.statusText].join(''));
784807
};
785
-
808
+
786809
/** Helper for reporting HTTP-level response errors via fetch().
787810
If response.ok then response.json() is returned, else an Error
788811
is thrown. */
789812
cs._fetchJsonOrError = function(response){
790813
if(response.ok) return response.json();
791814
else throw cs._newResponseError(response);
792815
};
793
-
816
+
794817
/**
795818
Removes the given message ID from the local chat record and, if
796819
the message was posted by this user OR this user in an
797820
admin/setup, also submits it for removal on the remote.
798821
@@ -819,10 +842,11 @@
819842
this.deleteMessageElem(id);
820843
}
821844
};
822845
document.addEventListener('visibilitychange', function(ev){
823846
cs.pageIsActive = ('visible' === document.visibilityState);
847
+ cs.playedBeep = false;
824848
if(cs.pageIsActive){
825849
cs.e.pageTitle.innerText = cs.pageTitleOrig;
826850
if(document.activeElement!==cs.inputElement()){
827851
/* An attempt to resolve usability problem reported by Joe
828852
M. where the Pale Moon browser is giving input focus to
@@ -886,11 +910,11 @@
886910
Chat.MessageWidget = (function(){
887911
/**
888912
Constructor. If passed an argument, it is passed to
889913
this.setMessage() after initialization.
890914
*/
891
- const cf = function(){
915
+ const ctor = function(){
892916
this.e = {
893917
body: D.addClass(D.div(), 'message-widget'),
894918
tab: D.addClass(D.div(), 'message-widget-tab'),
895919
content: D.addClass(D.div(), 'message-widget-content')
896920
};
@@ -905,20 +929,33 @@
905929
/* Map of Date.getDay() values to weekday names. */
906930
0: "Sunday", 1: "Monday", 2: "Tuesday",
907931
3: "Wednesday", 4: "Thursday", 5: "Friday",
908932
6: "Saturday"
909933
};
910
- /* Given a Date, returns the timestamp string used in the
911
- "tab" part of message widgets. */
912
- const theTime = function(d){
913
- return [
914
- //d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
915
- //'-',pad2(d.getDate()), ' ',
916
- d.getHours(),":",
917
- (d.getMinutes()+100).toString().slice(1,3),
918
- ' ', dowMap[d.getDay()]
919
- ].join('');
934
+ /* Given a Date, returns the timestamp string used in the "tab"
935
+ part of message widgets. If longFmt is true then a verbose
936
+ format is used, else a brief format is used. The returned string
937
+ is in client-local time. */
938
+ const theTime = function(d, longFmt=false){
939
+ const li = [];
940
+ if( longFmt ){
941
+ li.push(
942
+ d.getFullYear(),
943
+ '-', pad2(d.getMonth()+1),
944
+ '-', pad2(d.getDate()),
945
+ ' ',
946
+ d.getHours(), ":",
947
+ (d.getMinutes()+100).toString().slice(1,3)
948
+ );
949
+ }else{
950
+ li.push(
951
+ d.getHours(),":",
952
+ (d.getMinutes()+100).toString().slice(1,3),
953
+ ' ', dowMap[d.getDay()]
954
+ );
955
+ }
956
+ return li.join('');
920957
};
921958
922959
/**
923960
Returns true if this page believes it can embed a view of the
924961
file wrapped by the given message object, else returns false.
@@ -925,19 +962,20 @@
925962
*/
926963
const canEmbedFile = function f(msg){
927964
if(!f.$rx){
928965
f.$rx = /\.((html?)|(txt)|(md)|(wiki)|(pikchr))$/i;
929966
f.$specificTypes = [
967
+ /* Mime types we know we can embed, sans image/... */
930968
'text/plain',
931969
'text/html',
932970
'text/x-markdown',
933971
/* Firefox sends text/markdown when uploading .md files */
934972
'text/markdown',
935973
'text/x-pikchr',
936974
'text/x-fossil-wiki'
937
- // add more as we discover which ones Firefox won't
938
- // force the user to try to download.
975
+ /* Add more as we discover which ones Firefox won't
976
+ force the user to try to download. */
939977
];
940978
}
941979
if(msg.fmime){
942980
if(msg.fmime.startsWith("image/")
943981
|| f.$specificTypes.indexOf(msg.fmime)>=0){
@@ -951,20 +989,18 @@
951989
Returns true if the given message object "should"
952990
be embedded in fossil-rendered form instead of
953991
raw content form. This is only intended to be passed
954992
message objects for which canEmbedFile() returns true.
955993
*/
956
- const shouldWikiRenderEmbed = function f(msg){
994
+ const shouldFossilRenderEmbed = function f(msg){
957995
if(!f.$rx){
958996
f.$rx = /\.((md)|(wiki)|(pikchr))$/i;
959997
f.$specificTypes = [
960998
'text/x-markdown',
961999
'text/markdown' /* Firefox-uploaded md files */,
9621000
'text/x-pikchr',
9631001
'text/x-fossil-wiki'
964
- // add more as we discover which ones Firefox won't
965
- // force the user to try to download.
9661002
];
9671003
}
9681004
if(msg.fmime){
9691005
if(f.$specificTypes.indexOf(msg.fmime)>=0) return true;
9701006
}
@@ -990,12 +1026,12 @@
9901026
iframe.style.maxHeight = iframe.style.height
9911027
= iframe.contentWindow.document.documentElement.scrollHeight + 'px';
9921028
if(isHidden) D.addClass(iframe, 'hidden');
9931029
}
9941030
};
995
-
996
- cf.prototype = {
1031
+
1032
+ ctor.prototype = {
9971033
scrollIntoView: function(){
9981034
this.e.content.scrollIntoView();
9991035
},
10001036
setMessage: function(m){
10011037
const ds = this.e.body.dataset;
@@ -1016,20 +1052,26 @@
10161052
var eXFrom /* element holding xfrom name */;
10171053
if(m.xfrom){
10181054
eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
10191055
const wrapper = D.append(
10201056
D.span(), eXFrom,
1021
- D.text(" #",(m.msgid||'???'),' @ ',theTime(d)))
1057
+ ' ',
1058
+ D.append(D.addClass(D.span(), 'msgid'),
1059
+ '#' + (m.msgid||'???')),
1060
+ (m.isSearchResult ? ' ' : ' @ '),
1061
+ D.append(D.addClass(D.span(), 'timestamp'),
1062
+ theTime(d,!!m.isSearchResult))
1063
+ );
10221064
D.append(this.e.tab, wrapper);
10231065
}else{/*notification*/
10241066
D.addClass(this.e.body, 'notification');
10251067
if(m.isError){
10261068
D.addClass([contentTarget, this.e.tab], 'error');
10271069
}
10281070
D.append(
10291071
this.e.tab,
1030
- D.append(D.code(), 'notification @ ',theTime(d))
1072
+ D.append(D.code(), 'notification @ ',theTime(d,false))
10311073
);
10321074
}
10331075
if( m.xfrom && m.fsize>0 ){
10341076
if( m.fmime
10351077
&& m.fmime.startsWith("image/")
@@ -1052,18 +1094,18 @@
10521094
D.attr(a,'target','_blank');
10531095
D.append(w, a);
10541096
if(canEmbedFile(m)){
10551097
/* Add an option to embed HTML attachments in an iframe. The primary
10561098
use case is attached diffs. */
1057
- const shouldWikiRender = shouldWikiRenderEmbed(m);
1058
- const downloadArgs = shouldWikiRender ? '?render' : '';
1099
+ const shouldFossilRender = shouldFossilRenderEmbed(m);
1100
+ const downloadArgs = shouldFossilRender ? '?render' : '';
10591101
D.addClass(contentTarget, 'wide');
10601102
const embedTarget = this.e.content;
10611103
const self = this;
10621104
const btnEmbed = D.attr(D.checkbox("1", false), 'id',
10631105
'embed-'+ds.msgid);
1064
- const btnLabel = D.label(btnEmbed, shouldWikiRender
1106
+ const btnLabel = D.label(btnEmbed, shouldFossilRender
10651107
? "Embed (fossil-rendered)" : "Embed");
10661108
/* Maintenance reminder: do not disable the toggle
10671109
button while the content is loading because that will
10681110
cause it to get stuck in disabled mode if the browser
10691111
decides that loading the content should prompt the
@@ -1268,13 +1310,183 @@
12681310
}/*end static init*/
12691311
const theMsg = findMessageWidgetParent(ev.target);
12701312
if(theMsg) f.popup.show(theMsg);
12711313
}/*_handleLegendClicked()*/
12721314
};
1273
- return cf;
1315
+ return ctor;
12741316
})()/*MessageWidget*/;
12751317
1318
+ /**
1319
+ A widget for loading more messages (context) around a /chat-query
1320
+ result message.
1321
+ */
1322
+ Chat.SearchCtxLoader = (function(){
1323
+ const nMsgContext = 5;
1324
+ const zUpArrow = '\u25B2';
1325
+ const zDownArrow = '\u25BC';
1326
+ const ctor = function(o){
1327
+
1328
+ /* iFirstInTable:
1329
+ ** msgid of first row in chatfts table.
1330
+ **
1331
+ ** iLastInTable:
1332
+ ** msgid of last row in chatfts table.
1333
+ **
1334
+ ** iPrevId:
1335
+ ** msgid of message immediately above this spacer. Or 0 if this
1336
+ ** spacer is above all results.
1337
+ **
1338
+ ** iNextId:
1339
+ ** msgid of message immediately below this spacer. Or 0 if this
1340
+ ** spacer is below all results.
1341
+ **
1342
+ ** bIgnoreClick:
1343
+ ** ignore any clicks if this is true. This is used to ensure there
1344
+ ** is only ever one request belonging to this widget outstanding
1345
+ ** at any time.
1346
+ */
1347
+ this.o = {
1348
+ iFirstInTable: o.first,
1349
+ iLastInTable: o.last,
1350
+ iPrevId: o.previd,
1351
+ iNextId: o.nextid,
1352
+ bIgnoreClick: false
1353
+ };
1354
+
1355
+ this.e = {
1356
+ body: D.addClass(D.div(), 'spacer-widget'),
1357
+ up: D.addClass(
1358
+ D.button(zDownArrow+' Load '+nMsgContext+' more '+zDownArrow),
1359
+ 'up'
1360
+ ),
1361
+ down: D.addClass(
1362
+ D.button(zUpArrow+' Load '+nMsgContext+' more '+zUpArrow),
1363
+ 'down'
1364
+ ),
1365
+ all: D.addClass(D.button('Load More'), 'all')
1366
+ };
1367
+ D.append( this.e.body, this.e.up, this.e.down, this.e.all );
1368
+ const ms = this;
1369
+ this.e.up.addEventListener('click', ()=>ms.load_messages(false));
1370
+ this.e.down.addEventListener('click', ()=>ms.load_messages(true));
1371
+ this.e.all.addEventListener('click', ()=>ms.load_messages( (ms.o.iPrevId==0) ));
1372
+ this.set_button_visibility();
1373
+ };
1374
+
1375
+ ctor.prototype = {
1376
+ set_button_visibility: function() {
1377
+ if( !this.e ) return;
1378
+ const o = this.o;
1379
+
1380
+ const iPrevId = (o.iPrevId!=0) ? o.iPrevId : o.iFirstInTable-1;
1381
+ const iNextId = (o.iNextId!=0) ? o.iNextId : o.iLastInTable+1;
1382
+ let nDiff = (iNextId - iPrevId) - 1;
1383
+
1384
+ for( const x of [this.e.up, this.e.down, this.e.all] ){
1385
+ if( x ) D.addClass(x, 'hidden');
1386
+ }
1387
+ let nVisible = 0;
1388
+ if( nDiff>0 ){
1389
+ if( nDiff>nMsgContext && (o.iPrevId==0 || o.iNextId==0) ){
1390
+ nDiff = nMsgContext;
1391
+ }
1392
+
1393
+ if( nDiff<=nMsgContext && o.iPrevId!=0 && o.iNextId!=0 ){
1394
+ D.removeClass(this.e.all, 'hidden');
1395
+ ++nVisible;
1396
+ this.e.all.innerText = (
1397
+ zUpArrow + " Load " + nDiff + " more " + zDownArrow
1398
+ );
1399
+ }else{
1400
+ if( o.iPrevId!=0 ){
1401
+ ++nVisible;
1402
+ D.removeClass(this.e.up, 'hidden');
1403
+ }else if( this.e.up ){
1404
+ if( this.e.up.parentNode ) D.remove(this.e.up);
1405
+ delete this.e.up;
1406
+ }
1407
+ if( o.iNextId!=0 ){
1408
+ ++nVisible;
1409
+ D.removeClass(this.e.down, 'hidden');
1410
+ }else if( this.e.down ){
1411
+ if( this.e.down.parentNode ) D.remove( this.e.down );
1412
+ delete this.e.down;
1413
+ }
1414
+ }
1415
+ }
1416
+ if( !nVisible ){
1417
+ /* The DOM elements can now be disposed of. */
1418
+ for( const x of [this.e.up, this.e.down, this.e.all, this.e.body] ){
1419
+ if( x?.parentNode ) D.remove(x);
1420
+ }
1421
+ delete this.e;
1422
+ }
1423
+ },
1424
+
1425
+ load_messages: function(bDown) {
1426
+ if( this.bIgnoreClick ) return;
1427
+
1428
+ var iFirst = 0; /* msgid of first message to fetch */
1429
+ var nFetch = 0; /* Number of messages to fetch */
1430
+ var iEof = 0; /* last msgid in spacers range, plus 1 */
1431
+
1432
+ const e = this.e, o = this.o;
1433
+ this.bIgnoreClick = true;
1434
+
1435
+ /* Figure out the required range of messages. */
1436
+ if( bDown ){
1437
+ iFirst = this.o.iNextId - nMsgContext;
1438
+ if( iFirst<this.o.iFirstInTable ){
1439
+ iFirst = this.o.iFirstInTable;
1440
+ }
1441
+ }else{
1442
+ iFirst = this.o.iPrevId+1;
1443
+ }
1444
+ nFetch = nMsgContext;
1445
+ iEof = (this.o.iNextId > 0) ? this.o.iNextId : this.o.iLastInTable+1;
1446
+ if( iFirst+nFetch>iEof ){
1447
+ nFetch = iEof - iFirst;
1448
+ }
1449
+ const ms = this;
1450
+ F.fetch("chat-query",{
1451
+ urlParams:{
1452
+ q: '',
1453
+ n: nFetch,
1454
+ i: iFirst
1455
+ },
1456
+ responseType: "json",
1457
+ onload:function(jx){
1458
+ if( bDown ) jx.msgs.reverse();
1459
+ jx.msgs.forEach((m) => {
1460
+ m.isSearchResult = true;
1461
+ var mw = new Chat.MessageWidget(m);
1462
+ if( bDown ){
1463
+ /* Inject the message below this object's body, or
1464
+ append it to Chat.e.searchContent if this element
1465
+ is the final one in its parent (Chat.e.searchContent). */
1466
+ const eAnchor = e.body.nextElementSibling;
1467
+ if( eAnchor ) Chat.e.searchContent.insertBefore(mw.e.body, eAnchor);
1468
+ else D.append(Chat.e.searchContent, mw.e.body);
1469
+ }else{
1470
+ Chat.e.searchContent.insertBefore(mw.e.body, e.body);
1471
+ }
1472
+ });
1473
+ if( bDown ){
1474
+ o.iNextId -= jx.msgs.length;
1475
+ }else{
1476
+ o.iPrevId += jx.msgs.length;
1477
+ }
1478
+ ms.set_button_visibility();
1479
+ ms.bIgnoreClick = false;
1480
+ }
1481
+ });
1482
+ }
1483
+ };
1484
+
1485
+ return ctor;
1486
+ })() /*SearchCtxLoader*/;
1487
+
12761488
const BlobXferState = (function(){
12771489
/* State for paste and drag/drop */
12781490
const bxs = {
12791491
dropDetails: document.querySelector('#chat-drop-details'),
12801492
blob: undefined,
@@ -1413,16 +1625,26 @@
14131625
14141626
/**
14151627
Submits the contents of the message input field (if not empty)
14161628
and/or the file attachment field to the server. If both are
14171629
empty, this is a no-op.
1630
+
1631
+ If the current view is the history search, this instead sends the
1632
+ input text to that widget.
14181633
*/
14191634
Chat.submitMessage = function f(){
14201635
if(!f.spaces){
14211636
f.spaces = /\s+$/;
14221637
f.markdownContinuation = /\\\s+$/;
14231638
f.spaces2 = /\s{3,}$/;
1639
+ }
1640
+ switch( this.e.currentView ){
1641
+ case this.e.viewSearch: this.submitSearch();
1642
+ return;
1643
+ case this.e.viewPreview: this.e.btnPreview.click();
1644
+ return;
1645
+ default: break;
14241646
}
14251647
this.setCurrentView(this.e.viewMessages);
14261648
const fd = new FormData();
14271649
const fallback = {msg: this.inputValue()};
14281650
var msg = fallback.msg;
@@ -1495,14 +1717,16 @@
14951717
//console.debug("Enter key event:", ctrlMode, ev.ctrlKey, ev.shiftKey, ev);
14961718
if(ev.shiftKey){
14971719
const compactMode = Chat.settings.getBool('edit-compact-mode', false);
14981720
ev.preventDefault();
14991721
ev.stopPropagation();
1500
- /* Shift-enter will run preview mode UNLESS preview mode is
1501
- active AND the input field is empty, in which case it will
1722
+ /* Shift-enter will run preview mode UNLESS the input field is empty
1723
+ AND (preview or search mode) is active, in which cases it will
15021724
switch back to message view. */
1503
- if(Chat.e.currentView===Chat.e.viewPreview && !text){
1725
+ if(!text &&
1726
+ (Chat.e.currentView===Chat.e.viewPreview
1727
+ | Chat.e.currentView===Chat.e.viewSearch)){
15041728
Chat.setCurrentView(Chat.e.viewMessages);
15051729
}else if(!text){
15061730
f.$toggleCompact(compactMode);
15071731
}else if(Chat.settings.getBool('edit-shift-enter-preview', true)){
15081732
Chat.e.btnPreview.click();
@@ -1560,19 +1784,19 @@
15601784
tall vs wide. Can be toggled via settings. */
15611785
document.body.classList.add('my-messages-right');
15621786
}
15631787
const settingsButton = document.querySelector('#chat-button-settings');
15641788
const optionsMenu = E1('#chat-config-options');
1565
- const cbToggle = function(ev){
1789
+ const eToggleView = function(ev){
15661790
ev.preventDefault();
15671791
ev.stopPropagation();
15681792
Chat.setCurrentView(Chat.e.currentView===Chat.e.viewConfig
15691793
? Chat.e.viewMessages : Chat.e.viewConfig);
15701794
return false;
15711795
};
1572
- D.attr(settingsButton, 'role', 'button').addEventListener('click', cbToggle, false);
1573
- Chat.e.viewConfig.querySelector('button').addEventListener('click', cbToggle, false);
1796
+ D.attr(settingsButton, 'role', 'button').addEventListener('click', eToggleView, false);
1797
+ Chat.e.viewConfig.querySelector('button.action-close').addEventListener('click', eToggleView, false);
15741798
15751799
/** Internal acrobatics to allow certain settings toggles to access
15761800
related toggles. */
15771801
const namedOptions = {
15781802
activeUsers:{
@@ -1658,12 +1882,13 @@
16581882
boolValue: 'edit-ctrl-send'
16591883
},{
16601884
label: "Compact mode",
16611885
hint: [
16621886
"Toggle between a space-saving or more spacious writing area. ",
1663
- "When the input field has focus, is empty, and preview mode ",
1664
- "is NOT active then Shift-Enter toggles this setting."].join(''),
1887
+ "When the input field has focus and is empty ",
1888
+ "then Shift-Enter may (depending on the current view) toggle this setting."
1889
+ ].join(''),
16651890
boolValue: 'edit-compact-mode'
16661891
},{
16671892
label: "Use 'contenteditable' editing mode",
16681893
boolValue: 'edit-widget-x',
16691894
hint: [
@@ -1738,10 +1963,14 @@
17381963
const v = ev.target.value;
17391964
Chat.setNewMessageSound(v);
17401965
F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+".");
17411966
if(v) setTimeout(()=>Chat.playNewMessageSound(), 0);
17421967
}
1968
+ },{
1969
+ label: "Notify only once when away",
1970
+ hint: "Notify only for the first message received after chat is hidden from view.",
1971
+ boolValue: 'beep-once'
17431972
},{
17441973
label: "Play notification for your own messages",
17451974
hint: "When enabled, the audio notification will be played for all messages, "+
17461975
"including your own. When disabled only messages from other users "+
17471976
"will trigger a notification.",
@@ -1824,11 +2053,11 @@
18242053
op.persistentSetting,
18252054
function(setting){
18262055
if(op.checkbox) op.checkbox.checked = !!setting.value;
18272056
else if(op.select) op.select.value = setting.value;
18282057
if(op.callback) op.callback(setting);
1829
- }
2058
+ }
18302059
);
18312060
if(op.checkbox){
18322061
op.checkbox.addEventListener(
18332062
'change', function(){
18342063
Chat.settings.set(op.persistentSetting, op.checkbox.checked)
@@ -1900,11 +2129,11 @@
19002129
s.value ? 'add' : 'remove'
19012130
]('compact');
19022131
Chat.e.inputFields[Chat.e.inputFields.$currentIndex].focus();
19032132
});
19042133
Chat.settings.addListener('edit-ctrl-send',function(s){
1905
- const label = (s.value ? "Ctrl-" : "")+"Enter submits messages.";
2134
+ const label = (s.value ? "Ctrl-" : "")+"Enter submits message";
19062135
Chat.e.inputFields.forEach((e)=>{
19072136
const v = e.dataset.placeholder0 + " " +label;
19082137
if(e.isContentEditable) e.dataset.placeholder = v;
19092138
else D.attr(e,'placeholder',v);
19102139
});
@@ -1922,20 +2151,20 @@
19222151
Chat.settings.set(k,v)
19232152
/* fires event listeners so that the Config area checkboxes
19242153
get in sync */;
19252154
});
19262155
})();
1927
-
2156
+
19282157
(function(){/*set up message preview*/
19292158
const btnPreview = Chat.e.btnPreview;
19302159
Chat.setPreviewText = function(t){
19312160
this.setCurrentView(this.e.viewPreview);
19322161
this.e.previewContent.innerHTML = t;
19332162
this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
19342163
this.inputFocus();
19352164
};
1936
- Chat.e.viewPreview.querySelector('#chat-preview-close').
2165
+ Chat.e.viewPreview.querySelector('button.action-close').
19372166
addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
19382167
let previewPending = false;
19392168
const elemsToEnable = [btnPreview, Chat.e.btnSubmit, Chat.e.inputFields];
19402169
const submit = function(ev){
19412170
ev.preventDefault();
@@ -1952,11 +2181,14 @@
19522181
fd.append('filename','chat.md'
19532182
/*filename needed for mimetype determination*/);
19542183
fd.append('render_mode',F.page.previewModes.wiki);
19552184
F.fetch('ajax/preview-text',{
19562185
payload: fd,
1957
- onload: (html)=>Chat.setPreviewText(html),
2186
+ onload: function(html){
2187
+ Chat.setPreviewText(html);
2188
+ F.pikchr.addSrcView(Chat.e.viewPreview.querySelectorAll('svg.pikchr'));
2189
+ },
19582190
onerror: function(e){
19592191
F.fetch.onerror(e);
19602192
Chat.setPreviewText("ERROR: "+(
19612193
e.message || 'Unknown error fetching preview!'
19622194
));
@@ -1975,10 +2207,40 @@
19752207
});
19762208
return false;
19772209
};
19782210
btnPreview.addEventListener('click', submit, false);
19792211
})()/*message preview setup*/;
2212
+
2213
+ (function(){/*Set up #chat-search and related bits */
2214
+ const btn = document.querySelector('#chat-button-search');
2215
+ D.attr(btn, 'role', 'button').addEventListener('click', function(ev){
2216
+ ev.preventDefault();
2217
+ ev.stopPropagation();
2218
+ const msg = Chat.inputValue();
2219
+ if( Chat.e.currentView===Chat.e.viewSearch ){
2220
+ if( msg ) Chat.submitSearch();
2221
+ else Chat.setCurrentView(Chat.e.viewMessages);
2222
+ }else{
2223
+ Chat.setCurrentView(Chat.e.viewSearch);
2224
+ if( msg ) Chat.submitSearch();
2225
+ }
2226
+ return false;
2227
+ }, false);
2228
+ Chat.e.viewSearch.querySelector('button.action-clear').addEventListener('click', function(ev){
2229
+ ev.preventDefault();
2230
+ ev.stopPropagation();
2231
+ Chat.clearSearch(true);
2232
+ Chat.setCurrentView(Chat.e.viewMessages);
2233
+ return false;
2234
+ }, false);
2235
+ Chat.e.viewSearch.querySelector('button.action-close').addEventListener('click', function(ev){
2236
+ ev.preventDefault();
2237
+ ev.stopPropagation();
2238
+ Chat.setCurrentView(Chat.e.viewMessages);
2239
+ return false;
2240
+ }, false);
2241
+ })()/*search view setup*/;
19802242
19812243
/** Callback for poll() to inject new content into the page. jx ==
19822244
the response from /chat-poll. If atEnd is true, the message is
19832245
appended to the end of the chat list (for loading older
19842246
messages), else the beginning (the default). */
@@ -2107,10 +2369,82 @@
21072369
btn.addEventListener('click',()=>loadOldMessages(-1));
21082370
D.append(Chat.e.viewMessages, toolbar);
21092371
toolbar.disabled = true /*will be enabled when msg load finishes */;
21102372
})()/*end history loading widget setup*/;
21112373
2374
+ /**
2375
+ Clears the search result view. If addInstructions is true it adds
2376
+ text to that view instructing the user to enter their query into
2377
+ the message-entry widget (noting that that widget has text
2378
+ implying that it's only for submitting a message, which isn't
2379
+ exactly true when the search view is active).
2380
+
2381
+ Returns the DOM element which wraps all of the chat search
2382
+ result elements.
2383
+ */
2384
+ Chat.clearSearch = function(addInstructions=false){
2385
+ const e = D.clearElement( this.e.searchContent );
2386
+ if(addInstructions){
2387
+ D.append(e, "Enter search terms in the message field. "+
2388
+ "Use #NNNNN to search for the message with ID NNNNN.");
2389
+ }
2390
+ return e;
2391
+ };
2392
+ Chat.clearSearch(true);
2393
+ /**
2394
+ Submits a history search using the main input field's current
2395
+ text. It is assumed that Chat.e.viewSearch===Chat.e.currentView.
2396
+ */
2397
+ Chat.submitSearch = function(){
2398
+ const term = this.inputValue(true);
2399
+ const eMsgTgt = this.clearSearch(true);
2400
+ if( !term ) return;
2401
+ D.append( eMsgTgt, "Searching for ",term," ...");
2402
+ const fd = new FormData();
2403
+ fd.set('q', term);
2404
+ F.fetch(
2405
+ "chat-query", {
2406
+ payload: fd,
2407
+ responseType: 'json',
2408
+ onerror:function(err){
2409
+ Chat.setCurrentView(Chat.e.viewMessages);
2410
+ Chat.reportErrorAsMessage(err);
2411
+ },
2412
+ onload:function(jx){
2413
+ let previd = 0;
2414
+ D.clearElement(eMsgTgt);
2415
+ jx.msgs.forEach((m)=>{
2416
+ m.isSearchResult = true;
2417
+ const mw = new Chat.MessageWidget(m);
2418
+ const spacer = new Chat.SearchCtxLoader({
2419
+ first: jx.first,
2420
+ last: jx.last,
2421
+ previd: previd,
2422
+ nextid: m.msgid
2423
+ });
2424
+ if( spacer.e ) D.append( eMsgTgt, spacer.e.body );
2425
+ D.append( eMsgTgt, mw.e.body );
2426
+ previd = m.msgid;
2427
+ });
2428
+ if( jx.msgs.length ){
2429
+ const spacer = new Chat.SearchCtxLoader({
2430
+ first: jx.first,
2431
+ last: jx.last,
2432
+ previd: previd,
2433
+ nextid: 0
2434
+ });
2435
+ if( spacer.e ) D.append( eMsgTgt, spacer.e.body );
2436
+ }else{
2437
+ D.append( D.clearElement(eMsgTgt),
2438
+ 'No search results found for: ',
2439
+ term );
2440
+ }
2441
+ }
2442
+ }
2443
+ );
2444
+ }/*Chat.submitSearch()*/;
2445
+
21122446
const afterFetch = function f(){
21132447
if(true===f.isFirstCall){
21142448
f.isFirstCall = false;
21152449
Chat.ajaxEnd();
21162450
Chat.e.viewMessages.classList.remove('loading');
@@ -2126,10 +2460,25 @@
21262460
delete Chat.intervalTimer;
21272461
}
21282462
poll.running = false;
21292463
};
21302464
afterFetch.isFirstCall = true;
2465
+ /**
2466
+ FIXME: when polling fails because the remote server is
2467
+ reachable but it's not accepting HTTP requests, we should back
2468
+ off on polling for a while. e.g. if the remote web server process
2469
+ is killed, the poll fails quickly and immediately retries,
2470
+ hammering the remote server until the httpd is back up. That
2471
+ happens often during development of this application.
2472
+
2473
+ XHR does not offer a direct way of distinguishing between
2474
+ HTTP/connection errors, but we can hypothetically use the
2475
+ xhrRequest.status value to do so, with status==0 being a
2476
+ connection error. We do not currently have a clean way of passing
2477
+ that info back to the fossil.fetch() client, so we'll need to
2478
+ hammer on that API a bit to get this working.
2479
+ */
21312480
const poll = async function f(){
21322481
if(f.running) return;
21332482
f.running = true;
21342483
Chat._isBatchLoading = f.isFirstCall;
21352484
if(true===f.isFirstCall){
@@ -2168,17 +2517,11 @@
21682517
Chat._gotServerError = poll.running = false;
21692518
if( window.fossil.config.chat.fromcli ){
21702519
Chat.chatOnlyMode(true);
21712520
}
21722521
Chat.intervalTimer = setInterval(poll, 1000);
2173
- if(0){
2174
- const flip = (ev)=>Chat.animate(ev.target,'anim-flip-h');
2175
- document.querySelectorAll('#chat-buttons-wrapper .cbutton').forEach(function(e){
2176
- e.addEventListener('click',flip, false);
2177
- });
2178
- }
21792522
delete ForceResizeKludge.$disabled;
21802523
ForceResizeKludge();
21812524
Chat.animate.$disabled = false;
21822525
setTimeout( ()=>Chat.inputFocus(), 0 );
21832526
F.page.chat = Chat/* enables testing the APIs via the dev tools */;
21842527
});
21852528
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -124,13 +124,14 @@
124 window.addEventListener('resize', F.debounce(resized, 250), false);
125 return resized;
126 })();
127 fossil.FRK = ForceResizeKludge/*for debugging*/;
128 const Chat = ForceResizeKludge.chat = (function(){
129 const cs = {
130 verboseErrors: false /* if true then certain, mostly extraneous,
131 error messages may be sent to the console. */,
 
132 e:{/*map of certain DOM elements.*/
133 messageInjectPoint: E1('#message-inject-point'),
134 pageTitle: E1('head title'),
135 loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */,
136 inputWrapper: E1("#chat-input-area"),
@@ -145,10 +146,12 @@
145 inputFile: E1('#chat-input-file'),
146 contentDiv: E1('div.content'),
147 viewConfig: E1('#chat-config'),
148 viewPreview: E1('#chat-preview'),
149 previewContent: E1('#chat-preview-content'),
 
 
150 btnPreview: E1('#chat-button-preview'),
151 views: document.querySelectorAll('.chat-view'),
152 activeUserListWrapper: E1('#chat-user-list-wrapper'),
153 activeUserList: E1('#chat-user-list')
154 },
@@ -173,21 +176,31 @@
173 activeUser: undefined,
174 match: function(uname){
175 return this.activeUser===uname || !this.activeUser;
176 }
177 },
178 /** Gets (no args) or sets (1 arg) the current input text field value,
179 taking into account single- vs multi-line input. The getter returns
180 a string and the setter returns this object. */
181 inputValue: function(){
 
 
 
 
 
182 const e = this.inputElement();
183 if(arguments.length){
184 if(e.isContentEditable) e.innerText = arguments[0];
185 else e.value = arguments[0];
186 return this;
187 }
188 return e.isContentEditable ? e.innerText : e.value;
 
 
 
 
 
189 },
190 /** Asks the current user input field to take focus. Returns this. */
191 inputFocus: function(){
192 this.inputElement().focus();
193 return this;
@@ -410,10 +423,13 @@
410 /* When set to a URI, it is assumed to be an audio file,
411 which gets played when new messages arrive. When true,
412 the first entry in the audio file selection list will be
413 used. */
414 "audible-alert": true,
 
 
 
415 /* When on, show the list of "active" users - those from
416 whom we have messages in the currently-loaded history
417 (noting that deletions are also messages). */
418 "active-user-list": false,
419 /* When on, the [active-user-list] setting includes the
@@ -434,11 +450,17 @@
434 /** Plays a new-message notification sound IF the audible-alert
435 setting is true, else this is a no-op. Returns this.
436 */
437 playNewMessageSound: function f(){
438 if(f.uri){
 
 
 
 
 
439 try{
 
440 if(!f.audio) f.audio = new Audio(f.uri);
441 f.audio.currentTime = 0;
442 f.audio.play();
443 }catch(e){
444 console.error("Audio playblack failed.", f.uri, e);
@@ -451,10 +473,11 @@
451 repository-relative path which responds with an audio
452 file). Pass a falsy value to disable audio alerts. Returns
453 this.
454 */
455 setNewMessageSound: function f(uri){
 
456 delete this.playNewMessageSound.audio;
457 this.playNewMessageSound.uri = uri;
458 this.settings.set('audible-alert', uri);
459 return this;
460 },
@@ -502,11 +525,11 @@
502 const uDate = self.usersLastSeen[u];
503 if(self.filterState.activeUser===u){
504 uSpan.classList.add('selected');
505 }
506 uSpan.dataset.uname = u;
507 D.append(uSpan, u, "\n",
508 D.append(
509 D.addClass(D.span(),'timestamp'),
510 localTimeString(uDate)//.substr(5/*chop off year*/)
511 ));
512 if(uDate.$uColor){
@@ -780,19 +803,19 @@
780 cs._newResponseError = function(response){
781 return new Error([
782 "HTTP status ", response.status,": ",response.url,": ",
783 response.statusText].join(''));
784 };
785
786 /** Helper for reporting HTTP-level response errors via fetch().
787 If response.ok then response.json() is returned, else an Error
788 is thrown. */
789 cs._fetchJsonOrError = function(response){
790 if(response.ok) return response.json();
791 else throw cs._newResponseError(response);
792 };
793
794 /**
795 Removes the given message ID from the local chat record and, if
796 the message was posted by this user OR this user in an
797 admin/setup, also submits it for removal on the remote.
798
@@ -819,10 +842,11 @@
819 this.deleteMessageElem(id);
820 }
821 };
822 document.addEventListener('visibilitychange', function(ev){
823 cs.pageIsActive = ('visible' === document.visibilityState);
 
824 if(cs.pageIsActive){
825 cs.e.pageTitle.innerText = cs.pageTitleOrig;
826 if(document.activeElement!==cs.inputElement()){
827 /* An attempt to resolve usability problem reported by Joe
828 M. where the Pale Moon browser is giving input focus to
@@ -886,11 +910,11 @@
886 Chat.MessageWidget = (function(){
887 /**
888 Constructor. If passed an argument, it is passed to
889 this.setMessage() after initialization.
890 */
891 const cf = function(){
892 this.e = {
893 body: D.addClass(D.div(), 'message-widget'),
894 tab: D.addClass(D.div(), 'message-widget-tab'),
895 content: D.addClass(D.div(), 'message-widget-content')
896 };
@@ -905,20 +929,33 @@
905 /* Map of Date.getDay() values to weekday names. */
906 0: "Sunday", 1: "Monday", 2: "Tuesday",
907 3: "Wednesday", 4: "Thursday", 5: "Friday",
908 6: "Saturday"
909 };
910 /* Given a Date, returns the timestamp string used in the
911 "tab" part of message widgets. */
912 const theTime = function(d){
913 return [
914 //d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
915 //'-',pad2(d.getDate()), ' ',
916 d.getHours(),":",
917 (d.getMinutes()+100).toString().slice(1,3),
918 ' ', dowMap[d.getDay()]
919 ].join('');
 
 
 
 
 
 
 
 
 
 
 
 
 
920 };
921
922 /**
923 Returns true if this page believes it can embed a view of the
924 file wrapped by the given message object, else returns false.
@@ -925,19 +962,20 @@
925 */
926 const canEmbedFile = function f(msg){
927 if(!f.$rx){
928 f.$rx = /\.((html?)|(txt)|(md)|(wiki)|(pikchr))$/i;
929 f.$specificTypes = [
 
930 'text/plain',
931 'text/html',
932 'text/x-markdown',
933 /* Firefox sends text/markdown when uploading .md files */
934 'text/markdown',
935 'text/x-pikchr',
936 'text/x-fossil-wiki'
937 // add more as we discover which ones Firefox won't
938 // force the user to try to download.
939 ];
940 }
941 if(msg.fmime){
942 if(msg.fmime.startsWith("image/")
943 || f.$specificTypes.indexOf(msg.fmime)>=0){
@@ -951,20 +989,18 @@
951 Returns true if the given message object "should"
952 be embedded in fossil-rendered form instead of
953 raw content form. This is only intended to be passed
954 message objects for which canEmbedFile() returns true.
955 */
956 const shouldWikiRenderEmbed = function f(msg){
957 if(!f.$rx){
958 f.$rx = /\.((md)|(wiki)|(pikchr))$/i;
959 f.$specificTypes = [
960 'text/x-markdown',
961 'text/markdown' /* Firefox-uploaded md files */,
962 'text/x-pikchr',
963 'text/x-fossil-wiki'
964 // add more as we discover which ones Firefox won't
965 // force the user to try to download.
966 ];
967 }
968 if(msg.fmime){
969 if(f.$specificTypes.indexOf(msg.fmime)>=0) return true;
970 }
@@ -990,12 +1026,12 @@
990 iframe.style.maxHeight = iframe.style.height
991 = iframe.contentWindow.document.documentElement.scrollHeight + 'px';
992 if(isHidden) D.addClass(iframe, 'hidden');
993 }
994 };
995
996 cf.prototype = {
997 scrollIntoView: function(){
998 this.e.content.scrollIntoView();
999 },
1000 setMessage: function(m){
1001 const ds = this.e.body.dataset;
@@ -1016,20 +1052,26 @@
1016 var eXFrom /* element holding xfrom name */;
1017 if(m.xfrom){
1018 eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
1019 const wrapper = D.append(
1020 D.span(), eXFrom,
1021 D.text(" #",(m.msgid||'???'),' @ ',theTime(d)))
 
 
 
 
 
 
1022 D.append(this.e.tab, wrapper);
1023 }else{/*notification*/
1024 D.addClass(this.e.body, 'notification');
1025 if(m.isError){
1026 D.addClass([contentTarget, this.e.tab], 'error');
1027 }
1028 D.append(
1029 this.e.tab,
1030 D.append(D.code(), 'notification @ ',theTime(d))
1031 );
1032 }
1033 if( m.xfrom && m.fsize>0 ){
1034 if( m.fmime
1035 && m.fmime.startsWith("image/")
@@ -1052,18 +1094,18 @@
1052 D.attr(a,'target','_blank');
1053 D.append(w, a);
1054 if(canEmbedFile(m)){
1055 /* Add an option to embed HTML attachments in an iframe. The primary
1056 use case is attached diffs. */
1057 const shouldWikiRender = shouldWikiRenderEmbed(m);
1058 const downloadArgs = shouldWikiRender ? '?render' : '';
1059 D.addClass(contentTarget, 'wide');
1060 const embedTarget = this.e.content;
1061 const self = this;
1062 const btnEmbed = D.attr(D.checkbox("1", false), 'id',
1063 'embed-'+ds.msgid);
1064 const btnLabel = D.label(btnEmbed, shouldWikiRender
1065 ? "Embed (fossil-rendered)" : "Embed");
1066 /* Maintenance reminder: do not disable the toggle
1067 button while the content is loading because that will
1068 cause it to get stuck in disabled mode if the browser
1069 decides that loading the content should prompt the
@@ -1268,13 +1310,183 @@
1268 }/*end static init*/
1269 const theMsg = findMessageWidgetParent(ev.target);
1270 if(theMsg) f.popup.show(theMsg);
1271 }/*_handleLegendClicked()*/
1272 };
1273 return cf;
1274 })()/*MessageWidget*/;
1275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1276 const BlobXferState = (function(){
1277 /* State for paste and drag/drop */
1278 const bxs = {
1279 dropDetails: document.querySelector('#chat-drop-details'),
1280 blob: undefined,
@@ -1413,16 +1625,26 @@
1413
1414 /**
1415 Submits the contents of the message input field (if not empty)
1416 and/or the file attachment field to the server. If both are
1417 empty, this is a no-op.
 
 
 
1418 */
1419 Chat.submitMessage = function f(){
1420 if(!f.spaces){
1421 f.spaces = /\s+$/;
1422 f.markdownContinuation = /\\\s+$/;
1423 f.spaces2 = /\s{3,}$/;
 
 
 
 
 
 
 
1424 }
1425 this.setCurrentView(this.e.viewMessages);
1426 const fd = new FormData();
1427 const fallback = {msg: this.inputValue()};
1428 var msg = fallback.msg;
@@ -1495,14 +1717,16 @@
1495 //console.debug("Enter key event:", ctrlMode, ev.ctrlKey, ev.shiftKey, ev);
1496 if(ev.shiftKey){
1497 const compactMode = Chat.settings.getBool('edit-compact-mode', false);
1498 ev.preventDefault();
1499 ev.stopPropagation();
1500 /* Shift-enter will run preview mode UNLESS preview mode is
1501 active AND the input field is empty, in which case it will
1502 switch back to message view. */
1503 if(Chat.e.currentView===Chat.e.viewPreview && !text){
 
 
1504 Chat.setCurrentView(Chat.e.viewMessages);
1505 }else if(!text){
1506 f.$toggleCompact(compactMode);
1507 }else if(Chat.settings.getBool('edit-shift-enter-preview', true)){
1508 Chat.e.btnPreview.click();
@@ -1560,19 +1784,19 @@
1560 tall vs wide. Can be toggled via settings. */
1561 document.body.classList.add('my-messages-right');
1562 }
1563 const settingsButton = document.querySelector('#chat-button-settings');
1564 const optionsMenu = E1('#chat-config-options');
1565 const cbToggle = function(ev){
1566 ev.preventDefault();
1567 ev.stopPropagation();
1568 Chat.setCurrentView(Chat.e.currentView===Chat.e.viewConfig
1569 ? Chat.e.viewMessages : Chat.e.viewConfig);
1570 return false;
1571 };
1572 D.attr(settingsButton, 'role', 'button').addEventListener('click', cbToggle, false);
1573 Chat.e.viewConfig.querySelector('button').addEventListener('click', cbToggle, false);
1574
1575 /** Internal acrobatics to allow certain settings toggles to access
1576 related toggles. */
1577 const namedOptions = {
1578 activeUsers:{
@@ -1658,12 +1882,13 @@
1658 boolValue: 'edit-ctrl-send'
1659 },{
1660 label: "Compact mode",
1661 hint: [
1662 "Toggle between a space-saving or more spacious writing area. ",
1663 "When the input field has focus, is empty, and preview mode ",
1664 "is NOT active then Shift-Enter toggles this setting."].join(''),
 
1665 boolValue: 'edit-compact-mode'
1666 },{
1667 label: "Use 'contenteditable' editing mode",
1668 boolValue: 'edit-widget-x',
1669 hint: [
@@ -1738,10 +1963,14 @@
1738 const v = ev.target.value;
1739 Chat.setNewMessageSound(v);
1740 F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+".");
1741 if(v) setTimeout(()=>Chat.playNewMessageSound(), 0);
1742 }
 
 
 
 
1743 },{
1744 label: "Play notification for your own messages",
1745 hint: "When enabled, the audio notification will be played for all messages, "+
1746 "including your own. When disabled only messages from other users "+
1747 "will trigger a notification.",
@@ -1824,11 +2053,11 @@
1824 op.persistentSetting,
1825 function(setting){
1826 if(op.checkbox) op.checkbox.checked = !!setting.value;
1827 else if(op.select) op.select.value = setting.value;
1828 if(op.callback) op.callback(setting);
1829 }
1830 );
1831 if(op.checkbox){
1832 op.checkbox.addEventListener(
1833 'change', function(){
1834 Chat.settings.set(op.persistentSetting, op.checkbox.checked)
@@ -1900,11 +2129,11 @@
1900 s.value ? 'add' : 'remove'
1901 ]('compact');
1902 Chat.e.inputFields[Chat.e.inputFields.$currentIndex].focus();
1903 });
1904 Chat.settings.addListener('edit-ctrl-send',function(s){
1905 const label = (s.value ? "Ctrl-" : "")+"Enter submits messages.";
1906 Chat.e.inputFields.forEach((e)=>{
1907 const v = e.dataset.placeholder0 + " " +label;
1908 if(e.isContentEditable) e.dataset.placeholder = v;
1909 else D.attr(e,'placeholder',v);
1910 });
@@ -1922,20 +2151,20 @@
1922 Chat.settings.set(k,v)
1923 /* fires event listeners so that the Config area checkboxes
1924 get in sync */;
1925 });
1926 })();
1927
1928 (function(){/*set up message preview*/
1929 const btnPreview = Chat.e.btnPreview;
1930 Chat.setPreviewText = function(t){
1931 this.setCurrentView(this.e.viewPreview);
1932 this.e.previewContent.innerHTML = t;
1933 this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
1934 this.inputFocus();
1935 };
1936 Chat.e.viewPreview.querySelector('#chat-preview-close').
1937 addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
1938 let previewPending = false;
1939 const elemsToEnable = [btnPreview, Chat.e.btnSubmit, Chat.e.inputFields];
1940 const submit = function(ev){
1941 ev.preventDefault();
@@ -1952,11 +2181,14 @@
1952 fd.append('filename','chat.md'
1953 /*filename needed for mimetype determination*/);
1954 fd.append('render_mode',F.page.previewModes.wiki);
1955 F.fetch('ajax/preview-text',{
1956 payload: fd,
1957 onload: (html)=>Chat.setPreviewText(html),
 
 
 
1958 onerror: function(e){
1959 F.fetch.onerror(e);
1960 Chat.setPreviewText("ERROR: "+(
1961 e.message || 'Unknown error fetching preview!'
1962 ));
@@ -1975,10 +2207,40 @@
1975 });
1976 return false;
1977 };
1978 btnPreview.addEventListener('click', submit, false);
1979 })()/*message preview setup*/;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1980
1981 /** Callback for poll() to inject new content into the page. jx ==
1982 the response from /chat-poll. If atEnd is true, the message is
1983 appended to the end of the chat list (for loading older
1984 messages), else the beginning (the default). */
@@ -2107,10 +2369,82 @@
2107 btn.addEventListener('click',()=>loadOldMessages(-1));
2108 D.append(Chat.e.viewMessages, toolbar);
2109 toolbar.disabled = true /*will be enabled when msg load finishes */;
2110 })()/*end history loading widget setup*/;
2111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2112 const afterFetch = function f(){
2113 if(true===f.isFirstCall){
2114 f.isFirstCall = false;
2115 Chat.ajaxEnd();
2116 Chat.e.viewMessages.classList.remove('loading');
@@ -2126,10 +2460,25 @@
2126 delete Chat.intervalTimer;
2127 }
2128 poll.running = false;
2129 };
2130 afterFetch.isFirstCall = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2131 const poll = async function f(){
2132 if(f.running) return;
2133 f.running = true;
2134 Chat._isBatchLoading = f.isFirstCall;
2135 if(true===f.isFirstCall){
@@ -2168,17 +2517,11 @@
2168 Chat._gotServerError = poll.running = false;
2169 if( window.fossil.config.chat.fromcli ){
2170 Chat.chatOnlyMode(true);
2171 }
2172 Chat.intervalTimer = setInterval(poll, 1000);
2173 if(0){
2174 const flip = (ev)=>Chat.animate(ev.target,'anim-flip-h');
2175 document.querySelectorAll('#chat-buttons-wrapper .cbutton').forEach(function(e){
2176 e.addEventListener('click',flip, false);
2177 });
2178 }
2179 delete ForceResizeKludge.$disabled;
2180 ForceResizeKludge();
2181 Chat.animate.$disabled = false;
2182 setTimeout( ()=>Chat.inputFocus(), 0 );
2183 F.page.chat = Chat/* enables testing the APIs via the dev tools */;
2184 });
2185
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -124,13 +124,14 @@
124 window.addEventListener('resize', F.debounce(resized, 250), false);
125 return resized;
126 })();
127 fossil.FRK = ForceResizeKludge/*for debugging*/;
128 const Chat = ForceResizeKludge.chat = (function(){
129 const cs = { // the "Chat" object (result of this function)
130 verboseErrors: false /* if true then certain, mostly extraneous,
131 error messages may be sent to the console. */,
132 playedBeep: false /* used for the beep-once setting */,
133 e:{/*map of certain DOM elements.*/
134 messageInjectPoint: E1('#message-inject-point'),
135 pageTitle: E1('head title'),
136 loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */,
137 inputWrapper: E1("#chat-input-area"),
@@ -145,10 +146,12 @@
146 inputFile: E1('#chat-input-file'),
147 contentDiv: E1('div.content'),
148 viewConfig: E1('#chat-config'),
149 viewPreview: E1('#chat-preview'),
150 previewContent: E1('#chat-preview-content'),
151 viewSearch: E1('#chat-search'),
152 searchContent: E1('#chat-search-content'),
153 btnPreview: E1('#chat-button-preview'),
154 views: document.querySelectorAll('.chat-view'),
155 activeUserListWrapper: E1('#chat-user-list-wrapper'),
156 activeUserList: E1('#chat-user-list')
157 },
@@ -173,21 +176,31 @@
176 activeUser: undefined,
177 match: function(uname){
178 return this.activeUser===uname || !this.activeUser;
179 }
180 },
181 /**
182 Gets (no args) or sets (1 arg) the current input text field
183 value, taking into account single- vs multi-line input. The
184 getter returns a trim()'d string and the setter returns this
185 object. As a special case, if arguments[0] is a boolean
186 value, it behaves like a getter and, if arguments[0]===true
187 it clears the input field before returning.
188 */
189 inputValue: function(/*string newValue | bool clearInputField*/){
190 const e = this.inputElement();
191 if(arguments.length && 'boolean'!==typeof arguments[0]){
192 if(e.isContentEditable) e.innerText = arguments[0];
193 else e.value = arguments[0];
194 return this;
195 }
196 const rc = e.isContentEditable ? e.innerText : e.value;
197 if( true===arguments[0] ){
198 if(e.isContentEditable) e.innerText = '';
199 else e.value = '';
200 }
201 return rc && rc.trim();
202 },
203 /** Asks the current user input field to take focus. Returns this. */
204 inputFocus: function(){
205 this.inputElement().focus();
206 return this;
@@ -410,10 +423,13 @@
423 /* When set to a URI, it is assumed to be an audio file,
424 which gets played when new messages arrive. When true,
425 the first entry in the audio file selection list will be
426 used. */
427 "audible-alert": true,
428 /*
429 */
430 "beep-once": false,
431 /* When on, show the list of "active" users - those from
432 whom we have messages in the currently-loaded history
433 (noting that deletions are also messages). */
434 "active-user-list": false,
435 /* When on, the [active-user-list] setting includes the
@@ -434,11 +450,17 @@
450 /** Plays a new-message notification sound IF the audible-alert
451 setting is true, else this is a no-op. Returns this.
452 */
453 playNewMessageSound: function f(){
454 if(f.uri){
455 if(!cs.pageIsActive
456 /* ^^^ this could also arguably apply when chat is visible */
457 && this.playedBeep && this.settings.getBool('beep-once',false)){
458 return;
459 }
460 try{
461 this.playedBeep = true;
462 if(!f.audio) f.audio = new Audio(f.uri);
463 f.audio.currentTime = 0;
464 f.audio.play();
465 }catch(e){
466 console.error("Audio playblack failed.", f.uri, e);
@@ -451,10 +473,11 @@
473 repository-relative path which responds with an audio
474 file). Pass a falsy value to disable audio alerts. Returns
475 this.
476 */
477 setNewMessageSound: function f(uri){
478 this.playedBeep = false;
479 delete this.playNewMessageSound.audio;
480 this.playNewMessageSound.uri = uri;
481 this.settings.set('audible-alert', uri);
482 return this;
483 },
@@ -502,11 +525,11 @@
525 const uDate = self.usersLastSeen[u];
526 if(self.filterState.activeUser===u){
527 uSpan.classList.add('selected');
528 }
529 uSpan.dataset.uname = u;
530 D.append(uSpan, u, "\n",
531 D.append(
532 D.addClass(D.span(),'timestamp'),
533 localTimeString(uDate)//.substr(5/*chop off year*/)
534 ));
535 if(uDate.$uColor){
@@ -780,19 +803,19 @@
803 cs._newResponseError = function(response){
804 return new Error([
805 "HTTP status ", response.status,": ",response.url,": ",
806 response.statusText].join(''));
807 };
808
809 /** Helper for reporting HTTP-level response errors via fetch().
810 If response.ok then response.json() is returned, else an Error
811 is thrown. */
812 cs._fetchJsonOrError = function(response){
813 if(response.ok) return response.json();
814 else throw cs._newResponseError(response);
815 };
816
817 /**
818 Removes the given message ID from the local chat record and, if
819 the message was posted by this user OR this user in an
820 admin/setup, also submits it for removal on the remote.
821
@@ -819,10 +842,11 @@
842 this.deleteMessageElem(id);
843 }
844 };
845 document.addEventListener('visibilitychange', function(ev){
846 cs.pageIsActive = ('visible' === document.visibilityState);
847 cs.playedBeep = false;
848 if(cs.pageIsActive){
849 cs.e.pageTitle.innerText = cs.pageTitleOrig;
850 if(document.activeElement!==cs.inputElement()){
851 /* An attempt to resolve usability problem reported by Joe
852 M. where the Pale Moon browser is giving input focus to
@@ -886,11 +910,11 @@
910 Chat.MessageWidget = (function(){
911 /**
912 Constructor. If passed an argument, it is passed to
913 this.setMessage() after initialization.
914 */
915 const ctor = function(){
916 this.e = {
917 body: D.addClass(D.div(), 'message-widget'),
918 tab: D.addClass(D.div(), 'message-widget-tab'),
919 content: D.addClass(D.div(), 'message-widget-content')
920 };
@@ -905,20 +929,33 @@
929 /* Map of Date.getDay() values to weekday names. */
930 0: "Sunday", 1: "Monday", 2: "Tuesday",
931 3: "Wednesday", 4: "Thursday", 5: "Friday",
932 6: "Saturday"
933 };
934 /* Given a Date, returns the timestamp string used in the "tab"
935 part of message widgets. If longFmt is true then a verbose
936 format is used, else a brief format is used. The returned string
937 is in client-local time. */
938 const theTime = function(d, longFmt=false){
939 const li = [];
940 if( longFmt ){
941 li.push(
942 d.getFullYear(),
943 '-', pad2(d.getMonth()+1),
944 '-', pad2(d.getDate()),
945 ' ',
946 d.getHours(), ":",
947 (d.getMinutes()+100).toString().slice(1,3)
948 );
949 }else{
950 li.push(
951 d.getHours(),":",
952 (d.getMinutes()+100).toString().slice(1,3),
953 ' ', dowMap[d.getDay()]
954 );
955 }
956 return li.join('');
957 };
958
959 /**
960 Returns true if this page believes it can embed a view of the
961 file wrapped by the given message object, else returns false.
@@ -925,19 +962,20 @@
962 */
963 const canEmbedFile = function f(msg){
964 if(!f.$rx){
965 f.$rx = /\.((html?)|(txt)|(md)|(wiki)|(pikchr))$/i;
966 f.$specificTypes = [
967 /* Mime types we know we can embed, sans image/... */
968 'text/plain',
969 'text/html',
970 'text/x-markdown',
971 /* Firefox sends text/markdown when uploading .md files */
972 'text/markdown',
973 'text/x-pikchr',
974 'text/x-fossil-wiki'
975 /* Add more as we discover which ones Firefox won't
976 force the user to try to download. */
977 ];
978 }
979 if(msg.fmime){
980 if(msg.fmime.startsWith("image/")
981 || f.$specificTypes.indexOf(msg.fmime)>=0){
@@ -951,20 +989,18 @@
989 Returns true if the given message object "should"
990 be embedded in fossil-rendered form instead of
991 raw content form. This is only intended to be passed
992 message objects for which canEmbedFile() returns true.
993 */
994 const shouldFossilRenderEmbed = function f(msg){
995 if(!f.$rx){
996 f.$rx = /\.((md)|(wiki)|(pikchr))$/i;
997 f.$specificTypes = [
998 'text/x-markdown',
999 'text/markdown' /* Firefox-uploaded md files */,
1000 'text/x-pikchr',
1001 'text/x-fossil-wiki'
 
 
1002 ];
1003 }
1004 if(msg.fmime){
1005 if(f.$specificTypes.indexOf(msg.fmime)>=0) return true;
1006 }
@@ -990,12 +1026,12 @@
1026 iframe.style.maxHeight = iframe.style.height
1027 = iframe.contentWindow.document.documentElement.scrollHeight + 'px';
1028 if(isHidden) D.addClass(iframe, 'hidden');
1029 }
1030 };
1031
1032 ctor.prototype = {
1033 scrollIntoView: function(){
1034 this.e.content.scrollIntoView();
1035 },
1036 setMessage: function(m){
1037 const ds = this.e.body.dataset;
@@ -1016,20 +1052,26 @@
1052 var eXFrom /* element holding xfrom name */;
1053 if(m.xfrom){
1054 eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
1055 const wrapper = D.append(
1056 D.span(), eXFrom,
1057 ' ',
1058 D.append(D.addClass(D.span(), 'msgid'),
1059 '#' + (m.msgid||'???')),
1060 (m.isSearchResult ? ' ' : ' @ '),
1061 D.append(D.addClass(D.span(), 'timestamp'),
1062 theTime(d,!!m.isSearchResult))
1063 );
1064 D.append(this.e.tab, wrapper);
1065 }else{/*notification*/
1066 D.addClass(this.e.body, 'notification');
1067 if(m.isError){
1068 D.addClass([contentTarget, this.e.tab], 'error');
1069 }
1070 D.append(
1071 this.e.tab,
1072 D.append(D.code(), 'notification @ ',theTime(d,false))
1073 );
1074 }
1075 if( m.xfrom && m.fsize>0 ){
1076 if( m.fmime
1077 && m.fmime.startsWith("image/")
@@ -1052,18 +1094,18 @@
1094 D.attr(a,'target','_blank');
1095 D.append(w, a);
1096 if(canEmbedFile(m)){
1097 /* Add an option to embed HTML attachments in an iframe. The primary
1098 use case is attached diffs. */
1099 const shouldFossilRender = shouldFossilRenderEmbed(m);
1100 const downloadArgs = shouldFossilRender ? '?render' : '';
1101 D.addClass(contentTarget, 'wide');
1102 const embedTarget = this.e.content;
1103 const self = this;
1104 const btnEmbed = D.attr(D.checkbox("1", false), 'id',
1105 'embed-'+ds.msgid);
1106 const btnLabel = D.label(btnEmbed, shouldFossilRender
1107 ? "Embed (fossil-rendered)" : "Embed");
1108 /* Maintenance reminder: do not disable the toggle
1109 button while the content is loading because that will
1110 cause it to get stuck in disabled mode if the browser
1111 decides that loading the content should prompt the
@@ -1268,13 +1310,183 @@
1310 }/*end static init*/
1311 const theMsg = findMessageWidgetParent(ev.target);
1312 if(theMsg) f.popup.show(theMsg);
1313 }/*_handleLegendClicked()*/
1314 };
1315 return ctor;
1316 })()/*MessageWidget*/;
1317
1318 /**
1319 A widget for loading more messages (context) around a /chat-query
1320 result message.
1321 */
1322 Chat.SearchCtxLoader = (function(){
1323 const nMsgContext = 5;
1324 const zUpArrow = '\u25B2';
1325 const zDownArrow = '\u25BC';
1326 const ctor = function(o){
1327
1328 /* iFirstInTable:
1329 ** msgid of first row in chatfts table.
1330 **
1331 ** iLastInTable:
1332 ** msgid of last row in chatfts table.
1333 **
1334 ** iPrevId:
1335 ** msgid of message immediately above this spacer. Or 0 if this
1336 ** spacer is above all results.
1337 **
1338 ** iNextId:
1339 ** msgid of message immediately below this spacer. Or 0 if this
1340 ** spacer is below all results.
1341 **
1342 ** bIgnoreClick:
1343 ** ignore any clicks if this is true. This is used to ensure there
1344 ** is only ever one request belonging to this widget outstanding
1345 ** at any time.
1346 */
1347 this.o = {
1348 iFirstInTable: o.first,
1349 iLastInTable: o.last,
1350 iPrevId: o.previd,
1351 iNextId: o.nextid,
1352 bIgnoreClick: false
1353 };
1354
1355 this.e = {
1356 body: D.addClass(D.div(), 'spacer-widget'),
1357 up: D.addClass(
1358 D.button(zDownArrow+' Load '+nMsgContext+' more '+zDownArrow),
1359 'up'
1360 ),
1361 down: D.addClass(
1362 D.button(zUpArrow+' Load '+nMsgContext+' more '+zUpArrow),
1363 'down'
1364 ),
1365 all: D.addClass(D.button('Load More'), 'all')
1366 };
1367 D.append( this.e.body, this.e.up, this.e.down, this.e.all );
1368 const ms = this;
1369 this.e.up.addEventListener('click', ()=>ms.load_messages(false));
1370 this.e.down.addEventListener('click', ()=>ms.load_messages(true));
1371 this.e.all.addEventListener('click', ()=>ms.load_messages( (ms.o.iPrevId==0) ));
1372 this.set_button_visibility();
1373 };
1374
1375 ctor.prototype = {
1376 set_button_visibility: function() {
1377 if( !this.e ) return;
1378 const o = this.o;
1379
1380 const iPrevId = (o.iPrevId!=0) ? o.iPrevId : o.iFirstInTable-1;
1381 const iNextId = (o.iNextId!=0) ? o.iNextId : o.iLastInTable+1;
1382 let nDiff = (iNextId - iPrevId) - 1;
1383
1384 for( const x of [this.e.up, this.e.down, this.e.all] ){
1385 if( x ) D.addClass(x, 'hidden');
1386 }
1387 let nVisible = 0;
1388 if( nDiff>0 ){
1389 if( nDiff>nMsgContext && (o.iPrevId==0 || o.iNextId==0) ){
1390 nDiff = nMsgContext;
1391 }
1392
1393 if( nDiff<=nMsgContext && o.iPrevId!=0 && o.iNextId!=0 ){
1394 D.removeClass(this.e.all, 'hidden');
1395 ++nVisible;
1396 this.e.all.innerText = (
1397 zUpArrow + " Load " + nDiff + " more " + zDownArrow
1398 );
1399 }else{
1400 if( o.iPrevId!=0 ){
1401 ++nVisible;
1402 D.removeClass(this.e.up, 'hidden');
1403 }else if( this.e.up ){
1404 if( this.e.up.parentNode ) D.remove(this.e.up);
1405 delete this.e.up;
1406 }
1407 if( o.iNextId!=0 ){
1408 ++nVisible;
1409 D.removeClass(this.e.down, 'hidden');
1410 }else if( this.e.down ){
1411 if( this.e.down.parentNode ) D.remove( this.e.down );
1412 delete this.e.down;
1413 }
1414 }
1415 }
1416 if( !nVisible ){
1417 /* The DOM elements can now be disposed of. */
1418 for( const x of [this.e.up, this.e.down, this.e.all, this.e.body] ){
1419 if( x?.parentNode ) D.remove(x);
1420 }
1421 delete this.e;
1422 }
1423 },
1424
1425 load_messages: function(bDown) {
1426 if( this.bIgnoreClick ) return;
1427
1428 var iFirst = 0; /* msgid of first message to fetch */
1429 var nFetch = 0; /* Number of messages to fetch */
1430 var iEof = 0; /* last msgid in spacers range, plus 1 */
1431
1432 const e = this.e, o = this.o;
1433 this.bIgnoreClick = true;
1434
1435 /* Figure out the required range of messages. */
1436 if( bDown ){
1437 iFirst = this.o.iNextId - nMsgContext;
1438 if( iFirst<this.o.iFirstInTable ){
1439 iFirst = this.o.iFirstInTable;
1440 }
1441 }else{
1442 iFirst = this.o.iPrevId+1;
1443 }
1444 nFetch = nMsgContext;
1445 iEof = (this.o.iNextId > 0) ? this.o.iNextId : this.o.iLastInTable+1;
1446 if( iFirst+nFetch>iEof ){
1447 nFetch = iEof - iFirst;
1448 }
1449 const ms = this;
1450 F.fetch("chat-query",{
1451 urlParams:{
1452 q: '',
1453 n: nFetch,
1454 i: iFirst
1455 },
1456 responseType: "json",
1457 onload:function(jx){
1458 if( bDown ) jx.msgs.reverse();
1459 jx.msgs.forEach((m) => {
1460 m.isSearchResult = true;
1461 var mw = new Chat.MessageWidget(m);
1462 if( bDown ){
1463 /* Inject the message below this object's body, or
1464 append it to Chat.e.searchContent if this element
1465 is the final one in its parent (Chat.e.searchContent). */
1466 const eAnchor = e.body.nextElementSibling;
1467 if( eAnchor ) Chat.e.searchContent.insertBefore(mw.e.body, eAnchor);
1468 else D.append(Chat.e.searchContent, mw.e.body);
1469 }else{
1470 Chat.e.searchContent.insertBefore(mw.e.body, e.body);
1471 }
1472 });
1473 if( bDown ){
1474 o.iNextId -= jx.msgs.length;
1475 }else{
1476 o.iPrevId += jx.msgs.length;
1477 }
1478 ms.set_button_visibility();
1479 ms.bIgnoreClick = false;
1480 }
1481 });
1482 }
1483 };
1484
1485 return ctor;
1486 })() /*SearchCtxLoader*/;
1487
1488 const BlobXferState = (function(){
1489 /* State for paste and drag/drop */
1490 const bxs = {
1491 dropDetails: document.querySelector('#chat-drop-details'),
1492 blob: undefined,
@@ -1413,16 +1625,26 @@
1625
1626 /**
1627 Submits the contents of the message input field (if not empty)
1628 and/or the file attachment field to the server. If both are
1629 empty, this is a no-op.
1630
1631 If the current view is the history search, this instead sends the
1632 input text to that widget.
1633 */
1634 Chat.submitMessage = function f(){
1635 if(!f.spaces){
1636 f.spaces = /\s+$/;
1637 f.markdownContinuation = /\\\s+$/;
1638 f.spaces2 = /\s{3,}$/;
1639 }
1640 switch( this.e.currentView ){
1641 case this.e.viewSearch: this.submitSearch();
1642 return;
1643 case this.e.viewPreview: this.e.btnPreview.click();
1644 return;
1645 default: break;
1646 }
1647 this.setCurrentView(this.e.viewMessages);
1648 const fd = new FormData();
1649 const fallback = {msg: this.inputValue()};
1650 var msg = fallback.msg;
@@ -1495,14 +1717,16 @@
1717 //console.debug("Enter key event:", ctrlMode, ev.ctrlKey, ev.shiftKey, ev);
1718 if(ev.shiftKey){
1719 const compactMode = Chat.settings.getBool('edit-compact-mode', false);
1720 ev.preventDefault();
1721 ev.stopPropagation();
1722 /* Shift-enter will run preview mode UNLESS the input field is empty
1723 AND (preview or search mode) is active, in which cases it will
1724 switch back to message view. */
1725 if(!text &&
1726 (Chat.e.currentView===Chat.e.viewPreview
1727 | Chat.e.currentView===Chat.e.viewSearch)){
1728 Chat.setCurrentView(Chat.e.viewMessages);
1729 }else if(!text){
1730 f.$toggleCompact(compactMode);
1731 }else if(Chat.settings.getBool('edit-shift-enter-preview', true)){
1732 Chat.e.btnPreview.click();
@@ -1560,19 +1784,19 @@
1784 tall vs wide. Can be toggled via settings. */
1785 document.body.classList.add('my-messages-right');
1786 }
1787 const settingsButton = document.querySelector('#chat-button-settings');
1788 const optionsMenu = E1('#chat-config-options');
1789 const eToggleView = function(ev){
1790 ev.preventDefault();
1791 ev.stopPropagation();
1792 Chat.setCurrentView(Chat.e.currentView===Chat.e.viewConfig
1793 ? Chat.e.viewMessages : Chat.e.viewConfig);
1794 return false;
1795 };
1796 D.attr(settingsButton, 'role', 'button').addEventListener('click', eToggleView, false);
1797 Chat.e.viewConfig.querySelector('button.action-close').addEventListener('click', eToggleView, false);
1798
1799 /** Internal acrobatics to allow certain settings toggles to access
1800 related toggles. */
1801 const namedOptions = {
1802 activeUsers:{
@@ -1658,12 +1882,13 @@
1882 boolValue: 'edit-ctrl-send'
1883 },{
1884 label: "Compact mode",
1885 hint: [
1886 "Toggle between a space-saving or more spacious writing area. ",
1887 "When the input field has focus and is empty ",
1888 "then Shift-Enter may (depending on the current view) toggle this setting."
1889 ].join(''),
1890 boolValue: 'edit-compact-mode'
1891 },{
1892 label: "Use 'contenteditable' editing mode",
1893 boolValue: 'edit-widget-x',
1894 hint: [
@@ -1738,10 +1963,14 @@
1963 const v = ev.target.value;
1964 Chat.setNewMessageSound(v);
1965 F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+".");
1966 if(v) setTimeout(()=>Chat.playNewMessageSound(), 0);
1967 }
1968 },{
1969 label: "Notify only once when away",
1970 hint: "Notify only for the first message received after chat is hidden from view.",
1971 boolValue: 'beep-once'
1972 },{
1973 label: "Play notification for your own messages",
1974 hint: "When enabled, the audio notification will be played for all messages, "+
1975 "including your own. When disabled only messages from other users "+
1976 "will trigger a notification.",
@@ -1824,11 +2053,11 @@
2053 op.persistentSetting,
2054 function(setting){
2055 if(op.checkbox) op.checkbox.checked = !!setting.value;
2056 else if(op.select) op.select.value = setting.value;
2057 if(op.callback) op.callback(setting);
2058 }
2059 );
2060 if(op.checkbox){
2061 op.checkbox.addEventListener(
2062 'change', function(){
2063 Chat.settings.set(op.persistentSetting, op.checkbox.checked)
@@ -1900,11 +2129,11 @@
2129 s.value ? 'add' : 'remove'
2130 ]('compact');
2131 Chat.e.inputFields[Chat.e.inputFields.$currentIndex].focus();
2132 });
2133 Chat.settings.addListener('edit-ctrl-send',function(s){
2134 const label = (s.value ? "Ctrl-" : "")+"Enter submits message";
2135 Chat.e.inputFields.forEach((e)=>{
2136 const v = e.dataset.placeholder0 + " " +label;
2137 if(e.isContentEditable) e.dataset.placeholder = v;
2138 else D.attr(e,'placeholder',v);
2139 });
@@ -1922,20 +2151,20 @@
2151 Chat.settings.set(k,v)
2152 /* fires event listeners so that the Config area checkboxes
2153 get in sync */;
2154 });
2155 })();
2156
2157 (function(){/*set up message preview*/
2158 const btnPreview = Chat.e.btnPreview;
2159 Chat.setPreviewText = function(t){
2160 this.setCurrentView(this.e.viewPreview);
2161 this.e.previewContent.innerHTML = t;
2162 this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
2163 this.inputFocus();
2164 };
2165 Chat.e.viewPreview.querySelector('button.action-close').
2166 addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
2167 let previewPending = false;
2168 const elemsToEnable = [btnPreview, Chat.e.btnSubmit, Chat.e.inputFields];
2169 const submit = function(ev){
2170 ev.preventDefault();
@@ -1952,11 +2181,14 @@
2181 fd.append('filename','chat.md'
2182 /*filename needed for mimetype determination*/);
2183 fd.append('render_mode',F.page.previewModes.wiki);
2184 F.fetch('ajax/preview-text',{
2185 payload: fd,
2186 onload: function(html){
2187 Chat.setPreviewText(html);
2188 F.pikchr.addSrcView(Chat.e.viewPreview.querySelectorAll('svg.pikchr'));
2189 },
2190 onerror: function(e){
2191 F.fetch.onerror(e);
2192 Chat.setPreviewText("ERROR: "+(
2193 e.message || 'Unknown error fetching preview!'
2194 ));
@@ -1975,10 +2207,40 @@
2207 });
2208 return false;
2209 };
2210 btnPreview.addEventListener('click', submit, false);
2211 })()/*message preview setup*/;
2212
2213 (function(){/*Set up #chat-search and related bits */
2214 const btn = document.querySelector('#chat-button-search');
2215 D.attr(btn, 'role', 'button').addEventListener('click', function(ev){
2216 ev.preventDefault();
2217 ev.stopPropagation();
2218 const msg = Chat.inputValue();
2219 if( Chat.e.currentView===Chat.e.viewSearch ){
2220 if( msg ) Chat.submitSearch();
2221 else Chat.setCurrentView(Chat.e.viewMessages);
2222 }else{
2223 Chat.setCurrentView(Chat.e.viewSearch);
2224 if( msg ) Chat.submitSearch();
2225 }
2226 return false;
2227 }, false);
2228 Chat.e.viewSearch.querySelector('button.action-clear').addEventListener('click', function(ev){
2229 ev.preventDefault();
2230 ev.stopPropagation();
2231 Chat.clearSearch(true);
2232 Chat.setCurrentView(Chat.e.viewMessages);
2233 return false;
2234 }, false);
2235 Chat.e.viewSearch.querySelector('button.action-close').addEventListener('click', function(ev){
2236 ev.preventDefault();
2237 ev.stopPropagation();
2238 Chat.setCurrentView(Chat.e.viewMessages);
2239 return false;
2240 }, false);
2241 })()/*search view setup*/;
2242
2243 /** Callback for poll() to inject new content into the page. jx ==
2244 the response from /chat-poll. If atEnd is true, the message is
2245 appended to the end of the chat list (for loading older
2246 messages), else the beginning (the default). */
@@ -2107,10 +2369,82 @@
2369 btn.addEventListener('click',()=>loadOldMessages(-1));
2370 D.append(Chat.e.viewMessages, toolbar);
2371 toolbar.disabled = true /*will be enabled when msg load finishes */;
2372 })()/*end history loading widget setup*/;
2373
2374 /**
2375 Clears the search result view. If addInstructions is true it adds
2376 text to that view instructing the user to enter their query into
2377 the message-entry widget (noting that that widget has text
2378 implying that it's only for submitting a message, which isn't
2379 exactly true when the search view is active).
2380
2381 Returns the DOM element which wraps all of the chat search
2382 result elements.
2383 */
2384 Chat.clearSearch = function(addInstructions=false){
2385 const e = D.clearElement( this.e.searchContent );
2386 if(addInstructions){
2387 D.append(e, "Enter search terms in the message field. "+
2388 "Use #NNNNN to search for the message with ID NNNNN.");
2389 }
2390 return e;
2391 };
2392 Chat.clearSearch(true);
2393 /**
2394 Submits a history search using the main input field's current
2395 text. It is assumed that Chat.e.viewSearch===Chat.e.currentView.
2396 */
2397 Chat.submitSearch = function(){
2398 const term = this.inputValue(true);
2399 const eMsgTgt = this.clearSearch(true);
2400 if( !term ) return;
2401 D.append( eMsgTgt, "Searching for ",term," ...");
2402 const fd = new FormData();
2403 fd.set('q', term);
2404 F.fetch(
2405 "chat-query", {
2406 payload: fd,
2407 responseType: 'json',
2408 onerror:function(err){
2409 Chat.setCurrentView(Chat.e.viewMessages);
2410 Chat.reportErrorAsMessage(err);
2411 },
2412 onload:function(jx){
2413 let previd = 0;
2414 D.clearElement(eMsgTgt);
2415 jx.msgs.forEach((m)=>{
2416 m.isSearchResult = true;
2417 const mw = new Chat.MessageWidget(m);
2418 const spacer = new Chat.SearchCtxLoader({
2419 first: jx.first,
2420 last: jx.last,
2421 previd: previd,
2422 nextid: m.msgid
2423 });
2424 if( spacer.e ) D.append( eMsgTgt, spacer.e.body );
2425 D.append( eMsgTgt, mw.e.body );
2426 previd = m.msgid;
2427 });
2428 if( jx.msgs.length ){
2429 const spacer = new Chat.SearchCtxLoader({
2430 first: jx.first,
2431 last: jx.last,
2432 previd: previd,
2433 nextid: 0
2434 });
2435 if( spacer.e ) D.append( eMsgTgt, spacer.e.body );
2436 }else{
2437 D.append( D.clearElement(eMsgTgt),
2438 'No search results found for: ',
2439 term );
2440 }
2441 }
2442 }
2443 );
2444 }/*Chat.submitSearch()*/;
2445
2446 const afterFetch = function f(){
2447 if(true===f.isFirstCall){
2448 f.isFirstCall = false;
2449 Chat.ajaxEnd();
2450 Chat.e.viewMessages.classList.remove('loading');
@@ -2126,10 +2460,25 @@
2460 delete Chat.intervalTimer;
2461 }
2462 poll.running = false;
2463 };
2464 afterFetch.isFirstCall = true;
2465 /**
2466 FIXME: when polling fails because the remote server is
2467 reachable but it's not accepting HTTP requests, we should back
2468 off on polling for a while. e.g. if the remote web server process
2469 is killed, the poll fails quickly and immediately retries,
2470 hammering the remote server until the httpd is back up. That
2471 happens often during development of this application.
2472
2473 XHR does not offer a direct way of distinguishing between
2474 HTTP/connection errors, but we can hypothetically use the
2475 xhrRequest.status value to do so, with status==0 being a
2476 connection error. We do not currently have a clean way of passing
2477 that info back to the fossil.fetch() client, so we'll need to
2478 hammer on that API a bit to get this working.
2479 */
2480 const poll = async function f(){
2481 if(f.running) return;
2482 f.running = true;
2483 Chat._isBatchLoading = f.isFirstCall;
2484 if(true===f.isFirstCall){
@@ -2168,17 +2517,11 @@
2517 Chat._gotServerError = poll.running = false;
2518 if( window.fossil.config.chat.fromcli ){
2519 Chat.chatOnlyMode(true);
2520 }
2521 Chat.intervalTimer = setInterval(poll, 1000);
 
 
 
 
 
 
2522 delete ForceResizeKludge.$disabled;
2523 ForceResizeKludge();
2524 Chat.animate.$disabled = false;
2525 setTimeout( ()=>Chat.inputFocus(), 0 );
2526 F.page.chat = Chat/* enables testing the APIs via the dev tools */;
2527 });
2528
+18 -9
--- src/graph.c
+++ src/graph.c
@@ -24,22 +24,28 @@
2424
/* Notes:
2525
**
2626
** The graph is laid out in 1 or more "rails". A "rail" is a vertical
2727
** band in the graph in which one can place nodes or arrows connecting
2828
** nodes. There can be between 1 and GR_MAX_RAIL rails. If the graph
29
-** is to complex to be displayed in GR_MAX_RAIL rails, it is omitted.
29
+** is too complex to be displayed in GR_MAX_RAIL rails, it is omitted.
3030
**
3131
** A "riser" is the thick line that comes out of the top of a node and
3232
** goes up to the next node on the branch, or to the top of the screen.
3333
** A "descender" is a thick line that comes out of the bottom of a node
3434
** and proceeds down to the bottom of the page.
35
+**
36
+** A "merge riser" is a thin line going up out of a node to indicate a
37
+** merge or cherrypick. (Cherrypicks are drawn with thin dashed lines.
38
+** Merges are drawn with thin solid lines.) A "merge riser" might go
39
+** stright up out of the top of a leaf node, but for non-leaves, they
40
+** go horizontally to their assigned rail first, then up.
3541
**
3642
** Invoke graph_init() to create a new GraphContext object. Then
3743
** call graph_add_row() to add nodes, one by one, to the graph.
3844
** Nodes must be added in display order, from top to bottom.
3945
** Then invoke graph_render() to run the layout algorithm. The
40
-** layout algorithm computes which rails all of the nodes sit on, and
46
+** layout algorithm computes which rail each nodes sit on, and
4147
** the rails used for merge arrows.
4248
*/
4349
4450
#if INTERFACE
4551
@@ -930,11 +936,11 @@
930936
/* Find the "root" of the branch. The root is a different branch
931937
** from which the pRow branch emerges. There might not be a root
932938
** if the pRow branch started off the bottom of the screen.
933939
*/
934940
for(pRoot=pBottom->pNext; pRoot; pRoot=pRoot->pNext){
935
- if( pRoot->aiRiser[iFrom]>=0 ) break;
941
+ if( pRoot->aiRiser[iFrom]==pBottom->idx ) break;
936942
}
937943
if( pRoot && pRoot->iRail==iTo ){
938944
/* The parent branch from which this branch emerges is on the
939945
** same rail as pRow. Do not shift as that would stack a child
940946
** branch directly above its parent. */
@@ -973,11 +979,14 @@
973979
if( nTimewarp==0 ){
974980
/* Priority bits:
975981
**
976982
** 0x04 The preferred branch
977983
**
978
- ** 0x02 A merge rail - a rail that contains merge lines
984
+ ** 0x02 A merge rail - a rail that contains merge lines into
985
+ ** the preferred branch. Only applies if a preferred branch
986
+ ** is defined. This improves the display of r=BRANCH
987
+ ** options to /timeline.
979988
**
980989
** 0x01 A rail that merges with the preferred branch
981990
*/
982991
u8 aPriority[GR_MAX_RAIL];
983992
memset(aPriority, 0, p->mxRail+1);
@@ -989,10 +998,15 @@
989998
for(i=0; i<=p->mxRail; i++){
990999
if( pRow->mergeIn[i] ) aPriority[i] |= 1;
9911000
}
9921001
if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
9931002
}
1003
+ }
1004
+ for(i=0; i<=p->mxRail; i++){
1005
+ if( p->mergeRail & BIT(i) ){
1006
+ aPriority[i] |= 2;
1007
+ }
9941008
}
9951009
}else{
9961010
j = 1;
9971011
aPriority[0] = 4;
9981012
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
@@ -1002,15 +1016,10 @@
10021016
}
10031017
if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
10041018
}
10051019
}
10061020
}
1007
- for(i=0; i<=p->mxRail; i++){
1008
- if( p->mergeRail & BIT(i) ){
1009
- aPriority[i] |= 2;
1010
- }
1011
- }
10121021
10131022
#if 0
10141023
fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
10151024
fprintf(stderr,"Priority:");
10161025
for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
10171026
--- src/graph.c
+++ src/graph.c
@@ -24,22 +24,28 @@
24 /* Notes:
25 **
26 ** The graph is laid out in 1 or more "rails". A "rail" is a vertical
27 ** band in the graph in which one can place nodes or arrows connecting
28 ** nodes. There can be between 1 and GR_MAX_RAIL rails. If the graph
29 ** is to complex to be displayed in GR_MAX_RAIL rails, it is omitted.
30 **
31 ** A "riser" is the thick line that comes out of the top of a node and
32 ** goes up to the next node on the branch, or to the top of the screen.
33 ** A "descender" is a thick line that comes out of the bottom of a node
34 ** and proceeds down to the bottom of the page.
 
 
 
 
 
 
35 **
36 ** Invoke graph_init() to create a new GraphContext object. Then
37 ** call graph_add_row() to add nodes, one by one, to the graph.
38 ** Nodes must be added in display order, from top to bottom.
39 ** Then invoke graph_render() to run the layout algorithm. The
40 ** layout algorithm computes which rails all of the nodes sit on, and
41 ** the rails used for merge arrows.
42 */
43
44 #if INTERFACE
45
@@ -930,11 +936,11 @@
930 /* Find the "root" of the branch. The root is a different branch
931 ** from which the pRow branch emerges. There might not be a root
932 ** if the pRow branch started off the bottom of the screen.
933 */
934 for(pRoot=pBottom->pNext; pRoot; pRoot=pRoot->pNext){
935 if( pRoot->aiRiser[iFrom]>=0 ) break;
936 }
937 if( pRoot && pRoot->iRail==iTo ){
938 /* The parent branch from which this branch emerges is on the
939 ** same rail as pRow. Do not shift as that would stack a child
940 ** branch directly above its parent. */
@@ -973,11 +979,14 @@
973 if( nTimewarp==0 ){
974 /* Priority bits:
975 **
976 ** 0x04 The preferred branch
977 **
978 ** 0x02 A merge rail - a rail that contains merge lines
 
 
 
979 **
980 ** 0x01 A rail that merges with the preferred branch
981 */
982 u8 aPriority[GR_MAX_RAIL];
983 memset(aPriority, 0, p->mxRail+1);
@@ -989,10 +998,15 @@
989 for(i=0; i<=p->mxRail; i++){
990 if( pRow->mergeIn[i] ) aPriority[i] |= 1;
991 }
992 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
993 }
 
 
 
 
 
994 }
995 }else{
996 j = 1;
997 aPriority[0] = 4;
998 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
@@ -1002,15 +1016,10 @@
1002 }
1003 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
1004 }
1005 }
1006 }
1007 for(i=0; i<=p->mxRail; i++){
1008 if( p->mergeRail & BIT(i) ){
1009 aPriority[i] |= 2;
1010 }
1011 }
1012
1013 #if 0
1014 fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
1015 fprintf(stderr,"Priority:");
1016 for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
1017
--- src/graph.c
+++ src/graph.c
@@ -24,22 +24,28 @@
24 /* Notes:
25 **
26 ** The graph is laid out in 1 or more "rails". A "rail" is a vertical
27 ** band in the graph in which one can place nodes or arrows connecting
28 ** nodes. There can be between 1 and GR_MAX_RAIL rails. If the graph
29 ** is too complex to be displayed in GR_MAX_RAIL rails, it is omitted.
30 **
31 ** A "riser" is the thick line that comes out of the top of a node and
32 ** goes up to the next node on the branch, or to the top of the screen.
33 ** A "descender" is a thick line that comes out of the bottom of a node
34 ** and proceeds down to the bottom of the page.
35 **
36 ** A "merge riser" is a thin line going up out of a node to indicate a
37 ** merge or cherrypick. (Cherrypicks are drawn with thin dashed lines.
38 ** Merges are drawn with thin solid lines.) A "merge riser" might go
39 ** stright up out of the top of a leaf node, but for non-leaves, they
40 ** go horizontally to their assigned rail first, then up.
41 **
42 ** Invoke graph_init() to create a new GraphContext object. Then
43 ** call graph_add_row() to add nodes, one by one, to the graph.
44 ** Nodes must be added in display order, from top to bottom.
45 ** Then invoke graph_render() to run the layout algorithm. The
46 ** layout algorithm computes which rail each nodes sit on, and
47 ** the rails used for merge arrows.
48 */
49
50 #if INTERFACE
51
@@ -930,11 +936,11 @@
936 /* Find the "root" of the branch. The root is a different branch
937 ** from which the pRow branch emerges. There might not be a root
938 ** if the pRow branch started off the bottom of the screen.
939 */
940 for(pRoot=pBottom->pNext; pRoot; pRoot=pRoot->pNext){
941 if( pRoot->aiRiser[iFrom]==pBottom->idx ) break;
942 }
943 if( pRoot && pRoot->iRail==iTo ){
944 /* The parent branch from which this branch emerges is on the
945 ** same rail as pRow. Do not shift as that would stack a child
946 ** branch directly above its parent. */
@@ -973,11 +979,14 @@
979 if( nTimewarp==0 ){
980 /* Priority bits:
981 **
982 ** 0x04 The preferred branch
983 **
984 ** 0x02 A merge rail - a rail that contains merge lines into
985 ** the preferred branch. Only applies if a preferred branch
986 ** is defined. This improves the display of r=BRANCH
987 ** options to /timeline.
988 **
989 ** 0x01 A rail that merges with the preferred branch
990 */
991 u8 aPriority[GR_MAX_RAIL];
992 memset(aPriority, 0, p->mxRail+1);
@@ -989,10 +998,15 @@
998 for(i=0; i<=p->mxRail; i++){
999 if( pRow->mergeIn[i] ) aPriority[i] |= 1;
1000 }
1001 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
1002 }
1003 }
1004 for(i=0; i<=p->mxRail; i++){
1005 if( p->mergeRail & BIT(i) ){
1006 aPriority[i] |= 2;
1007 }
1008 }
1009 }else{
1010 j = 1;
1011 aPriority[0] = 4;
1012 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
@@ -1002,15 +1016,10 @@
1016 }
1017 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
1018 }
1019 }
1020 }
 
 
 
 
 
1021
1022 #if 0
1023 fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
1024 fprintf(stderr,"Priority:");
1025 for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
1026
+62 -14
--- src/http.c
+++ src/http.c
@@ -47,10 +47,15 @@
4747
#define MAX_HTTP_AUTH 2
4848
4949
/* Keep track of HTTP Basic Authorization failures */
5050
static int fSeenHttpAuth = 0;
5151
52
+/* The N value for most recent http-request-N.txt and http-reply-N.txt
53
+** trace files.
54
+*/
55
+static int traceCnt = 0;
56
+
5257
/*
5358
** Construct the "login" card with the client credentials.
5459
**
5560
** login LOGIN NONCE SIGNATURE
5661
**
@@ -389,10 +394,29 @@
389394
*/
390395
void ssh_add_path_argument(Blob *pCmd){
391396
blob_append_escaped_arg(pCmd,
392397
"PATH=$HOME/bin:/usr/local/bin:/opt/homebrew/bin:$PATH", 1);
393398
}
399
+
400
+/*
401
+** Return the complete text of the last HTTP reply as saved in the
402
+** http-reply-N.txt file. This only works if run using --httptrace.
403
+** Without the --httptrace option, this routine returns a NULL pointer.
404
+** It still might return a NULL pointer if for some reason it cannot
405
+** find and open the last http-reply-N.txt file.
406
+*/
407
+char *http_last_trace_reply(void){
408
+ Blob x;
409
+ int n;
410
+ char *zFilename;
411
+ if( g.fHttpTrace==0 ) return 0;
412
+ zFilename = mprintf("http-reply-%d.txt", traceCnt);
413
+ n = blob_read_from_file(&x, zFilename, ExtFILE);
414
+ fossil_free(zFilename);
415
+ if( n<=0 ) return 0;
416
+ return blob_str(&x);
417
+}
394418
395419
/*
396420
** Sign the content in pSend, compress it, and send it to the server
397421
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
398422
** in pRecv. pRecv is assumed to be uninitialized when
@@ -412,11 +436,10 @@
412436
Blob login; /* The login card */
413437
Blob payload; /* The complete payload including login card */
414438
Blob hdr; /* The HTTP request header */
415439
int closeConnection; /* True to close the connection when done */
416440
int iLength; /* Expected length of the reply payload */
417
- int iRecvLen; /* Received length of the reply payload */
418441
int rc = 0; /* Result code */
419442
int iHttpVersion; /* Which version of HTTP protocol server uses */
420443
char *zLine; /* A single line of the reply header */
421444
int i; /* Loop counter */
422445
int isError = 0; /* True if the reply is an error message */
@@ -465,11 +488,10 @@
465488
** server-side like this:
466489
**
467490
** ./fossil test-http <http-request-1.txt
468491
*/
469492
if( g.fHttpTrace ){
470
- static int traceCnt = 0;
471493
char *zOutFile;
472494
FILE *out;
473495
traceCnt++;
474496
zOutFile = mprintf("http-request-%d.txt", traceCnt);
475497
out = fopen(zOutFile, "wb");
@@ -502,10 +524,11 @@
502524
/*
503525
** Read and interpret the server reply
504526
*/
505527
closeConnection = 1;
506528
iLength = -1;
529
+ iHttpVersion = -1;
507530
while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
508531
if( mHttpFlags & HTTP_VERBOSE ){
509532
fossil_print("Read: [%s]\n", zLine);
510533
}
511534
if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
@@ -540,21 +563,19 @@
540563
for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
541564
while( zLine[ii]==' ' ) ii++;
542565
fossil_warning("server says: %s", &zLine[ii]);
543566
goto write_err;
544567
}
568
+ if( iHttpVersion<0 ) iHttpVersion = 1;
545569
closeConnection = 0;
546570
}else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
547571
for(i=15; fossil_isspace(zLine[i]); i++){}
548572
iLength = atoi(&zLine[i]);
549573
}else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
550
- char c;
551
- for(i=11; fossil_isspace(zLine[i]); i++){}
552
- c = zLine[i];
553
- if( c=='c' || c=='C' ){
574
+ if( sqlite3_strlike("%close%", &zLine[11], 0)==0 ){
554575
closeConnection = 1;
555
- }else if( c=='k' || c=='K' ){
576
+ }else if( sqlite3_strlike("%keep-alive%", &zLine[11], 0)==0 ){
556577
closeConnection = 0;
557578
}
558579
}else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
559580
fossil_strnicmp(zLine, "location:", 9)==0 ){
560581
int i, j;
@@ -613,11 +634,11 @@
613634
isError = 1;
614635
}
615636
}
616637
}
617638
}
618
- if( iLength<0 ){
639
+ if( iHttpVersion<0 ){
619640
/* We got nothing back from the server. If using the ssh: protocol,
620641
** this might mean we need to add or remove the PATH=... argument
621642
** to the SSH command being sent. If that is the case, retry the
622643
** request after adding or removing the PATH= argument.
623644
*/
@@ -659,17 +680,44 @@
659680
660681
/*
661682
** Extract the reply payload that follows the header
662683
*/
663684
blob_zero(pReply);
664
- blob_resize(pReply, iLength);
665
- iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
666
- if( iRecvLen != iLength ){
667
- fossil_warning("response truncated: got %d bytes of %d", iRecvLen, iLength);
668
- goto write_err;
685
+ if( iLength==0 ){
686
+ /* No content to read */
687
+ }else if( iLength>0 ){
688
+ /* Read content of a known length */
689
+ int iRecvLen; /* Received length of the reply payload */
690
+ blob_resize(pReply, iLength);
691
+ iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
692
+ if( mHttpFlags & HTTP_VERBOSE ){
693
+ fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
694
+ }
695
+ if( iRecvLen != iLength ){
696
+ fossil_warning("response truncated: got %d bytes of %d",
697
+ iRecvLen, iLength);
698
+ goto write_err;
699
+ }
700
+ }else if( closeConnection ){
701
+ /* Read content until end-of-file */
702
+ int iRecvLen; /* Received length of the reply payload */
703
+ unsigned int nReq = 1000;
704
+ unsigned int nPrior = 0;
705
+ do{
706
+ nReq *= 2;
707
+ blob_resize(pReply, nPrior+nReq);
708
+ iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
709
+ nPrior += iRecvLen;
710
+ pReply->nUsed = nPrior;
711
+ }while( iRecvLen==nReq && nReq<0x20000000 );
712
+ if( mHttpFlags & HTTP_VERBOSE ){
713
+ fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
714
+ }
715
+ }else{
716
+ assert( iLength<0 && !closeConnection );
717
+ fossil_warning("\"content-length\" missing from %d keep-alive reply", rc);
669718
}
670
- blob_resize(pReply, iLength);
671719
if( isError ){
672720
char *z;
673721
int i, j;
674722
z = blob_str(pReply);
675723
for(i=j=0; z[i]; i++, j++){
676724
--- src/http.c
+++ src/http.c
@@ -47,10 +47,15 @@
47 #define MAX_HTTP_AUTH 2
48
49 /* Keep track of HTTP Basic Authorization failures */
50 static int fSeenHttpAuth = 0;
51
 
 
 
 
 
52 /*
53 ** Construct the "login" card with the client credentials.
54 **
55 ** login LOGIN NONCE SIGNATURE
56 **
@@ -389,10 +394,29 @@
389 */
390 void ssh_add_path_argument(Blob *pCmd){
391 blob_append_escaped_arg(pCmd,
392 "PATH=$HOME/bin:/usr/local/bin:/opt/homebrew/bin:$PATH", 1);
393 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
395 /*
396 ** Sign the content in pSend, compress it, and send it to the server
397 ** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
398 ** in pRecv. pRecv is assumed to be uninitialized when
@@ -412,11 +436,10 @@
412 Blob login; /* The login card */
413 Blob payload; /* The complete payload including login card */
414 Blob hdr; /* The HTTP request header */
415 int closeConnection; /* True to close the connection when done */
416 int iLength; /* Expected length of the reply payload */
417 int iRecvLen; /* Received length of the reply payload */
418 int rc = 0; /* Result code */
419 int iHttpVersion; /* Which version of HTTP protocol server uses */
420 char *zLine; /* A single line of the reply header */
421 int i; /* Loop counter */
422 int isError = 0; /* True if the reply is an error message */
@@ -465,11 +488,10 @@
465 ** server-side like this:
466 **
467 ** ./fossil test-http <http-request-1.txt
468 */
469 if( g.fHttpTrace ){
470 static int traceCnt = 0;
471 char *zOutFile;
472 FILE *out;
473 traceCnt++;
474 zOutFile = mprintf("http-request-%d.txt", traceCnt);
475 out = fopen(zOutFile, "wb");
@@ -502,10 +524,11 @@
502 /*
503 ** Read and interpret the server reply
504 */
505 closeConnection = 1;
506 iLength = -1;
 
507 while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
508 if( mHttpFlags & HTTP_VERBOSE ){
509 fossil_print("Read: [%s]\n", zLine);
510 }
511 if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
@@ -540,21 +563,19 @@
540 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
541 while( zLine[ii]==' ' ) ii++;
542 fossil_warning("server says: %s", &zLine[ii]);
543 goto write_err;
544 }
 
545 closeConnection = 0;
546 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
547 for(i=15; fossil_isspace(zLine[i]); i++){}
548 iLength = atoi(&zLine[i]);
549 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
550 char c;
551 for(i=11; fossil_isspace(zLine[i]); i++){}
552 c = zLine[i];
553 if( c=='c' || c=='C' ){
554 closeConnection = 1;
555 }else if( c=='k' || c=='K' ){
556 closeConnection = 0;
557 }
558 }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
559 fossil_strnicmp(zLine, "location:", 9)==0 ){
560 int i, j;
@@ -613,11 +634,11 @@
613 isError = 1;
614 }
615 }
616 }
617 }
618 if( iLength<0 ){
619 /* We got nothing back from the server. If using the ssh: protocol,
620 ** this might mean we need to add or remove the PATH=... argument
621 ** to the SSH command being sent. If that is the case, retry the
622 ** request after adding or removing the PATH= argument.
623 */
@@ -659,17 +680,44 @@
659
660 /*
661 ** Extract the reply payload that follows the header
662 */
663 blob_zero(pReply);
664 blob_resize(pReply, iLength);
665 iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
666 if( iRecvLen != iLength ){
667 fossil_warning("response truncated: got %d bytes of %d", iRecvLen, iLength);
668 goto write_err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669 }
670 blob_resize(pReply, iLength);
671 if( isError ){
672 char *z;
673 int i, j;
674 z = blob_str(pReply);
675 for(i=j=0; z[i]; i++, j++){
676
--- src/http.c
+++ src/http.c
@@ -47,10 +47,15 @@
47 #define MAX_HTTP_AUTH 2
48
49 /* Keep track of HTTP Basic Authorization failures */
50 static int fSeenHttpAuth = 0;
51
52 /* The N value for most recent http-request-N.txt and http-reply-N.txt
53 ** trace files.
54 */
55 static int traceCnt = 0;
56
57 /*
58 ** Construct the "login" card with the client credentials.
59 **
60 ** login LOGIN NONCE SIGNATURE
61 **
@@ -389,10 +394,29 @@
394 */
395 void ssh_add_path_argument(Blob *pCmd){
396 blob_append_escaped_arg(pCmd,
397 "PATH=$HOME/bin:/usr/local/bin:/opt/homebrew/bin:$PATH", 1);
398 }
399
400 /*
401 ** Return the complete text of the last HTTP reply as saved in the
402 ** http-reply-N.txt file. This only works if run using --httptrace.
403 ** Without the --httptrace option, this routine returns a NULL pointer.
404 ** It still might return a NULL pointer if for some reason it cannot
405 ** find and open the last http-reply-N.txt file.
406 */
407 char *http_last_trace_reply(void){
408 Blob x;
409 int n;
410 char *zFilename;
411 if( g.fHttpTrace==0 ) return 0;
412 zFilename = mprintf("http-reply-%d.txt", traceCnt);
413 n = blob_read_from_file(&x, zFilename, ExtFILE);
414 fossil_free(zFilename);
415 if( n<=0 ) return 0;
416 return blob_str(&x);
417 }
418
419 /*
420 ** Sign the content in pSend, compress it, and send it to the server
421 ** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
422 ** in pRecv. pRecv is assumed to be uninitialized when
@@ -412,11 +436,10 @@
436 Blob login; /* The login card */
437 Blob payload; /* The complete payload including login card */
438 Blob hdr; /* The HTTP request header */
439 int closeConnection; /* True to close the connection when done */
440 int iLength; /* Expected length of the reply payload */
 
441 int rc = 0; /* Result code */
442 int iHttpVersion; /* Which version of HTTP protocol server uses */
443 char *zLine; /* A single line of the reply header */
444 int i; /* Loop counter */
445 int isError = 0; /* True if the reply is an error message */
@@ -465,11 +488,10 @@
488 ** server-side like this:
489 **
490 ** ./fossil test-http <http-request-1.txt
491 */
492 if( g.fHttpTrace ){
 
493 char *zOutFile;
494 FILE *out;
495 traceCnt++;
496 zOutFile = mprintf("http-request-%d.txt", traceCnt);
497 out = fopen(zOutFile, "wb");
@@ -502,10 +524,11 @@
524 /*
525 ** Read and interpret the server reply
526 */
527 closeConnection = 1;
528 iLength = -1;
529 iHttpVersion = -1;
530 while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
531 if( mHttpFlags & HTTP_VERBOSE ){
532 fossil_print("Read: [%s]\n", zLine);
533 }
534 if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
@@ -540,21 +563,19 @@
563 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
564 while( zLine[ii]==' ' ) ii++;
565 fossil_warning("server says: %s", &zLine[ii]);
566 goto write_err;
567 }
568 if( iHttpVersion<0 ) iHttpVersion = 1;
569 closeConnection = 0;
570 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
571 for(i=15; fossil_isspace(zLine[i]); i++){}
572 iLength = atoi(&zLine[i]);
573 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
574 if( sqlite3_strlike("%close%", &zLine[11], 0)==0 ){
 
 
 
575 closeConnection = 1;
576 }else if( sqlite3_strlike("%keep-alive%", &zLine[11], 0)==0 ){
577 closeConnection = 0;
578 }
579 }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
580 fossil_strnicmp(zLine, "location:", 9)==0 ){
581 int i, j;
@@ -613,11 +634,11 @@
634 isError = 1;
635 }
636 }
637 }
638 }
639 if( iHttpVersion<0 ){
640 /* We got nothing back from the server. If using the ssh: protocol,
641 ** this might mean we need to add or remove the PATH=... argument
642 ** to the SSH command being sent. If that is the case, retry the
643 ** request after adding or removing the PATH= argument.
644 */
@@ -659,17 +680,44 @@
680
681 /*
682 ** Extract the reply payload that follows the header
683 */
684 blob_zero(pReply);
685 if( iLength==0 ){
686 /* No content to read */
687 }else if( iLength>0 ){
688 /* Read content of a known length */
689 int iRecvLen; /* Received length of the reply payload */
690 blob_resize(pReply, iLength);
691 iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
692 if( mHttpFlags & HTTP_VERBOSE ){
693 fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
694 }
695 if( iRecvLen != iLength ){
696 fossil_warning("response truncated: got %d bytes of %d",
697 iRecvLen, iLength);
698 goto write_err;
699 }
700 }else if( closeConnection ){
701 /* Read content until end-of-file */
702 int iRecvLen; /* Received length of the reply payload */
703 unsigned int nReq = 1000;
704 unsigned int nPrior = 0;
705 do{
706 nReq *= 2;
707 blob_resize(pReply, nPrior+nReq);
708 iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
709 nPrior += iRecvLen;
710 pReply->nUsed = nPrior;
711 }while( iRecvLen==nReq && nReq<0x20000000 );
712 if( mHttpFlags & HTTP_VERBOSE ){
713 fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
714 }
715 }else{
716 assert( iLength<0 && !closeConnection );
717 fossil_warning("\"content-length\" missing from %d keep-alive reply", rc);
718 }
 
719 if( isError ){
720 char *z;
721 int i, j;
722 z = blob_str(pReply);
723 for(i=j=0; z[i]; i++, j++){
724
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -307,10 +307,27 @@
307307
if( zFile==0 ){
308308
/* fossil_fatal("Cannot find a trust store"); */
309309
}else if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
310310
fossil_fatal("Cannot load CA root certificates from %s", zFile);
311311
}
312
+
313
+/* Enable OpenSSL to use the Windows system ROOT certificate store to search for
314
+** certificates missing in the file and directory trust stores already loaded by
315
+** `SSL_CTX_load_verify_locations()'.
316
+** This feature was introduced with OpenSSL 3.2.0, and may be enabled by default
317
+** for future versions of OpenSSL, and explicit initialization may be redundant.
318
+** NOTE TO HACKERS TWEAKING THEIR OPENSSL CONFIGURATION:
319
+** The following OpenSSL configuration options must not be used for this feature
320
+** to be available: `no-autoalginit', `no-winstore'. The Fossil makefiles do not
321
+** currently set these options when building OpenSSL for Windows. */
322
+#if defined(_WIN32)
323
+#if OPENSSL_VERSION_NUMBER >= 0x030200000
324
+ if( SSL_CTX_load_verify_store(sslCtx, "org.openssl.winstore:")==0 ){
325
+ fossil_print("NOTICE: Failed to load the Windows root certificates.\n");
326
+ }
327
+#endif /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
328
+#endif /* _WIN32 */
312329
313330
/* Load client SSL identity, preferring the filename specified on the
314331
** command line */
315332
if( g.zSSLIdentity!=0 ){
316333
identityFile = g.zSSLIdentity;
@@ -1030,10 +1047,26 @@
10301047
" the identity of servers for \"https:\" URLs. These values\n"
10311048
" come into play when Fossil is used as a TLS client. These\n"
10321049
" values are built into your OpenSSL library.\n\n"
10331050
);
10341051
}
1052
+
1053
+#if defined(_WIN32)
1054
+#if OPENSSL_VERSION_NUMBER >= 0x030200000
1055
+ fossil_print(" OpenSSL-winstore: Yes\n");
1056
+#else /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
1057
+ fossil_print(" OpenSSL-winstore: No\n");
1058
+#endif /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
1059
+ if( verbose ){
1060
+ fossil_print("\n"
1061
+ " OpenSSL 3.2.0, or newer, use the root certificates managed by\n"
1062
+ " the Windows operating system. The installed root certificates\n"
1063
+ " are listed by the command:\n\n"
1064
+ " certutil -store \"ROOT\"\n\n"
1065
+ );
1066
+ }
1067
+#endif /* _WIN32 */
10351068
10361069
if( zUsed==0 ) zUsed = "";
10371070
fossil_print(" Trust store used: %s\n", zUsed);
10381071
if( verbose ){
10391072
fossil_print("\n"
10401073
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -307,10 +307,27 @@
307 if( zFile==0 ){
308 /* fossil_fatal("Cannot find a trust store"); */
309 }else if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
310 fossil_fatal("Cannot load CA root certificates from %s", zFile);
311 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
313 /* Load client SSL identity, preferring the filename specified on the
314 ** command line */
315 if( g.zSSLIdentity!=0 ){
316 identityFile = g.zSSLIdentity;
@@ -1030,10 +1047,26 @@
1030 " the identity of servers for \"https:\" URLs. These values\n"
1031 " come into play when Fossil is used as a TLS client. These\n"
1032 " values are built into your OpenSSL library.\n\n"
1033 );
1034 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1035
1036 if( zUsed==0 ) zUsed = "";
1037 fossil_print(" Trust store used: %s\n", zUsed);
1038 if( verbose ){
1039 fossil_print("\n"
1040
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -307,10 +307,27 @@
307 if( zFile==0 ){
308 /* fossil_fatal("Cannot find a trust store"); */
309 }else if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
310 fossil_fatal("Cannot load CA root certificates from %s", zFile);
311 }
312
313 /* Enable OpenSSL to use the Windows system ROOT certificate store to search for
314 ** certificates missing in the file and directory trust stores already loaded by
315 ** `SSL_CTX_load_verify_locations()'.
316 ** This feature was introduced with OpenSSL 3.2.0, and may be enabled by default
317 ** for future versions of OpenSSL, and explicit initialization may be redundant.
318 ** NOTE TO HACKERS TWEAKING THEIR OPENSSL CONFIGURATION:
319 ** The following OpenSSL configuration options must not be used for this feature
320 ** to be available: `no-autoalginit', `no-winstore'. The Fossil makefiles do not
321 ** currently set these options when building OpenSSL for Windows. */
322 #if defined(_WIN32)
323 #if OPENSSL_VERSION_NUMBER >= 0x030200000
324 if( SSL_CTX_load_verify_store(sslCtx, "org.openssl.winstore:")==0 ){
325 fossil_print("NOTICE: Failed to load the Windows root certificates.\n");
326 }
327 #endif /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
328 #endif /* _WIN32 */
329
330 /* Load client SSL identity, preferring the filename specified on the
331 ** command line */
332 if( g.zSSLIdentity!=0 ){
333 identityFile = g.zSSLIdentity;
@@ -1030,10 +1047,26 @@
1047 " the identity of servers for \"https:\" URLs. These values\n"
1048 " come into play when Fossil is used as a TLS client. These\n"
1049 " values are built into your OpenSSL library.\n\n"
1050 );
1051 }
1052
1053 #if defined(_WIN32)
1054 #if OPENSSL_VERSION_NUMBER >= 0x030200000
1055 fossil_print(" OpenSSL-winstore: Yes\n");
1056 #else /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
1057 fossil_print(" OpenSSL-winstore: No\n");
1058 #endif /* OPENSSL_VERSION_NUMBER >= 0x030200000 */
1059 if( verbose ){
1060 fossil_print("\n"
1061 " OpenSSL 3.2.0, or newer, use the root certificates managed by\n"
1062 " the Windows operating system. The installed root certificates\n"
1063 " are listed by the command:\n\n"
1064 " certutil -store \"ROOT\"\n\n"
1065 );
1066 }
1067 #endif /* _WIN32 */
1068
1069 if( zUsed==0 ) zUsed = "";
1070 fossil_print(" Trust store used: %s\n", zUsed);
1071 if( verbose ){
1072 fossil_print("\n"
1073
+13 -1
--- src/import.c
+++ src/import.c
@@ -1248,11 +1248,19 @@
12481248
zOut = blob_buffer(pOut)+lenOld;
12491249
while( zDiff<zInst+lenInst ){
12501250
u64 lenCpy = (*zDiff)&0x3f;
12511251
const char *zCpy;
12521252
switch( (*zDiff)&0xC0 ){
1253
- case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
1253
+ case 0x00:
1254
+ if( 0==blob_size(pSrc) ){
1255
+ /* https://fossil-scm.org/forum/forumpost/15d4b242bda2a108 */
1256
+ fossil_fatal("Don't know how to handle NULL input. "
1257
+ "Tip: do not use the --incremental flag "
1258
+ "in the svn dump command.");
1259
+ }
1260
+ zCpy = blob_buffer(pSrc)+offSrc;
1261
+ break;
12541262
case 0x40: zCpy = blob_buffer(pOut); break;
12551263
case 0x80: zCpy = zData; break;
12561264
default: fossil_fatal("Invalid svndiff0 instruction");
12571265
}
12581266
zDiff++;
@@ -1576,10 +1584,12 @@
15761584
}else{
15771585
blob_zero(&deltaSrc);
15781586
}
15791587
svn_apply_svndiff(&rec.content, &deltaSrc, &target);
15801588
rid = svn_handle_symlinks(zPerm, &target);
1589
+ blob_reset(&deltaSrc);
1590
+ blob_reset(&target);
15811591
}else if( rec.contentFlag ){
15821592
rid = svn_handle_symlinks(zPerm, &rec.content);
15831593
}else if( zSrcPath ){
15841594
if ( zPerm==0 ){
15851595
zPerm = db_text(0, "SELECT tperm FROM xfiles"
@@ -1618,10 +1628,12 @@
16181628
" WHERE tpath=%Q AND tbranch=%d"
16191629
")", zFile, branchId);
16201630
content_get(rid, &deltaSrc);
16211631
svn_apply_svndiff(&rec.content, &deltaSrc, &target);
16221632
rid = svn_handle_symlinks(zPerm, &target);
1633
+ blob_reset(&deltaSrc);
1634
+ blob_reset(&target);
16231635
}else{
16241636
rid = svn_handle_symlinks(zPerm, &rec.content);
16251637
}
16261638
db_bind_text(&addFile, ":path", zFile);
16271639
db_bind_int(&addFile, ":branch", branchId);
16281640
--- src/import.c
+++ src/import.c
@@ -1248,11 +1248,19 @@
1248 zOut = blob_buffer(pOut)+lenOld;
1249 while( zDiff<zInst+lenInst ){
1250 u64 lenCpy = (*zDiff)&0x3f;
1251 const char *zCpy;
1252 switch( (*zDiff)&0xC0 ){
1253 case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
 
 
 
 
 
 
 
 
1254 case 0x40: zCpy = blob_buffer(pOut); break;
1255 case 0x80: zCpy = zData; break;
1256 default: fossil_fatal("Invalid svndiff0 instruction");
1257 }
1258 zDiff++;
@@ -1576,10 +1584,12 @@
1576 }else{
1577 blob_zero(&deltaSrc);
1578 }
1579 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1580 rid = svn_handle_symlinks(zPerm, &target);
 
 
1581 }else if( rec.contentFlag ){
1582 rid = svn_handle_symlinks(zPerm, &rec.content);
1583 }else if( zSrcPath ){
1584 if ( zPerm==0 ){
1585 zPerm = db_text(0, "SELECT tperm FROM xfiles"
@@ -1618,10 +1628,12 @@
1618 " WHERE tpath=%Q AND tbranch=%d"
1619 ")", zFile, branchId);
1620 content_get(rid, &deltaSrc);
1621 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1622 rid = svn_handle_symlinks(zPerm, &target);
 
 
1623 }else{
1624 rid = svn_handle_symlinks(zPerm, &rec.content);
1625 }
1626 db_bind_text(&addFile, ":path", zFile);
1627 db_bind_int(&addFile, ":branch", branchId);
1628
--- src/import.c
+++ src/import.c
@@ -1248,11 +1248,19 @@
1248 zOut = blob_buffer(pOut)+lenOld;
1249 while( zDiff<zInst+lenInst ){
1250 u64 lenCpy = (*zDiff)&0x3f;
1251 const char *zCpy;
1252 switch( (*zDiff)&0xC0 ){
1253 case 0x00:
1254 if( 0==blob_size(pSrc) ){
1255 /* https://fossil-scm.org/forum/forumpost/15d4b242bda2a108 */
1256 fossil_fatal("Don't know how to handle NULL input. "
1257 "Tip: do not use the --incremental flag "
1258 "in the svn dump command.");
1259 }
1260 zCpy = blob_buffer(pSrc)+offSrc;
1261 break;
1262 case 0x40: zCpy = blob_buffer(pOut); break;
1263 case 0x80: zCpy = zData; break;
1264 default: fossil_fatal("Invalid svndiff0 instruction");
1265 }
1266 zDiff++;
@@ -1576,10 +1584,12 @@
1584 }else{
1585 blob_zero(&deltaSrc);
1586 }
1587 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1588 rid = svn_handle_symlinks(zPerm, &target);
1589 blob_reset(&deltaSrc);
1590 blob_reset(&target);
1591 }else if( rec.contentFlag ){
1592 rid = svn_handle_symlinks(zPerm, &rec.content);
1593 }else if( zSrcPath ){
1594 if ( zPerm==0 ){
1595 zPerm = db_text(0, "SELECT tperm FROM xfiles"
@@ -1618,10 +1628,12 @@
1628 " WHERE tpath=%Q AND tbranch=%d"
1629 ")", zFile, branchId);
1630 content_get(rid, &deltaSrc);
1631 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1632 rid = svn_handle_symlinks(zPerm, &target);
1633 blob_reset(&deltaSrc);
1634 blob_reset(&target);
1635 }else{
1636 rid = svn_handle_symlinks(zPerm, &rec.content);
1637 }
1638 db_bind_text(&addFile, ":path", zFile);
1639 db_bind_int(&addFile, ":branch", branchId);
1640
+4 -1
--- src/info.c
+++ src/info.c
@@ -2631,11 +2631,12 @@
26312631
fossil_free(zHeader);
26322632
if( !isFile && g.perm.Admin ){
26332633
Stmt q;
26342634
db_prepare(&q,
26352635
"SELECT coalesce(user.login,rcvfrom.uid),"
2636
- " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
2636
+ " datetime(rcvfrom.mtime,toLocal()),"
2637
+ " coalesce(rcvfrom.ipaddr,'unknown')"
26372638
" FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
26382639
" WHERE blob.rid=%d"
26392640
" AND rcvfrom.rcvid=blob.rcvid;", rid);
26402641
while( db_step(&q)==SQLITE_ROW ){
26412642
const char *zUser = db_column_text(&q,0);
@@ -3795,13 +3796,15 @@
37953796
" UNION ALL"
37963797
" SELECT plink.pid, event.mtime, singletonTag.tagname, n+1"
37973798
" FROM ancestor, plink, event"
37983799
" LEFT JOIN singletonTag ON singletonTag.rid=plink.pid"
37993800
" WHERE plink.cid=ancestor.rid"
3801
+ " AND plink.isprim=1"
38003802
" AND event.objid=plink.pid"
38013803
" AND ancestor.tagname IS NULL"
38023804
" ORDER BY mtime DESC"
3805
+ " LIMIT 100000"
38033806
" )"
38043807
"SELECT tagname, n"
38053808
" FROM ancestor"
38063809
" WHERE tagname IS NOT NULL"
38073810
" ORDER BY n LIMIT 1;",
38083811
--- src/info.c
+++ src/info.c
@@ -2631,11 +2631,12 @@
2631 fossil_free(zHeader);
2632 if( !isFile && g.perm.Admin ){
2633 Stmt q;
2634 db_prepare(&q,
2635 "SELECT coalesce(user.login,rcvfrom.uid),"
2636 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
 
2637 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
2638 " WHERE blob.rid=%d"
2639 " AND rcvfrom.rcvid=blob.rcvid;", rid);
2640 while( db_step(&q)==SQLITE_ROW ){
2641 const char *zUser = db_column_text(&q,0);
@@ -3795,13 +3796,15 @@
3795 " UNION ALL"
3796 " SELECT plink.pid, event.mtime, singletonTag.tagname, n+1"
3797 " FROM ancestor, plink, event"
3798 " LEFT JOIN singletonTag ON singletonTag.rid=plink.pid"
3799 " WHERE plink.cid=ancestor.rid"
 
3800 " AND event.objid=plink.pid"
3801 " AND ancestor.tagname IS NULL"
3802 " ORDER BY mtime DESC"
 
3803 " )"
3804 "SELECT tagname, n"
3805 " FROM ancestor"
3806 " WHERE tagname IS NOT NULL"
3807 " ORDER BY n LIMIT 1;",
3808
--- src/info.c
+++ src/info.c
@@ -2631,11 +2631,12 @@
2631 fossil_free(zHeader);
2632 if( !isFile && g.perm.Admin ){
2633 Stmt q;
2634 db_prepare(&q,
2635 "SELECT coalesce(user.login,rcvfrom.uid),"
2636 " datetime(rcvfrom.mtime,toLocal()),"
2637 " coalesce(rcvfrom.ipaddr,'unknown')"
2638 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
2639 " WHERE blob.rid=%d"
2640 " AND rcvfrom.rcvid=blob.rcvid;", rid);
2641 while( db_step(&q)==SQLITE_ROW ){
2642 const char *zUser = db_column_text(&q,0);
@@ -3795,13 +3796,15 @@
3796 " UNION ALL"
3797 " SELECT plink.pid, event.mtime, singletonTag.tagname, n+1"
3798 " FROM ancestor, plink, event"
3799 " LEFT JOIN singletonTag ON singletonTag.rid=plink.pid"
3800 " WHERE plink.cid=ancestor.rid"
3801 " AND plink.isprim=1"
3802 " AND event.objid=plink.pid"
3803 " AND ancestor.tagname IS NULL"
3804 " ORDER BY mtime DESC"
3805 " LIMIT 100000"
3806 " )"
3807 "SELECT tagname, n"
3808 " FROM ancestor"
3809 " WHERE tagname IS NOT NULL"
3810 " ORDER BY n LIMIT 1;",
3811
--- src/json_branch.c
+++ src/json_branch.c
@@ -197,16 +197,11 @@
197197
char *zDate; /* Date that branch was created */
198198
char *zComment; /* Check-in comment for the new branch */
199199
Blob branch; /* manifest for the new branch */
200200
Manifest *pParent; /* Parsed parent manifest */
201201
Blob mcksum; /* Self-checksum on the manifest */
202
- int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
203202
204
- if( fossil_strncmp(zColor, "auto", 4)==0 ) {
205
- bAutoColor = 1;
206
- zColor = 0;
207
- }
208203
/* fossil branch new name */
209204
if( zBranch==0 || zBranch[0]==0 ){
210205
zOpt->rcErrMsg = "Branch name may not be null/empty.";
211206
return FSL_JSON_E_INVALID_ARGS;
212207
}
@@ -265,11 +260,10 @@
265260
manifest_destroy(pParent);
266261
267262
/* Add the symbolic branch name and the "branch" tag to identify
268263
** this as a new branch */
269264
if( content_is_private(rootid) ) zOpt->isPrivate = 1;
270
- if( zOpt->isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
271265
if( zColor!=0 ){
272266
blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
273267
}
274268
blob_appendf(&branch, "T *branch * %F\n", zBranch);
275269
blob_appendf(&branch, "T *sym-%F *\n", zBranch);
276270
--- src/json_branch.c
+++ src/json_branch.c
@@ -197,16 +197,11 @@
197 char *zDate; /* Date that branch was created */
198 char *zComment; /* Check-in comment for the new branch */
199 Blob branch; /* manifest for the new branch */
200 Manifest *pParent; /* Parsed parent manifest */
201 Blob mcksum; /* Self-checksum on the manifest */
202 int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
203
204 if( fossil_strncmp(zColor, "auto", 4)==0 ) {
205 bAutoColor = 1;
206 zColor = 0;
207 }
208 /* fossil branch new name */
209 if( zBranch==0 || zBranch[0]==0 ){
210 zOpt->rcErrMsg = "Branch name may not be null/empty.";
211 return FSL_JSON_E_INVALID_ARGS;
212 }
@@ -265,11 +260,10 @@
265 manifest_destroy(pParent);
266
267 /* Add the symbolic branch name and the "branch" tag to identify
268 ** this as a new branch */
269 if( content_is_private(rootid) ) zOpt->isPrivate = 1;
270 if( zOpt->isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
271 if( zColor!=0 ){
272 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
273 }
274 blob_appendf(&branch, "T *branch * %F\n", zBranch);
275 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
276
--- src/json_branch.c
+++ src/json_branch.c
@@ -197,16 +197,11 @@
197 char *zDate; /* Date that branch was created */
198 char *zComment; /* Check-in comment for the new branch */
199 Blob branch; /* manifest for the new branch */
200 Manifest *pParent; /* Parsed parent manifest */
201 Blob mcksum; /* Self-checksum on the manifest */
 
202
 
 
 
 
203 /* fossil branch new name */
204 if( zBranch==0 || zBranch[0]==0 ){
205 zOpt->rcErrMsg = "Branch name may not be null/empty.";
206 return FSL_JSON_E_INVALID_ARGS;
207 }
@@ -265,11 +260,10 @@
260 manifest_destroy(pParent);
261
262 /* Add the symbolic branch name and the "branch" tag to identify
263 ** this as a new branch */
264 if( content_is_private(rootid) ) zOpt->isPrivate = 1;
 
265 if( zColor!=0 ){
266 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
267 }
268 blob_appendf(&branch, "T *branch * %F\n", zBranch);
269 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
270
+9 -26
--- src/login.c
+++ src/login.c
@@ -394,50 +394,33 @@
394394
cgi_replace_parameter(cookie, NULL);
395395
cgi_replace_parameter("anon", NULL);
396396
}
397397
}
398398
399
-/*
400
-** Return true if the prefix of zStr matches zPattern. Return false if
401
-** they are different.
402
-**
403
-** A lowercase character in zPattern will match either upper or lower
404
-** case in zStr. But an uppercase in zPattern will only match an
405
-** uppercase in zStr.
406
-*/
407
-static int prefix_match(const char *zPattern, const char *zStr){
408
- int i;
409
- char c;
410
- for(i=0; (c = zPattern[i])!=0; i++){
411
- if( zStr[i]!=c && fossil_tolower(zStr[i])!=c ) return 0;
412
- }
413
- return 1;
414
-}
415
-
416399
/*
417400
** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent
418401
** is a manually operated browser or a bot. When in doubt, assume a bot.
419402
** Return true if we believe the agent is a real person.
420403
*/
421404
static int isHuman(const char *zAgent){
422
- int i;
423405
if( zAgent==0 ) return 0; /* If no UserAgent, then probably a bot */
424
- for(i=0; zAgent[i]; i++){
425
- if( prefix_match("bot", zAgent+i) ) return 0;
426
- if( prefix_match("spider", zAgent+i) ) return 0;
427
- if( prefix_match("crawl", zAgent+i) ) return 0;
428
- /* If a URI appears in the User-Agent, it is probably a bot */
429
- if( strncmp("http", zAgent+i,4)==0 ) return 0;
430
- }
406
+ if( strstr(zAgent, "bot")!=0 ) return 0;
407
+ if( strstr(zAgent, "spider")!=0 ) return 0;
408
+ if( strstr(zAgent, "crawl")!=0 ) return 0;
409
+ /* If a URI appears in the User-Agent, it is probably a bot */
410
+ if( strstr(zAgent, "http")!=0 ) return 0;
431411
if( strncmp(zAgent, "Mozilla/", 8)==0 ){
432412
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
433413
414
+ /* Google AI Robot, maybe? */
415
+ if( strstr(zAgent, "GoogleOther)")!=0 ) return 0;
416
+
434417
/* 2016-05-30: A pernicious spider that likes to walk Fossil timelines has
435418
** been detected on the SQLite website. The spider changes its user-agent
436419
** string frequently, but it always seems to include the following text:
437420
*/
438
- if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
421
+ if( strstr(zAgent, "Safari/537.36Mozilla/5.0")!=0 ) return 0;
439422
440423
if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
441424
if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
442425
if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
443426
if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){
444427
--- src/login.c
+++ src/login.c
@@ -394,50 +394,33 @@
394 cgi_replace_parameter(cookie, NULL);
395 cgi_replace_parameter("anon", NULL);
396 }
397 }
398
399 /*
400 ** Return true if the prefix of zStr matches zPattern. Return false if
401 ** they are different.
402 **
403 ** A lowercase character in zPattern will match either upper or lower
404 ** case in zStr. But an uppercase in zPattern will only match an
405 ** uppercase in zStr.
406 */
407 static int prefix_match(const char *zPattern, const char *zStr){
408 int i;
409 char c;
410 for(i=0; (c = zPattern[i])!=0; i++){
411 if( zStr[i]!=c && fossil_tolower(zStr[i])!=c ) return 0;
412 }
413 return 1;
414 }
415
416 /*
417 ** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent
418 ** is a manually operated browser or a bot. When in doubt, assume a bot.
419 ** Return true if we believe the agent is a real person.
420 */
421 static int isHuman(const char *zAgent){
422 int i;
423 if( zAgent==0 ) return 0; /* If no UserAgent, then probably a bot */
424 for(i=0; zAgent[i]; i++){
425 if( prefix_match("bot", zAgent+i) ) return 0;
426 if( prefix_match("spider", zAgent+i) ) return 0;
427 if( prefix_match("crawl", zAgent+i) ) return 0;
428 /* If a URI appears in the User-Agent, it is probably a bot */
429 if( strncmp("http", zAgent+i,4)==0 ) return 0;
430 }
431 if( strncmp(zAgent, "Mozilla/", 8)==0 ){
432 if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
433
 
 
 
434 /* 2016-05-30: A pernicious spider that likes to walk Fossil timelines has
435 ** been detected on the SQLite website. The spider changes its user-agent
436 ** string frequently, but it always seems to include the following text:
437 */
438 if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
439
440 if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
441 if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
442 if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
443 if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){
444
--- src/login.c
+++ src/login.c
@@ -394,50 +394,33 @@
394 cgi_replace_parameter(cookie, NULL);
395 cgi_replace_parameter("anon", NULL);
396 }
397 }
398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399 /*
400 ** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent
401 ** is a manually operated browser or a bot. When in doubt, assume a bot.
402 ** Return true if we believe the agent is a real person.
403 */
404 static int isHuman(const char *zAgent){
 
405 if( zAgent==0 ) return 0; /* If no UserAgent, then probably a bot */
406 if( strstr(zAgent, "bot")!=0 ) return 0;
407 if( strstr(zAgent, "spider")!=0 ) return 0;
408 if( strstr(zAgent, "crawl")!=0 ) return 0;
409 /* If a URI appears in the User-Agent, it is probably a bot */
410 if( strstr(zAgent, "http")!=0 ) return 0;
 
 
411 if( strncmp(zAgent, "Mozilla/", 8)==0 ){
412 if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
413
414 /* Google AI Robot, maybe? */
415 if( strstr(zAgent, "GoogleOther)")!=0 ) return 0;
416
417 /* 2016-05-30: A pernicious spider that likes to walk Fossil timelines has
418 ** been detected on the SQLite website. The spider changes its user-agent
419 ** string frequently, but it always seems to include the following text:
420 */
421 if( strstr(zAgent, "Safari/537.36Mozilla/5.0")!=0 ) return 0;
422
423 if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
424 if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
425 if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
426 if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){
427
+44 -14
--- src/main.c
+++ src/main.c
@@ -227,10 +227,11 @@
227227
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
228228
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
229229
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
230230
** SSL client identity */
231231
const char *zCgiFile; /* Name of the CGI file */
232
+ const char *zReqType; /* Type of request: "HTTP", "CGI", "SCGI" */
232233
#if USE_SEE
233234
const char *zPidKey; /* Saved value of the --usepidkey option. Only
234235
* applicable when using SEE on Windows or Linux. */
235236
#endif
236237
int useLocalauth; /* No login required if from 127.0.0.1 */
@@ -1701,10 +1702,17 @@
17011702
17021703
g.zPhase = "process_one_web_page";
17031704
#if !defined(_WIN32)
17041705
signal(SIGSEGV, sigsegv_handler);
17051706
#endif
1707
+
1708
+ /* Decode %HH escapes in PATHINFO */
1709
+ if( strchr(zPathInfo,'%') ){
1710
+ char *z = fossil_strdup(zPathInfo);
1711
+ dehttpize(z);
1712
+ zPathInfo = z;
1713
+ }
17061714
17071715
/* Handle universal query parameters */
17081716
if( PB("utc") ){
17091717
g.fTimeFormat = 1;
17101718
}else if( PB("localtime") ){
@@ -1756,32 +1764,44 @@
17561764
@ <!-- Looking for repository named "%h(zRepo)" -->
17571765
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
17581766
}
17591767
17601768
1761
- /* For safety -- to prevent an attacker from accessing arbitrary disk
1762
- ** files by sending a maliciously crafted request URI to a public
1763
- ** server -- make sure the repository basename contains no
1764
- ** characters other than alphanumerics, "/", "_", "-", and ".", and
1765
- ** that "-" never occurs immediately after a "/" and that "." is always
1766
- ** surrounded by two alphanumerics. Any character that does not
1767
- ** satisfy these constraints is converted into "_".
1768
- */
1769
+ /* Restrictions on the URI for security:
1770
+ **
1771
+ ** 1. Reject characters that are not ASCII alphanumerics,
1772
+ ** "-", "_", ".", "/", or unicode (above ASCII).
1773
+ ** In other words: No ASCII punctuation or control characters
1774
+ ** other than "-", "_", "." and "/".
1775
+ ** 2. Exception to rule 1: Allow /X:/ where X is any ASCII
1776
+ ** alphabetic character at the beginning of the name on windows.
1777
+ ** 3. "-" may not occur immediately after "/"
1778
+ ** 4. "." may not be adjacent to another "." or to "/"
1779
+ **
1780
+ ** Any character does not satisfy these constraints a Not Found
1781
+ ** error is returned.
1782
+ */
17691783
szFile = 0;
17701784
for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){
17711785
char c = zRepo[j];
1772
- if( fossil_isalnum(c) ) continue;
1786
+ if( c>='a' && c<='z' ) continue;
1787
+ if( c>='A' && c<='Z' ) continue;
1788
+ if( c>='0' && c<='9' ) continue;
1789
+ if( (c&0x80)==0x80 ) continue;
17731790
#if defined(_WIN32) || defined(__CYGWIN__)
17741791
/* Allow names to begin with "/X:/" on windows */
17751792
if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
17761793
continue;
17771794
}
17781795
#endif
17791796
if( c=='/' ) continue;
17801797
if( c=='_' ) continue;
17811798
if( c=='-' && zRepo[j-1]!='/' ) continue;
1782
- if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
1799
+ if( c=='.'
1800
+ && zRepo[j-1]!='.' && zRepo[j-1]!='/'
1801
+ && zRepo[j+1]!='.' && zRepo[j+1]!='/'
1802
+ ){
17831803
continue;
17841804
}
17851805
if( c=='.' && g.fAllowACME && j==(int)nBase+1
17861806
&& strncmp(&zRepo[j-1],"/.well-known/",12)==0
17871807
){
@@ -2301,12 +2321,13 @@
23012321
** nossl Signal that no SSL connections are available.
23022322
**
23032323
** nocompress Do not compress HTTP replies.
23042324
**
23052325
** skin: LABEL Use the built-in skin called LABEL rather than
2306
-** the default. If there are no skins called LABEL
2307
-** then this line is a no-op.
2326
+** the default, or the default if LABEL is empty.
2327
+** If there are no skins called LABEL then this
2328
+** line is a no-op.
23082329
**
23092330
** files: GLOBLIST GLOBLIST is a comma-separated list of GLOB
23102331
** patterns that specify files that can be
23112332
** returned verbatim. This feature allows Fossil
23122333
** to act as a web server returning static
@@ -2363,10 +2384,11 @@
23632384
g.httpOut = stdout;
23642385
g.httpIn = stdin;
23652386
fossil_binary_mode(g.httpOut);
23662387
fossil_binary_mode(g.httpIn);
23672388
g.cgiOutput = 1;
2389
+ g.zReqType = "CGI";
23682390
fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
23692391
/* Find the name of the CGI control file */
23702392
if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
23712393
g.zCgiFile = g.argv[2];
23722394
}else if( g.argc>=2 ){
@@ -2846,10 +2868,11 @@
28462868
g.useLocalauth = find_option("localauth", 0, 0)!=0;
28472869
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
28482870
g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
28492871
g.zExtRoot = find_option("extroot",0,1);
28502872
g.zCkoutAlias = find_option("ckout-alias",0,1);
2873
+ g.zReqType = "HTTP";
28512874
zInFile = find_option("in",0,1);
28522875
if( zInFile ){
28532876
backoffice_disable();
28542877
g.httpIn = fossil_fopen(zInFile, "rb");
28552878
if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2869,10 +2892,11 @@
28692892
_setmode(_fileno(stdout), _O_BINARY);
28702893
#endif
28712894
}
28722895
zIpAddr = find_option("ipaddr",0,1);
28732896
useSCGI = find_option("scgi", 0, 0)!=0;
2897
+ if( useSCGI ) g.zReqType = "SCGI";
28742898
zAltBase = find_option("baseurl", 0, 1);
28752899
if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
28762900
if( zAltBase ) set_base_url(zAltBase);
28772901
if( find_option("https",0,0)!=0 ){
28782902
zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
@@ -2995,10 +3019,11 @@
29953019
g.httpOut = stdout;
29963020
fossil_binary_mode(g.httpOut);
29973021
fossil_binary_mode(g.httpIn);
29983022
g.zExtRoot = find_option("extroot",0,1);
29993023
find_server_repository(2, 0);
3024
+ g.zReqType = "HTTP";
30003025
g.cgiOutput = 1;
30013026
g.fNoHttpCompress = 1;
30023027
g.fullHttpReply = 1;
30033028
g.sslNotAvailable = 1; /* Avoid attempts to redirect */
30043029
zIpAddr = bTest ? 0 : cgi_ssh_remote_addr(0);
@@ -3155,11 +3180,12 @@
31553180
** -p|--page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
31563181
** --pkey FILE Read the private key used for TLS from FILE
31573182
** -P|--port [IP:]PORT Listen on the given IP (optional) and port
31583183
** --repolist If REPOSITORY is dir, URL "/" lists repos
31593184
** --scgi Accept SCGI rather than HTTP
3160
-** --skin LABEL Use override skin LABEL
3185
+** --skin LABEL Use override skin LABEL, or the site's default skin if
3186
+** LABEL is an empty string.
31613187
** --th-trace Trace TH1 execution (for debugging purposes)
31623188
** --usepidkey Use saved encryption key from parent process. This is
31633189
** only necessary when using SEE on Windows or Linux.
31643190
**
31653191
** See also: [[cgi]], [[http]], [[winsrv]]
@@ -3231,11 +3257,15 @@
32313257
zNotFound = find_option("notfound", 0, 1);
32323258
allowRepoList = find_option("repolist",0,0)!=0;
32333259
if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
32343260
zAltBase = find_option("baseurl", 0, 1);
32353261
fCreate = find_option("create",0,0)!=0;
3236
- if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
3262
+ g.zReqType = "HTTP";
3263
+ if( find_option("scgi", 0, 0)!=0 ){
3264
+ g.zReqType = "SCGI";
3265
+ flags |= HTTP_SERVER_SCGI;
3266
+ }
32373267
if( zAltBase ){
32383268
set_base_url(zAltBase);
32393269
}
32403270
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
32413271
fNoBrowser = find_option("nobrowser", "B", 0)!=0;
32423272
--- src/main.c
+++ src/main.c
@@ -227,10 +227,11 @@
227 const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
228 const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
229 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
230 ** SSL client identity */
231 const char *zCgiFile; /* Name of the CGI file */
 
232 #if USE_SEE
233 const char *zPidKey; /* Saved value of the --usepidkey option. Only
234 * applicable when using SEE on Windows or Linux. */
235 #endif
236 int useLocalauth; /* No login required if from 127.0.0.1 */
@@ -1701,10 +1702,17 @@
1701
1702 g.zPhase = "process_one_web_page";
1703 #if !defined(_WIN32)
1704 signal(SIGSEGV, sigsegv_handler);
1705 #endif
 
 
 
 
 
 
 
1706
1707 /* Handle universal query parameters */
1708 if( PB("utc") ){
1709 g.fTimeFormat = 1;
1710 }else if( PB("localtime") ){
@@ -1756,32 +1764,44 @@
1756 @ <!-- Looking for repository named "%h(zRepo)" -->
1757 fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
1758 }
1759
1760
1761 /* For safety -- to prevent an attacker from accessing arbitrary disk
1762 ** files by sending a maliciously crafted request URI to a public
1763 ** server -- make sure the repository basename contains no
1764 ** characters other than alphanumerics, "/", "_", "-", and ".", and
1765 ** that "-" never occurs immediately after a "/" and that "." is always
1766 ** surrounded by two alphanumerics. Any character that does not
1767 ** satisfy these constraints is converted into "_".
1768 */
 
 
 
 
 
 
1769 szFile = 0;
1770 for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){
1771 char c = zRepo[j];
1772 if( fossil_isalnum(c) ) continue;
 
 
 
1773 #if defined(_WIN32) || defined(__CYGWIN__)
1774 /* Allow names to begin with "/X:/" on windows */
1775 if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
1776 continue;
1777 }
1778 #endif
1779 if( c=='/' ) continue;
1780 if( c=='_' ) continue;
1781 if( c=='-' && zRepo[j-1]!='/' ) continue;
1782 if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
 
 
 
1783 continue;
1784 }
1785 if( c=='.' && g.fAllowACME && j==(int)nBase+1
1786 && strncmp(&zRepo[j-1],"/.well-known/",12)==0
1787 ){
@@ -2301,12 +2321,13 @@
2301 ** nossl Signal that no SSL connections are available.
2302 **
2303 ** nocompress Do not compress HTTP replies.
2304 **
2305 ** skin: LABEL Use the built-in skin called LABEL rather than
2306 ** the default. If there are no skins called LABEL
2307 ** then this line is a no-op.
 
2308 **
2309 ** files: GLOBLIST GLOBLIST is a comma-separated list of GLOB
2310 ** patterns that specify files that can be
2311 ** returned verbatim. This feature allows Fossil
2312 ** to act as a web server returning static
@@ -2363,10 +2384,11 @@
2363 g.httpOut = stdout;
2364 g.httpIn = stdin;
2365 fossil_binary_mode(g.httpOut);
2366 fossil_binary_mode(g.httpIn);
2367 g.cgiOutput = 1;
 
2368 fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
2369 /* Find the name of the CGI control file */
2370 if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
2371 g.zCgiFile = g.argv[2];
2372 }else if( g.argc>=2 ){
@@ -2846,10 +2868,11 @@
2846 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2847 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
2848 g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
2849 g.zExtRoot = find_option("extroot",0,1);
2850 g.zCkoutAlias = find_option("ckout-alias",0,1);
 
2851 zInFile = find_option("in",0,1);
2852 if( zInFile ){
2853 backoffice_disable();
2854 g.httpIn = fossil_fopen(zInFile, "rb");
2855 if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2869,10 +2892,11 @@
2869 _setmode(_fileno(stdout), _O_BINARY);
2870 #endif
2871 }
2872 zIpAddr = find_option("ipaddr",0,1);
2873 useSCGI = find_option("scgi", 0, 0)!=0;
 
2874 zAltBase = find_option("baseurl", 0, 1);
2875 if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
2876 if( zAltBase ) set_base_url(zAltBase);
2877 if( find_option("https",0,0)!=0 ){
2878 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
@@ -2995,10 +3019,11 @@
2995 g.httpOut = stdout;
2996 fossil_binary_mode(g.httpOut);
2997 fossil_binary_mode(g.httpIn);
2998 g.zExtRoot = find_option("extroot",0,1);
2999 find_server_repository(2, 0);
 
3000 g.cgiOutput = 1;
3001 g.fNoHttpCompress = 1;
3002 g.fullHttpReply = 1;
3003 g.sslNotAvailable = 1; /* Avoid attempts to redirect */
3004 zIpAddr = bTest ? 0 : cgi_ssh_remote_addr(0);
@@ -3155,11 +3180,12 @@
3155 ** -p|--page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
3156 ** --pkey FILE Read the private key used for TLS from FILE
3157 ** -P|--port [IP:]PORT Listen on the given IP (optional) and port
3158 ** --repolist If REPOSITORY is dir, URL "/" lists repos
3159 ** --scgi Accept SCGI rather than HTTP
3160 ** --skin LABEL Use override skin LABEL
 
3161 ** --th-trace Trace TH1 execution (for debugging purposes)
3162 ** --usepidkey Use saved encryption key from parent process. This is
3163 ** only necessary when using SEE on Windows or Linux.
3164 **
3165 ** See also: [[cgi]], [[http]], [[winsrv]]
@@ -3231,11 +3257,15 @@
3231 zNotFound = find_option("notfound", 0, 1);
3232 allowRepoList = find_option("repolist",0,0)!=0;
3233 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
3234 zAltBase = find_option("baseurl", 0, 1);
3235 fCreate = find_option("create",0,0)!=0;
3236 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
 
 
 
 
3237 if( zAltBase ){
3238 set_base_url(zAltBase);
3239 }
3240 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
3241 fNoBrowser = find_option("nobrowser", "B", 0)!=0;
3242
--- src/main.c
+++ src/main.c
@@ -227,10 +227,11 @@
227 const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
228 const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
229 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
230 ** SSL client identity */
231 const char *zCgiFile; /* Name of the CGI file */
232 const char *zReqType; /* Type of request: "HTTP", "CGI", "SCGI" */
233 #if USE_SEE
234 const char *zPidKey; /* Saved value of the --usepidkey option. Only
235 * applicable when using SEE on Windows or Linux. */
236 #endif
237 int useLocalauth; /* No login required if from 127.0.0.1 */
@@ -1701,10 +1702,17 @@
1702
1703 g.zPhase = "process_one_web_page";
1704 #if !defined(_WIN32)
1705 signal(SIGSEGV, sigsegv_handler);
1706 #endif
1707
1708 /* Decode %HH escapes in PATHINFO */
1709 if( strchr(zPathInfo,'%') ){
1710 char *z = fossil_strdup(zPathInfo);
1711 dehttpize(z);
1712 zPathInfo = z;
1713 }
1714
1715 /* Handle universal query parameters */
1716 if( PB("utc") ){
1717 g.fTimeFormat = 1;
1718 }else if( PB("localtime") ){
@@ -1756,32 +1764,44 @@
1764 @ <!-- Looking for repository named "%h(zRepo)" -->
1765 fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
1766 }
1767
1768
1769 /* Restrictions on the URI for security:
1770 **
1771 ** 1. Reject characters that are not ASCII alphanumerics,
1772 ** "-", "_", ".", "/", or unicode (above ASCII).
1773 ** In other words: No ASCII punctuation or control characters
1774 ** other than "-", "_", "." and "/".
1775 ** 2. Exception to rule 1: Allow /X:/ where X is any ASCII
1776 ** alphabetic character at the beginning of the name on windows.
1777 ** 3. "-" may not occur immediately after "/"
1778 ** 4. "." may not be adjacent to another "." or to "/"
1779 **
1780 ** Any character does not satisfy these constraints a Not Found
1781 ** error is returned.
1782 */
1783 szFile = 0;
1784 for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){
1785 char c = zRepo[j];
1786 if( c>='a' && c<='z' ) continue;
1787 if( c>='A' && c<='Z' ) continue;
1788 if( c>='0' && c<='9' ) continue;
1789 if( (c&0x80)==0x80 ) continue;
1790 #if defined(_WIN32) || defined(__CYGWIN__)
1791 /* Allow names to begin with "/X:/" on windows */
1792 if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
1793 continue;
1794 }
1795 #endif
1796 if( c=='/' ) continue;
1797 if( c=='_' ) continue;
1798 if( c=='-' && zRepo[j-1]!='/' ) continue;
1799 if( c=='.'
1800 && zRepo[j-1]!='.' && zRepo[j-1]!='/'
1801 && zRepo[j+1]!='.' && zRepo[j+1]!='/'
1802 ){
1803 continue;
1804 }
1805 if( c=='.' && g.fAllowACME && j==(int)nBase+1
1806 && strncmp(&zRepo[j-1],"/.well-known/",12)==0
1807 ){
@@ -2301,12 +2321,13 @@
2321 ** nossl Signal that no SSL connections are available.
2322 **
2323 ** nocompress Do not compress HTTP replies.
2324 **
2325 ** skin: LABEL Use the built-in skin called LABEL rather than
2326 ** the default, or the default if LABEL is empty.
2327 ** If there are no skins called LABEL then this
2328 ** line is a no-op.
2329 **
2330 ** files: GLOBLIST GLOBLIST is a comma-separated list of GLOB
2331 ** patterns that specify files that can be
2332 ** returned verbatim. This feature allows Fossil
2333 ** to act as a web server returning static
@@ -2363,10 +2384,11 @@
2384 g.httpOut = stdout;
2385 g.httpIn = stdin;
2386 fossil_binary_mode(g.httpOut);
2387 fossil_binary_mode(g.httpIn);
2388 g.cgiOutput = 1;
2389 g.zReqType = "CGI";
2390 fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
2391 /* Find the name of the CGI control file */
2392 if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){
2393 g.zCgiFile = g.argv[2];
2394 }else if( g.argc>=2 ){
@@ -2846,10 +2868,11 @@
2868 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2869 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
2870 g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
2871 g.zExtRoot = find_option("extroot",0,1);
2872 g.zCkoutAlias = find_option("ckout-alias",0,1);
2873 g.zReqType = "HTTP";
2874 zInFile = find_option("in",0,1);
2875 if( zInFile ){
2876 backoffice_disable();
2877 g.httpIn = fossil_fopen(zInFile, "rb");
2878 if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2869,10 +2892,11 @@
2892 _setmode(_fileno(stdout), _O_BINARY);
2893 #endif
2894 }
2895 zIpAddr = find_option("ipaddr",0,1);
2896 useSCGI = find_option("scgi", 0, 0)!=0;
2897 if( useSCGI ) g.zReqType = "SCGI";
2898 zAltBase = find_option("baseurl", 0, 1);
2899 if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
2900 if( zAltBase ) set_base_url(zAltBase);
2901 if( find_option("https",0,0)!=0 ){
2902 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
@@ -2995,10 +3019,11 @@
3019 g.httpOut = stdout;
3020 fossil_binary_mode(g.httpOut);
3021 fossil_binary_mode(g.httpIn);
3022 g.zExtRoot = find_option("extroot",0,1);
3023 find_server_repository(2, 0);
3024 g.zReqType = "HTTP";
3025 g.cgiOutput = 1;
3026 g.fNoHttpCompress = 1;
3027 g.fullHttpReply = 1;
3028 g.sslNotAvailable = 1; /* Avoid attempts to redirect */
3029 zIpAddr = bTest ? 0 : cgi_ssh_remote_addr(0);
@@ -3155,11 +3180,12 @@
3180 ** -p|--page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
3181 ** --pkey FILE Read the private key used for TLS from FILE
3182 ** -P|--port [IP:]PORT Listen on the given IP (optional) and port
3183 ** --repolist If REPOSITORY is dir, URL "/" lists repos
3184 ** --scgi Accept SCGI rather than HTTP
3185 ** --skin LABEL Use override skin LABEL, or the site's default skin if
3186 ** LABEL is an empty string.
3187 ** --th-trace Trace TH1 execution (for debugging purposes)
3188 ** --usepidkey Use saved encryption key from parent process. This is
3189 ** only necessary when using SEE on Windows or Linux.
3190 **
3191 ** See also: [[cgi]], [[http]], [[winsrv]]
@@ -3231,11 +3257,15 @@
3257 zNotFound = find_option("notfound", 0, 1);
3258 allowRepoList = find_option("repolist",0,0)!=0;
3259 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
3260 zAltBase = find_option("baseurl", 0, 1);
3261 fCreate = find_option("create",0,0)!=0;
3262 g.zReqType = "HTTP";
3263 if( find_option("scgi", 0, 0)!=0 ){
3264 g.zReqType = "SCGI";
3265 flags |= HTTP_SERVER_SCGI;
3266 }
3267 if( zAltBase ){
3268 set_base_url(zAltBase);
3269 }
3270 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
3271 fNoBrowser = find_option("nobrowser", "B", 0)!=0;
3272
--- src/main.mk
+++ src/main.mk
@@ -271,10 +271,11 @@
271271
$(SRCDIR)/sounds/f.wav \
272272
$(SRCDIR)/style.admin_log.css \
273273
$(SRCDIR)/style.chat.css \
274274
$(SRCDIR)/style.fileedit.css \
275275
$(SRCDIR)/style.pikchrshow.css \
276
+ $(SRCDIR)/style.uvlist.css \
276277
$(SRCDIR)/style.wikiedit.css \
277278
$(SRCDIR)/tree.js \
278279
$(SRCDIR)/useredit.js \
279280
$(SRCDIR)/wiki.wiki
280281
281282
--- src/main.mk
+++ src/main.mk
@@ -271,10 +271,11 @@
271 $(SRCDIR)/sounds/f.wav \
272 $(SRCDIR)/style.admin_log.css \
273 $(SRCDIR)/style.chat.css \
274 $(SRCDIR)/style.fileedit.css \
275 $(SRCDIR)/style.pikchrshow.css \
 
276 $(SRCDIR)/style.wikiedit.css \
277 $(SRCDIR)/tree.js \
278 $(SRCDIR)/useredit.js \
279 $(SRCDIR)/wiki.wiki
280
281
--- src/main.mk
+++ src/main.mk
@@ -271,10 +271,11 @@
271 $(SRCDIR)/sounds/f.wav \
272 $(SRCDIR)/style.admin_log.css \
273 $(SRCDIR)/style.chat.css \
274 $(SRCDIR)/style.fileedit.css \
275 $(SRCDIR)/style.pikchrshow.css \
276 $(SRCDIR)/style.uvlist.css \
277 $(SRCDIR)/style.wikiedit.css \
278 $(SRCDIR)/tree.js \
279 $(SRCDIR)/useredit.js \
280 $(SRCDIR)/wiki.wiki
281
282
+73 -18
--- src/merge.c
+++ src/merge.c
@@ -274,28 +274,34 @@
274274
}
275275
276276
277277
/*
278278
** COMMAND: merge
279
-** COMMAND: cherry-pick
279
+** COMMAND: cherry-pick alias
280
+** COMMAND: cherrypick
280281
**
281
-** Usage: %fossil merge ?OPTIONS? ?VERSION?
282
+** Usage: %fossil merge ?OPTIONS? ?VERSION ...?
283
+** Or: %fossil cherrypick ?OPTIONS? ?VERSION ...?
282284
**
283285
** The argument VERSION is a version that should be merged into the
284286
** current check-out. All changes from VERSION back to the nearest
285287
** common ancestor are merged. Except, if either of the --cherrypick
286288
** or --backout options are used only the changes associated with the
287289
** single check-in VERSION are merged. The --backout option causes
288290
** the changes associated with VERSION to be removed from the current
289
-** check-out rather than added. When invoked with the name
290
-** cherry-pick, this command works exactly like merge --cherrypick.
291
+** check-out rather than added. When invoked with the name
292
+** "cherrypick" instead of "merge", this command works exactly like
293
+** "merge --cherrypick".
291294
**
292295
** Files which are renamed in the merged-in branch will be renamed in
293296
** the current check-out.
294297
**
295298
** If the VERSION argument is omitted, then Fossil attempts to find
296299
** a recent fork on the current branch to merge.
300
+**
301
+** If there are multiple VERSION arguments, then each VERSION is merged
302
+** (or cherrypicked) in the order that they appear on the command-line.
297303
**
298304
** Options:
299305
** --backout Do a reverse cherrypick merge against VERSION.
300306
** In other words, back out the changes that were
301307
** added by VERSION.
@@ -315,10 +321,11 @@
315321
** --integrate Merged branch will be closed when committing
316322
** -K|--keep-merge-files On merge conflict, retain the temporary files
317323
** used for merging, named *-baseline, *-original,
318324
** and *-merge.
319325
** -n|--dry-run If given, display instead of run actions
326
+** --nosync Do not auto-sync prior to merging
320327
** -v|--verbose Show additional details of the merge
321328
*/
322329
void merge_cmd(void){
323330
int vid; /* Current version "V" */
324331
int mid; /* Version we are merging from "M" */
@@ -337,11 +344,14 @@
337344
int showVfileFlag; /* True if the --show-vfile flag is present */
338345
int keepMergeFlag; /* True if --keep-merge-files is present */
339346
int nConflict = 0; /* Number of conflicts seen */
340347
int nOverwrite = 0; /* Number of unmanaged files overwritten */
341348
char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
342
- Stmt q;
349
+ const char *zVersion; /* The VERSION argument */
350
+ int bMultiMerge = 0; /* True if there are two or more VERSION arguments */
351
+ int nMerge = 0; /* Number of prior merges processed */
352
+ Stmt q; /* SQL statment used for merge processing */
343353
344354
345355
/* Notation:
346356
**
347357
** V The current check-out
@@ -355,20 +365,21 @@
355365
forceMissingFlag = find_option("force-missing",0,0)!=0;
356366
if( !verboseFlag ){
357367
verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
358368
}
359369
pickFlag = find_option("cherrypick",0,0)!=0;
360
- if('c'==*g.zCmdName/*called as cherry-pick, possibly a short form*/){
370
+ if('c'==*g.zCmdName /*called as cherrypick, possibly a short form*/){
361371
pickFlag = 1;
362372
}
363373
integrateFlag = find_option("integrate",0,0)!=0;
364374
backoutFlag = find_option("backout",0,0)!=0;
365375
zBinGlob = find_option("binary",0,1);
366376
dryRunFlag = find_option("dry-run","n",0)!=0;
367377
if( !dryRunFlag ){
368378
dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
369379
}
380
+ if( find_option("nosync",0,0) ) g.fNoSync = 1;
370381
forceFlag = find_option("force","f",0)!=0;
371382
zPivot = find_option("baseline",0,1);
372383
keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
373384
374385
/* Undocumented --debug and --show-vfile options:
@@ -401,17 +412,40 @@
401412
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, 1, "merge") ){
402413
fossil_fatal("merge abandoned due to sync failure");
403414
}
404415
}
405416
406
- /* Find mid, the artifactID of the version to be merged into the current
407
- ** check-out */
408
- if( g.argc==3 ){
417
+ /*
418
+ ** A "multi-merge" means two or more other check-ins are being merged
419
+ ** into the current check-in. In other words, there are two or more
420
+ ** VERSION arguments on the command-line. Multi-merge works by doing
421
+ ** the merges one by one, as long as there are no conflicts. At the
422
+ ** bottom of this routine, a jump is made back up to this point if there
423
+ ** are more merges yet to be done and no errors have yet been seen.
424
+ **
425
+ ** Related variables:
426
+ ** bMultiMerge True if there are one or more merges yet to do
427
+ ** zVersion The name of the current checking being merged in
428
+ ** nMerge Number of prior merges
429
+ */
430
+merge_next_child:
431
+
432
+ /* Find mid, the artifactID of the version to be merged into
433
+ ** the current check-out.
434
+ */
435
+ if( g.argc>=3 ){
436
+ int i;
409437
/* Mid is specified as an argument on the command-line */
410
- mid = name_to_typed_rid(g.argv[2], "ci");
438
+ zVersion = g.argv[2];
439
+ mid = name_to_typed_rid(zVersion, "ci");
411440
if( mid==0 || !is_a_version(mid) ){
412
- fossil_fatal("not a version: %s", g.argv[2]);
441
+ fossil_fatal("not a version: %s", zVersion);
442
+ }
443
+ bMultiMerge = g.argc>3;
444
+ if( bMultiMerge ){
445
+ for(i=3; i<g.argc; i++) g.argv[i-1] = g.argv[i];
446
+ g.argc--;
413447
}
414448
}else if( g.argc==2 ){
415449
/* No version specified on the command-line so pick the most recent
416450
** leaf that is (1) not the version currently checked out and (2)
417451
** has not already been merged into the current check-out and (3)
@@ -438,16 +472,18 @@
438472
" coalesce(euser, user)"
439473
" FROM event, blob"
440474
" WHERE event.objid=%d AND blob.rid=%d",
441475
mid, mid
442476
);
477
+ zVersion = 0;
443478
if( db_step(&q)==SQLITE_ROW ){
444479
char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
445480
db_column_text(&q, 0), db_column_text(&q, 1),
446481
db_column_text(&q, 3), db_column_text(&q, 2));
447482
comment_print(zCom, db_column_text(&q,2), 0, -1, get_comment_format());
448483
fossil_free(zCom);
484
+ zVersion = mprintf("%S",db_column_text(&q,0));
449485
}
450486
db_finalize(&q);
451487
}else{
452488
usage("?OPTIONS? ?VERSION?");
453489
return;
@@ -467,11 +503,11 @@
467503
fossil_fatal("incompatible options: --integrate and --cherrypick "
468504
"with --backout");
469505
}
470506
pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
471507
if( pid<=0 ){
472
- fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
508
+ fossil_fatal("cannot find an ancestor for %s", zVersion);
473509
}
474510
}else{
475511
if( !zPivot ){
476512
pivot_set_primary(mid);
477513
pivot_set_secondary(vid);
@@ -481,11 +517,11 @@
481517
}
482518
db_finalize(&q);
483519
pid = pivot_find(0);
484520
if( pid<=0 ){
485521
fossil_fatal("cannot find a common ancestor between the current "
486
- "check-out and %s", g.argv[2]);
522
+ "check-out and %s", zVersion);
487523
}
488524
}
489525
pivot_set_primary(mid);
490526
pivot_set_secondary(vid);
491527
nid = pivot_find(1);
@@ -508,27 +544,27 @@
508544
fossil_print("Merge skipped because it is a no-op. "
509545
" Use --force to override.\n");
510546
return;
511547
}
512548
if( integrateFlag && !is_a_leaf(mid)){
513
- fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
549
+ fossil_warning("ignoring --integrate: %s is not a leaf", zVersion);
514550
integrateFlag = 0;
515551
}
516552
if( integrateFlag && content_is_private(mid) ){
517553
fossil_warning(
518554
"ignoring --integrate: %s is on a private branch"
519555
"\n Use \"fossil amend --close\" (after commit) to close the leaf.",
520
- g.argv[2]);
556
+ zVersion);
521557
integrateFlag = 0;
522558
}
523559
if( verboseFlag ){
524560
print_checkin_description(mid, 12,
525561
integrateFlag ? "integrate:" : "merge-from:");
526562
print_checkin_description(pid, 12, "baseline:");
527563
}
528564
vfile_check_signature(vid, CKSIG_ENOTFILE);
529
- db_begin_transaction();
565
+ if( nMerge==0 ) db_begin_transaction();
530566
if( !dryRunFlag ) undo_begin();
531567
if( load_vfile_from_rid(mid) && !forceMissingFlag ){
532568
fossil_fatal("missing content, unable to merge");
533569
}
534570
if( load_vfile_from_rid(pid) && !forceMissingFlag ){
@@ -1014,16 +1050,30 @@
10141050
10151051
/* Report on conflicts
10161052
*/
10171053
if( nConflict ){
10181054
fossil_warning("WARNING: %d merge conflicts", nConflict);
1055
+ if( bMultiMerge ){
1056
+ int i;
1057
+ Blob msg;
1058
+ blob_init(&msg, 0, 0);
1059
+ blob_appendf(&msg,
1060
+ "The following %ss were not attempted due to prior conflicts:",
1061
+ pickFlag ? "cherrypick" : backoutFlag ? "backout" : "merge"
1062
+ );
1063
+ for(i=2; i<g.argc; i++){
1064
+ blob_appendf(&msg, " %s", g.argv[i]);
1065
+ }
1066
+ fossil_warning("%s", blob_str(&msg));
1067
+ blob_zero(&msg);
1068
+ }
10191069
}
10201070
if( nOverwrite ){
10211071
fossil_warning("WARNING: %d unmanaged files were overwritten",
10221072
nOverwrite);
10231073
}
1024
- if( dryRunFlag ){
1074
+ if( dryRunFlag && !bMultiMerge ){
10251075
fossil_warning("REMINDER: this was a dry run -"
10261076
" no files were actually changed.");
10271077
}
10281078
10291079
/*
@@ -1030,11 +1080,11 @@
10301080
** Clean up the mid and pid VFILE entries. Then commit the changes.
10311081
*/
10321082
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
10331083
if( pickFlag ){
10341084
vmerge_insert(-1, mid);
1035
- /* For a cherry-pick merge, make the default check-in comment the same
1085
+ /* For a cherrypick merge, make the default check-in comment the same
10361086
** as the check-in comment on the check-in that is being merged in. */
10371087
db_multi_exec(
10381088
"REPLACE INTO vvar(name,value)"
10391089
" SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
10401090
" WHERE type='ci' AND objid=%d",
@@ -1044,9 +1094,14 @@
10441094
vmerge_insert(-2, pid);
10451095
}else if( integrateFlag ){
10461096
vmerge_insert(-4, mid);
10471097
}else{
10481098
vmerge_insert(0, mid);
1099
+ }
1100
+ if( bMultiMerge && nConflict==0 ){
1101
+ nMerge++;
1102
+ goto merge_next_child;
10491103
}
10501104
if( !dryRunFlag ) undo_finish();
1105
+
10511106
db_end_transaction(dryRunFlag);
10521107
}
10531108
--- src/merge.c
+++ src/merge.c
@@ -274,28 +274,34 @@
274 }
275
276
277 /*
278 ** COMMAND: merge
279 ** COMMAND: cherry-pick
 
280 **
281 ** Usage: %fossil merge ?OPTIONS? ?VERSION?
 
282 **
283 ** The argument VERSION is a version that should be merged into the
284 ** current check-out. All changes from VERSION back to the nearest
285 ** common ancestor are merged. Except, if either of the --cherrypick
286 ** or --backout options are used only the changes associated with the
287 ** single check-in VERSION are merged. The --backout option causes
288 ** the changes associated with VERSION to be removed from the current
289 ** check-out rather than added. When invoked with the name
290 ** cherry-pick, this command works exactly like merge --cherrypick.
 
291 **
292 ** Files which are renamed in the merged-in branch will be renamed in
293 ** the current check-out.
294 **
295 ** If the VERSION argument is omitted, then Fossil attempts to find
296 ** a recent fork on the current branch to merge.
 
 
 
297 **
298 ** Options:
299 ** --backout Do a reverse cherrypick merge against VERSION.
300 ** In other words, back out the changes that were
301 ** added by VERSION.
@@ -315,10 +321,11 @@
315 ** --integrate Merged branch will be closed when committing
316 ** -K|--keep-merge-files On merge conflict, retain the temporary files
317 ** used for merging, named *-baseline, *-original,
318 ** and *-merge.
319 ** -n|--dry-run If given, display instead of run actions
 
320 ** -v|--verbose Show additional details of the merge
321 */
322 void merge_cmd(void){
323 int vid; /* Current version "V" */
324 int mid; /* Version we are merging from "M" */
@@ -337,11 +344,14 @@
337 int showVfileFlag; /* True if the --show-vfile flag is present */
338 int keepMergeFlag; /* True if --keep-merge-files is present */
339 int nConflict = 0; /* Number of conflicts seen */
340 int nOverwrite = 0; /* Number of unmanaged files overwritten */
341 char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
342 Stmt q;
 
 
 
343
344
345 /* Notation:
346 **
347 ** V The current check-out
@@ -355,20 +365,21 @@
355 forceMissingFlag = find_option("force-missing",0,0)!=0;
356 if( !verboseFlag ){
357 verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
358 }
359 pickFlag = find_option("cherrypick",0,0)!=0;
360 if('c'==*g.zCmdName/*called as cherry-pick, possibly a short form*/){
361 pickFlag = 1;
362 }
363 integrateFlag = find_option("integrate",0,0)!=0;
364 backoutFlag = find_option("backout",0,0)!=0;
365 zBinGlob = find_option("binary",0,1);
366 dryRunFlag = find_option("dry-run","n",0)!=0;
367 if( !dryRunFlag ){
368 dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
369 }
 
370 forceFlag = find_option("force","f",0)!=0;
371 zPivot = find_option("baseline",0,1);
372 keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
373
374 /* Undocumented --debug and --show-vfile options:
@@ -401,17 +412,40 @@
401 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, 1, "merge") ){
402 fossil_fatal("merge abandoned due to sync failure");
403 }
404 }
405
406 /* Find mid, the artifactID of the version to be merged into the current
407 ** check-out */
408 if( g.argc==3 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409 /* Mid is specified as an argument on the command-line */
410 mid = name_to_typed_rid(g.argv[2], "ci");
 
411 if( mid==0 || !is_a_version(mid) ){
412 fossil_fatal("not a version: %s", g.argv[2]);
 
 
 
 
 
413 }
414 }else if( g.argc==2 ){
415 /* No version specified on the command-line so pick the most recent
416 ** leaf that is (1) not the version currently checked out and (2)
417 ** has not already been merged into the current check-out and (3)
@@ -438,16 +472,18 @@
438 " coalesce(euser, user)"
439 " FROM event, blob"
440 " WHERE event.objid=%d AND blob.rid=%d",
441 mid, mid
442 );
 
443 if( db_step(&q)==SQLITE_ROW ){
444 char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
445 db_column_text(&q, 0), db_column_text(&q, 1),
446 db_column_text(&q, 3), db_column_text(&q, 2));
447 comment_print(zCom, db_column_text(&q,2), 0, -1, get_comment_format());
448 fossil_free(zCom);
 
449 }
450 db_finalize(&q);
451 }else{
452 usage("?OPTIONS? ?VERSION?");
453 return;
@@ -467,11 +503,11 @@
467 fossil_fatal("incompatible options: --integrate and --cherrypick "
468 "with --backout");
469 }
470 pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
471 if( pid<=0 ){
472 fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
473 }
474 }else{
475 if( !zPivot ){
476 pivot_set_primary(mid);
477 pivot_set_secondary(vid);
@@ -481,11 +517,11 @@
481 }
482 db_finalize(&q);
483 pid = pivot_find(0);
484 if( pid<=0 ){
485 fossil_fatal("cannot find a common ancestor between the current "
486 "check-out and %s", g.argv[2]);
487 }
488 }
489 pivot_set_primary(mid);
490 pivot_set_secondary(vid);
491 nid = pivot_find(1);
@@ -508,27 +544,27 @@
508 fossil_print("Merge skipped because it is a no-op. "
509 " Use --force to override.\n");
510 return;
511 }
512 if( integrateFlag && !is_a_leaf(mid)){
513 fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
514 integrateFlag = 0;
515 }
516 if( integrateFlag && content_is_private(mid) ){
517 fossil_warning(
518 "ignoring --integrate: %s is on a private branch"
519 "\n Use \"fossil amend --close\" (after commit) to close the leaf.",
520 g.argv[2]);
521 integrateFlag = 0;
522 }
523 if( verboseFlag ){
524 print_checkin_description(mid, 12,
525 integrateFlag ? "integrate:" : "merge-from:");
526 print_checkin_description(pid, 12, "baseline:");
527 }
528 vfile_check_signature(vid, CKSIG_ENOTFILE);
529 db_begin_transaction();
530 if( !dryRunFlag ) undo_begin();
531 if( load_vfile_from_rid(mid) && !forceMissingFlag ){
532 fossil_fatal("missing content, unable to merge");
533 }
534 if( load_vfile_from_rid(pid) && !forceMissingFlag ){
@@ -1014,16 +1050,30 @@
1014
1015 /* Report on conflicts
1016 */
1017 if( nConflict ){
1018 fossil_warning("WARNING: %d merge conflicts", nConflict);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1019 }
1020 if( nOverwrite ){
1021 fossil_warning("WARNING: %d unmanaged files were overwritten",
1022 nOverwrite);
1023 }
1024 if( dryRunFlag ){
1025 fossil_warning("REMINDER: this was a dry run -"
1026 " no files were actually changed.");
1027 }
1028
1029 /*
@@ -1030,11 +1080,11 @@
1030 ** Clean up the mid and pid VFILE entries. Then commit the changes.
1031 */
1032 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
1033 if( pickFlag ){
1034 vmerge_insert(-1, mid);
1035 /* For a cherry-pick merge, make the default check-in comment the same
1036 ** as the check-in comment on the check-in that is being merged in. */
1037 db_multi_exec(
1038 "REPLACE INTO vvar(name,value)"
1039 " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
1040 " WHERE type='ci' AND objid=%d",
@@ -1044,9 +1094,14 @@
1044 vmerge_insert(-2, pid);
1045 }else if( integrateFlag ){
1046 vmerge_insert(-4, mid);
1047 }else{
1048 vmerge_insert(0, mid);
 
 
 
 
1049 }
1050 if( !dryRunFlag ) undo_finish();
 
1051 db_end_transaction(dryRunFlag);
1052 }
1053
--- src/merge.c
+++ src/merge.c
@@ -274,28 +274,34 @@
274 }
275
276
277 /*
278 ** COMMAND: merge
279 ** COMMAND: cherry-pick alias
280 ** COMMAND: cherrypick
281 **
282 ** Usage: %fossil merge ?OPTIONS? ?VERSION ...?
283 ** Or: %fossil cherrypick ?OPTIONS? ?VERSION ...?
284 **
285 ** The argument VERSION is a version that should be merged into the
286 ** current check-out. All changes from VERSION back to the nearest
287 ** common ancestor are merged. Except, if either of the --cherrypick
288 ** or --backout options are used only the changes associated with the
289 ** single check-in VERSION are merged. The --backout option causes
290 ** the changes associated with VERSION to be removed from the current
291 ** check-out rather than added. When invoked with the name
292 ** "cherrypick" instead of "merge", this command works exactly like
293 ** "merge --cherrypick".
294 **
295 ** Files which are renamed in the merged-in branch will be renamed in
296 ** the current check-out.
297 **
298 ** If the VERSION argument is omitted, then Fossil attempts to find
299 ** a recent fork on the current branch to merge.
300 **
301 ** If there are multiple VERSION arguments, then each VERSION is merged
302 ** (or cherrypicked) in the order that they appear on the command-line.
303 **
304 ** Options:
305 ** --backout Do a reverse cherrypick merge against VERSION.
306 ** In other words, back out the changes that were
307 ** added by VERSION.
@@ -315,10 +321,11 @@
321 ** --integrate Merged branch will be closed when committing
322 ** -K|--keep-merge-files On merge conflict, retain the temporary files
323 ** used for merging, named *-baseline, *-original,
324 ** and *-merge.
325 ** -n|--dry-run If given, display instead of run actions
326 ** --nosync Do not auto-sync prior to merging
327 ** -v|--verbose Show additional details of the merge
328 */
329 void merge_cmd(void){
330 int vid; /* Current version "V" */
331 int mid; /* Version we are merging from "M" */
@@ -337,11 +344,14 @@
344 int showVfileFlag; /* True if the --show-vfile flag is present */
345 int keepMergeFlag; /* True if --keep-merge-files is present */
346 int nConflict = 0; /* Number of conflicts seen */
347 int nOverwrite = 0; /* Number of unmanaged files overwritten */
348 char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
349 const char *zVersion; /* The VERSION argument */
350 int bMultiMerge = 0; /* True if there are two or more VERSION arguments */
351 int nMerge = 0; /* Number of prior merges processed */
352 Stmt q; /* SQL statment used for merge processing */
353
354
355 /* Notation:
356 **
357 ** V The current check-out
@@ -355,20 +365,21 @@
365 forceMissingFlag = find_option("force-missing",0,0)!=0;
366 if( !verboseFlag ){
367 verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
368 }
369 pickFlag = find_option("cherrypick",0,0)!=0;
370 if('c'==*g.zCmdName /*called as cherrypick, possibly a short form*/){
371 pickFlag = 1;
372 }
373 integrateFlag = find_option("integrate",0,0)!=0;
374 backoutFlag = find_option("backout",0,0)!=0;
375 zBinGlob = find_option("binary",0,1);
376 dryRunFlag = find_option("dry-run","n",0)!=0;
377 if( !dryRunFlag ){
378 dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
379 }
380 if( find_option("nosync",0,0) ) g.fNoSync = 1;
381 forceFlag = find_option("force","f",0)!=0;
382 zPivot = find_option("baseline",0,1);
383 keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
384
385 /* Undocumented --debug and --show-vfile options:
@@ -401,17 +412,40 @@
412 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, 1, "merge") ){
413 fossil_fatal("merge abandoned due to sync failure");
414 }
415 }
416
417 /*
418 ** A "multi-merge" means two or more other check-ins are being merged
419 ** into the current check-in. In other words, there are two or more
420 ** VERSION arguments on the command-line. Multi-merge works by doing
421 ** the merges one by one, as long as there are no conflicts. At the
422 ** bottom of this routine, a jump is made back up to this point if there
423 ** are more merges yet to be done and no errors have yet been seen.
424 **
425 ** Related variables:
426 ** bMultiMerge True if there are one or more merges yet to do
427 ** zVersion The name of the current checking being merged in
428 ** nMerge Number of prior merges
429 */
430 merge_next_child:
431
432 /* Find mid, the artifactID of the version to be merged into
433 ** the current check-out.
434 */
435 if( g.argc>=3 ){
436 int i;
437 /* Mid is specified as an argument on the command-line */
438 zVersion = g.argv[2];
439 mid = name_to_typed_rid(zVersion, "ci");
440 if( mid==0 || !is_a_version(mid) ){
441 fossil_fatal("not a version: %s", zVersion);
442 }
443 bMultiMerge = g.argc>3;
444 if( bMultiMerge ){
445 for(i=3; i<g.argc; i++) g.argv[i-1] = g.argv[i];
446 g.argc--;
447 }
448 }else if( g.argc==2 ){
449 /* No version specified on the command-line so pick the most recent
450 ** leaf that is (1) not the version currently checked out and (2)
451 ** has not already been merged into the current check-out and (3)
@@ -438,16 +472,18 @@
472 " coalesce(euser, user)"
473 " FROM event, blob"
474 " WHERE event.objid=%d AND blob.rid=%d",
475 mid, mid
476 );
477 zVersion = 0;
478 if( db_step(&q)==SQLITE_ROW ){
479 char *zCom = mprintf("Merging fork [%S] at %s by %s: \"%s\"",
480 db_column_text(&q, 0), db_column_text(&q, 1),
481 db_column_text(&q, 3), db_column_text(&q, 2));
482 comment_print(zCom, db_column_text(&q,2), 0, -1, get_comment_format());
483 fossil_free(zCom);
484 zVersion = mprintf("%S",db_column_text(&q,0));
485 }
486 db_finalize(&q);
487 }else{
488 usage("?OPTIONS? ?VERSION?");
489 return;
@@ -467,11 +503,11 @@
503 fossil_fatal("incompatible options: --integrate and --cherrypick "
504 "with --backout");
505 }
506 pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
507 if( pid<=0 ){
508 fossil_fatal("cannot find an ancestor for %s", zVersion);
509 }
510 }else{
511 if( !zPivot ){
512 pivot_set_primary(mid);
513 pivot_set_secondary(vid);
@@ -481,11 +517,11 @@
517 }
518 db_finalize(&q);
519 pid = pivot_find(0);
520 if( pid<=0 ){
521 fossil_fatal("cannot find a common ancestor between the current "
522 "check-out and %s", zVersion);
523 }
524 }
525 pivot_set_primary(mid);
526 pivot_set_secondary(vid);
527 nid = pivot_find(1);
@@ -508,27 +544,27 @@
544 fossil_print("Merge skipped because it is a no-op. "
545 " Use --force to override.\n");
546 return;
547 }
548 if( integrateFlag && !is_a_leaf(mid)){
549 fossil_warning("ignoring --integrate: %s is not a leaf", zVersion);
550 integrateFlag = 0;
551 }
552 if( integrateFlag && content_is_private(mid) ){
553 fossil_warning(
554 "ignoring --integrate: %s is on a private branch"
555 "\n Use \"fossil amend --close\" (after commit) to close the leaf.",
556 zVersion);
557 integrateFlag = 0;
558 }
559 if( verboseFlag ){
560 print_checkin_description(mid, 12,
561 integrateFlag ? "integrate:" : "merge-from:");
562 print_checkin_description(pid, 12, "baseline:");
563 }
564 vfile_check_signature(vid, CKSIG_ENOTFILE);
565 if( nMerge==0 ) db_begin_transaction();
566 if( !dryRunFlag ) undo_begin();
567 if( load_vfile_from_rid(mid) && !forceMissingFlag ){
568 fossil_fatal("missing content, unable to merge");
569 }
570 if( load_vfile_from_rid(pid) && !forceMissingFlag ){
@@ -1014,16 +1050,30 @@
1050
1051 /* Report on conflicts
1052 */
1053 if( nConflict ){
1054 fossil_warning("WARNING: %d merge conflicts", nConflict);
1055 if( bMultiMerge ){
1056 int i;
1057 Blob msg;
1058 blob_init(&msg, 0, 0);
1059 blob_appendf(&msg,
1060 "The following %ss were not attempted due to prior conflicts:",
1061 pickFlag ? "cherrypick" : backoutFlag ? "backout" : "merge"
1062 );
1063 for(i=2; i<g.argc; i++){
1064 blob_appendf(&msg, " %s", g.argv[i]);
1065 }
1066 fossil_warning("%s", blob_str(&msg));
1067 blob_zero(&msg);
1068 }
1069 }
1070 if( nOverwrite ){
1071 fossil_warning("WARNING: %d unmanaged files were overwritten",
1072 nOverwrite);
1073 }
1074 if( dryRunFlag && !bMultiMerge ){
1075 fossil_warning("REMINDER: this was a dry run -"
1076 " no files were actually changed.");
1077 }
1078
1079 /*
@@ -1030,11 +1080,11 @@
1080 ** Clean up the mid and pid VFILE entries. Then commit the changes.
1081 */
1082 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
1083 if( pickFlag ){
1084 vmerge_insert(-1, mid);
1085 /* For a cherrypick merge, make the default check-in comment the same
1086 ** as the check-in comment on the check-in that is being merged in. */
1087 db_multi_exec(
1088 "REPLACE INTO vvar(name,value)"
1089 " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
1090 " WHERE type='ci' AND objid=%d",
@@ -1044,9 +1094,14 @@
1094 vmerge_insert(-2, pid);
1095 }else if( integrateFlag ){
1096 vmerge_insert(-4, mid);
1097 }else{
1098 vmerge_insert(0, mid);
1099 }
1100 if( bMultiMerge && nConflict==0 ){
1101 nMerge++;
1102 goto merge_next_child;
1103 }
1104 if( !dryRunFlag ) undo_finish();
1105
1106 db_end_transaction(dryRunFlag);
1107 }
1108
+10 -3
--- src/path.c
+++ src/path.c
@@ -468,10 +468,18 @@
468468
if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
469469
/* Skip nodes where the parent is not on the path */
470470
continue;
471471
}
472472
db_bind_int(&q1, ":mid", p->rid);
473
+ if( zDebug ){
474
+ fossil_print("%s check-in %.16z %z rid %d\n",
475
+ zDebug,
476
+ db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
477
+ db_text(0, "SELECT date(mtime) FROM event WHERE objid=%d", p->rid),
478
+ p->rid
479
+ );
480
+ }
473481
while( db_step(&q1)==SQLITE_ROW ){
474482
fnid = db_column_int(&q1, 1);
475483
pfnid = db_column_int(&q1, 0);
476484
if( pfnid==0 ){
477485
pfnid = fnid;
@@ -481,13 +489,12 @@
481489
int t = fnid;
482490
fnid = pfnid;
483491
pfnid = t;
484492
}
485493
if( zDebug ){
486
- fossil_print("%s at %d%s %.10z: %d[%z] -> %d[%z]\n",
487
- zDebug, p->rid, p->fromIsParent ? ">" : "<",
488
- db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
494
+ fossil_print("%s %d[%z] -> %d[%z]\n",
495
+ zDebug,
489496
pfnid,
490497
db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
491498
fnid,
492499
db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
493500
}
494501
--- src/path.c
+++ src/path.c
@@ -468,10 +468,18 @@
468 if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
469 /* Skip nodes where the parent is not on the path */
470 continue;
471 }
472 db_bind_int(&q1, ":mid", p->rid);
 
 
 
 
 
 
 
 
473 while( db_step(&q1)==SQLITE_ROW ){
474 fnid = db_column_int(&q1, 1);
475 pfnid = db_column_int(&q1, 0);
476 if( pfnid==0 ){
477 pfnid = fnid;
@@ -481,13 +489,12 @@
481 int t = fnid;
482 fnid = pfnid;
483 pfnid = t;
484 }
485 if( zDebug ){
486 fossil_print("%s at %d%s %.10z: %d[%z] -> %d[%z]\n",
487 zDebug, p->rid, p->fromIsParent ? ">" : "<",
488 db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
489 pfnid,
490 db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
491 fnid,
492 db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
493 }
494
--- src/path.c
+++ src/path.c
@@ -468,10 +468,18 @@
468 if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
469 /* Skip nodes where the parent is not on the path */
470 continue;
471 }
472 db_bind_int(&q1, ":mid", p->rid);
473 if( zDebug ){
474 fossil_print("%s check-in %.16z %z rid %d\n",
475 zDebug,
476 db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
477 db_text(0, "SELECT date(mtime) FROM event WHERE objid=%d", p->rid),
478 p->rid
479 );
480 }
481 while( db_step(&q1)==SQLITE_ROW ){
482 fnid = db_column_int(&q1, 1);
483 pfnid = db_column_int(&q1, 0);
484 if( pfnid==0 ){
485 pfnid = fnid;
@@ -481,13 +489,12 @@
489 int t = fnid;
490 fnid = pfnid;
491 pfnid = t;
492 }
493 if( zDebug ){
494 fossil_print("%s %d[%z] -> %d[%z]\n",
495 zDebug,
 
496 pfnid,
497 db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
498 fnid,
499 db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
500 }
501
--- src/rebuild.c
+++ src/rebuild.c
@@ -140,10 +140,15 @@
140140
}
141141
142142
/* Do the fossil-2.0 updates to the schema. (2017-02-28)
143143
*/
144144
rebuild_schema_update_2_0();
145
+
146
+ /* Add the user.jx and reportfmt.jx columns if they are missing. (2022-11-18)
147
+ */
148
+ user_update_user_table();
149
+ report_update_reportfmt_table();
145150
}
146151
147152
/*
148153
** Update the repository schema for Fossil version 2.0. (2017-02-28)
149154
** (1) Change the CHECK constraint on BLOB.UUID so that the length
150155
--- src/rebuild.c
+++ src/rebuild.c
@@ -140,10 +140,15 @@
140 }
141
142 /* Do the fossil-2.0 updates to the schema. (2017-02-28)
143 */
144 rebuild_schema_update_2_0();
 
 
 
 
 
145 }
146
147 /*
148 ** Update the repository schema for Fossil version 2.0. (2017-02-28)
149 ** (1) Change the CHECK constraint on BLOB.UUID so that the length
150
--- src/rebuild.c
+++ src/rebuild.c
@@ -140,10 +140,15 @@
140 }
141
142 /* Do the fossil-2.0 updates to the schema. (2017-02-28)
143 */
144 rebuild_schema_update_2_0();
145
146 /* Add the user.jx and reportfmt.jx columns if they are missing. (2022-11-18)
147 */
148 user_update_user_table();
149 report_update_reportfmt_table();
150 }
151
152 /*
153 ** Update the repository schema for Fossil version 2.0. (2017-02-28)
154 ** (1) Change the CHECK constraint on BLOB.UUID so that the length
155
+2 -1
--- src/regexp.c
+++ src/regexp.c
@@ -711,11 +711,12 @@
711711
zPattern = (const char*)sqlite3_value_text(argv[0]);
712712
if( zPattern==0 ) return;
713713
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
714714
if( zErr ){
715715
re_free(pRe);
716
- sqlite3_result_error(context, zErr, -1);
716
+ sqlite3_result_int(context, 0);
717
+ /* sqlite3_result_error(context, zErr, -1); */
717718
return;
718719
}
719720
if( pRe==0 ){
720721
sqlite3_result_error_nomem(context);
721722
return;
722723
--- src/regexp.c
+++ src/regexp.c
@@ -711,11 +711,12 @@
711 zPattern = (const char*)sqlite3_value_text(argv[0]);
712 if( zPattern==0 ) return;
713 zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
714 if( zErr ){
715 re_free(pRe);
716 sqlite3_result_error(context, zErr, -1);
 
717 return;
718 }
719 if( pRe==0 ){
720 sqlite3_result_error_nomem(context);
721 return;
722
--- src/regexp.c
+++ src/regexp.c
@@ -711,11 +711,12 @@
711 zPattern = (const char*)sqlite3_value_text(argv[0]);
712 if( zPattern==0 ) return;
713 zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
714 if( zErr ){
715 re_free(pRe);
716 sqlite3_result_int(context, 0);
717 /* sqlite3_result_error(context, zErr, -1); */
718 return;
719 }
720 if( pRe==0 ){
721 sqlite3_result_error_nomem(context);
722 return;
723
+47 -13
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975975
}
976976
#else
977977
sqlite3_result_double(context, r);
978978
#endif
979979
}
980
+
981
+/*
982
+** Expects a search pattern string. Makes a copy of the string,
983
+** replaces all non-alphanum ASCII characters with a space, and
984
+** lower-cases all upper-case ASCII characters. The intent is to avoid
985
+** causing errors in FTS5 searches with inputs which contain AND, OR,
986
+** and symbols like #. The caller is responsible for passing the
987
+** result to fossil_free().
988
+*/
989
+char *search_simplify_pattern(const char * zPattern){
990
+ char *zPat = mprintf("%s",zPattern);
991
+ int i;
992
+ for(i=0; zPat[i]; i++){
993
+ if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
994
+ if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
995
+ }
996
+ for(i--; i>=0 && zPat[i]==' '; i--){}
997
+ if( i<0 ){
998
+ fossil_free(zPat);
999
+ zPat = mprintf("\"\"");
1000
+ }
1001
+ return zPat;
1002
+}
9801003
9811004
/*
9821005
** When this routine is called, there already exists a table
9831006
**
9841007
** x(label,url,score,id,snip).
@@ -997,19 +1020,16 @@
9971020
LOCAL void search_indexed(
9981021
const char *zPattern, /* The query pattern */
9991022
unsigned int srchFlags /* What to search over */
10001023
){
10011024
Blob sql;
1002
- char *zPat = mprintf("%s",zPattern);
1003
- int i;
1025
+ char *zPat;
10041026
static const char *zSnippetCall;
10051027
if( srchFlags==0 ) return;
10061028
sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
10071029
search_rank_sqlfunc, 0, 0);
1008
- for(i=0; zPat[i]; i++){
1009
- if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
1010
- }
1030
+ zPat = search_simplify_pattern(zPattern);
10111031
blob_init(&sql, 0, 0);
10121032
if( search_index_type(0)==4 ){
10131033
/* If this repo is still using the legacy FTS4 search index, then
10141034
** the snippet() function is slightly different */
10151035
zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
@@ -1631,10 +1651,11 @@
16311651
;
16321652
static const char zFtsDrop[] =
16331653
@ DROP TABLE IF EXISTS repository.ftsidx;
16341654
@ DROP VIEW IF EXISTS repository.ftscontent;
16351655
@ DROP TABLE IF EXISTS repository.ftsdocs;
1656
+@ DROP TABLE IF EXISTS repository.chatfts1;
16361657
;
16371658
16381659
#if INTERFACE
16391660
/*
16401661
** Values for the search-tokenizer config option.
@@ -1675,10 +1696,25 @@
16751696
iFtsTokenizer = is_truth(z) ? FTS5TOK_PORTER : FTS5TOK_NONE;
16761697
}
16771698
fossil_free(z);
16781699
return iFtsTokenizer;
16791700
}
1701
+
1702
+/*
1703
+** Returns a string in the form ",tokenize=X", where X is the string
1704
+** counterpart of the given FTS5TOK_xyz value. Returns "" if tokType
1705
+** does not correspond to a known FTS5 tokenizer.
1706
+*/
1707
+const char * search_tokenize_arg_for_type(int tokType){
1708
+ switch( tokType ){
1709
+ case FTS5TOK_PORTER: return ",tokenize=porter";
1710
+ case FTS5TOK_UNICODE61: return ",tokenize=unicode61";
1711
+ case FTS5TOK_TRIGRAM: return ",tokenize=trigram";
1712
+ case FTS5TOK_NONE:
1713
+ default: return "";
1714
+ }
1715
+}
16801716
16811717
/*
16821718
** Returns a string value suitable for use as the search-tokenizer
16831719
** setting's value, depending on the value of z. If z is 0 then the
16841720
** current search-tokenizer value is used as the basis for formulating
@@ -1720,18 +1756,13 @@
17201756
/*
17211757
** Create or drop the tables associated with a full-text index.
17221758
*/
17231759
static int searchIdxExists = -1;
17241760
void search_create_index(void){
1725
- const int useTokenizer = search_tokenizer_type(0);
1726
- const char *zExtra;
1727
- switch(useTokenizer){
1728
- case FTS5TOK_PORTER: zExtra = ",tokenize=porter"; break;
1729
- case FTS5TOK_UNICODE61: zExtra = ",tokenize=unicode61"; break;
1730
- case FTS5TOK_TRIGRAM: zExtra = ",tokenize=trigram"; break;
1731
- default: zExtra = ""; break;
1732
- }
1761
+ const char *zExtra =
1762
+ search_tokenize_arg_for_type(search_tokenizer_type(0));
1763
+ assert( zExtra );
17331764
search_sql_setup(g.db);
17341765
db_multi_exec(zFtsSchema/*works-like:"%s"*/, zExtra/*safe-for-%s*/);
17351766
searchIdxExists = 1;
17361767
}
17371768
void search_drop_index(void){
@@ -2051,10 +2082,13 @@
20512082
fossil_print("rebuilding the search index...");
20522083
fflush(stdout);
20532084
search_create_index();
20542085
search_fill_index();
20552086
search_update_index(search_restrict(SRCH_ALL));
2087
+ if( db_table_exists("repository","chat") ){
2088
+ chat_rebuild_index(1);
2089
+ }
20562090
fossil_print(" done\n");
20572091
}
20582092
20592093
/*
20602094
** COMMAND: fts-config*
20612095
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975 }
976 #else
977 sqlite3_result_double(context, r);
978 #endif
979 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
980
981 /*
982 ** When this routine is called, there already exists a table
983 **
984 ** x(label,url,score,id,snip).
@@ -997,19 +1020,16 @@
997 LOCAL void search_indexed(
998 const char *zPattern, /* The query pattern */
999 unsigned int srchFlags /* What to search over */
1000 ){
1001 Blob sql;
1002 char *zPat = mprintf("%s",zPattern);
1003 int i;
1004 static const char *zSnippetCall;
1005 if( srchFlags==0 ) return;
1006 sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1007 search_rank_sqlfunc, 0, 0);
1008 for(i=0; zPat[i]; i++){
1009 if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
1010 }
1011 blob_init(&sql, 0, 0);
1012 if( search_index_type(0)==4 ){
1013 /* If this repo is still using the legacy FTS4 search index, then
1014 ** the snippet() function is slightly different */
1015 zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
@@ -1631,10 +1651,11 @@
1631 ;
1632 static const char zFtsDrop[] =
1633 @ DROP TABLE IF EXISTS repository.ftsidx;
1634 @ DROP VIEW IF EXISTS repository.ftscontent;
1635 @ DROP TABLE IF EXISTS repository.ftsdocs;
 
1636 ;
1637
1638 #if INTERFACE
1639 /*
1640 ** Values for the search-tokenizer config option.
@@ -1675,10 +1696,25 @@
1675 iFtsTokenizer = is_truth(z) ? FTS5TOK_PORTER : FTS5TOK_NONE;
1676 }
1677 fossil_free(z);
1678 return iFtsTokenizer;
1679 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1680
1681 /*
1682 ** Returns a string value suitable for use as the search-tokenizer
1683 ** setting's value, depending on the value of z. If z is 0 then the
1684 ** current search-tokenizer value is used as the basis for formulating
@@ -1720,18 +1756,13 @@
1720 /*
1721 ** Create or drop the tables associated with a full-text index.
1722 */
1723 static int searchIdxExists = -1;
1724 void search_create_index(void){
1725 const int useTokenizer = search_tokenizer_type(0);
1726 const char *zExtra;
1727 switch(useTokenizer){
1728 case FTS5TOK_PORTER: zExtra = ",tokenize=porter"; break;
1729 case FTS5TOK_UNICODE61: zExtra = ",tokenize=unicode61"; break;
1730 case FTS5TOK_TRIGRAM: zExtra = ",tokenize=trigram"; break;
1731 default: zExtra = ""; break;
1732 }
1733 search_sql_setup(g.db);
1734 db_multi_exec(zFtsSchema/*works-like:"%s"*/, zExtra/*safe-for-%s*/);
1735 searchIdxExists = 1;
1736 }
1737 void search_drop_index(void){
@@ -2051,10 +2082,13 @@
2051 fossil_print("rebuilding the search index...");
2052 fflush(stdout);
2053 search_create_index();
2054 search_fill_index();
2055 search_update_index(search_restrict(SRCH_ALL));
 
 
 
2056 fossil_print(" done\n");
2057 }
2058
2059 /*
2060 ** COMMAND: fts-config*
2061
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975 }
976 #else
977 sqlite3_result_double(context, r);
978 #endif
979 }
980
981 /*
982 ** Expects a search pattern string. Makes a copy of the string,
983 ** replaces all non-alphanum ASCII characters with a space, and
984 ** lower-cases all upper-case ASCII characters. The intent is to avoid
985 ** causing errors in FTS5 searches with inputs which contain AND, OR,
986 ** and symbols like #. The caller is responsible for passing the
987 ** result to fossil_free().
988 */
989 char *search_simplify_pattern(const char * zPattern){
990 char *zPat = mprintf("%s",zPattern);
991 int i;
992 for(i=0; zPat[i]; i++){
993 if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
994 if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
995 }
996 for(i--; i>=0 && zPat[i]==' '; i--){}
997 if( i<0 ){
998 fossil_free(zPat);
999 zPat = mprintf("\"\"");
1000 }
1001 return zPat;
1002 }
1003
1004 /*
1005 ** When this routine is called, there already exists a table
1006 **
1007 ** x(label,url,score,id,snip).
@@ -997,19 +1020,16 @@
1020 LOCAL void search_indexed(
1021 const char *zPattern, /* The query pattern */
1022 unsigned int srchFlags /* What to search over */
1023 ){
1024 Blob sql;
1025 char *zPat;
 
1026 static const char *zSnippetCall;
1027 if( srchFlags==0 ) return;
1028 sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1029 search_rank_sqlfunc, 0, 0);
1030 zPat = search_simplify_pattern(zPattern);
 
 
1031 blob_init(&sql, 0, 0);
1032 if( search_index_type(0)==4 ){
1033 /* If this repo is still using the legacy FTS4 search index, then
1034 ** the snippet() function is slightly different */
1035 zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
@@ -1631,10 +1651,11 @@
1651 ;
1652 static const char zFtsDrop[] =
1653 @ DROP TABLE IF EXISTS repository.ftsidx;
1654 @ DROP VIEW IF EXISTS repository.ftscontent;
1655 @ DROP TABLE IF EXISTS repository.ftsdocs;
1656 @ DROP TABLE IF EXISTS repository.chatfts1;
1657 ;
1658
1659 #if INTERFACE
1660 /*
1661 ** Values for the search-tokenizer config option.
@@ -1675,10 +1696,25 @@
1696 iFtsTokenizer = is_truth(z) ? FTS5TOK_PORTER : FTS5TOK_NONE;
1697 }
1698 fossil_free(z);
1699 return iFtsTokenizer;
1700 }
1701
1702 /*
1703 ** Returns a string in the form ",tokenize=X", where X is the string
1704 ** counterpart of the given FTS5TOK_xyz value. Returns "" if tokType
1705 ** does not correspond to a known FTS5 tokenizer.
1706 */
1707 const char * search_tokenize_arg_for_type(int tokType){
1708 switch( tokType ){
1709 case FTS5TOK_PORTER: return ",tokenize=porter";
1710 case FTS5TOK_UNICODE61: return ",tokenize=unicode61";
1711 case FTS5TOK_TRIGRAM: return ",tokenize=trigram";
1712 case FTS5TOK_NONE:
1713 default: return "";
1714 }
1715 }
1716
1717 /*
1718 ** Returns a string value suitable for use as the search-tokenizer
1719 ** setting's value, depending on the value of z. If z is 0 then the
1720 ** current search-tokenizer value is used as the basis for formulating
@@ -1720,18 +1756,13 @@
1756 /*
1757 ** Create or drop the tables associated with a full-text index.
1758 */
1759 static int searchIdxExists = -1;
1760 void search_create_index(void){
1761 const char *zExtra =
1762 search_tokenize_arg_for_type(search_tokenizer_type(0));
1763 assert( zExtra );
 
 
 
 
 
1764 search_sql_setup(g.db);
1765 db_multi_exec(zFtsSchema/*works-like:"%s"*/, zExtra/*safe-for-%s*/);
1766 searchIdxExists = 1;
1767 }
1768 void search_drop_index(void){
@@ -2051,10 +2082,13 @@
2082 fossil_print("rebuilding the search index...");
2083 fflush(stdout);
2084 search_create_index();
2085 search_fill_index();
2086 search_update_index(search_restrict(SRCH_ALL));
2087 if( db_table_exists("repository","chat") ){
2088 chat_rebuild_index(1);
2089 }
2090 fossil_print(" done\n");
2091 }
2092
2093 /*
2094 ** COMMAND: fts-config*
2095
--- src/security_audit.c
+++ src/security_audit.c
@@ -803,10 +803,11 @@
803803
style_header("Server Error Log");
804804
style_submenu_element("Test", "%R/test-warning");
805805
style_submenu_element("Refresh", "%R/errorlog");
806806
style_submenu_element("Log-Menu", "%R/setup-logmenu");
807807
style_submenu_element("Panics", "%R/paniclog");
808
+ style_submenu_element("Non-Hacks", "%R/hacklog?not");
808809
809810
if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
810811
no_error_log_available();
811812
style_finish_page();
812813
return;
@@ -904,10 +905,78 @@
904905
@ <pre>
905906
while( fgets(z, sizeof(z), in) ){
906907
if( prevWasTime
907908
&& (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0)
908909
){
910
+ @ %h(zTime)\
911
+ bOutput = 1;
912
+ }
913
+ if( strncmp(z, "--------", 8)==0 ){
914
+ size_t n = strlen(z);
915
+ memcpy(zTime, z, n+1);
916
+ prevWasTime = 1;
917
+ bOutput = 0;
918
+ }else{
919
+ prevWasTime = 0;
920
+ }
921
+ if( bOutput ){
922
+ @ %h(z)\
923
+ }
924
+ }
925
+ fclose(in);
926
+ @ </pre>
927
+ style_finish_page();
928
+}
929
+
930
+/*
931
+** WEBPAGE: hacklog
932
+**
933
+** Scan the error log for "possible hack attempt" entries Show hack
934
+** attempt messages only, omitting all others. Or if the "not" query
935
+** parameter is present, show only messages that are not hack attempts.
936
+*/
937
+void hacklog_page(void){
938
+ i64 szFile;
939
+ char *zLog;
940
+ FILE *in;
941
+ int bOutput = 0;
942
+ int prevWasTime = 0;
943
+ int isNot = P("not")!=0;
944
+ char z[10000];
945
+ char zTime[10000];
946
+
947
+ login_check_credentials();
948
+ if( !g.perm.Admin ){
949
+ login_needed(0);
950
+ return;
951
+ }
952
+ style_header("Server Hack Log");
953
+ style_submenu_element("Log-Menu", "%R/setup-logmenu");
954
+
955
+ if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
956
+ no_error_log_available();
957
+ style_finish_page();
958
+ return;
959
+ }
960
+ in = fossil_fopen(g.zErrlog, "rb");
961
+ if( in==0 ){
962
+ @ <p class='generalError'>Unable to open that file for reading!</p>
963
+ style_finish_page();
964
+ return;
965
+ }
966
+ szFile = file_size(g.zErrlog, ExtFILE);
967
+ zLog = file_canonical_name_dup(g.zErrlog);
968
+ @ %s(isNot?"Non-hack":"Hack") messages contained within the %lld(szFile)-byte
969
+ @ <a href="%R/errorlog?all">error log</a> found at
970
+ @ "%h(zLog)".
971
+ fossil_free(zLog);
972
+ @ <hr>
973
+ @ <pre>
974
+ while( fgets(z, sizeof(z), in) ){
975
+ if( prevWasTime
976
+ && ((strncmp(z,"possible hack attempt - 418 ", 27)==0) ^ isNot)
977
+ ){
909978
@ %h(zTime)\
910979
bOutput = 1;
911980
}
912981
if( strncmp(z, "--------", 8)==0 ){
913982
size_t n = strlen(z);
914983
--- src/security_audit.c
+++ src/security_audit.c
@@ -803,10 +803,11 @@
803 style_header("Server Error Log");
804 style_submenu_element("Test", "%R/test-warning");
805 style_submenu_element("Refresh", "%R/errorlog");
806 style_submenu_element("Log-Menu", "%R/setup-logmenu");
807 style_submenu_element("Panics", "%R/paniclog");
 
808
809 if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
810 no_error_log_available();
811 style_finish_page();
812 return;
@@ -904,10 +905,78 @@
904 @ <pre>
905 while( fgets(z, sizeof(z), in) ){
906 if( prevWasTime
907 && (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0)
908 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909 @ %h(zTime)\
910 bOutput = 1;
911 }
912 if( strncmp(z, "--------", 8)==0 ){
913 size_t n = strlen(z);
914
--- src/security_audit.c
+++ src/security_audit.c
@@ -803,10 +803,11 @@
803 style_header("Server Error Log");
804 style_submenu_element("Test", "%R/test-warning");
805 style_submenu_element("Refresh", "%R/errorlog");
806 style_submenu_element("Log-Menu", "%R/setup-logmenu");
807 style_submenu_element("Panics", "%R/paniclog");
808 style_submenu_element("Non-Hacks", "%R/hacklog?not");
809
810 if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
811 no_error_log_available();
812 style_finish_page();
813 return;
@@ -904,10 +905,78 @@
905 @ <pre>
906 while( fgets(z, sizeof(z), in) ){
907 if( prevWasTime
908 && (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0)
909 ){
910 @ %h(zTime)\
911 bOutput = 1;
912 }
913 if( strncmp(z, "--------", 8)==0 ){
914 size_t n = strlen(z);
915 memcpy(zTime, z, n+1);
916 prevWasTime = 1;
917 bOutput = 0;
918 }else{
919 prevWasTime = 0;
920 }
921 if( bOutput ){
922 @ %h(z)\
923 }
924 }
925 fclose(in);
926 @ </pre>
927 style_finish_page();
928 }
929
930 /*
931 ** WEBPAGE: hacklog
932 **
933 ** Scan the error log for "possible hack attempt" entries Show hack
934 ** attempt messages only, omitting all others. Or if the "not" query
935 ** parameter is present, show only messages that are not hack attempts.
936 */
937 void hacklog_page(void){
938 i64 szFile;
939 char *zLog;
940 FILE *in;
941 int bOutput = 0;
942 int prevWasTime = 0;
943 int isNot = P("not")!=0;
944 char z[10000];
945 char zTime[10000];
946
947 login_check_credentials();
948 if( !g.perm.Admin ){
949 login_needed(0);
950 return;
951 }
952 style_header("Server Hack Log");
953 style_submenu_element("Log-Menu", "%R/setup-logmenu");
954
955 if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
956 no_error_log_available();
957 style_finish_page();
958 return;
959 }
960 in = fossil_fopen(g.zErrlog, "rb");
961 if( in==0 ){
962 @ <p class='generalError'>Unable to open that file for reading!</p>
963 style_finish_page();
964 return;
965 }
966 szFile = file_size(g.zErrlog, ExtFILE);
967 zLog = file_canonical_name_dup(g.zErrlog);
968 @ %s(isNot?"Non-hack":"Hack") messages contained within the %lld(szFile)-byte
969 @ <a href="%R/errorlog?all">error log</a> found at
970 @ "%h(zLog)".
971 fossil_free(zLog);
972 @ <hr>
973 @ <pre>
974 while( fgets(z, sizeof(z), in) ){
975 if( prevWasTime
976 && ((strncmp(z,"possible hack attempt - 418 ", 27)==0) ^ isNot)
977 ){
978 @ %h(zTime)\
979 bOutput = 1;
980 }
981 if( strncmp(z, "--------", 8)==0 ){
982 size_t n = strlen(z);
983
--- src/setup.c
+++ src/setup.c
@@ -235,10 +235,19 @@
235235
236236
setup_menu_entry("User Log", "user_log",
237237
"The user log is a record of login attempts. The user log is stored\n"
238238
"in the \"accesslog\" table of the respository.\n"
239239
);
240
+
241
+ setup_menu_entry("Hack Log", "hacklog",
242
+ "All 418 hack attempts"
243
+ );
244
+
245
+ setup_menu_entry("Non-Hack Log", "hacklog?not",
246
+ "All log messages that are not hack attempts"
247
+ );
248
+
240249
241250
@ </table>
242251
style_finish_page();
243252
}
244253
245254
--- src/setup.c
+++ src/setup.c
@@ -235,10 +235,19 @@
235
236 setup_menu_entry("User Log", "user_log",
237 "The user log is a record of login attempts. The user log is stored\n"
238 "in the \"accesslog\" table of the respository.\n"
239 );
 
 
 
 
 
 
 
 
 
240
241 @ </table>
242 style_finish_page();
243 }
244
245
--- src/setup.c
+++ src/setup.c
@@ -235,10 +235,19 @@
235
236 setup_menu_entry("User Log", "user_log",
237 "The user log is a record of login attempts. The user log is stored\n"
238 "in the \"accesslog\" table of the respository.\n"
239 );
240
241 setup_menu_entry("Hack Log", "hacklog",
242 "All 418 hack attempts"
243 );
244
245 setup_menu_entry("Non-Hack Log", "hacklog?not",
246 "All log messages that are not hack attempts"
247 );
248
249
250 @ </table>
251 style_finish_page();
252 }
253
254
+5 -2
--- src/stash.c
+++ src/stash.c
@@ -581,23 +581,26 @@
581581
stashid = stash_create();
582582
undo_disable();
583583
if( g.argc>=2 ){
584584
int nFile = db_int(0, "SELECT count(*) FROM stashfile WHERE stashid=%d",
585585
stashid);
586
- char **newArgv = fossil_malloc( sizeof(char*)*(nFile+2) );
586
+ char **newArgv;
587587
int i = 2;
588588
Stmt q;
589
+ if( nFile==0 ){
590
+ fossil_fatal("No modified files match the provided pattern.");
591
+ }
592
+ newArgv = fossil_malloc( sizeof(char*)*(nFile+2) );
589593
db_prepare(&q,"SELECT origname FROM stashfile WHERE stashid=%d", stashid);
590594
while( db_step(&q)==SQLITE_ROW ){
591595
newArgv[i++] = mprintf("%s%s", g.zLocalRoot, db_column_text(&q, 0));
592596
}
593597
db_finalize(&q);
594598
newArgv[0] = g.argv[0];
595599
newArgv[1] = 0;
596600
g.argv = newArgv;
597601
g.argc = nFile+2;
598
- if( nFile==0 ) return;
599602
}
600603
/* Make sure the stash has committed before running the revert, so that
601604
** we have a copy of the changes before deleting them. */
602605
db_commit_transaction();
603606
g.argv[1] = "revert";
604607
--- src/stash.c
+++ src/stash.c
@@ -581,23 +581,26 @@
581 stashid = stash_create();
582 undo_disable();
583 if( g.argc>=2 ){
584 int nFile = db_int(0, "SELECT count(*) FROM stashfile WHERE stashid=%d",
585 stashid);
586 char **newArgv = fossil_malloc( sizeof(char*)*(nFile+2) );
587 int i = 2;
588 Stmt q;
 
 
 
 
589 db_prepare(&q,"SELECT origname FROM stashfile WHERE stashid=%d", stashid);
590 while( db_step(&q)==SQLITE_ROW ){
591 newArgv[i++] = mprintf("%s%s", g.zLocalRoot, db_column_text(&q, 0));
592 }
593 db_finalize(&q);
594 newArgv[0] = g.argv[0];
595 newArgv[1] = 0;
596 g.argv = newArgv;
597 g.argc = nFile+2;
598 if( nFile==0 ) return;
599 }
600 /* Make sure the stash has committed before running the revert, so that
601 ** we have a copy of the changes before deleting them. */
602 db_commit_transaction();
603 g.argv[1] = "revert";
604
--- src/stash.c
+++ src/stash.c
@@ -581,23 +581,26 @@
581 stashid = stash_create();
582 undo_disable();
583 if( g.argc>=2 ){
584 int nFile = db_int(0, "SELECT count(*) FROM stashfile WHERE stashid=%d",
585 stashid);
586 char **newArgv;
587 int i = 2;
588 Stmt q;
589 if( nFile==0 ){
590 fossil_fatal("No modified files match the provided pattern.");
591 }
592 newArgv = fossil_malloc( sizeof(char*)*(nFile+2) );
593 db_prepare(&q,"SELECT origname FROM stashfile WHERE stashid=%d", stashid);
594 while( db_step(&q)==SQLITE_ROW ){
595 newArgv[i++] = mprintf("%s%s", g.zLocalRoot, db_column_text(&q, 0));
596 }
597 db_finalize(&q);
598 newArgv[0] = g.argv[0];
599 newArgv[1] = 0;
600 g.argv = newArgv;
601 g.argc = nFile+2;
 
602 }
603 /* Make sure the stash has committed before running the revert, so that
604 ** we have a copy of the changes before deleting them. */
605 db_commit_transaction();
606 g.argv[1] = "revert";
607
+8 -3
--- src/style.c
+++ src/style.c
@@ -419,10 +419,11 @@
419419
** or after a change to the stylesheet.
420420
*/
421421
static void stylesheet_url_var(void){
422422
char *zBuiltin; /* Auxiliary page-specific CSS page */
423423
Blob url; /* The URL */
424
+ const char * zPage = local_zCurrentPage ? local_zCurrentPage : g.zPath;
424425
425426
/* Initialize the URL to its baseline */
426427
url = empty_blob;
427428
blob_appendf(&url, "%R/style.css");
428429
@@ -438,13 +439,13 @@
438439
**
439440
** The /style.css page (implemented below) will detect this extra "wikiedit"
440441
** path information and include the page-specific CSS along with the
441442
** default CSS when it delivers the page.
442443
*/
443
- zBuiltin = mprintf("style.%s.css", g.zPath);
444
+ zBuiltin = mprintf("style.%s.css", zPage);
444445
if( builtin_file(zBuiltin,0)!=0 ){
445
- blob_appendf(&url, "/%s", g.zPath);
446
+ blob_appendf(&url, "/%s", zPage);
446447
}
447448
fossil_free(zBuiltin);
448449
449450
/* Add query parameters that will change whenever the skin changes
450451
** or after any updates to the CSS files
@@ -1398,11 +1399,11 @@
13981399
** the error message is shown.
13991400
**
14001401
** If zFormat is an empty string, then this is the /test_env page.
14011402
*/
14021403
void webpage_error(const char *zFormat, ...){
1403
- int showAll;
1404
+ int showAll = 0;
14041405
char *zErr = 0;
14051406
int isAuth = 0;
14061407
char zCap[100];
14071408
14081409
login_check_credentials();
@@ -1495,10 +1496,14 @@
14951496
}
14961497
@ <hr>
14971498
P("HTTP_USER_AGENT");
14981499
P("SERVER_SOFTWARE");
14991500
cgi_print_all(showAll, 0, 0);
1501
+ @ <p><form method="POST" action="%R/test_env">
1502
+ @ <input type="hidden" name="showall" value="%d(showAll)">
1503
+ @ <input type="submit" name="post-test-button" value="POST Test">
1504
+ @ </form>
15001505
if( showAll && blob_size(&g.httpHeader)>0 ){
15011506
@ <hr>
15021507
@ <pre>
15031508
@ %h(blob_str(&g.httpHeader))
15041509
@ </pre>
15051510
--- src/style.c
+++ src/style.c
@@ -419,10 +419,11 @@
419 ** or after a change to the stylesheet.
420 */
421 static void stylesheet_url_var(void){
422 char *zBuiltin; /* Auxiliary page-specific CSS page */
423 Blob url; /* The URL */
 
424
425 /* Initialize the URL to its baseline */
426 url = empty_blob;
427 blob_appendf(&url, "%R/style.css");
428
@@ -438,13 +439,13 @@
438 **
439 ** The /style.css page (implemented below) will detect this extra "wikiedit"
440 ** path information and include the page-specific CSS along with the
441 ** default CSS when it delivers the page.
442 */
443 zBuiltin = mprintf("style.%s.css", g.zPath);
444 if( builtin_file(zBuiltin,0)!=0 ){
445 blob_appendf(&url, "/%s", g.zPath);
446 }
447 fossil_free(zBuiltin);
448
449 /* Add query parameters that will change whenever the skin changes
450 ** or after any updates to the CSS files
@@ -1398,11 +1399,11 @@
1398 ** the error message is shown.
1399 **
1400 ** If zFormat is an empty string, then this is the /test_env page.
1401 */
1402 void webpage_error(const char *zFormat, ...){
1403 int showAll;
1404 char *zErr = 0;
1405 int isAuth = 0;
1406 char zCap[100];
1407
1408 login_check_credentials();
@@ -1495,10 +1496,14 @@
1495 }
1496 @ <hr>
1497 P("HTTP_USER_AGENT");
1498 P("SERVER_SOFTWARE");
1499 cgi_print_all(showAll, 0, 0);
 
 
 
 
1500 if( showAll && blob_size(&g.httpHeader)>0 ){
1501 @ <hr>
1502 @ <pre>
1503 @ %h(blob_str(&g.httpHeader))
1504 @ </pre>
1505
--- src/style.c
+++ src/style.c
@@ -419,10 +419,11 @@
419 ** or after a change to the stylesheet.
420 */
421 static void stylesheet_url_var(void){
422 char *zBuiltin; /* Auxiliary page-specific CSS page */
423 Blob url; /* The URL */
424 const char * zPage = local_zCurrentPage ? local_zCurrentPage : g.zPath;
425
426 /* Initialize the URL to its baseline */
427 url = empty_blob;
428 blob_appendf(&url, "%R/style.css");
429
@@ -438,13 +439,13 @@
439 **
440 ** The /style.css page (implemented below) will detect this extra "wikiedit"
441 ** path information and include the page-specific CSS along with the
442 ** default CSS when it delivers the page.
443 */
444 zBuiltin = mprintf("style.%s.css", zPage);
445 if( builtin_file(zBuiltin,0)!=0 ){
446 blob_appendf(&url, "/%s", zPage);
447 }
448 fossil_free(zBuiltin);
449
450 /* Add query parameters that will change whenever the skin changes
451 ** or after any updates to the CSS files
@@ -1398,11 +1399,11 @@
1399 ** the error message is shown.
1400 **
1401 ** If zFormat is an empty string, then this is the /test_env page.
1402 */
1403 void webpage_error(const char *zFormat, ...){
1404 int showAll = 0;
1405 char *zErr = 0;
1406 int isAuth = 0;
1407 char zCap[100];
1408
1409 login_check_credentials();
@@ -1495,10 +1496,14 @@
1496 }
1497 @ <hr>
1498 P("HTTP_USER_AGENT");
1499 P("SERVER_SOFTWARE");
1500 cgi_print_all(showAll, 0, 0);
1501 @ <p><form method="POST" action="%R/test_env">
1502 @ <input type="hidden" name="showall" value="%d(showAll)">
1503 @ <input type="submit" name="post-test-button" value="POST Test">
1504 @ </form>
1505 if( showAll && blob_size(&g.httpHeader)>0 ){
1506 @ <hr>
1507 @ <pre>
1508 @ %h(blob_str(&g.httpHeader))
1509 @ </pre>
1510
+50 -25
--- src/style.chat.css
+++ src/style.chat.css
@@ -68,11 +68,11 @@
6868
content placed below this. */
6969
border-bottom: 1px transparent;
7070
}
7171
body.chat.monospace-messages .message-widget-content,
7272
body.chat.monospace-messages .chat-input-field{
73
- font-family: monospace;
73
+ font-family: monospace;
7474
}
7575
body.chat .message-widget-content > * {
7676
margin: 0;
7777
padding: 0;
7878
}
@@ -115,16 +115,37 @@
115115
white-space: nowrap;
116116
}
117117
body.chat .fossil-tooltip.help-buttonlet-content {
118118
font-size: 80%;
119119
}
120
+
121
+body.chat .message-widget .message-widget-tab {
122
+ /* Element which renders the main metadata for a given message. */
123
+}
120124
body.chat .message-widget .message-widget-tab .xfrom {
121
- /* Element which holds the "this message is from user X" part
122
- of the message banner. */
125
+ /* xfrom part of the message tab */
123126
font-style: italic;
124127
font-weight: bold;
125128
}
129
+
130
+body.chat .message-widget .message-widget-tab .mtime {
131
+ /* mtime part of the message tab */
132
+}
133
+
134
+body.chat .message-widget .message-widget-tab .msgid {
135
+ /* msgid part of the message tab */
136
+}
137
+
138
+body.chat .message-widget .match {
139
+ font-weight: bold;
140
+ background-color: yellow;
141
+}
142
+
143
+body.chat.fossil-dark-style .message-widget .match {
144
+ background-color: #ff4800;
145
+}
146
+
126147
/* The popup element for displaying message timestamps
127148
and deletion controls. */
128149
body.chat .chat-message-popup {
129150
font-family: monospace;
130151
font-size: 0.9em;
@@ -182,20 +203,10 @@
182203
body.chat.chat-only-mode{
183204
padding: 0;
184205
margin: 0 auto;
185206
}
186207
body.chat #chat-button-settings {}
187
-/** Popup widget for the /chat settings. */
188
-body.chat .chat-settings-popup {
189
- font-size: 0.8em;
190
- text-align: left;
191
- display: flex;
192
- flex-direction: column;
193
- align-items: stretch;
194
- padding: 0.25em;
195
- z-index: 200;
196
-}
197208
198209
/** Container for the list of /chat messages. */
199210
body.chat #chat-messages-wrapper {
200211
overflow: auto;
201212
padding: 0 0.25em;
@@ -346,18 +357,18 @@
346357
body.chat #chat-buttons-wrapper > .cbutton:hover {
347358
background-color: rgba(200,200,200,0.3);
348359
}
349360
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper > .cbutton {
350361
margin: 2px 0.125em 0 0.125em;
351
- min-width: 6ex;
352
- max-width: 6ex;
362
+ min-width: 4.5ex;
363
+ max-width: 4.5ex;
353364
min-height: 2.3ex;
354365
max-height: 2.3ex;
355366
font-size: 120%;
356367
}
357368
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper #chat-button-submit {
358
- min-width: 12ex;
369
+ min-width: 10ex;
359370
}
360371
.chat-input-field {
361372
font-family: inherit
362373
}
363374
body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-multi,
@@ -440,10 +451,11 @@
440451
/*ensure that these grow more than the non-.chat-view elements.
441452
Note that setting flex shrink to 0 breaks/disables scrolling!*/;
442453
margin-bottom: 0.2em;
443454
}
444455
body.chat #chat-config,
456
+body.chat #chat-search,
445457
body.chat #chat-preview {
446458
/* /chat configuration widget */
447459
display: flex;
448460
flex-direction: column;
449461
overflow: auto;
@@ -518,31 +530,38 @@
518530
display: inline-block;
519531
opacity: 0.85;
520532
}
521533
body.chat #chat-config #chat-config-options .menu-entry select {
522534
}
523
-body.chat #chat-preview #chat-preview-content {
535
+body.chat #chat-preview #chat-preview-content,
536
+body.chat #chat-search #chat-search-content {
524537
overflow: auto;
525538
flex: 1 1 auto;
526539
padding: 0.5em;
527540
border: 1px dotted;
528541
}
542
+
529543
body.chat #chat-preview #chat-preview-content > * {
530544
margin: 0;
531545
padding: 0;
532546
}
533
-body.chat #chat-preview #chat-preview-buttons {
547
+body.chat .chat-view .button-bar {
534548
flex: 0 1 auto;
535549
display: flex;
536550
flex-direction: column;
537551
}
538
-body.chat #chat-config > button,
539
-body.chat #chat-preview #chat-preview-buttons > button {
552
+body.chat .chat-view .button-bar button {
540553
padding: 0.5em;
541
- flex: 0 1 auto;
554
+ flex: 1 1 auto;
542555
margin: 0.25em 0;
543556
}
557
+
558
+body.chat #chat-search .button-bar {
559
+ flex: 0 1 auto;
560
+ display: flex;
561
+ flex-direction: row;
562
+}
544563
545564
body.chat #chat-user-list-wrapper {
546565
/* Safari can't do fieldsets right, so we emulate one. */
547566
border-radius: 0.5em;
548567
margin: 1em 0 0.2em 0;
@@ -605,14 +624,19 @@
605624
body.chat #chat-user-list .chat-user.selected {
606625
font-weight: bold;
607626
text-decoration: underline;
608627
}
609628
610
-body.chat.fossil-dark-style #chat-button-attach > svg {
611
- /* The black paperclip is barely visible in dark-mode
612
- skins when they have dark buttons */
613
- filter: invert(0.8);
629
+body.chat .searchForm {
630
+ margin-top: 1em;
631
+}
632
+body.chat .spacer-widget button {
633
+ margin-left: 1ex;
634
+ margin-right: 1ex;
635
+ display: block;
636
+ margin-top: 0.5em;
637
+ margin-bottom: 0.5em;
614638
}
615639
616640
body.chat .anim-rotate-360 {
617641
animation: rotate-360 750ms linear;
618642
}
@@ -649,5 +673,6 @@
649673
}
650674
@keyframes fade-out {
651675
from { opacity: 1; }
652676
to { opacity: 0; }
653677
}
678
+
654679
655680
ADDED src/style.uvlist.css
--- src/style.chat.css
+++ src/style.chat.css
@@ -68,11 +68,11 @@
68 content placed below this. */
69 border-bottom: 1px transparent;
70 }
71 body.chat.monospace-messages .message-widget-content,
72 body.chat.monospace-messages .chat-input-field{
73 font-family: monospace;
74 }
75 body.chat .message-widget-content > * {
76 margin: 0;
77 padding: 0;
78 }
@@ -115,16 +115,37 @@
115 white-space: nowrap;
116 }
117 body.chat .fossil-tooltip.help-buttonlet-content {
118 font-size: 80%;
119 }
 
 
 
 
120 body.chat .message-widget .message-widget-tab .xfrom {
121 /* Element which holds the "this message is from user X" part
122 of the message banner. */
123 font-style: italic;
124 font-weight: bold;
125 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126 /* The popup element for displaying message timestamps
127 and deletion controls. */
128 body.chat .chat-message-popup {
129 font-family: monospace;
130 font-size: 0.9em;
@@ -182,20 +203,10 @@
182 body.chat.chat-only-mode{
183 padding: 0;
184 margin: 0 auto;
185 }
186 body.chat #chat-button-settings {}
187 /** Popup widget for the /chat settings. */
188 body.chat .chat-settings-popup {
189 font-size: 0.8em;
190 text-align: left;
191 display: flex;
192 flex-direction: column;
193 align-items: stretch;
194 padding: 0.25em;
195 z-index: 200;
196 }
197
198 /** Container for the list of /chat messages. */
199 body.chat #chat-messages-wrapper {
200 overflow: auto;
201 padding: 0 0.25em;
@@ -346,18 +357,18 @@
346 body.chat #chat-buttons-wrapper > .cbutton:hover {
347 background-color: rgba(200,200,200,0.3);
348 }
349 body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper > .cbutton {
350 margin: 2px 0.125em 0 0.125em;
351 min-width: 6ex;
352 max-width: 6ex;
353 min-height: 2.3ex;
354 max-height: 2.3ex;
355 font-size: 120%;
356 }
357 body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper #chat-button-submit {
358 min-width: 12ex;
359 }
360 .chat-input-field {
361 font-family: inherit
362 }
363 body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-multi,
@@ -440,10 +451,11 @@
440 /*ensure that these grow more than the non-.chat-view elements.
441 Note that setting flex shrink to 0 breaks/disables scrolling!*/;
442 margin-bottom: 0.2em;
443 }
444 body.chat #chat-config,
 
445 body.chat #chat-preview {
446 /* /chat configuration widget */
447 display: flex;
448 flex-direction: column;
449 overflow: auto;
@@ -518,31 +530,38 @@
518 display: inline-block;
519 opacity: 0.85;
520 }
521 body.chat #chat-config #chat-config-options .menu-entry select {
522 }
523 body.chat #chat-preview #chat-preview-content {
 
524 overflow: auto;
525 flex: 1 1 auto;
526 padding: 0.5em;
527 border: 1px dotted;
528 }
 
529 body.chat #chat-preview #chat-preview-content > * {
530 margin: 0;
531 padding: 0;
532 }
533 body.chat #chat-preview #chat-preview-buttons {
534 flex: 0 1 auto;
535 display: flex;
536 flex-direction: column;
537 }
538 body.chat #chat-config > button,
539 body.chat #chat-preview #chat-preview-buttons > button {
540 padding: 0.5em;
541 flex: 0 1 auto;
542 margin: 0.25em 0;
543 }
 
 
 
 
 
 
544
545 body.chat #chat-user-list-wrapper {
546 /* Safari can't do fieldsets right, so we emulate one. */
547 border-radius: 0.5em;
548 margin: 1em 0 0.2em 0;
@@ -605,14 +624,19 @@
605 body.chat #chat-user-list .chat-user.selected {
606 font-weight: bold;
607 text-decoration: underline;
608 }
609
610 body.chat.fossil-dark-style #chat-button-attach > svg {
611 /* The black paperclip is barely visible in dark-mode
612 skins when they have dark buttons */
613 filter: invert(0.8);
 
 
 
 
 
614 }
615
616 body.chat .anim-rotate-360 {
617 animation: rotate-360 750ms linear;
618 }
@@ -649,5 +673,6 @@
649 }
650 @keyframes fade-out {
651 from { opacity: 1; }
652 to { opacity: 0; }
653 }
 
654
655 DDED src/style.uvlist.css
--- src/style.chat.css
+++ src/style.chat.css
@@ -68,11 +68,11 @@
68 content placed below this. */
69 border-bottom: 1px transparent;
70 }
71 body.chat.monospace-messages .message-widget-content,
72 body.chat.monospace-messages .chat-input-field{
73 font-family: monospace;
74 }
75 body.chat .message-widget-content > * {
76 margin: 0;
77 padding: 0;
78 }
@@ -115,16 +115,37 @@
115 white-space: nowrap;
116 }
117 body.chat .fossil-tooltip.help-buttonlet-content {
118 font-size: 80%;
119 }
120
121 body.chat .message-widget .message-widget-tab {
122 /* Element which renders the main metadata for a given message. */
123 }
124 body.chat .message-widget .message-widget-tab .xfrom {
125 /* xfrom part of the message tab */
 
126 font-style: italic;
127 font-weight: bold;
128 }
129
130 body.chat .message-widget .message-widget-tab .mtime {
131 /* mtime part of the message tab */
132 }
133
134 body.chat .message-widget .message-widget-tab .msgid {
135 /* msgid part of the message tab */
136 }
137
138 body.chat .message-widget .match {
139 font-weight: bold;
140 background-color: yellow;
141 }
142
143 body.chat.fossil-dark-style .message-widget .match {
144 background-color: #ff4800;
145 }
146
147 /* The popup element for displaying message timestamps
148 and deletion controls. */
149 body.chat .chat-message-popup {
150 font-family: monospace;
151 font-size: 0.9em;
@@ -182,20 +203,10 @@
203 body.chat.chat-only-mode{
204 padding: 0;
205 margin: 0 auto;
206 }
207 body.chat #chat-button-settings {}
 
 
 
 
 
 
 
 
 
 
208
209 /** Container for the list of /chat messages. */
210 body.chat #chat-messages-wrapper {
211 overflow: auto;
212 padding: 0 0.25em;
@@ -346,18 +357,18 @@
357 body.chat #chat-buttons-wrapper > .cbutton:hover {
358 background-color: rgba(200,200,200,0.3);
359 }
360 body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper > .cbutton {
361 margin: 2px 0.125em 0 0.125em;
362 min-width: 4.5ex;
363 max-width: 4.5ex;
364 min-height: 2.3ex;
365 max-height: 2.3ex;
366 font-size: 120%;
367 }
368 body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper #chat-button-submit {
369 min-width: 10ex;
370 }
371 .chat-input-field {
372 font-family: inherit
373 }
374 body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-multi,
@@ -440,10 +451,11 @@
451 /*ensure that these grow more than the non-.chat-view elements.
452 Note that setting flex shrink to 0 breaks/disables scrolling!*/;
453 margin-bottom: 0.2em;
454 }
455 body.chat #chat-config,
456 body.chat #chat-search,
457 body.chat #chat-preview {
458 /* /chat configuration widget */
459 display: flex;
460 flex-direction: column;
461 overflow: auto;
@@ -518,31 +530,38 @@
530 display: inline-block;
531 opacity: 0.85;
532 }
533 body.chat #chat-config #chat-config-options .menu-entry select {
534 }
535 body.chat #chat-preview #chat-preview-content,
536 body.chat #chat-search #chat-search-content {
537 overflow: auto;
538 flex: 1 1 auto;
539 padding: 0.5em;
540 border: 1px dotted;
541 }
542
543 body.chat #chat-preview #chat-preview-content > * {
544 margin: 0;
545 padding: 0;
546 }
547 body.chat .chat-view .button-bar {
548 flex: 0 1 auto;
549 display: flex;
550 flex-direction: column;
551 }
552 body.chat .chat-view .button-bar button {
 
553 padding: 0.5em;
554 flex: 1 1 auto;
555 margin: 0.25em 0;
556 }
557
558 body.chat #chat-search .button-bar {
559 flex: 0 1 auto;
560 display: flex;
561 flex-direction: row;
562 }
563
564 body.chat #chat-user-list-wrapper {
565 /* Safari can't do fieldsets right, so we emulate one. */
566 border-radius: 0.5em;
567 margin: 1em 0 0.2em 0;
@@ -605,14 +624,19 @@
624 body.chat #chat-user-list .chat-user.selected {
625 font-weight: bold;
626 text-decoration: underline;
627 }
628
629 body.chat .searchForm {
630 margin-top: 1em;
631 }
632 body.chat .spacer-widget button {
633 margin-left: 1ex;
634 margin-right: 1ex;
635 display: block;
636 margin-top: 0.5em;
637 margin-bottom: 0.5em;
638 }
639
640 body.chat .anim-rotate-360 {
641 animation: rotate-360 750ms linear;
642 }
@@ -649,5 +673,6 @@
673 }
674 @keyframes fade-out {
675 from { opacity: 1; }
676 to { opacity: 0; }
677 }
678
679
680 DDED src/style.uvlist.css
--- a/src/style.uvlist.css
+++ b/src/style.uvlist.css
@@ -0,0 +1,7 @@
1
+body.uvlist input {
2
+ margin: 0.5em;
3
+}
4
+
5
+body.uvlist form {
6
+ display: block;
7
+}
--- a/src/style.uvlist.css
+++ b/src/style.uvlist.css
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
--- a/src/style.uvlist.css
+++ b/src/style.uvlist.css
@@ -0,0 +1,7 @@
1 body.uvlist input {
2 margin: 0.5em;
3 }
4
5 body.uvlist form {
6 display: block;
7 }
+64 -24
--- src/tag.c
+++ src/tag.c
@@ -402,17 +402,17 @@
402402
** --propagate flag is present and ARTIFACT-ID refers to a
403403
** wiki page, forum post, technote, or check-in, the tag
404404
** propagates to all descendants of that artifact.
405405
**
406406
** Options:
407
+** --date-override DATETIME Set date and time added
408
+** -n|--dry-run Display the tag text, but do not
409
+** actually insert it into the database
410
+** --propagate Propagating tag
407411
** --raw Raw tag name. Ignored for
408412
** non-CHECK-IN artifacts.
409
-** --propagate Propagating tag
410
-** --date-override DATETIME Set date and time added
411413
** --user-override USER Name USER when adding the tag
412
-** -n|--dry-run Display the tag text, but do not
413
-** actually insert it into the database
414414
**
415415
** The --date-override and --user-override options support
416416
** importing history from other SCM systems. DATETIME has
417417
** the form 'YYYY-MMM-DD HH:MM:SS'.
418418
**
@@ -427,31 +427,31 @@
427427
** any descendants. Use the the -n|--dry-run option to see
428428
** what would have happened. Certain tag name prefixes are
429429
** forbidden, as documented for the 'add' subcommand.
430430
**
431431
** Options:
432
+** --date-override DATETIME Set date and time deleted
433
+** -n|--dry-run Display the control artifact, but do
434
+** not insert it into the database
432435
** --raw Raw tag name. Ignored for
433436
** non-CHECK-IN artifacts.
434
-** --date-override DATETIME Set date and time deleted
435437
** --user-override USER Name USER when deleting the tag
436
-** -n|--dry-run Display the control artifact, but do
437
-** not insert it into the database
438438
**
439439
** > fossil tag find ?OPTIONS? TAGNAME
440440
**
441441
** List all objects that use TAGNAME.
442442
**
443443
** Options:
444
+** -n|--limit N Limit to N results
444445
** --raw Interprets tag as a raw name instead of a
445446
** branch name and matches any type of artifact.
446447
** Changes the output to include only the
447448
** hashes of matching objects.
448449
** -t|--type TYPE One of: ci (check-in), w (wiki),
449450
** e (event/technote), f (forum post),
450451
** t (ticket). Default is all types. Ignored
451452
** if --raw is used.
452
-** -n|--limit N Limit to N results
453453
**
454454
** > fossil tag list|ls ?OPTIONS? ?ARTIFACT-ID?
455455
**
456456
** List all tags or, if ARTIFACT-ID is supplied, all tags and
457457
** their values for that artifact. The tagtype option accepts
@@ -459,21 +459,26 @@
459459
** scripting compatibility, the internal tag types "wiki-",
460460
** "tkt-", and "event-" (technote) are elided by default
461461
** unless the --raw or --prefix options are used.
462462
**
463463
** Options:
464
-** --raw List raw names of tags
465
-** --tagtype TYPE List only tags of type TYPE, which must
466
-** be one of: cancel, singleton, propagated
467464
** -v|--inverse Inverse the meaning of --tagtype TYPE
468465
** --prefix List only tags with the given prefix
469466
** Fossil-internal prefixes include "sym-"
470467
** (branch name), "wiki-", "event-"
471468
** (technote), and "tkt-" (ticket). The
472469
** prefix is stripped from the resulting
473470
** list unless --raw is provided. Ignored if
474471
** ARTIFACT-ID is provided.
472
+** --raw List raw names of tags
473
+** --sep SEP Separator when concatenating values
474
+** --tagtype TYPE List only tags of type TYPE, which must
475
+** be one of: cancel, singleton, propagated
476
+** --values List tag values
477
+** If --sep is supplied, list all values of a tag on
478
+** the same line, separated by SEP; otherwise list
479
+** each value on its own line.
475480
**
476481
** The option --raw allows the manipulation of all types of tags
477482
** used for various internal purposes in fossil. It also shows
478483
** "cancel" tags for the "find" and "list" subcommands. You should
479484
** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
635640
const int fRaw = find_option("raw","",0)!=0;
636641
const char *zTagType = find_option("tagtype","t",1);
637642
const int fInverse = find_option("inverse","v",0)!=0;
638643
const char *zTagPrefix = find_option("prefix","",1);
639644
int nTagType = fRaw ? -1 : 0;
645
+ int fValues = find_option("values","",0)!=0;
646
+ const char *zSep = find_option("sep","",1);
647
+
640648
641649
if( zTagType!=0 ){
642650
int l = strlen(zTagType);
643651
if( strncmp(zTagType,"cancel",l)==0 ){
644652
nTagType = 0;
@@ -650,29 +658,61 @@
650658
fossil_fatal("unrecognized tag type");
651659
}
652660
}
653661
if( g.argc==3 ){
654662
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
655
- db_prepare(&q,
656
- "SELECT tagname FROM tag"
657
- " WHERE EXISTS(SELECT 1 FROM tagxref"
658
- " WHERE tagid=tag.tagid"
659
- " AND tagtype%s%d)"
660
- " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
661
- " END ORDER BY tagname COLLATE uintnocase",
662
- zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
663
- nTagType, zTagPrefix, zTagPrefix
664
- );
663
+ if( !fValues ){
664
+ db_prepare(&q,
665
+ "SELECT tagname FROM tag"
666
+ " WHERE EXISTS(SELECT 1 FROM tagxref"
667
+ " WHERE tagid=tag.tagid"
668
+ " AND tagtype%s%d)"
669
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
670
+ " END ORDER BY tagname COLLATE uintnocase",
671
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
672
+ nTagType, zTagPrefix, zTagPrefix
673
+ );
674
+ }else{
675
+ if( zSep ){
676
+ db_prepare(&q,
677
+ /* work around group_concat() with DISTINCT and custom separator */
678
+ "SELECT tagname,"
679
+ " rtrim(replace(group_concat(DISTINCT value||'@!' "
680
+ " ORDER BY value ASC), '@!,', %Q),'@!')"
681
+ " FROM tagxref, tag"
682
+ " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
683
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
684
+ " GROUP BY tagname"
685
+ " ORDER BY tagname COLLATE uintnocase",
686
+ ( zSep && strlen(zSep)>0 ) ? zSep : ",",
687
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
688
+ nTagType, zTagPrefix, zTagPrefix
689
+ );
690
+ }else{
691
+ db_prepare(&q,
692
+ "SELECT DISTINCT tagname, value"
693
+ " FROM tagxref, tag"
694
+ " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
695
+ " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
696
+ " ORDER BY tagname, value COLLATE uintnocase",
697
+ zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
698
+ nTagType, zTagPrefix, zTagPrefix
699
+ );
700
+ }
701
+ }
665702
while( db_step(&q)==SQLITE_ROW ){
666703
const char *zName = db_column_text(&q, 0);
704
+ const char *zValue = db_column_text(&q, 1);
705
+ int nWidth = fValues ? 20 : 0;
706
+ const char *zzValue = (fValues && zValue) ? mprintf(" %s", zValue) : "";
667707
if( fRaw ){
668
- fossil_print("%s\n", zName);
708
+ fossil_print("%-*s%s\n", nWidth, zName, zzValue);
669709
}else if( nTagPrefix>0 ){
670710
assert(db_column_bytes(&q,0)>=nTagPrefix);
671
- fossil_print("%s\n", &zName[nTagPrefix]);
711
+ fossil_print("%-*s%s\n", nWidth, &zName[nTagPrefix], zzValue);
672712
}else if( strncmp(zName, "sym-", 4)==0 ){
673
- fossil_print("%s\n", &zName[4]);
713
+ fossil_print("%-*s%s\n", nWidth, &zName[4], zzValue);
674714
}
675715
}
676716
db_finalize(&q);
677717
}else if( g.argc==4 ){
678718
char const *zObjId = g.argv[3];
679719
--- src/tag.c
+++ src/tag.c
@@ -402,17 +402,17 @@
402 ** --propagate flag is present and ARTIFACT-ID refers to a
403 ** wiki page, forum post, technote, or check-in, the tag
404 ** propagates to all descendants of that artifact.
405 **
406 ** Options:
 
 
 
 
407 ** --raw Raw tag name. Ignored for
408 ** non-CHECK-IN artifacts.
409 ** --propagate Propagating tag
410 ** --date-override DATETIME Set date and time added
411 ** --user-override USER Name USER when adding the tag
412 ** -n|--dry-run Display the tag text, but do not
413 ** actually insert it into the database
414 **
415 ** The --date-override and --user-override options support
416 ** importing history from other SCM systems. DATETIME has
417 ** the form 'YYYY-MMM-DD HH:MM:SS'.
418 **
@@ -427,31 +427,31 @@
427 ** any descendants. Use the the -n|--dry-run option to see
428 ** what would have happened. Certain tag name prefixes are
429 ** forbidden, as documented for the 'add' subcommand.
430 **
431 ** Options:
 
 
 
432 ** --raw Raw tag name. Ignored for
433 ** non-CHECK-IN artifacts.
434 ** --date-override DATETIME Set date and time deleted
435 ** --user-override USER Name USER when deleting the tag
436 ** -n|--dry-run Display the control artifact, but do
437 ** not insert it into the database
438 **
439 ** > fossil tag find ?OPTIONS? TAGNAME
440 **
441 ** List all objects that use TAGNAME.
442 **
443 ** Options:
 
444 ** --raw Interprets tag as a raw name instead of a
445 ** branch name and matches any type of artifact.
446 ** Changes the output to include only the
447 ** hashes of matching objects.
448 ** -t|--type TYPE One of: ci (check-in), w (wiki),
449 ** e (event/technote), f (forum post),
450 ** t (ticket). Default is all types. Ignored
451 ** if --raw is used.
452 ** -n|--limit N Limit to N results
453 **
454 ** > fossil tag list|ls ?OPTIONS? ?ARTIFACT-ID?
455 **
456 ** List all tags or, if ARTIFACT-ID is supplied, all tags and
457 ** their values for that artifact. The tagtype option accepts
@@ -459,21 +459,26 @@
459 ** scripting compatibility, the internal tag types "wiki-",
460 ** "tkt-", and "event-" (technote) are elided by default
461 ** unless the --raw or --prefix options are used.
462 **
463 ** Options:
464 ** --raw List raw names of tags
465 ** --tagtype TYPE List only tags of type TYPE, which must
466 ** be one of: cancel, singleton, propagated
467 ** -v|--inverse Inverse the meaning of --tagtype TYPE
468 ** --prefix List only tags with the given prefix
469 ** Fossil-internal prefixes include "sym-"
470 ** (branch name), "wiki-", "event-"
471 ** (technote), and "tkt-" (ticket). The
472 ** prefix is stripped from the resulting
473 ** list unless --raw is provided. Ignored if
474 ** ARTIFACT-ID is provided.
 
 
 
 
 
 
 
 
475 **
476 ** The option --raw allows the manipulation of all types of tags
477 ** used for various internal purposes in fossil. It also shows
478 ** "cancel" tags for the "find" and "list" subcommands. You should
479 ** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
635 const int fRaw = find_option("raw","",0)!=0;
636 const char *zTagType = find_option("tagtype","t",1);
637 const int fInverse = find_option("inverse","v",0)!=0;
638 const char *zTagPrefix = find_option("prefix","",1);
639 int nTagType = fRaw ? -1 : 0;
 
 
 
640
641 if( zTagType!=0 ){
642 int l = strlen(zTagType);
643 if( strncmp(zTagType,"cancel",l)==0 ){
644 nTagType = 0;
@@ -650,29 +658,61 @@
650 fossil_fatal("unrecognized tag type");
651 }
652 }
653 if( g.argc==3 ){
654 const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
655 db_prepare(&q,
656 "SELECT tagname FROM tag"
657 " WHERE EXISTS(SELECT 1 FROM tagxref"
658 " WHERE tagid=tag.tagid"
659 " AND tagtype%s%d)"
660 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
661 " END ORDER BY tagname COLLATE uintnocase",
662 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
663 nTagType, zTagPrefix, zTagPrefix
664 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665 while( db_step(&q)==SQLITE_ROW ){
666 const char *zName = db_column_text(&q, 0);
 
 
 
667 if( fRaw ){
668 fossil_print("%s\n", zName);
669 }else if( nTagPrefix>0 ){
670 assert(db_column_bytes(&q,0)>=nTagPrefix);
671 fossil_print("%s\n", &zName[nTagPrefix]);
672 }else if( strncmp(zName, "sym-", 4)==0 ){
673 fossil_print("%s\n", &zName[4]);
674 }
675 }
676 db_finalize(&q);
677 }else if( g.argc==4 ){
678 char const *zObjId = g.argv[3];
679
--- src/tag.c
+++ src/tag.c
@@ -402,17 +402,17 @@
402 ** --propagate flag is present and ARTIFACT-ID refers to a
403 ** wiki page, forum post, technote, or check-in, the tag
404 ** propagates to all descendants of that artifact.
405 **
406 ** Options:
407 ** --date-override DATETIME Set date and time added
408 ** -n|--dry-run Display the tag text, but do not
409 ** actually insert it into the database
410 ** --propagate Propagating tag
411 ** --raw Raw tag name. Ignored for
412 ** non-CHECK-IN artifacts.
 
 
413 ** --user-override USER Name USER when adding the tag
 
 
414 **
415 ** The --date-override and --user-override options support
416 ** importing history from other SCM systems. DATETIME has
417 ** the form 'YYYY-MMM-DD HH:MM:SS'.
418 **
@@ -427,31 +427,31 @@
427 ** any descendants. Use the the -n|--dry-run option to see
428 ** what would have happened. Certain tag name prefixes are
429 ** forbidden, as documented for the 'add' subcommand.
430 **
431 ** Options:
432 ** --date-override DATETIME Set date and time deleted
433 ** -n|--dry-run Display the control artifact, but do
434 ** not insert it into the database
435 ** --raw Raw tag name. Ignored for
436 ** non-CHECK-IN artifacts.
 
437 ** --user-override USER Name USER when deleting the tag
 
 
438 **
439 ** > fossil tag find ?OPTIONS? TAGNAME
440 **
441 ** List all objects that use TAGNAME.
442 **
443 ** Options:
444 ** -n|--limit N Limit to N results
445 ** --raw Interprets tag as a raw name instead of a
446 ** branch name and matches any type of artifact.
447 ** Changes the output to include only the
448 ** hashes of matching objects.
449 ** -t|--type TYPE One of: ci (check-in), w (wiki),
450 ** e (event/technote), f (forum post),
451 ** t (ticket). Default is all types. Ignored
452 ** if --raw is used.
 
453 **
454 ** > fossil tag list|ls ?OPTIONS? ?ARTIFACT-ID?
455 **
456 ** List all tags or, if ARTIFACT-ID is supplied, all tags and
457 ** their values for that artifact. The tagtype option accepts
@@ -459,21 +459,26 @@
459 ** scripting compatibility, the internal tag types "wiki-",
460 ** "tkt-", and "event-" (technote) are elided by default
461 ** unless the --raw or --prefix options are used.
462 **
463 ** Options:
 
 
 
464 ** -v|--inverse Inverse the meaning of --tagtype TYPE
465 ** --prefix List only tags with the given prefix
466 ** Fossil-internal prefixes include "sym-"
467 ** (branch name), "wiki-", "event-"
468 ** (technote), and "tkt-" (ticket). The
469 ** prefix is stripped from the resulting
470 ** list unless --raw is provided. Ignored if
471 ** ARTIFACT-ID is provided.
472 ** --raw List raw names of tags
473 ** --sep SEP Separator when concatenating values
474 ** --tagtype TYPE List only tags of type TYPE, which must
475 ** be one of: cancel, singleton, propagated
476 ** --values List tag values
477 ** If --sep is supplied, list all values of a tag on
478 ** the same line, separated by SEP; otherwise list
479 ** each value on its own line.
480 **
481 ** The option --raw allows the manipulation of all types of tags
482 ** used for various internal purposes in fossil. It also shows
483 ** "cancel" tags for the "find" and "list" subcommands. You should
484 ** not use this option to make changes unless you are sure what
@@ -635,10 +640,13 @@
640 const int fRaw = find_option("raw","",0)!=0;
641 const char *zTagType = find_option("tagtype","t",1);
642 const int fInverse = find_option("inverse","v",0)!=0;
643 const char *zTagPrefix = find_option("prefix","",1);
644 int nTagType = fRaw ? -1 : 0;
645 int fValues = find_option("values","",0)!=0;
646 const char *zSep = find_option("sep","",1);
647
648
649 if( zTagType!=0 ){
650 int l = strlen(zTagType);
651 if( strncmp(zTagType,"cancel",l)==0 ){
652 nTagType = 0;
@@ -650,29 +658,61 @@
658 fossil_fatal("unrecognized tag type");
659 }
660 }
661 if( g.argc==3 ){
662 const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
663 if( !fValues ){
664 db_prepare(&q,
665 "SELECT tagname FROM tag"
666 " WHERE EXISTS(SELECT 1 FROM tagxref"
667 " WHERE tagid=tag.tagid"
668 " AND tagtype%s%d)"
669 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
670 " END ORDER BY tagname COLLATE uintnocase",
671 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
672 nTagType, zTagPrefix, zTagPrefix
673 );
674 }else{
675 if( zSep ){
676 db_prepare(&q,
677 /* work around group_concat() with DISTINCT and custom separator */
678 "SELECT tagname,"
679 " rtrim(replace(group_concat(DISTINCT value||'@!' "
680 " ORDER BY value ASC), '@!,', %Q),'@!')"
681 " FROM tagxref, tag"
682 " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
683 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
684 " GROUP BY tagname"
685 " ORDER BY tagname COLLATE uintnocase",
686 ( zSep && strlen(zSep)>0 ) ? zSep : ",",
687 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
688 nTagType, zTagPrefix, zTagPrefix
689 );
690 }else{
691 db_prepare(&q,
692 "SELECT DISTINCT tagname, value"
693 " FROM tagxref, tag"
694 " WHERE tagxref.tagid=tag.tagid AND tagtype%s%d"
695 " AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' END"
696 " ORDER BY tagname, value COLLATE uintnocase",
697 zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
698 nTagType, zTagPrefix, zTagPrefix
699 );
700 }
701 }
702 while( db_step(&q)==SQLITE_ROW ){
703 const char *zName = db_column_text(&q, 0);
704 const char *zValue = db_column_text(&q, 1);
705 int nWidth = fValues ? 20 : 0;
706 const char *zzValue = (fValues && zValue) ? mprintf(" %s", zValue) : "";
707 if( fRaw ){
708 fossil_print("%-*s%s\n", nWidth, zName, zzValue);
709 }else if( nTagPrefix>0 ){
710 assert(db_column_bytes(&q,0)>=nTagPrefix);
711 fossil_print("%-*s%s\n", nWidth, &zName[nTagPrefix], zzValue);
712 }else if( strncmp(zName, "sym-", 4)==0 ){
713 fossil_print("%-*s%s\n", nWidth, &zName[4], zzValue);
714 }
715 }
716 db_finalize(&q);
717 }else if( g.argc==4 ){
718 char const *zObjId = g.argv[3];
719
+9 -6
--- src/timeline.c
+++ src/timeline.c
@@ -1718,13 +1718,16 @@
17181718
** n=COUNT Maximum number of events. "all" for no limit
17191719
** n1=COUNT Same as "n" but doesn't set the display-preference cookie
17201720
** Use "n1=COUNT" for a one-time display change
17211721
** p=CHECKIN Parents and ancestors of CHECKIN
17221722
** bt=PRIOR ... going back to PRIOR
1723
+** p2=CKIN2 ... use CKIN2 if CHECKIN is not found
17231724
** d=CHECKIN Children and descendants of CHECKIN
1725
+** d2=CKIN2 ... Use CKIN2 if CHECKIN is not found
17241726
** ft=DESCENDANT ... going forward to DESCENDANT
17251727
** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1728
+** dp2=CKIN2 Same as 'd2=CKIN2&p2=CKIN2'
17261729
** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
17271730
** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
17281731
** p=CX ... from CX back to time of CHECKIN
17291732
** from=CX ... shortest path from CX back to CHECKIN
17301733
** ft=CHECKIN "Forward To": Show decendents forward to CHECKIN
@@ -1844,10 +1847,11 @@
18441847
int to_rid = name_choice("to","to2",&zTo2); /* to= for path timelines */
18451848
int noMerge = P("shortest")==0; /* Follow merge links if shorter */
18461849
int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
18471850
int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
18481851
int pd_rid;
1852
+ const char *zDPName; /* Value of p=, d=, or dp= params */
18491853
double rBefore, rAfter, rCirca; /* Boundary times */
18501854
const char *z;
18511855
char *zOlderButton = 0; /* URL for Older button at the bottom */
18521856
char *zOlderButtonLabel = 0; /* Label for the Older Button */
18531857
char *zNewerButton = 0; /* URL for Newer button at the top */
@@ -1902,21 +1906,20 @@
19021906
}else{
19031907
nEntry = 50;
19041908
}
19051909
19061910
/* Query parameters d=, p=, and f= and variants */
1907
- z = P("p");
1908
- p_rid = z ? name_to_typed_rid(z,"ci") : 0;
1909
- z = P("d");
1910
- d_rid = z ? name_to_typed_rid(z,"ci") : 0;
1911
+ p_rid = name_choice("p","p2", &zDPName);
1912
+ d_rid = name_choice("d","d2", &zDPName);
19111913
z = P("f");
19121914
f_rid = z ? name_to_typed_rid(z,"ci") : 0;
19131915
z = P("df");
19141916
if( z && (d_rid = name_to_typed_rid(z,"ci"))!=0 ){
19151917
nEntry = 0;
19161918
useDividers = 0;
19171919
cgi_replace_query_parameter("d",fossil_strdup(z));
1920
+ zDPName = z;
19181921
}
19191922
19201923
/* Undocumented query parameter to set JS mode */
19211924
builtin_set_js_delivery_mode(P("jsmode"),1);
19221925
@@ -1936,11 +1939,11 @@
19361939
showCherrypicks = 0;
19371940
}
19381941
19391942
/* To view the timeline, must have permission to read project data.
19401943
*/
1941
- pd_rid = name_to_typed_rid(P("dp"),"ci");
1944
+ pd_rid = name_choice("dp","dp2",&zDPName);
19421945
if( pd_rid ){
19431946
p_rid = d_rid = pd_rid;
19441947
}
19451948
login_check_credentials();
19461949
if( (!g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki && !g.perm.RdForum)
@@ -2329,11 +2332,11 @@
23292332
db_multi_exec(
23302333
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)"
23312334
);
23322335
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d",
23332336
p_rid ? p_rid : d_rid);
2334
- zCiName = pd_rid ? P("pd") : p_rid ? P("p") : P("d");
2337
+ zCiName = zDPName;
23352338
if( zCiName==0 ) zCiName = zUuid;
23362339
blob_append_sql(&sql, " AND event.objid IN ok");
23372340
nd = 0;
23382341
if( d_rid ){
23392342
Stmt s;
23402343
--- src/timeline.c
+++ src/timeline.c
@@ -1718,13 +1718,16 @@
1718 ** n=COUNT Maximum number of events. "all" for no limit
1719 ** n1=COUNT Same as "n" but doesn't set the display-preference cookie
1720 ** Use "n1=COUNT" for a one-time display change
1721 ** p=CHECKIN Parents and ancestors of CHECKIN
1722 ** bt=PRIOR ... going back to PRIOR
 
1723 ** d=CHECKIN Children and descendants of CHECKIN
 
1724 ** ft=DESCENDANT ... going forward to DESCENDANT
1725 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
 
1726 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1727 ** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1728 ** p=CX ... from CX back to time of CHECKIN
1729 ** from=CX ... shortest path from CX back to CHECKIN
1730 ** ft=CHECKIN "Forward To": Show decendents forward to CHECKIN
@@ -1844,10 +1847,11 @@
1844 int to_rid = name_choice("to","to2",&zTo2); /* to= for path timelines */
1845 int noMerge = P("shortest")==0; /* Follow merge links if shorter */
1846 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
1847 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
1848 int pd_rid;
 
1849 double rBefore, rAfter, rCirca; /* Boundary times */
1850 const char *z;
1851 char *zOlderButton = 0; /* URL for Older button at the bottom */
1852 char *zOlderButtonLabel = 0; /* Label for the Older Button */
1853 char *zNewerButton = 0; /* URL for Newer button at the top */
@@ -1902,21 +1906,20 @@
1902 }else{
1903 nEntry = 50;
1904 }
1905
1906 /* Query parameters d=, p=, and f= and variants */
1907 z = P("p");
1908 p_rid = z ? name_to_typed_rid(z,"ci") : 0;
1909 z = P("d");
1910 d_rid = z ? name_to_typed_rid(z,"ci") : 0;
1911 z = P("f");
1912 f_rid = z ? name_to_typed_rid(z,"ci") : 0;
1913 z = P("df");
1914 if( z && (d_rid = name_to_typed_rid(z,"ci"))!=0 ){
1915 nEntry = 0;
1916 useDividers = 0;
1917 cgi_replace_query_parameter("d",fossil_strdup(z));
 
1918 }
1919
1920 /* Undocumented query parameter to set JS mode */
1921 builtin_set_js_delivery_mode(P("jsmode"),1);
1922
@@ -1936,11 +1939,11 @@
1936 showCherrypicks = 0;
1937 }
1938
1939 /* To view the timeline, must have permission to read project data.
1940 */
1941 pd_rid = name_to_typed_rid(P("dp"),"ci");
1942 if( pd_rid ){
1943 p_rid = d_rid = pd_rid;
1944 }
1945 login_check_credentials();
1946 if( (!g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki && !g.perm.RdForum)
@@ -2329,11 +2332,11 @@
2329 db_multi_exec(
2330 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)"
2331 );
2332 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d",
2333 p_rid ? p_rid : d_rid);
2334 zCiName = pd_rid ? P("pd") : p_rid ? P("p") : P("d");
2335 if( zCiName==0 ) zCiName = zUuid;
2336 blob_append_sql(&sql, " AND event.objid IN ok");
2337 nd = 0;
2338 if( d_rid ){
2339 Stmt s;
2340
--- src/timeline.c
+++ src/timeline.c
@@ -1718,13 +1718,16 @@
1718 ** n=COUNT Maximum number of events. "all" for no limit
1719 ** n1=COUNT Same as "n" but doesn't set the display-preference cookie
1720 ** Use "n1=COUNT" for a one-time display change
1721 ** p=CHECKIN Parents and ancestors of CHECKIN
1722 ** bt=PRIOR ... going back to PRIOR
1723 ** p2=CKIN2 ... use CKIN2 if CHECKIN is not found
1724 ** d=CHECKIN Children and descendants of CHECKIN
1725 ** d2=CKIN2 ... Use CKIN2 if CHECKIN is not found
1726 ** ft=DESCENDANT ... going forward to DESCENDANT
1727 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1728 ** dp2=CKIN2 Same as 'd2=CKIN2&p2=CKIN2'
1729 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1730 ** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1731 ** p=CX ... from CX back to time of CHECKIN
1732 ** from=CX ... shortest path from CX back to CHECKIN
1733 ** ft=CHECKIN "Forward To": Show decendents forward to CHECKIN
@@ -1844,10 +1847,11 @@
1847 int to_rid = name_choice("to","to2",&zTo2); /* to= for path timelines */
1848 int noMerge = P("shortest")==0; /* Follow merge links if shorter */
1849 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
1850 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
1851 int pd_rid;
1852 const char *zDPName; /* Value of p=, d=, or dp= params */
1853 double rBefore, rAfter, rCirca; /* Boundary times */
1854 const char *z;
1855 char *zOlderButton = 0; /* URL for Older button at the bottom */
1856 char *zOlderButtonLabel = 0; /* Label for the Older Button */
1857 char *zNewerButton = 0; /* URL for Newer button at the top */
@@ -1902,21 +1906,20 @@
1906 }else{
1907 nEntry = 50;
1908 }
1909
1910 /* Query parameters d=, p=, and f= and variants */
1911 p_rid = name_choice("p","p2", &zDPName);
1912 d_rid = name_choice("d","d2", &zDPName);
 
 
1913 z = P("f");
1914 f_rid = z ? name_to_typed_rid(z,"ci") : 0;
1915 z = P("df");
1916 if( z && (d_rid = name_to_typed_rid(z,"ci"))!=0 ){
1917 nEntry = 0;
1918 useDividers = 0;
1919 cgi_replace_query_parameter("d",fossil_strdup(z));
1920 zDPName = z;
1921 }
1922
1923 /* Undocumented query parameter to set JS mode */
1924 builtin_set_js_delivery_mode(P("jsmode"),1);
1925
@@ -1936,11 +1939,11 @@
1939 showCherrypicks = 0;
1940 }
1941
1942 /* To view the timeline, must have permission to read project data.
1943 */
1944 pd_rid = name_choice("dp","dp2",&zDPName);
1945 if( pd_rid ){
1946 p_rid = d_rid = pd_rid;
1947 }
1948 login_check_credentials();
1949 if( (!g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki && !g.perm.RdForum)
@@ -2329,11 +2332,11 @@
2332 db_multi_exec(
2333 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)"
2334 );
2335 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d",
2336 p_rid ? p_rid : d_rid);
2337 zCiName = zDPName;
2338 if( zCiName==0 ) zCiName = zUuid;
2339 blob_append_sql(&sql, " AND event.objid IN ok");
2340 nd = 0;
2341 if( d_rid ){
2342 Stmt s;
2343
--- src/unversioned.c
+++ src/unversioned.c
@@ -291,11 +291,11 @@
291291
** touch FILE ... Update the TIMESTAMP on all of the listed files
292292
**
293293
** Options:
294294
** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add",
295295
** "edit", "remove", and "touch" subcommands.
296
-** -R|--repository REPO Use FILE as the repository
296
+** -R|--repository REPO Use REPO as the repository
297297
*/
298298
void unversioned_cmd(void){
299299
const char *zCmd;
300300
int nCmd;
301301
const char *zMtime = find_option("mtime", 0, 1);
@@ -520,10 +520,64 @@
520520
db_end_transaction(0);
521521
}else{
522522
usage("add|cat|edit|export|list|revert|remove|sync|touch");
523523
}
524524
}
525
+
526
+/*
527
+** Emit an HTML form for uploading a new unversioned file if
528
+** the current user has WrUnver permissions, else this is
529
+** a no-op.
530
+**
531
+** If this function detects that the form it emits has been submitted,
532
+** it will add the uploaded file to the unversioned file list before
533
+** returning.
534
+**
535
+** Intended only for use by /uvlist, and its form's action is that
536
+** page.
537
+*/
538
+static void uvlist_upload(void){
539
+ const char * aContent;
540
+ if( !g.perm.WrUnver ) return;
541
+ aContent = P("f");
542
+ if( aContent!=0 ){
543
+ const char * const zName = P("f:filename");
544
+ int const nContent = atoi(PD("f:bytes","0"));
545
+ const char * zError = 0;
546
+ Blob content;
547
+ if( zName[0]==0 ){
548
+ zError = "be an empty string";
549
+ }else if( contains_whitespace(zName) ){
550
+ zError = "contain spaces";
551
+ }
552
+ if( zError ){
553
+ fossil_fatal("Unversioned filenames may not %s: %h",
554
+ zError, zName);
555
+ }
556
+ unversioned_schema();
557
+ db_begin_transaction();
558
+ content_rcvid_init("#!fossil /uvlist upload");
559
+ blob_init(&content, aContent, nContent);
560
+ unversioned_write(zName, &content, time(0));
561
+ blob_reset(&content);
562
+ db_end_transaction(0);
563
+ CX("<div>Added: %h</div>", zName);
564
+ }
565
+ form_begin("enctype='multipart/form-data'", "%R/uvlist");
566
+ @ <label for='uvupload'>Upload unversioned file:</label>
567
+ @ <input type='file' id='uvupload' name='f'/>
568
+ @ <input type='submit' id='uvsubmit' value='Upload' disabled='disabled'/>
569
+ @ </form>
570
+ @ <script nonce='%h(style_nonce())'>;/* unversioned.c:%d(__LINE__) */
571
+ @ var upl = document.getElementById('uvupload');
572
+ @ var sbm = document.getElementById('uvsubmit');
573
+ @ upl.onchange = function(){
574
+ @ if (!upl.value) sbm.setAttribute('disabled', 'disabled');
575
+ @ else sbm.removeAttribute('disabled');
576
+ @ }
577
+ @ </script>
578
+}
525579
526580
/*
527581
** WEBPAGE: uvlist
528582
**
529583
** Display a list of all unversioned files in the repository.
@@ -545,10 +599,11 @@
545599
login_check_credentials();
546600
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
547601
cgi_check_for_malice();
548602
etag_check(ETAG_DATA,0);
549603
style_header("Unversioned Files");
604
+ uvlist_upload();
550605
if( !db_table_exists("repository","unversioned") ){
551606
@ No unversioned files on this server
552607
style_finish_page();
553608
return;
554609
}
555610
--- src/unversioned.c
+++ src/unversioned.c
@@ -291,11 +291,11 @@
291 ** touch FILE ... Update the TIMESTAMP on all of the listed files
292 **
293 ** Options:
294 ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add",
295 ** "edit", "remove", and "touch" subcommands.
296 ** -R|--repository REPO Use FILE as the repository
297 */
298 void unversioned_cmd(void){
299 const char *zCmd;
300 int nCmd;
301 const char *zMtime = find_option("mtime", 0, 1);
@@ -520,10 +520,64 @@
520 db_end_transaction(0);
521 }else{
522 usage("add|cat|edit|export|list|revert|remove|sync|touch");
523 }
524 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
526 /*
527 ** WEBPAGE: uvlist
528 **
529 ** Display a list of all unversioned files in the repository.
@@ -545,10 +599,11 @@
545 login_check_credentials();
546 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
547 cgi_check_for_malice();
548 etag_check(ETAG_DATA,0);
549 style_header("Unversioned Files");
 
550 if( !db_table_exists("repository","unversioned") ){
551 @ No unversioned files on this server
552 style_finish_page();
553 return;
554 }
555
--- src/unversioned.c
+++ src/unversioned.c
@@ -291,11 +291,11 @@
291 ** touch FILE ... Update the TIMESTAMP on all of the listed files
292 **
293 ** Options:
294 ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add",
295 ** "edit", "remove", and "touch" subcommands.
296 ** -R|--repository REPO Use REPO as the repository
297 */
298 void unversioned_cmd(void){
299 const char *zCmd;
300 int nCmd;
301 const char *zMtime = find_option("mtime", 0, 1);
@@ -520,10 +520,64 @@
520 db_end_transaction(0);
521 }else{
522 usage("add|cat|edit|export|list|revert|remove|sync|touch");
523 }
524 }
525
526 /*
527 ** Emit an HTML form for uploading a new unversioned file if
528 ** the current user has WrUnver permissions, else this is
529 ** a no-op.
530 **
531 ** If this function detects that the form it emits has been submitted,
532 ** it will add the uploaded file to the unversioned file list before
533 ** returning.
534 **
535 ** Intended only for use by /uvlist, and its form's action is that
536 ** page.
537 */
538 static void uvlist_upload(void){
539 const char * aContent;
540 if( !g.perm.WrUnver ) return;
541 aContent = P("f");
542 if( aContent!=0 ){
543 const char * const zName = P("f:filename");
544 int const nContent = atoi(PD("f:bytes","0"));
545 const char * zError = 0;
546 Blob content;
547 if( zName[0]==0 ){
548 zError = "be an empty string";
549 }else if( contains_whitespace(zName) ){
550 zError = "contain spaces";
551 }
552 if( zError ){
553 fossil_fatal("Unversioned filenames may not %s: %h",
554 zError, zName);
555 }
556 unversioned_schema();
557 db_begin_transaction();
558 content_rcvid_init("#!fossil /uvlist upload");
559 blob_init(&content, aContent, nContent);
560 unversioned_write(zName, &content, time(0));
561 blob_reset(&content);
562 db_end_transaction(0);
563 CX("<div>Added: %h</div>", zName);
564 }
565 form_begin("enctype='multipart/form-data'", "%R/uvlist");
566 @ <label for='uvupload'>Upload unversioned file:</label>
567 @ <input type='file' id='uvupload' name='f'/>
568 @ <input type='submit' id='uvsubmit' value='Upload' disabled='disabled'/>
569 @ </form>
570 @ <script nonce='%h(style_nonce())'>;/* unversioned.c:%d(__LINE__) */
571 @ var upl = document.getElementById('uvupload');
572 @ var sbm = document.getElementById('uvsubmit');
573 @ upl.onchange = function(){
574 @ if (!upl.value) sbm.setAttribute('disabled', 'disabled');
575 @ else sbm.removeAttribute('disabled');
576 @ }
577 @ </script>
578 }
579
580 /*
581 ** WEBPAGE: uvlist
582 **
583 ** Display a list of all unversioned files in the repository.
@@ -545,10 +599,11 @@
599 login_check_credentials();
600 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
601 cgi_check_for_malice();
602 etag_check(ETAG_DATA,0);
603 style_header("Unversioned Files");
604 uvlist_upload();
605 if( !db_table_exists("repository","unversioned") ){
606 @ No unversioned files on this server
607 style_finish_page();
608 return;
609 }
610
+11 -1
--- src/wiki.c
+++ src/wiki.c
@@ -1845,10 +1845,11 @@
18451845
** The "id" query parameter is required. "pid" is optional. If "pid"
18461846
** is omitted, then the diff is against the first parent of the child.
18471847
*/
18481848
void wdiff_page(void){
18491849
const char *zId;
1850
+ const char *zIdFull;
18501851
const char *zPid;
18511852
Manifest *pW1, *pW2 = 0;
18521853
int rid1, rid2, nextRid;
18531854
Blob w1, w2, d;
18541855
DiffConfig DCfg;
@@ -1859,11 +1860,20 @@
18591860
if( zId==0 ){
18601861
rid1 = atoi(PD("rid","0"));
18611862
}else{
18621863
rid1 = name_to_typed_rid(zId, "w");
18631864
}
1864
- zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid1);
1865
+ zIdFull = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid1);
1866
+ if( zIdFull==0 ){
1867
+ if( zId ){
1868
+ webpage_notfound_error("No such wiki page: \"%s\"", zId);
1869
+ }else{
1870
+ webpage_notfound_error("No such wiki page: %d", rid1);
1871
+ }
1872
+ return;
1873
+ }
1874
+ zId = zIdFull;
18651875
pW1 = manifest_get(rid1, CFTYPE_WIKI, 0);
18661876
if( pW1==0 ) fossil_redirect_home();
18671877
blob_init(&w1, pW1->zWiki, -1);
18681878
zPid = P("pid");
18691879
if( ( zPid==0 || zPid[0] == 0 ) && pW1->nParent ){
18701880
--- src/wiki.c
+++ src/wiki.c
@@ -1845,10 +1845,11 @@
1845 ** The "id" query parameter is required. "pid" is optional. If "pid"
1846 ** is omitted, then the diff is against the first parent of the child.
1847 */
1848 void wdiff_page(void){
1849 const char *zId;
 
1850 const char *zPid;
1851 Manifest *pW1, *pW2 = 0;
1852 int rid1, rid2, nextRid;
1853 Blob w1, w2, d;
1854 DiffConfig DCfg;
@@ -1859,11 +1860,20 @@
1859 if( zId==0 ){
1860 rid1 = atoi(PD("rid","0"));
1861 }else{
1862 rid1 = name_to_typed_rid(zId, "w");
1863 }
1864 zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid1);
 
 
 
 
 
 
 
 
 
1865 pW1 = manifest_get(rid1, CFTYPE_WIKI, 0);
1866 if( pW1==0 ) fossil_redirect_home();
1867 blob_init(&w1, pW1->zWiki, -1);
1868 zPid = P("pid");
1869 if( ( zPid==0 || zPid[0] == 0 ) && pW1->nParent ){
1870
--- src/wiki.c
+++ src/wiki.c
@@ -1845,10 +1845,11 @@
1845 ** The "id" query parameter is required. "pid" is optional. If "pid"
1846 ** is omitted, then the diff is against the first parent of the child.
1847 */
1848 void wdiff_page(void){
1849 const char *zId;
1850 const char *zIdFull;
1851 const char *zPid;
1852 Manifest *pW1, *pW2 = 0;
1853 int rid1, rid2, nextRid;
1854 Blob w1, w2, d;
1855 DiffConfig DCfg;
@@ -1859,11 +1860,20 @@
1860 if( zId==0 ){
1861 rid1 = atoi(PD("rid","0"));
1862 }else{
1863 rid1 = name_to_typed_rid(zId, "w");
1864 }
1865 zIdFull = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid1);
1866 if( zIdFull==0 ){
1867 if( zId ){
1868 webpage_notfound_error("No such wiki page: \"%s\"", zId);
1869 }else{
1870 webpage_notfound_error("No such wiki page: %d", rid1);
1871 }
1872 return;
1873 }
1874 zId = zIdFull;
1875 pW1 = manifest_get(rid1, CFTYPE_WIKI, 0);
1876 if( pW1==0 ) fossil_redirect_home();
1877 blob_init(&w1, pW1->zWiki, -1);
1878 zPid = P("pid");
1879 if( ( zPid==0 || zPid[0] == 0 ) && pW1->nParent ){
1880
+1 -2
--- test/amend.test
+++ test/amend.test
@@ -296,20 +296,19 @@
296296
set tc 0
297297
foreach {tagt result} $tagtests {
298298
incr tc
299299
set tags {}
300300
set cancels {}
301
- set t1exp ""
301
+ set t1exp [join $result ", "]
302302
set t2exp "*"
303303
set t3exp "*"
304304
set t5exp "*"
305305
foreach tag $tagt {
306306
lappend tags -tag $tag
307307
lappend cancels -cancel $tag
308308
}
309309
foreach res $result {
310
- append t1exp ", $res"
311310
append t3exp "Add*tag*\"$res\".*"
312311
append t5exp "Cancel*tag*\"$res\".*"
313312
}
314313
foreach res [lsort -nocase $result] {
315314
append t2exp "sym-$res*"
316315
--- test/amend.test
+++ test/amend.test
@@ -296,20 +296,19 @@
296 set tc 0
297 foreach {tagt result} $tagtests {
298 incr tc
299 set tags {}
300 set cancels {}
301 set t1exp ""
302 set t2exp "*"
303 set t3exp "*"
304 set t5exp "*"
305 foreach tag $tagt {
306 lappend tags -tag $tag
307 lappend cancels -cancel $tag
308 }
309 foreach res $result {
310 append t1exp ", $res"
311 append t3exp "Add*tag*\"$res\".*"
312 append t5exp "Cancel*tag*\"$res\".*"
313 }
314 foreach res [lsort -nocase $result] {
315 append t2exp "sym-$res*"
316
--- test/amend.test
+++ test/amend.test
@@ -296,20 +296,19 @@
296 set tc 0
297 foreach {tagt result} $tagtests {
298 incr tc
299 set tags {}
300 set cancels {}
301 set t1exp [join $result ", "]
302 set t2exp "*"
303 set t3exp "*"
304 set t5exp "*"
305 foreach tag $tagt {
306 lappend tags -tag $tag
307 lappend cancels -cancel $tag
308 }
309 foreach res $result {
 
310 append t3exp "Add*tag*\"$res\".*"
311 append t5exp "Cancel*tag*\"$res\".*"
312 }
313 foreach res [lsort -nocase $result] {
314 append t2exp "sym-$res*"
315
--- test/merge5.test
+++ test/merge5.test
@@ -23,11 +23,11 @@
2323
}
2424
protOut {
2525
fossil sqlite3 --no-repository reacts badly to SQL dumped from
2626
repositories created from fossil older than version 2.0.
2727
}
28
-test merge5-sqlite3-issue false knownBug
28
+#test merge5-sqlite3-issue false knownBug
2929
test_cleanup_then_return
3030
3131
# Verify the results of a check-out
3232
#
3333
proc checkout-test {testid expected_content} {
3434
--- test/merge5.test
+++ test/merge5.test
@@ -23,11 +23,11 @@
23 }
24 protOut {
25 fossil sqlite3 --no-repository reacts badly to SQL dumped from
26 repositories created from fossil older than version 2.0.
27 }
28 test merge5-sqlite3-issue false knownBug
29 test_cleanup_then_return
30
31 # Verify the results of a check-out
32 #
33 proc checkout-test {testid expected_content} {
34
--- test/merge5.test
+++ test/merge5.test
@@ -23,11 +23,11 @@
23 }
24 protOut {
25 fossil sqlite3 --no-repository reacts badly to SQL dumped from
26 repositories created from fossil older than version 2.0.
27 }
28 #test merge5-sqlite3-issue false knownBug
29 test_cleanup_then_return
30
31 # Verify the results of a check-out
32 #
33 proc checkout-test {testid expected_content} {
34
+16 -15
--- test/stash.test
+++ test/stash.test
@@ -168,14 +168,14 @@
168168
169169
########
170170
# fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
171171
# fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
172172
173
-fossil stash show
174
-test stash-1-show {[normalize_result] eq $diff_stash_1}
175
-fossil stash diff
176
-test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug
173
+#fossil stash show
174
+#test stash-1-show {[normalize_result] eq $diff_stash_1}
175
+#fossil stash diff
176
+#test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug
177177
178178
########
179179
# fossil stash pop
180180
181181
stash-test 2 pop {
@@ -206,16 +206,16 @@
206206
# fossil: ./src/delta.c:231: checksum: Assertion '...' failed.
207207
# Should be triggered by this stash-WY-1 test.
208208
fossil checkout --force c1
209209
fossil clean
210210
fossil mv --soft f1 f1new
211
-stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
212
- REVERT f1
213
- DELETE f1new
214
-} -changes {
215
-} -addremove {
216
-} -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
211
+#stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
212
+# REVERT f1
213
+# DELETE f1new
214
+#} -changes {
215
+#} -addremove {
216
+#} -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
217217
# TODO: add tests that verify the saved stash is sensible. Possibly
218218
# by applying it and checking results. But until the SQLITE_CONSTRAINT
219219
# error is fixed, there is nothing stashed to test.
220220
221221
@@ -296,16 +296,17 @@
296296
}] -changes {
297297
RENAMED f2 -> f2n
298298
} -addremove {
299299
} -exists {f1 f2n} -notexists {f2}
300300
301
-stash-test 3-2 {save -m f2n} {
302
- REVERT f2
303
- DELETE f2n
304
-} -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
301
+fossil stash save -m f2n
302
+#stash-test 3-2 {save -m f2n} {
303
+# REVERT f2
304
+# DELETE f2n
305
+#} -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
305306
fossil stash show
306
-test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
307
+#test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
307308
test stash-3-2-show-2 {[regexp {\sf2n} $RESULT]}
308309
stash-test 3-2-pop {pop} {
309310
UPDATE f1
310311
UPDATE f2n
311312
} -changes {
312313
--- test/stash.test
+++ test/stash.test
@@ -168,14 +168,14 @@
168
169 ########
170 # fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
171 # fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
172
173 fossil stash show
174 test stash-1-show {[normalize_result] eq $diff_stash_1}
175 fossil stash diff
176 test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug
177
178 ########
179 # fossil stash pop
180
181 stash-test 2 pop {
@@ -206,16 +206,16 @@
206 # fossil: ./src/delta.c:231: checksum: Assertion '...' failed.
207 # Should be triggered by this stash-WY-1 test.
208 fossil checkout --force c1
209 fossil clean
210 fossil mv --soft f1 f1new
211 stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
212 REVERT f1
213 DELETE f1new
214 } -changes {
215 } -addremove {
216 } -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
217 # TODO: add tests that verify the saved stash is sensible. Possibly
218 # by applying it and checking results. But until the SQLITE_CONSTRAINT
219 # error is fixed, there is nothing stashed to test.
220
221
@@ -296,16 +296,17 @@
296 }] -changes {
297 RENAMED f2 -> f2n
298 } -addremove {
299 } -exists {f1 f2n} -notexists {f2}
300
301 stash-test 3-2 {save -m f2n} {
302 REVERT f2
303 DELETE f2n
304 } -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
 
305 fossil stash show
306 test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
307 test stash-3-2-show-2 {[regexp {\sf2n} $RESULT]}
308 stash-test 3-2-pop {pop} {
309 UPDATE f1
310 UPDATE f2n
311 } -changes {
312
--- test/stash.test
+++ test/stash.test
@@ -168,14 +168,14 @@
168
169 ########
170 # fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
171 # fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
172
173 #fossil stash show
174 #test stash-1-show {[normalize_result] eq $diff_stash_1}
175 #fossil stash diff
176 #test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug
177
178 ########
179 # fossil stash pop
180
181 stash-test 2 pop {
@@ -206,16 +206,16 @@
206 # fossil: ./src/delta.c:231: checksum: Assertion '...' failed.
207 # Should be triggered by this stash-WY-1 test.
208 fossil checkout --force c1
209 fossil clean
210 fossil mv --soft f1 f1new
211 #stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
212 # REVERT f1
213 # DELETE f1new
214 #} -changes {
215 #} -addremove {
216 #} -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
217 # TODO: add tests that verify the saved stash is sensible. Possibly
218 # by applying it and checking results. But until the SQLITE_CONSTRAINT
219 # error is fixed, there is nothing stashed to test.
220
221
@@ -296,16 +296,17 @@
296 }] -changes {
297 RENAMED f2 -> f2n
298 } -addremove {
299 } -exists {f1 f2n} -notexists {f2}
300
301 fossil stash save -m f2n
302 #stash-test 3-2 {save -m f2n} {
303 # REVERT f2
304 # DELETE f2n
305 #} -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
306 fossil stash show
307 #test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
308 test stash-3-2-show-2 {[regexp {\sf2n} $RESULT]}
309 stash-test 3-2-pop {pop} {
310 UPDATE f1
311 UPDATE f2n
312 } -changes {
313
--- test/tester.tcl
+++ test/tester.tcl
@@ -308,10 +308,11 @@
308308
comment-format \
309309
crlf-glob \
310310
crnl-glob \
311311
default-csp \
312312
default-perms \
313
+ default-skin \
313314
diff-binary \
314315
diff-command \
315316
dont-commit \
316317
dont-push \
317318
dotfiles \
318319
--- test/tester.tcl
+++ test/tester.tcl
@@ -308,10 +308,11 @@
308 comment-format \
309 crlf-glob \
310 crnl-glob \
311 default-csp \
312 default-perms \
 
313 diff-binary \
314 diff-command \
315 dont-commit \
316 dont-push \
317 dotfiles \
318
--- test/tester.tcl
+++ test/tester.tcl
@@ -308,10 +308,11 @@
308 comment-format \
309 crlf-glob \
310 crnl-glob \
311 default-csp \
312 default-perms \
313 default-skin \
314 diff-binary \
315 diff-command \
316 dont-commit \
317 dont-push \
318 dotfiles \
319
+47 -47
--- test/utf.test
+++ test/utf.test
@@ -35,11 +35,11 @@
3535
set i 1
3636
foreach {fileName result} $args {
3737
set fileName [file join $tempPath $fileName]
3838
fossil test-looks-like-utf $fileName
3939
set result [string map [list %TEMP% $tempPath \r\n \n] $result]
40
- # if {$::RESULT ne $result} {puts stdout $::RESULT}
40
+ # if {$::RESULT ne $result} {puts stdout $::RESULT; exit}
4141
test utf-check-$testname.$i {$::RESULT eq $result}
4242
incr i
4343
}
4444
}
4545
@@ -17609,25 +17609,25 @@
1760917609
Has flag LOOK_LONG: no
1761017610
Has flag LOOK_INVALID: no
1761117611
Has flag LOOK_ODD: no
1761217612
Has flag LOOK_SHORT: no}
1761317613
17614
-utf-check 1179 utf-check-1179-2-129-1.jnk \
17615
-{File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
17616
-Starts with UTF-8 BOM: no
17617
-Starts with UTF-16 BOM: yes
17618
-Looks like UTF-8: no
17619
-Has flag LOOK_NUL: yes
17620
-Has flag LOOK_CR: no
17621
-Has flag LOOK_LONE_CR: no
17622
-Has flag LOOK_LF: no
17623
-Has flag LOOK_LONE_LF: no
17624
-Has flag LOOK_CRLF: no
17625
-Has flag LOOK_LONG: no
17626
-Has flag LOOK_INVALID: yes
17627
-Has flag LOOK_ODD: no
17628
-Has flag LOOK_SHORT: no}
17614
+#utf-check 1179 utf-check-1179-2-129-1.jnk \
17615
+#{File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
17616
+#Starts with UTF-8 BOM: no
17617
+#Starts with UTF-16 BOM: yes
17618
+#Looks like UTF-8: yes
17619
+#Has flag LOOK_NUL: no
17620
+#Has flag LOOK_CR: no
17621
+#Has flag LOOK_LONE_CR: no
17622
+#Has flag LOOK_LF: no
17623
+#Has flag LOOK_LONE_LF: no
17624
+#Has flag LOOK_CRLF: no
17625
+#Has flag LOOK_LONG: no
17626
+#Has flag LOOK_INVALID: yes
17627
+#Has flag LOOK_ODD: no
17628
+#Has flag LOOK_SHORT: no}
1762917629
1763017630
utf-check 1180 utf-check-1180-2-130-0.jnk \
1763117631
{File "%TEMP%/utf-check-1180-2-130-0.jnk" has 4 bytes.
1763217632
Starts with UTF-8 BOM: no
1763317633
Starts with UTF-16 BOM: yes
@@ -24121,41 +24121,41 @@
2412124121
Has flag LOOK_LONG: no
2412224122
Has flag LOOK_INVALID: yes
2412324123
Has flag LOOK_ODD: no
2412424124
Has flag LOOK_SHORT: no}
2412524125
24126
-utf-check 1586 utf-check-1586-3-128-0.jnk \
24127
-{File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
24128
-Starts with UTF-8 BOM: no
24129
-Starts with UTF-16 BOM: no
24130
-Looks like UTF-8: no
24131
-Has flag LOOK_NUL: yes
24132
-Has flag LOOK_CR: no
24133
-Has flag LOOK_LONE_CR: no
24134
-Has flag LOOK_LF: no
24135
-Has flag LOOK_LONE_LF: no
24136
-Has flag LOOK_CRLF: no
24137
-Has flag LOOK_LONG: no
24138
-Has flag LOOK_INVALID: yes
24139
-Has flag LOOK_ODD: no
24140
-Has flag LOOK_SHORT: no}
24141
-
24142
-utf-check 1587 utf-check-1587-3-128-1.jnk \
24143
-{File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
24144
-Starts with UTF-8 BOM: no
24145
-Starts with UTF-16 BOM: no
24146
-Looks like UTF-8: no
24147
-Has flag LOOK_NUL: yes
24148
-Has flag LOOK_CR: no
24149
-Has flag LOOK_LONE_CR: no
24150
-Has flag LOOK_LF: no
24151
-Has flag LOOK_LONE_LF: no
24152
-Has flag LOOK_CRLF: no
24153
-Has flag LOOK_LONG: no
24154
-Has flag LOOK_INVALID: yes
24155
-Has flag LOOK_ODD: no
24156
-Has flag LOOK_SHORT: no}
24126
+#utf-check 1586 utf-check-1586-3-128-0.jnk \
24127
+#{File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
24128
+#Starts with UTF-8 BOM: no
24129
+#Starts with UTF-16 BOM: reversed
24130
+#Looks like UTF-16: no
24131
+#Has flag LOOK_NUL: yes
24132
+#Has flag LOOK_CR: no
24133
+#Has flag LOOK_LONE_CR: no
24134
+#Has flag LOOK_LF: no
24135
+#Has flag LOOK_LONE_LF: no
24136
+#Has flag LOOK_CRLF: no
24137
+#Has flag LOOK_LONG: no
24138
+#Has flag LOOK_INVALID: no
24139
+#Has flag LOOK_ODD: no
24140
+#Has flag LOOK_SHORT: no}
24141
+
24142
+#utf-check 1587 utf-check-1587-3-128-1.jnk \
24143
+#{File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
24144
+#Starts with UTF-8 BOM: no
24145
+#Starts with UTF-16 BOM: reversed
24146
+#Looks like UTF-8: no
24147
+#Has flag LOOK_NUL: yes
24148
+#Has flag LOOK_CR: no
24149
+#Has flag LOOK_LONE_CR: no
24150
+#Has flag LOOK_LF: no
24151
+#Has flag LOOK_LONE_LF: no
24152
+#Has flag LOOK_CRLF: no
24153
+#Has flag LOOK_LONG: no
24154
+#Has flag LOOK_INVALID: yes
24155
+#Has flag LOOK_ODD: no
24156
+#Has flag LOOK_SHORT: no}
2415724157
2415824158
utf-check 1588 utf-check-1588-3-129-0.jnk \
2415924159
{File "%TEMP%/utf-check-1588-3-129-0.jnk" has 6 bytes.
2416024160
Starts with UTF-8 BOM: no
2416124161
Starts with UTF-16 BOM: no
2416224162
--- test/utf.test
+++ test/utf.test
@@ -35,11 +35,11 @@
35 set i 1
36 foreach {fileName result} $args {
37 set fileName [file join $tempPath $fileName]
38 fossil test-looks-like-utf $fileName
39 set result [string map [list %TEMP% $tempPath \r\n \n] $result]
40 # if {$::RESULT ne $result} {puts stdout $::RESULT}
41 test utf-check-$testname.$i {$::RESULT eq $result}
42 incr i
43 }
44 }
45
@@ -17609,25 +17609,25 @@
17609 Has flag LOOK_LONG: no
17610 Has flag LOOK_INVALID: no
17611 Has flag LOOK_ODD: no
17612 Has flag LOOK_SHORT: no}
17613
17614 utf-check 1179 utf-check-1179-2-129-1.jnk \
17615 {File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
17616 Starts with UTF-8 BOM: no
17617 Starts with UTF-16 BOM: yes
17618 Looks like UTF-8: no
17619 Has flag LOOK_NUL: yes
17620 Has flag LOOK_CR: no
17621 Has flag LOOK_LONE_CR: no
17622 Has flag LOOK_LF: no
17623 Has flag LOOK_LONE_LF: no
17624 Has flag LOOK_CRLF: no
17625 Has flag LOOK_LONG: no
17626 Has flag LOOK_INVALID: yes
17627 Has flag LOOK_ODD: no
17628 Has flag LOOK_SHORT: no}
17629
17630 utf-check 1180 utf-check-1180-2-130-0.jnk \
17631 {File "%TEMP%/utf-check-1180-2-130-0.jnk" has 4 bytes.
17632 Starts with UTF-8 BOM: no
17633 Starts with UTF-16 BOM: yes
@@ -24121,41 +24121,41 @@
24121 Has flag LOOK_LONG: no
24122 Has flag LOOK_INVALID: yes
24123 Has flag LOOK_ODD: no
24124 Has flag LOOK_SHORT: no}
24125
24126 utf-check 1586 utf-check-1586-3-128-0.jnk \
24127 {File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
24128 Starts with UTF-8 BOM: no
24129 Starts with UTF-16 BOM: no
24130 Looks like UTF-8: no
24131 Has flag LOOK_NUL: yes
24132 Has flag LOOK_CR: no
24133 Has flag LOOK_LONE_CR: no
24134 Has flag LOOK_LF: no
24135 Has flag LOOK_LONE_LF: no
24136 Has flag LOOK_CRLF: no
24137 Has flag LOOK_LONG: no
24138 Has flag LOOK_INVALID: yes
24139 Has flag LOOK_ODD: no
24140 Has flag LOOK_SHORT: no}
24141
24142 utf-check 1587 utf-check-1587-3-128-1.jnk \
24143 {File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
24144 Starts with UTF-8 BOM: no
24145 Starts with UTF-16 BOM: no
24146 Looks like UTF-8: no
24147 Has flag LOOK_NUL: yes
24148 Has flag LOOK_CR: no
24149 Has flag LOOK_LONE_CR: no
24150 Has flag LOOK_LF: no
24151 Has flag LOOK_LONE_LF: no
24152 Has flag LOOK_CRLF: no
24153 Has flag LOOK_LONG: no
24154 Has flag LOOK_INVALID: yes
24155 Has flag LOOK_ODD: no
24156 Has flag LOOK_SHORT: no}
24157
24158 utf-check 1588 utf-check-1588-3-129-0.jnk \
24159 {File "%TEMP%/utf-check-1588-3-129-0.jnk" has 6 bytes.
24160 Starts with UTF-8 BOM: no
24161 Starts with UTF-16 BOM: no
24162
--- test/utf.test
+++ test/utf.test
@@ -35,11 +35,11 @@
35 set i 1
36 foreach {fileName result} $args {
37 set fileName [file join $tempPath $fileName]
38 fossil test-looks-like-utf $fileName
39 set result [string map [list %TEMP% $tempPath \r\n \n] $result]
40 # if {$::RESULT ne $result} {puts stdout $::RESULT; exit}
41 test utf-check-$testname.$i {$::RESULT eq $result}
42 incr i
43 }
44 }
45
@@ -17609,25 +17609,25 @@
17609 Has flag LOOK_LONG: no
17610 Has flag LOOK_INVALID: no
17611 Has flag LOOK_ODD: no
17612 Has flag LOOK_SHORT: no}
17613
17614 #utf-check 1179 utf-check-1179-2-129-1.jnk \
17615 #{File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
17616 #Starts with UTF-8 BOM: no
17617 #Starts with UTF-16 BOM: yes
17618 #Looks like UTF-8: yes
17619 #Has flag LOOK_NUL: no
17620 #Has flag LOOK_CR: no
17621 #Has flag LOOK_LONE_CR: no
17622 #Has flag LOOK_LF: no
17623 #Has flag LOOK_LONE_LF: no
17624 #Has flag LOOK_CRLF: no
17625 #Has flag LOOK_LONG: no
17626 #Has flag LOOK_INVALID: yes
17627 #Has flag LOOK_ODD: no
17628 #Has flag LOOK_SHORT: no}
17629
17630 utf-check 1180 utf-check-1180-2-130-0.jnk \
17631 {File "%TEMP%/utf-check-1180-2-130-0.jnk" has 4 bytes.
17632 Starts with UTF-8 BOM: no
17633 Starts with UTF-16 BOM: yes
@@ -24121,41 +24121,41 @@
24121 Has flag LOOK_LONG: no
24122 Has flag LOOK_INVALID: yes
24123 Has flag LOOK_ODD: no
24124 Has flag LOOK_SHORT: no}
24125
24126 #utf-check 1586 utf-check-1586-3-128-0.jnk \
24127 #{File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
24128 #Starts with UTF-8 BOM: no
24129 #Starts with UTF-16 BOM: reversed
24130 #Looks like UTF-16: no
24131 #Has flag LOOK_NUL: yes
24132 #Has flag LOOK_CR: no
24133 #Has flag LOOK_LONE_CR: no
24134 #Has flag LOOK_LF: no
24135 #Has flag LOOK_LONE_LF: no
24136 #Has flag LOOK_CRLF: no
24137 #Has flag LOOK_LONG: no
24138 #Has flag LOOK_INVALID: no
24139 #Has flag LOOK_ODD: no
24140 #Has flag LOOK_SHORT: no}
24141
24142 #utf-check 1587 utf-check-1587-3-128-1.jnk \
24143 #{File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
24144 #Starts with UTF-8 BOM: no
24145 #Starts with UTF-16 BOM: reversed
24146 #Looks like UTF-8: no
24147 #Has flag LOOK_NUL: yes
24148 #Has flag LOOK_CR: no
24149 #Has flag LOOK_LONE_CR: no
24150 #Has flag LOOK_LF: no
24151 #Has flag LOOK_LONE_LF: no
24152 #Has flag LOOK_CRLF: no
24153 #Has flag LOOK_LONG: no
24154 #Has flag LOOK_INVALID: yes
24155 #Has flag LOOK_ODD: no
24156 #Has flag LOOK_SHORT: no}
24157
24158 utf-check 1588 utf-check-1588-3-129-0.jnk \
24159 {File "%TEMP%/utf-check-1588-3-129-0.jnk" has 6 bytes.
24160 Starts with UTF-8 BOM: no
24161 Starts with UTF-16 BOM: no
24162
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -657,10 +657,11 @@
657657
$(SRCDIR)/sounds/f.wav \
658658
$(SRCDIR)/style.admin_log.css \
659659
$(SRCDIR)/style.chat.css \
660660
$(SRCDIR)/style.fileedit.css \
661661
$(SRCDIR)/style.pikchrshow.css \
662
+ $(SRCDIR)/style.uvlist.css \
662663
$(SRCDIR)/style.wikiedit.css \
663664
$(SRCDIR)/tree.js \
664665
$(SRCDIR)/useredit.js \
665666
$(SRCDIR)/wiki.wiki
666667
667668
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -657,10 +657,11 @@
657 $(SRCDIR)/sounds/f.wav \
658 $(SRCDIR)/style.admin_log.css \
659 $(SRCDIR)/style.chat.css \
660 $(SRCDIR)/style.fileedit.css \
661 $(SRCDIR)/style.pikchrshow.css \
 
662 $(SRCDIR)/style.wikiedit.css \
663 $(SRCDIR)/tree.js \
664 $(SRCDIR)/useredit.js \
665 $(SRCDIR)/wiki.wiki
666
667
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -657,10 +657,11 @@
657 $(SRCDIR)/sounds/f.wav \
658 $(SRCDIR)/style.admin_log.css \
659 $(SRCDIR)/style.chat.css \
660 $(SRCDIR)/style.fileedit.css \
661 $(SRCDIR)/style.pikchrshow.css \
662 $(SRCDIR)/style.uvlist.css \
663 $(SRCDIR)/style.wikiedit.css \
664 $(SRCDIR)/tree.js \
665 $(SRCDIR)/useredit.js \
666 $(SRCDIR)/wiki.wiki
667
668
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -615,10 +615,11 @@
615615
"$(SRCDIR)\sounds\f.wav" \
616616
"$(SRCDIR)\style.admin_log.css" \
617617
"$(SRCDIR)\style.chat.css" \
618618
"$(SRCDIR)\style.fileedit.css" \
619619
"$(SRCDIR)\style.pikchrshow.css" \
620
+ "$(SRCDIR)\style.uvlist.css" \
620621
"$(SRCDIR)\style.wikiedit.css" \
621622
"$(SRCDIR)\tree.js" \
622623
"$(SRCDIR)\useredit.js" \
623624
"$(SRCDIR)\wiki.wiki"
624625
@@ -1244,10 +1245,11 @@
12441245
echo "$(SRCDIR)\sounds/f.wav" >> $@
12451246
echo "$(SRCDIR)\style.admin_log.css" >> $@
12461247
echo "$(SRCDIR)\style.chat.css" >> $@
12471248
echo "$(SRCDIR)\style.fileedit.css" >> $@
12481249
echo "$(SRCDIR)\style.pikchrshow.css" >> $@
1250
+ echo "$(SRCDIR)\style.uvlist.css" >> $@
12491251
echo "$(SRCDIR)\style.wikiedit.css" >> $@
12501252
echo "$(SRCDIR)\tree.js" >> $@
12511253
echo "$(SRCDIR)\useredit.js" >> $@
12521254
echo "$(SRCDIR)\wiki.wiki" >> $@
12531255
12541256
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -615,10 +615,11 @@
615 "$(SRCDIR)\sounds\f.wav" \
616 "$(SRCDIR)\style.admin_log.css" \
617 "$(SRCDIR)\style.chat.css" \
618 "$(SRCDIR)\style.fileedit.css" \
619 "$(SRCDIR)\style.pikchrshow.css" \
 
620 "$(SRCDIR)\style.wikiedit.css" \
621 "$(SRCDIR)\tree.js" \
622 "$(SRCDIR)\useredit.js" \
623 "$(SRCDIR)\wiki.wiki"
624
@@ -1244,10 +1245,11 @@
1244 echo "$(SRCDIR)\sounds/f.wav" >> $@
1245 echo "$(SRCDIR)\style.admin_log.css" >> $@
1246 echo "$(SRCDIR)\style.chat.css" >> $@
1247 echo "$(SRCDIR)\style.fileedit.css" >> $@
1248 echo "$(SRCDIR)\style.pikchrshow.css" >> $@
 
1249 echo "$(SRCDIR)\style.wikiedit.css" >> $@
1250 echo "$(SRCDIR)\tree.js" >> $@
1251 echo "$(SRCDIR)\useredit.js" >> $@
1252 echo "$(SRCDIR)\wiki.wiki" >> $@
1253
1254
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -615,10 +615,11 @@
615 "$(SRCDIR)\sounds\f.wav" \
616 "$(SRCDIR)\style.admin_log.css" \
617 "$(SRCDIR)\style.chat.css" \
618 "$(SRCDIR)\style.fileedit.css" \
619 "$(SRCDIR)\style.pikchrshow.css" \
620 "$(SRCDIR)\style.uvlist.css" \
621 "$(SRCDIR)\style.wikiedit.css" \
622 "$(SRCDIR)\tree.js" \
623 "$(SRCDIR)\useredit.js" \
624 "$(SRCDIR)\wiki.wiki"
625
@@ -1244,10 +1245,11 @@
1245 echo "$(SRCDIR)\sounds/f.wav" >> $@
1246 echo "$(SRCDIR)\style.admin_log.css" >> $@
1247 echo "$(SRCDIR)\style.chat.css" >> $@
1248 echo "$(SRCDIR)\style.fileedit.css" >> $@
1249 echo "$(SRCDIR)\style.pikchrshow.css" >> $@
1250 echo "$(SRCDIR)\style.uvlist.css" >> $@
1251 echo "$(SRCDIR)\style.wikiedit.css" >> $@
1252 echo "$(SRCDIR)\tree.js" >> $@
1253 echo "$(SRCDIR)\useredit.js" >> $@
1254 echo "$(SRCDIR)\wiki.wiki" >> $@
1255
1256
+53 -14
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,51 @@
11
<title>Change Log</title>
22
3
-<h2 id='v2_24'>Changes for version 2.24 (pending)</h2>
3
+<h2 id='v2_25'>Changes for version 2.25 (pending)</h2>
44
5
- * Improvements to the default skin
5
+ * The "[/help?cmd=ui|fossil ui /]" command now works even for repositories
6
+ that have non-ASCII filenames
7
+ * Add the [/help?cmd=tree|fossil tree] command.
8
+ * On case-insensitive filesystems, store files using the filesystem's
9
+ preferred case rather than the case typed in by the user.
10
+ * Change the name "fossil cherry-pick" command to "fossil cherrypick",
11
+ which is more familiar to Git users. Retain the legacy name for
12
+ compatibility.
13
+ * Add new query parameters to the [/help?cmd=/timeline|/timeline page]:
14
+ d2=, p2=, and dp2=.
15
+ * Add options to the [/help?cmd=tag|fossil tag] command that will list tag values.
16
+ * Add ability to upload unversioned files via the [/help?cmd=/uvlist|/uvlist page].
17
+ * Add history search to the [/help?cmd=/chat|/chat page].
18
+
19
+
20
+<h2 id='v2_24'>Changes for version 2.24 (2024-04-23)</h2>
21
+
22
+ * Apache change work-around &rarr; As part of a security fix, the Apache webserver
23
+ mod_cgi module has stopped relaying the Content-Length field of the HTTP
24
+ reply header from the CGI programs back to the client in cases where the
25
+ connection is to be closed and the client is able to read until end-of-file.
26
+ The HTTP and CGI specs allow for this, though it does seem rude.
27
+ Older versions of Fossil were depending on the Content-Length header field
28
+ being set. To work around the change to Apache, Fossil has
29
+ been enhanced to cope with a missing Content-Length in the reply header. See
30
+ [forum:/forumpost/12ac403fd29cfc89|forum thread 12ac403fd29cfc89].
31
+ * [./customskin.md|Skin] enhancements:
32
+ <ul>
33
+ <li> Reworked the default skin to make everything more readable: larger
34
+ fonts, more whitespace, deeper indents to show hierarchy and to
35
+ offset command examples, etc. Adjusted colors slightly to bring
36
+ things into better accord with the WCAG accessibility guidelines.
37
+ This constitutes a <strong>breaking change</strong> for those with
38
+ custom skins; see [./customskin.md#version-2.24 | this section of
39
+ the docs] for migration advice.
40
+ <li> Add a new link added to the [/login] page that allows the user to
41
+ [/skins|select their preferred skin]. This preference is stored in
42
+ the [/fdscookie|fossil display_settings cookie].
43
+ <li> The /setup_skin_admin page is simplified to let administrators easily
44
+ select one of the built-in skins as a default, or to specify a
45
+ custom skin.
46
+ </ul>
647
* If an "ssh:" sync fails in a way that suggests that the fossil executable
748
could not be found on the remote host, then retry after adding a PATH=
849
prefix to the command. This helps "ssh:" to "just work" when the server
950
is a Mac.
1051
* Enhancements to the [/help?cmd=/timeline|/timeline page]:
@@ -16,32 +57,30 @@
1657
<li> Add the to2=Z query parameter to augment from=X,to=Y so that the
1758
path from X to Z is shown if Y cannot be found.
1859
</ul>
1960
* Moved the /museum/repo.fossil file referenced from the Dockerfile from
2061
the ENTRYPOINT to the CMD part to allow use of --repolist mode.
21
- * The /uvlist page now shows the hash algorithm used so that
22
- outsiders don't have to guess it from the hash length when
23
- double-checking hashes of downloaded files on their end.
24
- * The hash itself is now shown in a fixed-width font on the /uvlist
25
- page, suiting this tabular display.
62
+ * The [/uvlist] page now shows the hash algorithm used so that
63
+ viewers don't have to guess. The hash is shown in a fixed-width
64
+ font for a more visually pleasing display.
2665
* If the [/help?cmd=autosync|autosync setting] contains keyword "all",
2766
the automatic sync occurs against all defined remote repositories, not
2867
just the default.
2968
* Markdown formatter: improved handling of indented fenced code blocks
3069
that contain blank lines.
70
+ * When doing a "[/help?cmd=add|fossil add]" on a system with case-insensitive
71
+ but case-preserving filenames (Mac and Windows) try to use the filename
72
+ case as it is known to the filesystem, not the case entered by the
73
+ user on the command-line. See
74
+ [forum:/forumpost/30d9c0d131610f53|forum thread 30d9c0d131610f53].
3175
* Fix problems with one-click unsubscribe on email notifications.
3276
* Import the latest [/doc/trunk/www/pikchr.md|Pikchr] containing support
3377
for "diamond" objects.
34
- * Reworked the default skin to make everything more readable: larger
35
- fonts, more whitespace, deeper indents to show hierarchy and to
36
- offset command examples, etc. Adjusted colors slightly to bring
37
- things into better accord with the WCAG accessibility guidelines.
38
- This constitutes a <strong>breaking change</strong> for those with
39
- custom skins; see [./customskin.md#version-2.24 | this section of
40
- the docs] for migration advice.
4178
* Add ability to render committed Pikchr files to SVG via
4279
<samp>/doc/…/foo.pikchr?popup</samp> URLs.
80
+ * Update Fossil's internal robot detection logic so that it correctly
81
+ identifies the new GoogleOther crawler as a robot.
4382
4483
<h2 id='v2_23'>Changes for version 2.23 (2023-11-01)</h2>
4584
4685
* Add ability to "close" forum threads, such that unprivileged users
4786
may no longer respond to them. Only administrators can close
4887
4988
ADDED www/colordiff.md
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,51 @@
1 <title>Change Log</title>
2
3 <h2 id='v2_24'>Changes for version 2.24 (pending)</h2>
4
5 * Improvements to the default skin
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6 * If an "ssh:" sync fails in a way that suggests that the fossil executable
7 could not be found on the remote host, then retry after adding a PATH=
8 prefix to the command. This helps "ssh:" to "just work" when the server
9 is a Mac.
10 * Enhancements to the [/help?cmd=/timeline|/timeline page]:
@@ -16,32 +57,30 @@
16 <li> Add the to2=Z query parameter to augment from=X,to=Y so that the
17 path from X to Z is shown if Y cannot be found.
18 </ul>
19 * Moved the /museum/repo.fossil file referenced from the Dockerfile from
20 the ENTRYPOINT to the CMD part to allow use of --repolist mode.
21 * The /uvlist page now shows the hash algorithm used so that
22 outsiders don't have to guess it from the hash length when
23 double-checking hashes of downloaded files on their end.
24 * The hash itself is now shown in a fixed-width font on the /uvlist
25 page, suiting this tabular display.
26 * If the [/help?cmd=autosync|autosync setting] contains keyword "all",
27 the automatic sync occurs against all defined remote repositories, not
28 just the default.
29 * Markdown formatter: improved handling of indented fenced code blocks
30 that contain blank lines.
 
 
 
 
 
31 * Fix problems with one-click unsubscribe on email notifications.
32 * Import the latest [/doc/trunk/www/pikchr.md|Pikchr] containing support
33 for "diamond" objects.
34 * Reworked the default skin to make everything more readable: larger
35 fonts, more whitespace, deeper indents to show hierarchy and to
36 offset command examples, etc. Adjusted colors slightly to bring
37 things into better accord with the WCAG accessibility guidelines.
38 This constitutes a <strong>breaking change</strong> for those with
39 custom skins; see [./customskin.md#version-2.24 | this section of
40 the docs] for migration advice.
41 * Add ability to render committed Pikchr files to SVG via
42 <samp>/doc/…/foo.pikchr?popup</samp> URLs.
 
 
43
44 <h2 id='v2_23'>Changes for version 2.23 (2023-11-01)</h2>
45
46 * Add ability to "close" forum threads, such that unprivileged users
47 may no longer respond to them. Only administrators can close
48
49 DDED www/colordiff.md
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,51 @@
1 <title>Change Log</title>
2
3 <h2 id='v2_25'>Changes for version 2.25 (pending)</h2>
4
5 * The "[/help?cmd=ui|fossil ui /]" command now works even for repositories
6 that have non-ASCII filenames
7 * Add the [/help?cmd=tree|fossil tree] command.
8 * On case-insensitive filesystems, store files using the filesystem's
9 preferred case rather than the case typed in by the user.
10 * Change the name "fossil cherry-pick" command to "fossil cherrypick",
11 which is more familiar to Git users. Retain the legacy name for
12 compatibility.
13 * Add new query parameters to the [/help?cmd=/timeline|/timeline page]:
14 d2=, p2=, and dp2=.
15 * Add options to the [/help?cmd=tag|fossil tag] command that will list tag values.
16 * Add ability to upload unversioned files via the [/help?cmd=/uvlist|/uvlist page].
17 * Add history search to the [/help?cmd=/chat|/chat page].
18
19
20 <h2 id='v2_24'>Changes for version 2.24 (2024-04-23)</h2>
21
22 * Apache change work-around &rarr; As part of a security fix, the Apache webserver
23 mod_cgi module has stopped relaying the Content-Length field of the HTTP
24 reply header from the CGI programs back to the client in cases where the
25 connection is to be closed and the client is able to read until end-of-file.
26 The HTTP and CGI specs allow for this, though it does seem rude.
27 Older versions of Fossil were depending on the Content-Length header field
28 being set. To work around the change to Apache, Fossil has
29 been enhanced to cope with a missing Content-Length in the reply header. See
30 [forum:/forumpost/12ac403fd29cfc89|forum thread 12ac403fd29cfc89].
31 * [./customskin.md|Skin] enhancements:
32 <ul>
33 <li> Reworked the default skin to make everything more readable: larger
34 fonts, more whitespace, deeper indents to show hierarchy and to
35 offset command examples, etc. Adjusted colors slightly to bring
36 things into better accord with the WCAG accessibility guidelines.
37 This constitutes a <strong>breaking change</strong> for those with
38 custom skins; see [./customskin.md#version-2.24 | this section of
39 the docs] for migration advice.
40 <li> Add a new link added to the [/login] page that allows the user to
41 [/skins|select their preferred skin]. This preference is stored in
42 the [/fdscookie|fossil display_settings cookie].
43 <li> The /setup_skin_admin page is simplified to let administrators easily
44 select one of the built-in skins as a default, or to specify a
45 custom skin.
46 </ul>
47 * If an "ssh:" sync fails in a way that suggests that the fossil executable
48 could not be found on the remote host, then retry after adding a PATH=
49 prefix to the command. This helps "ssh:" to "just work" when the server
50 is a Mac.
51 * Enhancements to the [/help?cmd=/timeline|/timeline page]:
@@ -16,32 +57,30 @@
57 <li> Add the to2=Z query parameter to augment from=X,to=Y so that the
58 path from X to Z is shown if Y cannot be found.
59 </ul>
60 * Moved the /museum/repo.fossil file referenced from the Dockerfile from
61 the ENTRYPOINT to the CMD part to allow use of --repolist mode.
62 * The [/uvlist] page now shows the hash algorithm used so that
63 viewers don't have to guess. The hash is shown in a fixed-width
64 font for a more visually pleasing display.
 
 
65 * If the [/help?cmd=autosync|autosync setting] contains keyword "all",
66 the automatic sync occurs against all defined remote repositories, not
67 just the default.
68 * Markdown formatter: improved handling of indented fenced code blocks
69 that contain blank lines.
70 * When doing a "[/help?cmd=add|fossil add]" on a system with case-insensitive
71 but case-preserving filenames (Mac and Windows) try to use the filename
72 case as it is known to the filesystem, not the case entered by the
73 user on the command-line. See
74 [forum:/forumpost/30d9c0d131610f53|forum thread 30d9c0d131610f53].
75 * Fix problems with one-click unsubscribe on email notifications.
76 * Import the latest [/doc/trunk/www/pikchr.md|Pikchr] containing support
77 for "diamond" objects.
 
 
 
 
 
 
 
78 * Add ability to render committed Pikchr files to SVG via
79 <samp>/doc/…/foo.pikchr?popup</samp> URLs.
80 * Update Fossil's internal robot detection logic so that it correctly
81 identifies the new GoogleOther crawler as a robot.
82
83 <h2 id='v2_23'>Changes for version 2.23 (2023-11-01)</h2>
84
85 * Add ability to "close" forum threads, such that unprivileged users
86 may no longer respond to them. Only administrators can close
87
88 DDED www/colordiff.md
--- a/www/colordiff.md
+++ b/www/colordiff.md
@@ -0,0 +1,104 @@
1
+# Colorized Diffs
2
+
3
+The oldest and most widely compatible method to get colorized diffs in
4
+Fossil is to use its web UI:
5
+
6
+ fossil ui --page '/vdiff?from=2024-04-01&to=trunk'
7
+
8
+That syntax is admittedly awkward, and it doesn’t work where “from” is
9
+the current checkout. Fortunately, there are many other methods to get
10
+colorized `diff` output from Fossil.
11
+
12
+
13
+<a id="ui"></a>
14
+## `fossil diff -b`
15
+
16
+This produces a graphical diff in HTML format and sends it to the
17
+user’s default web browser for viewing.
18
+
19
+
20
+
21
+<a id="ui"></a>
22
+## `fossil diff -tk`
23
+
24
+You may be surprised to learn that the prior feature doesn’t use any of
25
+the skinning or chrome from Fossil UI. This is because it is meant as a
26
+functional replacement for an older method of getting colorized diffs,
27
+“`fossil diff -tk`”. The feature was added after Apple stopped shipping
28
+Tcl/Tk in macOS, and the third-party replacements often failed to work
29
+correctly. It’s useful on other platforms as well.
30
+
31
+
32
+<a id="git"></a>
33
+## Delegate to Git
34
+
35
+It may be considered sacrilege by some, but the most direct method for
36
+those who want Git-like diff behavior may be to delegate diff behavior
37
+to Git:
38
+
39
+ fossil set --global diff-command 'git diff --no-index'
40
+
41
+The flag permits it to diff files that aren’t inside a Git repository.
42
+
43
+
44
+<a id="diffutils"></a>
45
+## GNU Diffutils
46
+
47
+If your system is from 2016 or later, it may include [GNU Diffutils][gd]
48
+3.4 or newer, which lets you say:
49
+
50
+ fossil set --global diff-command 'diff -dwu --color=always'
51
+
52
+You might think you could give `--color=auto`, but that fails with
53
+commands like “`fossil diff | less`” since the pipe turns the output
54
+non-interactive from the perspective of the underlying `diff` instance.
55
+
56
+This use of unconditional colorization means you will then have to
57
+remember to add the `-i` option to `fossil diff` commands when producing
58
+`patch(1)` files or piping diff output to another command that doesn’t
59
+understand ANSI escape sequences, such as [`diffstat`][ds].
60
+
61
+[ds]: https://invisible-island.net/diffstat/
62
+[gd]: https://www.gnu.org/software/diffutils/
63
+
64
+
65
+<a id="bat"></a>
66
+## Bat, the Cat with Wings
67
+
68
+We can work around the `--color=auto` problem by switching from GNU less
69
+as our pager to [`bat`][bat], as it can detect GNU diff output and
70
+colorize it for you:
71
+
72
+ fossil set --global diff-command 'diff -dwu --color=auto'
73
+ fossil diff | bat
74
+
75
+In this author’s experience, that works a lot more reliably than GNU
76
+less’s ANSI color escape code handling, even when you set `LESS=-R` in
77
+your environment.
78
+
79
+The reason we don’t leave the `diff-command` unset in this case is that
80
+Fossil produces additional lines at the start which confuse the diff
81
+format detection in `bat`. Forcing output through an external diff
82
+command solves that. It also means that if you forget to pipe the output
83
+through `bat`, you still get colorized output from GNU diff.
84
+
85
+[bat]: https://github.com/sharkdp/bat
86
+
87
+
88
+<a id="colordiff"></a>
89
+## Colordiff
90
+
91
+A method that works on systems predating GNU diffutils 3.4 or the
92
+widespread availability of `bat` is to install [`colordiff`][cdurl], as
93
+it is included in [many package systems][cdpkg], including ones for
94
+outdated OSes. That then lets you say:
95
+
96
+ fossil set --global diff-command 'colordiff -dwu'
97
+
98
+The main reason we list this alternative last is that it has the same
99
+limitation of unconditional color as [above](#diffutils).
100
+
101
+[cdurl]: https://www.colordiff.org/
102
+[cdpkg]: https://repology.org/project/colordiff/versions
103
+
104
+<div style="height:50em" id="this-space-intentionally-left-blank"></div>
--- a/www/colordiff.md
+++ b/www/colordiff.md
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/colordiff.md
+++ b/www/colordiff.md
@@ -0,0 +1,104 @@
1 # Colorized Diffs
2
3 The oldest and most widely compatible method to get colorized diffs in
4 Fossil is to use its web UI:
5
6 fossil ui --page '/vdiff?from=2024-04-01&to=trunk'
7
8 That syntax is admittedly awkward, and it doesn’t work where “from” is
9 the current checkout. Fortunately, there are many other methods to get
10 colorized `diff` output from Fossil.
11
12
13 <a id="ui"></a>
14 ## `fossil diff -b`
15
16 This produces a graphical diff in HTML format and sends it to the
17 user’s default web browser for viewing.
18
19
20
21 <a id="ui"></a>
22 ## `fossil diff -tk`
23
24 You may be surprised to learn that the prior feature doesn’t use any of
25 the skinning or chrome from Fossil UI. This is because it is meant as a
26 functional replacement for an older method of getting colorized diffs,
27 “`fossil diff -tk`”. The feature was added after Apple stopped shipping
28 Tcl/Tk in macOS, and the third-party replacements often failed to work
29 correctly. It’s useful on other platforms as well.
30
31
32 <a id="git"></a>
33 ## Delegate to Git
34
35 It may be considered sacrilege by some, but the most direct method for
36 those who want Git-like diff behavior may be to delegate diff behavior
37 to Git:
38
39 fossil set --global diff-command 'git diff --no-index'
40
41 The flag permits it to diff files that aren’t inside a Git repository.
42
43
44 <a id="diffutils"></a>
45 ## GNU Diffutils
46
47 If your system is from 2016 or later, it may include [GNU Diffutils][gd]
48 3.4 or newer, which lets you say:
49
50 fossil set --global diff-command 'diff -dwu --color=always'
51
52 You might think you could give `--color=auto`, but that fails with
53 commands like “`fossil diff | less`” since the pipe turns the output
54 non-interactive from the perspective of the underlying `diff` instance.
55
56 This use of unconditional colorization means you will then have to
57 remember to add the `-i` option to `fossil diff` commands when producing
58 `patch(1)` files or piping diff output to another command that doesn’t
59 understand ANSI escape sequences, such as [`diffstat`][ds].
60
61 [ds]: https://invisible-island.net/diffstat/
62 [gd]: https://www.gnu.org/software/diffutils/
63
64
65 <a id="bat"></a>
66 ## Bat, the Cat with Wings
67
68 We can work around the `--color=auto` problem by switching from GNU less
69 as our pager to [`bat`][bat], as it can detect GNU diff output and
70 colorize it for you:
71
72 fossil set --global diff-command 'diff -dwu --color=auto'
73 fossil diff | bat
74
75 In this author’s experience, that works a lot more reliably than GNU
76 less’s ANSI color escape code handling, even when you set `LESS=-R` in
77 your environment.
78
79 The reason we don’t leave the `diff-command` unset in this case is that
80 Fossil produces additional lines at the start which confuse the diff
81 format detection in `bat`. Forcing output through an external diff
82 command solves that. It also means that if you forget to pipe the output
83 through `bat`, you still get colorized output from GNU diff.
84
85 [bat]: https://github.com/sharkdp/bat
86
87
88 <a id="colordiff"></a>
89 ## Colordiff
90
91 A method that works on systems predating GNU diffutils 3.4 or the
92 widespread availability of `bat` is to install [`colordiff`][cdurl], as
93 it is included in [many package systems][cdpkg], including ones for
94 outdated OSes. That then lets you say:
95
96 fossil set --global diff-command 'colordiff -dwu'
97
98 The main reason we list this alternative last is that it has the same
99 limitation of unconditional color as [above](#diffutils).
100
101 [cdurl]: https://www.colordiff.org/
102 [cdpkg]: https://repology.org/project/colordiff/versions
103
104 <div style="height:50em" id="this-space-intentionally-left-blank"></div>
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -241,11 +241,11 @@
241241
When the symbolic name is a date and time, fossil shows the version
242242
of the document that was most recently checked in as of the date
243243
and time specified. So, for example, to see what the fossil website
244244
looked like at the beginning of 2010, enter:
245245
246
-<pre><a href="/doc/2010-01-01/www/index.wiki">https://fossil-scm.org/home/doc/<b>2010-01-01</b>/www/index.wiki
246
+<pre><a href="https://fossil-scm.org/home/doc/2010-01-01/www/index.wiki">https://fossil-scm.org/home/doc/<b>2010-01-01</b>/www/index.wiki
247247
</a></pre>
248248
249249
The file that encodes this document is stored in the fossil source tree under
250250
the name "<b>www/embeddeddoc.wiki</b>" and so that name forms the
251251
last part of the URL for this document.
252252
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -241,11 +241,11 @@
241 When the symbolic name is a date and time, fossil shows the version
242 of the document that was most recently checked in as of the date
243 and time specified. So, for example, to see what the fossil website
244 looked like at the beginning of 2010, enter:
245
246 <pre><a href="/doc/2010-01-01/www/index.wiki">https://fossil-scm.org/home/doc/<b>2010-01-01</b>/www/index.wiki
247 </a></pre>
248
249 The file that encodes this document is stored in the fossil source tree under
250 the name "<b>www/embeddeddoc.wiki</b>" and so that name forms the
251 last part of the URL for this document.
252
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -241,11 +241,11 @@
241 When the symbolic name is a date and time, fossil shows the version
242 of the document that was most recently checked in as of the date
243 and time specified. So, for example, to see what the fossil website
244 looked like at the beginning of 2010, enter:
245
246 <pre><a href="https://fossil-scm.org/home/doc/2010-01-01/www/index.wiki">https://fossil-scm.org/home/doc/<b>2010-01-01</b>/www/index.wiki
247 </a></pre>
248
249 The file that encodes this document is stored in the fossil source tree under
250 the name "<b>www/embeddeddoc.wiki</b>" and so that name forms the
251 last part of the URL for this document.
252
+3 -3
--- www/faq.tcl
+++ www/faq.tcl
@@ -72,11 +72,11 @@
7272
command, you can add a tag to that check-in using the
7373
"--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
7474
option to give a check-in multiple tags. Tags need not be unique. So,
7575
for example, it is common to give every released version a "release" tag.
7676
77
- If you want add a tag to an existing check-in, you can use the
77
+ If you want to add a tag to an existing check-in, you can use the
7878
<b>[/help/tag|tag]</b> command. For example:
7979
8080
<pre>
8181
<b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
8282
</pre>
@@ -84,11 +84,11 @@
8484
The CHECK-IN in the previous line can be any
8585
[./checkin_names.wiki | valid check-in name format].
8686
8787
You can also add (and remove) tags from a check-in using the
8888
[./webui.wiki | web interface]. First locate the check-in that you
89
- what to tag on the timeline, then click on the link to go the detailed
89
+ want to tag on the timeline, then click on the link to go the detailed
9090
information page for that check-in. Then find the "<b>edit</b>"
9191
link (near the "Commands:" label) and click on that. There are
9292
controls on the edit page that allow new tags to be added and existing
9393
tags to be removed.
9494
}
@@ -96,11 +96,11 @@
9696
faq {
9797
How do I create a private branch that won't get pushed back to the
9898
main repository.
9999
} {
100100
Use the <b>--private</b> command-line option on the
101
- <b>commit</b> command. The result will be a check-in which exists on
101
+ <b>commit</b> command. The result will be a check-in which exists in
102102
your local repository only and is never pushed to other repositories.
103103
All descendants of a private check-in are also private.
104104
105105
Unless you specify something different using the <b>--branch</b> and/or
106106
<b>--bgcolor</b> options, the new private check-in will be put on a branch
107107
--- www/faq.tcl
+++ www/faq.tcl
@@ -72,11 +72,11 @@
72 command, you can add a tag to that check-in using the
73 "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
74 option to give a check-in multiple tags. Tags need not be unique. So,
75 for example, it is common to give every released version a "release" tag.
76
77 If you want add a tag to an existing check-in, you can use the
78 <b>[/help/tag|tag]</b> command. For example:
79
80 <pre>
81 <b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
82 </pre>
@@ -84,11 +84,11 @@
84 The CHECK-IN in the previous line can be any
85 [./checkin_names.wiki | valid check-in name format].
86
87 You can also add (and remove) tags from a check-in using the
88 [./webui.wiki | web interface]. First locate the check-in that you
89 what to tag on the timeline, then click on the link to go the detailed
90 information page for that check-in. Then find the "<b>edit</b>"
91 link (near the "Commands:" label) and click on that. There are
92 controls on the edit page that allow new tags to be added and existing
93 tags to be removed.
94 }
@@ -96,11 +96,11 @@
96 faq {
97 How do I create a private branch that won't get pushed back to the
98 main repository.
99 } {
100 Use the <b>--private</b> command-line option on the
101 <b>commit</b> command. The result will be a check-in which exists on
102 your local repository only and is never pushed to other repositories.
103 All descendants of a private check-in are also private.
104
105 Unless you specify something different using the <b>--branch</b> and/or
106 <b>--bgcolor</b> options, the new private check-in will be put on a branch
107
--- www/faq.tcl
+++ www/faq.tcl
@@ -72,11 +72,11 @@
72 command, you can add a tag to that check-in using the
73 "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
74 option to give a check-in multiple tags. Tags need not be unique. So,
75 for example, it is common to give every released version a "release" tag.
76
77 If you want to add a tag to an existing check-in, you can use the
78 <b>[/help/tag|tag]</b> command. For example:
79
80 <pre>
81 <b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
82 </pre>
@@ -84,11 +84,11 @@
84 The CHECK-IN in the previous line can be any
85 [./checkin_names.wiki | valid check-in name format].
86
87 You can also add (and remove) tags from a check-in using the
88 [./webui.wiki | web interface]. First locate the check-in that you
89 want to tag on the timeline, then click on the link to go the detailed
90 information page for that check-in. Then find the "<b>edit</b>"
91 link (near the "Commands:" label) and click on that. There are
92 controls on the edit page that allow new tags to be added and existing
93 tags to be removed.
94 }
@@ -96,11 +96,11 @@
96 faq {
97 How do I create a private branch that won't get pushed back to the
98 main repository.
99 } {
100 Use the <b>--private</b> command-line option on the
101 <b>commit</b> command. The result will be a check-in which exists in
102 your local repository only and is never pushed to other repositories.
103 All descendants of a private check-in are also private.
104
105 Unless you specify something different using the <b>--branch</b> and/or
106 <b>--bgcolor</b> options, the new private check-in will be put on a branch
107
+3 -3
--- www/faq.wiki
+++ www/faq.wiki
@@ -70,11 +70,11 @@
7070
command, you can add a tag to that check-in using the
7171
"--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
7272
option to give a check-in multiple tags. Tags need not be unique. So,
7373
for example, it is common to give every released version a "release" tag.
7474
75
-If you want add a tag to an existing check-in, you can use the
75
+If you want to add a tag to an existing check-in, you can use the
7676
<b>[/help/tag|tag]</b> command. For example:
7777
7878
<pre>
7979
<b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
8080
</pre>
@@ -82,21 +82,21 @@
8282
The CHECK-IN in the previous line can be any
8383
[./checkin_names.wiki | valid check-in name format].
8484
8585
You can also add (and remove) tags from a check-in using the
8686
[./webui.wiki | web interface]. First locate the check-in that you
87
-what to tag on the timeline, then click on the link to go the detailed
87
+want to tag on the timeline, then click on the link to go the detailed
8888
information page for that check-in. Then find the "<b>edit</b>"
8989
link (near the "Commands:" label) and click on that. There are
9090
controls on the edit page that allow new tags to be added and existing
9191
tags to be removed.</li>
9292
9393
<p id="q5"><b>(5) How do I create a private branch that won't get pushed back to the
9494
main repository.</b></p>
9595
9696
Use the <b>--private</b> command-line option on the
97
-<b>commit</b> command. The result will be a check-in which exists on
97
+<b>commit</b> command. The result will be a check-in which exists in
9898
your local repository only and is never pushed to other repositories.
9999
All descendants of a private check-in are also private.
100100
101101
Unless you specify something different using the <b>--branch</b> and/or
102102
<b>--bgcolor</b> options, the new private check-in will be put on a branch
103103
--- www/faq.wiki
+++ www/faq.wiki
@@ -70,11 +70,11 @@
70 command, you can add a tag to that check-in using the
71 "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
72 option to give a check-in multiple tags. Tags need not be unique. So,
73 for example, it is common to give every released version a "release" tag.
74
75 If you want add a tag to an existing check-in, you can use the
76 <b>[/help/tag|tag]</b> command. For example:
77
78 <pre>
79 <b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
80 </pre>
@@ -82,21 +82,21 @@
82 The CHECK-IN in the previous line can be any
83 [./checkin_names.wiki | valid check-in name format].
84
85 You can also add (and remove) tags from a check-in using the
86 [./webui.wiki | web interface]. First locate the check-in that you
87 what to tag on the timeline, then click on the link to go the detailed
88 information page for that check-in. Then find the "<b>edit</b>"
89 link (near the "Commands:" label) and click on that. There are
90 controls on the edit page that allow new tags to be added and existing
91 tags to be removed.</li>
92
93 <p id="q5"><b>(5) How do I create a private branch that won't get pushed back to the
94 main repository.</b></p>
95
96 Use the <b>--private</b> command-line option on the
97 <b>commit</b> command. The result will be a check-in which exists on
98 your local repository only and is never pushed to other repositories.
99 All descendants of a private check-in are also private.
100
101 Unless you specify something different using the <b>--branch</b> and/or
102 <b>--bgcolor</b> options, the new private check-in will be put on a branch
103
--- www/faq.wiki
+++ www/faq.wiki
@@ -70,11 +70,11 @@
70 command, you can add a tag to that check-in using the
71 "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
72 option to give a check-in multiple tags. Tags need not be unique. So,
73 for example, it is common to give every released version a "release" tag.
74
75 If you want to add a tag to an existing check-in, you can use the
76 <b>[/help/tag|tag]</b> command. For example:
77
78 <pre>
79 <b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
80 </pre>
@@ -82,21 +82,21 @@
82 The CHECK-IN in the previous line can be any
83 [./checkin_names.wiki | valid check-in name format].
84
85 You can also add (and remove) tags from a check-in using the
86 [./webui.wiki | web interface]. First locate the check-in that you
87 want to tag on the timeline, then click on the link to go the detailed
88 information page for that check-in. Then find the "<b>edit</b>"
89 link (near the "Commands:" label) and click on that. There are
90 controls on the edit page that allow new tags to be added and existing
91 tags to be removed.</li>
92
93 <p id="q5"><b>(5) How do I create a private branch that won't get pushed back to the
94 main repository.</b></p>
95
96 Use the <b>--private</b> command-line option on the
97 <b>commit</b> command. The result will be a check-in which exists in
98 your local repository only and is never pushed to other repositories.
99 All descendants of a private check-in are also private.
100
101 Unless you specify something different using the <b>--branch</b> and/or
102 <b>--bgcolor</b> options, the new private check-in will be put on a branch
103
+64 -68
--- www/gitusers.md
+++ www/gitusers.md
@@ -139,13 +139,13 @@
139139
140140
141141
#### <a id="close" name="dotfile"></a> Closing a Check-Out
142142
143143
The [`fossil close`][close] command dissociates a check-out directory from the
144
-Fossil repository database, nondestructively inverting [`fossil open`][open].
145
-(Contrast [its closest inverse](#worktree), `git worktree remove`, which *is*
146
-destructive in Git!) This Fossil command does not
144
+Fossil repository database, _nondestructively_ inverting [`fossil open`][open].
145
+(Contrast Git’s [closest alternative](#worktree), `git worktree remove`, which *is*
146
+destructive!) This Fossil command does not
147147
remove the managed files, and unless you give the `--force`
148148
option, it won’t let you close the check-out with uncommitted changes to
149149
those managed files.
150150
151151
The `close` command also refuses to run without `--force` when you have
@@ -300,15 +300,15 @@
300300
Yet the constants are *not* equal because Fossil
301301
reads from a single disk file rather than visit potentially many
302302
files in sequence as Git must, so the OS’s buffer cache can result in
303303
[still better performance][35pct].
304304
305
-Unlike Git’s log, Fossil’s timeline shows info across branches by
306
-default, a feature for maintaining better situational awareness. Although the
307
-`fossil timeline` command has no way to show a single branch’s commits,
308
-you can restrict your view like this using the web UI equivalent by
309
-clicking the name of a branch on the `/timeline` or `/brlist` page. (Or
305
+Unlike Git’s log, Fossil’s timeline shows info across all branches by
306
+default, a feature for maintaining better situational awareness.
307
+It is possible to restrict the timeline to a single branch using `fossil timeline -b`.
308
+Similarly, to restrict the timeline using the web UI equivalent,
309
+click the name of a branch on the `/timeline` or `/brlist` page. (Or
310310
manually, by adding the `r=` query parameter.) Note that even in this
311311
case, the Fossil timeline still shows other branches where they interact
312312
with the one you’ve referenced in this way; again, better situational
313313
awareness.
314314
@@ -457,28 +457,67 @@
457457
458458
[cskin]: ./customskin.md
459459
[lsl]: https://chris.beams.io/posts/git-commit/#limit-50
460460
461461
462
+<a id="autocommit"></a>
463
+## Fossil Never Auto-Commits
464
+
465
+There are several features in Git besides its `commit` command that
466
+produce a new commit to the repository, and by default, they do it
467
+without prompting or even asking for a commit message. These include
468
+Git’s [`rebase`](#rebase), `merge`, and [`cherrypick`](#cpickrev)
469
+commands, plus the [commit splitting](#comsplit) sub-feature
470
+“`git commit -p`”.
471
+
472
+Fossil never does this, on firm philosophical grounds: we wish to be
473
+able to test that each potentially repository-changing command does not
474
+break anything _before_ freezing it immutably into the [Merkle
475
+tree](./blockchain.md). Where Fossil has equivalent commands, they
476
+modify the checkout tree alone, requiring a separate `commit` command
477
+afterward, withheld until the user has satisfied themselves that the
478
+command’s result is correct.
479
+
480
+We believe this is the main reason Git lacks an [autosync](#autosync)
481
+feature: making push a manual step gives the user a chance to rewrite
482
+history after triggering one of these autocommits locally, should the
483
+automatic commit fail to work out as expected. Fossil chooses the
484
+inverse path under the philosophy that commits are *commitments,* not
485
+something you’re allowed to go back and rewrite later.
486
+
487
+This is also why there is no automatic commit message writing feature in
488
+Fossil, as in these autocommit-triggering Git commands. The user is
489
+meant to write the commit message by hand after they are sure it’s
490
+correct, in clear-headed retrospective fashion. Having the tool do it
491
+prospectively before one can test the result is simply backwards.
492
+
462493
463494
<a id="staging"></a>
464495
## There Is No Staging Area
465496
466497
Fossil omits the "Git index" or "staging area" concept. When you
467498
type "`fossil commit`" _all_ changes in your check-out are committed,
468
-automatically. There is no need for the "-a" option as with Git.
499
+by default. There is no need for the "-a" option as with Git.
469500
470501
If you only want to commit _some_ of the changes, list the names
471502
of the files or directories you want to commit as arguments, like this:
472503
473504
fossil commit src/feature.c doc/feature.md examples/feature
474505
475506
Note that the last element is a directory name, meaning “any changed
476507
file under the `examples/feature` directory.”
477508
478
-Although there are currently no
479
-<a id="csplit"></a>[commit splitting][gcspl] features in Fossil like
509
+
510
+<a id="comsplit"></a>
511
+## Commit Splitting
512
+
513
+[Git’s commit splitting features][gcspl] rely on
514
+other features of Git that Fossil purposefully lacks, as covered in the
515
+prior two sections: [autocommit](#autocommit) and [the staging
516
+area](#staging).
517
+
518
+While there is no direct Fossil equivalent for
480519
`git add -p`, `git commit -p`, or `git rebase -i`, you can get the same
481520
effect by converting an uncommitted change set to a patch and then
482521
running it through [Patchouli].
483522
484523
Rather than use `fossil diff -i` to produce such a patch, a safer and
@@ -494,28 +533,17 @@
494533
hunks already applied.
495534
496535
In this way, the combination of working tree and stash replaces the need
497536
for Git’s index feature.
498537
499
-This also solves a philosophical problem with `git commit -p`: how can
500
-you test that a split commit doesn’t break anything if you do it as part
501
-of the commit action? Git’s lack of an autosync feature means you can
502
-commit locally and then rewrite history if the commit doesn’t work out,
503
-but we’d rather make changes only to the working directory, test the
504
-changes there, and only commit once we’re sure it’s right.
505
-
506
-This also explains why we don’t have anything like `git rebase -i`
507
-to split an existing commit: in Fossil, commits are *commitments,* not
508
-something you’re allowed to go back and rewrite later.
509
-
510
-If someone does [contribute][ctrb] a commit splitting feature to Fossil,
511
-we’d expect it to be an interactive form of
512
-[`fossil stash apply`][stash], rather than follow Git’s ill-considered
513
-design leads.
514
-
515
-Until then, there’s the third-party tool [`fnc`][fnc] and
516
-[its interactive `stash` command][fncsta].
538
+We believe we know how to do commit splitting in a way compatible with
539
+the Fossil philosophy, without following Git’s ill-considered design
540
+leads. It amounts to automating the above process through an interactive
541
+variant of [`fossil stash apply`][stash], as currently prototyped in the
542
+third-party tool [`fnc`][fnc] and [its interactive `stash`
543
+command][fncsta]. We merely await someone’s [contribution][ctrb] of this
544
+feature into Fossil proper.
517545
518546
[ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki
519547
[fnc]: https://fnc.bsdbox.org/
520548
[fncsta]: https://fnc.bsdbox.org/uv/doc/fnc.1.html#stash
521549
[gcspl]: https://git-scm.com/docs/git-rebase#_splitting_commits
@@ -817,57 +845,27 @@
817845
come up with a new objection that we haven’t already considered and
818846
addressed there.
819847
820848
There is only one sub-feature of `git rebase` that is philosophically
821849
compatible with Fossil yet which currently has no functional equivalent.
822
-We [covered this and the workaround for its lack](#csplit) above.
850
+We [covered this and the workaround for its lack](#comsplit) above.
823851
824852
[3]: ./rebaseharm.md
825853
826854
827
-## <a id="cdiff"></a> Colorized Diffs
855
+<a id="cdiff"></a>
856
+## Colorized Diffs
828857
829858
When you run `git diff` on an ANSI X3.64 capable terminal, it uses color
830859
to distinguish insertions, deletions, and replacements, but as of this
831860
writing, `fossil diff` produces traditional uncolored [unified diff
832861
format][udiff] output, suitable for producing a [patch file][pfile].
833862
834
-Nevertheless, there are multiple ways to get colorized diff output from
835
-Fossil:
836
-
837
-* The most direct method is to delegate diff behavior back to Git:
838
-
839
- fossil set --global diff-command 'git diff --no-index'
840
-
841
- The flag permits it to diff files that aren’t inside a Git repository.
842
-
843
-* Another method is to install [`colordiff`][cdiff] — included in
844
- [many package systems][cdpkg] — then say:
845
-
846
- fossil set --global diff-command 'colordiff -wu'
847
-
848
- Because this is unconditional, unlike `git diff --color=auto`, you
849
- will then have to remember to add the `-i` option to `fossil diff`
850
- commands when you want color disabled, such as when producing
851
- `patch(1)` files or piping diff output to another command that
852
- doesn’t understand ANSI escape sequences. There’s an example of this
853
- [below](#dstat).
854
-
855
-* Use the Fossil web UI to diff existing commits.
856
-
857
-* To diff the current working directory contents against some parent
858
- instead, Fossil’s diff command can produce
859
- colorized HTML output and open it in the OS’s default web browser.
860
- For example, `fossil diff -by` will show side-by-side diffs.
861
-
862
-* Use the older `fossil diff --tk` option to do much the same using
863
- Tcl/Tk instead of a browser.
864
-
863
+There are [many methods](./colordiff.md) for solving this.
865864
Viewed this way, Fossil doesn’t lack colorized diffs, it simply has
866865
*one* method where they *aren’t* colorized.
867866
868
-[cdpkg]: https://repology.org/project/colordiff/versions
869867
[pfile]: https://en.wikipedia.org/wiki/Patch_(Unix)
870868
[udiff]: https://en.wikipedia.org/wiki/Diff#Unified_format
871869
872870
873871
## <a id="show"></a> Showing Information About Commits
@@ -936,19 +934,17 @@
936934
a histogram in its default output mode rather than bare integers:
937935
938936
fossil diff -i -v --from 2020-04-01 | diffstat
939937
940938
We gave the `-i` flag in both cases to force Fossil to use its internal
941
-diff implementation, bypassing [your local `diff-command` setting][dcset].
942
-The `--numstat` option has no effect when you have an external diff
943
-command set, and some diff command alternatives like
944
-[`colordiff`][cdiff] (covered [above](#cdiff)) produce output that confuses `diffstat`.
939
+diff implementation, bypassing [your local `diff-command` setting][dcset]
940
+since the `--numstat` option has no effect when you have an external diff
941
+command set.
945942
946943
If you leave off the `-v` flag in the second example, the `diffstat`
947944
output won’t include info about any newly-added files.
948945
949
-[cdiff]: https://www.colordiff.org/
950946
[dcset]: https://fossil-scm.org/home/help?cmd=diff-command
951947
[dst]: https://invisible-island.net/diffstat/diffstat.html
952948
953949
954950
<a id="btnames"></a>
955951
--- www/gitusers.md
+++ www/gitusers.md
@@ -139,13 +139,13 @@
139
140
141 #### <a id="close" name="dotfile"></a> Closing a Check-Out
142
143 The [`fossil close`][close] command dissociates a check-out directory from the
144 Fossil repository database, nondestructively inverting [`fossil open`][open].
145 (Contrast [its closest inverse](#worktree), `git worktree remove`, which *is*
146 destructive in Git!) This Fossil command does not
147 remove the managed files, and unless you give the `--force`
148 option, it won’t let you close the check-out with uncommitted changes to
149 those managed files.
150
151 The `close` command also refuses to run without `--force` when you have
@@ -300,15 +300,15 @@
300 Yet the constants are *not* equal because Fossil
301 reads from a single disk file rather than visit potentially many
302 files in sequence as Git must, so the OS’s buffer cache can result in
303 [still better performance][35pct].
304
305 Unlike Git’s log, Fossil’s timeline shows info across branches by
306 default, a feature for maintaining better situational awareness. Although the
307 `fossil timeline` command has no way to show a single branch’s commits,
308 you can restrict your view like this using the web UI equivalent by
309 clicking the name of a branch on the `/timeline` or `/brlist` page. (Or
310 manually, by adding the `r=` query parameter.) Note that even in this
311 case, the Fossil timeline still shows other branches where they interact
312 with the one you’ve referenced in this way; again, better situational
313 awareness.
314
@@ -457,28 +457,67 @@
457
458 [cskin]: ./customskin.md
459 [lsl]: https://chris.beams.io/posts/git-commit/#limit-50
460
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
463 <a id="staging"></a>
464 ## There Is No Staging Area
465
466 Fossil omits the "Git index" or "staging area" concept. When you
467 type "`fossil commit`" _all_ changes in your check-out are committed,
468 automatically. There is no need for the "-a" option as with Git.
469
470 If you only want to commit _some_ of the changes, list the names
471 of the files or directories you want to commit as arguments, like this:
472
473 fossil commit src/feature.c doc/feature.md examples/feature
474
475 Note that the last element is a directory name, meaning “any changed
476 file under the `examples/feature` directory.”
477
478 Although there are currently no
479 <a id="csplit"></a>[commit splitting][gcspl] features in Fossil like
 
 
 
 
 
 
 
 
480 `git add -p`, `git commit -p`, or `git rebase -i`, you can get the same
481 effect by converting an uncommitted change set to a patch and then
482 running it through [Patchouli].
483
484 Rather than use `fossil diff -i` to produce such a patch, a safer and
@@ -494,28 +533,17 @@
494 hunks already applied.
495
496 In this way, the combination of working tree and stash replaces the need
497 for Git’s index feature.
498
499 This also solves a philosophical problem with `git commit -p`: how can
500 you test that a split commit doesn’t break anything if you do it as part
501 of the commit action? Git’s lack of an autosync feature means you can
502 commit locally and then rewrite history if the commit doesn’t work out,
503 but we’d rather make changes only to the working directory, test the
504 changes there, and only commit once we’re sure it’s right.
505
506 This also explains why we don’t have anything like `git rebase -i`
507 to split an existing commit: in Fossil, commits are *commitments,* not
508 something you’re allowed to go back and rewrite later.
509
510 If someone does [contribute][ctrb] a commit splitting feature to Fossil,
511 we’d expect it to be an interactive form of
512 [`fossil stash apply`][stash], rather than follow Git’s ill-considered
513 design leads.
514
515 Until then, there’s the third-party tool [`fnc`][fnc] and
516 [its interactive `stash` command][fncsta].
517
518 [ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki
519 [fnc]: https://fnc.bsdbox.org/
520 [fncsta]: https://fnc.bsdbox.org/uv/doc/fnc.1.html#stash
521 [gcspl]: https://git-scm.com/docs/git-rebase#_splitting_commits
@@ -817,57 +845,27 @@
817 come up with a new objection that we haven’t already considered and
818 addressed there.
819
820 There is only one sub-feature of `git rebase` that is philosophically
821 compatible with Fossil yet which currently has no functional equivalent.
822 We [covered this and the workaround for its lack](#csplit) above.
823
824 [3]: ./rebaseharm.md
825
826
827 ## <a id="cdiff"></a> Colorized Diffs
 
828
829 When you run `git diff` on an ANSI X3.64 capable terminal, it uses color
830 to distinguish insertions, deletions, and replacements, but as of this
831 writing, `fossil diff` produces traditional uncolored [unified diff
832 format][udiff] output, suitable for producing a [patch file][pfile].
833
834 Nevertheless, there are multiple ways to get colorized diff output from
835 Fossil:
836
837 * The most direct method is to delegate diff behavior back to Git:
838
839 fossil set --global diff-command 'git diff --no-index'
840
841 The flag permits it to diff files that aren’t inside a Git repository.
842
843 * Another method is to install [`colordiff`][cdiff] — included in
844 [many package systems][cdpkg] — then say:
845
846 fossil set --global diff-command 'colordiff -wu'
847
848 Because this is unconditional, unlike `git diff --color=auto`, you
849 will then have to remember to add the `-i` option to `fossil diff`
850 commands when you want color disabled, such as when producing
851 `patch(1)` files or piping diff output to another command that
852 doesn’t understand ANSI escape sequences. There’s an example of this
853 [below](#dstat).
854
855 * Use the Fossil web UI to diff existing commits.
856
857 * To diff the current working directory contents against some parent
858 instead, Fossil’s diff command can produce
859 colorized HTML output and open it in the OS’s default web browser.
860 For example, `fossil diff -by` will show side-by-side diffs.
861
862 * Use the older `fossil diff --tk` option to do much the same using
863 Tcl/Tk instead of a browser.
864
865 Viewed this way, Fossil doesn’t lack colorized diffs, it simply has
866 *one* method where they *aren’t* colorized.
867
868 [cdpkg]: https://repology.org/project/colordiff/versions
869 [pfile]: https://en.wikipedia.org/wiki/Patch_(Unix)
870 [udiff]: https://en.wikipedia.org/wiki/Diff#Unified_format
871
872
873 ## <a id="show"></a> Showing Information About Commits
@@ -936,19 +934,17 @@
936 a histogram in its default output mode rather than bare integers:
937
938 fossil diff -i -v --from 2020-04-01 | diffstat
939
940 We gave the `-i` flag in both cases to force Fossil to use its internal
941 diff implementation, bypassing [your local `diff-command` setting][dcset].
942 The `--numstat` option has no effect when you have an external diff
943 command set, and some diff command alternatives like
944 [`colordiff`][cdiff] (covered [above](#cdiff)) produce output that confuses `diffstat`.
945
946 If you leave off the `-v` flag in the second example, the `diffstat`
947 output won’t include info about any newly-added files.
948
949 [cdiff]: https://www.colordiff.org/
950 [dcset]: https://fossil-scm.org/home/help?cmd=diff-command
951 [dst]: https://invisible-island.net/diffstat/diffstat.html
952
953
954 <a id="btnames"></a>
955
--- www/gitusers.md
+++ www/gitusers.md
@@ -139,13 +139,13 @@
139
140
141 #### <a id="close" name="dotfile"></a> Closing a Check-Out
142
143 The [`fossil close`][close] command dissociates a check-out directory from the
144 Fossil repository database, _nondestructively_ inverting [`fossil open`][open].
145 (Contrast Git’s [closest alternative](#worktree), `git worktree remove`, which *is*
146 destructive!) This Fossil command does not
147 remove the managed files, and unless you give the `--force`
148 option, it won’t let you close the check-out with uncommitted changes to
149 those managed files.
150
151 The `close` command also refuses to run without `--force` when you have
@@ -300,15 +300,15 @@
300 Yet the constants are *not* equal because Fossil
301 reads from a single disk file rather than visit potentially many
302 files in sequence as Git must, so the OS’s buffer cache can result in
303 [still better performance][35pct].
304
305 Unlike Git’s log, Fossil’s timeline shows info across all branches by
306 default, a feature for maintaining better situational awareness.
307 It is possible to restrict the timeline to a single branch using `fossil timeline -b`.
308 Similarly, to restrict the timeline using the web UI equivalent,
309 click the name of a branch on the `/timeline` or `/brlist` page. (Or
310 manually, by adding the `r=` query parameter.) Note that even in this
311 case, the Fossil timeline still shows other branches where they interact
312 with the one you’ve referenced in this way; again, better situational
313 awareness.
314
@@ -457,28 +457,67 @@
457
458 [cskin]: ./customskin.md
459 [lsl]: https://chris.beams.io/posts/git-commit/#limit-50
460
461
462 <a id="autocommit"></a>
463 ## Fossil Never Auto-Commits
464
465 There are several features in Git besides its `commit` command that
466 produce a new commit to the repository, and by default, they do it
467 without prompting or even asking for a commit message. These include
468 Git’s [`rebase`](#rebase), `merge`, and [`cherrypick`](#cpickrev)
469 commands, plus the [commit splitting](#comsplit) sub-feature
470 “`git commit -p`”.
471
472 Fossil never does this, on firm philosophical grounds: we wish to be
473 able to test that each potentially repository-changing command does not
474 break anything _before_ freezing it immutably into the [Merkle
475 tree](./blockchain.md). Where Fossil has equivalent commands, they
476 modify the checkout tree alone, requiring a separate `commit` command
477 afterward, withheld until the user has satisfied themselves that the
478 command’s result is correct.
479
480 We believe this is the main reason Git lacks an [autosync](#autosync)
481 feature: making push a manual step gives the user a chance to rewrite
482 history after triggering one of these autocommits locally, should the
483 automatic commit fail to work out as expected. Fossil chooses the
484 inverse path under the philosophy that commits are *commitments,* not
485 something you’re allowed to go back and rewrite later.
486
487 This is also why there is no automatic commit message writing feature in
488 Fossil, as in these autocommit-triggering Git commands. The user is
489 meant to write the commit message by hand after they are sure it’s
490 correct, in clear-headed retrospective fashion. Having the tool do it
491 prospectively before one can test the result is simply backwards.
492
493
494 <a id="staging"></a>
495 ## There Is No Staging Area
496
497 Fossil omits the "Git index" or "staging area" concept. When you
498 type "`fossil commit`" _all_ changes in your check-out are committed,
499 by default. There is no need for the "-a" option as with Git.
500
501 If you only want to commit _some_ of the changes, list the names
502 of the files or directories you want to commit as arguments, like this:
503
504 fossil commit src/feature.c doc/feature.md examples/feature
505
506 Note that the last element is a directory name, meaning “any changed
507 file under the `examples/feature` directory.”
508
509
510 <a id="comsplit"></a>
511 ## Commit Splitting
512
513 [Git’s commit splitting features][gcspl] rely on
514 other features of Git that Fossil purposefully lacks, as covered in the
515 prior two sections: [autocommit](#autocommit) and [the staging
516 area](#staging).
517
518 While there is no direct Fossil equivalent for
519 `git add -p`, `git commit -p`, or `git rebase -i`, you can get the same
520 effect by converting an uncommitted change set to a patch and then
521 running it through [Patchouli].
522
523 Rather than use `fossil diff -i` to produce such a patch, a safer and
@@ -494,28 +533,17 @@
533 hunks already applied.
534
535 In this way, the combination of working tree and stash replaces the need
536 for Git’s index feature.
537
538 We believe we know how to do commit splitting in a way compatible with
539 the Fossil philosophy, without following Git’s ill-considered design
540 leads. It amounts to automating the above process through an interactive
541 variant of [`fossil stash apply`][stash], as currently prototyped in the
542 third-party tool [`fnc`][fnc] and [its interactive `stash`
543 command][fncsta]. We merely await someone’s [contribution][ctrb] of this
544 feature into Fossil proper.
 
 
 
 
 
 
 
 
 
 
 
545
546 [ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki
547 [fnc]: https://fnc.bsdbox.org/
548 [fncsta]: https://fnc.bsdbox.org/uv/doc/fnc.1.html#stash
549 [gcspl]: https://git-scm.com/docs/git-rebase#_splitting_commits
@@ -817,57 +845,27 @@
845 come up with a new objection that we haven’t already considered and
846 addressed there.
847
848 There is only one sub-feature of `git rebase` that is philosophically
849 compatible with Fossil yet which currently has no functional equivalent.
850 We [covered this and the workaround for its lack](#comsplit) above.
851
852 [3]: ./rebaseharm.md
853
854
855 <a id="cdiff"></a>
856 ## Colorized Diffs
857
858 When you run `git diff` on an ANSI X3.64 capable terminal, it uses color
859 to distinguish insertions, deletions, and replacements, but as of this
860 writing, `fossil diff` produces traditional uncolored [unified diff
861 format][udiff] output, suitable for producing a [patch file][pfile].
862
863 There are [many methods](./colordiff.md) for solving this.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864 Viewed this way, Fossil doesn’t lack colorized diffs, it simply has
865 *one* method where they *aren’t* colorized.
866
 
867 [pfile]: https://en.wikipedia.org/wiki/Patch_(Unix)
868 [udiff]: https://en.wikipedia.org/wiki/Diff#Unified_format
869
870
871 ## <a id="show"></a> Showing Information About Commits
@@ -936,19 +934,17 @@
934 a histogram in its default output mode rather than bare integers:
935
936 fossil diff -i -v --from 2020-04-01 | diffstat
937
938 We gave the `-i` flag in both cases to force Fossil to use its internal
939 diff implementation, bypassing [your local `diff-command` setting][dcset]
940 since the `--numstat` option has no effect when you have an external diff
941 command set.
 
942
943 If you leave off the `-v` flag in the second example, the `diffstat`
944 output won’t include info about any newly-added files.
945
 
946 [dcset]: https://fossil-scm.org/home/help?cmd=diff-command
947 [dst]: https://invisible-island.net/diffstat/diffstat.html
948
949
950 <a id="btnames"></a>
951
+14 -2
--- www/hints.wiki
+++ www/hints.wiki
@@ -1,9 +1,11 @@
11
<title>Fossil Tips And Usage Hints</title>
22
3
- 1. Click on nodes of any timeline graph to see diffs between the two
4
- selected versions.
3
+A collection of useful hints and tricks in no particular order:
4
+
5
+ 1. Click on two nodes of any timeline graph in succession
6
+ to see a diff between the two versions.
57
68
2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands
79
to get a pop-up
810
window containing a complete side-by-side diff. (NB: The pop-up
911
window is run as a separate Tcl/Tk process, so you will need to
@@ -58,5 +60,15 @@
5860
5961
10. When editing documentation to be checked in as managed files, you can
6062
preview what the documentation will look like by using the special
6163
"ckout" branch name in the "doc" URL while running "fossil ui".
6264
See the [./embeddeddoc.wiki | embedded documentation] for details.
65
+
66
+ 11. Use the "[/help?cmd=ui|fossil ui /]" command to bring up a menu of
67
+ all of your local Fossil repositories in your web browser.
68
+
69
+ 12. If you have a bunch of Fossil repositories living on a remote machine
70
+ that you are able to access using ssh using a command like
71
+ "ssh login@remote", then you can bring up a user interface for all
72
+ those remote repositories using the command:
73
+ "[/help?cmd=ui|fossil ui login@remote:/]". This works by tunneling
74
+ all HTTP traffic through SSH to the remote machine.
6375
--- www/hints.wiki
+++ www/hints.wiki
@@ -1,9 +1,11 @@
1 <title>Fossil Tips And Usage Hints</title>
2
3 1. Click on nodes of any timeline graph to see diffs between the two
4 selected versions.
 
 
5
6 2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands
7 to get a pop-up
8 window containing a complete side-by-side diff. (NB: The pop-up
9 window is run as a separate Tcl/Tk process, so you will need to
@@ -58,5 +60,15 @@
58
59 10. When editing documentation to be checked in as managed files, you can
60 preview what the documentation will look like by using the special
61 "ckout" branch name in the "doc" URL while running "fossil ui".
62 See the [./embeddeddoc.wiki | embedded documentation] for details.
 
 
 
 
 
 
 
 
 
 
63
--- www/hints.wiki
+++ www/hints.wiki
@@ -1,9 +1,11 @@
1 <title>Fossil Tips And Usage Hints</title>
2
3 A collection of useful hints and tricks in no particular order:
4
5 1. Click on two nodes of any timeline graph in succession
6 to see a diff between the two versions.
7
8 2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands
9 to get a pop-up
10 window containing a complete side-by-side diff. (NB: The pop-up
11 window is run as a separate Tcl/Tk process, so you will need to
@@ -58,5 +60,15 @@
60
61 10. When editing documentation to be checked in as managed files, you can
62 preview what the documentation will look like by using the special
63 "ckout" branch name in the "doc" URL while running "fossil ui".
64 See the [./embeddeddoc.wiki | embedded documentation] for details.
65
66 11. Use the "[/help?cmd=ui|fossil ui /]" command to bring up a menu of
67 all of your local Fossil repositories in your web browser.
68
69 12. If you have a bunch of Fossil repositories living on a remote machine
70 that you are able to access using ssh using a command like
71 "ssh login@remote", then you can bring up a user interface for all
72 those remote repositories using the command:
73 "[/help?cmd=ui|fossil ui login@remote:/]". This works by tunneling
74 all HTTP traffic through SSH to the remote machine.
75
+4 -4
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
8484
the repository are consistent prior to each commit.
8585
8686
8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
8787
8888
<hr>
89
-<h3>Latest Release: 2.23 ([/timeline?c=version-2.23|2023-11-01])</h3>
89
+<h3>Latest Release: 2.24 ([/timeline?c=version-2.24|2024-04-23])</h3>
9090
9191
* [/uv/download.html|Download]
92
- * [./changes.wiki#v2_23|Change Summary]
93
- * [/timeline?p=version-2.23&bt=version-2.22&y=ci|Check-ins in version 2.23]
94
- * [/timeline?df=version-2.23&y=ci|Check-ins derived from the 2.23 release]
92
+ * [./changes.wiki#v2_24|Change Summary]
93
+ * [/timeline?p=version-2.24&bt=version-2.23&y=ci|Check-ins in version 2.24]
94
+ * [/timeline?df=version-2.24&y=ci|Check-ins derived from the 2.24 release]
9595
* [/timeline?t=release|Timeline of all past releases]
9696
9797
<hr>
9898
<h3>Quick Start</h3>
9999
100100
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
84 the repository are consistent prior to each commit.
85
86 8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
87
88 <hr>
89 <h3>Latest Release: 2.23 ([/timeline?c=version-2.23|2023-11-01])</h3>
90
91 * [/uv/download.html|Download]
92 * [./changes.wiki#v2_23|Change Summary]
93 * [/timeline?p=version-2.23&bt=version-2.22&y=ci|Check-ins in version 2.23]
94 * [/timeline?df=version-2.23&y=ci|Check-ins derived from the 2.23 release]
95 * [/timeline?t=release|Timeline of all past releases]
96
97 <hr>
98 <h3>Quick Start</h3>
99
100
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
84 the repository are consistent prior to each commit.
85
86 8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
87
88 <hr>
89 <h3>Latest Release: 2.24 ([/timeline?c=version-2.24|2024-04-23])</h3>
90
91 * [/uv/download.html|Download]
92 * [./changes.wiki#v2_24|Change Summary]
93 * [/timeline?p=version-2.24&bt=version-2.23&y=ci|Check-ins in version 2.24]
94 * [/timeline?df=version-2.24&y=ci|Check-ins derived from the 2.24 release]
95 * [/timeline?t=release|Timeline of all past releases]
96
97 <hr>
98 <h3>Quick Start</h3>
99
100
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -35,10 +35,11 @@
3535
checkin.wiki {Check-in Checklist}
3636
childprojects.wiki {Child Projects}
3737
chroot.md {Server Chroot Jail}
3838
ckout-workflows.md {Check-Out Workflows}
3939
co-vs-up.md {Checkout vs Update}
40
+ colordiff.md {Colorized Diffs}
4041
copyright-release.html {Contributor License Agreement}
4142
concepts.wiki {Fossil Core Concepts}
4243
contact.md {Developer Contact Information}
4344
containers.md {OCI Containers}
4445
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
4546
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -35,10 +35,11 @@
35 checkin.wiki {Check-in Checklist}
36 childprojects.wiki {Child Projects}
37 chroot.md {Server Chroot Jail}
38 ckout-workflows.md {Check-Out Workflows}
39 co-vs-up.md {Checkout vs Update}
 
40 copyright-release.html {Contributor License Agreement}
41 concepts.wiki {Fossil Core Concepts}
42 contact.md {Developer Contact Information}
43 containers.md {OCI Containers}
44 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
45
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -35,10 +35,11 @@
35 checkin.wiki {Check-in Checklist}
36 childprojects.wiki {Child Projects}
37 chroot.md {Server Chroot Jail}
38 ckout-workflows.md {Check-Out Workflows}
39 co-vs-up.md {Checkout vs Update}
40 colordiff.md {Colorized Diffs}
41 copyright-release.html {Contributor License Agreement}
42 concepts.wiki {Fossil Core Concepts}
43 contact.md {Developer Contact Information}
44 containers.md {OCI Containers}
45 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
46
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -35,10 +35,11 @@
3535
<li><a href="checkin.wiki">Check-in Checklist</a></li>
3636
<li><a href="ckout-workflows.md">Check-Out Workflows</a></li>
3737
<li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
3838
<li><a href="co-vs-up.md">Checkout vs Update</a></li>
3939
<li><a href="childprojects.wiki">Child Projects</a></li>
40
+<li><a href="colordiff.md">Colorized Diffs</a></li>
4041
<li><a href="build.wiki">Compiling and Installing Fossil</a></li>
4142
<li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
4243
<li><a href="copyright-release.html">Contributor License Agreement</a></li>
4344
<li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li>
4445
<li><a href="customskin.md">Custom Skins</a></li>
4546
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -35,10 +35,11 @@
35 <li><a href="checkin.wiki">Check-in Checklist</a></li>
36 <li><a href="ckout-workflows.md">Check-Out Workflows</a></li>
37 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
38 <li><a href="co-vs-up.md">Checkout vs Update</a></li>
39 <li><a href="childprojects.wiki">Child Projects</a></li>
 
40 <li><a href="build.wiki">Compiling and Installing Fossil</a></li>
41 <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
42 <li><a href="copyright-release.html">Contributor License Agreement</a></li>
43 <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li>
44 <li><a href="customskin.md">Custom Skins</a></li>
45
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -35,10 +35,11 @@
35 <li><a href="checkin.wiki">Check-in Checklist</a></li>
36 <li><a href="ckout-workflows.md">Check-Out Workflows</a></li>
37 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
38 <li><a href="co-vs-up.md">Checkout vs Update</a></li>
39 <li><a href="childprojects.wiki">Child Projects</a></li>
40 <li><a href="colordiff.md">Colorized Diffs</a></li>
41 <li><a href="build.wiki">Compiling and Installing Fossil</a></li>
42 <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li>
43 <li><a href="copyright-release.html">Contributor License Agreement</a></li>
44 <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li>
45 <li><a href="customskin.md">Custom Skins</a></li>
46
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -88,5 +88,28 @@
8888
proxy_set_header X-Forwarded-Proto $scheme;
8989
9090
has been be added in the relevant proxying section of the Nginx config file.
9191
9292
*[Return to the top-level Fossil server article.](../)*
93
+
94
+#### Apache mod_cgi and `CONTENT_LENGTH`
95
+
96
+At some point in its 2.4.x family, Apache's `mod_cgi` stopped relaying
97
+the Content-Length header in the HTTP reply from CGIs back to clients.
98
+However, Fossil clients prior to 2024-04-17 depended on seeing the
99
+Content-Length header and were unable to handle HTTP replies without
100
+one. The change in Apache behavior caused "fossil clone" and "fossil
101
+sync" to stop working. There are two possible fixes to this problem:
102
+
103
+ 1. Restore legacy behavior in Apache by adding
104
+ the following to the Apache configuration, scoped to the `<Directory>`
105
+ entry or entries in which fossil is being served via CGI:
106
+ <blockquote><pre>
107
+ &lt;Directory ...&gt;
108
+ SetEnv ap_trust_cgilike_cl "yes"
109
+ &lt;/Directory&gt;
110
+ </pre></blockquote>
111
+
112
+ 2. Upgrade your Fossil client to any trunk check-in after 2024-04-17,
113
+ as Fossil was upgraded to be able to deal with the missing
114
+ Content-Length field by
115
+ [check-in a8e33fb161f45b65](/info/a8e33fb161f45b65).
93116
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -88,5 +88,28 @@
88 proxy_set_header X-Forwarded-Proto $scheme;
89
90 has been be added in the relevant proxying section of the Nginx config file.
91
92 *[Return to the top-level Fossil server article.](../)*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -88,5 +88,28 @@
88 proxy_set_header X-Forwarded-Proto $scheme;
89
90 has been be added in the relevant proxying section of the Nginx config file.
91
92 *[Return to the top-level Fossil server article.](../)*
93
94 #### Apache mod_cgi and `CONTENT_LENGTH`
95
96 At some point in its 2.4.x family, Apache's `mod_cgi` stopped relaying
97 the Content-Length header in the HTTP reply from CGIs back to clients.
98 However, Fossil clients prior to 2024-04-17 depended on seeing the
99 Content-Length header and were unable to handle HTTP replies without
100 one. The change in Apache behavior caused "fossil clone" and "fossil
101 sync" to stop working. There are two possible fixes to this problem:
102
103 1. Restore legacy behavior in Apache by adding
104 the following to the Apache configuration, scoped to the `<Directory>`
105 entry or entries in which fossil is being served via CGI:
106 <blockquote><pre>
107 &lt;Directory ...&gt;
108 SetEnv ap_trust_cgilike_cl "yes"
109 &lt;/Directory&gt;
110 </pre></blockquote>
111
112 2. Upgrade your Fossil client to any trunk check-in after 2024-04-17,
113 as Fossil was upgraded to be able to deal with the missing
114 Content-Length field by
115 [check-in a8e33fb161f45b65](/info/a8e33fb161f45b65).
116
+16
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -189,10 +189,26 @@
189189
190190
This can also happen if you've linked Fossil to a version of OpenSSL
191191
[#openssl-src|built from source]. That same <tt>cacert.pem</tt> fix can
192192
work in that case, too.
193193
194
+<blockquote>
195
+OpenSSL 3.2.0 or greater is able to use the stock CA certificates
196
+managed by Windows, and Fossil 2.25 (still in development as of
197
+2024-07-15) takes advantage of this feature. This <em>possibly</em>
198
+eliminates the need to manually install the Mozilla certificate package,
199
+for example when connecting to Fossil servers secured by the widely-used
200
+Let's Encrypt certificates. Run the following command to check if the
201
+feature is supported:
202
+
203
+<pre>
204
+fossil tls-config show -v
205
+</pre>
206
+
207
+(See the "OpenSSL-winstore" section, requires Fossil 2.25 or greater.)
208
+</blockquote>
209
+
194210
When you build Fossil on Linux platforms against the binary OpenSSL
195211
package provided with the OS, you typically get a root cert store along
196212
with the platform OpenSSL package, either built-in or as a hard
197213
dependency.
198214
199215
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -189,10 +189,26 @@
189
190 This can also happen if you've linked Fossil to a version of OpenSSL
191 [#openssl-src|built from source]. That same <tt>cacert.pem</tt> fix can
192 work in that case, too.
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194 When you build Fossil on Linux platforms against the binary OpenSSL
195 package provided with the OS, you typically get a root cert store along
196 with the platform OpenSSL package, either built-in or as a hard
197 dependency.
198
199
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -189,10 +189,26 @@
189
190 This can also happen if you've linked Fossil to a version of OpenSSL
191 [#openssl-src|built from source]. That same <tt>cacert.pem</tt> fix can
192 work in that case, too.
193
194 <blockquote>
195 OpenSSL 3.2.0 or greater is able to use the stock CA certificates
196 managed by Windows, and Fossil 2.25 (still in development as of
197 2024-07-15) takes advantage of this feature. This <em>possibly</em>
198 eliminates the need to manually install the Mozilla certificate package,
199 for example when connecting to Fossil servers secured by the widely-used
200 Let's Encrypt certificates. Run the following command to check if the
201 feature is supported:
202
203 <pre>
204 fossil tls-config show -v
205 </pre>
206
207 (See the "OpenSSL-winstore" section, requires Fossil 2.25 or greater.)
208 </blockquote>
209
210 When you build Fossil on Linux platforms against the binary OpenSSL
211 package provided with the OS, you typically get a root cert store along
212 with the platform OpenSSL package, either built-in or as a hard
213 dependency.
214
215
+9 -7
--- www/unvers.wiki
+++ www/unvers.wiki
@@ -1,21 +1,22 @@
11
<title>Unversioned Content</title>
22
33
"Unversioned content" or "unversioned files" are
44
files stored in a Fossil repository without history, meaning
55
it retains the newest version of each such file, and that alone.
6
+Unversioned files may have an optional directory name prefix.
67
78
Though it omits history, Fossil does sync unversioned content between
89
repositories. In the event of a conflict during a sync, it retains
910
the most recent version of each unversioned file, discarding
1011
older versions.
1112
12
-Unversioned files are useful for storing ephemeral content such as builds
13
-or frequently changing web pages. We store
14
-the [https://fossil-scm.org/home/uv/download.html|download] page of
15
-the self-hosting Fossil repository as unversioned
16
-content, for example.
13
+Unversioned files are useful for storing ephemeral content such as
14
+builds or frequently changing web pages. We store the
15
+[https://fossil-scm.org/home/uv/download.html|download] page of the
16
+self-hosting Fossil repository as unversioned content, for
17
+example.
1718
1819
<h2>Accessing Unversioned Files</h2>
1920
2021
Unversioned files are <u>not</u> a part of a check-out.
2122
Unversioned files are intended to be accessible as web pages using
@@ -23,14 +24,15 @@
2324
In other words, the URI method "<b>uv</b>" (short for "unversioned")
2425
followed by the name of the unversioned file will retrieve the content
2526
of the file. The MIME type is inferred from the filename suffix.
2627
2728
The content of unversioned files can also be retrieved using the
28
-[/help?cmd=unversioned|fossil unvers cat <i>FILENAME</i>] command.
29
+[/help?cmd=unversioned|fossil unvers cat <i>FILENAME...</i>]
30
+or [/help?cmd=unversioned|fossil unvers export <i>FILENAME</i>] commands.
2931
3032
A list of all unversioned files on a server can be seen using
31
-the [/help?cmd=/uvlist|/uvlist] URL. ([/uvlist|example]).
33
+the [/help?cmd=/uvlist|/uvlist] URL. ([/uvlist|example].)
3234
3335
<h2>Syncing Unversioned Files</h2>
3436
3537
Unversioned content does not sync between repositories by default.
3638
One must request it via commands such as:
3739
--- www/unvers.wiki
+++ www/unvers.wiki
@@ -1,21 +1,22 @@
1 <title>Unversioned Content</title>
2
3 "Unversioned content" or "unversioned files" are
4 files stored in a Fossil repository without history, meaning
5 it retains the newest version of each such file, and that alone.
 
6
7 Though it omits history, Fossil does sync unversioned content between
8 repositories. In the event of a conflict during a sync, it retains
9 the most recent version of each unversioned file, discarding
10 older versions.
11
12 Unversioned files are useful for storing ephemeral content such as builds
13 or frequently changing web pages. We store
14 the [https://fossil-scm.org/home/uv/download.html|download] page of
15 the self-hosting Fossil repository as unversioned
16 content, for example.
17
18 <h2>Accessing Unversioned Files</h2>
19
20 Unversioned files are <u>not</u> a part of a check-out.
21 Unversioned files are intended to be accessible as web pages using
@@ -23,14 +24,15 @@
23 In other words, the URI method "<b>uv</b>" (short for "unversioned")
24 followed by the name of the unversioned file will retrieve the content
25 of the file. The MIME type is inferred from the filename suffix.
26
27 The content of unversioned files can also be retrieved using the
28 [/help?cmd=unversioned|fossil unvers cat <i>FILENAME</i>] command.
 
29
30 A list of all unversioned files on a server can be seen using
31 the [/help?cmd=/uvlist|/uvlist] URL. ([/uvlist|example]).
32
33 <h2>Syncing Unversioned Files</h2>
34
35 Unversioned content does not sync between repositories by default.
36 One must request it via commands such as:
37
--- www/unvers.wiki
+++ www/unvers.wiki
@@ -1,21 +1,22 @@
1 <title>Unversioned Content</title>
2
3 "Unversioned content" or "unversioned files" are
4 files stored in a Fossil repository without history, meaning
5 it retains the newest version of each such file, and that alone.
6 Unversioned files may have an optional directory name prefix.
7
8 Though it omits history, Fossil does sync unversioned content between
9 repositories. In the event of a conflict during a sync, it retains
10 the most recent version of each unversioned file, discarding
11 older versions.
12
13 Unversioned files are useful for storing ephemeral content such as
14 builds or frequently changing web pages. We store the
15 [https://fossil-scm.org/home/uv/download.html|download] page of the
16 self-hosting Fossil repository as unversioned content, for
17 example.
18
19 <h2>Accessing Unversioned Files</h2>
20
21 Unversioned files are <u>not</u> a part of a check-out.
22 Unversioned files are intended to be accessible as web pages using
@@ -23,14 +24,15 @@
24 In other words, the URI method "<b>uv</b>" (short for "unversioned")
25 followed by the name of the unversioned file will retrieve the content
26 of the file. The MIME type is inferred from the filename suffix.
27
28 The content of unversioned files can also be retrieved using the
29 [/help?cmd=unversioned|fossil unvers cat <i>FILENAME...</i>]
30 or [/help?cmd=unversioned|fossil unvers export <i>FILENAME</i>] commands.
31
32 A list of all unversioned files on a server can be seen using
33 the [/help?cmd=/uvlist|/uvlist] URL. ([/uvlist|example].)
34
35 <h2>Syncing Unversioned Files</h2>
36
37 Unversioned content does not sync between repositories by default.
38 One must request it via commands such as:
39

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button