upload all files

This commit is contained in:
2026-01-07 21:21:28 +08:00
parent 09d49d22c9
commit 8f53d867a2
220 changed files with 419218 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
The *.tcl files in this directory are part of the SQLite's "autoconf"
bundle which are specific to the TEA(-ish) build. During the tarball
generation process, they are copied into <TOP>/autoconf/autosetup/teaish
(which itself is created as part of that process).

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,214 @@
########################################################################
# 2025 April 7
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# * May you do good and not evil.
# * May you find forgiveness for yourself and forgive others.
# * May you share freely, never taking more than you give.
#
########################################################################
# ----- @module feature-tests.tcl -----
# @section TEA-ish collection of feature tests.
#
# Functions in this file with a prefix of teaish__ are
# private/internal APIs. Those with a prefix of teaish- are
# public APIs.
# @teaish-check-libz
#
# Checks for zlib.h and the function deflate in libz. If found,
# prepends -lz to the extension's ldflags and returns 1, else returns
# 0. It also defines LDFLAGS_LIBZ to the libs flag.
#
proc teaish-check-libz {} {
teaish-check-cached "Checking for libz" {
set rc 0
if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} {
teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
undefine lib_deflate
incr rc
}
expr $rc
}
}
# @teaish-check-librt ?funclist?
#
# Checks whether -lrt is needed for any of the given functions. If
# so, appends -lrt via [teaish-ldflags-prepend] and returns 1, else
# returns 0. It also defines LDFLAGS_LIBRT to the libs flag or an
# empty string.
#
# Some systems (ex: SunOS) require -lrt in order to use nanosleep.
#
proc teaish-check-librt {{funclist {fdatasync nanosleep}}} {
teaish-check-cached -nostatus "Checking whether ($funclist) need librt" {
define LDFLAGS_LIBRT ""
foreach func $funclist {
if {[msg-quiet proj-check-function-in-lib $func rt]} {
set ldrt [get-define lib_${func}]
undefine lib_${func}
if {"" ne $ldrt} {
teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
msg-result $ldrt
return 1
} else {
msg-result "no lib needed"
return 1
}
}
}
msg-result "not found"
return 0
}
}
# @teaish-check-stdint
#
# A thin proxy for [cc-with] which checks for <stdint.h> and the
# various fixed-size int types it declares. It defines HAVE_STDINT_T
# to 0 or 1 and (if it's 1) defines HAVE_XYZ_T for each XYZ int type
# to 0 or 1, depending on whether its available.
proc teaish-check-stdint {} {
teaish-check-cached "Checking for stdint.h" {
msg-quiet cc-with {-includes stdint.h} \
{cc-check-types int8_t int16_t int32_t int64_t intptr_t \
uint8_t uint16_t uint32_t uint64_t uintptr_t}
}
}
# @teaish-is-mingw
#
# Returns 1 if building for mingw, else 0.
proc teaish-is-mingw {} {
return [expr {
[string match *mingw* [get-define host]] &&
![file exists /dev/null]
}]
}
# @teaish-check-libdl
#
# Checks for whether dlopen() can be found and whether it requires
# -ldl for linking. If found, returns 1, defines LDFLAGS_DLOPEN to the
# linker flags (if any), and passes those flags to
# teaish-ldflags-prepend. It unconditionally defines HAVE_DLOPEN to 0
# or 1 (the its return result value).
proc teaish-check-dlopen {} {
teaish-check-cached -nostatus "Checking for dlopen()" {
set rc 0
set lfl ""
if {[cc-with {-includes dlfcn.h} {
cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
msg-result "-ldl not needed"
incr rc
} elseif {[cc-check-includes dlfcn.h]} {
incr rc
if {[cc-check-function-in-lib dlopen dl]} {
set lfl [get-define lib_dlopen]
undefine lib_dlopen
msg-result " dlopen() needs $lfl"
} else {
msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
}
} else {
msg-result "not found"
}
teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
define HAVE_DLOPEN $rc
}
}
#
# @teaish-check-libmath
#
# Handles the --enable-math flag. Returns 1 if found, else 0.
# If found, it prepends -lm (if needed) to the linker flags.
proc teaish-check-libmath {} {
teaish-check-cached "Checking for libc math library" {
set lfl ""
set rc 0
if {[msg-quiet proj-check-function-in-lib ceil m]} {
incr rc
set lfl [get-define lib_ceil]
undefine lib_ceil
teaish-ldflags-prepend $lfl
msg-checking "$lfl "
}
define LDFLAGS_LIBMATH $lfl
expr $rc
}
}
# @teaish-import-features ?-flags? feature-names...
#
# For each $name in feature-names... it invokes:
#
# use teaish/feature/$name
#
# to load TEAISH_AUTOSETUP_DIR/feature/$name.tcl
#
# By default, if a proc named teaish-check-${name}-options is defined
# after sourcing a file, it is called and its result is passed to
# proj-append-options. This can be suppressed with the -no-options
# flag.
#
# Flags:
#
# -no-options: disables the automatic running of
# teaish-check-NAME-options,
#
# -run: if the function teaish-check-NAME exists after importing
# then it is called. This flag must not be used when calling this
# function from teaish-options. This trumps both -pre and -post.
#
# -pre: if the function teaish-check-NAME exists after importing
# then it is passed to [teaish-checks-queue -pre].
#
# -post: works like -pre but instead uses[teaish-checks-queue -post].
proc teaish-import-features {args} {
set pk ""
set doOpt 1
proj-parse-simple-flags args flags {
-no-options 0 {set doOpt 0}
-run 0 {expr 1}
-pre 0 {set pk -pre}
-post 0 {set pk -post}
}
#
# TODO: never import the same module more than once. The "use"
# command is smart enough to not do that but we would need to
# remember whether or not any teaish-check-${arg}* procs have been
# called before, and skip them.
#
if {$flags(-run) && "" ne $pk} {
proj-error "Cannot use both -run and $pk" \
" (called from [proj-scope 1])"
}
foreach arg $args {
uplevel "use teaish/feature/$arg"
if {$doOpt} {
set n "teaish-check-${arg}-options"
if {[llength [info proc $n]] > 0} {
if {"" ne [set x [$n]]} {
options-add $x
}
}
}
if {$flags(-run)} {
set n "teaish-check-${arg}"
if {[llength [info proc $n]] > 0} {
uplevel 1 $n
}
} elseif {"" ne $pk} {
set n "teaish-check-${arg}"
if {[llength [info proc $n]] > 0} {
teaish-checks-queue {*}$pk $n
}
}
}
}

View File

@@ -0,0 +1,293 @@
########################################################################
# 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
# returned and if it would be negative then a string indicating such
# is returned (as opposed to throwing an error).
#
proc test-current-scope {{lvl 0}} {
#uplevel [expr {$lvl + 1}] {lindex [info level 0] 0}
set ilvl [info level]
set offset [expr {$ilvl - $lvl - 1}]
if { $offset < 0} {
return "invalid scope ($offset)"
} elseif { $offset == 0} {
return "global scope"
} else {
return [lindex [info level $offset] 0]
}
}
# @test-msg
#
# Emits all arugments to stdout.
#
proc test-msg {args} {
puts "$args"
}
# @test-warn
#
# Emits all arugments to stderr.
#
proc test-warn {args} {
puts stderr "WARNING: $args"
}
#
# @test-error msg
#
# Triggers a test-failed error with a string describing the calling
# scope and the provided message.
#
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 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
}
#
# @assert-matches ?-e? pattern ?-e? rhs ?msg?
#
# Equivalent to assert {[string match $pattern $rhs]} except that
# if either of those are prefixed with an -e flag, they are eval'd
# and their results are used.
#
proc assert-matches {args} {
set evalLhs 0
set evalRhs 0
if {"-e" eq [lindex $args 0]} {
incr evalLhs
set args [lassign $args -]
}
set args [lassign $args pattern]
if {"-e" eq [lindex $args 0]} {
incr evalRhs
set args [lassign $args -]
}
set args [lassign $args rhs msg]
if {$evalLhs} {
set pattern [uplevel 1 $pattern]
}
if {$evalRhs} {
set rhs [uplevel 1 $rhs]
}
#puts "***pattern=$pattern\n***rhs=$rhs"
tailcall test__affert 1 \
[join [list \[ string match [list $pattern] [list $rhs] \]]] $msg
# why does this not work? [list \[ string match [list $pattern] [list $rhs] \]] $msg
# "\[string match [list $pattern] [list $rhs]\]"
}
#
# @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
# the failure. Returns 1 if it caught anything, 0 if it didn't.
#
proc test-catch {cmd args} {
if {[catch {
uplevel 1 $cmd {*}$args
} rc xopts]} {
puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc"
return 1
}
return 0
}
#
# @test-catch-matching pattern (script|cmd args...)
#
# Works like test-catch, but it expects its argument(s) to to throw an
# error matching the given string (checked with [string match]). If
# they do not throw, or the error does not match $pattern, this
# function throws, else it returns 1.
#
# If there is no second argument, the $cmd is assumed to be a script,
# and will be eval'd in the caller's scope.
#
# TODO: add -glob and -regex flags to control matching flavor.
#
proc test-catch-matching {pattern cmd args} {
if {[catch {
#puts "**** catch-matching cmd=$cmd args=$args"
if {0 == [llength $args]} {
uplevel 1 $cmd {*}$args
} else {
$cmd {*}$args
}
} rc xopts]} {
if {[string match $pattern $rc]} {
return 1
} else {
error "[test-current-scope] exception does not match {$pattern}: {$rc}"
}
}
error "[test-current-scope] expecting to see an error matching {$pattern}"
}
if {![array exists ::teaish__BuildFlags]} {
array set ::teaish__BuildFlags {}
}
#
# @teaish-build-flag3 flag tgtVar ?dflt?
#
# If the current build has the configure-time flag named $flag set
# then tgtVar is assigned its value and 1 is returned, else tgtVal is
# assigned $dflt and 0 is returned.
#
# Caveat #1: only valid when called in the context of teaish's default
# "make test" recipe, e.g. from teaish.test.tcl. It is not valid from
# a teaish.tcl configure script because (A) the state it relies on
# doesn't fully exist at that point and (B) that level of the API has
# more direct access to the build state. This function requires that
# an external script have populated its internal state, which is
# normally handled via teaish.tester.tcl.in.
#
# Caveat #2: defines in the style of HAVE_FEATURENAME with a value of
# 0 are, by long-standing configure script conventions, treated as
# _undefined_ here.
#
proc teaish-build-flag3 {flag tgtVar {dflt ""}} {
upvar $tgtVar tgt
if {[info exists ::teaish__BuildFlags($flag)]} {
set tgt $::teaish__BuildFlags($flag)
return 1;
} elseif {0==[array size ::teaish__BuildFlags]} {
test-warn \
"\[[test-current-scope]] was called from " \
"[test-current-scope 1] without the build flags imported."
}
set tgt $dflt
return 0
}
#
# @teaish-build-flag flag ?dflt?
#
# Convenience form of teaish-build-flag3 which returns the
# configure-time-defined value of $flag or "" if it's not defined (or
# if it's an empty string).
#
proc teaish-build-flag {flag {dflt ""}} {
set tgt ""
teaish-build-flag3 $flag tgt $dflt
return $tgt
}