aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/codeql.yml4
-rw-r--r--Makefile.in2
-rw-r--r--README.namespaces7
-rw-r--r--Tcl_shipped.html50
-rw-r--r--auto.def8
-rw-r--r--autosetup/README.autosetup2
-rwxr-xr-xautosetup/autosetup10
-rwxr-xr-xautosetup/autosetup-config.guess121
-rwxr-xr-xautosetup/autosetup-config.sub953
-rwxr-xr-xautosetup/autosetup-find-tclsh2
-rw-r--r--autosetup/cc.tcl126
-rw-r--r--autosetup/jimsh0.c732
-rw-r--r--autosetup/system.tcl170
-rw-r--r--initjimsh.tcl10
-rw-r--r--jim-aio.c250
-rw-r--r--jim-file.c12
-rw-r--r--jim-namespace.c2
-rw-r--r--jim-package.c18
-rw-r--r--jim-win32compat.h11
-rw-r--r--jim.c61
-rw-r--r--jim_tcl.txt367
-rw-r--r--jimiocompat.c2
-rw-r--r--jimiocompat.h23
-rw-r--r--jimsh.c8
-rw-r--r--linenoise.c186
-rwxr-xr-xmake-bootstrap-jim10
-rwxr-xr-xmake-index10
-rw-r--r--regtest.tcl7
-rw-r--r--tclcompat.tcl5
-rw-r--r--tcltest.tcl5
-rw-r--r--tests/breakcont.test (renamed from tests/breakcontinue.test)0
-rw-r--r--tests/event.test23
-rw-r--r--tests/expr.test7
-rw-r--r--tests/forget-test.tcl3
-rw-r--r--tests/io.test26
-rw-r--r--tests/jimsh.test30
-rw-r--r--tests/package.test12
-rw-r--r--tests/try.test9
38 files changed, 2164 insertions, 1120 deletions
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 8164922..f55e344 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -27,7 +27,7 @@ jobs:
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
- runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }}
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
@@ -114,7 +114,7 @@ jobs:
- name: Upload CodeQL results as an artifact
if: success() || failure()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}
diff --git a/Makefile.in b/Makefile.in
index 29c226b..2fba1c0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -118,7 +118,9 @@ install: all @TCL_EXTS@ install-exec install-docs
@srcdir@/jim-subcmd.h @srcdir@/jim-win32compat.h $(DESTDIR)@includedir@
$(INSTALL_DATA) jim-config.h $(DESTDIR)@includedir@
$(INSTALL_DATA_DIR) $(DESTDIR)@bindir@
+@if BUILD_JIM_EXT
$(INSTALL_DATA) build-jim-ext $(DESTDIR)@bindir@
+@endif
$(INSTALL_DATA_DIR) $(DESTDIR)@libdir@/pkgconfig
$(INSTALL_DATA) jimtcl.pc $(DESTDIR)@libdir@/pkgconfig
diff --git a/README.namespaces b/README.namespaces
index ef50769..9d23a74 100644
--- a/README.namespaces
+++ b/README.namespaces
@@ -115,6 +115,7 @@ Currently, the following namespace commands are supported.
* delete - deletes all variables and commands with the namespace prefix
* which - implemented
* upvar - implemented
+* ensemble - 'create' command is implemented
namespace children, exists, path
--------------------------------
@@ -126,12 +127,6 @@ or variable in the namespace.
Command resolution is always done by first looking in the namespace and then
at the global scope, so namespace path is not required.
-namespace ensemble
-------------------
-The namespace ensemble command is not currently supported. A future version
-of Jim Tcl will have a general-purpose ensemble creation and manipulation
-mechanism and namespace ensemble will be implemented in terms of that mechanism.
-
namespace import, export, forget, origin
----------------------------------------
Since Jim Tcl namespaces are implicit, there is no location to store export patterns.
diff --git a/Tcl_shipped.html b/Tcl_shipped.html
index 1f03d6d..5f237f5 100644
--- a/Tcl_shipped.html
+++ b/Tcl_shipped.html
@@ -4,7 +4,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 9.0.0rc1" />
+<meta name="generator" content="AsciiDoc 10.2.1" />
<title>Jim Tcl(n)</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
@@ -739,7 +739,7 @@ Jim Tcl(n) Manual Page
</h1>
<h2>NAME</h2>
<div class="sectionbody">
-<p>Jim Tcl v0.83 -
+<p>Jim Tcl v0.83+ -
reference manual for the Jim Tcl scripting language
</p>
</div>
@@ -880,7 +880,17 @@ Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets
<h2 id="_recent_changes">RECENT CHANGES</h2>
<div class="sectionbody">
<div class="sect2">
-<h3 id="_changes_since_0_82">Changes since 0.82</h3>
+<h3 id="_changes_since_0_83">Changes since 0.83</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+<a href="#_aio"><strong><code>aio</code></strong></a> - support for configurable read and write buffering
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_changes_between_0_82_and_0_83">Changes between 0.82 and 0.83</h3>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
@@ -1872,7 +1882,7 @@ sequence is replaced by the given character:</p></div>
<div class="paragraph"><p>For example, in the command</p></div>
<div class="listingblock">
<div class="content">
-<pre><code> set a \{x\[\ yz\141</code></pre>
+<pre><code> set a {x\[\ yz\141</code></pre>
</div></div>
<div class="paragraph"><p>the second argument to <a href="#_set"><strong><code>set</code></strong></a> will be <code>{x[ yza</code>.</p></div>
<div class="paragraph"><p>If a backslash is followed by something other than one of the options
@@ -1882,7 +1892,7 @@ normal processing with the next character. For example, in the
command</p></div>
<div class="listingblock">
<div class="content">
-<pre><code> set \*a \\{foo</code></pre>
+<pre><code> set \*a \{foo</code></pre>
</div></div>
<div class="paragraph"><p>The first argument to <a href="#_set"><strong><code>set</code></strong></a> will be <code>*a</code> and the second
argument will be <code>{foo</code>.</p></div>
@@ -1897,9 +1907,9 @@ For example, in the
command</p></div>
<div class="listingblock">
<div class="content">
-<pre><code> set a {\\{abc}</code></pre>
+<pre><code> set a {\{abc}</code></pre>
</div></div>
-<div class="paragraph"><p>the second argument to <a href="#_set"><strong><code>set</code></strong></a> will be <code>\\{abc</code>.</p></div>
+<div class="paragraph"><p>the second argument to <a href="#_set"><strong><code>set</code></strong></a> will be <code>\{abc</code>.</p></div>
<div class="paragraph"><p>This backslash mechanism is not sufficient to generate absolutely
any argument structure; it only covers the
most common cases. To produce particularly complicated arguments
@@ -2514,14 +2524,14 @@ arguments. Support for this feature is also available in Jim.</p></div>
</div></div>
<div class="paragraph"><p>This will attempt to exec a command named "ls -l", which will clearly not
work. Typically eval and concat are required to solve this problem, however
-it can be solved much more easily with <code>{*}</code>.</p></div>
+it can be solved much more easily with <code>\{*}</code>.</p></div>
<div class="listingblock">
<div class="content">
<pre><code> exec {*}$cmd</code></pre>
</div></div>
<div class="paragraph"><p>This will expand the following argument into individual elements and then evaluate
the resulting command.</p></div>
-<div class="paragraph"><p>Note that the official Tcl syntax is <code>{*}</code>, however <code>{expand}</code> is retained
+<div class="paragraph"><p>Note that the official Tcl syntax is <code>\{*}</code>, however <code>{expand}</code> is retained
for backward compatibility with experimental versions of this feature.</p></div>
</div>
</div>
@@ -7006,7 +7016,7 @@ is performed: open and close brackets are treated as ordinary
characters with no special interpretation.</p></div>
<div class="paragraph"><p><strong>Note</strong>: when it performs its substitutions, subst does not give any
special treatment to double quotes or curly braces. For example,
-the following script returns <code>xyz {44}</code>, not <code>xyz {$a}</code>.</p></div>
+the following script returns <code>xyz {44}</code>, not <code>xyz \{$a}</code>.</p></div>
<div class="listingblock">
<div class="content">
<pre><code> set a 44
@@ -7536,7 +7546,7 @@ over <a href="#_aio"><strong><code>aio</code></strong></a> <code>read</code> and
</p>
</dd>
<dt class="hdlist1">
-<code>$handle <strong>buffering none|line|full</strong></code>
+<code>$handle <strong>buffering none|line|full</strong> ?size?</code>
</dt>
<dd>
<p>
@@ -7544,11 +7554,14 @@ over <a href="#_aio"><strong><code>aio</code></strong></a> <code>read</code> and
that puts immediately writes output. <code><em>line</em></code> means output (including
previously buffered output) is written if a newline is to be written.
<code><em>full</em></code> means that data is written when the output buffer is full
- (currently approx 64KB). Note that line buffering will also write
+ (default 64KB). Size may be specified in full mode.
+ Note that line buffering will also write
once the output buffer limit is reached, even if there is no newline.
Channels usually begin in full buffering mode, unless they identify
as a tty channel, in which case line buffering is used, and <code>stderr</code>
- begins with no buffering. See also <a href="#_aio"><strong><code>aio</code></strong></a> <code>puts</code> and <a href="#_aio"><strong><code>aio</code></strong></a> <code>flush</code>.
+ begins with no buffering. Returns the current buffering mode (including
+ size in full mode - e.g. <code><em>line</em></code> or <code><em>full 65536</code></em>.
+ See also <a href="#_aio"><strong><code>aio</code></strong></a> <code>puts</code> and <a href="#_aio"><strong><code>aio</code></strong></a> <code>flush</code>.
</p>
</dd>
<dt class="hdlist1">
@@ -7703,6 +7716,17 @@ over <a href="#_aio"><strong><code>aio</code></strong></a> <code>read</code> and
</p>
</dd>
<dt class="hdlist1">
+<code>$handle <strong>readsize</strong> ?size?'</code>
+</dt>
+<dd>
+<p>
+ Sets or returns the current size of the read buffer used
+ for read, gets and copyto.
+ Defaults to 256, but can be increased to improve performance
+ for large reads.
+</p>
+</dd>
+<dt class="hdlist1">
<code>$handle <strong>recvfrom</strong> <em>maxlen ?addrvar?</em></code>
</dt>
<dd>
diff --git a/auto.def b/auto.def
index 1b06f04..81ee889 100644
--- a/auto.def
+++ b/auto.def
@@ -1,7 +1,7 @@
# vim:se syn=tcl:
#
-define JIM_VERSION 83
+define JIM_VERSION 84
options-defaults {
silent-rules 1
@@ -549,7 +549,7 @@ if {$withinfo(without) eq "default"} {
# Now go check everything - see autosetup/local.tcl
array set extinfo [check-extensions [opt-bool allextmod]]
-set buildjimext 1
+define BUILD_JIM_EXT 1
# Now special checks
if {[have-feature windows]} {
@@ -560,7 +560,7 @@ if {[have-feature windows]} {
user-error "cygwin/mingw require --shared for dynamic modules"
} else {
user-notice "Building static library, so build-jim-ext will not work on cygwin/mingw"
- set buildjimext 0
+ define BUILD_JIM_EXT 0
}
}
} else {
@@ -668,7 +668,7 @@ make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE
make-template Makefile.in
make-template tests/Makefile.in
make-template examples.api/Makefile.in
-if {$buildjimext} {
+if {[get-define BUILD_JIM_EXT]} {
make-template build-jim-ext.in
catch {exec chmod +x build-jim-ext}
}
diff --git a/autosetup/README.autosetup b/autosetup/README.autosetup
index 30bef32..3952980 100644
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -1,4 +1,4 @@
-README.autosetup created by autosetup v0.7.1+
+README.autosetup created by autosetup v0.7.2
This is the autosetup directory for a local install of autosetup.
It contains autosetup, support files and loadable modules.
diff --git a/autosetup/autosetup b/autosetup/autosetup
index e4d5a31..90f5454 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -6,7 +6,7 @@
dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
# Note that the version has a trailing + on unreleased versions
-set autosetup(version) 0.7.1+
+set autosetup(version) 0.7.2
# Can be set to 1 to debug early-init problems
set autosetup(debug) [expr {"--debug" in $argv}]
@@ -566,7 +566,10 @@ proc options-show {what} {
set indent [string repeat " " [expr {$max+4}]]
set cols [getenv COLUMNS 80]
catch {
- lassign [exec stty size] rows cols
+ lassign [exec stty size] _ sttycols
+ if {[string is integer -strict $sttycols]} {
+ set cols $sttycols
+ }
}
incr cols -1
# Now output
@@ -910,8 +913,7 @@ proc list-non-empty {list} {
# Searches the path for an executable with the given name.
# Note that the name may include some parameters, e.g. 'cc -mbig-endian',
# in which case the parameters are ignored.
-# The full path to the executable if found, or "" if not found.
-# Returns 1 if found, or 0 if not.
+# Returns the full path to the executable if found, or "" if not found.
#
proc find-executable-path {name} {
# Ignore any parameters
diff --git a/autosetup/autosetup-config.guess b/autosetup/autosetup-config.guess
index e81d3ae..48a6846 100755
--- a/autosetup/autosetup-config.guess
+++ b/autosetup/autosetup-config.guess
@@ -1,14 +1,14 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2021 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2021-06-03'
+timestamp='2024-07-27'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
@@ -60,13 +60,13 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2021 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -102,8 +102,8 @@ GUESS=
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
@@ -123,7 +123,7 @@ set_cc_for_build() {
dummy=$tmp/dummy
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
,,) echo "int x;" > "$dummy.c"
- for driver in cc gcc c89 c99 ; do
+ for driver in cc gcc c17 c99 c89 ; do
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
CC_FOR_BUILD=$driver
break
@@ -155,6 +155,9 @@ Linux|GNU|GNU/*)
set_cc_for_build
cat <<-EOF > "$dummy.c"
+ #if defined(__ANDROID__)
+ LIBC=android
+ #else
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
@@ -162,6 +165,8 @@ Linux|GNU|GNU/*)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
+ #elif defined(__LLVM_LIBC__)
+ LIBC=llvm
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
@@ -169,6 +174,7 @@ Linux|GNU|GNU/*)
LIBC=musl
#endif
#endif
+ #endif
EOF
cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
eval "$cc_set_libc"
@@ -437,7 +443,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
# This test works for both compilers.
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
@@ -459,7 +465,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
UNAME_RELEASE=`uname -v`
;;
esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
+ # Japanese Language versions have a version number like '4.1.3-JL'.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
GUESS=sparc-sun-sunos$SUN_REL
;;
@@ -628,7 +634,8 @@ EOF
sed 's/^ //' << EOF > "$dummy.c"
#include <sys/systemcfg.h>
- main()
+ int
+ main ()
{
if (!__power_pc())
exit(1);
@@ -712,7 +719,8 @@ EOF
#include <stdlib.h>
#include <unistd.h>
- int main ()
+ int
+ main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
@@ -904,7 +912,7 @@ EOF
fi
;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
@@ -929,6 +937,9 @@ EOF
i*:PW*:*)
GUESS=$UNAME_MACHINE-pc-pw32
;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
*:Interix*:*)
case $UNAME_MACHINE in
x86)
@@ -963,11 +974,37 @@ EOF
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
*:Minix:*:*)
GUESS=$UNAME_MACHINE-unknown-minix
;;
aarch64:Linux:*:*)
- GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __ARM_EABI__
+ #ifdef __ARM_PCS_VFP
+ ABI=eabihf
+ #else
+ ABI=eabi
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+ esac
+ fi
+ GUESS=$CPU-unknown-linux-$LIBCABI
;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
@@ -1033,7 +1070,16 @@ EOF
k1om:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
- loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ kvx:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:cos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-cos
+ ;;
+ kvx:mbr:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mbr
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m32r*:Linux:*:*)
@@ -1148,16 +1194,27 @@ EOF
;;
x86_64:Linux:*:*)
set_cc_for_build
+ CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI=${LIBC}x32
- fi
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
fi
- GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@@ -1177,7 +1234,7 @@ EOF
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
;;
i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
+ # If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
GUESS=$UNAME_MACHINE-pc-os2-emx
;;
@@ -1318,7 +1375,7 @@ EOF
GUESS=ns32k-sni-sysv
fi
;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
GUESS=i586-unisys-sysv4
;;
@@ -1364,8 +1421,11 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
- x86_64:Haiku:*:*)
- GUESS=x86_64-unknown-haiku
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE
@@ -1522,6 +1582,9 @@ EOF
i*86:rdos:*:*)
GUESS=$UNAME_MACHINE-pc-rdos
;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
*:AROS:*:*)
GUESS=$UNAME_MACHINE-unknown-aros
;;
@@ -1534,6 +1597,9 @@ EOF
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
+ *:Ironclad:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ironclad
+ ;;
esac
# Do we have a guess based on uname results?
@@ -1557,6 +1623,7 @@ cat > "$dummy.c" <<EOF
#endif
#endif
#endif
+int
main ()
{
#if defined (sony)
diff --git a/autosetup/autosetup-config.sub b/autosetup/autosetup-config.sub
index d80c5d7..4aaae46 100755
--- a/autosetup/autosetup-config.sub
+++ b/autosetup/autosetup-config.sub
@@ -1,14 +1,14 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2021 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
-# shellcheck disable=SC2006,SC2268 # see below for rationale
+# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
-timestamp='2021-07-03'
+timestamp='2024-05-27'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -76,13 +76,13 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2021 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -120,15 +120,16 @@ case $# in
esac
# Split fields of configuration type
-# shellcheck disable=SC2162
+saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <<EOF
$1
EOF
+IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
*-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
+ echo "Invalid configuration '$1': more than four components" >&2
exit 1
;;
*-*-*-*)
@@ -140,10 +141,21 @@ case $1 in
# parts
maybe_os=$field2-$field3
case $maybe_os in
- nto-qnx* | linux-* | uclinux-uclibc* \
- | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
- | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
+ cloudabi*-eabi* \
+ | kfreebsd*-gnu* \
+ | knetbsd*-gnu* \
+ | kopensolaris*-gnu* \
+ | linux-* \
+ | managarm-* \
+ | netbsd*-eabi* \
+ | netbsd*-gnu* \
+ | nto-qnx* \
+ | os2-emx* \
+ | rtmk-nova* \
+ | storm-chaos* \
+ | uclinux-gnu* \
+ | uclinux-uclibc* \
+ | windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
@@ -158,8 +170,12 @@ case $1 in
esac
;;
*-*)
- # A lone config we happen to match not fitting any pattern
case $field1-$field2 in
+ # Shorthands that happen to contain a single dash
+ convex-c[12] | convex-c3[248])
+ basic_machine=$field2-convex
+ basic_os=
+ ;;
decstation-3100)
basic_machine=mips-dec
basic_os=
@@ -167,24 +183,88 @@ case $1 in
*-*)
# Second component is usually, but not always the OS
case $field2 in
- # Prevent following clause from handling this valid os
+ # Do not treat sunos as a manufacturer
sun*os*)
basic_machine=$field1
basic_os=$field2
;;
# Manufacturers
- dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
- | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
- | unicom* | ibm* | next | hp | isi* | apollo | altos* \
- | convergent* | ncr* | news | 32* | 3600* | 3100* \
- | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
- | ultra | tti* | harris | dolphin | highlevel | gould \
- | cbm | ns | masscomp | apple | axis | knuth | cray \
- | microblaze* | sim | cisco \
- | oki | wec | wrs | winbond)
+ 3100* \
+ | 32* \
+ | 3300* \
+ | 3600* \
+ | 7300* \
+ | acorn \
+ | altos* \
+ | apollo \
+ | apple \
+ | atari \
+ | att* \
+ | axis \
+ | be \
+ | bull \
+ | cbm \
+ | ccur \
+ | cisco \
+ | commodore \
+ | convergent* \
+ | convex* \
+ | cray \
+ | crds \
+ | dec* \
+ | delta* \
+ | dg \
+ | digital \
+ | dolphin \
+ | encore* \
+ | gould \
+ | harris \
+ | highlevel \
+ | hitachi* \
+ | hp \
+ | ibm* \
+ | intergraph \
+ | isi* \
+ | knuth \
+ | masscomp \
+ | microblaze* \
+ | mips* \
+ | motorola* \
+ | ncr* \
+ | news \
+ | next \
+ | ns \
+ | oki \
+ | omron* \
+ | pc533* \
+ | rebel \
+ | rom68k \
+ | rombug \
+ | semi \
+ | sequent* \
+ | siemens \
+ | sgi* \
+ | siemens \
+ | sim \
+ | sni \
+ | sony* \
+ | stratus \
+ | sun \
+ | sun[234]* \
+ | tektronix \
+ | tti* \
+ | ultra \
+ | unicom* \
+ | wec \
+ | winbond \
+ | wrs)
basic_machine=$field1-$field2
basic_os=
;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
*)
basic_machine=$field1
basic_os=$field2
@@ -265,26 +345,6 @@ case $1 in
basic_machine=arm-unknown
basic_os=cegcc
;;
- convex-c1)
- basic_machine=c1-convex
- basic_os=bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- basic_os=bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- basic_os=bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- basic_os=bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- basic_os=bsd
- ;;
cray)
basic_machine=j90-cray
basic_os=unicos
@@ -707,15 +767,26 @@ case $basic_machine in
vendor=dec
basic_os=tops20
;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
+ delta | 3300 | delta-motorola | 3300-motorola | motorola-delta | motorola-3300)
cpu=m68k
vendor=motorola
;;
- dpx2*)
+ # This used to be dpx2*, but that gets the RS6000-based
+ # DPX/20 and the x86-based DPX/2-100 wrong. See
+ # https://oldskool.silicium.org/stations/bull_dpx20.htm
+ # https://www.feb-patrimoine.com/english/bull_dpx2.htm
+ # https://www.feb-patrimoine.com/english/unix_and_bull.htm
+ dpx2 | dpx2[23]00 | dpx2[23]xx)
cpu=m68k
vendor=bull
- basic_os=sysv3
+ ;;
+ dpx2100 | dpx21xx)
+ cpu=i386
+ vendor=bull
+ ;;
+ dpx20)
+ cpu=rs6000
+ vendor=bull
;;
encore | umax | mmax)
cpu=ns32k
@@ -830,18 +901,6 @@ case $basic_machine in
next | m*-next)
cpu=m68k
vendor=next
- case $basic_os in
- openstep*)
- ;;
- nextstep*)
- ;;
- ns2*)
- basic_os=nextstep2
- ;;
- *)
- basic_os=nextstep3
- ;;
- esac
;;
np1)
cpu=np1
@@ -930,12 +989,13 @@ case $basic_machine in
;;
*-*)
- # shellcheck disable=SC2162
+ saved_IFS=$IFS
IFS="-" read cpu vendor <<EOF
$basic_machine
EOF
+ IFS=$saved_IFS
;;
- # We use `pc' rather than `unknown'
+ # We use 'pc' rather than 'unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
@@ -963,15 +1023,19 @@ unset -v basic_machine
# Decode basic machines in the full and proper CPU-Company form.
case $cpu-$vendor in
- # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
- # some cases the only manufacturer, in others, it is the most popular.
+ # Here we handle the default manufacturer of certain CPU types in canonical form.
+ # It is in some cases the only manufacturer, in others, it is the most popular.
+ c[12]-convex | c[12]-unknown | c3[248]-convex | c3[248]-unknown)
+ vendor=convex
+ basic_os=${basic_os:-bsd}
+ ;;
craynv-unknown)
vendor=cray
basic_os=${basic_os:-unicosmp}
;;
c90-unknown | c90-cray)
vendor=cray
- basic_os=${Basic_os:-unicos}
+ basic_os=${basic_os:-unicos}
;;
fx80-unknown)
vendor=alliant
@@ -1012,11 +1076,34 @@ case $cpu-$vendor in
;;
# Here we normalize CPU types with a missing or matching vendor
- dpx20-unknown | dpx20-bull)
- cpu=rs6000
- vendor=bull
+ armh-unknown | armh-alt)
+ cpu=armv7l
+ vendor=alt
+ basic_os=${basic_os:-linux-gnueabihf}
+ ;;
+
+ # Normalized CPU+vendor pairs that imply an OS, if not otherwise specified
+ m68k-isi)
+ basic_os=${basic_os:-sysv}
+ ;;
+ m68k-sony)
+ basic_os=${basic_os:-newsos}
+ ;;
+ m68k-tektronix)
+ basic_os=${basic_os:-bsd}
+ ;;
+ m88k-harris)
+ basic_os=${basic_os:-sysv3}
+ ;;
+ i386-bull | m68k-bull)
+ basic_os=${basic_os:-sysv3}
+ ;;
+ rs6000-bull)
basic_os=${basic_os:-bosx}
;;
+ mips-sni)
+ basic_os=${basic_os:-sysv4}
+ ;;
# Here we normalize CPU types irrespective of the vendor
amd64-*)
@@ -1024,7 +1111,7 @@ case $cpu-$vendor in
;;
blackfin-*)
cpu=bfin
- basic_os=linux
+ basic_os=${basic_os:-linux}
;;
c54x-*)
cpu=tic54x
@@ -1047,7 +1134,7 @@ case $cpu-$vendor in
;;
m68knommu-*)
cpu=m68k
- basic_os=linux
+ basic_os=${basic_os:-linux}
;;
m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
cpu=s12z
@@ -1057,12 +1144,12 @@ case $cpu-$vendor in
;;
parisc-*)
cpu=hppa
- basic_os=linux
+ basic_os=${basic_os:-linux}
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
cpu=i586
;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
cpu=i686
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
@@ -1071,9 +1158,6 @@ case $cpu-$vendor in
pentium4-*)
cpu=i786
;;
- pc98-*)
- cpu=i386
- ;;
ppc-* | ppcbe-*)
cpu=powerpc
;;
@@ -1107,13 +1191,10 @@ case $cpu-$vendor in
tx39el-*)
cpu=mipstx39el
;;
- x64-*)
- cpu=x86_64
- ;;
xscale-* | xscalee[bl]-*)
cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
- arm64-*)
+ arm64-* | aarch64le-*)
cpu=aarch64
;;
@@ -1165,114 +1246,231 @@ case $cpu-$vendor in
# Recognize the canonical CPU types that are allowed with any
# company name.
case $cpu in
- 1750a | 580 \
+ 1750a \
+ | 580 \
+ | [cjt]90 \
| a29k \
- | aarch64 | aarch64_be \
+ | aarch64 \
+ | aarch64_be \
+ | aarch64c \
| abacus \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
- | alphapca5[67] | alpha64pca5[67] \
+ | alpha \
+ | alpha64 \
+ | alpha64ev56 \
+ | alpha64ev6[78] \
+ | alpha64ev[4-8] \
+ | alpha64pca5[67] \
+ | alphaev56 \
+ | alphaev6[78] \
+ | alphaev[4-8] \
+ | alphapca5[67] \
| am33_2.0 \
| amdgcn \
- | arc | arceb | arc32 | arc64 \
- | arm | arm[lb]e | arme[lb] | armv* \
- | avr | avr32 \
+ | arc \
+ | arc32 \
+ | arc64 \
+ | arceb \
+ | arm \
+ | arm64e \
+ | arm64ec \
+ | arm[lb]e \
+ | arme[lb] \
+ | armv* \
| asmjs \
+ | avr \
+ | avr32 \
| ba \
- | be32 | be64 \
- | bfin | bpf | bs2000 \
- | c[123]* | c30 | [cjt]90 | c4x \
- | c8051 | clipper | craynv | csky | cydra \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | elxsi | epiphany \
- | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
- | h8300 | h8500 \
- | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | be32 \
+ | be64 \
+ | bfin \
+ | bpf \
+ | bs2000 \
+ | c30 \
+ | c4x \
+ | c8051 \
+ | c[123]* \
+ | clipper \
+ | craynv \
+ | csky \
+ | cydra \
+ | d10v \
+ | d30v \
+ | dlx \
+ | dsp16xx \
+ | e2k \
+ | elxsi \
+ | epiphany \
+ | f30[01] \
+ | f700 \
+ | fido \
+ | fr30 \
+ | frv \
+ | ft32 \
+ | fx80 \
+ | h8300 \
+ | h8500 \
| hexagon \
- | i370 | i*86 | i860 | i960 | ia16 | ia64 \
- | ip2k | iq2000 \
+ | hppa \
+ | hppa1.[01] \
+ | hppa2.0 \
+ | hppa2.0[nw] \
+ | hppa64 \
+ | i*86 \
+ | i370 \
+ | i860 \
+ | i960 \
+ | ia16 \
+ | ia64 \
+ | ip2k \
+ | iq2000 \
+ | javascript \
| k1om \
- | le32 | le64 \
+ | kvx \
+ | le32 \
+ | le64 \
| lm32 \
- | loongarch32 | loongarch64 | loongarchx32 \
- | m32c | m32r | m32rle \
- | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
- | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
- | m88110 | m88k | maxq | mb | mcore | mep | metag \
- | microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r3 | mipsisa32r3el \
- | mipsisa32r5 | mipsisa32r5el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r3 | mipsisa64r3el \
- | mipsisa64r5 | mipsisa64r5el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
+ | loongarch32 \
+ | loongarch64 \
+ | m32c \
+ | m32r \
+ | m32rle \
+ | m5200 \
+ | m68000 \
+ | m680[012346]0 \
+ | m6811 \
+ | m6812 \
+ | m68360 \
+ | m683?2 \
+ | m68hc11 \
+ | m68hc12 \
+ | m68hcs12x \
+ | m68k \
+ | m88110 \
+ | m88k \
+ | maxq \
+ | mb \
+ | mcore \
+ | mep \
+ | metag \
+ | microblaze \
+ | microblazeel \
+ | mips* \
| mmix \
- | mn10200 | mn10300 \
+ | mn10200 \
+ | mn10300 \
| moxie \
- | mt \
| msp430 \
- | nds32 | nds32le | nds32be \
+ | mt \
+ | nanomips* \
+ | nds32 \
+ | nds32be \
+ | nds32le \
| nfp \
- | nios | nios2 | nios2eb | nios2el \
- | none | np1 | ns16k | ns32k | nvptx \
+ | nios \
+ | nios2 \
+ | nios2eb \
+ | nios2el \
+ | none \
+ | np1 \
+ | ns16k \
+ | ns32k \
+ | nvptx \
| open8 \
| or1k* \
| or32 \
| orion \
+ | pdp10 \
+ | pdp11 \
| picochip \
- | pdp10 | pdp11 | pj | pjl | pn | power \
- | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pj \
+ | pjl \
+ | pn \
+ | power \
+ | powerpc \
+ | powerpc64 \
+ | powerpc64le \
+ | powerpcle \
+ | powerpcspe \
| pru \
| pyramid \
- | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
- | rl78 | romp | rs6000 | rx \
- | s390 | s390x \
+ | riscv \
+ | riscv32 \
+ | riscv32be \
+ | riscv64 \
+ | riscv64be \
+ | rl78 \
+ | romp \
+ | rs6000 \
+ | rx \
+ | s390 \
+ | s390x \
| score \
- | sh | shl \
- | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
- | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sh \
+ | sh64 \
+ | sh64le \
+ | sh[12345][lb]e \
+ | sh[1234] \
+ | sh[1234]e[lb] \
+ | sh[23]e \
+ | sh[23]ele \
+ | sh[24]a \
+ | sh[24]ae[lb] \
+ | sh[lb]e \
+ | she[lb] \
+ | shl \
+ | sparc \
+ | sparc64 \
+ | sparc64b \
+ | sparc64v \
+ | sparc86x \
+ | sparclet \
| sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | sparcv8 \
+ | sparcv9 \
+ | sparcv9b \
+ | sparcv9v \
| spu \
+ | sv1 \
+ | sx* \
| tahoe \
| thumbv7* \
- | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tic30 \
+ | tic4x \
+ | tic54x \
+ | tic55x \
+ | tic6x \
+ | tic80 \
| tron \
| ubicom32 \
- | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | v70 \
+ | v810 \
+ | v850 \
+ | v850e \
+ | v850e1 \
+ | v850e2 \
+ | v850e2v3 \
+ | v850es \
| vax \
+ | vc4 \
| visium \
| w65 \
- | wasm32 | wasm64 \
+ | wasm32 \
+ | wasm64 \
| we32k \
- | x86 | x86_64 | xc16x | xgate | xps100 \
- | xstormy16 | xtensa* \
+ | x86 \
+ | x86_64 \
+ | xc16x \
+ | xgate \
+ | xps100 \
+ | xstormy16 \
+ | xtensa* \
| ymp \
- | z8k | z80)
+ | z80 \
+ | z8k)
;;
*)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
exit 1
;;
esac
@@ -1293,11 +1491,12 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if test x$basic_os != x
+if test x"$basic_os" != x
then
-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
+obj=
case $basic_os in
gnu/linux*)
kernel=linux
@@ -1312,10 +1511,11 @@ case $basic_os in
os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;;
*-*)
- # shellcheck disable=SC2162
+ saved_IFS=$IFS
IFS="-" read kernel os <<EOF
$basic_os
EOF
+ IFS=$saved_IFS
;;
# Default OS when just kernel was specified
nto*)
@@ -1326,6 +1526,10 @@ EOF
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+ ;;
*)
kernel=
os=$basic_os
@@ -1353,6 +1557,23 @@ case $os in
unixware*)
os=sysv4.2uw
;;
+ # The marketing names for NeXT's operating systems were
+ # NeXTSTEP, NeXTSTEP 2, OpenSTEP 3, OpenSTEP 4. 'openstep' is
+ # mapped to 'openstep3', but 'openstep1' and 'openstep2' are
+ # mapped to 'nextstep' and 'nextstep2', consistent with the
+ # treatment of SunOS/Solaris.
+ ns | ns1 | nextstep | nextstep1 | openstep1)
+ os=nextstep
+ ;;
+ ns2 | nextstep2 | openstep2)
+ os=nextstep2
+ ;;
+ ns3 | nextstep3 | openstep | openstep3)
+ os=openstep3
+ ;;
+ ns4 | nextstep4 | openstep4)
+ os=openstep4
+ ;;
# es1800 is here to avoid being matched by es* (a different OS)
es1800*)
os=ose
@@ -1423,6 +1644,7 @@ case $os in
;;
utek*)
os=bsd
+ vendor=`echo "$vendor" | sed -e 's|^unknown$|tektronix|'`
;;
dynix*)
os=bsd
@@ -1439,21 +1661,25 @@ case $os in
386bsd)
os=bsd
;;
- ctix* | uts*)
+ ctix*)
os=sysv
+ vendor=`echo "$vendor" | sed -e 's|^unknown$|convergent|'`
;;
- nova*)
- os=rtmk-nova
+ uts*)
+ os=sysv
;;
- ns2)
- os=nextstep2
+ nova*)
+ kernel=rtmk
+ os=nova
;;
# Preserve the version number of sinix5.
sinix5.*)
os=`echo "$os" | sed -e 's|sinix|sysv|'`
+ vendor=`echo "$vendor" | sed -e 's|^unknown$|sni|'`
;;
sinix*)
os=sysv4
+ vendor=`echo "$vendor" | sed -e 's|^unknown$|sni|'`
;;
tpf*)
os=tpf
@@ -1491,10 +1717,16 @@ case $os in
os=eabi
;;
*)
- os=elf
+ os=
+ obj=elf
;;
esac
;;
+ aout* | coff* | elf* | pe*)
+ # These are machine code file formats, not OSes
+ obj=$os
+ os=
+ ;;
*)
# No normalization, but not necessarily accepted, that comes below.
;;
@@ -1513,12 +1745,15 @@ else
# system, and we'll never get to this point.
kernel=
+obj=
case $cpu-$vendor in
score-*)
- os=elf
+ os=
+ obj=elf
;;
spu-*)
- os=elf
+ os=
+ obj=elf
;;
*-acorn)
os=riscix1.2
@@ -1528,28 +1763,35 @@ case $cpu-$vendor in
os=gnu
;;
arm*-semi)
- os=aout
+ os=
+ obj=aout
;;
c4x-* | tic4x-*)
- os=coff
+ os=
+ obj=coff
;;
c8051-*)
- os=elf
+ os=
+ obj=elf
;;
clipper-intergraph)
os=clix
;;
hexagon-*)
- os=elf
+ os=
+ obj=elf
;;
tic54x-*)
- os=coff
+ os=
+ obj=coff
;;
tic55x-*)
- os=coff
+ os=
+ obj=coff
;;
tic6x-*)
- os=coff
+ os=
+ obj=coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1571,28 +1813,43 @@ case $cpu-$vendor in
os=sunos3
;;
m68*-cisco)
- os=aout
+ os=
+ obj=aout
;;
mep-*)
- os=elf
+ os=
+ obj=elf
+ ;;
+ # The -sgi and -siemens entries must be before the mips- entry
+ # or we get the wrong os.
+ *-sgi)
+ os=irix
+ ;;
+ *-siemens)
+ os=sysv4
;;
mips*-cisco)
- os=elf
+ os=
+ obj=elf
;;
- mips*-*)
- os=elf
+ mips*-*|nanomips*-*)
+ os=
+ obj=elf
;;
or32-*)
- os=coff
+ os=
+ obj=coff
;;
- *-tti) # must be before sparc entry or we get the wrong os.
+ # This must be before the sparc-* entry or we get the wrong os.
+ *-tti)
os=sysv3
;;
sparc-* | *-sun)
os=sunos4.1.1
;;
pru-*)
- os=elf
+ os=
+ obj=elf
;;
*-be)
os=beos
@@ -1616,7 +1873,7 @@ case $cpu-$vendor in
os=hpux
;;
*-hitachi)
- os=hiux
+ os=hiuxwe2
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=sysv
@@ -1660,12 +1917,6 @@ case $cpu-$vendor in
*-encore)
os=bsd
;;
- *-sgi)
- os=irix
- ;;
- *-siemens)
- os=sysv4
- ;;
*-masscomp)
os=rtu
;;
@@ -1673,10 +1924,12 @@ case $cpu-$vendor in
os=uxpv
;;
*-rom68k)
- os=coff
+ os=
+ obj=coff
;;
*-*bug)
- os=coff
+ os=
+ obj=coff
;;
*-apple)
os=macos
@@ -1694,10 +1947,11 @@ esac
fi
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
case $os in
# Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | uclibc*)
+ llvm* | musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
@@ -1705,81 +1959,308 @@ case $os in
# VxWorks passes extra cpu info in the 4th filed.
simlinux | simwindows | spe)
;;
+ # See `case $cpu-$os` validation below
+ ghcjs)
+ ;;
# Now accept the basic system types.
- # The portable systems comes first.
# Each alternative MUST end in a * to match a version number.
- gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
- | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
- | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
- | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
- | hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* \
- | mpw* | magic* | mmixware* | mon960* | lnews* \
- | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
- | aos* | aros* | cloudabi* | sortix* | twizzler* \
- | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
- | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
- | mirbsd* | netbsd* | dicos* | openedition* | ose* \
- | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
- | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
- | udi* | lites* | ieee* | go32* | aux* | hcos* \
- | chorusrdb* | cegcc* | glidix* | serenity* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
- | midipix* | mingw32* | mingw64* | mint* \
- | uxpv* | beos* | mpeix* | udk* | moxiebox* \
- | interix* | uwin* | mks* | rhapsody* | darwin* \
- | openstep* | oskit* | conix* | pw32* | nonstopux* \
- | storm-chaos* | tops10* | tenex* | tops20* | its* \
- | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
- | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
- | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
- | skyos* | haiku* | rdos* | toppers* | drops* | es* \
- | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
- | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
+ abug \
+ | aix* \
+ | amdhsa* \
+ | amigados* \
+ | amigaos* \
+ | android* \
+ | aof* \
+ | aos* \
+ | aros* \
+ | atheos* \
+ | auroraux* \
+ | aux* \
+ | beos* \
+ | bitrig* \
+ | bme* \
+ | bosx* \
+ | bsd* \
+ | cegcc* \
+ | chorusos* \
+ | chorusrdb* \
+ | clix* \
+ | cloudabi* \
+ | cnk* \
+ | conix* \
+ | cos* \
+ | cxux* \
+ | cygwin* \
+ | darwin* \
+ | dgux* \
+ | dicos* \
+ | dnix* \
+ | domain* \
+ | dragonfly* \
+ | drops* \
+ | ebmon* \
+ | ecoff* \
+ | ekkobsd* \
+ | emscripten* \
+ | emx* \
+ | es* \
+ | fiwix* \
+ | freebsd* \
+ | fuchsia* \
+ | genix* \
+ | genode* \
+ | glidix* \
+ | gnu* \
+ | go32* \
+ | haiku* \
+ | hcos* \
+ | hiux* \
+ | hms* \
+ | hpux* \
+ | ieee* \
+ | interix* \
+ | ios* \
+ | iris* \
+ | irix* \
+ | ironclad* \
+ | isc* \
+ | its* \
+ | l4re* \
+ | libertybsd* \
+ | lites* \
+ | lnews* \
+ | luna* \
+ | lynxos* \
+ | mach* \
+ | macos* \
+ | magic* \
+ | mbr* \
+ | midipix* \
+ | midnightbsd* \
+ | mingw32* \
+ | mingw64* \
+ | minix* \
+ | mint* \
+ | mirbsd* \
+ | mks* \
+ | mlibc* \
+ | mmixware* \
+ | mon960* \
+ | morphos* \
+ | moss* \
+ | moxiebox* \
+ | mpeix* \
+ | mpw* \
+ | msdos* \
+ | msys* \
+ | mvs* \
+ | nacl* \
+ | netbsd* \
+ | netware* \
+ | newsos* \
+ | nextstep* \
+ | nindy* \
+ | nonstopux* \
+ | nova* \
+ | nsk* \
+ | nucleus* \
+ | nx6 \
+ | nx7 \
+ | oabi* \
+ | ohos* \
+ | onefs* \
+ | openbsd* \
+ | openedition* \
+ | openstep* \
+ | os108* \
+ | os2* \
+ | os400* \
+ | os68k* \
+ | os9* \
+ | ose* \
+ | osf* \
+ | oskit* \
+ | osx* \
+ | palmos* \
+ | phoenix* \
+ | plan9* \
+ | powermax* \
+ | powerunix* \
+ | proelf* \
+ | psos* \
+ | psp* \
+ | ptx* \
+ | pw32* \
+ | qnx* \
+ | rdos* \
+ | redox* \
+ | rhapsody* \
+ | riscix* \
+ | riscos* \
+ | rtems* \
+ | rtmk* \
+ | rtu* \
+ | scout* \
+ | secbsd* \
+ | sei* \
+ | serenity* \
+ | sim* \
+ | skyos* \
+ | solaris* \
+ | solidbsd* \
+ | sortix* \
+ | storm-chaos* \
+ | sunos \
+ | sunos[34]* \
+ | superux* \
+ | syllable* \
+ | sym* \
+ | sysv* \
+ | tenex* \
+ | tirtos* \
+ | toppers* \
+ | tops10* \
+ | tops20* \
+ | tpf* \
+ | tvos* \
+ | twizzler* \
+ | uclinux* \
+ | udi* \
+ | udk* \
+ | ultrix* \
+ | unicos* \
+ | uniplus* \
+ | unleashed* \
+ | unos* \
+ | uwin* \
+ | uxpv* \
+ | v88r* \
+ |*vms* \
+ | vos* \
+ | vsta* \
+ | vxsim* \
+ | vxworks* \
+ | wasi* \
+ | watchos* \
+ | wince* \
+ | windiss* \
+ | windows* \
+ | winnt* \
+ | xenix* \
+ | xray* \
+ | zephyr* \
+ | zvmoe* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
;;
+ # This refers to builds using the UEFI calling convention
+ # (which depends on the architecture) and PE file format.
+ # Note that this is both a different calling convention and
+ # different file format than that of GNU-EFI
+ # (x86_64-w64-mingw32).
+ uefi)
+ ;;
none)
;;
+ kernel* | msvc* )
+ # Restricted further below
+ ;;
+ '')
+ if test x"$obj" = x
+ then
+ echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2
+ fi
+ ;;
*)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+case $obj in
+ aout* | coff* | elf* | pe*)
+ ;;
+ '')
+ # empty is fine
+ ;;
+ *)
+ echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+ # The "javascript-unknown-ghcjs" triple is used by GHC; we
+ # accept it here in order to tolerate that, but reject any
+ # variations.
+ javascript-ghcjs)
+ ;;
+ javascript-* | *-ghcjs)
+ echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
+case $kernel-$os-$obj in
+ linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
+ | linux-mlibc*- | linux-musl*- | linux-newlib*- \
+ | linux-relibc*- | linux-uclibc*- | linux-ohos*- )
;;
- uclinux-uclibc* )
+ uclinux-uclibc*- | uclinux-gnu*- )
;;
- -dietlibc* | -newlib* | -musl* | -uclibc* )
+ managarm-mlibc*- | managarm-kernel*- )
+ ;;
+ windows*-msvc*-)
+ ;;
+ -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
+ | -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
+ -kernel*- )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+ exit 1
;;
- vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ *-kernel*- )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
+ exit 1
;;
- nto-qnx*)
+ *-msvc*- )
+ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+ exit 1
;;
- os2-emx)
+ kfreebsd*-gnu*- | knetbsd*-gnu*- | netbsd*-gnu*- | kopensolaris*-gnu*-)
+ ;;
+ vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
+ ;;
+ nto-qnx*-)
;;
- *-eabi* | *-gnueabi*)
+ os2-emx-)
;;
- -*)
+ rtmk-nova-)
+ ;;
+ *-eabi*- | *-gnueabi*-)
+ ;;
+ none--*)
+ # None (no kernel, i.e. freestanding / bare metal),
+ # can be paired with an machine code file format
+ ;;
+ -*-)
# Blank kernel with real OS is always fine.
;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ --*)
+ # Blank kernel and OS with real machine code file format is always fine.
+ ;;
+ *-*-*)
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
@@ -1792,7 +2273,7 @@ case $vendor in
*-riscix*)
vendor=acorn
;;
- *-sunos*)
+ *-sunos* | *-solaris*)
vendor=sun
;;
*-cnk* | *-aix*)
@@ -1862,7 +2343,7 @@ case $vendor in
;;
esac
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
diff --git a/autosetup/autosetup-find-tclsh b/autosetup/autosetup-find-tclsh
index 0029f17..f0fd98c 100755
--- a/autosetup/autosetup-find-tclsh
+++ b/autosetup/autosetup-find-tclsh
@@ -9,7 +9,7 @@ for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; d
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
- { $cc -o jimsh0 "$d/jimsh0.c"; } 2>/dev/null || continue
+ { $cc -o jimsh0 "$d/jimsh0.c"; } 2>&1 >/dev/null || continue
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
done
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
diff --git a/autosetup/cc.tcl b/autosetup/cc.tcl
index f45cc2e..05c1b1c 100644
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -5,7 +5,7 @@
#
# The 'cc' module supports checking various 'features' of the C or C++
# compiler/linker environment. Common commands are 'cc-check-includes',
-# 'cc-check-types', 'cc-check-functions', 'cc-with', 'make-config-header' and 'make-template'.
+# 'cc-check-types', 'cc-check-functions', 'cc-with' and 'make-config-header'
#
# The following environment variables are used if set:
#
@@ -677,80 +677,82 @@ proc calc-define-output-type {name spec} {
return ""
}
-# Initialise some values from the environment or commandline or default settings
-foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
- lassign $i var default
- define $var [get-env $var $default]
-}
+proc cc-init {} {
+ global autosetup
-if {[env-is-set CC]} {
- # Set by the user, so don't try anything else
- set try [list [get-env CC ""]]
-} else {
- # Try some reasonable options
- set try [list [get-define cross]cc [get-define cross]gcc]
-}
-define CC [find-an-executable {*}$try]
-if {[get-define CC] eq ""} {
- user-error "Could not find a C compiler. Tried: [join $try ", "]"
-}
+ # Initialise some values from the environment or commandline or default settings
+ foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
+ lassign $i var default
+ define $var [get-env $var $default]
+ }
-define CPP [get-env CPP "[get-define CC] -E"]
+ if {[env-is-set CC]} {
+ # Set by the user, so don't try anything else
+ set try [list [get-env CC ""]]
+ } else {
+ # Try some reasonable options
+ set try [list [get-define cross]cc [get-define cross]gcc]
+ }
+ define CC [find-an-executable {*}$try]
+ if {[get-define CC] eq ""} {
+ user-error "Could not find a C compiler. Tried: [join $try ", "]"
+ }
-# XXX: Could avoid looking for a C++ compiler until requested
-# If CXX isn't found, it is set to the empty string.
-if {[env-is-set CXX]} {
- define CXX [find-an-executable -required [get-env CXX ""]]
-} else {
- define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
-}
+ define CPP [get-env CPP "[get-define CC] -E"]
-# CXXFLAGS default to CFLAGS if not specified
-define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
+ # XXX: Could avoid looking for a C++ compiler until requested
+ # If CXX isn't found, it is set to the empty string.
+ if {[env-is-set CXX]} {
+ define CXX [find-an-executable -required [get-env CXX ""]]
+ } else {
+ define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
+ }
-# May need a CC_FOR_BUILD, so look for one
-define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
+ # CXXFLAGS default to CFLAGS if not specified
+ define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
-if {[get-define CC] eq ""} {
- user-error "Could not find a C compiler. Tried: [join $try ", "]"
-}
+ # May need a CC_FOR_BUILD, so look for one
+ define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
-# These start empty and never come from the user or environment
-define AS_CFLAGS ""
-define AS_CPPFLAGS ""
-define AS_CXXFLAGS ""
+ # These start empty and never come from the user or environment
+ define AS_CFLAGS ""
+ define AS_CPPFLAGS ""
+ define AS_CXXFLAGS ""
-define CCACHE [find-an-executable [get-env CCACHE ccache]]
+ define CCACHE [find-an-executable [get-env CCACHE ccache]]
-# If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
-foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
- if {[env-is-set $i]} {
- # Note: If the variable is set on the command line, get-env will return that value
- # so the command line will continue to override the environment
- define-append-argv AUTOREMAKE $i=[get-env $i ""]
+ # If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
+ foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
+ if {[env-is-set $i]} {
+ # Note: If the variable is set on the command line, get-env will return that value
+ # so the command line will continue to override the environment
+ define-append-argv AUTOREMAKE $i=[get-env $i ""]
+ }
}
-}
-# Initial cctest settings
-cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
-set autosetup(cc-include-deps) {}
+ # Initial cctest settings
+ cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
+ set autosetup(cc-include-deps) {}
-msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
-if {[get-define CXX] ne "false"} {
- msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
-}
-msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
-
-# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
-# but some compilers may not support it, so test here.
-switch -glob -- [get-define host] {
- *-*-darwin* {
- if {[cctest -cflags {-g0}]} {
- define cc-default-debug -g0
+ msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
+ if {[get-define CXX] ne "false"} {
+ msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
+ }
+ msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
+
+ # On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
+ # but some compilers may not support it, so test here.
+ switch -glob -- [get-define host] {
+ *-*-darwin* {
+ if {[cctest -cflags {-g0}]} {
+ define cc-default-debug -g0
+ }
}
}
-}
-if {![cc-check-includes stdlib.h]} {
- user-error "Compiler does not work. See config.log"
+ if {![cc-check-includes stdlib.h]} {
+ user-error "Compiler does not work. See config.log"
+ }
}
+
+cc-init
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index f3ec997..8f6f7ea 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -1,8 +1,9 @@
/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
-#define JIM_TCL_COMPAT
+#define JIM_COMPAT
#define JIM_ANSIC
#define JIM_REGEXP
#define HAVE_NO_AUTOCONF
+#define JIM_TINY
#define _JIMAUTOCONF_H
#define TCL_LIBRARY "."
#define jim_ext_bootstrap
@@ -12,7 +13,6 @@
#define jim_ext_file
#define jim_ext_glob
#define jim_ext_exec
-#define jim_ext_posix
#define jim_ext_clock
#define jim_ext_array
#define jim_ext_stdlib
@@ -62,7 +62,7 @@
#define HAVE_PIPE
#define _FILE_OFFSET_BITS 64
#endif
-#define JIM_VERSION 82
+#define JIM_VERSION 84
#ifndef JIM_WIN32COMPAT_H
#define JIM_WIN32COMPAT_H
@@ -95,6 +95,9 @@ char *dlerror(void);
#include <limits.h>
#define jim_wide _int64
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG
+#endif
#ifndef LLONG_MAX
#define LLONG_MAX 9223372036854775807I64
#endif
@@ -109,11 +112,7 @@ char *dlerror(void);
#include <io.h>
-struct timeval {
- long tv_sec;
- long tv_usec;
-};
-
+#include <winsock.h>
int gettimeofday(struct timeval *tv, void *unused);
#define HAVE_OPENDIR
@@ -576,7 +575,7 @@ typedef struct Jim_Interp {
Jim_Obj *result;
int unused_errorLine;
Jim_Obj *currentFilenameObj;
- int unused_addStackTrace;
+ int break_level;
int maxCallFrameDepth;
int maxEvalDepth;
int evalDepth;
@@ -720,6 +719,14 @@ JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr,
Jim_Obj **resObjPtrPtr, int flags);
+JIM_EXPORT Jim_Obj *Jim_GetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
+ int *lineptr);
+
+JIM_EXPORT void Jim_SetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
+ Jim_Obj *fileNameObj, int lineNumber);
+
+
+
JIM_EXPORT void Jim_InitStack(Jim_Stack *stack);
JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack);
JIM_EXPORT int Jim_StackLen(Jim_Stack *stack);
@@ -1155,7 +1162,7 @@ int Jim_OpenForWrite(const char *filename, int append);
int Jim_OpenForRead(const char *filename);
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(_WIN32)
#ifndef STRICT
#define STRICT
#endif
@@ -1190,6 +1197,7 @@ int Jim_OpenForRead(const char *filename);
#define Jim_Stat _stat64
#define Jim_FileStat _fstat64
#define Jim_Lseek _lseeki64
+ #define O_TEXT _O_TEXT
#else
#if defined(HAVE_STAT64)
@@ -1232,10 +1240,11 @@ int Jim_OpenForRead(const char *filename);
#define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
#endif
#endif
-#endif
-#ifndef O_TEXT
-#define O_TEXT 0
+ #ifndef O_TEXT
+ #define O_TEXT 0
+ #endif
+
#endif
@@ -1284,8 +1293,14 @@ int Jim_initjimshInit(Jim_Interp *interp)
" if {[string match \"*/*\" $jim::argv0]} {\n"
" set jim::exe [file join [pwd] $jim::argv0]\n"
" } else {\n"
-" foreach path [split [env PATH \"\"] $tcl_platform(pathSeparator)] {\n"
-" set exec [file join [pwd] [string map {\\\\ /} $path] $jim::argv0]\n"
+" set jim::argv0 [file tail $jim::argv0]\n"
+" set path [split [env PATH \"\"] $tcl_platform(pathSeparator)]\n"
+" if {$tcl_platform(platform) eq \"windows\"} {\n"
+"\n"
+" set path [lmap p [list \"\" {*}$path] { string map {\\\\ /} $p }]\n"
+" }\n"
+" foreach p $path {\n"
+" set exec [file join [pwd] $p $jim::argv0]\n"
" if {[file executable $exec]} {\n"
" set jim::exe $exec\n"
" break\n"
@@ -1938,9 +1953,6 @@ int Jim_tclcompatInit(Jim_Interp *interp)
" if {$cmd eq \"pid\"} {\n"
" return $pids\n"
" }\n"
-" if {$cmd eq \"getfd\"} {\n"
-" $f getfd\n"
-" }\n"
" if {$cmd eq \"close\"} {\n"
" $f close\n"
"\n"
@@ -2040,8 +2052,8 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define AIO_CMD_LEN 32
-#define AIO_BUF_LEN 256
-#define AIO_WBUF_FULL_SIZE (64 * 1024)
+#define AIO_DEFAULT_RBUF_LEN 256
+#define AIO_DEFAULT_WBUF_LIMIT (64 * 1024)
#define AIO_KEEPOPEN 1
#define AIO_NODELETE 2
@@ -2049,6 +2061,8 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define AIO_WBUF_NONE 8
#define AIO_NONBLOCK 16
+#define AIO_ONEREAD 32
+
enum wbuftype {
WBUF_OPT_NONE,
WBUF_OPT_LINE,
@@ -2123,11 +2137,20 @@ typedef struct AioFile
const JimAioFopsType *fops;
Jim_Obj *readbuf;
Jim_Obj *writebuf;
+ char *rbuf;
+ size_t rbuf_len;
+ size_t wbuf_limit;
} AioFile;
+static void aio_consume(Jim_Obj *objPtr, int n);
+
static int stdio_writer(struct AioFile *af, const char *buf, int len)
{
- return write(af->fd, buf, len);
+ int ret = write(af->fd, buf, len);
+ if (ret < 0 && errno == EPIPE) {
+ aio_consume(af->writebuf, Jim_Length(af->writebuf));
+ }
+ return ret;
}
static int stdio_reader(struct AioFile *af, char *buf, int len, int nb)
@@ -2264,7 +2287,22 @@ static void aio_consume(Jim_Obj *objPtr, int n)
}
-static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask);
+static int aio_flush(Jim_Interp *interp, AioFile *af);
+
+#ifdef jim_ext_eventloop
+static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask)
+{
+ AioFile *af = clientData;
+
+ aio_flush(interp, af);
+ if (Jim_Length(af->writebuf) == 0) {
+
+ return -1;
+ }
+ return 0;
+}
+#endif
+
static int aio_flush(Jim_Interp *interp, AioFile *af)
{
@@ -2299,19 +2337,7 @@ static int aio_flush(Jim_Interp *interp, AioFile *af)
return JIM_OK;
}
-static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask)
-{
- AioFile *af = clientData;
-
- aio_flush(interp, af);
- if (Jim_Length(af->writebuf) == 0) {
-
- return -1;
- }
- return 0;
-}
-
-static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size_t buflen, int neededLen)
+static int aio_read_len(Jim_Interp *interp, AioFile *af, unsigned flags, int neededLen)
{
if (!af->readbuf) {
af->readbuf = Jim_NewStringObj(interp, NULL, 0);
@@ -2329,25 +2355,32 @@ static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size
int readlen;
if (neededLen == -1) {
- readlen = AIO_BUF_LEN;
+ readlen = af->rbuf_len;
}
else {
- readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
+ readlen = (neededLen > af->rbuf_len ? af->rbuf_len : neededLen);
+ }
+
+ if (!af->rbuf) {
+ af->rbuf = Jim_Alloc(af->rbuf_len);
}
- retval = af->fops->reader(af, buf, readlen, nb);
+ retval = af->fops->reader(af, af->rbuf, readlen, flags & AIO_NONBLOCK);
if (retval > 0) {
- Jim_AppendString(interp, af->readbuf, buf, retval);
+ if (retval) {
+ Jim_AppendString(interp, af->readbuf, af->rbuf, retval);
+ }
if (neededLen != -1) {
neededLen -= retval;
}
+ if (flags & AIO_ONEREAD) {
+ return JIM_OK;
+ }
continue;
}
- if (JimCheckStreamError(interp, af)) {
+ if ((flags & AIO_ONEREAD) || JimCheckStreamError(interp, af)) {
return JIM_ERR;
}
- if (nb || af->timeout) {
- return JIM_OK;
- }
+ break;
}
return JIM_OK;
@@ -2415,6 +2448,7 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
Jim_FreeNewObj(interp, af->readbuf);
}
+ Jim_Free(af->rbuf);
Jim_Free(af);
}
@@ -2428,7 +2462,6 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int option;
int nb;
Jim_Obj *objPtr;
- char buf[AIO_BUF_LEN];
if (argc) {
if (*Jim_String(argv[0]) == '-') {
@@ -2462,7 +2495,7 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
nb = aio_start_nonblocking(af);
- if (aio_read_len(interp, af, nb, buf, sizeof(buf), neededLen) != JIM_OK) {
+ if (aio_read_len(interp, af, nb ? AIO_NONBLOCK : 0, neededLen) != JIM_OK) {
aio_set_nonblocking(af, nb);
return JIM_ERR;
}
@@ -2517,11 +2550,6 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
AioFile *af = Jim_CmdPrivData(interp);
jim_wide count = 0;
jim_wide maxlen = JIM_WIDE_MAX;
-
- char buf[AIO_BUF_LEN];
-
- char *bufp = buf;
- int buflen = sizeof(buf);
int ok = 1;
Jim_Obj *objv[4];
@@ -2547,10 +2575,10 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
while (count < maxlen) {
jim_wide len = maxlen - count;
- if (len > buflen) {
- len = buflen;
+ if (len > af->rbuf_len) {
+ len = af->rbuf_len;
}
- if (aio_read_len(interp, af, 0, bufp, buflen, len) != JIM_OK) {
+ if (aio_read_len(interp, af, 0, len) != JIM_OK) {
ok = 0;
break;
}
@@ -2563,17 +2591,13 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (aio_eof(af)) {
break;
}
- if (count >= 16384 && bufp == buf) {
+ if (count >= 16384 && af->rbuf_len < 65536) {
- buflen = 65536;
- bufp = Jim_Alloc(buflen);
+ af->rbuf_len = 65536;
+ af->rbuf = Jim_Realloc(af->rbuf, af->rbuf_len);
}
}
- if (bufp != buf) {
- Jim_Free(bufp);
- }
-
Jim_DecrRefCount(interp, objv[1]);
Jim_DecrRefCount(interp, objv[2]);
@@ -2589,10 +2613,10 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- char buf[AIO_BUF_LEN];
Jim_Obj *objPtr = NULL;
int len;
int nb;
+ unsigned flags = AIO_ONEREAD;
char *nl = NULL;
int offset = 0;
@@ -2600,38 +2624,33 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
nb = aio_start_nonblocking(af);
-
- if (!af->readbuf) {
- af->readbuf = Jim_NewStringObj(interp, NULL, 0);
+ if (nb) {
+ flags |= AIO_NONBLOCK;
}
while (!aio_eof(af)) {
- const char *pt = Jim_GetString(af->readbuf, &len);
- nl = memchr(pt + offset, '\n', len - offset);
- if (nl) {
+ if (af->readbuf) {
+ const char *pt = Jim_GetString(af->readbuf, &len);
+ nl = memchr(pt + offset, '\n', len - offset);
+ if (nl) {
- objPtr = Jim_NewStringObj(interp, pt, nl - pt);
-
- aio_consume(af->readbuf, nl - pt + 1);
- break;
- }
-
- offset = len;
- len = af->fops->reader(af, buf, AIO_BUF_LEN, nb);
- if (len <= 0) {
- if (nb || af->timeout) {
+ objPtr = Jim_NewStringObj(interp, pt, nl - pt);
+ aio_consume(af->readbuf, nl - pt + 1);
break;
}
+ offset = len;
}
- else {
- Jim_AppendString(interp, af->readbuf, buf, len);
+
+
+ if (aio_read_len(interp, af, flags, -1) != JIM_OK) {
+ break;
}
}
aio_set_nonblocking(af, nb);
- if (!nl && aio_eof(af)) {
+ if (!nl && aio_eof(af) && af->readbuf) {
objPtr = af->readbuf;
af->readbuf = NULL;
@@ -2680,6 +2699,13 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
strObj = argv[0];
}
+#ifdef JIM_MAINTAINER
+ if (Jim_IsShared(af->writebuf)) {
+ Jim_DecrRefCount(interp, af->writebuf);
+ af->writebuf = Jim_DuplicateObj(interp, af->writebuf);
+ Jim_IncrRefCount(af->writebuf);
+ }
+#endif
Jim_AppendObj(interp, af->writebuf, strObj);
if (nl) {
Jim_AppendString(interp, af->writebuf, "\n", 1);
@@ -2701,7 +2727,7 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
break;
case WBUF_OPT_FULL:
- if (wlen >= AIO_WBUF_FULL_SIZE) {
+ if (wlen >= af->wbuf_limit) {
wnow = 1;
}
break;
@@ -2870,6 +2896,7 @@ static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
+ Jim_Obj *resultObj;
static const char * const options[] = {
"none",
@@ -2878,17 +2905,57 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
NULL
};
- if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) {
- return JIM_ERR;
+ if (argc) {
+ if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+
+ if (af->wbuft == WBUF_OPT_FULL && argc == 2) {
+ long l;
+ if (Jim_GetLong(interp, argv[1], &l) != JIM_OK || l <= 0) {
+ return JIM_ERR;
+ }
+ af->wbuf_limit = l;
+ }
+
+ if (af->wbuft == WBUF_OPT_NONE) {
+ if (aio_flush(interp, af) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+
}
- if (af->wbuft == WBUF_OPT_NONE) {
- return aio_flush(interp, af);
+ resultObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, resultObj, Jim_NewStringObj(interp, options[af->wbuft], -1));
+ if (af->wbuft == WBUF_OPT_FULL) {
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, af->wbuf_limit));
}
+ Jim_SetResult(interp, resultObj);
return JIM_OK;
}
+static int aio_cmd_readsize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ if (argc) {
+ long l;
+ if (Jim_GetLong(interp, argv[0], &l) != JIM_OK || l <= 0) {
+ return JIM_ERR;
+ }
+ af->rbuf_len = l;
+ if (af->rbuf) {
+ af->rbuf = Jim_Realloc(af->rbuf, af->rbuf_len);
+ }
+ }
+ Jim_SetResultInt(interp, af->rbuf_len);
+
+ return JIM_OK;
+}
+
+#ifdef jim_ext_eventloop
static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef HAVE_SELECT
@@ -2906,7 +2973,6 @@ static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
#endif
}
-#ifdef jim_ext_eventloop
static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask,
int argc, Jim_Obj * const *argv)
{
@@ -3074,9 +3140,16 @@ static const jim_subcmd_type aio_command_table[] = {
},
#endif
{ "buffering",
- "none|line|full",
+ "?none|line|full? ?size?",
aio_cmd_buffering,
- 1,
+ 0,
+ 2,
+
+ },
+ { "readsize",
+ "?size?",
+ aio_cmd_readsize,
+ 0,
1,
},
@@ -3319,6 +3392,9 @@ static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
af->writebuf = Jim_NewStringObj(interp, NULL, 0);
Jim_IncrRefCount(af->writebuf);
+ af->wbuf_limit = AIO_DEFAULT_WBUF_LIMIT;
+ af->rbuf_len = AIO_DEFAULT_RBUF_LEN;
+
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
@@ -3772,27 +3848,30 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int regcomp_flags = 0;
int regexec_flags = 0;
int opt_all = 0;
+ int opt_command = 0;
int offset = 0;
regex_t *regex;
const char *p;
- int result;
+ int result = JIM_OK;
regmatch_t pmatch[MAX_SUB_MATCHES + 1];
int num_matches = 0;
int i, j, n;
Jim_Obj *varname;
Jim_Obj *resultObj;
+ Jim_Obj *cmd_prefix = NULL;
+ Jim_Obj *regcomp_obj = NULL;
const char *source_str;
int source_len;
- const char *replace_str;
+ const char *replace_str = NULL;
int replace_len;
const char *pattern;
int option;
enum {
- OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END
+ OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_COMMAND, OPT_END
};
static const char * const options[] = {
- "-nocase", "-line", "-all", "-start", "--", NULL
+ "-nocase", "-line", "-all", "-start", "-command", "--", NULL
};
if (argc < 4) {
@@ -3836,20 +3915,39 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
break;
+
+ case OPT_COMMAND:
+ opt_command = 1;
+ break;
}
}
if (argc - i != 3 && argc - i != 4) {
goto wrongNumArgs;
}
- regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
+
+ regcomp_obj = Jim_DuplicateObj(interp, argv[i]);
+ Jim_IncrRefCount(regcomp_obj);
+ regex = SetRegexpFromAny(interp, regcomp_obj, regcomp_flags);
if (!regex) {
+ Jim_DecrRefCount(interp, regcomp_obj);
return JIM_ERR;
}
pattern = Jim_String(argv[i]);
source_str = Jim_GetString(argv[i + 1], &source_len);
- replace_str = Jim_GetString(argv[i + 2], &replace_len);
+ if (opt_command) {
+ cmd_prefix = argv[i + 2];
+ if (Jim_ListLength(interp, cmd_prefix) == 0) {
+ Jim_SetResultString(interp, "command prefix must be a list of at least one element", -1);
+ Jim_DecrRefCount(interp, regcomp_obj);
+ return JIM_ERR;
+ }
+ Jim_IncrRefCount(cmd_prefix);
+ }
+ else {
+ replace_str = Jim_GetString(argv[i + 2], &replace_len);
+ }
varname = argv[i + 3];
@@ -3893,35 +3991,58 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
+ if (opt_command) {
- for (j = 0; j < replace_len; j++) {
- int idx;
- int c = replace_str[j];
+ Jim_Obj *cmdListObj = Jim_DuplicateObj(interp, cmd_prefix);
+ for (j = 0; j < MAX_SUB_MATCHES; j++) {
+ if (pmatch[j].rm_so == -1) {
+ break;
+ }
+ else {
+ Jim_Obj *srcObj = Jim_NewStringObj(interp, p + pmatch[j].rm_so, pmatch[j].rm_eo - pmatch[j].rm_so);
+ Jim_ListAppendElement(interp, cmdListObj, srcObj);
+ }
+ }
+ Jim_IncrRefCount(cmdListObj);
- if (c == '&') {
- idx = 0;
+ result = Jim_EvalObj(interp, cmdListObj);
+ Jim_DecrRefCount(interp, cmdListObj);
+ if (result != JIM_OK) {
+ goto cmd_error;
}
- else if (c == '\\' && j < replace_len) {
- c = replace_str[++j];
- if ((c >= '0') && (c <= '9')) {
- idx = c - '0';
+ Jim_AppendString(interp, resultObj, Jim_String(Jim_GetResult(interp)), -1);
+ }
+ else {
+
+ for (j = 0; j < replace_len; j++) {
+ int idx;
+ int c = replace_str[j];
+
+ if (c == '&') {
+ idx = 0;
}
- else if ((c == '\\') || (c == '&')) {
- Jim_AppendString(interp, resultObj, replace_str + j, 1);
- continue;
+ else if (c == '\\' && j < replace_len) {
+ c = replace_str[++j];
+ if ((c >= '0') && (c <= '9')) {
+ idx = c - '0';
+ }
+ else if ((c == '\\') || (c == '&')) {
+ Jim_AppendString(interp, resultObj, replace_str + j, 1);
+ continue;
+ }
+ else {
+ Jim_AppendString(interp, resultObj, replace_str + j - 1, (j == replace_len) ? 1 : 2);
+ continue;
+ }
}
else {
- Jim_AppendString(interp, resultObj, replace_str + j - 1, (j == replace_len) ? 1 : 2);
+ Jim_AppendString(interp, resultObj, replace_str + j, 1);
continue;
}
- }
- else {
- Jim_AppendString(interp, resultObj, replace_str + j, 1);
- continue;
- }
- if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) {
- Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so,
- pmatch[idx].rm_eo - pmatch[idx].rm_so);
+ if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) {
+ Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so,
+ pmatch[idx].rm_eo - pmatch[idx].rm_so);
+ }
}
}
@@ -3958,22 +4079,34 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_AppendString(interp, resultObj, p, -1);
+cmd_error:
+ if (result == JIM_OK) {
- if (argc - i == 4) {
- result = Jim_SetVariable(interp, varname, resultObj);
+ if (argc - i == 4) {
+ result = Jim_SetVariable(interp, varname, resultObj);
- if (result == JIM_OK) {
- Jim_SetResultInt(interp, num_matches);
+ if (result == JIM_OK) {
+ Jim_SetResultInt(interp, num_matches);
+ }
+ else {
+ Jim_FreeObj(interp, resultObj);
+ }
}
else {
- Jim_FreeObj(interp, resultObj);
+ Jim_SetResult(interp, resultObj);
+ result = JIM_OK;
}
}
else {
- Jim_SetResult(interp, resultObj);
- result = JIM_OK;
+ Jim_FreeObj(interp, resultObj);
+ }
+
+ if (opt_command) {
+ Jim_DecrRefCount(interp, cmd_prefix);
}
+ Jim_DecrRefCount(interp, regcomp_obj);
+
return result;
}
@@ -6355,6 +6488,7 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
+ tm.tm_isdst = options.gmt ? 0 : -1;
Jim_SetResultInt(interp, options.gmt ? jim_timegm(&tm) : mktime(&tm));
return JIM_OK;
@@ -6659,53 +6793,6 @@ int Jim_arrayInit(Jim_Interp *interp)
Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
return JIM_OK;
}
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-
-#ifdef HAVE_SYS_SYSINFO_H
-#include <sys/sysinfo.h>
-#endif
-
-static void Jim_PosixSetError(Jim_Interp *interp)
-{
- Jim_SetResultString(interp, strerror(errno), -1);
-}
-
-#if defined(HAVE_FORK)
-static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- pid_t pid;
-
- JIM_NOTUSED(argv);
-
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
- return JIM_ERR;
- }
- if ((pid = fork()) == -1) {
- Jim_PosixSetError(interp);
- return JIM_ERR;
- }
- Jim_SetResultInt(interp, (jim_wide) pid);
- return JIM_OK;
-}
-#endif
-
-
-int Jim_posixInit(Jim_Interp *interp)
-{
- Jim_PackageProvideCheck(interp, "posix");
-#ifdef HAVE_FORK
- Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL);
-#endif
- return JIM_OK;
-}
int Jim_InitStaticExtensions(Jim_Interp *interp)
{
extern int Jim_bootstrapInit(Jim_Interp *);
@@ -6715,7 +6802,6 @@ extern int Jim_regexpInit(Jim_Interp *);
extern int Jim_fileInit(Jim_Interp *);
extern int Jim_globInit(Jim_Interp *);
extern int Jim_execInit(Jim_Interp *);
-extern int Jim_posixInit(Jim_Interp *);
extern int Jim_clockInit(Jim_Interp *);
extern int Jim_arrayInit(Jim_Interp *);
extern int Jim_stdlibInit(Jim_Interp *);
@@ -6727,14 +6813,15 @@ Jim_regexpInit(interp);
Jim_fileInit(interp);
Jim_globInit(interp);
Jim_execInit(interp);
-Jim_posixInit(interp);
Jim_clockInit(interp);
Jim_arrayInit(interp);
Jim_stdlibInit(interp);
Jim_tclcompatInit(interp);
return JIM_OK;
}
+#ifndef JIM_TINY
#define JIM_OPTIMIZATION
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -6794,7 +6881,9 @@ return JIM_OK;
#define JIM_INTEGER_SPACE 24
-const char *jim_tt_name(int type);
+#if defined(DEBUG_SHOW_SCRIPT) || defined(DEBUG_SHOW_SCRIPT_TOKENS) || defined(JIM_DEBUG_COMMAND) || defined(DEBUG_SHOW_SUBST)
+static const char *jim_tt_name(int type);
+#endif
#ifdef JIM_DEBUG_PANIC
static void JimPanicDump(int fail_condition, const char *fmt, ...);
@@ -6830,7 +6919,6 @@ static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv);
static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr);
-static void JimSetErrorStack(Jim_Interp *interp);
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
#define JIM_DICT_SUGAR 100
@@ -7809,6 +7897,7 @@ struct JimParserCtx
int inquote;
int comment;
struct JimParseMissing missing;
+ const char *errmsg;
};
static int JimParseScript(struct JimParserCtx *pc);
@@ -9509,17 +9598,6 @@ void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
}
-static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
- Jim_Obj *fileNameObj, int lineNumber)
-{
- JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
- JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
- Jim_IncrRefCount(fileNameObj);
- objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
- objPtr->internalRep.sourceValue.lineNumber = lineNumber;
- objPtr->typePtr = &sourceObjType;
-}
-
static const Jim_ObjType scriptLineObjType = {
"scriptline",
NULL,
@@ -9580,6 +9658,7 @@ typedef struct ScriptObj
static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
static int JimParseCheckMissing(Jim_Interp *interp, int ch);
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
+static void JimSetErrorStack(Jim_Interp *interp, ScriptObj *script);
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
@@ -9795,7 +9874,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
token->objPtr = JimMakeScriptObj(interp, t);
Jim_IncrRefCount(token->objPtr);
- JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line);
+ Jim_SetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line);
token++;
}
}
@@ -9855,6 +9934,39 @@ static int JimParseCheckMissing(Jim_Interp *interp, int ch)
return JIM_ERR;
}
+Jim_Obj *Jim_GetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, int *lineptr)
+{
+ int line;
+ Jim_Obj *fileNameObj;
+
+ if (objPtr->typePtr == &sourceObjType) {
+ fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
+ line = objPtr->internalRep.sourceValue.lineNumber;
+ }
+ else if (objPtr->typePtr == &scriptObjType) {
+ ScriptObj *script = JimGetScript(interp, objPtr);
+ fileNameObj = script->fileNameObj;
+ line = script->firstline;
+ }
+ else {
+ fileNameObj = interp->emptyObj;
+ line = 1;
+ }
+ *lineptr = line;
+ return fileNameObj;
+}
+
+void Jim_SetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
+ Jim_Obj *fileNameObj, int lineNumber)
+{
+ JimPanic((Jim_IsShared(objPtr), "Jim_SetSourceInfo called with shared object"));
+ Jim_FreeIntRep(interp, objPtr);
+ Jim_IncrRefCount(fileNameObj);
+ objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
+ objPtr->internalRep.sourceValue.lineNumber = lineNumber;
+ objPtr->typePtr = &sourceObjType;
+}
+
static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
ParseTokenList *tokenlist)
{
@@ -9883,12 +9995,11 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
struct JimParserCtx parser;
struct ScriptObj *script;
ParseTokenList tokenlist;
- int line = 1;
+ Jim_Obj *fileNameObj;
+ int line;
- if (objPtr->typePtr == &sourceObjType) {
- line = objPtr->internalRep.sourceValue.lineNumber;
- }
+ fileNameObj = Jim_GetSourceInfo(interp, objPtr, &line);
ScriptTokenListInit(&tokenlist);
@@ -9907,12 +10018,7 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
script = Jim_Alloc(sizeof(*script));
memset(script, 0, sizeof(*script));
script->inUse = 1;
- if (objPtr->typePtr == &sourceObjType) {
- script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
- }
- else {
- script->fileNameObj = interp->emptyObj;
- }
+ script->fileNameObj = fileNameObj;
Jim_IncrRefCount(script->fileNameObj);
script->missing = parser.missing.ch;
script->linenr = parser.missing.line;
@@ -11377,6 +11483,9 @@ void Jim_FreeInterp(Jim_Interp *i)
JimFreeCallFrame(i, cf, JIM_FCF_FULL);
}
+
+ Jim_FreeHashTable(&i->commands);
+
Jim_DecrRefCount(i, i->emptyObj);
Jim_DecrRefCount(i, i->trueObj);
Jim_DecrRefCount(i, i->falseObj);
@@ -11391,7 +11500,6 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_InterpIncrProcEpoch(i);
- Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
Jim_FreeHashTable(&i->references);
#endif
@@ -11590,16 +11698,24 @@ static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
interp->errorFlag = 1;
}
-static void JimSetErrorStack(Jim_Interp *interp)
+static void JimSetErrorStack(Jim_Interp *interp, ScriptObj *script)
{
if (!interp->errorFlag) {
int i;
Jim_Obj *stackTrace = Jim_NewListObj(interp, NULL, 0);
- for (i = 0; i <= interp->procLevel; i++) {
- Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
- if (frame) {
- JimAddStackFrame(interp, frame, stackTrace);
+ if (interp->procLevel == 0 && script) {
+ Jim_ListAppendElement(interp, stackTrace, interp->emptyObj);
+ Jim_ListAppendElement(interp, stackTrace, script->fileNameObj);
+ Jim_ListAppendElement(interp, stackTrace, Jim_NewIntObj(interp, script->linenr));
+ Jim_ListAppendElement(interp, stackTrace, interp->emptyObj);
+ }
+ else {
+ for (i = 0; i <= interp->procLevel; i++) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
+ if (frame) {
+ JimAddStackFrame(interp, frame, stackTrace);
+ }
}
}
JimSetStackTrace(interp, stackTrace);
@@ -12290,14 +12406,7 @@ static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
- if (objPtr->typePtr == &sourceObjType) {
- fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
- linenr = objPtr->internalRep.sourceValue.lineNumber;
- }
- else {
- fileNameObj = interp->emptyObj;
- linenr = 1;
- }
+ fileNameObj = Jim_GetSourceInfo(interp, objPtr, &linenr);
Jim_IncrRefCount(fileNameObj);
@@ -12319,7 +12428,7 @@ static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC)
continue;
elementPtr = JimParserGetTokenObj(interp, &parser);
- JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
+ Jim_SetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
ListAppendElement(objPtr, elementPtr);
}
}
@@ -12374,7 +12483,8 @@ struct lsort_info {
JIM_LSORT_NOCASE,
JIM_LSORT_INTEGER,
JIM_LSORT_REAL,
- JIM_LSORT_COMMAND
+ JIM_LSORT_COMMAND,
+ JIM_LSORT_DICT
} type;
int order;
Jim_Obj **indexv;
@@ -12407,6 +12517,43 @@ static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order;
}
+static int ListSortDict(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+
+ const char *left = Jim_String(*lhsObj);
+ const char *right = Jim_String(*rhsObj);
+
+ while (1) {
+ if (isdigit(UCHAR(*left)) && isdigit(UCHAR(*right))) {
+
+ jim_wide lint, rint;
+ char *lend, *rend;
+ lint = jim_strtoull(left, &lend);
+ rint = jim_strtoull(right, &rend);
+ if (lint != rint) {
+ return JimSign(lint - rint) * sort_info->order;
+ }
+ if (lend -left != rend - right) {
+ return JimSign((lend - left) - (rend - right)) * sort_info->order;
+ }
+ left = lend;
+ right = rend;
+ }
+ else {
+ int cl, cr;
+ left += utf8_tounicode_case(left, &cl, 1);
+ right += utf8_tounicode_case(right, &cr, 1);
+ if (cl != cr) {
+ return JimSign(cl - cr) * sort_info->order;
+ }
+ if (cl == 0) {
+
+ return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order;
+ }
+ }
+ }
+}
+
static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
jim_wide lhs = 0, rhs = 0;
@@ -12521,6 +12668,9 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
case JIM_LSORT_COMMAND:
fn = ListSortCommand;
break;
+ case JIM_LSORT_DICT:
+ fn = ListSortDict;
+ break;
default:
fn = NULL;
JimPanic((1, "ListSort called with invalid sort type"));
@@ -12570,6 +12720,11 @@ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *co
int i;
Jim_Obj **point;
+ if (elemc == 0) {
+
+ return;
+ }
+
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
if (currentLen) {
@@ -14334,6 +14489,8 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
static int JimParseExpression(struct JimParserCtx *pc)
{
+ pc->errmsg = NULL;
+
while (1) {
while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
@@ -14384,6 +14541,7 @@ singlechar:
else {
if (pc->tt == JIM_TT_EXPRSUGAR) {
+ pc->errmsg = "nesting expr in expr is not allowed";
return JIM_ERR;
}
return JIM_OK;
@@ -14528,6 +14686,7 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
p++;
}
if (*p != '(') {
+ pc->errmsg = "function requires parentheses";
return JIM_ERR;
}
}
@@ -14539,31 +14698,6 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
return JIM_OK;
}
-const char *jim_tt_name(int type)
-{
- static const char * const tt_names[JIM_TT_EXPR_OP] =
- { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
- "DBL", "BOO", "$()" };
- if (type < JIM_TT_EXPR_OP) {
- return tt_names[type];
- }
- else if (type == JIM_EXPROP_UNARYMINUS) {
- return "-VE";
- }
- else if (type == JIM_EXPROP_UNARYPLUS) {
- return "+VE";
- }
- else {
- const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
- static char buf[20];
-
- if (op->name) {
- return op->name;
- }
- sprintf(buf, "(%d)", type);
- return buf;
- }
-}
static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -14869,7 +15003,7 @@ missingoperand:
objPtr = Jim_NewStringObj(interp, t->token, t->len);
if (t->type == JIM_TT_CMD) {
- JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line);
+ Jim_SetSourceInfo(interp, objPtr, builder->fileNameObj, t->line);
}
}
@@ -14967,14 +15101,7 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
int rc = JIM_ERR;
- if (objPtr->typePtr == &sourceObjType) {
- fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
- line = objPtr->internalRep.sourceValue.lineNumber;
- }
- else {
- fileNameObj = interp->emptyObj;
- line = 1;
- }
+ fileNameObj = Jim_GetSourceInfo(interp, objPtr, &line);
Jim_IncrRefCount(fileNameObj);
exprText = Jim_GetString(objPtr, &exprTextLen);
@@ -14987,6 +15114,9 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
if (JimParseExpression(&parser) != JIM_OK) {
ScriptTokenListFree(&tokenlist);
Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
+ if (parser.errmsg) {
+ Jim_AppendStrings(interp, Jim_GetResult(interp), ": ", parser.errmsg, NULL);
+ }
expr = NULL;
goto err;
}
@@ -15006,10 +15136,17 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
#endif
- if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
+ if (tokenlist.count <= 1) {
+ Jim_SetResultString(interp, "empty expression", -1);
+ rc = JIM_ERR;
+ }
+ else {
+ rc = JimParseCheckMissing(interp, parser.missing.ch);
+ }
+ if (rc != JIM_OK) {
ScriptTokenListFree(&tokenlist);
Jim_DecrRefCount(interp, fileNameObj);
- return JIM_ERR;
+ return rc;
}
@@ -15860,13 +15997,18 @@ static int JimTraceCallback(Jim_Interp *interp, const char *type, int argc, Jim_
Jim_Obj *nargv[7];
Jim_Obj *traceCmdObj = interp->traceCmdObj;
Jim_Obj *resultObj = Jim_GetResult(interp);
+ ScriptObj *script = NULL;
- ScriptObj *script = JimGetScript(interp, interp->evalFrame->scriptObj);
+
+
+ if (interp->evalFrame->scriptObj) {
+ script = JimGetScript(interp, interp->evalFrame->scriptObj);
+ }
nargv[0] = traceCmdObj;
nargv[1] = Jim_NewStringObj(interp, type, -1);
- nargv[2] = script->fileNameObj;
- nargv[3] = Jim_NewIntObj(interp, script->linenr);
+ nargv[2] = script ? script->fileNameObj : interp->emptyObj;
+ nargv[3] = Jim_NewIntObj(interp, script ? script->linenr : 1);
nargv[4] = resultObj;
nargv[5] = argv[0];
nargv[6] = Jim_NewListObj(interp, argv + 1, argc - 1);
@@ -15988,7 +16130,7 @@ tailcall:
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
}
if (retcode == JIM_ERR) {
- JimSetErrorStack(interp);
+ JimSetErrorStack(interp, NULL);
}
}
@@ -16023,7 +16165,7 @@ out:
JimDecrCmdRefCount(interp, cmdPtr);
if (retcode == JIM_ERR) {
- JimSetErrorStack(interp);
+ JimSetErrorStack(interp, NULL);
}
if (interp->framePtr->tailcallObj) {
@@ -16045,6 +16187,7 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
for (i = 0; i < objc; i++)
Jim_IncrRefCount(objv[i]);
+
JimPushEvalFrame(interp, &frame, NULL);
retcode = JimInvokeCommand(interp, objc, objv);
@@ -16183,7 +16326,9 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
}
else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
- JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
+ int line;
+ Jim_Obj *fileNameObj = Jim_GetSourceInfo(interp, intv[0], &line);
+ Jim_SetSourceInfo(interp, objPtr, fileNameObj, line);
}
@@ -16250,7 +16395,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
Jim_IncrRefCount(scriptObjPtr);
script = JimGetScript(interp, scriptObjPtr);
if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
- JimSetErrorStack(interp);
+ JimSetErrorStack(interp, script);
Jim_DecrRefCount(interp, scriptObjPtr);
return JIM_ERR;
}
@@ -16422,7 +16567,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
if (retcode == JIM_ERR) {
- JimSetErrorStack(interp);
+ JimSetErrorStack(interp, NULL);
}
JimPopEvalFrame(interp);
@@ -16650,7 +16795,7 @@ int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const c
scriptObjPtr = Jim_NewStringObj(interp, script, -1);
Jim_IncrRefCount(scriptObjPtr);
if (filename) {
- JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
+ Jim_SetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
}
retval = Jim_EvalObj(interp, scriptObjPtr);
Jim_DecrRefCount(interp, scriptObjPtr);
@@ -16732,7 +16877,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
}
filenameObj = Jim_NewStringObj(interp, filename, -1);
- JimSetSourceInfo(interp, scriptObjPtr, filenameObj, 1);
+ Jim_SetSourceInfo(interp, scriptObjPtr, filenameObj, 1);
oldFilenameObj = JimPushInterpObj(interp->currentFilenameObj, filenameObj);
@@ -16773,7 +16918,9 @@ static void JimParseSubst(struct JimParserCtx *pc, int flags)
}
pc->tstart = pc->p;
- flags |= JIM_SUBST_NOVAR;
+
+ pc->p++;
+ pc->len--;
}
while (pc->len) {
if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
@@ -17276,7 +17423,7 @@ static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
static int JimCheckLoopRetcode(Jim_Interp *interp, int retval)
{
if (retval == JIM_BREAK || retval == JIM_CONTINUE) {
- if (--interp->returnLevel > 0) {
+ if (--interp->break_level > 0) {
return 1;
}
}
@@ -17466,15 +17613,14 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
retval = Jim_EvalObj(interp, argv[4]);
-
+ if (JimCheckLoopRetcode(interp, retval)) {
+ immediate++;
+ break;
+ }
if (retval == JIM_OK || retval == JIM_CONTINUE) {
JIM_IF_OPTIM(evalnext:)
retval = Jim_EvalObj(interp, argv[3]);
- if (JimCheckLoopRetcode(interp, retval)) {
- immediate++;
- goto out;
- }
if (retval == JIM_OK || retval == JIM_CONTINUE) {
JIM_IF_OPTIM(testcond:)
@@ -17505,7 +17651,7 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
{
int retval;
jim_wide i;
- jim_wide limit;
+ jim_wide limit = 0;
jim_wide incr = 1;
Jim_Obj *bodyObjPtr;
@@ -18329,17 +18475,19 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
{
static const char * const options[] = {
"-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique",
- "-stride", NULL
+ "-stride", "-dictionary", NULL
};
enum {
OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE,
- OPT_STRIDE
+ OPT_STRIDE, OPT_DICT
};
Jim_Obj *resObj;
int i;
int retCode;
int shared;
long stride = 1;
+ Jim_Obj **elements;
+ int listlen;
struct lsort_info info;
@@ -18366,6 +18514,9 @@ wrongargs:
case OPT_ASCII:
info.type = JIM_LSORT_ASCII;
break;
+ case OPT_DICT:
+ info.type = JIM_LSORT_DICT;
+ break;
case OPT_NOCASE:
info.type = JIM_LSORT_NOCASE;
break;
@@ -18420,13 +18571,17 @@ badindex:
}
}
resObj = argv[argc - 1];
+ JimListGetElements(interp, resObj, &listlen, &elements);
+ if (listlen <= 1) {
+
+ Jim_SetResult(interp, resObj);
+ return JIM_OK;
+ }
+
if (stride > 1) {
Jim_Obj *tmpListObj;
- Jim_Obj **elements;
- int listlen;
int i;
- JimListGetElements(interp, resObj, &listlen, &elements);
if (listlen % stride) {
Jim_SetResultString(interp, "list size must be a multiple of the stride length", -1);
return JIM_ERR;
@@ -18614,7 +18769,7 @@ static int JimBreakContinueHelper(Jim_Interp *interp, int argc, Jim_Obj *const *
if (ret != JIM_OK) {
return ret;
}
- interp->returnLevel = level;
+ interp->break_level = level;
}
return retcode;
}
@@ -20332,7 +20487,6 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
case INFO_SOURCE:{
- jim_wide line;
Jim_Obj *resObjPtr;
Jim_Obj *fileNameObj;
@@ -20341,26 +20495,16 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
if (argc == 5) {
+ jim_wide line;
if (Jim_GetWide(interp, argv[4], &line) != JIM_OK) {
return JIM_ERR;
}
resObjPtr = Jim_NewStringObj(interp, Jim_String(argv[2]), Jim_Length(argv[2]));
- JimSetSourceInfo(interp, resObjPtr, argv[3], line);
+ Jim_SetSourceInfo(interp, resObjPtr, argv[3], line);
}
else {
- if (argv[2]->typePtr == &sourceObjType) {
- fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj;
- line = argv[2]->internalRep.sourceValue.lineNumber;
- }
- else if (argv[2]->typePtr == &scriptObjType) {
- ScriptObj *script = JimGetScript(interp, argv[2]);
- fileNameObj = script->fileNameObj;
- line = script->firstline;
- }
- else {
- fileNameObj = interp->emptyObj;
- line = 1;
- }
+ int line;
+ fileNameObj = Jim_GetSourceInfo(interp, argv[2], &line);
resObjPtr = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, resObjPtr, fileNameObj);
Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line));
@@ -20819,11 +20963,12 @@ char **Jim_GetEnviron(void)
{
#if defined(HAVE__NSGETENVIRON)
return *_NSGetEnviron();
+#elif defined(_environ)
+ return _environ;
#else
#if !defined(NO_ENVIRON_EXTERN)
extern char **environ;
#endif
-
return environ;
#endif
}
@@ -20832,6 +20977,8 @@ void Jim_SetEnviron(char **env)
{
#if defined(HAVE__NSGETENVIRON)
*_NSGetEnviron() = env;
+#elif defined(_environ)
+ _environ = env;
#else
#if !defined(NO_ENVIRON_EXTERN)
extern char **environ;
@@ -23450,7 +23597,7 @@ void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
}
-#if defined(__MINGW32__)
+#if defined(_WIN32) || defined(WIN32)
#include <sys/stat.h>
int Jim_Errno(void)
@@ -23646,7 +23793,9 @@ int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unli
}
+#ifdef HAVE_UMASK
mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+#endif
#ifdef HAVE_MKSTEMP
fd = mkstemp(filenameObj->bytes);
#else
@@ -23657,7 +23806,9 @@ int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unli
fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC);
}
#endif
+#ifdef HAVE_UMASK
umask(mask);
+#endif
if (fd < 0) {
Jim_SetResultErrno(interp, Jim_String(filenameObj));
Jim_FreeNewObj(interp, filenameObj);
@@ -24260,6 +24411,11 @@ int main(int argc, char *const argv[])
Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
+#ifdef USE_LINENOISE
+ Jim_SetVariableStrWithStr(interp, "jim::lineedit", "1");
+#else
+ Jim_SetVariableStrWithStr(interp, "jim::lineedit", "0");
+#endif
retcode = Jim_initjimshInit(interp);
if (argc == 1) {
diff --git a/autosetup/system.tcl b/autosetup/system.tcl
index f23781b..05d378a 100644
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -55,6 +55,8 @@ options {
program-prefix:
program-suffix:
program-transform-name:
+ x-includes:
+ x-libraries:
}
# @check-feature name { script }
@@ -318,95 +320,101 @@ proc make-template {template {out {}}} {
}
}
-# build/host tuples and cross-compilation prefix
-opt-str build build ""
-define build_alias $build
-if {$build eq ""} {
- define build [config_guess]
-} else {
- define build [config_sub $build]
-}
+proc system-init {} {
+ global autosetup
-opt-str host host ""
-define host_alias $host
-if {$host eq ""} {
- define host [get-define build]
- set cross ""
-} else {
- define host [config_sub $host]
- set cross $host-
-}
-define cross [get-env CROSS $cross]
+ # build/host tuples and cross-compilation prefix
+ opt-str build build ""
+ define build_alias $build
+ if {$build eq ""} {
+ define build [config_guess]
+ } else {
+ define build [config_sub $build]
+ }
-# build/host _cpu, _vendor and _os
-foreach type {build host} {
- set v [get-define $type]
- if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
- user-error "Invalid canonical $type: $v"
+ opt-str host host ""
+ define host_alias $host
+ if {$host eq ""} {
+ define host [get-define build]
+ set cross ""
+ } else {
+ define host [config_sub $host]
+ set cross $host-
}
- define ${type}_cpu $cpu
- define ${type}_vendor $vendor
- define ${type}_os $os
-}
+ define cross [get-env CROSS $cross]
-opt-str prefix prefix /usr/local
-
-# These are for compatibility with autoconf
-define target [get-define host]
-define prefix $prefix
-define builddir $autosetup(builddir)
-define srcdir $autosetup(srcdir)
-define top_srcdir $autosetup(srcdir)
-define abs_top_srcdir [file-normalize $autosetup(srcdir)]
-define abs_top_builddir [file-normalize $autosetup(builddir)]
-
-# autoconf supports all of these
-define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
-foreach {name defpath} {
- bindir /bin
- sbindir /sbin
- libexecdir /libexec
- libdir /lib
-} {
- define $name [opt-str $name o $exec_prefix$defpath]
-}
-foreach {name defpath} {
- datadir /share
- sharedstatedir /com
- infodir /share/info
- mandir /share/man
- includedir /include
-} {
- define $name [opt-str $name o $prefix$defpath]
-}
-if {$prefix ne {/usr}} {
- opt-str sysconfdir sysconfdir $prefix/etc
-} else {
- opt-str sysconfdir sysconfdir /etc
-}
-define sysconfdir $sysconfdir
+ # build/host _cpu, _vendor and _os
+ foreach type {build host} {
+ set v [get-define $type]
+ if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
+ user-error "Invalid canonical $type: $v"
+ }
+ define ${type}_cpu $cpu
+ define ${type}_vendor $vendor
+ define ${type}_os $os
+ }
+
+ opt-str prefix prefix /usr/local
+
+ # These are for compatibility with autoconf
+ define target [get-define host]
+ define prefix $prefix
+ define builddir $autosetup(builddir)
+ define srcdir $autosetup(srcdir)
+ define top_srcdir $autosetup(srcdir)
+ define abs_top_srcdir [file-normalize $autosetup(srcdir)]
+ define abs_top_builddir [file-normalize $autosetup(builddir)]
+
+ # autoconf supports all of these
+ define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
+ foreach {name defpath} {
+ bindir /bin
+ sbindir /sbin
+ libexecdir /libexec
+ libdir /lib
+ } {
+ define $name [opt-str $name o $exec_prefix$defpath]
+ }
+ foreach {name defpath} {
+ datadir /share
+ sharedstatedir /com
+ infodir /share/info
+ mandir /share/man
+ includedir /include
+ } {
+ define $name [opt-str $name o $prefix$defpath]
+ }
+ if {$prefix ne {/usr}} {
+ opt-str sysconfdir sysconfdir $prefix/etc
+ } else {
+ opt-str sysconfdir sysconfdir /etc
+ }
+ define sysconfdir $sysconfdir
-define localstatedir [opt-str localstatedir o /var]
-define runstatedir [opt-str runstatedir o /run]
+ define localstatedir [opt-str localstatedir o /var]
+ define runstatedir [opt-str runstatedir o /run]
-define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
+ define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
-# These could be used to generate Makefiles following some automake conventions
-define AM_SILENT_RULES [opt-bool silent-rules]
-define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
-define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
+ # These could be used to generate Makefiles following some automake conventions
+ define AM_SILENT_RULES [opt-bool silent-rules]
+ define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
+ define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
-# Windows vs. non-Windows
-switch -glob -- [get-define host] {
- *-*-ming* - *-*-cygwin - *-*-msys {
- define-feature windows
- define EXEEXT .exe
- }
- default {
- define EXEEXT ""
+ # Windows vs. non-Windows
+ switch -glob -- [get-define host] {
+ *-*-ming* - *-*-cygwin - *-*-msys {
+ define-feature windows
+ define EXEEXT .exe
+ }
+ default {
+ define EXEEXT ""
+ }
}
+
+ # Display
+ msg-result "Host System...[get-define host]"
+ msg-result "Build System...[get-define build]"
}
-# Display
-msg-result "Host System...[get-define host]"
-msg-result "Build System...[get-define build]"
+system-init
diff --git a/initjimsh.tcl b/initjimsh.tcl
index 6fa54c6..e632623 100644
--- a/initjimsh.tcl
+++ b/initjimsh.tcl
@@ -10,8 +10,14 @@ proc _jimsh_init {} {
if {[string match "*/*" $jim::argv0]} {
set jim::exe [file join [pwd] $jim::argv0]
} else {
- foreach path [split [env PATH ""] $tcl_platform(pathSeparator)] {
- set exec [file join [pwd] [string map {\\ /} $path] $jim::argv0]
+ set jim::argv0 [file tail $jim::argv0]
+ set path [split [env PATH ""] $tcl_platform(pathSeparator)]
+ if {$tcl_platform(platform) eq "windows"} {
+ # Windows searches the current directory first, and convert backslashes to slashes
+ set path [lmap p [list "" {*}$path] { string map {\\ /} $p }]
+ }
+ foreach p $path {
+ set exec [file join [pwd] $p $jim::argv0]
if {[file executable $exec]} {
set jim::exe $exec
break
diff --git a/jim-aio.c b/jim-aio.c
index 4c59e1d..221d7f5 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -85,8 +85,8 @@
#include "jimiocompat.h"
#define AIO_CMD_LEN 32 /* e.g. aio.handleXXXXXX */
-#define AIO_BUF_LEN 256 /* read size for gets, read */
-#define AIO_WBUF_FULL_SIZE (64 * 1024) /* This could be configurable */
+#define AIO_DEFAULT_RBUF_LEN 256 /* read size for gets, read */
+#define AIO_DEFAULT_WBUF_LIMIT (64 * 1024) /* max size of writebuf before flushing */
#define AIO_KEEPOPEN 1 /* don't set O_CLOEXEC, don't close on command delete */
#define AIO_NODELETE 2 /* don't delete AF_UNIX path on close */
@@ -94,6 +94,8 @@
#define AIO_WBUF_NONE 8 /* default to buffering=none */
#define AIO_NONBLOCK 16 /* socket is non-blocking */
+#define AIO_ONEREAD 32 /* passed to aio_read_len() to return after a single read */
+
enum wbuftype {
WBUF_OPT_NONE, /* write immediately */
WBUF_OPT_LINE, /* write if NL is seen */
@@ -114,10 +116,6 @@ enum wbuftype {
#define UNIX_SOCKETS 0
#endif
-#ifndef MAXPATHLEN
-#define MAXPATHLEN JIM_PATH_LEN
-#endif
-
#if defined(HAVE_SOCKETS) && !defined(JIM_BOOTSTRAP)
/* Avoid type punned pointers */
union sockaddr_any {
@@ -192,11 +190,22 @@ typedef struct AioFile
const JimAioFopsType *fops;
Jim_Obj *readbuf; /* Contains any buffered read data. NULL if empty. refcount=0 */
Jim_Obj *writebuf; /* Contains any buffered write data. refcount=1 */
+ char *rbuf; /* Temporary read buffer (NULL if not yet allocated) */
+ size_t rbuf_len; /* Length of rbuf */
+ size_t wbuf_limit; /* Max size of writebuf before flushing */
} AioFile;
+static void aio_consume(Jim_Obj *objPtr, int n);
+
static int stdio_writer(struct AioFile *af, const char *buf, int len)
{
- return write(af->fd, buf, len);
+ int ret = write(af->fd, buf, len);
+ if (ret < 0 && errno == EPIPE) {
+ /* Also discard the write buffer since otherwise when
+ * we try to flush on shutdown we may get SIGPIPE */
+ aio_consume(af->writebuf, Jim_Length(af->writebuf));
+ }
+ return ret;
}
static int stdio_reader(struct AioFile *af, char *buf, int len, int nb)
@@ -710,7 +719,26 @@ static void aio_consume(Jim_Obj *objPtr, int n)
}
/* forward declaration */
-static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask);
+static int aio_flush(Jim_Interp *interp, AioFile *af);
+
+#ifdef jim_ext_eventloop
+/**
+ * Called when the channel is writable.
+ * Write what we can and return -1 when the write buffer is empty to remove the handler.
+ */
+static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask)
+{
+ AioFile *af = clientData;
+
+ aio_flush(interp, af);
+ if (Jim_Length(af->writebuf) == 0) {
+ /* Done, so remove the handler */
+ return -1;
+ }
+ return 0;
+}
+#endif
+
/**
* Flushes af->writebuf to the channel and removes that data
@@ -759,30 +787,18 @@ static int aio_flush(Jim_Interp *interp, AioFile *af)
}
/**
- * Called when the channel is writable.
- * Write what we can and return -1 when the write buffer is empty to remove the handler.
- */
-static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask)
-{
- AioFile *af = clientData;
-
- aio_flush(interp, af);
- if (Jim_Length(af->writebuf) == 0) {
- /* Done, so remove the handler */
- return -1;
- }
- return 0;
-}
-
-/**
* Read until 'len' bytes are available in readbuf.
*
+ * If flags contains AIO_NONBLOCK, indicates a nonblocking read.
+ * If flags contains AIO_ONEREAD, return after a single read.
+ * (In this case JIM_ERR is also returned on timeout)
+ *
* If nonblocking or timeout, may return early.
* 'len' may be -1 to read until eof (or until no more data if nonblocking)
*
* Returns JIM_OK if data was read or JIM_ERR on error.
*/
-static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size_t buflen, int neededLen)
+static int aio_read_len(Jim_Interp *interp, AioFile *af, unsigned flags, int neededLen)
{
if (!af->readbuf) {
af->readbuf = Jim_NewStringObj(interp, NULL, 0);
@@ -800,20 +816,29 @@ static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size
int readlen;
if (neededLen == -1) {
- readlen = AIO_BUF_LEN;
+ readlen = af->rbuf_len;
}
else {
- readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
+ readlen = (neededLen > af->rbuf_len ? af->rbuf_len : neededLen);
}
- retval = af->fops->reader(af, buf, readlen, nb);
+ /* Allocate buffer if not already allocated */
+ if (!af->rbuf) {
+ af->rbuf = Jim_Alloc(af->rbuf_len);
+ }
+ retval = af->fops->reader(af, af->rbuf, readlen, flags & AIO_NONBLOCK);
if (retval > 0) {
- Jim_AppendString(interp, af->readbuf, buf, retval);
+ if (retval) {
+ Jim_AppendString(interp, af->readbuf, af->rbuf, retval);
+ }
if (neededLen != -1) {
neededLen -= retval;
}
+ if (flags & AIO_ONEREAD) {
+ return JIM_OK;
+ }
continue;
}
- if (JimCheckStreamError(interp, af)) {
+ if ((flags & AIO_ONEREAD) || JimCheckStreamError(interp, af)) {
return JIM_ERR;
}
break;
@@ -892,6 +917,7 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
Jim_FreeNewObj(interp, af->readbuf);
}
+ Jim_Free(af->rbuf);
Jim_Free(af);
}
@@ -905,7 +931,6 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int option;
int nb;
Jim_Obj *objPtr;
- char buf[AIO_BUF_LEN];
if (argc) {
if (*Jim_String(argv[0]) == '-') {
@@ -939,7 +964,7 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
/* reads are nonblocking if a timeout is given */
nb = aio_start_nonblocking(af);
- if (aio_read_len(interp, af, nb, buf, sizeof(buf), neededLen) != JIM_OK) {
+ if (aio_read_len(interp, af, nb ? AIO_NONBLOCK : 0, neededLen) != JIM_OK) {
aio_set_nonblocking(af, nb);
return JIM_ERR;
}
@@ -997,11 +1022,6 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
AioFile *af = Jim_CmdPrivData(interp);
jim_wide count = 0;
jim_wide maxlen = JIM_WIDE_MAX;
- /* Small, static buffer for small files */
- char buf[AIO_BUF_LEN];
- /* Will be allocated if the file is large */
- char *bufp = buf;
- int buflen = sizeof(buf);
int ok = 1;
Jim_Obj *objv[4];
@@ -1031,10 +1051,10 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
while (count < maxlen) {
jim_wide len = maxlen - count;
- if (len > buflen) {
- len = buflen;
+ if (len > af->rbuf_len) {
+ len = af->rbuf_len;
}
- if (aio_read_len(interp, af, 0, bufp, buflen, len) != JIM_OK) {
+ if (aio_read_len(interp, af, 0, len) != JIM_OK) {
ok = 0;
break;
}
@@ -1047,17 +1067,13 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (aio_eof(af)) {
break;
}
- if (count >= 16384 && bufp == buf) {
+ if (count >= 16384 && af->rbuf_len < 65536) {
/* Heuristic check - for large copy speed-up */
- buflen = 65536;
- bufp = Jim_Alloc(buflen);
+ af->rbuf_len = 65536;
+ af->rbuf = Jim_Realloc(af->rbuf, af->rbuf_len);
}
}
- if (bufp != buf) {
- Jim_Free(bufp);
- }
-
Jim_DecrRefCount(interp, objv[1]);
Jim_DecrRefCount(interp, objv[2]);
@@ -1073,10 +1089,10 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- char buf[AIO_BUF_LEN];
Jim_Obj *objPtr = NULL;
int len;
int nb;
+ unsigned flags = AIO_ONEREAD;
char *nl = NULL;
int offset = 0;
@@ -1084,33 +1100,33 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
/* reads are non-blocking if a timeout has been given */
nb = aio_start_nonblocking(af);
-
- if (!af->readbuf) {
- af->readbuf = Jim_NewStringObj(interp, NULL, 0);
+ if (nb) {
+ flags |= AIO_NONBLOCK;
}
while (!aio_eof(af)) {
- const char *pt = Jim_GetString(af->readbuf, &len);
- nl = memchr(pt + offset, '\n', len - offset);
- if (nl) {
- /* got a line */
- objPtr = Jim_NewStringObj(interp, pt, nl - pt);
- /* And consume it plus the newline */
- aio_consume(af->readbuf, nl - pt + 1);
- break;
+ if (af->readbuf) {
+ const char *pt = Jim_GetString(af->readbuf, &len);
+ nl = memchr(pt + offset, '\n', len - offset);
+ if (nl) {
+ /* got a line */
+ objPtr = Jim_NewStringObj(interp, pt, nl - pt);
+ /* And consume it plus the newline */
+ aio_consume(af->readbuf, nl - pt + 1);
+ break;
+ }
+ offset = len;
}
- offset = len;
- len = af->fops->reader(af, buf, AIO_BUF_LEN, nb);
- if (len <= 0) {
+ /* Not got a line yet, so read more */
+ if (aio_read_len(interp, af, flags, -1) != JIM_OK) {
break;
}
- Jim_AppendString(interp, af->readbuf, buf, len);
}
aio_set_nonblocking(af, nb);
- if (!nl && aio_eof(af)) {
+ if (!nl && aio_eof(af) && af->readbuf) {
/* Just take what we have as the line */
objPtr = af->readbuf;
af->readbuf = NULL;
@@ -1162,6 +1178,15 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
/* Keep it simple and always go via the writebuf instead of trying to optimise
* the case that we can write immediately
*/
+#ifdef JIM_MAINTAINER
+ if (Jim_IsShared(af->writebuf)) {
+ /* This should generally never happen since this object isn't accessible,
+ * but it is possible with 'debug objects' */
+ Jim_DecrRefCount(interp, af->writebuf);
+ af->writebuf = Jim_DuplicateObj(interp, af->writebuf);
+ Jim_IncrRefCount(af->writebuf);
+ }
+#endif
Jim_AppendObj(interp, af->writebuf, strObj);
if (nl) {
Jim_AppendString(interp, af->writebuf, "\n", 1);
@@ -1183,7 +1208,7 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
break;
case WBUF_OPT_FULL:
- if (wlen >= AIO_WBUF_FULL_SIZE) {
+ if (wlen >= af->wbuf_limit) {
wnow = 1;
}
break;
@@ -1597,6 +1622,7 @@ static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
+ Jim_Obj *resultObj;
static const char * const options[] = {
"none",
@@ -1605,17 +1631,79 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
NULL
};
- if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) {
- return JIM_ERR;
+ if (argc) {
+ if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+
+ if (af->wbuft == WBUF_OPT_FULL && argc == 2) {
+ long l;
+ if (Jim_GetLong(interp, argv[1], &l) != JIM_OK || l <= 0) {
+ return JIM_ERR;
+ }
+ af->wbuf_limit = l;
+ }
+
+ if (af->wbuft == WBUF_OPT_NONE) {
+ if (aio_flush(interp, af) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+ /* don't bother flushing when switching from full to line */
}
- if (af->wbuft == WBUF_OPT_NONE) {
- return aio_flush(interp, af);
+ resultObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, resultObj, Jim_NewStringObj(interp, options[af->wbuft], -1));
+ if (af->wbuft == WBUF_OPT_FULL) {
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, af->wbuf_limit));
+ }
+ Jim_SetResult(interp, resultObj);
+
+ return JIM_OK;
+}
+
+static int aio_cmd_translation(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ enum {OPT_BINARY, OPT_TEXT};
+ static const char * const options[] = {
+ "binary",
+ "text",
+ NULL
+ };
+ int opt;
+
+ if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+#if defined(Jim_SetMode)
+ else {
+ AioFile *af = Jim_CmdPrivData(interp);
+ Jim_SetMode(af->fd, opt == OPT_BINARY ? O_BINARY : O_TEXT);
+ }
+#endif
+ return JIM_OK;
+}
+
+static int aio_cmd_readsize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ if (argc) {
+ long l;
+ if (Jim_GetLong(interp, argv[0], &l) != JIM_OK || l <= 0) {
+ return JIM_ERR;
+ }
+ af->rbuf_len = l;
+ if (af->rbuf) {
+ af->rbuf = Jim_Realloc(af->rbuf, af->rbuf_len);
+ }
}
- /* don't bother flushing when switching from full to line */
+ Jim_SetResultInt(interp, af->rbuf_len);
+
return JIM_OK;
}
+#ifdef jim_ext_eventloop
static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef HAVE_SELECT
@@ -1633,7 +1721,6 @@ static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
#endif
}
-#ifdef jim_ext_eventloop
static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask,
int argc, Jim_Obj * const *argv)
{
@@ -2107,11 +2194,25 @@ static const jim_subcmd_type aio_command_table[] = {
},
#endif
{ "buffering",
- "none|line|full",
+ "?none|line|full? ?size?",
aio_cmd_buffering,
+ 0,
+ 2,
+ /* Description: Sets or returns write buffering */
+ },
+ { "translation",
+ "binary|text",
+ aio_cmd_translation,
1,
1,
- /* Description: Sets buffering */
+ /* Description: Sets output translation mode */
+ },
+ { "readsize",
+ "?size?",
+ aio_cmd_readsize,
+ 0,
+ 1,
+ /* Description: Sets or returns read size */
},
#if defined(jim_ext_file) && defined(Jim_FileStat)
{ "stat",
@@ -2448,6 +2549,9 @@ static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
/* Create an empty write buf */
af->writebuf = Jim_NewStringObj(interp, NULL, 0);
Jim_IncrRefCount(af->writebuf);
+ af->wbuf_limit = AIO_DEFAULT_WBUF_LIMIT;
+ af->rbuf_len = AIO_DEFAULT_RBUF_LEN;
+ /* Don't allocate rbuf or readbuf until we need it */
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
diff --git a/jim-file.c b/jim-file.c
index 4a8380b..01e305a 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -67,14 +67,6 @@
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
-# ifndef MAXPATHLEN
-# ifdef PATH_MAX
-# define MAXPATHLEN PATH_MAX
-# else
-# define MAXPATHLEN JIM_PATH_LEN
-# endif
-# endif
-
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
#define ISWINDOWS 1
/* Even if we have symlink it isn't compatible enought to use */
@@ -568,8 +560,8 @@ static int mkdir_all(char *path)
/* Create the parent and try again */
continue;
}
- /* Maybe it already exists as a directory */
- if (errno == EEXIST) {
+ /* Maybe it already exists as a directory. MorphOS can return ENOTDIR instead of EEXIST */
+ if (errno == EEXIST || errno == ENOTDIR) {
jim_stat_t sb;
if (Jim_Stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
diff --git a/jim-namespace.c b/jim-namespace.c
index 0bdb0a9..d1a02f5 100644
--- a/jim-namespace.c
+++ b/jim-namespace.c
@@ -231,7 +231,7 @@ static int JimNamespaceCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
JIM_DEF_SUBCMD("tail", "string", 1, 1),
JIM_DEF_SUBCMD("upvar", "ns ?arg ...?", 1, -1),
JIM_DEF_SUBCMD("which", "?-command|-variable? name", 1, 2),
- { /* null terminator */ }
+ { NULL }
};
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, namespace_cmds, argc, argv);
if (ct) {
diff --git a/jim-package.c b/jim-package.c
index 69af074..18b64fe 100644
--- a/jim-package.c
+++ b/jim-package.c
@@ -148,6 +148,16 @@ int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags)
return JIM_OK;
}
+static int package_cmd_forget(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ Jim_DeleteHashEntry(&interp->packages, Jim_String(argv[i]));
+ }
+ return JIM_OK;
+}
+
/*
*----------------------------------------------------------------------
*
@@ -216,6 +226,14 @@ static int package_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static const jim_subcmd_type package_command_table[] = {
{
+ "forget",
+ "package ...",
+ package_cmd_forget,
+ 1,
+ -1,
+ /* Description: Forget that the given packages were loaded */
+ },
+ {
"provide",
"name ?version?",
package_cmd_provide,
diff --git a/jim-win32compat.h b/jim-win32compat.h
index 16133b5..acb47c8 100644
--- a/jim-win32compat.h
+++ b/jim-win32compat.h
@@ -30,6 +30,9 @@ char *dlerror(void);
#include <limits.h>
#define jim_wide _int64
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG
+#endif
#ifndef LLONG_MAX
#define LLONG_MAX 9223372036854775807I64
#endif
@@ -43,12 +46,8 @@ char *dlerror(void);
#define strtoull _strtoui64
#include <io.h>
-
-struct timeval {
- long tv_sec;
- long tv_usec;
-};
-
+/* For struct timeval */
+#include <winsock.h>
int gettimeofday(struct timeval *tv, void *unused);
#define HAVE_OPENDIR
diff --git a/jim.c b/jim.c
index c89f685..ecf4c8b 100644
--- a/jim.c
+++ b/jim.c
@@ -2613,7 +2613,7 @@ int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
const char *sA = Jim_GetString(aObjPtr, &Alen);
const char *sB = Jim_GetString(bObjPtr, &Blen);
- return Alen == Blen && memcmp(sA, sB, Alen) == 0;
+ return Alen == Blen && *sA == *sB && memcmp(sA, sB, Alen) == 0;
}
}
@@ -3997,7 +3997,7 @@ static int JimCommandsHT_KeyCompare(void *privdata, const void *key1, const void
int len1, len2;
const char *str1 = Jim_GetStringNoQualifier((Jim_Obj *)key1, &len1);
const char *str2 = Jim_GetStringNoQualifier((Jim_Obj *)key2, &len2);
- return len1 == len2 && memcmp(str1, str2, len1) == 0;
+ return len1 == len2 && *str1 == *str2 && memcmp(str1, str2, len1) == 0;
}
static void JimCommandsHT_ValDestructor(void *interp, void *val)
@@ -5825,6 +5825,9 @@ void Jim_FreeInterp(Jim_Interp *i)
JimFreeCallFrame(i, cf, JIM_FCF_FULL);
}
+ /* Must be done before freeing singletons */
+ Jim_FreeHashTable(&i->commands);
+
Jim_DecrRefCount(i, i->emptyObj);
Jim_DecrRefCount(i, i->trueObj);
Jim_DecrRefCount(i, i->falseObj);
@@ -5836,8 +5839,6 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->nullScriptObj);
Jim_DecrRefCount(i, i->currentFilenameObj);
- Jim_FreeHashTable(&i->commands);
-
/* This will disard any cached commands */
Jim_InterpIncrProcEpoch(i);
@@ -8451,6 +8452,13 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
case JIM_EXPROP_NOT:
wC = !bA;
break;
+ case JIM_EXPROP_UNARYPLUS:
+ case JIM_EXPROP_UNARYMINUS:
+ rc = JIM_ERR;
+ Jim_SetResultFormatted(interp,
+ "can't use non-numeric string as operand of \"%s\"",
+ node->type == JIM_EXPROP_UNARYPLUS ? "+" : "-");
+ break;
default:
abort();
}
@@ -12602,7 +12610,7 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
{
int retval;
jim_wide i;
- jim_wide limit;
+ jim_wide limit = 0;
jim_wide incr = 1;
Jim_Obj *bodyObjPtr;
@@ -13696,7 +13704,7 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
JIM_DEF_SUBCMD("refcount", "object", 1, 1),
JIM_DEF_SUBCMD("scriptlen", "script", 1, 1),
JIM_DEF_SUBCMD("show", "object", 1, 1),
- { /* null terminator */ }
+ { NULL }
};
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
@@ -14459,7 +14467,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
JIM_DEF_SUBCMD("trim", "string ?trimchars?", 1, 2),
JIM_DEF_SUBCMD("trimleft", "string ?trimchars?", 1, 2),
JIM_DEF_SUBCMD("trimright", "string ?trimchars?", 1, 2),
- { /* null terminator */ }
+ { NULL }
};
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
if (!ct) {
@@ -15015,16 +15023,22 @@ wrongargs:
}
else if (errorCodeObj) {
int len = Jim_ListLength(interp, argv[idx + 1]);
- int i;
-
- ret = JIM_OK;
- /* Try to match the sublist against errorcode */
- for (i = 0; i < len; i++) {
- Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i);
- Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i);
- if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) {
- ret = -1;
- break;
+
+ if (len > Jim_ListLength(interp, errorCodeObj)) {
+ /* More elements in the sublist than in the errorCode so we can't match */
+ ret = -1;
+ }
+ else {
+ int i;
+ ret = JIM_OK;
+ /* Try to match the sublist against errorcode */
+ for (i = 0; i < len; i++) {
+ Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i);
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i);
+ if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) {
+ ret = -1;
+ break;
+ }
}
}
}
@@ -15491,7 +15505,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
JIM_DEF_SUBCMD("for", "vars dictionary script", 3, 3),
JIM_DEF_SUBCMD("replace", "dictionary ?key value ...?", 1, -1),
JIM_DEF_SUBCMD("update", "varName ?arg ...? script", 2, -1),
- { /* null terminator */ }
+ { NULL }
};
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
if (!ct) {
@@ -15529,7 +15543,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
case OPT_SET:
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
+ return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG | JIM_UNSHARED);
case OPT_EXISTS:{
int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_NONE);
@@ -15541,7 +15555,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
case OPT_UNSET:
- if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE) != JIM_OK) {
+ if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_UNSHARED) != JIM_OK) {
return JIM_ERR;
}
return JIM_OK;
@@ -15700,7 +15714,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
JIM_DEF_SUBCMD("statics", "procname", 1, 1),
JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1),
JIM_DEF_SUBCMD("version", NULL, 0, 0),
- { /* null terminator */ }
+ { NULL }
};
const jim_subcmd_type *ct;
#ifdef jim_ext_namespace
@@ -16272,11 +16286,12 @@ char **Jim_GetEnviron(void)
{
#if defined(HAVE__NSGETENVIRON)
return *_NSGetEnviron();
+#elif defined(_environ)
+ return _environ;
#else
#if !defined(NO_ENVIRON_EXTERN)
extern char **environ;
#endif
-
return environ;
#endif
}
@@ -16285,6 +16300,8 @@ void Jim_SetEnviron(char **env)
{
#if defined(HAVE__NSGETENVIRON)
*_NSGetEnviron() = env;
+#elif defined(_environ)
+ _environ = env;
#else
#if !defined(NO_ENVIRON_EXTERN)
extern char **environ;
diff --git a/jim_tcl.txt b/jim_tcl.txt
index 66100ca..97f8374 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -3,7 +3,7 @@ Jim Tcl(n)
NAME
----
-Jim Tcl v0.83 - reference manual for the Jim Tcl scripting language
+Jim Tcl v0.83+ - reference manual for the Jim Tcl scripting language
SYNOPSIS
--------
@@ -33,129 +33,135 @@ available only in Jim Tcl.
Some notable differences with Tcl 8.5/8.6/8.7 are:
-1. Object-based I/O (aio), but with a Tcl-compatibility layer
-2. I/O: Support for sockets and pipes including udp, unix domain sockets and IPv6
-3. Integers are 64bit
-4. Support for references (`ref`/`getref`/`setref`) and garbage collection
-5. Builtin dictionary type (`dict`) with some limitations compared to Tcl 8.6
-6. `env` command to access environment variables
-7. Operating system features: `os.fork`, `os.uptime`, `wait`, `signal`, `alarm`, `sleep`
-8. Much better error reporting. `info stacktrace` as a replacement for '$errorInfo', '$errorCode'
-9. Support for "static" variables in procedures
-10. Threads and coroutines are not supported
-11. Command and variable traces are not supported
-12. Built-in command line editing
-13. Expression shorthand syntax: +$(...)+
-14. Modular build allows many features to be omitted or built as dynamic, loadable modules
-15. Highly suitable for use in an embedded environment
-16. Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets
+#. Object-based I/O (aio), but with a Tcl-compatibility layer
+#. I/O: Support for sockets and pipes including TCP, UDP, UNIX-Domain sockets and IPv6
+#. Integers are 64bit
+#. Support for references (`ref`/`getref`/`setref`) and garbage collection
+#. Builtin dictionary type (`dict`) with some limitations compared to Tcl 8.6
+#. `env` command to access environment variables
+#. Operating system features: `os.fork`, `os.uptime`, `wait`, `signal`, `alarm`, `sleep`
+#. Much better error reporting. `info stacktrace` as a replacement for '$errorInfo', '$errorCode'
+#. Support for "static" variables in procedures
+#. Threads and coroutines are not supported
+#. Command and variable traces are not supported
+#. Built-in command line editing in interactive mode with autocompletion and hints
+#. Expression shorthand syntax: +$(...)+
+#. Modular build allows many features to be omitted or built as dynamic, loadable modules
+#. Highly suitable for use in an embedded environment
+#. Jim does not convert backslash-newline within braces (in order to preserve accurate line numbers)
RECENT CHANGES
--------------
-Changes since 0.82
+Changes since 0.83
~~~~~~~~~~~~~~~~~~
-1. Multi-level `break` and `continue` are now supported
-2. `info frame` now only returns 'proc' levels
-3. `stacktrace` is now a builtin command
-4. The stack trace on error now includes the full stack trace, not just back to where it was caught
-5. Improvements with `aio`, related to eventloop and buffering. Add `aio timeout`.
-6. `socket` , `open` and `aio accept` now support '-noclose'
-7. Add support for hinting with `history hints`
-8. Support for `proc` statics by reference (lexical closure) rather than by value
-9. `regsub` now supports '-command' (per Tcl 8.7)
-10. Add support for `lsort -dict`
+#. `aio` - support for configurable read and write buffering
+#. Add support for `package forget`
+#. Add `aio translation` support (and fconfigure -translation)
+
+Changes between 0.82 and 0.83
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#. Multi-level `break` and `continue` are now supported
+#. `info frame` now only returns 'proc' levels
+#. `stacktrace` is now a builtin command
+#. The stack trace on error now includes the full stack trace, not just back to where it was caught
+#. Improvements with `aio`, related to eventloop and buffering. Add `aio timeout`.
+#. `socket` , `open` and `aio accept` now support '-noclose'
+#. Add support for hinting with `history hints`
+#. Support for `proc` statics by reference (lexical closure) rather than by value
+#. `regsub` now supports '-command' (per Tcl 8.7)
+#. Add support for `lsort -dict`
Changes between 0.81 and 0.82
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. `try` now supports trap to match on errorcode
-2. TIP 603, `aio stat` is now supported to stat a file handle
-3. Add support for `socket -async`
-4. The handles created by `socket pty` now make the replica name available via 'filename'
-5. `info frame` now returns a (largely) Tcl-compatible dictionary, and supports 'info frame 0'
-6. `vwait -signal` is now supported
-7. ./configure now defaults to '--full'
-8. New `timerate` command as an improvement over `time`, somewhat compatible with TIP 527
-9. Add `ensemble` command and support for `namespace ensemble` (as an optional extension)
+#. `try` now supports trap to match on errorcode
+#. TIP 603, `aio stat` is now supported to stat a file handle
+#. Add support for `socket -async`
+#. The handles created by `socket pty` now make the replica name available via 'filename'
+#. `info frame` now returns a (largely) Tcl-compatible dictionary, and supports 'info frame 0'
+#. `vwait -signal` is now supported
+#. ./configure now defaults to '--full'
+#. New `timerate` command as an improvement over `time`, somewhat compatible with TIP 527
+#. Add `ensemble` command and support for `namespace ensemble` (as an optional extension)
Changes between 0.80 and 0.81
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. TIP 582, comments allowed in expressions
-2. Many commands now accept "safe" integer expressions rather than simple integers:
+#. TIP 582, comments allowed in expressions
+#. Many commands now accept "safe" integer expressions rather than simple integers:
`loop`, `range`, `incr`, `string repeat`, `lrepeat`, `pack`, `unpack`, `rand`
-3. String and list indexes now accept integer expressions (<<_string_and_list_index_specifications,STRING AND LIST INDEX SPECIFICATIONS>>)
-4. `loop` can now omit the start value
-5. Add the `xtrace` command for execution trace support
-6. Add `history keep`
-7. Add support for `lsearch -index` and `lsearch -stride`, the latter per TIP 351
-8. `lsort -index` now supports multiple indices
-9. Add support for `lsort -stride`
-10. `open` now supports POSIX-style access arguments
-11. TIP 526, `expr` now only allows a single argument (unless --compat is enabled)
+#. String and list indexes now accept integer expressions (<<_string_and_list_index_specifications,STRING AND LIST INDEX SPECIFICATIONS>>)
+#. `loop` can now omit the start value
+#. Add the `xtrace` command for execution trace support
+#. Add `history keep`
+#. Add support for `lsearch -index` and `lsearch -stride`, the latter per TIP 351
+#. `lsort -index` now supports multiple indices
+#. Add support for `lsort -stride`
+#. `open` now supports POSIX-style access arguments
+#. TIP 526, `expr` now only allows a single argument (unless --compat is enabled)
Changes between 0.79 and 0.80
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. `regsub` now fully supports +{backslash}A+
-2. Add `socket pty` to create a pseudo-tty pair
-3. Null characters (\x00) are now supported in variable and proc names
-4. dictionaries and arrays now preserve insertion order, matching Tcl and the documentation
-5. Add `dict getwithdefault` (and the alias `dict getdef`) per TIP 342
-6. Add string comparison operators (lt, gt, le, ge) per TIP 461
-7. Implement 0d radix prefix for decimal per TIP 472
+#. `regsub` now fully supports +{backslash}A+
+#. Add `socket pty` to create a pseudo-tty pair
+#. Null characters (\x00) are now supported in variable and proc names
+#. dictionaries and arrays now preserve insertion order, matching Tcl and the documentation
+#. Add `dict getwithdefault` (and the alias `dict getdef`) per TIP 342
+#. Add string comparison operators (lt, gt, le, ge) per TIP 461
+#. Implement +0d+ radix prefix for decimal per TIP 472
Changes between 0.78 and 0.79
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Add `file mtimeus` for high resolution file timestamps
-2. `aio` now supports datagram Unix-Domain sockets
-3. Add support for `aio lock -wait`
-4. Add `signal block` to prevent delivery of signals
-5. Add support for `file split`
-6. Add support for `json::encode` and `json::decode`
-7. `aio tty` now allows setting +echo+ without full +raw+ mode
+#. Add `file mtimeus` for high resolution file timestamps
+#. `aio` now supports datagram Unix-Domain sockets
+#. Add support for `aio lock -wait`
+#. Add `signal block` to prevent delivery of signals
+#. Add support for `file split`
+#. Add support for `json::encode` and `json::decode`
+#. `aio tty` now allows setting +echo+ without full +raw+ mode
Changes between 0.77 and 0.78
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Add serial/tty support with `aio tty`
-2. Add support for 'jimsh -'
-3. Add hidden '-commands' option to many commands
-4. Add scriptable autocompletion support in interactive mode with `tcl::autocomplete`
-5. Add `aio sockopt`
-6. Add scriptable autocompletion support with `history completion`
-7. Add support for `tree delete`
-8. Add support for `defer` and '$jim::defer'
-9. Renamed `os.wait` to `wait`, now more Tcl-compatible and compatible with `exec ... &`
-10. `pipe` is now a synonym for `socket pipe`
-11. Closing a pipe open with `open |...` now returns Tcl-like status
-12. It is now possible to used `exec` redirection with a pipe opened with `open |...`
-13. Interactive line editing now supports multiline mode if $::history::multiline is set
+#. Add serial/tty support with `aio tty`
+#. Add support for 'jimsh -'
+#. Add hidden '-commands' option to many commands
+#. Add scriptable autocompletion support in interactive mode with `tcl::autocomplete`
+#. Add `aio sockopt`
+#. Add scriptable autocompletion support with `history completion`
+#. Add support for `tree delete`
+#. Add support for `defer` and '$jim::defer'
+#. Renamed `os.wait` to `wait`, now more Tcl-compatible and compatible with `exec ... &`
+#. `pipe` is now a synonym for `socket pipe`
+#. Closing a pipe open with `open |...` now returns Tcl-like status
+#. It is now possible to used `exec` redirection with a pipe opened with `open |...`
+#. Interactive line editing now supports multiline mode if $::history::multiline is set
Changes between 0.76 and 0.77
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Add support for `aio sync`
-2. Add SSL and TLS support in aio
-3. Added `zlib`
-4. Added support for boolean constants in `expr`
-5. `string is` now supports 'boolean' class
-6. Add support for `aio lock` and `aio unlock`
-7. Add new `interp` command
+#. Add support for `aio sync`
+#. Add SSL and TLS support in aio
+#. Added `zlib`
+#. Added support for boolean constants in `expr`
+#. `string is` now supports 'boolean' class
+#. Add support for `aio lock` and `aio unlock`
+#. Add new `interp` command
Changes between 0.75 and 0.76
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. `glob` now supports the +-tails+ option
-2. Add support for `string cat`
-3. Allow `info source` to add source info
+#. `glob` now supports the +-tails+ option
+#. Add support for `string cat`
+#. Allow `info source` to add source info
Changes between 0.74 and 0.75
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. `binary`, `pack` and `unpack` now support floating point
-2. `file copy` +-force+ handles source and target as the same file
-3. `format` now supports +%b+ for binary conversion
-4. `lsort` now supports +-unique+ and +-real+
-5. Add support for half-close with `aio close` +?r|w?+
-6. Add `socket pair` for a bidirectional pipe
-7. Add '--random-hash' to randomise hash tables for greater security
-8. `dict` now supports 'for', 'values', 'incr', 'append', 'lappend', 'update', 'info' and 'replace'
-9. `file stat` no longer requires the variable name
-10. Add support for `file link`
+#. `binary`, `pack` and `unpack` now support floating point
+#. `file copy` +-force+ handles source and target as the same file
+#. `format` now supports +%b+ for binary conversion
+#. `lsort` now supports +-unique+ and +-real+
+#. Add support for half-close with `aio close` +?r|w?+
+#. Add `socket pair` for a bidirectional pipe
+#. Add '--random-hash' to randomise hash tables for greater security
+#. `dict` now supports 'for', 'values', 'incr', 'append', 'lappend', 'update', 'info' and 'replace'
+#. `file stat` no longer requires the variable name
+#. Add support for `file link`
TCL INTRODUCTION
-----------------
@@ -591,41 +597,12 @@ sequence is replaced by the given character:
+{backslash}v+::
Vertical tab (0xb).
-+{backslash}{+::
- Left brace ({).
-
-+{backslash}}+::
- Right brace (}).
-
-+{backslash}[+::
- Open bracket ([).
-
-+{backslash}]+::
- Close bracket (]).
-
-+{backslash}$+::
- Dollar sign ($).
-
-+{backslash}<space>+::
- Space ( ): doesn't terminate argument.
-
-+{backslash};+::
- Semi-colon: doesn't terminate command.
-
-+{backslash}"+::
- Double-quote.
-
-+{backslash}<newline>+::
- Nothing: this joins two lines together
- into a single line. This backslash feature is unique in that
- it will be applied even when the sequence occurs within braces.
-
-+{backslash}{backslash}+::
- Backslash ('{backslash}').
-
+{backslash}ddd+::
The digits +'ddd'+ (one, two, or three of them) give the octal value of
- the character. Note that Jim supports null characters in strings.
+ the byte. Note that Jim supports null characters in strings.
+
++{backslash}xnn+::
+ The hexidecimal digits +'nn'+ give the value of the byte.
+{backslash}unnnn+::
+{backslash}u\{nnn\}+::
@@ -634,32 +611,24 @@ sequence is replaced by the given character:
The 'u' form allows for one to four hex digits.
The 'U' form allows for one to eight hex digits.
The 'u\{nnn\}' form allows for one to eight hex digits, but makes it easier to insert
- characters UTF-8 characters which are followed by a hex digit.
-
-For example, in the command
-
-----
- set a \{x\[\ yz\141
-----
-
-the second argument to `set` will be +{x[ yza+.
+ UTF-8 characters that are followed by a hex digit.
If a backslash is followed by something other than one of the options
-described above, then the backslash is transmitted to the argument
-field without any special processing, and the Tcl scanner continues
+described above, the backslash is skipped and character following the backslash is treated
+as a normal character without any special meaning. The Tcl scanner continues
normal processing with the next character. For example, in the
command
+For example, in the command
+
----
- set \*a \\{foo
+ set a \\{x\[\ yz\141
----
-The first argument to `set` will be +*a+ and the second
-argument will be +{foo+.
+the second argument to `set` will be +{x[ yza+.
If an argument is enclosed in braces, then backslash sequences inside
-the argument are parsed but no substitution occurs (except for
-backslash-newline): the backslash
+the argument are parsed but no substitution occurs: the backslash
sequence is passed through to the argument as is, without making
any special interpretation of the characters in the backslash sequence.
In particular, backslashed braces are not counted in locating the
@@ -2092,7 +2061,7 @@ curry
Similar to `alias` except it creates an anonymous procedure (lambda) instead of
a named procedure.
-the following creates a local, unnamed alias for the command `info exists`.
+The following creates a local, unnamed alias for the command `info exists`.
----
set e [local curry info exists]
@@ -2131,6 +2100,11 @@ Performs one of several operations on dictionary values.
The +'option'+ argument determines what action is carried out by the
command. The legal +'options'+ are:
++*dict append* 'dictionaryName key ?string ...?'+::
+ This appends the given string (or strings) to the value that
+ the given key maps to in +'dictionaryName'+. Non-existent keys
+ are treated as if they map to an empty string.
+
+*dict create* '?key value \...?'+::
Create and return a new dictionary value that contains each of
the key/value mappings listed as arguments (keys and values
@@ -2143,6 +2117,9 @@ command. The legal +'options'+ are:
dictionary value. This returns a true value exactly when `dict get`
on that path will succeed.
++*dict for* '{keyvar valuevar} dictionary script'+::
+ *TBD*
+
+*dict get* 'dictionary ?key \...?'+::
Given a dictionary value (first argument) and a key (second argument),
this will retrieve the value for that key. Where several keys are
@@ -2163,12 +2140,28 @@ command. The legal +'options'+ are:
Similar to `dict get` except if no value exists in the dictionary for the
give key(s), returns +'default'+ instead.
++*dict incr* 'dictionaryName key ?increment?'+::
+ This adds the given increment value (an integer that defaults
+ to 1 if not specified) to the value that the given key maps to
+ in +'dictionaryName'+. Non-existent keys are treated as if
+ they map to 0. It is an error to increment a value for an
+ existing key if that value is not an integer.
+
++*dict info* 'dictionary'+::
+ Returns some information about the utilisation of the data
+ within the hashtable that represents +'dictionary'+.
+
+*dict keys* 'dictionary ?pattern?'+::
Returns a list of the keys in the dictionary.
If +'pattern'+ is specified, then only those keys whose
names match +'pattern'+ (using <<_string_matching,STRING MATCHING>> rules)
are included.
++*dict lappend* 'dictionaryName key ?value ...?'+::
+ This appends the given items to the list value that the given
+ key maps to in +'dictionaryName'+. Non-existent keys are treated
+ as if they map to the empty list.
+
+*dict merge* ?'dictionary \...'?+::
Return a dictionary that contains the contents of each of the
+'dictionary'+ arguments. Where two (or more) dictionaries
@@ -2176,6 +2169,13 @@ command. The legal +'options'+ are:
maps that key to the value according to the last dictionary on
the command line containing a mapping for that key.
++*dict replace* 'dictionary ?key value ...?'+::
+ Return a new dictionary that is a copy of +'dictionary'+
+ except with some values different or some
+ extra key/value pairs added. It is legal for this command to
+ be called with no key/value pairs, but illegal for this command
+ to be called with a key but no value.
+
+*dict set* 'dictionaryName key ?key \...? value'+::
This operation takes the +'name'+ of a variable containing a dictionary
value and places an updated dictionary value in that variable
@@ -2195,6 +2195,16 @@ command. The legal +'options'+ are:
least one key must be specified, but the last key on the key-path
need not exist. All other components on the path must exist.
++*dict update* 'dictionaryName key varName ?key VarName ...? script'+::
+ *TBD*
+
++*dict values* 'dictionary ?globPattern?'+::
+ Return a list of all values in +'dictionary'+. If a pattern is
+ supplied, only those values that match it (according to the
+ rules of `string match`) will be returned. The returned values
+ will be in the order of that the keys associated with those
+ values were inserted into the dictionary.
+
+*dict with* 'dictionaryName key ?key \...? script'+::
Execute the Tcl script in +'script'+ with the value for each
key in +'dictionaryName'+ mapped to a variable with the same
@@ -2214,8 +2224,6 @@ command. The legal +'options'+ are:
explicitly unset). Note that changes to the contents of +'dictionaryName'+
only happen when +'script'+ terminates.
-+*dict for, values, incr, append, lappend, update, info, replace*+ to be documented...
-
ensemble
~~~~~~~~
+*ensemble* 'name ?*-automap*? prefix'+
@@ -2225,15 +2233,15 @@ By default, the prefix is +'name'+ followed by a single space.
For example, consider:
+----
proc {test open} {name} { ... }
proc {test close} {handle} { ... }
proc {test show} {handle} { ... }
ensemble test
+----
Now the '+test+' command has been created that redirects based on the first argument.
-e.g.
-
- test open $filename => {test open} $filename
+e.g. +'test open $filename'+ => +'{test open} $filename'+
env
~~~
@@ -3152,16 +3160,13 @@ continues to have global scope while it is active.
----
In this example, the lambda is deleted at the end of the procedure rather
-than waiting until garbage collection.
+than waiting until garbage collection. Note that `local` returns the command name.
----
proc outer {} {
- set x [lambda inner {args} {
+ set x [local lambda {args} {
# will be deleted when 'outer' exits
}]
- # Use 'function' here which simply returns $x
- local function $x
-
$x ...
...
}
@@ -3657,32 +3662,34 @@ See also `socket`, `pid`, `exec`
package
~~~~~~~
-+*package provide* 'name ?version?'+
++*package forget* '?name ...?'+::
+Removes the knowledge that the given packages were loaded. This allows new, replacement
+packages to be loaded. Note that it does not remove any effects of the previous packages
+being loaded.
++*package provide* 'name ?version?'+::
Indicates that the current script provides the package named +'name'+.
*Note*: The supplied version is ignored. All packages are registered as version 1.0
(it is simply accepted for compatibility purposes).
-
+ ::
Any script that provides a package may include this statement
as the first statement, although it is not required.
-+*package require* 'name ?version?'+
-
++*package require* 'name ?version?'+::
Searches for the package with the given +'name'+ by examining each path
in '$::auto_path' and trying to load '$path/$name.so' as a dynamic extension,
or '$path/$name.tcl' as a script package.
-
+ ::
The first such file which is found is considered to provide the package.
(The version number is ignored).
-
+ ::
If '$name.so' exists, it is loaded with the `load` command,
otherwise if '$name.tcl' exists it is loaded with the `source` command.
-
+ ::
If `load` or `source` fails, `package require` will fail immediately.
No further attempt will be made to locate the file.
-+*package names*+
-
++*package names*+::
Returns a list of all known/loaded packages, including internal packages.
pid
@@ -3783,7 +3790,7 @@ Integer parameters may be any integer expression.
read
~~~~
-+*read ?-nonewline? 'fileId ?length?'+
++*read* ?-nonewline? 'fileId ?length?'+
Tcl-compatible alterative version of +'fileId' *read ?-nonewline?* '?length?'+
@@ -4978,16 +4985,19 @@ aio
If +'-noclose'+ is given, the returned handle is not automatically
closed for child proceses. See `socket` for details.
-+$handle *buffering none|line|full*+::
++$handle *buffering none|line|full* ?size?+::
Sets the output buffering mode of the stream channel. +'none'+ means
that puts immediately writes output. +'line'+ means output (including
previously buffered output) is written if a newline is to be written.
+'full'+ means that data is written when the output buffer is full
- (currently approx 64KB). Note that line buffering will also write
+ (default 64KB). Size may be specified in full mode.
+ Note that line buffering will also write
once the output buffer limit is reached, even if there is no newline.
Channels usually begin in full buffering mode, unless they identify
as a tty channel, in which case line buffering is used, and `stderr`
- begins with no buffering. See also `aio puts` and `aio flush`.
+ begins with no buffering. Returns the current buffering mode (including
+ size in full mode - e.g. +'line'+ or +'full 65536+'.
+ See also `aio puts` and `aio flush`.
+$handle *close ?r(ead)|w(rite)? ?-nodelete?*+::
Closes the stream.
@@ -5075,6 +5085,12 @@ aio
expected number of bytes (including zero). Use `aio eof` to determine
if the end-of-file has been reached.
++$handle *readsize* ?size?'+::
+ Sets or returns the current size of the read buffer used
+ for read, gets and copyto.
+ Defaults to 256, but can be increased to improve performance
+ for large reads.
+
+$handle *recvfrom* 'maxlen ?addrvar?'+::
Receives a message from the datagram channel via recvfrom(2) and returns it.
At most +'maxlen'+ bytes are read. If +'addrvar'+ is specified, the sending address
@@ -5146,6 +5162,12 @@ This command returns an empty string.
See `aio read` and `aio gets` for command that use the timeout.
Note that the timeout is only used if the channel is in blocking mode.
++$handle *translation binary|text*+::
+ This has no effect on Unix platforms, but on Windows it changes the mode of the file
+ handle to binary or text. In general, use "wb" as the open mode instead, but this
+ can be useful on existing filehandles such as +stdout+ and +stderr+. It is probably
+ a good idea to do this immediately before sending any output.
+
+$handle *tty* ?settings?+::
If no arguments are given, returns a dictionary containing the tty settings for the stream.
If arguments are given, they must either be a dictionary, or +setting value \...+.
@@ -5257,7 +5279,7 @@ fconfigure
command is supported.
* `fconfigure ... -blocking` maps to `aio ndelay`
* `fconfigure ... -buffering` maps to `aio buffering`
- * `fconfigure ... -translation` is accepted but ignored
+ * `fconfigure ... -translation` maps to `aio translation` and suppports only +binary+ and +text+
[[cmd_2]]
eventloop: after, vwait, update
@@ -5758,6 +5780,11 @@ namespace
~~~~~~~~~
Provides namespace-related functions. See also: http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm
++*namespace canonical* ?current? ?name?+::
+ Returns the full name of +'name'+ within namespace '+current+'.
+ If '+current+' is not given, `namespace current` is used.
+ If neither are given, returns the current namespace (not qualified with a leading '::').
+
+*namespace code* 'script'+::
Captures the current namespace context for later execution of
the script +'script'+. It returns a new script in which script has
@@ -5769,7 +5796,7 @@ Provides namespace-related functions. See also: http://www.tcl.tk/man/tcl8.6/Tcl
+*namespace delete* '?namespace ...?'+::
Deletes all commands and variables with the given namespace prefixes.
-+*namespace ensemble create*'+::
++*namespace ensemble create*+::
Creates an ensemble command for the current namespace (requires the 'ensemble' extension').
+*namespace eval* 'namespace arg ?arg...?'+::
diff --git a/jimiocompat.c b/jimiocompat.c
index 0f789f4..44a1387 100644
--- a/jimiocompat.c
+++ b/jimiocompat.c
@@ -6,7 +6,7 @@ void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
}
-#if defined(__MINGW32__)
+#if defined(_WIN32) || defined(WIN32)
#include <sys/stat.h>
int Jim_Errno(void)
diff --git a/jimiocompat.h b/jimiocompat.h
index 0837b73..0f807a0 100644
--- a/jimiocompat.h
+++ b/jimiocompat.h
@@ -31,7 +31,7 @@ int Jim_OpenForWrite(const char *filename, int append);
*/
int Jim_OpenForRead(const char *filename);
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(_WIN32)
#ifndef STRICT
#define STRICT
#endif
@@ -69,6 +69,12 @@ int Jim_OpenForRead(const char *filename);
#define Jim_Stat _stat64
#define Jim_FileStat _fstat64
#define Jim_Lseek _lseeki64
+ #define O_TEXT _O_TEXT
+ #define O_BINARY _O_BINARY
+ #define Jim_SetMode _setmode
+ #ifndef STDIN_FILENO
+ #define STDIN_FILENO 0
+ #endif
#else
#if defined(HAVE_STAT64)
@@ -111,12 +117,21 @@ int Jim_OpenForRead(const char *filename);
#define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
#endif
#endif
-#endif
-#ifndef O_TEXT
-#define O_TEXT 0
+ #ifndef O_TEXT
+ #define O_TEXT 0
+ #endif
+
#endif
+# ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# else
+# define MAXPATHLEN JIM_PATH_LEN
+# endif
+# endif
+
/* jim-file.c */
/* Note that this is currently an internal function only.
* It does not form part of the public Jim API
diff --git a/jimsh.c b/jimsh.c
index 6104afb..e9427d1 100644
--- a/jimsh.c
+++ b/jimsh.c
@@ -37,8 +37,9 @@
#include <stdlib.h>
#include <string.h>
-#include "jim.h"
#include "jimautoconf.h"
+#include "jim.h"
+#include "jimiocompat.h"
/* From initjimsh.tcl */
extern int Jim_initjimshInit(Jim_Interp *interp);
@@ -123,6 +124,10 @@ int main(int argc, char *const argv[])
}
if (retcode != JIM_EXIT) {
JimSetArgv(interp, 0, NULL);
+ if (!isatty(STDIN_FILENO)) {
+ /* Just read from stdin and evaluate */
+ goto eval_stdin;
+ }
retcode = Jim_InteractivePrompt(interp);
}
}
@@ -145,6 +150,7 @@ int main(int argc, char *const argv[])
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
JimSetArgv(interp, argc - 2, argv + 2);
if (strcmp(argv[1], "-") == 0) {
+eval_stdin:
retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
} else {
retcode = Jim_EvalFile(interp, argv[1]);
diff --git a/linenoise.c b/linenoise.c
index 8b628fe..0d2fee5 100644
--- a/linenoise.c
+++ b/linenoise.c
@@ -1,3 +1,4 @@
+#line 1 "stringbuf.h"
#ifndef STRINGBUF_H
#define STRINGBUF_H
/**
@@ -135,6 +136,7 @@ char *sb_to_string(stringbuf *sb);
#endif
#endif
+#line 1 "stringbuf.c"
/**
* resizable string buffer
*
@@ -180,7 +182,7 @@ void sb_free(stringbuf *sb)
free(sb);
}
-void sb_realloc(stringbuf *sb, int newlen)
+static void sb_realloc(stringbuf *sb, int newlen)
{
sb->data = (char *)realloc(sb->data, newlen);
sb->remaining = newlen - sb->last;
@@ -308,6 +310,7 @@ void sb_clear(stringbuf *sb)
#endif
}
}
+#line 1 "linenoise.c"
/* linenoise.c -- guerrilla line editing library against the idea that a
* line editing lib needs to be 20,000 lines of C code.
*
@@ -425,10 +428,6 @@ void sb_clear(stringbuf *sb)
#define USE_WINCONSOLE
#ifdef __MINGW32__
#define HAVE_UNISTD_H
-#else
-/* Microsoft headers don't like old POSIX names */
-#define strdup _strdup
-#define snprintf _snprintf
#endif
#else
#include <termios.h>
@@ -451,6 +450,12 @@ void sb_clear(stringbuf *sb)
#include <stdlib.h>
#include <sys/types.h>
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* Microsoft headers don't like old POSIX names */
+#define strdup _strdup
+#define snprintf _snprintf
+#endif
+
#include "linenoise.h"
#ifndef STRINGBUF_H
#include "stringbuf.h"
@@ -488,6 +493,7 @@ enum {
static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
static int history_len = 0;
+static int history_index = 0;
static char **history = NULL;
/* Structure to contain the status of the current (being edited) line */
@@ -504,6 +510,8 @@ struct current {
stringbuf *output; /* used only during refreshLine() - output accumulator */
#if defined(USE_TERMIOS)
int fd; /* Terminal fd */
+ int pending; /* pending char fd_read_char() */
+ int query_cursor_failed; /* if 1, don't try to query the cursor position again */
#elif defined(USE_WINCONSOLE)
HANDLE outh; /* Console output handle */
HANDLE inh; /* Console input handle */
@@ -530,6 +538,16 @@ static void setCursorPos(struct current *current, int x);
static void setOutputHighlight(struct current *current, const int *props, int nprops);
static void set_current(struct current *current, const char *str);
+static int fd_isatty(struct current *current)
+{
+#ifdef USE_TERMIOS
+ return isatty(current->fd);
+#else
+ (void)current;
+ return 0;
+#endif
+}
+
void linenoiseHistoryFree(void) {
if (history) {
int j;
@@ -832,25 +850,31 @@ void linenoiseClearScreen(void)
}
/**
- * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
+ * Reads a char from 'current->fd', waiting at most 'timeout' milliseconds.
*
* A timeout of -1 means to wait forever.
*
* Returns -1 if no char is received within the time or an error occurs.
*/
-static int fd_read_char(int fd, int timeout)
+static int fd_read_char(struct current *current, int timeout)
{
struct pollfd p;
unsigned char c;
- p.fd = fd;
+ if (current->pending) {
+ c = current->pending;
+ current->pending = 0;
+ return c;
+ }
+
+ p.fd = current->fd;
p.events = POLLIN;
if (poll(&p, 1, timeout) == 0) {
/* timeout */
return -1;
}
- if (read(fd, &c, 1) != 1) {
+ if (read(current->fd, &c, 1) != 1) {
return -1;
}
return c;
@@ -868,7 +892,11 @@ static int fd_read(struct current *current)
int i;
int c;
- if (read(current->fd, &buf[0], 1) != 1) {
+ if (current->pending) {
+ buf[0] = current->pending;
+ current->pending = 0;
+ }
+ else if (read(current->fd, &buf[0], 1) != 1) {
return -1;
}
n = utf8_charlen(buf[0]);
@@ -884,7 +912,7 @@ static int fd_read(struct current *current)
utf8_tounicode(buf, &c);
return c;
#else
- return fd_read_char(current->fd, -1);
+ return fd_read_char(current, -1);
#endif
}
@@ -898,6 +926,11 @@ static int queryCursor(struct current *current, int* cols)
struct esc_parser parser;
int ch;
+ if (current->query_cursor_failed) {
+ /* If it every fails, don't try again */
+ return 0;
+ }
+
/* Should not be buffering this output, it needs to go immediately */
assert(current->output == NULL);
@@ -906,7 +939,7 @@ static int queryCursor(struct current *current, int* cols)
/* Parse the response: ESC [ rows ; cols R */
initParseEscapeSeq(&parser, 'R');
- while ((ch = fd_read_char(current->fd, 100)) > 0) {
+ while ((ch = fd_read_char(current, 100)) > 0) {
switch (parseEscapeSequence(&parser, ch)) {
default:
continue;
@@ -917,11 +950,14 @@ static int queryCursor(struct current *current, int* cols)
}
break;
case EP_ERROR:
+ /* Push back the character that caused the error */
+ current->pending = ch;
break;
}
/* failed */
break;
}
+ current->query_cursor_failed = 1;
return 0;
}
@@ -988,20 +1024,20 @@ static int getWindowSize(struct current *current)
* If no additional char is received within a short time,
* CHAR_ESCAPE is returned.
*/
-static int check_special(int fd)
+static int check_special(struct current *current)
{
- int c = fd_read_char(fd, 50);
+ int c = fd_read_char(current, 50);
int c2;
if (c < 0) {
return CHAR_ESCAPE;
}
- else if (c >= 'a' && c <= 'z') {
- /* esc-a => meta-a */
- return meta(c);
- }
+ else if (c >= 'a' && c <= 'z') {
+ /* esc-a => meta-a */
+ return meta(c);
+ }
- c2 = fd_read_char(fd, 50);
+ c2 = fd_read_char(current, 50);
if (c2 < 0) {
return c2;
}
@@ -1024,7 +1060,7 @@ static int check_special(int fd)
}
if (c == '[' && c2 >= '1' && c2 <= '8') {
/* extended escape */
- c = fd_read_char(fd, 50);
+ c = fd_read_char(current, 50);
if (c == '~') {
switch (c2) {
case '2':
@@ -1043,7 +1079,7 @@ static int check_special(int fd)
}
while (c != -1 && c != '~') {
/* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
- c = fd_read_char(fd, 50);
+ c = fd_read_char(current, 50);
}
}
@@ -1112,7 +1148,7 @@ static linenoiseHintsCallback *hintsCallback = NULL;
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
static void *hintsUserdata = NULL;
-static void beep() {
+static void beep(void) {
#ifdef USE_TERMIOS
fprintf(stderr, "\x7");
fflush(stderr);
@@ -1783,6 +1819,26 @@ static int skip_nonspace(struct current *current, int dir)
return skip_space_nonspace(current, dir, 0);
}
+static void set_history_index(struct current *current, int new_index)
+{
+ if (history_len > 1) {
+ /* Update the current history entry before to
+ * overwrite it with the next one. */
+ free(history[history_len - 1 - history_index]);
+ history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
+ /* Show the new entry */
+ history_index = new_index;
+ if (history_index < 0) {
+ history_index = 0;
+ } else if (history_index >= history_len) {
+ history_index = history_len - 1;
+ } else {
+ set_current(current, history[history_len - 1 - history_index]);
+ refreshLine(current);
+ }
+ }
+}
+
/**
* Returns the keycode to process, or 0 if none.
*/
@@ -1816,17 +1872,17 @@ static int reverseIncrementalSearch(struct current *current)
}
#ifdef USE_TERMIOS
if (c == CHAR_ESCAPE) {
- c = check_special(current->fd);
+ c = check_special(current);
}
#endif
- if (c == ctrl('P') || c == SPECIAL_UP) {
+ if (c == ctrl('R')) {
/* Search for the previous (earlier) match */
if (searchpos > 0) {
searchpos--;
}
skipsame = 1;
}
- else if (c == ctrl('N') || c == SPECIAL_DOWN) {
+ else if (c == ctrl('S')) {
/* Search for the next (later) match */
if (searchpos < history_len) {
searchpos++;
@@ -1834,6 +1890,18 @@ static int reverseIncrementalSearch(struct current *current)
searchdir = 1;
skipsame = 1;
}
+ else if (c == ctrl('P') || c == SPECIAL_UP) {
+ /* Exit Ctrl-R mode and go to the previous history line from the current search pos */
+ set_history_index(current, history_len - searchpos);
+ c = 0;
+ break;
+ }
+ else if (c == ctrl('N') || c == SPECIAL_DOWN) {
+ /* Exit Ctrl-R mode and go to the next history line from the current search pos */
+ set_history_index(current, history_len - searchpos - 2);
+ c = 0;
+ break;
+ }
else if (c >= ' ' && c <= '~') {
/* >= here to allow for null terminator */
if (rlen >= (int)sizeof(rbuf) - MAX_UTF8_LEN) {
@@ -1863,6 +1931,7 @@ static int reverseIncrementalSearch(struct current *current)
continue;
}
/* Copy the matching line and set the cursor position */
+ history_index = history_len - 1 - searchpos;
set_current(current,history[searchpos]);
current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
break;
@@ -1878,25 +1947,25 @@ static int reverseIncrementalSearch(struct current *current)
if (c == ctrl('G') || c == ctrl('C')) {
/* ctrl-g terminates the search with no effect */
set_current(current, "");
+ history_index = 0;
c = 0;
}
else if (c == ctrl('J')) {
/* ctrl-j terminates the search leaving the buffer in place */
+ history_index = 0;
c = 0;
}
-
/* Go process the char normally */
refreshLine(current);
return c;
}
static int linenoiseEdit(struct current *current) {
- int history_index = 0;
+ history_index = 0;
refreshLine(current);
while(1) {
- int dir = -1;
int c = fd_read(current);
#ifndef NO_COMPLETION
@@ -1915,7 +1984,7 @@ static int linenoiseEdit(struct current *current) {
#ifdef USE_TERMIOS
if (c == CHAR_ESCAPE) { /* escape sequence */
- c = check_special(current->fd);
+ c = check_special(current);
}
#endif
if (c == -1) {
@@ -2051,36 +2120,19 @@ static int linenoiseEdit(struct current *current) {
refreshLine(current);
}
break;
- case SPECIAL_PAGE_UP:
- dir = history_len - history_index - 1; /* move to start of history */
- goto history_navigation;
- case SPECIAL_PAGE_DOWN:
- dir = -history_index; /* move to 0 == end of history, i.e. current */
- goto history_navigation;
+ case SPECIAL_PAGE_UP: /* move to start of history */
+ set_history_index(current, history_len - 1);
+ break;
+ case SPECIAL_PAGE_DOWN: /* move to 0 == end of history, i.e. current */
+ set_history_index(current, 0);
+ break;
case ctrl('P'):
case SPECIAL_UP:
- dir = 1;
- goto history_navigation;
+ set_history_index(current, history_index + 1);
+ break;
case ctrl('N'):
case SPECIAL_DOWN:
-history_navigation:
- if (history_len > 1) {
- /* Update the current history entry before to
- * overwrite it with tne next one. */
- free(history[history_len - 1 - history_index]);
- history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
- /* Show the new entry */
- history_index += dir;
- if (history_index < 0) {
- history_index = 0;
- break;
- } else if (history_index >= history_len) {
- history_index = history_len - 1;
- break;
- }
- set_current(current, history[history_len - 1 - history_index]);
- refreshLine(current);
- }
+ set_history_index(current, history_index - 1);
break;
case ctrl('A'): /* Ctrl+a, go to the start of the line */
case SPECIAL_HOME:
@@ -2115,10 +2167,10 @@ history_navigation:
refreshLine(current);
break;
default:
- if (c >= meta('a') && c <= meta('z')) {
- /* Don't insert meta chars that are not bound */
- break;
- }
+ if (c >= meta('a') && c <= meta('z')) {
+ /* Don't insert meta chars that are not bound */
+ break;
+ }
/* Only tab is allowed without ^V */
if (c == '\t' || c >= ' ') {
if (insert_char(current, current->pos, c) == 1) {
@@ -2169,7 +2221,7 @@ static stringbuf *sb_getline(FILE *fh)
/* ignore the effect of character count for partial utf8 sequences */
sb_append_len(sb, &ch, 1);
}
- if (n == 0) {
+ if (n == 0 || sb->data == NULL) {
sb_free(sb);
return NULL;
}
@@ -2188,6 +2240,10 @@ char *linenoiseWithInitial(const char *prompt, const char *initial)
printf("%s", prompt);
fflush(stdout);
sb = sb_getline(stdin);
+ if (sb && !fd_isatty(&current)) {
+ printf("%s\n", sb_str(sb));
+ fflush(stdout);
+ }
}
else {
current.buf = sb_alloc();
@@ -2195,9 +2251,9 @@ char *linenoiseWithInitial(const char *prompt, const char *initial)
current.nrows = 1;
current.prompt = prompt;
- /* The latest history entry is always our current buffer */
- linenoiseHistoryAdd(initial);
- set_current(&current, initial);
+ /* The latest history entry is always our current buffer */
+ linenoiseHistoryAdd(initial);
+ set_current(&current, initial);
count = linenoiseEdit(&current);
@@ -2216,11 +2272,11 @@ char *linenoiseWithInitial(const char *prompt, const char *initial)
char *linenoise(const char *prompt)
{
- return linenoiseWithInitial(prompt, "");
+ return linenoiseWithInitial(prompt, "");
}
/* Using a circular buffer is smarter, but a bit more complex to handle. */
-int linenoiseHistoryAddAllocated(char *line) {
+static int linenoiseHistoryAddAllocated(char *line) {
if (history_max_len == 0) {
notinserted:
diff --git a/make-bootstrap-jim b/make-bootstrap-jim
index 67ac71b..3a10ac6 100755
--- a/make-bootstrap-jim
+++ b/make-bootstrap-jim
@@ -40,16 +40,16 @@ EOF
echo "}"
}
-cexts="aio readdir regexp file exec clock array posix"
+cexts="aio readdir regexp file exec clock array"
tclexts="bootstrap initjimsh glob stdlib tclcompat"
# Note ordering
-allexts="bootstrap aio readdir regexp file glob exec posix clock array stdlib tclcompat"
+allexts="bootstrap aio readdir regexp file glob exec clock array stdlib tclcompat"
echo "/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */"
# define some core features
-for i in JIM_TCL_COMPAT JIM_ANSIC JIM_REGEXP HAVE_NO_AUTOCONF JIM_TINY _JIMAUTOCONF_H; do
+for i in JIM_COMPAT JIM_ANSIC JIM_REGEXP HAVE_NO_AUTOCONF JIM_TINY _JIMAUTOCONF_H; do
echo "#define $i"
done
echo '#define TCL_LIBRARY "."'
@@ -92,7 +92,11 @@ cat <<EOF
#else
#define _GNU_SOURCE
#endif
+#ifndef __ixemul__
#define HAVE_FORK
+#else
+#define HAVE_VFORK
+#endif
#define HAVE_WAITPID
#define HAVE_ISATTY
#define HAVE_MKSTEMP
diff --git a/make-index b/make-index
index 5071d88..6911d03 100755
--- a/make-index
+++ b/make-index
@@ -9,8 +9,16 @@ set lines {}
set commands {}
array set cdict {}
set c 0
+set numlist 1
while {[gets $f buf] >= 0} {
+ # Handle auto numbered lists
+ if {[string match "#. *" $buf]} {
+ set buf "$numlist. [string range $buf 3 end]"
+ incr numlist
+ } elseif {$buf eq ""} {
+ set numlist 1
+ }
if {[string match "~~*" $buf]} {
if {[string match "*: *" $prev]} {
incr c
@@ -29,6 +37,8 @@ while {[gets $f buf] >= 0} {
}
}
}
+ # Handle TIP nnn references
+ regsub -all {TIP ([0-9]+)} $buf {https://core.tcl-lang.org/tips/doc/main/tip/\1.md[TIP \1]} buf
lappend lines $buf
set prev $buf
}
diff --git a/regtest.tcl b/regtest.tcl
index 5e66aa3..99a65fe 100644
--- a/regtest.tcl
+++ b/regtest.tcl
@@ -399,6 +399,13 @@ set json {
catch {json::decode $json}
puts "TEST 56 PASSED"
+if {[exists -command debug]} {
+ set f [open /dev/null w]
+ $f puts [debug objects]
+ $f close
+}
+puts "TEST 57 PASSED"
+
# TAKE THE FOLLOWING puts AS LAST LINE
puts "--- ALL TESTS PASSED ---"
diff --git a/tclcompat.tcl b/tclcompat.tcl
index 3485d00..14ce688 100644
--- a/tclcompat.tcl
+++ b/tclcompat.tcl
@@ -48,7 +48,7 @@ if {[exists -command stdout]} {
$f buffering $v
}
-tr* {
- # Just ignore -translation
+ $f translation $v
}
default {
return -code error "fconfigure: unknown option $n"
@@ -137,9 +137,6 @@ proc popen {cmd {mode r}} {
if {$cmd eq "pid"} {
return $pids
}
- if {$cmd eq "getfd"} {
- $f getfd
- }
if {$cmd eq "close"} {
$f close
# And wait for the child processes to complete
diff --git a/tcltest.tcl b/tcltest.tcl
index 1f13365..8d3d51e 100644
--- a/tcltest.tcl
+++ b/tcltest.tcl
@@ -168,8 +168,8 @@ proc basename-stacktrace {stacktrace} {
# If tcl, just use tcltest
if {[catch {info version}]} {
- package require Tcl 8.5
- package require tcltest 2.1
+ package require Tcl 8.5-
+ package require tcltest 2.1-
namespace import tcltest::*
if {$testinfo(verbose)} {
@@ -185,7 +185,6 @@ if {[catch {info version}]} {
incr skip
for {set level $skip} {$level < [info frame] - $last} {incr level} {
set frame [info frame -$level]
- puts $frame
if {[dict get $frame type] ne "source"} {
continue
}
diff --git a/tests/breakcontinue.test b/tests/breakcont.test
index ddf9438..ddf9438 100644
--- a/tests/breakcontinue.test
+++ b/tests/breakcont.test
diff --git a/tests/event.test b/tests/event.test
index 4f0b3c7..a81128e 100644
--- a/tests/event.test
+++ b/tests/event.test
@@ -78,18 +78,24 @@ test event-7.4 {bgerror throws an error} -constraints jim -body {
}
after 0 {error err1}
update
- }
+ } 2>gorp.err
+ set f [open gorp.err]
+ set err [read $f]
+ close $f
+ set err
} -result {stdin:3: Error: inside bgerror
Traceback (most recent call last):
File "stdin", line 6
bgerror err1
File "stdin", line 3, in bgerror
- error {inside bgerror}}
+ error {inside bgerror}
+} -cleanup {
+ file delete gorp.err
+}
# end of bgerror tests
catch {rename bgerror {}}
-
test event-10.1 {Tcl_Exit procedure} exec {
set cmd [list exec [info nameofexecutable] "<<exit 3"]
list [catch $cmd msg] [lindex $errorCode 0] \
@@ -170,9 +176,10 @@ test event-11.6 {Tcl_VwaitCmd procedure: round robin scheduling, same source} {s
list $x $y $z
} {3 3 done}
-test event-12.1 {Tcl_UpdateCmd procedure} {
- list [catch {update a b} msg] $msg
-} {1 {wrong # args: should be "update ?idletasks?"}}
+test event-12.1 {Tcl_UpdateCmd procedure - usage} -body {
+ update a b
+} -returnCodes error -result {wrong # args: should be "update ?idletasks?"}
+
test event-12.3 {Tcl_UpdateCmd procedure} {
foreach i [after info] {
after cancel $i
@@ -211,8 +218,8 @@ test event-13.1 "vwait/signal" signal {
signal handle ALRM
list [catch -signal {
alarm 0.1
- # This is just to prevent the vwait from exiting immediately
- stdin readable { format test }
+ # prevent the vwait from exiting immediately
+ after 1000 { }
vwait forever
} msg] $msg
} {5 SIGALRM}
diff --git a/tests/expr.test b/tests/expr.test
index 7e26c0a..bc52afd 100644
--- a/tests/expr.test
+++ b/tests/expr.test
@@ -154,5 +154,12 @@ test expr-5.3 {boolean in expression} {
expr {true ? 4 : 5}
} {4}
+test expr-6.1 "Unary negation on boolean - should return error" -body {
+ expr {-true}
+} -returnCodes error -result {can't use non-numeric string as operand of "-"}
+
+test expr-6.2 "Unary plus on boolean - should return error" -body {
+ expr {+true}
+} -returnCodes error -result {can't use non-numeric string as operand of "+"}
testreport
diff --git a/tests/forget-test.tcl b/tests/forget-test.tcl
new file mode 100644
index 0000000..8d4289b
--- /dev/null
+++ b/tests/forget-test.tcl
@@ -0,0 +1,3 @@
+# This is a dummy package used for testing package forget
+
+set forgotten 1
diff --git a/tests/io.test b/tests/io.test
new file mode 100644
index 0000000..1b06439
--- /dev/null
+++ b/tests/io.test
@@ -0,0 +1,26 @@
+source [file dirname [info script]]/testing.tcl
+
+# This is a proxy for tcl || tclcompat
+constraint cmd fconfigure
+
+# The tests in this file are intended to test Tcl-compatible I/O features
+
+test io-1.1 {translation binary} -body {
+ # write a file via stdout in binary mode
+ # This will always work on Unix
+ set script {
+ fconfigure stdout -translation binary
+ puts line1
+ puts line2
+ }
+ exec [info nameofexecutable] << $script >binary.out
+ # Read it back in binary mode
+ set f [open binary.out rb]
+ set buf [read $f]
+ close $f
+ set buf
+} -cleanup {
+ file delete binary.out
+} -result "line1\nline2\n"
+
+testreport
diff --git a/tests/jimsh.test b/tests/jimsh.test
index a02ed9f..8faf2d8 100644
--- a/tests/jimsh.test
+++ b/tests/jimsh.test
@@ -28,29 +28,17 @@ test jimsh-1.5 {jimsh --version} {
test jimsh-1.6 {jimsh -e with error} -body {
exec [info nameofexecutable] -e blah
-} -returnCodes error -result {invalid command name "blah"}
+} -returnCodes error -match glob -result {invalid command name "blah"*}
-test jimsh-1.7 {jimsh prompt} -body {
- exec [info nameofexecutable] << "set x 3\nincr x\nexit \$x\n"
-} -returnCodes error -match glob -result {Welcome to Jim version *
-. 3
-. 4
-. }
+test jimsh-1.7 {jimsh exit code} -body {
+ set script "set x 3\nincr x\nexit \$x\n"
+ set rc [catch {exec [info nameofexecutable] << $script} msg opts]
+ lassign [dict get $opts -errorcode] status pid exitcode
+ list $rc $status $exitcode
+} -result {1 CHILDSTATUS 4}
-test jimsh-1.8 {jimsh prompt - error} -body {
+test jimsh-1.8 {jimsh error} -body {
exec [info nameofexecutable] << "blah\n"
-} -match glob -result {Welcome to Jim version *
-. invalid command name "blah"
-\[error\] . }
-
-test jimsh-1.9 {jimsh prompt - error} -body {
- exec [info nameofexecutable] << "throw 99\n"
-} -match glob -result {Welcome to Jim version *
-. \[99\] . }
-
-test jimsh-1.10 {jimsh prompt - continuation} -body {
- exec [info nameofexecutable] << "set x {\nabc\n}\n"
-} -match glob -result "Welcome to Jim version *\n. {> {> \nabc\n\n. "
-
+} -returnCodes error -match glob -result {stdin:1: Error: invalid command name "blah"*}
testreport
diff --git a/tests/package.test b/tests/package.test
index b8afa18..1484bd6 100644
--- a/tests/package.test
+++ b/tests/package.test
@@ -20,5 +20,17 @@ test package-1.3 {package names} -body {
expr {"stdlib" in [package names]}
} -result 1
+test package-2.1 {package forget} -body {
+ # First pretend the package was loaded
+ package provide forget-test
+ # Now it won't load anything
+ package require forget-test
+ # Now forget it and another unloaded test
+ package forget forget-test missing
+ # And load the local package
+ package require forget-test
+ info exists forgotten
+} -result 1
+
testreport
diff --git a/tests/try.test b/tests/try.test
index 0d76865..36a9bf9 100644
--- a/tests/try.test
+++ b/tests/try.test
@@ -104,7 +104,7 @@ test try-2.1 "try ... trap" -body {
try {
a
} trap CUSTOM {msg opts} {
- list $msg $opts(-code) $opts(-errorcode)
+ list $msg [dict get $opts -code] [dict get $opts -errorcode]
}
} -result {{custom errorcode} 1 {CUSTOM RESULT}}
@@ -140,6 +140,13 @@ test try-2.5 "trap match first but not second" -body {
}
} -returnCodes error -result failed
+test try-2.6 "trap match too long" -body {
+ try {
+ apply {{} {return -code error -errorcode {FOO BAR} failed}}
+ } trap {FOO BAR BAZ} {msg opts} {
+ list trapped
+ }
+} -returnCodes error -result failed
proc c {} {
try {