Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest trunk changes into the begin-concurrent branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | begin-concurrent |
Files: | files | file ages | folders |
SHA3-256: |
9fec43d927fdd7d58cca352f7e7414c9 |
User & Date: | drh 2025-05-19 16:45:11.870 |
Context
2025-05-19
| ||
16:45 | Merge the latest trunk changes into the begin-concurrent branch. (Leaf check-in: 9fec43d927 user: drh tags: begin-concurrent) | |
14:50 | Clarify some malloc size computations to simplify the proof that they are safe. Remove some code associated with cygwin that is marked "#if 0". (check-in: ba8184d132 user: drh tags: trunk) | |
2025-05-06
| ||
21:26 | Merge all the latest trunk enhancements into the begin-concurrent branch. (check-in: 55a51ba58f user: drh tags: begin-concurrent) | |
Changes
Changes to autoconf/tea/Makefile.in.
1 2 3 4 5 6 7 8 | all: # # This makefile is part of the teaish framework, a tool for building # Tcl extensions, conceptually related to TEA/tclconfig but using the # Autosetup configuration system instead of the GNU Autotools. # # A copy of this makefile gets processed for each extension separately # and populated with info about how to build, test, and install the | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | all: # # Unless this file is named Makefile.in, you are probably looking # at an automatically generated/filtered copy and should probably not # edit it. # # This makefile is part of the teaish framework, a tool for building # Tcl extensions, conceptually related to TEA/tclconfig but using the # Autosetup configuration system instead of the GNU Autotools. # # A copy of this makefile gets processed for each extension separately # and populated with info about how to build, test, and install the |
︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | tx.makefile.in = @TEAISH_MAKEFILE_IN@ tx.dll8.basename = @TEAISH_DLL8_BASENAME@ tx.dll9.basename = @TEAISH_DLL9_BASENAME@ tx.dll8 = @TEAISH_DLL8@ tx.dll9 = @TEAISH_DLL9@ tx.dll = $(tx.dll$(TCL_MAJOR_VERSION)) tx.dir = @TEAISH_EXT_DIR@ @if TEAISH_DIST_NAME tx.name.dist = @TEAISH_DIST_NAME@ @else tx.name.dist = $(teaish.name) @endif | > > > > > > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | tx.makefile.in = @TEAISH_MAKEFILE_IN@ tx.dll8.basename = @TEAISH_DLL8_BASENAME@ tx.dll9.basename = @TEAISH_DLL9_BASENAME@ tx.dll8 = @TEAISH_DLL8@ tx.dll9 = @TEAISH_DLL9@ tx.dll = $(tx.dll$(TCL_MAJOR_VERSION)) tx.dir = @TEAISH_EXT_DIR@ @if TEAISH_TM_TCL # Input filename for tcl::tm-style module tx.tm = @TEAISH_TM_TCL@ # Target filename for tcl::tm-style installation tx.tm.tgt = $(tx.name.pkg)-$(tx.version).tm @endif @if TEAISH_DIST_NAME tx.name.dist = @TEAISH_DIST_NAME@ @else tx.name.dist = $(teaish.name) @endif |
︙ | ︙ | |||
153 154 155 156 157 158 159 | # # The list of 'dist' files may be appended to from teaish.make.in. # It can also be set up from teaish.tcl using [teaish-dist-add] # and/or [teaish-src-add -dist ...]. # tx.dist.files = @TEAISH_DIST_FILES@ | < < < < < < < < < < < | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | # # The list of 'dist' files may be appended to from teaish.make.in. # It can also be set up from teaish.tcl using [teaish-dist-add] # and/or [teaish-src-add -dist ...]. # tx.dist.files = @TEAISH_DIST_FILES@ # List of deps which may trigger an auto-reconfigure. # teaish__autogen.deps = \ $(tx.makefile.in) $(teaish.makefile.in) \ $(tx.tcl) \ @TEAISH_PKGINDEX_TCL_IN@ @TEAISH_TM_TCL_IN@ \ @AUTODEPS@ @if TEAISH_MAKEFILE_IN $(tx.makefile): $(tx.makefile.in) @endif teaish.autoreconfig = \ |
︙ | ︙ | |||
267 268 269 270 271 272 273 | test-post: test-core test: test-post # # Cleanup rules... # #.PHONY: clean-pre clean-core clean-post clean-extension | < > | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | test-post: test-core test: test-post # # Cleanup rules... # #.PHONY: clean-pre clean-core clean-post clean-extension # clean-pre: clean-core: clean-pre rm -f $(tx.dll8) $(tx.dll9) tclsh clean-post: clean-core clean: clean-post .PHONY: distclean-pre distclean-core distclean-post clean-extension distclean-pre: clean distclean-core: distclean-pre rm -f Makefile |
︙ | ︙ | |||
296 297 298 299 300 301 302 | @endif @if TEAISH_PKGINIT_TCL_IN rm -f @TEAISH_PKGINIT_TCL@ @endif @if TEAISH_TEST_TCL_IN rm -f @TEAISH_TEST_TCL@ @endif | < > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | @endif @if TEAISH_PKGINIT_TCL_IN rm -f @TEAISH_PKGINIT_TCL@ @endif @if TEAISH_TEST_TCL_IN rm -f @TEAISH_TEST_TCL@ @endif distclean-post: distclean-core distclean: distclean-post # # The (dist)clean-extension targets are reserved for use by # client-side teaish.make. # # Client code which wants to clean up extra stuff should do so by # adding their cleanup target (e.g. clean-extension) as a dependency # to the 'clean' target, like so: # # clean: distclean-extension # distclean: distclean-extension # distclean-extension: clean-extension: # # Installation rules... # @if TEAISH_ENABLE_INSTALL .PHONY: install-pre install-core install-post install-test install-prepre install-extension install-extension: # this name is reserved for use by teaish.make @if TEAISH_ENABLE_DLL install-prepre: $(tx.dll) @else install-prepre: @endif @if TEAISH_TM_TCL install-core.tmdir = $(DESTDIR)@TEAISH_TCL_TM_DIR@ @endif install-pre: install-prepre install-core: install-pre @if [ ! -d "$(DESTDIR)$(TCLLIBDIR)" ]; then \ set -x; $(INSTALL) -d "$(DESTDIR)$(TCLLIBDIR)"; \ fi # ^^^^ on some platforms, install -d fails if the target already exists. @if TEAISH_ENABLE_DLL $(INSTALL) $(tx.dll) "$(DESTDIR)$(TCLLIBDIR)" @endif @if TEAISH_PKGINDEX_TCL $(INSTALL.noexec) "@TEAISH_PKGINDEX_TCL@" "$(DESTDIR)$(TCLLIBDIR)" @endif @if TEAISH_PKGINIT_TCL $(INSTALL.noexec) "@TEAISH_PKGINIT_TCL@" "$(DESTDIR)$(TCLLIBDIR)" @endif @if TEAISH_TM_TCL @if [ ! -d "$(install-core.tmdir)" ]; then \ set -x; $(INSTALL) -d "$(install-core.tmdir)"; \ fi $(INSTALL.noexec) "@TEAISH_TM_TCL@" "$(install-core.tmdir)/$(tx.tm.tgt)" @endif install-test: install-core @echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \ if echo \ 'set c 0; ' \ '@TEAISH_POSTINST_PREREQUIRE@' \ 'if {[catch {package require $(tx.name.pkg) $(tx.version)}]} {incr c};' \ |
︙ | ︙ | |||
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | # # Uninstall rules... # .PHONY: uninstall uninstall-pre uninstall-core uninstall-post uninstall-extension uninstall-extension: # this name is reserved for use by teaish.make uninstall-pre: uninstall-core: uninstall-pre rm -fr "$(DESTDIR)$(TCLLIBDIR)" uninstall-post: uninstall-core @echo "Uninstalled Tcl extension $(tx.name) $(tx.version)" uninstall: uninstall-post @if TEAISH_MAKEFILE_IN Makefile: $(tx.makefile.in) config.log: $(teaish.makefile.in) @endif # | > > > > > > > | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | # # Uninstall rules... # .PHONY: uninstall uninstall-pre uninstall-core uninstall-post uninstall-extension uninstall-extension: # this name is reserved for use by teaish.make uninstall-pre: uninstall-core: uninstall-pre @if TEAISH_ENABLE_DLL rm -fr "$(DESTDIR)$(TCLLIBDIR)" @endif @if TEAISH_TM_TCL rm -f "$(DESTDIR)$(install-core.tmdir)/$(tx.tm.tgt)" @endif uninstall-post: uninstall-core @echo "Uninstalled Tcl extension $(tx.name) $(tx.version)" uninstall: uninstall-post @endif # TEAISH_ENABLE_INSTALL @if TEAISH_MAKEFILE_IN Makefile: $(tx.makefile.in) config.log: $(teaish.makefile.in) @endif # |
︙ | ︙ |
Name change from autoconf/tea/teaish.tester.tcl.in to autoconf/tea/_teaish.tester.tcl.in.
1 2 | # -*- tcl -*- # | | | 1 2 3 4 5 6 7 8 9 10 | # -*- tcl -*- # # Unless this file is named _teaish.tester.tcl.in, you are probably # looking at an automatically generated/filtered copy and should # probably not edit it. # # This is the wrapper script invoked by teaish's "make test" recipe. # It gets passed 3 args: # # $1 = the DLL name, or "" if the extension has no DLL |
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | source -encoding utf-8 [lindex $::argv 2]; # teaish/tester.tcl @if TEAISH_PKGINIT_TCL apply {{file} { set dir [file dirname $::argv0] source -encoding utf-8 $file }} [join {@TEAISH_PKGINIT_TCL@}] @endif @if TEAISH_TEST_TCL apply {{file} { # Populate state for [tester.tcl::teaish-build-flag*] array set ::teaish__BuildFlags @TEAISH__DEFINES_MAP@ set dir [file normalize [file dirname $file]] #test-fail "Just testing" source -encoding utf-8 $file }} [join {@TEAISH_TEST_TCL@}] @else # TEAISH_TEST_TCL # No $TEAISH_TEST_TCL provided, so here's a default test which simply # loads the extension. puts {Extension @TEAISH_NAME@ @TEAISH_VERSION@ successfully loaded from @TEAISH_TESTER_TCL@} @endif | > > > > > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | source -encoding utf-8 [lindex $::argv 2]; # teaish/tester.tcl @if TEAISH_PKGINIT_TCL apply {{file} { set dir [file dirname $::argv0] source -encoding utf-8 $file }} [join {@TEAISH_PKGINIT_TCL@}] @endif @if TEAISH_TM_TCL apply {{file} { set dir [file dirname $::argv0] source -encoding utf-8 $file }} [join {@TEAISH_TM_TCL@}] @endif @if TEAISH_TEST_TCL apply {{file} { # Populate state for [tester.tcl::teaish-build-flag*] array set ::teaish__BuildFlags @TEAISH__DEFINES_MAP@ set dir [file normalize [file dirname $file]] #test-fail "Just testing" source -encoding utf-8 $file }} [join {@TEAISH_TEST_TCL@}] @else # TEAISH_TEST_TCL # No $TEAISH_TEST_TCL provided, so here's a default test which simply # loads the extension. puts {Extension @TEAISH_NAME@ @TEAISH_VERSION@ successfully loaded from @TEAISH_TESTER_TCL@} @endif |
Changes to autoconf/tea/teaish.tcl.
︙ | ︙ | |||
113 114 115 116 117 118 119 | } # # Gets called by tea-configure-core. Must perform any configuration # work needed for this extension. # proc teaish-configure {} { | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | } # # Gets called by tea-configure-core. Must perform any configuration # work needed for this extension. # proc teaish-configure {} { use teaish/feature teaish-src-add -dist -dir generic/tclsqlite3.c if {[proj-opt-was-provided override-sqlite-version]} { teaish-pkginfo-set -version [opt-val override-sqlite-version] proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version] } elseif {[proj-opt-was-provided with-system-sqlite] |
︙ | ︙ |
Changes to autosetup/proj.tcl.
︙ | ︙ | |||
56 57 58 59 60 61 62 | # updating global state via feature tests. # # # $proj__Config is an internal-use-only array for storing whatever generic # internal stuff we need stored. # | | | | | > > > > > > > > > > > > > > > > > > > < < | < < < < < | < < | < < | < | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | # updating global state via feature tests. # # # $proj__Config is an internal-use-only array for storing whatever generic # internal stuff we need stored. # array set ::proj__Config { self-tests 1 } # # List of dot-in files to filter in the final stages of # configuration. Some configuration steps may append to this. Each # one in this list which exists will trigger the generation of a # file with that same name, minus the ".in", in the build directory # (which differ from the source dir in out-of-tree builds). # # See: proj-dot-ins-append and proj-dot-ins-process # set ::proj__Config(dot-in-files) [list] set ::proj__Config(isatty) [isatty? stdout] # # @proj-warn msg # # Emits a warning message to stderr. All args are appended with a # space between each. # proc proj-warn {args} { show-notices puts stderr [join [list "WARNING: \[[proj-scope 1]\]: " {*}$args] " "] } # Internal impl of [proj-fatal] and [proj-error]. It must be called # using tailcall. proc proj__faterr {failMode argv} { show-notices set lvl 1 while {"-up" eq [lindex $argv 0]} { set argv [lassign $argv -] incr lvl } if {$failMode} { puts stderr [join [list "FATAL: \[[proj-scope $lvl]]: " {*}$argv]] exit 1 } else { error [join [list "\[[proj-scope $lvl]]:" {*}$argv]] } } # # @proj-fatal ?-up...? msg... # # Emits an error message to stderr and exits with non-0. All args are # appended with a space between each. # # The calling scope's name is used in the error message. To instead # use the name of a call higher up in the stack, use -up once for each # additional level. # proc proj-fatal {args} { tailcall proj__faterr 1 $args } # # @proj-error ?-up...? msg... # # Works like proj-fatal but uses [error] intead of [exit]. # proc proj-error {args} { tailcall proj__faterr 0 $args } set ::proj__Config(verbose-assert) [get-env proj-assert-verbose 0] # # @proj-assert script ?message? # # Kind of like a C assert: if uplevel of [list expr $script] is false, # a fatal error is triggered. The error message, by default, includes # the body of the failed assertion, but if $msg is set then that is # used instead. # proc proj-assert {script {msg ""}} { if {1 eq $::proj__Config(verbose-assert)} { msg-result [proj-bold "asserting: $script"] } if {![uplevel 1 [list expr $script]]} { if {"" eq $msg} { set msg $script } proj-fatal "Assertion failed in \[[proj-scope 1]\]: $msg" |
︙ | ︙ | |||
158 159 160 161 162 163 164 | return "\033\[1m${args}\033\[0m" } # # @proj-indented-notice ?-error? ?-notice? msg # # Takes a multi-line message and emits it with consistent indentation. | | > > | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | return "\033\[1m${args}\033\[0m" } # # @proj-indented-notice ?-error? ?-notice? msg # # Takes a multi-line message and emits it with consistent indentation. # It does not perform any line-wrapping of its own. Which output # routine it uses depends on its flags, defaulting to msg-result. # For -error and -notice it uses user-notice. # # If the -notice flag it used then it emits using [user-notice], which # means its rendering will (A) go to stderr and (B) be delayed until # the next time autosetup goes to output a message. # # If the -error flag is provided then it renders the message # immediately to stderr and then exits. # # If neither -notice nor -error are used, the message will be sent to # stdout without delay. # proc proj-indented-notice {args} { set fErr "" set outFunc "msg-result" while {[llength $args] > 1} { switch -exact -- [lindex $args 0] { -error { set args [lassign $args fErr] set outFunc "user-notice" } -notice { |
︙ | ︙ | |||
628 629 630 631 632 633 634 | proc proj-no-check-module-loader {} { define HAVE_LIBDL 0 define HAVE_LIBLTDL 0 define LDFLAGS_MODULE_LOADER "" } # | | | 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | proc proj-no-check-module-loader {} { define HAVE_LIBDL 0 define HAVE_LIBLTDL 0 define LDFLAGS_MODULE_LOADER "" } # # @proj-file-content ?-trim? filename # # Opens the given file, reads all of its content, and returns it. If # the first arg is -trim, the contents of the file named by the second # argument are trimmed before returning them. # proc proj-file-content {args} { set trim 0 |
︙ | ︙ | |||
697 698 699 700 701 702 703 | # # @proj-check-compile-commands ?configFlag? # # Checks the compiler for compile_commands.json support. If passed an # argument it is assumed to be the name of an autosetup boolean config # which controls whether to run/skip this check. # | > | | | < > | 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | # # @proj-check-compile-commands ?configFlag? # # Checks the compiler for compile_commands.json support. If passed an # argument it is assumed to be the name of an autosetup boolean config # which controls whether to run/skip this check. # # Returns 1 if supported, else 0, and defines HAVE_COMPILE_COMMANDS to # that value. Defines MAKE_COMPILATION_DB to "yes" if supported, "no" # if not. The use of MAKE_COMPILATION_DB is deprecated/discouraged: # HAVE_COMPILE_COMMANDS is preferred. # # ACHTUNG: this test has a long history of false positive results # because of compilers reacting differently to the -MJ flag. # proc proj-check-compile-commands {{configFlag {}}} { msg-checking "compile_commands.json support... " if {"" ne $configFlag && ![proj-opt-truthy $configFlag]} { msg-result "explicitly disabled" define HAVE_COMPILE_COMMANDS 0 define MAKE_COMPILATION_DB no return 0 } else { if {[cctest -lang c -cflags {/dev/null -MJ} -source {}]} { # This test reportedly incorrectly succeeds on one of # Martin G.'s older systems. drh also reports a false # positive on an unspecified older Mac system. |
︙ | ︙ | |||
783 784 785 786 787 788 789 | } } #puts "filenames=$filename" if {[file exists $fOut]} { catch { exec chmod u+w $fOut } } #puts "making template: $fIn ==> $fOut" | > > | > > > | 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 | } } #puts "filenames=$filename" if {[file exists $fOut]} { catch { exec chmod u+w $fOut } } #puts "making template: $fIn ==> $fOut" #define-push {top_srcdir} { #puts "--- $fIn $fOut top_srcdir=[get-define top_srcdir]" make-template $fIn $fOut #puts "--- $fIn $fOut top_srcdir=[get-define top_srcdir]" # make-template modifies top_srcdir #} if {$touch} { proj-touch $fOut } catch { exec chmod -w $fOut #file attributes -w $f; #jimtcl has no 'attributes' } |
︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 | # # An internal impl detail of proj-dump-defs-json. Requires a data # type specifier, as used by make-config-header, and a value. Returns # the formatted value or the value $::proj__Config(defs-skip) if the caller # should skip emitting that value. # | | | 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | # # An internal impl detail of proj-dump-defs-json. Requires a data # type specifier, as used by make-config-header, and a value. Returns # the formatted value or the value $::proj__Config(defs-skip) if the caller # should skip emitting that value. # set ::proj__Config(defs-skip) "-proj-defs-format_ sentinel" proc proj-defs-format_ {type value} { switch -exact -- $type { -bare { # Just output the value unchanged } -none { set value $::proj__Config(defs-skip) |
︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 | default { proj-fatal "Unknown type in proj-dump-defs-json: $type" } } return $value } # # This function works almost identically to autosetup's # make-config-header but emits its output in JSON form. It is not a # fully-functional JSON emitter, and will emit broken JSON for # complicated outputs, but should be sufficient for purposes of # emitting most configure vars (numbers and simple strings). # | > > | 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | default { proj-fatal "Unknown type in proj-dump-defs-json: $type" } } return $value } # # @proj-dump-defs-json outfile ...flags # # This function works almost identically to autosetup's # make-config-header but emits its output in JSON form. It is not a # fully-functional JSON emitter, and will emit broken JSON for # complicated outputs, but should be sufficient for purposes of # emitting most configure vars (numbers and simple strings). # |
︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 | } }; # proj-options-* # Internal cache for use via proj-cache-*. array set proj__Cache {} # | | > > < < | < | | | | > > > > > | | | | > > > > > | | 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 | } }; # proj-options-* # Internal cache for use via proj-cache-*. array set proj__Cache {} # # @proj-cache-key arg {addLevel 0} # # Helper to generate cache keys for [proj-cache-*]. # # $addLevel should almost always be 0. # # Returns a cache key for the given argument: # # integer: relative call stack levels to get the scope name of for # use as a key. [proj-scope [expr {1 + $arg + addLevel}]] is # then used to generate the key. i.e. the default of 0 uses the # calling scope's name as the key. # # Anything else: returned as-is # proc proj-cache-key {arg {addLevel 0}} { if {[string is integer -strict $arg]} { return [proj-scope [expr {$arg + $addLevel + 1}]] } return $arg } # # @proj-cache-set ?-key KEY? ?-level 0? value # # Sets a feature-check cache entry with the given key. # # See proj-cache-key for -key's and -level's semantics, noting that # this function adds one to -level for purposes of that call. proc proj-cache-set {args} { proj-parse-simple-flags args flags { -key => 0 -level => 0 } lassign $args val set key [proj-cache-key $flags(-key) [expr {1 + $flags(-level)}]] #puts "** fcheck set $key = $val" set ::proj__Cache($key) $val } # # @proj-cache-remove ?key? ?addLevel? # # Removes an entry from the proj-cache. proc proj-cache-remove {{key 0} {addLevel 0}} { set key [proj-cache-key $key [expr {1 + $addLevel}]] set rv "" if {[info exists ::proj__Cache($key)]} { set rv $::proj__Cache($key) unset ::proj__Cache($key) } return $rv; } # # @proj-cache-check ?-key KEY? ?-level LEVEL? tgtVarName # # Checks for a feature-check cache entry with the given key. # # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-key for $key's and $addLevel's semantics, noting that # this function adds one to $addLevel for purposes of that call. proc proj-cache-check {args} { proj-parse-simple-flags args flags { -key => 0 -level => 0 } lassign $args tgtVar upvar $tgtVar tgt set rc 0 set key [proj-cache-key $flags(-key) [expr {1 + $flags(-level)}]] #puts "** fcheck get key=$key" if {[info exists ::proj__Cache($key)]} { set tgt $::proj__Cache($key) incr rc } else { set tgt "" } |
︙ | ︙ | |||
2042 2043 2044 2045 2046 2047 2048 | } return "" } # # @proj-parse-simple-flags ... # | < < | 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 | } return "" } # # @proj-parse-simple-flags ... # # A helper to parse flags from proc argument lists. # # Expects a list of arguments to parse, an array name to store any # -flag values to, and a prototype object which declares the flags. # # The prototype must be a list in one of the following forms: # |
︙ | ︙ | |||
2093 2094 2095 2096 2097 2098 2099 | # Any argvName entries not described in $prototype are not treated as # flags. # # Returns the number of flags it processed in $argvName. # # Example: # | | | | | > | 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 | # Any argvName entries not described in $prototype are not treated as # flags. # # Returns the number of flags it processed in $argvName. # # Example: # # set args [list -foo -bar {blah} 8 9 10 -theEnd] # proj-parse-simple-flags args flags { # -foo 0 {expr 1} # -bar => 0 # -no-baz 2 {return 0} # } # # After that $flags would contain {-foo 1 -bar {blah} -no-baz 2} # and $args would be {8 9 10 -theEnd}. # # Potential TODOs: consider using lappend instead of set so that any # given flag can be used more than once. Or add a syntax to indicate # that multiples are allowed. Also consider searching the whole # argv list, rather than stopping at the first non-flag # proc proj-parse-simple-flags {argvName tgtArrayName prototype} { upvar $argvName argv upvar $tgtArrayName tgt array set dflt {} array set scripts {} array set consuming {} |
︙ | ︙ | |||
2183 2184 2185 2186 2187 2188 2189 | } set argv $rv return $rc } if {$::proj__Config(self-tests)} { apply {{} { | | | | | | | 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 | } set argv $rv return $rc } if {$::proj__Config(self-tests)} { apply {{} { #proj-warn "Test code for proj-cache" proj-assert {![proj-cache-check -key here check]} proj-assert {"here" eq [proj-cache-key here]} proj-assert {"" eq $check} proj-cache-set -key here thevalue proj-assert {[proj-cache-check -key here check]} proj-assert {"thevalue" eq $check} proj-assert {![proj-cache-check check]} #puts "*** key = ([proj-cache-key 0])" proj-assert {"" eq $check} proj-cache-set abc proj-assert {[proj-cache-check check]} proj-assert {"abc" eq $check} #parray ::proj__Cache; proj-assert {"" ne [proj-cache-remove]} proj-assert {![proj-cache-check check]} proj-assert {"" eq [proj-cache-remove]} proj-assert {"" eq $check} }} } |
Name change from autoconf/tea/autosetup/README.txt to autosetup/teaish/README.txt.
Name change from autoconf/tea/autosetup/core.tcl to autosetup/teaish/core.tcl.
︙ | ︙ | |||
32 33 34 35 36 37 38 | # version 0.1-beta # set to 1 to enable some internal debugging output debug-enabled 0 # | | | | | | > > > > > > > | > > > > > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # version 0.1-beta # set to 1 to enable some internal debugging output debug-enabled 0 # # 0 = don't yet have extension's pkgindex # 0x01 = found TEAISH_EXT_DIR/pkgIndex.tcl.in # 0x02 = found srcdir/pkgIndex.tcl.in # 0x10 = found TEAISH_EXT_DIR/pkgIndex.tcl (static file) # 0x20 = static-pkgIndex.tcl pragma: behave as if 0x10 # 0x100 = disabled by -tm.tcl.in # 0x200 = disabled by -tm.tcl # # Reminder: it's significant that the bottom 4 bits be # cases where teaish manages ./pkgIndex.tcl. # pkgindex-policy 0 # # The pkginit counterpart of pkgindex-policy: # # 0 = no pkginit # 0x01 = found default X.in: generate X from X.in # 0x10 = found static pkginit file X # 0x02 = user-provided X.in generates ./X. # 0x20 = user-provided static pkginit file X # # The 0x0f bits indicate that teaish is responsible for cleaning up # the (generated) pkginit file. # pkginit-policy 0 # # 0 = no tm.tcl # 0x01 = tm.tcl.in # 0x10 = static tm.tcl tm-policy 0 # # If 1+ then teaish__verbose will emit messages. # verbose 0 # # Mapping of pkginfo -flags to their TEAISH_xxx define (if any). # This must not be modified after initialization. # pkginfo-f2d { -name TEAISH_NAME -name.dist TEAISH_DIST_NAME -name.pkg TEAISH_PKGNAME -version TEAISH_VERSION -libDir TEAISH_LIBDIR_NAME -loadPrefix TEAISH_LOAD_PREFIX -vsatisfies TEAISH_VSATISFIES -pkgInit.tcl TEAISH_PKGINIT_TCL -pkgInit.tcl.in TEAISH_PKGINIT_TCL_IN -url TEAISH_URL -tm.tcl TEAISH_TM_TCL -tm.tcl.in TEAISH_TM_TCL_IN -options {} -pragmas {} } # # Queues for use with teaish-checks-queue and teaish-checks-run. # queued-checks-pre {} queued-checks-post {} # Whether or not "make dist" parts are enabled. They get enabled # when building from an extension's dir, disabled when building # elsewhere. dist-enabled 1 # Whether or not "make install" parts are enabled. By default # they are, but we have a single use case where they're # both unnecessary and unhelpful, so... install-enabled 1 # By default we enable compilation of a native extension but if the # extension has no native code or the user wants to take that over # via teaish.make.in or provide a script-only extension, we will # elide the default compilation rules if this is 0. dll-enabled 1 |
︙ | ︙ | |||
268 269 270 271 272 273 274 275 | t-v-c teaish-vsatisfies-check=1 => {Disable the configure-time "vsatisfies" check on the target tclsh.} }]; # main options. if {$gotExt} { proj-assert {"" ne [teaish-pkginfo-get -name]} | > > | | > | > > > > | | | | | | | > > > | | | | | | | | | | | | | | > > | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | t-v-c teaish-vsatisfies-check=1 => {Disable the configure-time "vsatisfies" check on the target tclsh.} }]; # main options. if {$gotExt} { # We found an extension. Source it... set ttcl $::teaish__Config(teaish.tcl) proj-assert {"" ne [teaish-pkginfo-get -name]} proj-assert {[file exists $ttcl]} \ "Expecting to have found teaish.(tcl|config) by now" if {[string match *.tcl $ttcl]} { uplevel 1 {source $::teaish__Config(teaish.tcl)} } else { teaish-pkginfo-set {*}[proj-file-content -trim $ttcl] } unset ttcl # Set up some default values if the extension did not set them. # This must happen _after_ it's sourced but before # teaish-configure is called. array set f2d $::teaish__Config(pkginfo-f2d) foreach {pflag key type val} { - TEAISH_CFLAGS -v "" - TEAISH_LDFLAGS -v "" - TEAISH_MAKEFILE -v "" - TEAISH_MAKEFILE_CODE -v "" - TEAISH_MAKEFILE_IN -v "" - TEAISH_PKGINDEX_TCL -v "" - TEAISH_PKGINDEX_TCL_IN -v "" - TEAISH_PKGINIT_TCL -v "" - TEAISH_PKGINIT_TCL_IN -v "" - TEAISH_PKGINIT_TCL_TAIL -v "" - TEAISH_TEST_TCL -v "" - TEAISH_TEST_TCL_IN -v "" -version - -v 0.0.0 -name.pkg - -e {set ::teaish__PkgInfo(-name)} -name.dist - -e {set ::teaish__PkgInfo(-name)} -libDir - -e { join [list \ $::teaish__PkgInfo(-name.pkg) \ $::teaish__PkgInfo(-version)] "" } -loadPrefix - -e { string totitle $::teaish__PkgInfo(-name.pkg) } -vsatisfies - -v {{Tcl 8.5-}} -pkgInit.tcl - -v "" -pkgInit.tcl.in - -v "" -url - -v "" -tm.tcl - -v "" -tm.tcl.in - -v "" } { set isPIFlag [expr {"-" ne $pflag}] if {$isPIFlag} { if {[info exists ::teaish__PkgInfo($pflag)]} { # Was already set - skip it. continue; } proj-assert {{-} eq $key} set key $f2d($pflag) } proj-assert {"" ne $key} set got [get-define $key "<nope>"] if {"<nope>" ne $got} { # Was already set - skip it. continue |
︙ | ︙ | |||
466 467 468 469 470 471 472 | # teaish.tcl teaish-configure } teaish-checks-run -post apply {{} { # Set up "vsatisfies" code for pkgIndex.tcl.in, | | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | # teaish.tcl teaish-configure } teaish-checks-run -post apply {{} { # Set up "vsatisfies" code for pkgIndex.tcl.in, # _teaish.tester.tcl.in, and for a configure-time check. We would # like to put this before [teaish-checks-run -pre] but it's # marginally conceivable that a client may need to dynamically # calculate the vsatisfies and set it via [teaish-configure]. set vs [get-define TEAISH_VSATISFIES ""] if {"" eq $vs} return set code {} set n 0 |
︙ | ︙ | |||
497 498 499 500 501 502 503 | set vputs "puts \[ $vsat \]" #puts "*** vputs = $vputs" scan [exec echo $vputs | $tclsh] %d vvcheck if {0 == $vvcheck} { proj-fatal -up $tclsh "check failed:" $vsat } } | < < | > > | > | | | > > | | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | set vputs "puts \[ $vsat \]" #puts "*** vputs = $vputs" scan [exec echo $vputs | $tclsh] %d vvcheck if {0 == $vvcheck} { proj-fatal -up $tclsh "check failed:" $vsat } } if {$::teaish__Config(vsatisfies-error)} { set vunsat \ [list error [list Package \ $::teaish__PkgInfo(-name) $::teaish__PkgInfo(-version) \ requires $pv]] } else { set vunsat return } lappend code \ [string trim [subst -nocommands \ {if { ![package vsatisfies [package provide $pkg] $vcheck] } {\n $vunsat\n}}]] }; # foreach pv define TEAISH_VSATISFIES_CODE [join $code "\n"] }}; # vsatisfies if {[proj-looks-like-windows]} { # Without this, linking of an extension will not work on Cygwin or # Msys2. |
︙ | ︙ | |||
527 528 529 530 531 532 533 | # # Ensure we have a pkgIndex.tcl and don't have a stale generated one # when rebuilding for different --with-tcl=... values. # if {!$::teaish__Config(pkgindex-policy)} { proj-error "Cannot determine which pkgIndex.tcl to use" } | > > > | | | | | | | | | | | | | > > > > > | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | # # Ensure we have a pkgIndex.tcl and don't have a stale generated one # when rebuilding for different --with-tcl=... values. # if {!$::teaish__Config(pkgindex-policy)} { proj-error "Cannot determine which pkgIndex.tcl to use" } if {0x300 & $::teaish__Config(pkgindex-policy)} { teaish__verbose 1 msg-result "pkgIndex disabled by -tm.tcl(.in)" } else { set tpi [proj-coalesce \ [get-define TEAISH_PKGINDEX_TCL_IN] \ [get-define TEAISH_PKGINDEX_TCL]] proj-assert {$tpi ne ""} \ "TEAISH_PKGINDEX_TCL should have been set up by now" teaish__verbose 1 msg-result "Using pkgIndex from $tpi" if {0x0f & $::teaish__Config(pkgindex-policy)} { # Don't leave stale pkgIndex.tcl laying around yet don't delete # or overwrite a user-managed static pkgIndex.tcl. file delete -force -- [get-define TEAISH_PKGINDEX_TCL] proj-dot-ins-append [get-define TEAISH_PKGINDEX_TCL_IN] } else { teaish-dist-add [file tail $tpi] } } }}; # $::teaish__Config(pkgindex-policy) # # Ensure we clean up TEAISH_PKGINIT_TCL if needed and @-process # TEAISH_PKGINIT_TCL_IN if needed. # if {0x0f & $::teaish__Config(pkginit-policy)} { file delete -force -- [get-define TEAISH_PKGINIT_TCL] proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN] } if {0x0f & $::teaish__Config(tm-policy)} { file delete -force -- [get-define TEAISH_TM_TCL] proj-dot-ins-append [get-define TEAISH_TM_TCL_IN] } apply {{} { # Queue up any remaining dot-in files set dotIns [list] foreach d { TEAISH_TESTER_TCL_IN TEAISH_TEST_TCL_IN |
︙ | ︙ | |||
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | [expr { $::teaish__Config(dist-enabled) && $::teaish__Config(dist-full-enabled) }] define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir) define TEAISH_ENABLE_DIST $::teaish__Config(dist-enabled) define TEAISH_ENABLE_DLL $::teaish__Config(dll-enabled) define TEAISH_TCL $::teaish__Config(teaish.tcl) define TEAISH_DIST_FILES [join $::teaish__Config(dist-files)] define TEAISH_EXT_DIR [join $::teaish__Config(extension-dir)] define TEAISH_EXT_SRC [join $::teaish__Config(extension-src)] proj-setup-autoreconfig TEAISH_AUTORECONFIG foreach f { TEAISH_CFLAGS TEAISH_LDFLAGS } { # Ensure that any of these lists are flattened define $f [join [get-define $f]] } | > < < < < | | < < < < < | | < < | > | | | | < < < < < | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 | [expr { $::teaish__Config(dist-enabled) && $::teaish__Config(dist-full-enabled) }] define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir) define TEAISH_ENABLE_DIST $::teaish__Config(dist-enabled) define TEAISH_ENABLE_INSTALL $::teaish__Config(install-enabled) define TEAISH_ENABLE_DLL $::teaish__Config(dll-enabled) define TEAISH_TCL $::teaish__Config(teaish.tcl) define TEAISH_DIST_FILES [join $::teaish__Config(dist-files)] define TEAISH_EXT_DIR [join $::teaish__Config(extension-dir)] define TEAISH_EXT_SRC [join $::teaish__Config(extension-src)] proj-setup-autoreconfig TEAISH_AUTORECONFIG foreach f { TEAISH_CFLAGS TEAISH_LDFLAGS } { # Ensure that any of these lists are flattened define $f [join [get-define $f]] } proj-remap-autoconf-dir-vars set tdefs [teaish__defines_to_list] define TEAISH__DEFINES_MAP $tdefs; # injected into _teaish.tester.tcl # # NO [define]s after this point! # proj-dot-ins-process -validate proj-if-opt-truthy teaish-dump-defines { proj-file-write config.defines.txt $tdefs } }; # teaish__configure_phase1 # # Run checks for required binaries. # proc teaish__check_common_bins {} { if {"" eq [proj-bin-define install]} { |
︙ | ︙ | |||
785 786 787 788 789 790 791 | proj-warn "Cannot find a usable tclsh (tried: $tryThese)" } } define TCLSH_CMD $withSh if {$use_tcl} { # Set up the TCLLIBDIR set tcllibdir [get-env TCLLIBDIR ""] | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | > > > | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | proj-warn "Cannot find a usable tclsh (tried: $tryThese)" } } define TCLSH_CMD $withSh if {$use_tcl} { # Set up the TCLLIBDIR set tcllibdir [get-env TCLLIBDIR ""] set extDirName [teaish-pkginfo-get -libDir] if {"" eq $tcllibdir} { # Attempt to extract TCLLIBDIR from TCL's $auto_path if {"" ne $withSh && [catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} { foreach i $result { if {[file isdirectory $i]} { set tcllibdir $i/$extDirName break } } } else { proj-error "Cannot determine TCLLIBDIR." } } define TCLLIBDIR $tcllibdir }; # find TCLLIBDIR set gotSh [file-isexec $withSh] set tmdir ""; # first tcl::tm::list entry if {$gotSh} { catch { set tmli [exec echo {puts [tcl::tm::list]} | $withSh] # Reminder: this list contains many names of dirs which do not # exist but are legitimate. If we rely only on an is-dir check, # we can end up not finding any of the many candidates. set firstDir "" foreach d $tmli { if {"" eq $firstDir && ![string match //*:* $d]} { # First non-VFS entry, e.g. not //zipfs: set firstDir $d } if {[file isdirectory $d]} { set tmdir $d break } } if {"" eq $tmdir} { set tmdir $firstDir } }; # find tcl::tm path } define TEAISH_TCL_TM_DIR $tmdir # Finally, let's wrap up... if {$gotSh} { teaish__verbose 1 msg-result "Using tclsh = $withSh" if {$cfg ne ""} { define HAVE_TCL 1 } else { proj-warn "Found tclsh but no tclConfig.sh." } if {"" eq $tmdir} { proj-warn "Did not find tcl::tm directory." } } show-notices # If TCL is not found: if it was explicitly requested then fail # fatally, else just emit a warning. If we can find the APIs needed # to generate a working JimTCL then that will suffice for build-time # TCL purposes (see: proc sqlite-determine-codegen-tcl). if {!$gotSh} { proj-error "Did not find tclsh" } elseif {"" eq $cfg} { proj-indented-notice -error { Cannot find a usable tclConfig.sh file. Use --with-tcl=DIR to specify a directory near which tclConfig.sh can be found, or --with-tclsh=/path/to/tclsh to allow the tclsh binary to locate its tclConfig.sh, with the caveat that a symlink to tclsh, or wrapper script around it, e.g. ~/bin/tclsh -> $HOME/tcl/9.0/bin/tclsh9.1, may not work because tclsh emits different library paths for the former than the latter. } } msg-result "Using Tcl [get-define TCL_VERSION] from [get-define TCL_PREFIX]." teaish__tcl_platform_quirks }; # teaish__check_tcl # |
︙ | ︙ | |||
862 863 864 865 866 867 868 | set ld "${pp}/${tail}" } define TCLLIBDIR $ld # [load foo.so], without a directory part, does not work via # automated tests on Haiku (but works when run # manually). Similarly, the post-install [package require ...] # test fails, presumably for a similar reason. We work around | | | 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 | set ld "${pp}/${tail}" } define TCLLIBDIR $ld # [load foo.so], without a directory part, does not work via # automated tests on Haiku (but works when run # manually). Similarly, the post-install [package require ...] # test fails, presumably for a similar reason. We work around # the former in _teaish.tester.tcl.in. We work around the # latter by amending the post-install check's ::auto_path (in # Makefile.in). This code MUST NOT contain any single-quotes. define TEAISH_POSTINST_PREREQUIRE \ [join [list set ::auto_path \ \[ linsert \$::auto_path 0 $ld \] \; \ ]] proj-indented-notice [subst -nocommands -nobackslashes { |
︙ | ︙ | |||
898 899 900 901 902 903 904 | # proc teaish__find_extension {} { proj-assert {!$::teaish__Config(install-mode)} teaish__verbose 1 msg-result "Looking for teaish extension..." # Helper for the foreach loop below. set checkTeaishTcl {{mustHave fid dir} { | < | | | | | | < < < < | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 | # proc teaish__find_extension {} { proj-assert {!$::teaish__Config(install-mode)} teaish__verbose 1 msg-result "Looking for teaish extension..." # Helper for the foreach loop below. set checkTeaishTcl {{mustHave fid dir} { set f [file join $dir $fid] if {[file readable $f]} { file-normalize $f } elseif {$mustHave} { proj-error "Missing required $dir/$fid" } }} # # We have to handle some flags manually because the extension must # be loaded before [options] is run (so that the extension can # inject its own options). # |
︙ | ︙ | |||
934 935 936 937 938 939 940 | # Ensure that $extD refers to a directory and contains a # teaish.tcl. regexp -- {--[^=]+=(.+)} $arg - extD set extD [file-normalize $extD] if {![file isdirectory $extD]} { proj-error "--teaish-extension-dir value is not a directory: $extD" } | > > | > | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | # Ensure that $extD refers to a directory and contains a # teaish.tcl. regexp -- {--[^=]+=(.+)} $arg - extD set extD [file-normalize $extD] if {![file isdirectory $extD]} { proj-error "--teaish-extension-dir value is not a directory: $extD" } set extT [apply $checkTeaishTcl 0 teaish.config $extD] if {"" eq $extT} { set extT [apply $checkTeaishTcl 1 teaish.tcl $extD] } set ::teaish__Config(extension-dir) $extD } --help { incr gotHelpArg lappend largv $arg } default { |
︙ | ︙ | |||
958 959 960 961 962 963 964 | # interfaces described by this framework. # # We use the first one we find in the builddir or srcdir. # if {"" eq $extT} { set flist [list] proj-assert {$dirExt eq ""} | | | 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 | # interfaces described by this framework. # # We use the first one we find in the builddir or srcdir. # if {"" eq $extT} { set flist [list] proj-assert {$dirExt eq ""} lappend flist $dirBld/teaish.tcl $dirBld/teaish.config $dirSrc/teaish.tcl if {![proj-first-file-found extT $flist]} { if {$gotHelpArg} { # Tell teaish-configure-core that the lack of extension is not # an error when --help or --teaish-install is used. return 0; } proj-indented-notice -error " |
︙ | ︙ | |||
1092 1093 1094 1095 1096 1097 1098 | } apply $addDist $ttt } else { define TEAISH_TEST_TCL "" define TEAISH_TEST_TCL_IN "" } | | | | | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 | } apply $addDist $ttt } else { define TEAISH_TEST_TCL "" define TEAISH_TEST_TCL_IN "" } # Look for _teaish.tester.tcl[.in] set flist [list $dirExt/_teaish.tester.tcl.in $dirSrc/_teaish.tester.tcl.in] if {[proj-first-file-found ttt $flist]} { # Generate teaish.test.tcl from $ttt set xt [file rootname [file tail $ttt]] file delete -force -- $xt; # ensure no stale copy is used define TEAISH_TESTER_TCL $xt define TEAISH_TESTER_TCL_IN $ttt if {[lindex $flist 0] eq $ttt} { apply $addDist $ttt } unset ttt xt } else { if {[file exists [set ttt [file join $dirSrc _teaish.tester.tcl.in]]]} { set xt [file rootname [file tail $ttt]] define TEAISH_TESTER_TCL $xt define TEAISH_TESTER_TCL_IN $ttt } else { define TEAISH_TESTER_TCL "" define TEAISH_TESTER_TCL_IN "" } |
︙ | ︙ | |||
1455 1456 1457 1458 1459 1460 1461 | -none {HAVE_CFLAG_* LDFLAGS_* SH_* TEAISH__* TEAISH_*_CODE} \ -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ -none * proj-touch $filename; # help avoid frequent unnecessary auto-reconfig } # | | | > | | | > > > > | | | | > | | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > < | > | > > | > > > > > > > > > > < | | > | > > | 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 | -none {HAVE_CFLAG_* LDFLAGS_* SH_* TEAISH__* TEAISH_*_CODE} \ -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ -none * proj-touch $filename; # help avoid frequent unnecessary auto-reconfig } # # @teaish-feature-cache-set $key value # # Sets a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. $key should # normally be 0. # proc teaish-feature-cache-set {key val} { proj-cache-set -key $key -level 1 $val } # # @teaish-feature-cache-check key tgtVarName # # Checks for a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. # # $key should also almost always be 0 but, due to a tclsh # incompatibility in 1 OS, it cannot have a default value unless it's # the second argument (but it should be the first one). # # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-check for $key's semantics. # proc teaish-feature-cache-check {key tgtVar} { upvar $tgtVar tgt proj-cache-check -key $key -level 1 tgt } # # @teaish-check-cached@ ?flags? msg script... # # A proxy for feature-test impls which handles caching of a feature # flag check on per-function basis, using the calling scope's name as # the cache key. # # It emits [msg-checking $msg]. If $msg is empty then it defaults to # the name of the caller's scope. The -nomsg flag suppresses the # message for non-cache-hit checks. At the end, it will [msg-result # "ok"] [msg-result "no"] unless -nostatus is used, in which case the # caller is responsible for emitting at least a newline when it's # done. The -msg-0 and -msg-1 flags can be used to change the ok/no # text. # # This function checks for a cache hit before running $script and # caching the result. If no hit is found then $script is run in the # calling scope and its result value is stored in the cache. This # routine will intercept a 'return' from $script. # # $script may be a command and its arguments, as opposed to a single # script block. # # Flags: # # -nostatus = do not emit "ok" or "no" at the end. This presumes # that either $script will emit at least one newline before # returning or the caller will account for it. Because of how this # function is typically used, -nostatus is not honored when the # response includes a cached result. # # -quiet = disable output from Autosetup's msg-checking and # msg-result for the duration of the $script check. Note that when # -quiet is in effect, Autosetup's user-notice can be used to queue # up output to appear after the check is done. Also note that # -quiet has no effect on _this_ function, only the $script part. # # -nomsg = do not emit $msg for initial check. Like -nostatus, this # flag is not honored when the response includes a cached result # because it would otherwise produce no output (which is confusing # in this context). This is useful when a check runs several other # verbose checks and they emit all the necessary info. # # -msg-0 and -msg-1 MSG = strings to show when the check has failed # resp. passed. Defaults are "no" and "ok". The 0 and 1 refer to the # result value from teaish-feature-cache-check. # # -key cachekey = set the cache context key. Only needs to be # explicit when using this function multiple times from a single # scope. See proj-cache-check and friends for details on the key # name. Its default is the name of the scope which calls this # function. # proc teaish-check-cached {args} { proj-parse-simple-flags args flags { -nostatus 0 {expr 1} -quiet 0 {expr 1} -key => 1 -nomsg 0 {expr 1} -msg-0 => no -msg-1 => ok } set args [lassign $args msg] set script [join $args] if {"" eq $msg} { set msg [proj-scope 1] } if {[teaish-feature-cache-check $flags(-key) check]} { #if {0 == $flags(-nomsg)} { msg-checking "${msg} ... (cached) " #} #if {!$flags(-nostatus)} { msg-result $flags(-msg-[expr {0 != ${check}}]) #} return $check } else { if {0 == $flags(-nomsg)} { msg-checking "${msg} ... " } if {$flags(-quiet)} { incr ::autosetup(msg-quiet) } set code [catch {uplevel 1 $script} rc xopt] if {$flags(-quiet)} { incr ::autosetup(msg-quiet) -1 } #puts "***** cached-check got code=$code rc=$rc" if {$code in {0 2}} { teaish-feature-cache-set 1 $rc if {!$flags(-nostatus)} { msg-result $flags(-msg-[expr {0 != ${rc}}]) } else { #show-notices; # causes a phantom newline because we're in a #msg-checking scope, so... if {[info exists ::autosetup(notices)]} { show-notices } } } else { #puts "**** code=$code rc=$rc xopt=$xopt" teaish-feature-cache-set 1 0 } #puts "**** code=$code rc=$rc" |
︙ | ︙ | |||
1547 1548 1549 1550 1551 1552 1553 | # # If $asList is true then the return value is in {$value} form. If # $asList is false it only performs the most basic of escaping and # the input must not contain any control characters. # proc teaish__quote_str {asList value} { if {$asList} { | | | | | | | | | | > | 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 | # # If $asList is true then the return value is in {$value} form. If # $asList is false it only performs the most basic of escaping and # the input must not contain any control characters. # proc teaish__quote_str {asList value} { if {$asList} { return "{${value}}" } return \"[string map [list \\ \\\\ \" \\\"] $value]\" } # # Internal helper for teaish__defines_to_list. Expects to be passed # a name and the variadic $args which are passed to # teaish__defines_to_list.. If it finds a pattern match for the # given $name in the various $args, it returns the type flag for that # $name, e.g. "-str" or "-bare", else returns an empty string. # proc teaish__defs_type {name spec} { foreach {type patterns} $spec { foreach pattern $patterns { if {[string match $pattern $name]} { return $type } } } return "" } # # An internal impl detail. Requires a data type specifier, as used by # Autosetup's [make-config-header], and a value. Returns the formatted # value or the value $::teaish__Config(defs-skip) if the caller should # skip emitting that value. # # In addition to -str, -auto, etc., as defined by make-config-header, # it supports: # # -list {...} will cause non-integer values to be quoted in {...} # instead of quotes. # # -autolist {...} works like -auto {...} except that it falls back to # -list {...} type instead of -str {...} style for non-integers. # # -jsarray {...} emits the output in something which, for # conservative inputs, will be a valid JSON array. It can only # handle relatively simple values with no control characters in # them. # set teaish__Config(defs-skip) "-teaish__defs_format sentinel" proc teaish__defs_format {type value} { switch -exact -- $type { -bare { # Just output the value unchanged } |
︙ | ︙ | |||
1615 1616 1617 1618 1619 1620 1621 | if {![string is integer -strict $value]} { set value [teaish__quote_str 1 $value] } } -list { set value [teaish__quote_str 1 $value] } | | > | > | > | | > > > > > > | | | | | | | < < | | | | | | | | 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 | if {![string is integer -strict $value]} { set value [teaish__quote_str 1 $value] } } -list { set value [teaish__quote_str 1 $value] } -jsarray { set ar {} foreach v $value { if {![string is integer -strict $v]} { set v [teaish__quote_str 0 $v] } if {$::teaish__Config(defs-skip) ne $v} { lappend ar $v } } set value [concat \[ [join $ar {, }] \]] } "" { # (Much later:) Why do we do this? set value $::teaish__Config(defs-skip) } default { proj-error \ "Unknown [proj-scope] -type ($type) called from" \ [proj-scope 1] } } return $value } # # Returns Tcl code in the form of code which evaluates to a list of # configure-time DEFINEs in the form {key val key2 val...}. It may # misbehave for values which are not numeric or simple strings. Some # defines are specifically filtered out of the result, either because # their irrelevant to teaish or because they may be arbitrarily large # (e.g. makefile content). # # The $args are explained in the docs for internal-use-only # [teaish__defs_format]. The default mode is -autolist. # proc teaish__defines_to_list {args} { set lines {} lappend lines "\{" set skipper $::teaish__Config(defs-skip) set args [list \ -none { TEAISH__* TEAISH_*_CODE AM_* AS_* } \ {*}$args \ -autolist *] foreach d [lsort [dict keys [all-defines]]] { set type [teaish__defs_type $d $args] set value [teaish__defs_format $type [get-define $d]] if {$skipper ne $value} { lappend lines "$d $value" } } lappend lines "\}" tailcall join $lines "\n" } # # teaish__pragma ...flags # # Offers a way to tweak how teaish's core behaves in some cases, in # particular those which require changing how the core looks for an |
︙ | ︙ | |||
1693 1694 1695 1696 1697 1698 1699 | # no-dll [L]: tells teaish to elide the DLL-building recipe # from the generated Makefile. # # no-vsatisfies-error [L]: tells teaish that failure to match the # -vsatisfies value should simply "return" instead of "error". # # no-tester [L]: disables automatic generation of teaish.test.tcl | | > > > | > > > > | 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 | # no-dll [L]: tells teaish to elide the DLL-building recipe # from the generated Makefile. # # no-vsatisfies-error [L]: tells teaish that failure to match the # -vsatisfies value should simply "return" instead of "error". # # no-tester [L]: disables automatic generation of teaish.test.tcl # even if a copy of _teaish.tester.tcl.in is found. # # no-full-dist [L]: changes the "make dist" rules to never include # a copy of teaish itself. By default it will include itself only # if the extension lives in the same directory as teaish. # # full-dist [L]: changes the "make dist" rules to always include # a copy of teaish itself. # # Emits a warning message for unknown arguments. # proc teaish__pragma {args} { foreach arg $args { switch -exact -- $arg { static-pkgIndex.tcl { if {$::teaish__Config(tm-policy)} { proj-fatal -up "Cannot use pragma $arg together with -tm.tcl or -tm.tcl.in." } set tpi [file join $::teaish__Config(extension-dir) pkgIndex.tcl] if {[file exists $tpi]} { define TEAISH_PKGINDEX_TCL_IN "" define TEAISH_PKGINDEX_TCL $tpi set ::teaish__Config(pkgindex-policy) 0x20 } else { proj-error "pragma $arg: found no package-local pkgIndex.tcl\[.in]" } } no-dist { set ::teaish__Config(dist-enabled) 0 } no-install { set ::teaish__Config(install-enabled) 0 } full-dist { set ::teaish__Config(dist-full-enabled) 1 } no-full-dist { set ::teaish__Config(dist-full-enabled) 0 |
︙ | ︙ | |||
1809 1810 1811 1812 1813 1814 1815 | # -options {...}: If provided, it must be a list compatible with # Autosetup's `options-add` function. These can also be set up via # `teaish-options`. # # -vsatisfies {{...} ...}: Expects a list-of-lists of conditions # for Tcl's `package vsatisfies` command: each list entry is a # sub-list of `{PkgName Condition...}`. Teaish inserts those | | | 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 | # -options {...}: If provided, it must be a list compatible with # Autosetup's `options-add` function. These can also be set up via # `teaish-options`. # # -vsatisfies {{...} ...}: Expects a list-of-lists of conditions # for Tcl's `package vsatisfies` command: each list entry is a # sub-list of `{PkgName Condition...}`. Teaish inserts those # checks via its default pkgIndex.tcl.in and _teaish.tester.tcl.in # templates to verify that the system's package dependencies meet # these requirements. The default value is `{{Tcl 8.5-}}` (recall # that it's a list-of-lists), as 8.5 is the minimum Tcl version # teaish will run on, but some extensions may require newer # versions or dependencies on other packages. As a special case, # if `-vsatisfies` is given a single token, e.g. `8.6-`, then it # is transformed into `{Tcl $thatToken}`, i.e. it checks the Tcl |
︙ | ︙ | |||
1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 | proj-parse-simple-flags args flags $flagDefs if {[llength $args]} { proj-error -up "Too many (or unknown) arguments to [proj-scope]: $args" } foreach {f d} $::teaish__Config(pkginfo-f2d) { if {$sentinel eq [set v $flags($f)]} continue switch -exact -- $f { -options { proj-assert {"" eq $d} options-add $v } -pragmas { | > > < | | | > > > > > > > > | > > > > > > > > > > > | | | < | | < > | > | > | > > > > > > > > > > > > > > > > > > > > > > | | | < > > > | 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 | proj-parse-simple-flags args flags $flagDefs if {[llength $args]} { proj-error -up "Too many (or unknown) arguments to [proj-scope]: $args" } foreach {f d} $::teaish__Config(pkginfo-f2d) { if {$sentinel eq [set v $flags($f)]} continue switch -exact -- $f { -options { proj-assert {"" eq $d} options-add $v } -pragmas { teaish__pragma {*}$v } -vsatisfies { if {1 == [llength $v] && 1 == [llength [lindex $v 0]]} { # Transform X to {Tcl $X} set v [list [join [list Tcl $v]]] } define $d $v } -pkgInit.tcl - -pkgInit.tcl.in { if {0x22 & $::teaish__Config(pkginit-policy)} { proj-fatal "Cannot use -pkgInit.tcl(.in) more than once." } set x [file join $::teaish__Config(extension-dir) $v] set tTail [file tail $v] if {"-pkgInit.tcl.in" eq $f} { # Generate pkginit file X from X.in set pI 0x02 set tIn $x set tOut [file rootname $tTail] set other -pkgInit.tcl } else { # Static pkginit file X set pI 0x20 set tIn "" set tOut $x set other -pkgInit.tcl.in } set ::teaish__Config(pkginit-policy) $pI set ::teaish__PkgInfo($other) {} define TEAISH_PKGINIT_TCL_IN $tIn define TEAISH_PKGINIT_TCL $tOut define TEAISH_PKGINIT_TCL_TAIL $tTail teaish-dist-add $v set v $x } -tm.tcl - -tm.tcl.in { if {0x30 & $::teaish__Config(pkgindex-policy)} { proj-fatal "Cannot use $f together with a pkgIndex.tcl." } elseif {$::teaish__Config(tm-policy)} { proj-fatal "Cannot use -tm.tcl(.in) more than once." } set x [file join $::teaish__Config(extension-dir) $v] if {"-tm.tcl.in" eq $f} { # Generate tm file X from X.in set pT 0x02 set pI 0x100 set tIn $x set tOut [file rootname [file tail $v]] set other -tm.tcl } else { # Static tm file X set pT 0x20 set pI 0x200 set tIn "" set tOut $x set other -tm.tcl.in } set ::teaish__Config(pkgindex-policy) $pI set ::teaish__Config(tm-policy) $pT set ::teaish__PkgInfo($other) {} define TEAISH_TM_TCL_IN $tIn define TEAISH_TM_TCL $tOut define TEAISH_PKGINDEX_TCL "" define TEAISH_PKGINDEX_TCL_IN "" define TEAISH_PKGINDEX_TCL_TAIL "" teaish-dist-add $v teaish__pragma no-dll set v $x } default { proj-assert {"" ne $d} define $d $v } } set ::teaish__PkgInfo($f) $v if {$f in {-name -version -libDir -loadPrefix}} { lappend recalc $f } |
︙ | ︙ | |||
2253 2254 2255 2256 2257 2258 2259 | # tx.src = \$(tx.dir)/generic/teaish.c # tx.LDFLAGS = # tx.CFLAGS = " proj-file-write teaish.make.in $content teaish__verbose 1 msg-result "Created teaish.make.in" | | | | | 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 | # tx.src = \$(tx.dir)/generic/teaish.c # tx.LDFLAGS = # tx.CFLAGS = " proj-file-write teaish.make.in $content teaish__verbose 1 msg-result "Created teaish.make.in" msg-result "Created new extension \[$dir\]." cd $cwd set ::teaish__Config(install-ext-dir) $dir } # # Internal helper for teaish__install # proc teaish__install_file {f destDir force} { set dest $destDir/[file tail $f] if {[file isdirectory $f]} { file mkdir $dest } elseif {!$force && [file exists $dest]} { array set st1 [file stat $f] array set st2 [file stat $dest] if {($st1(mtime) == $st2(mtime)) && ($st1(size) == $st2(size))} { if {[file tail $f] in { pkgIndex.tcl.in _teaish.tester.tcl.in }} { # Assume they're the same. In the scope of the "make dist" # rules, this happens legitimately when an extension with a # copy of teaish installed in the same dir assumes that the # pkgIndex.tcl.in and _teaish.tester.tcl.in belong to the # extension, whereas teaish believes they belong to teaish. # So we end up with dupes of those. return } } proj-error -up "Cowardly refusing to overwrite \[$dest\]." \ "Use --teaish-force to enable overwriting." |
︙ | ︙ | |||
2354 2355 2356 2357 2358 2359 2360 | teaish__verbose 2 msg-result "\t$f" teaish__install_file $f $destDir $force } } teaish__verbose 1 msg-result "Copying files to $dDest..." foreach f { auto.def configure Makefile.in pkgIndex.tcl.in | | | 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 | teaish__verbose 2 msg-result "\t$f" teaish__install_file $f $destDir $force } } teaish__verbose 1 msg-result "Copying files to $dDest..." foreach f { auto.def configure Makefile.in pkgIndex.tcl.in _teaish.tester.tcl.in } { teaish__verbose 2 msg-result "\t$f" teaish__install_file $dSrc/$f $dDest $force } set ::teaish__Config(install-self-dir) $dDest msg-result "Teaish $::teaish__Config(version) installed in \[$dDest\]." } |
Name change from autoconf/tea/autosetup/feature-tests.tcl to autosetup/teaish/feature.tcl.
︙ | ︙ |
Name change from autoconf/tea/autosetup/tester.tcl to autosetup/teaish/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 | ######################################################################## # 2025 April 5 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # * May you do good and not evil. # * May you find forgiveness for yourself and forgive others. # * May you share freely, never taking more than you give. # ######################################################################## # | | | | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ######################################################################## # 2025 April 5 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # * May you do good and not evil. # * May you find forgiveness for yourself and forgive others. # * May you share freely, never taking more than you give. # ######################################################################## # # Helper routines for running tests on teaish extensions # ######################################################################## # ----- @module teaish/tester.tcl ----- # # @section TEA-ish Testing APIs. # # Though these are part of the autosup dir hierarchy, they are not # intended to be run from autosetup code. Rather, they're for use # with/via teaish.tester.tcl and target canonical Tcl only, not JimTcl # (which the autosetup pieces do target). # # @test-current-scope ?lvl? # # Returns the name of the _calling_ proc from ($lvl + 1) levels up the # call stack (where the caller's level will be 1 up from _this_ # call). If $lvl would resolve to global scope "global scope" is |
︙ | ︙ | |||
67 68 69 70 71 72 73 | # proc test-fail {args} { #puts stderr "ERROR: \[[test-current-scope 1]]: $msg" #exit 1 error "FAIL: \[[test-current-scope 1]]: $args" } | > > > > | | < > | > > > > > > > | > > > > > > | > > > | < > > | | > | > > > | | | | > > > > > | > > > > | | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | # proc test-fail {args} { #puts stderr "ERROR: \[[test-current-scope 1]]: $msg" #exit 1 error "FAIL: \[[test-current-scope 1]]: $args" } array set ::test__Counters {} array set ::test__Config { verbose-assert 0 verbose-affirm 0 } # Internal impl for affirm and assert. # # $args = ?-v? script {msg-on-fail ""} proc test__affert {failMode args} { if {$failMode} { set what assert } else { set what affirm } set verbose $::test__Config(verbose-$what) if {"-v" eq [lindex $args 0]} { lassign $args - script msg if {1 == [llength $args]} { # If -v is the only arg, toggle default verbose mode set ::test__Config(verbose-$what) [expr {!$::test__Config(verbose-$what)}] return } incr verbose } else { lassign $args script msg } incr ::test__Counters($what) if {![uplevel 1 [concat expr [list $script]]]} { if {"" eq $msg} { set msg $script } set txt [join [list $what # $::test__Counters($what) "failed:" $msg]] if {$failMode} { puts stderr $txt exit 1 } else { error $txt } } elseif {$verbose} { puts stderr [join [list $what # $::test__Counters($what) "passed:" $script]] } } # # @affirm ?-v? script ?msg? # # Works like a conventional assert method does, but reports failures # using [error] instead of [exit]. If -v is used, it reports passing # assertions to stderr. $script is evaluated in the caller's scope as # an argument to [expr]. # proc affirm {args} { tailcall test__affert 0 {*}$args } # # @assert ?-v? script ?msg? # # Works like [affirm] but exits on error. # proc assert {args} { tailcall test__affert 1 {*}$args } # # @test-assert testId script ?msg? # # Works like [assert] but emits $testId to stdout first. # proc test-assert {testId script {msg ""}} { puts "test $testId" tailcall test__affert 1 $script $msg } # # @test-expect testId script result # # Runs $script in the calling scope and compares its result to # $result, minus any leading or trailing whitespace. If they differ, # it triggers an [assert]. # proc test-expect {testId script result} { puts "test $testId" set x [string trim [uplevel 1 $script]] set result [string trim $result] tailcall test__affert 0 [list $x eq $result] \ "\nEXPECTED: <<$result>>\nGOT: <<$x>>" } # # @test-catch cmd ?...args? # # Runs [cmd ...args], repressing any exception except to possibly log |
︙ | ︙ |
Changes to ext/misc/fileio.c.
︙ | ︙ | |||
94 95 96 97 98 99 100 | # include <sys/time.h> #else # include "windows.h" # include <io.h> # include <direct.h> # include "test_windirent.h" # define dirent DIRENT | < < < < | | | < | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | # include <sys/time.h> #else # include "windows.h" # include <io.h> # include <direct.h> # include "test_windirent.h" # define dirent DIRENT # define stat _stat # define chmod(path,mode) fileio_chmod(path,mode) # define mkdir(path,mode) fileio_mkdir(path) #endif #include <time.h> #include <errno.h> /* When used as part of the CLI, the sqlite3_stdio.h module will have ** been included before this one. In that case use the sqlite3_stdio.h ** #defines. If not, create our own for fopen(). |
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #define FSDIR_COLUMN_NAME 0 /* Name of the file */ #define FSDIR_COLUMN_MODE 1 /* Access mode */ #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ #define FSDIR_COLUMN_DATA 3 /* File content */ #define FSDIR_COLUMN_PATH 4 /* Path to top of search */ #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ /* ** Set the result stored by context ctx to a blob containing the ** contents of file zName. Or, leave the result unchanged (NULL) ** if the file does not exist or is unreadable. ** ** If the file exceeds the SQLite blob size limit, through an | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | #define FSDIR_COLUMN_NAME 0 /* Name of the file */ #define FSDIR_COLUMN_MODE 1 /* Access mode */ #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ #define FSDIR_COLUMN_DATA 3 /* File content */ #define FSDIR_COLUMN_PATH 4 /* Path to top of search */ #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ /* ** UTF8 chmod() function for Windows */ #if defined(_WIN32) || defined(WIN32) static int fileio_chmod(const char *zPath, int pmode){ sqlite3_int64 sz = strlen(zPath); wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; if( b1==0 ) return -1; sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); b1[sz] = 0; rc = _wchmod(b1, pmode); sqlite3_free(b1); return rc; } #endif /* ** UTF8 mkdir() function for Windows */ #if defined(_WIN32) || defined(WIN32) static int fileio_mkdir(const char *zPath){ sqlite3_int64 sz = strlen(zPath); wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; if( b1==0 ) return -1; sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); b1[sz] = 0; rc = _wmkdir(b1); sqlite3_free(b1); return rc; } #endif /* ** Set the result stored by context ctx to a blob containing the ** contents of file zName. Or, leave the result unchanged (NULL) ** if the file does not exist or is unreadable. ** ** If the file exceeds the SQLite blob size limit, through an |
︙ | ︙ | |||
287 288 289 290 291 292 293 | ** other systems, this function simply calls stat(). */ static int fileStat( const char *zPath, struct stat *pStatBuf ){ #if defined(_WIN32) | > > | > > > > | < < | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | ** other systems, this function simply calls stat(). */ static int fileStat( const char *zPath, struct stat *pStatBuf ){ #if defined(_WIN32) sqlite3_int64 sz = strlen(zPath); wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; if( b1==0 ) return 1; sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); b1[sz] = 0; rc = _wstat(b1, pStatBuf); if( rc==0 ) statTimesToUtc(zPath, pStatBuf); return rc; #else return stat(zPath, pStatBuf); #endif } /* ** This function is used in place of lstat(). On Windows, special handling ** is required in order for the included time to be returned as UTC. On all ** other systems, this function simply calls lstat(). */ static int fileLinkStat( const char *zPath, struct stat *pStatBuf ){ #if defined(_WIN32) return fileStat(zPath, pStatBuf); #else return lstat(zPath, pStatBuf); #endif } /* ** Argument zFile is the name of a file that will be created and/or written |
︙ | ︙ |
Changes to ext/misc/vfstrace.c.
︙ | ︙ | |||
577 578 579 580 581 582 583 | case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break; case SQLITE_FCNTL_PRAGMA: { const char *const* a = (const char*const*)pArg; if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){ const u8 *zArg = (const u8*)a[2]; | | | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 | case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break; case SQLITE_FCNTL_PRAGMA: { const char *const* a = (const char*const*)pArg; if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){ const u8 *zArg = (const u8*)a[2]; if( zArg[0]>='0' && zArg[0]<='9' ){ pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0); }else{ static const struct { const char *z; unsigned int m; } aKw[] = { { "all", 0xffffffff }, |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
2844 2845 2846 2847 2848 2849 2850 | }else{ rc = fixBoundingBox(pRtree, pNode); } } return rc; } | | | 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 | }else{ rc = fixBoundingBox(pRtree, pNode); } } return rc; } /* ** Insert cell pCell into node pNode. Node pNode is the head of a ** subtree iHeight high (leaf nodes have iHeight==0). */ static int rtreeInsertCell( Rtree *pRtree, RtreeNode *pNode, |
︙ | ︙ |
Changes to ext/session/changeset.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | /* ** Show a usage message on stderr then quit. */ static void usage(const char *argv0){ fprintf(stderr, "Usage: %s FILENAME COMMAND ...\n", argv0); fprintf(stderr, "COMMANDs:\n" | | > > > > > > | | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /* ** Show a usage message on stderr then quit. */ static void usage(const char *argv0){ fprintf(stderr, "Usage: %s FILENAME COMMAND ...\n", argv0); fprintf(stderr, "COMMANDs:\n" " apply DB [OPTIONS] Apply the changeset to database file DB. OPTIONS:\n" " -n|--dryrun Test run. Don't apply changes\n" " --enablefk Enable FOREIGN KEY support\n" " --nosavepoint \\\n" " --invert \\___ Flags passed into\n" " --ignorenoop / changeset_apply_v2()\n" " --fknoaction /\n" " concat FILE2 OUT Concatenate FILENAME and FILE2 into OUT\n" " dump Show the complete content of the changeset\n" " invert OUT Write an inverted changeset into file OUT\n" " sql Give a pseudo-SQL rendering of the changeset\n" ); exit(1); } /* ** Read the content of a disk file into an in-memory buffer */ |
︙ | ︙ | |||
157 158 159 160 161 162 163 | } switch( op ){ case SQLITE_UPDATE: zOp = "UPDATE of"; break; case SQLITE_INSERT: zOp = "INSERT into"; break; case SQLITE_DELETE: zOp = "DELETE from"; break; } printf("%s conflict on %s table %s with primary key", zType, zOp, zTab); | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | } switch( op ){ case SQLITE_UPDATE: zOp = "UPDATE of"; break; case SQLITE_INSERT: zOp = "INSERT into"; break; case SQLITE_DELETE: zOp = "DELETE from"; break; } printf("%s conflict on %s table %s with primary key", zType, zOp, zTab); for(i=0; i<nCol && abPK; i++){ sqlite3_value *pVal; if( abPK[i]==0 ) continue; printf("%s", zSep); if( op==SQLITE_INSERT ){ sqlite3changeset_new(pIter, i, &pVal); }else{ sqlite3changeset_old(pIter, i, &pVal); |
︙ | ︙ | |||
184 185 186 187 188 189 190 | readFile(argv[1], &sz, &pBuf); /* changeset FILENAME apply DB ** Apply the changeset in FILENAME to the database file DB */ if( strcmp(argv[2],"apply")==0 ){ sqlite3 *db; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | | > > > > > > > | > | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | readFile(argv[1], &sz, &pBuf); /* changeset FILENAME apply DB ** Apply the changeset in FILENAME to the database file DB */ if( strcmp(argv[2],"apply")==0 ){ sqlite3 *db; int bDryRun = 0; int bEnableFK = 0; const char *zDb = 0; int i; int applyFlags = 0; for(i=3; i<argc; i++){ const char *zArg = argv[i]; if( zArg[0]=='-' ){ if( zArg[1]=='-' && zArg[2]!=0 ) zArg++; if( strcmp(zArg, "-n")==0 || strcmp(zArg,"-dryrun")==0 ){ bDryRun = 1; continue; } if( strcmp(zArg, "-nosavepoint")==0 ){ applyFlags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT; continue; } if( strcmp(zArg, "-invert")==0 ){ applyFlags |= SQLITE_CHANGESETAPPLY_INVERT; continue; } if( strcmp(zArg, "-ignorenoop")==0 ){ applyFlags |= SQLITE_CHANGESETAPPLY_IGNORENOOP; continue; } if( strcmp(zArg, "-fknoaction")==0 ){ applyFlags |= SQLITE_CHANGESETAPPLY_FKNOACTION; continue; } if( strcmp(zArg, "-enablefk")==0 ){ bEnableFK = 1; continue; } fprintf(stderr, "unknown option: \"%s\"\n", argv[i]); exit(1); }else if( zDb ){ fprintf(stderr, "unknown argument: \"%s\"\n", argv[i]); exit(1); }else{ zDb = zArg; } } rc = sqlite3_open(zDb, &db); if( rc!=SQLITE_OK ){ fprintf(stderr, "unable to open database file \"%s\": %s\n", zDb, sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } if( bEnableFK ){ sqlite3_exec(db, "PRAGMA foreign_keys=1;", 0, 0, 0); } sqlite3_exec(db, "BEGIN", 0, 0, 0); nConflict = 0; if( applyFlags ){ rc = sqlite3changeset_apply_v2(db, sz, pBuf, 0, conflictCallback, 0, 0, 0, applyFlags); }else{ rc = sqlite3changeset_apply(db, sz, pBuf, 0, conflictCallback, 0); } if( rc ){ fprintf(stderr, "sqlite3changeset_apply() returned %d\n", rc); } if( nConflict || bDryRun ){ fprintf(stderr, "%d conflicts - no changes applied\n", nConflict); sqlite3_exec(db, "ROLLBACK", 0, 0, 0); }else if( rc ){ fprintf(stderr, "sqlite3changeset_apply() returns %d " "- no changes applied\n", rc); sqlite3_exec(db, "ROLLBACK", 0, 0, 0); }else{ |
︙ | ︙ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
579 580 581 582 583 584 585 | /* ** CAPI3REF: Flags for sqlite3changeset_start_v2 ** ** The following flags may passed via the 4th parameter to ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ** | | | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 | /* ** CAPI3REF: Flags for sqlite3changeset_start_v2 ** ** The following flags may passed via the 4th parameter to ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ** ** <dt>SQLITE_CHANGESETSTART_INVERT <dd> ** Invert the changeset while iterating through it. This is equivalent to ** inverting a changeset using sqlite3changeset_invert() before applying it. ** It is an error to specify this flag with a patchset. */ #define SQLITE_CHANGESETSTART_INVERT 0x0002 |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
1219 1220 1221 1222 1223 1224 1225 | if( zQuot==0 ){ return SQLITE_NOMEM; }else{ nQuot = sqlite3Strlen30(zQuot)-1; } assert( nQuot>=nNew && nSql>=0 && nNew>=0 ); | | | | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 | if( zQuot==0 ){ return SQLITE_NOMEM; }else{ nQuot = sqlite3Strlen30(zQuot)-1; } assert( nQuot>=nNew && nSql>=0 && nNew>=0 ); zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1); }else{ assert( nSql>0 ); zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3); if( zOut ){ zBuf1 = &zOut[nSql*2+1]; zBuf2 = &zOut[nSql*4+2]; } } /* At this point pRename->pList contains a list of RenameToken objects |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
1572 1573 1574 1575 1576 1577 1578 | else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9)); } #endif while( z[0]!=0 && z[0]!=' ' ) z++; while( z[0]==' ' ) z++; } | < < < < < < < < < < | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 | else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9)); } #endif while( z[0]!=0 && z[0]!=' ' ) z++; while( z[0]==' ' ) z++; } } } /* ** This callback is invoked once for each index when reading the ** sqlite_stat1 table. ** |
︙ | ︙ |
Changes to src/json.c.
︙ | ︙ | |||
1752 1753 1754 1755 1756 1757 1758 | break; }else if( c=='\\' ){ c = z[++j]; if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' || (c=='u' && jsonIs4Hex(&z[j+1])) ){ if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ; | | > > > > > | 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 | break; }else if( c=='\\' ){ c = z[++j]; if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' || (c=='u' && jsonIs4Hex(&z[j+1])) ){ if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ; }else if( c=='\'' || c=='v' || c=='\n' #ifdef SQLITE_BUG_COMPATIBLE_20250510 || (c=='0') /* Legacy bug compatible */ #else || (c=='0' && !sqlite3Isdigit(z[j+1])) /* Correct implementation */ #endif || (0xe2==(u8)c && 0x80==(u8)z[j+1] && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2])) || (c=='x' && jsonIs2Hex(&z[j+1])) ){ opcode = JSONB_TEXT5; pParse->hasNonstd = 1; }else if( c=='\r' ){ if( z[j+1]=='\n' ) j++; |
︙ | ︙ | |||
2139 2140 2141 2142 2143 2144 2145 | || pParse->aBlob[i+2]!=0 || pParse->aBlob[i+3]!=0 || pParse->aBlob[i+4]!=0 ){ *pSz = 0; return 0; } | | | 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 | || pParse->aBlob[i+2]!=0 || pParse->aBlob[i+3]!=0 || pParse->aBlob[i+4]!=0 ){ *pSz = 0; return 0; } sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) + (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8]; n = 9; } if( (i64)i+sz+n > pParse->nBlob && (i64)i+sz+n > pParse->nBlob-pParse->delta ){ *pSz = 0; |
︙ | ︙ | |||
2720 2721 2722 2723 2724 2725 2726 | } case 'b': { *piOut = '\b'; return 2; } case 'f': { *piOut = '\f'; return 2; } case 'n': { *piOut = '\n'; return 2; } case 'r': { *piOut = '\r'; return 2; } case 't': { *piOut = '\t'; return 2; } case 'v': { *piOut = '\v'; return 2; } | | > > > > > > > > > > > > > > | 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 | } case 'b': { *piOut = '\b'; return 2; } case 'f': { *piOut = '\f'; return 2; } case 'n': { *piOut = '\n'; return 2; } case 'r': { *piOut = '\r'; return 2; } case 't': { *piOut = '\t'; return 2; } case 'v': { *piOut = '\v'; return 2; } case '0': { /* JSON5 requires that the \0 escape not be followed by a digit. ** But SQLite did not enforce this restriction in versions 3.42.0 ** through 3.49.2. That was a bug. But some applications might have ** come to depend on that bug. Use the SQLITE_BUG_COMPATIBLE_20250510 ** option to restore the old buggy behavior. */ #ifdef SQLITE_BUG_COMPATIBLE_20250510 /* Legacy bug-compatible behavior */ *piOut = 0; #else /* Correct behavior */ *piOut = (n>2 && sqlite3Isdigit(z[2])) ? JSON_INVALID_CHAR : 0; #endif return 2; } case '\'': case '"': case '/': case '\\':{ *piOut = z[1]; return 2; } case 'x': { if( n<4 ){ *piOut = JSON_INVALID_CHAR; |
︙ | ︙ |
Changes to src/loadext.c.
︙ | ︙ | |||
513 514 515 516 517 518 519 | sqlite3_value_encoding, /* Version 3.41.0 and later */ sqlite3_is_interrupted, /* Version 3.43.0 and later */ sqlite3_stmt_explain, /* Version 3.44.0 and later */ sqlite3_get_clientdata, | | > > | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | sqlite3_value_encoding, /* Version 3.41.0 and later */ sqlite3_is_interrupted, /* Version 3.43.0 and later */ sqlite3_stmt_explain, /* Version 3.44.0 and later */ sqlite3_get_clientdata, sqlite3_set_clientdata, /* Version 3.50.0 and later */ sqlite3_setlk_timeout }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
4204 4205 4206 4207 4208 4209 4210 | if( osIsNT() ){ #ifdef __CYGWIN__ int nChar; LPWSTR zWideFilename; if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) && winIsDirSep(zFilename[2])) ){ | | | | | 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 | if( osIsNT() ){ #ifdef __CYGWIN__ int nChar; LPWSTR zWideFilename; if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) && winIsDirSep(zFilename[2])) ){ i64 nByte; int convertflag = CCP_POSIX_TO_WIN_W; if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; nByte = (i64)osCygwin_conv_path(convertflag, zFilename, 0, 0); if( nByte>0 ){ zConverted = sqlite3MallocZero(12+(u64)nByte); if ( zConverted==0 ){ return zConverted; } zWideFilename = zConverted; /* Filenames should be prefixed, except when converted * full path already starts with "\\?\". */ if( osCygwin_conv_path(convertflag, zFilename, |
︙ | ︙ | |||
5093 5094 5095 5096 5097 5098 5099 | /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** ** This division contains the implementation of methods on the ** sqlite3_vfs object. */ | < < < < < < < < < < < < < < < < < < < < < | 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 | /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** ** This division contains the implementation of methods on the ** sqlite3_vfs object. */ /* ** This function returns non-zero if the specified UTF-8 string buffer ** ends with a directory separator character or one was successfully ** added to it. */ static int winMakeEndInDirSep(int nBuf, char *zBuf){ if( zBuf ){ |
︙ | ︙ | |||
5253 5254 5255 5256 5257 5258 5259 | } if( winIsDir(zConverted) ){ sqlite3_snprintf(nMax, zBuf, "%s", zDir); sqlite3_free(zConverted); break; } sqlite3_free(zConverted); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 | } if( winIsDir(zConverted) ){ sqlite3_snprintf(nMax, zBuf, "%s", zDir); sqlite3_free(zConverted); break; } sqlite3_free(zConverted); } } } #endif #if !SQLITE_OS_WINRT && defined(_WIN32) else if( osIsNT() ){ |
︙ | ︙ | |||
6187 6188 6189 6190 6191 6192 6193 | sqlite3_free(zDel); winSimplifyName(zFull); return rc; } } #endif /* __CYGWIN__ */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 | sqlite3_free(zDel); winSimplifyName(zFull); return rc; } } #endif /* __CYGWIN__ */ #if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) SimulateIOError( return SQLITE_ERROR ); /* WinCE has no concept of a relative pathname, or so I am told. */ /* WinRT has no way to convert a relative path to an absolute one. */ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ /* |
︙ | ︙ | |||
6360 6361 6362 6363 6364 6365 6366 | #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. */ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; | < < < < < < < < < < < < < < < < < < < | 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 | #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. */ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; void *zConverted = winConvertFromUtf8Filename(zFilename); UNUSED_PARAMETER(pVfs); if( zConverted==0 ){ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); return 0; } if( osIsNT() ){ #if SQLITE_OS_WINRT h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | } if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ /* Clearly non-deterministic functions like random(), but also ** date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index or generated column. Curiously, they can be used ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all | | < > | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | } if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ /* Clearly non-deterministic functions like random(), but also ** date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index or generated column. Curiously, they can be used ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all ** allow this. */ sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr); }else{ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */ pExpr->op2 = pNC->ncFlags & NC_SelfRef; } if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 ){ /* Internal-use-only functions are disallowed unless the ** SQL is being compiled using sqlite3NestedParse() or ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be ** used to activate internal functions for testing purposes */ no_such_func = 1; pDef = 0; }else if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 && !IN_RENAME_OBJECT ){ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL); sqlite3ExprFunctionUsable(pParse, pExpr, pDef); } } if( 0==IN_RENAME_OBJECT ){ #ifndef SQLITE_OMIT_WINDOWFUNC assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 | pAggInfo->directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } if( iOrderByCol ){ Expr *pX = p->pEList->a[iOrderByCol-1].pExpr; Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX); if( ALWAYS(pBase!=0) && pBase->op!=TK_AGG_COLUMN && pBase->op!=TK_REGISTER ){ sqlite3ExprToRegister(pX, iAMem+j); } } | > > > > | 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 | pAggInfo->directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } if( iOrderByCol ){ Expr *pX = p->pEList->a[iOrderByCol-1].pExpr; Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX); while( ALWAYS(pBase!=0) && pBase->op==TK_IF_NULL_ROW ){ pX = pBase->pLeft; pBase = sqlite3ExprSkipCollateAndLikely(pX); } if( ALWAYS(pBase!=0) && pBase->op!=TK_AGG_COLUMN && pBase->op!=TK_REGISTER ){ sqlite3ExprToRegister(pX, iAMem+j); } } |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
5336 5337 5338 5339 5340 5341 5342 | #ifndef SQLITE_SHELL_FIDDLE ".www Display output of the next command in web browser", " --plain Show results as text/plain, not as HTML", #endif }; /* | | < | | > > > > > > > > > > > > > > > > | | > | | | | < < < | | > | < | < < < < | < | < | | < < < < < < < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < | 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 | #ifndef SQLITE_SHELL_FIDDLE ".www Display output of the next command in web browser", " --plain Show results as text/plain, not as HTML", #endif }; /* ** Output help text for commands that match zPattern. ** ** * If zPattern is NULL, then show all documented commands, but ** only give a one-line summary of each. ** ** * If zPattern is "-a" or "-all" or "--all" then show all help text ** for all commands except undocumented commands. ** ** * If zPattern is "0" then show all help for undocumented commands. ** Undocumented commands begin with "," instead of "." in the azHelp[] ** array. ** ** * If zPattern is a prefix for one or more documented commands, then ** show help for those commands. If only a single command matches the ** prefix, show the full text of the help. If multiple commands match, ** Only show just the first line of each. ** ** * Otherwise, show the complete text of any documented command for which ** zPattern is a LIKE match for any text within that command help ** text. ** ** Return the number commands that match zPattern. */ static int showHelp(FILE *out, const char *zPattern){ int i = 0; int j = 0; int n = 0; char *zPat; if( zPattern==0 ){ /* Show just the first line for all help topics */ zPattern = "[a-z]"; }else if( cli_strcmp(zPattern,"-a")==0 || cli_strcmp(zPattern,"-all")==0 || cli_strcmp(zPattern,"--all")==0 ){ /* Show everything except undocumented commands */ zPattern = "."; }else if( cli_strcmp(zPattern,"0")==0 ){ /* Show complete help text of undocumented commands */ int show = 0; for(i=0; i<ArraySize(azHelp); i++){ if( azHelp[i][0]=='.' ){ show = 0; }else if( azHelp[i][0]==',' ){ show = 1; sqlite3_fprintf(out, ".%s\n", &azHelp[i][1]); n++; }else if( show ){ sqlite3_fprintf(out, "%s\n", azHelp[i]); } } return n; } /* Seek documented commands for which zPattern is an exact prefix */ zPat = sqlite3_mprintf(".%s*", zPattern); shell_check_oom(zPat); for(i=0; i<ArraySize(azHelp); i++){ if( sqlite3_strglob(zPat, azHelp[i])==0 ){ sqlite3_fprintf(out, "%s\n", azHelp[i]); j = i+1; n++; } } sqlite3_free(zPat); if( n ){ if( n==1 ){ /* when zPattern is a prefix of exactly one command, then include ** the details of that command, which should begin at offset j */ while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){ sqlite3_fprintf(out, "%s\n", azHelp[j]); j++; } } return n; } /* Look for documented commands that contain zPattern anywhere. ** Show complete text of all documented commands that match. */ zPat = sqlite3_mprintf("%%%s%%", zPattern); shell_check_oom(zPat); for(i=0; i<ArraySize(azHelp); i++){ if( azHelp[i][0]==',' ){ while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i; continue; } if( azHelp[i][0]=='.' ) j = i; if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){ sqlite3_fprintf(out, "%s\n", azHelp[j]); while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){ j++; sqlite3_fprintf(out, "%s\n", azHelp[j]); } i = j; n++; } } sqlite3_free(zPat); return n; } /* Forward reference */ static int process_input(ShellState *p); /* |
︙ | ︙ |
Changes to src/sqlite3ext.h.
︙ | ︙ | |||
362 363 364 365 366 367 368 369 370 371 372 373 374 375 | /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*); /* Version 3.43.0 and later */ int (*stmt_explain)(sqlite3_stmt*,int); /* Version 3.44.0 and later */ void *(*get_clientdata)(sqlite3*,const char*); int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( | > > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*); /* Version 3.43.0 and later */ int (*stmt_explain)(sqlite3_stmt*,int); /* Version 3.44.0 and later */ void *(*get_clientdata)(sqlite3*,const char*); int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); /* Version 3.50.0 and later */ int (*setlk_timeout)(sqlite3*,int,int); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( |
︙ | ︙ | |||
695 696 697 698 699 700 701 702 703 704 705 706 707 708 | /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted /* Version 3.43.0 and later */ #define sqlite3_stmt_explain sqlite3_api->stmt_explain /* Version 3.44.0 and later */ #define sqlite3_get_clientdata sqlite3_api->get_clientdata #define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted /* Version 3.43.0 and later */ #define sqlite3_stmt_explain sqlite3_api->stmt_explain /* Version 3.44.0 and later */ #define sqlite3_get_clientdata sqlite3_api->get_clientdata #define sqlite3_set_clientdata sqlite3_api->set_clientdata /* Version 3.50.0 and later */ #define sqlite3_setlk_timeout sqlite3_api->setlk_timeout #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2806 2807 2808 2809 2810 2811 2812 | unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ | < | 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 | unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ unsigned bHasExpr:1; /* Index contains an expression, either a literal ** expression, or a reference to a VIRTUAL column */ #ifdef SQLITE_ENABLE_STAT4 |
︙ | ︙ |
Changes to src/test_windirent.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | } } /* ** Implementation of the POSIX opendir() function using the MSVCRT. */ LPDIR opendir( | | | > > | | > > > > > > > > > > > > > > > > | | | | | < | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | } } /* ** Implementation of the POSIX opendir() function using the MSVCRT. */ LPDIR opendir( const char *dirname /* Directory name, UTF8 encoding */ ){ struct _wfinddata_t data; LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); wchar_t *b1; sqlite3_int64 sz; if( dirp==NULL ) return NULL; memset(dirp, 0, sizeof(DIR)); /* TODO: Remove this if Unix-style root paths are not used. */ if( sqlite3_stricmp(dirname, "/")==0 ){ dirname = windirent_getenv("SystemDrive"); } memset(&data, 0, sizeof(data)); sz = strlen(dirname); b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); if( b1==0 ){ closedir(dirp); return NULL; } sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz); b1[sz++] = '\\'; b1[sz++] = '*'; b1[sz] = 0; if( sz+1>(sqlite3_int64)namesize ){ closedir(dirp); sqlite3_free(b1); return NULL; } memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); sqlite3_free(b1); dirp->d_handle = _wfindfirst(data.name, &data); if( dirp->d_handle==BAD_INTPTR_T ){ closedir(dirp); return NULL; } /* TODO: Remove this block to allow hidden and/or system files. */ if( is_filtered(data) ){ next: memset(&data, 0, sizeof(data)); if( _wfindnext(dirp->d_handle, &data)==-1 ){ closedir(dirp); return NULL; } /* TODO: Remove this block to allow hidden and/or system files. */ if( is_filtered(data) ) goto next; } dirp->d_first.d_attributes = data.attrib; WideCharToMultiByte(CP_UTF8, 0, data.name, -1, dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0); return dirp; } /* ** Implementation of the POSIX readdir() function using the MSVCRT. */ LPDIRENT readdir( LPDIR dirp ){ struct _wfinddata_t data; if( dirp==NULL ) return NULL; if( dirp->d_first.d_ino==0 ){ dirp->d_first.d_ino++; dirp->d_next.d_ino++; return &dirp->d_first; } next: memset(&data, 0, sizeof(data)); if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL; /* TODO: Remove this block to allow hidden and/or system files. */ if( is_filtered(data) ) goto next; dirp->d_next.d_ino++; dirp->d_next.d_attributes = data.attrib; WideCharToMultiByte(CP_UTF8, 0, data.name, -1, dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0); return &dirp->d_next; } /* ** Implementation of the POSIX closedir() function using the MSVCRT. */ INT closedir( LPDIR dirp ){ INT result = 0; |
︙ | ︙ |
Changes to src/test_windirent.h.
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #ifndef NAME_MAX # ifdef FILENAME_MAX # define NAME_MAX (FILENAME_MAX) # else # define NAME_MAX (260) # endif #endif /* ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". */ #ifndef NULL_INTPTR_T | > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #ifndef NAME_MAX # ifdef FILENAME_MAX # define NAME_MAX (FILENAME_MAX) # else # define NAME_MAX (260) # endif # define DIRENT_NAME_MAX (NAME_MAX) #endif /* ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". */ #ifndef NULL_INTPTR_T |
︙ | ︙ | |||
127 128 129 130 131 132 133 | DIRENT d_next; /* DIRENT constructed based on "_findnext". */ }; #endif /* ** Provide a macro, for use by the implementation, to determine if a ** particular directory entry should be skipped over when searching for | | < | < | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | DIRENT d_next; /* DIRENT constructed based on "_findnext". */ }; #endif /* ** Provide a macro, for use by the implementation, to determine if a ** particular directory entry should be skipped over when searching for ** the next directory entry that should be returned by the readdir(). */ #ifndef is_filtered # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) #endif /* ** Provide the function prototype for the POSIX compatible getenv() ** function. This function is not thread-safe. */ extern const char *windirent_getenv(const char *name); /* ** Finally, we can provide the function prototypes for the opendir(), ** readdir(), and closedir() POSIX functions. */ extern LPDIR opendir(const char *dirname); extern LPDIRENT readdir(LPDIR dirp); extern INT closedir(LPDIR dirp); #endif /* defined(WIN32) && defined(_MSC_VER) */ |
Changes to src/utf.c.
︙ | ︙ | |||
104 105 106 107 108 109 110 | *zOut++ = (u8)(c&0x00FF); \ } \ } /* ** Write a single UTF8 character whose value is v into the ** buffer starting at zOut. zOut must be sized to hold at | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | *zOut++ = (u8)(c&0x00FF); \ } \ } /* ** Write a single UTF8 character whose value is v into the ** buffer starting at zOut. zOut must be sized to hold at ** least four bytes. Return the number of bytes needed ** to encode the new character. */ int sqlite3AppendOneUtf8Character(char *zOut, u32 v){ if( v<0x00080 ){ zOut[0] = (u8)(v & 0xff); return 1; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
3155 3156 3157 3158 3159 3160 3161 | assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } | | | < < < | 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 | assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } if( pProbe->bUnordered ){ opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); } assert( pNew->u.btree.nEq<pProbe->nColumn ); assert( pNew->u.btree.nEq<pProbe->nKeyCol || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY ); saved_nEq = pNew->u.btree.nEq; |
︙ | ︙ | |||
4096 4097 4098 4099 4100 4101 4102 | " according to whereIsCoveringIndex()\n", pProbe->zName)); } } }else if( m==0 && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700)) ){ WHERETRACE(0x200, | | | 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 | " according to whereIsCoveringIndex()\n", pProbe->zName)); } } }else if( m==0 && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700)) ){ WHERETRACE(0x200, ("-> %s is a covering index according to bitmasks\n", pProbe->zName, m==0 ? "is" : "is not")); pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; } } /* Full scan via index */ if( b |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
596 597 598 599 600 601 602 | for(i=iEq; i<pLoop->nLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ int iField; assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 ); iField = pLoop->aLTerm[i]->u.x.iField - 1; if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */ pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); | | | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | for(i=iEq; i<pLoop->nLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ int iField; assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 ); iField = pLoop->aLTerm[i]->u.x.iField - 1; if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */ pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); pOrigRhs->a[iField].pExpr = 0; if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1; if( pOrigLhs ){ assert( pOrigLhs->a[iField].pExpr!=0 ); pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr); pOrigLhs->a[iField].pExpr = 0; } } |
︙ | ︙ |
Changes to test/date4.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | # ifcapable {!datetime} { finish_test return } if {$tcl_platform(os)=="Linux"} { | > > > > > | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # ifcapable {!datetime} { finish_test return } if {$tcl_platform(os)=="Linux"} { if {"" eq [strftime {%P} 1]} { # This is probably musl libc, which does not support # %k, %l, %P set FMT {%d,%e,%F,%H,%I,%j,%m,%M,%u,%w,%W,%Y,%%,%p,%U,%V,%G,%g} } else { set FMT {%d,%e,%F,%H,%k,%I,%l,%j,%m,%M,%u,%w,%W,%Y,%%,%P,%p,%U,%V,%G,%g} } } else { set FMT {%d,%e,%F,%H,%I,%j,%p,%R,%u,%w,%W,%%} } for {set i 0} {$i<=24858} {incr i} { set TS [expr {$i*86390}] do_execsql_test date4-$i { SELECT strftime($::FMT,$::TS,'unixepoch'); |
︙ | ︙ |
Changes to tool/mkautoconfamal.sh.
︙ | ︙ | |||
59 60 61 62 63 64 65 | cp $TOP/tool/Replace.cs $TMPSPACE cp $TOP/VERSION $TMPSPACE cp $TOP/main.mk $TMPSPACE cd $TMPSPACE # Clean up emacs-generated backup files from the target | | < < < < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | cp $TOP/tool/Replace.cs $TMPSPACE cp $TOP/VERSION $TMPSPACE cp $TOP/main.mk $TMPSPACE cd $TMPSPACE # Clean up emacs-generated backup files from the target rm -f ./autosetup/*~ ./autosetup/teaish/*~ rm -f ./*~ #if true; then # Clean up *~ files (emacs-generated backups). # This bit is only for use during development of # the autoconf bundle. # find . -name '*~' -exec rm \{} \; #fi mkdir -p tea/generic cat <<EOF > tea/generic/tclsqlite3.c #ifdef USE_SYSTEM_SQLITE # include <sqlite3.h> #else # include "sqlite3.c" #endif |
︙ | ︙ |
Changes to tool/mkctimec.tcl.
︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC SQLITE_ALLOW_ROWID_IN_VIEW SQLITE_ALLOW_URI_AUTHORITY SQLITE_BUG_COMPATIBLE_20160819 SQLITE_CASE_SENSITIVE_LIKE SQLITE_CHECK_PAGES SQLITE_COVERAGE_TEST SQLITE_DEBUG SQLITE_DEFAULT_AUTOMATIC_INDEX SQLITE_DEFAULT_AUTOVACUUM SQLITE_DEFAULT_CKPTFULLFSYNC | > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC SQLITE_ALLOW_ROWID_IN_VIEW SQLITE_ALLOW_URI_AUTHORITY SQLITE_BUG_COMPATIBLE_20160819 SQLITE_BUG_COMPATIBLE_20250510 SQLITE_CASE_SENSITIVE_LIKE SQLITE_CHECK_PAGES SQLITE_COVERAGE_TEST SQLITE_DEBUG SQLITE_DEFAULT_AUTOMATIC_INDEX SQLITE_DEFAULT_AUTOVACUUM SQLITE_DEFAULT_CKPTFULLFSYNC |
︙ | ︙ |
Changes to tool/sqlite3_rsync.c.
︙ | ︙ | |||
597 598 599 600 601 602 603 | # elif defined(sparc) || defined(__ppc__) # define Hash_BYTEORDER 4321 # else # define Hash_BYTEORDER 0 # endif #endif | < < | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | # elif defined(sparc) || defined(__ppc__) # define Hash_BYTEORDER 4321 # else # define Hash_BYTEORDER 0 # endif #endif /* ** State structure for a Hash hash in progress */ typedef struct HashContext HashContext; struct HashContext { union { u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ |
︙ | ︙ |
Changes to tool/src-verify.c.
︙ | ︙ | |||
748 749 750 751 752 753 754 | if( n<=0 ) break; SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose(in); SHA1Final(zResult, &ctx); DigestToBase16(zResult, zCksum, 20); } | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | if( n<=0 ) break; SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose(in); SHA1Final(zResult, &ctx); DigestToBase16(zResult, zCksum, 20); } /* ** Decode a fossilized string in-place. */ void defossilize(char *z){ int i, j, cc; char *zSlash = strchr(z, '\\'); if( zSlash==0 ) return; |
︙ | ︙ |
Changes to tool/warnings.sh.
1 2 3 4 5 6 7 8 9 10 11 12 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # if uname | grep -i openbsd ; then # Use these for testing on OpenBSD: WARNING_OPTS=-Wall WARNING_ANDROID_OPTS=-Wall else # Use these for testing on Linux and Mac OSX: | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # if uname | grep -i openbsd ; then # Use these for testing on OpenBSD: WARNING_OPTS=-Wall WARNING_ANDROID_OPTS=-Wall else # Use these for testing on Linux and Mac OSX: WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -Wno-array-bounds" gccvers=`gcc -v 2>&1 | grep '^gcc version'` if test "$gccvers" '<' 'gcc version 6' then WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra" else WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra -Wimplicit-fallthrough=0" fi fi rm -f sqlite3.c make sqlite3.c echo '**** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***' echo '****' $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 \ sqlite3.c if test x`uname` = 'xLinux'; then echo '**** Android configuration ******************************' echo '****' $WARNING_ANDROID_OPTS gcc -c \ -DSQLITE_HAVE_ISNAN \ -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \ -DSQLITE_THREADSAFE=2 \ -DSQLITE_TEMP_STORE=3 \ -DSQLITE_POWERSAFE_OVERWRITE=1 \ -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
︙ | ︙ | |||
48 49 50 51 52 53 54 | -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \ -DSQLITE_ENABLE_ICU \ -DUSE_PREAD64 \ $WARNING_ANDROID_OPTS \ -Os sqlite3.c shell.c fi | | | | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \ -DSQLITE_ENABLE_ICU \ -DUSE_PREAD64 \ $WARNING_ANDROID_OPTS \ -Os sqlite3.c shell.c fi echo '**** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******' echo '****' $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ sqlite3.c echo '**** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******' echo '****' $WARNING_OPTS gcc -O3 -c $WARNING_OPTS -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 \ sqlite3.c |