Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update autosetup to the latest version
Baptiste Daroussin committed 6 years ago
commit 1ff0a1542dd45d8f838d7a34a36e7bdf18e3835c
parent aaf3eba
22 files changed +2616 -2210
modified Makefile.autosetup
@@ -1,9 +1,12 @@
include @builddir@/mk/defs.mk
-
DIRS=	external compat libpkg/repo libpkg src docs scripts @testsdir@
+
DIRS=	external compat libpkg/repo libpkg src docs scripts
+
@if TESTS
+
DIRS+=	tests
+
@endif

include $(MK)/dir.mk

-
@if coverage == "1"
+
@if coverage
check: clean-profiles

clean-profiles:
@@ -11,7 +14,7 @@ clean-profiles:
@endif

check: all
-
@if testsdir == "tests"
+
@if TESTS
	export LLVM_PROFILE_FILE=/tmp/pkg.%p.profraw
	if [ "$(HTML)" != "" ]; then \
		args="-r $(top_builddir)/res.db" ; \
@@ -26,7 +29,7 @@ check: all
	exit $${FAILED}
@endif

-
@if coverage == "1"
+
@if coverage
check-coverage: check
	llvm-profdata merge --output=pkg.profdata /tmp/pkg.*.profraw

modified auto.def
@@ -204,7 +204,7 @@ foreach header [list endian.h sys/endian.h] {
}

if {[string match *-darwin* [get-define host]]} {
-
	define libabidir libmachista
+
	define libmachista
	define waflags ""
	define nowaflags ""
} else {
@@ -219,17 +219,17 @@ if {[string match *-darwin* [get-define host]]} {
		cc-with { -libs { -lelf } } {
			if {[cc-check-functions gelf_getehdr]} {
				define-feature libelf
+
				define libelf-external
				define-append EXTRA_LIBS -lelf
-
				define libabidir ""
				cc-check-types Elf_Note
			} else {
+
				define libelf-internal
				define-feature libelf 0
-
				define libabidir "libelf"
			}
		}
	} else {
		define-feature libelf 0
-
		define libabidir "libelf"
+
		define libelf-internal
	}
}

@@ -261,11 +261,10 @@ if {[opt-bool with-coverage]} {
	}
}

-
define testsdir ""
if {[pkg-config-init 0]} {
# atf
	if {[pkg-config atf-c] && [cc-check-progs kyua]} {
-
		define testsdir tests
+
		define TESTS
		puts "test suite will be built"
	} else {
		puts "Skipping test suite"
modified autosetup/README.autosetup
@@ -1,4 +1,4 @@
-
README.autosetup created by autosetup v0.6.8
+
README.autosetup created by autosetup v0.6.9+

This is the autosetup directory for a local install of autosetup.
It contains autosetup, support files and loadable modules.
modified autosetup/autosetup
@@ -5,7 +5,8 @@
# \
dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"

-
set autosetup(version) 0.6.8
+
# Note that the version has a trailing + on unreleased versions
+
set autosetup(version) 0.6.9+

# Can be set to 1 to debug early-init problems
set autosetup(debug) [expr {"--debug" in $argv}]
@@ -81,6 +82,8 @@ proc main {argv} {
	set autosetup(optionhelp) {}
	set autosetup(showhelp) 0

+
	use util
+

	# Parse options
	use getopt

@@ -90,13 +93,13 @@ proc main {argv} {

	#"=Core Options:"
	options-add {
-
		help:=local  => "display help and options. Optionally specify a module name, such as --help=system"
+
		help:=all       => "display help and options. Optional: module name, such as --help=system"
		licence license => "display the autosetup license"
-
		version      => "display the version of autosetup"
+
		version         => "display the version of autosetup"
		ref:=text manual:=text
		reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
-
		debug        => "display debugging output as autosetup runs"
-
		install:=.   => "install autosetup to the current or given directory"
+
		debug           => "display debugging output as autosetup runs"
+
		install:=.      => "install autosetup to the current or given directory"
	}
	if {$autosetup(installed)} {
		# hidden options so we can produce a nice error
@@ -201,19 +204,26 @@ proc main {argv} {

	autosetup_add_dep $autosetup(autodef)

-
	define CONFIGURE_OPTS ""
+
	# Add $argv to CONFIGURE_OPTS, but ignore duplicates and quote if needed
+
	set configure_opts {}
	foreach arg $autosetup(argv) {
-
		define-append CONFIGURE_OPTS [quote-if-needed $arg]
+
		set quoted [quote-if-needed $arg]
+
		# O(n^2), but n will be small
+
		if {$quoted ni $configure_opts} {
+
			lappend configure_opts $quoted
+
		}
	}
+
	define CONFIGURE_OPTS [join $configure_opts]
	define AUTOREMAKE [file-normalize $autosetup(exe)]
	define-append AUTOREMAKE [get-define CONFIGURE_OPTS]


	# Log how we were invoked
	configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
+
	configlog "Tclsh: [info nameofexecutable]"

-
	# Note that auto.def is *not* loaded in the global scope
-
	source $autosetup(autodef)
+
	# Load auto.def as module "auto.def"
+
	autosetup_load_module auto.def source $autosetup(autodef)

	# Could warn here if options {} was not specified

@@ -338,8 +348,8 @@ proc opt-str {names varname args} {
	if {![info exists result]} {
		# No user-specified value. Has options-defaults been set?
		foreach opt $names {
-
			if {[dict exists $::autosetup(options-defaults) $opt]} {
-
				set result [dict get $autosetup(options-defaults) $opt]
+
			if {[dict exists $::autosetup(optdefault) $opt]} {
+
				set result [dict get $autosetup(optdefault) $opt]
			}
		}
	}
@@ -371,7 +381,7 @@ proc option-check-names {args} {
# Parse the option definition in $opts and update
# ::autosetup(setoptions) and ::autosetup(optionhelp) appropriately
#
-
proc options-add {opts {header ""}} {
+
proc options-add {opts} {
	global autosetup

	# First weed out comment lines
@@ -387,8 +397,7 @@ proc options-add {opts {header ""}} {
		set opt [lindex $opts $i]
		if {[string match =* $opt]} {
			# This is a special heading
-
			lappend autosetup(optionhelp) $opt ""
-
			set header {}
+
			lappend autosetup(optionhelp) [list $opt $autosetup(module)]
			continue
		}
		unset -nocomplain defaultvalue equal value
@@ -449,8 +458,8 @@ proc options-add {opts {header ""}} {
			# String option.
			lappend autosetup(options) $name

-
			if {$colon eq ":"} {
-
				# Was ":name=default" given?
+
			if {$equal ne "="} {
+
				# Was the option given as "name:value=default"?
				# If so, set $value to the display name and $defaultvalue to the default
				# (This is the preferred way to set a default value for a string option)
				if {[regexp {^([^=]+)=(.*)$} $value -> value defaultvalue]} {
@@ -464,9 +473,9 @@ proc options-add {opts {header ""}} {
				set defaultvalue [dict get $autosetup(options-defaults) $name]
				dict set autosetup(optdefault) $name $defaultvalue
			} elseif {![info exists defaultvalue]} {
-
				# For backward compatiblity, if ":name" was given, use name as both
-
				# the display text and the default value, but only if the user
-
				# specified the option without the value
+
				# No default value was given by value=default or options-defaults
+
				# so use the value as the default when the plain option with no
+
				# value is given (.e.g. just --opt instead of --opt=value)
				set defaultvalue $value
			}

@@ -505,13 +514,8 @@ proc options-add {opts {header ""}} {
			if {[info exists defaultvalue]} {
				set desc [string map [list @default@ $defaultvalue] $desc]
			}
-
			#string match \n* $desc
-
			if {$header ne ""} {
-
				lappend autosetup(optionhelp) $header ""
-
				set header ""
-
			}
			# A multi-line description
-
			lappend autosetup(optionhelp) $opthelp $desc
+
			lappend autosetup(optionhelp) [list $opthelp $autosetup(module) $desc]
			incr i 2
		}
	}
@@ -519,21 +523,9 @@ proc options-add {opts {header ""}} {

# @module-options optionlist
#
-
# Like 'options', but used within a module.
+
# Deprecated. Simply use 'options' from within a module.
proc module-options {opts} {
-
	set header ""
-
	if {$::autosetup(showhelp) > 1 && [llength $opts]} {
-
		set header "Module Options:"
-
	}
-
	options-add $opts $header
-

-
	if {$::autosetup(showhelp)} {
-
		# Ensure that the module isn't executed on --help
-
		# We are running under eval or source, so use break
-
		# to prevent further execution
-
		#return -code break -level 2
-
		return -code break
-
	}
+
	options $opts
}

proc max {a b} {
@@ -562,10 +554,17 @@ proc options-wrap-desc {text length firstprefix nextprefix initial} {
	}
}

-
proc options-show {} {
+
# Display options (from $autosetup(optionhelp)) for modules that match
+
# glob pattern $what
+
proc options-show {what} {
+
	set local 0
	# Determine the max option width
	set max 0
-
	foreach {opt desc} $::autosetup(optionhelp) {
+
	foreach help $::autosetup(optionhelp) {
+
		lassign $help opt module desc
+
		if {![string match $what $module]} {
+
			continue
+
		}
		if {[string match =* $opt] || [string match \n* $desc]} {
			continue
		}
@@ -578,13 +577,23 @@ proc options-show {} {
	}
	incr cols -1
	# Now output
-
	foreach {opt desc} $::autosetup(optionhelp) {
+
	foreach help $::autosetup(optionhelp) {
+
		lassign $help opt module desc
+
		if {![string match $what $module]} {
+
			continue
+
		}
+
		if {$local == 0 && $module eq "auto.def"} {
+
			puts "Local Options:"
+
			incr local
+
		}
		if {[string match =* $opt]} {
+
			# Output a special heading line"
			puts [string range $opt 1 end]
			continue
		}
		puts -nonewline "  [format %-${max}s $opt]"
		if {[string match \n* $desc]} {
+
			# Output a pre-formatted help description as-is
			puts $desc
		} else {
			options-wrap-desc [string trim $desc] $cols "  " $indent [expr $max + 2]
@@ -606,12 +615,16 @@ proc options-show {} {
# If 'name=1' is used to make the option enabled by default, the description should reflect
# that with text like "Disable support for ...".
#
-
# An argument option (one which takes a parameter) is of the form:
+
# An argument option (one which takes a parameter) is of one of the following forms:
#
-
## name:[=]value  => "Description of this option"
+
## name:value         => "Description of this option"
+
## name:value=default => "Description of this option with a default value"
+
## name:=value        => "Description of this option with an optional value"
#
# If the 'name:value' form is used, the value must be provided with the option (as '--name=myvalue').
-
# If the 'name:=value' form is used, the value is optional and the given value is used as the default
+
# If the 'name:value=default' form is used, the option has the given default value even if not
+
# specified by the user.
+
# If the 'name:=value' form is used, the value is optional and the given value is used
# if it is not provided.
#
# The description may contain '@default@', in which case it will be replaced with the default
@@ -625,19 +638,22 @@ proc options-show {} {
## lfs=1 largefile=1 => "Disable large file support"
#
proc options {optlist} {
-
	# Allow options as a list or args
-
	options-add $optlist "Local Options:"
+
	global autosetup

-
	if {$::autosetup(showhelp)} {
-
		options-show
-
		exit 0
+
	options-add $optlist
+

+
	if {$autosetup(showhelp)} {
+
		# If --help, stop now to show help
+
		return -code break
	}

-
	# Check for invalid options
-
	if {[opt-bool option-checking]} {
-
		foreach o [dict keys $::autosetup(getopt)] {
-
			if {$o ni $::autosetup(options)} {
-
				user-error "Unknown option --$o"
+
	if {$autosetup(module) eq "auto.def"} {
+
		# Check for invalid options
+
		if {[opt-bool option-checking]} {
+
			foreach o [dict keys $::autosetup(getopt)] {
+
				if {$o ni $::autosetup(options)} {
+
					user-error "Unknown option --$o"
+
				}
			}
		}
	}
@@ -707,6 +723,9 @@ proc define-append {name args} {
	if {[get-define $name ""] ne ""} {
		# Avoid duplicates
		foreach arg $args {
+
			if {$arg eq ""} {
+
				continue
+
			}
			set found 0
			foreach str [split $::define($name) " "] {
				if {$str eq $arg} {
@@ -745,6 +764,18 @@ proc is-defined {name} {
	info exists ::define($name)
}

+
# @is-define-set name
+
#
+
# Returns 1 if the given variable is defined and is set
+
# to a value other than "" or 0
+
#
+
proc is-define-set {name} {
+
	if {[get-define $name] in {0 ""}} {
+
		return 0
+
	}
+
	return 1
+
}
+

# @all-defines
#
# Returns a dictionary (name, value list) of all defined variables.
@@ -1040,7 +1071,6 @@ proc maybe-show-timestamp {} {
# A fatal error is generated if the current version is less than that required.
#
proc autosetup-require-version {required} {
-
	use util
	if {[compare-versions $::autosetup(version) $required] < 0} {
		user-error "autosetup version $required is required, but this is $::autosetup(version)"
	}
@@ -1155,8 +1185,9 @@ proc use {args} {
			continue
		}
		set libmodule($m) 1
+

		if {[info exists modsource(${m}.tcl)]} {
-
			automf_load eval $modsource(${m}.tcl)
+
			autosetup_load_module $m eval $modsource(${m}.tcl)
		} else {
			set locs [list ${m}.tcl ${m}/init.tcl]
			set found 0
@@ -1176,7 +1207,7 @@ proc use {args} {
				# For the convenience of the "use" source, point to the directory
				# it is being loaded from
				set ::usedir [file dirname $source]
-
				automf_load source $source
+
				autosetup_load_module $m source $source
				autosetup_add_dep $source
			} else {
				autosetup-error "use: No such module: $m"
@@ -1189,19 +1220,24 @@ proc autosetup_load_auto_modules {} {
	global autosetup modsource
	# First load any embedded auto modules
	foreach mod [array names modsource *.auto] {
-
		automf_load eval $modsource($mod)
+
		autosetup_load_module $mod eval $modsource($mod)
	}
	# Now any external auto modules
	foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
-
		automf_load source $file
+
		autosetup_load_module [file tail $file] source $file
	}
}

# Load module source in the global scope by executing the given command
-
proc automf_load {args} {
+
proc autosetup_load_module {module args} {
+
	global autosetup
+
	set prev $autosetup(module)
+
	set autosetup(module) $module
+

	if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
		autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
	}
+
	set autosetup(module) $prev
}

# Initial settings
@@ -1213,6 +1249,7 @@ set autosetup(sysinstall) 0
set autosetup(msg-checking) 0
set autosetup(msg-quiet) 0
set autosetup(inittypes) {}
+
set autosetup(module) autosetup

# Embedded modules are inserted below here
set autosetup(installed) 1
@@ -1295,7 +1332,7 @@ set modsource(formatting.tcl) {

# Module which provides common text formatting

-
# This is designed for documenation which looks like:
+
# This is designed for documentation which looks like:
# code {...}
# or
# code {
@@ -1418,22 +1455,22 @@ proc autosetup_help {what} {
    puts "This is [autosetup_version], a build environment \"autoconfigurator\""
    puts "See the documentation online at http://msteveb.github.com/autosetup/\n"

-
    if {$what eq "local"} {
+
    if {$what in {all local}} {
+
        # Need to load auto.def now
        if {[file exists $::autosetup(autodef)]} {
-
            # This relies on auto.def having a call to 'options'
-
            # which will display options and quit
-
            source $::autosetup(autodef)
-
        } else {
-
            options-show
+
            # Load auto.def as module "auto.def"
+
            autosetup_load_module auto.def source $::autosetup(autodef)
        }
-
    } else {
-
        incr ::autosetup(showhelp)
-
        if {[catch {use $what}]} {
-
            user-error "Unknown module: $what"
+
        if {$what eq "all"} {
+
            set what *
        } else {
-
            options-show
+
            set what auto.def
        }
+
    } else {
+
        use $what
+
        puts "Options for module $what:"
    }
+
    options-show $what
    exit 0
}

@@ -1686,7 +1723,7 @@ set modsource(install.tcl) {
# Module which can install autosetup

# autosetup(installed)=1 means that autosetup is not running from source
-
# autosetup(sysinstall)=1 means that autosetup is running from a sysinstall verion
+
# autosetup(sysinstall)=1 means that autosetup is running from a sysinstall version
# shared=1 means that we are trying to do a sysinstall. This is only possible from the development source.

proc autosetup_install {dir {shared 0}} {
@@ -1847,7 +1884,7 @@ WRAPPER="$0"; export WRAPPER; "autosetup" "$@"
		writefile configure \
{#!/bin/sh
dir="`dirname "$0"`/autosetup"
-
WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
+
WRAPPER="$0"; export WRAPPER; exec "`"$dir/autosetup-find-tclsh"`" "$dir/autosetup" "$@"
}
	}
	catch {exec chmod 755 configure}
@@ -2344,6 +2381,16 @@ proc prefix {pre list} {
	}
	return $result
}
+

+
# @lpop list
+
#
+
# Removes the last entry from the given list and returns it.
+
proc lpop {listname} {
+
	upvar $listname list
+
	set val [lindex $list end]
+
	set list [lrange $list 0 end-1]
+
	return $val
+
}
}

# ----- @module wiki-formatting.tcl -----
modified autosetup/autosetup-config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-
#   Copyright 1992-2014 Free Software Foundation, Inc.
+
#   Copyright 1992-2018 Free Software Foundation, Inc.

-
timestamp='2014-11-04'
+
timestamp='2018-03-08'

# 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
@@ -15,7 +15,7 @@ timestamp='2014-11-04'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-
# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -27,7 +27,7 @@ timestamp='2014-11-04'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.

@@ -39,7 +39,7 @@ Usage: $0 [OPTION]

Output the configuration name of the system \`$me' is run on.

-
Operation modes:
+
Options:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)

Originally written by Per Bothner.
-
Copyright 1992-2014 Free Software Foundation, Inc.
+
Copyright 1992-2018 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."
@@ -107,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
-
 ,,)    echo "int x;" > $dummy.c ;
+
 ,,)    echo "int x;" > "$dummy.c" ;
	for c in cc gcc c89 c99 ; do
-
	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+
	  if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
	     CC_FOR_BUILD="$c"; break ;
	  fi ;
	done ;
@@ -132,14 +132,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown

-
case "${UNAME_SYSTEM}" in
+
case "$UNAME_SYSTEM" in
Linux|GNU|GNU/*)
	# If the system lacks a compiler, then just pick glibc.
	# We could probably try harder.
	LIBC=gnu

-
	eval $set_cc_for_build
-
	cat <<-EOF > $dummy.c
+
	eval "$set_cc_for_build"
+
	cat <<-EOF > "$dummy.c"
	#include <features.h>
	#if defined(__UCLIBC__)
	LIBC=uclibc
@@ -149,13 +149,20 @@ Linux|GNU|GNU/*)
	LIBC=gnu
	#endif
	EOF
-
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+
	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+

+
	# If ldd exists, use it to detect musl libc.
+
	if command -v ldd >/dev/null && \
+
		ldd --version 2>&1 | grep -q ^musl
+
	then
+
	    LIBC=musl
+
	fi
	;;
esac

# Note: order is significant - the case branches are not exclusive.

-
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+
case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
    *:NetBSD:*:*)
	# NetBSD (nbsd) targets should (where applicable) match one or
	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -168,21 +175,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
	# Note: NetBSD doesn't particularly care about the vendor
	# portion of the name.  We always set it to "unknown".
	sysctl="sysctl -n hw.machine_arch"
-
	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
-
	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
-
	case "${UNAME_MACHINE_ARCH}" in
+
	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+
	    "/sbin/$sysctl" 2>/dev/null || \
+
	    "/usr/sbin/$sysctl" 2>/dev/null || \
+
	    echo unknown)`
+
	case "$UNAME_MACHINE_ARCH" in
	    armeb) machine=armeb-unknown ;;
	    arm*) machine=arm-unknown ;;
	    sh3el) machine=shl-unknown ;;
	    sh3eb) machine=sh-unknown ;;
	    sh5el) machine=sh5le-unknown ;;
-
	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+
	    earmv*)
+
		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+
		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+
		machine="${arch}${endian}"-unknown
+
		;;
+
	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
	esac
	# The Operating System including object format, if it has switched
-
	# to ELF recently, or will in the future.
-
	case "${UNAME_MACHINE_ARCH}" in
+
	# to ELF recently (or will in the future) and ABI.
+
	case "$UNAME_MACHINE_ARCH" in
+
	    earm*)
+
		os=netbsdelf
+
		;;
	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
-
		eval $set_cc_for_build
+
		eval "$set_cc_for_build"
		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
			| grep -q __ELF__
		then
@@ -197,44 +214,67 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
		os=netbsd
		;;
	esac
+
	# Determine ABI tags.
+
	case "$UNAME_MACHINE_ARCH" in
+
	    earm*)
+
		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+
		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+
		;;
+
	esac
	# The OS release
	# Debian GNU/NetBSD machines have a different userland, and
	# thus, need a distinct triplet. However, they do not need
	# kernel version information, so it can be replaced with a
	# suitable tag, in the style of linux-gnu.
-
	case "${UNAME_VERSION}" in
+
	case "$UNAME_VERSION" in
	    Debian*)
		release='-gnu'
		;;
	    *)
-
		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+
		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
		;;
	esac
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
	# contains redundant information, the shorter form:
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-
	echo "${machine}-${os}${release}"
+
	echo "$machine-${os}${release}${abi}"
	exit ;;
    *:Bitrig:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-
	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
	exit ;;
    *:OpenBSD:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
-
	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+
	exit ;;
+
    *:LibertyBSD:*:*)
+
	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+
	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+
	exit ;;
+
    *:MidnightBSD:*:*)
+
	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
	exit ;;
    *:ekkoBSD:*:*)
-
	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
	exit ;;
    *:SolidBSD:*:*)
-
	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
	exit ;;
    macppc:MirBSD:*:*)
-
	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+
	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
	exit ;;
    *:MirBSD:*:*)
-
	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
	exit ;;
+
    *:Sortix:*:*)
+
	echo "$UNAME_MACHINE"-unknown-sortix
+
	exit ;;
+
    *:Redox:*:*)
+
	echo "$UNAME_MACHINE"-unknown-redox
+
	exit ;;
+
    mips:OSF1:*.*)
+
        echo mips-dec-osf1
+
        exit ;;
    alpha:OSF1:*:*)
	case $UNAME_RELEASE in
	*4.0)
@@ -251,63 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
	case "$ALPHA_CPU_TYPE" in
	    "EV4 (21064)")
-
		UNAME_MACHINE="alpha" ;;
+
		UNAME_MACHINE=alpha ;;
	    "EV4.5 (21064)")
-
		UNAME_MACHINE="alpha" ;;
+
		UNAME_MACHINE=alpha ;;
	    "LCA4 (21066/21068)")
-
		UNAME_MACHINE="alpha" ;;
+
		UNAME_MACHINE=alpha ;;
	    "EV5 (21164)")
-
		UNAME_MACHINE="alphaev5" ;;
+
		UNAME_MACHINE=alphaev5 ;;
	    "EV5.6 (21164A)")
-
		UNAME_MACHINE="alphaev56" ;;
+
		UNAME_MACHINE=alphaev56 ;;
	    "EV5.6 (21164PC)")
-
		UNAME_MACHINE="alphapca56" ;;
+
		UNAME_MACHINE=alphapca56 ;;
	    "EV5.7 (21164PC)")
-
		UNAME_MACHINE="alphapca57" ;;
+
		UNAME_MACHINE=alphapca57 ;;
	    "EV6 (21264)")
-
		UNAME_MACHINE="alphaev6" ;;
+
		UNAME_MACHINE=alphaev6 ;;
	    "EV6.7 (21264A)")
-
		UNAME_MACHINE="alphaev67" ;;
+
		UNAME_MACHINE=alphaev67 ;;
	    "EV6.8CB (21264C)")
-
		UNAME_MACHINE="alphaev68" ;;
+
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.8AL (21264B)")
-
		UNAME_MACHINE="alphaev68" ;;
+
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.8CX (21264D)")
-
		UNAME_MACHINE="alphaev68" ;;
+
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.9A (21264/EV69A)")
-
		UNAME_MACHINE="alphaev69" ;;
+
		UNAME_MACHINE=alphaev69 ;;
	    "EV7 (21364)")
-
		UNAME_MACHINE="alphaev7" ;;
+
		UNAME_MACHINE=alphaev7 ;;
	    "EV7.9 (21364A)")
-
		UNAME_MACHINE="alphaev79" ;;
+
		UNAME_MACHINE=alphaev79 ;;
	esac
	# A Pn.n version is a patched version.
	# A Vn.n version is a released version.
	# A Tn.n version is a released field test version.
	# A Xn.n version is an unreleased experimental baselevel.
	# 1.2 uses "1.2" for uname -r.
-
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+
	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
	exitcode=$?
	trap '' 0
	exit $exitcode ;;
-
    Alpha\ *:Windows_NT*:*)
-
	# How do we know it's Interix rather than the generic POSIX subsystem?
-
	# Should we change UNAME_MACHINE based on the output of uname instead
-
	# of the specific Alpha model?
-
	echo alpha-pc-interix
-
	exit ;;
-
    21064:Windows_NT:50:3)
-
	echo alpha-dec-winnt3.5
-
	exit ;;
    Amiga*:UNIX_System_V:4.0:*)
	echo m68k-unknown-sysv4
	exit ;;
    *:[Aa]miga[Oo][Ss]:*:*)
-
	echo ${UNAME_MACHINE}-unknown-amigaos
+
	echo "$UNAME_MACHINE"-unknown-amigaos
	exit ;;
    *:[Mm]orph[Oo][Ss]:*:*)
-
	echo ${UNAME_MACHINE}-unknown-morphos
+
	echo "$UNAME_MACHINE"-unknown-morphos
	exit ;;
    *:OS/390:*:*)
	echo i370-ibm-openedition
@@ -319,7 +350,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
	echo powerpc-ibm-os400
	exit ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-
	echo arm-acorn-riscix${UNAME_RELEASE}
+
	echo arm-acorn-riscix"$UNAME_RELEASE"
	exit ;;
    arm*:riscos:*:*|arm*:RISCOS:*:*)
	echo arm-unknown-riscos
@@ -346,38 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
	    sparc) echo sparc-icl-nx7; exit ;;
	esac ;;
    s390x:SunOS:*:*)
-
	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
	exit ;;
    sun4H:SunOS:5.*:*)
-
	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-
	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
	exit ;;
    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-
	echo i386-pc-auroraux${UNAME_RELEASE}
+
	echo i386-pc-auroraux"$UNAME_RELEASE"
	exit ;;
    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-
	eval $set_cc_for_build
-
	SUN_ARCH="i386"
+
	eval "$set_cc_for_build"
+
	SUN_ARCH=i386
	# If there is a compiler, see if it is configured for 64-bit objects.
	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
	# This test works for both compilers.
-
	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+
	if [ "$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 -E - 2>/dev/null) | \
		grep IS_64BIT_ARCH >/dev/null
	    then
-
		SUN_ARCH="x86_64"
+
		SUN_ARCH=x86_64
	    fi
	fi
-
	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:6*:*)
	# According to config.sub, this is the proper way to canonicalize
	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
	# it's likely to be more like Solaris than SunOS4.
-
	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:*:*)
	case "`/usr/bin/arch -k`" in
@@ -386,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
		;;
	esac
	# Japanese Language versions have a version number like `4.1.3-JL'.
-
	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+
	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
	exit ;;
    sun3*:SunOS:*:*)
-
	echo m68k-sun-sunos${UNAME_RELEASE}
+
	echo m68k-sun-sunos"$UNAME_RELEASE"
	exit ;;
    sun*:*:4.2BSD:*)
	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-
	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+
	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
	case "`/bin/arch`" in
	    sun3)
-
		echo m68k-sun-sunos${UNAME_RELEASE}
+
		echo m68k-sun-sunos"$UNAME_RELEASE"
		;;
	    sun4)
-
		echo sparc-sun-sunos${UNAME_RELEASE}
+
		echo sparc-sun-sunos"$UNAME_RELEASE"
		;;
	esac
	exit ;;
    aushp:SunOS:*:*)
-
	echo sparc-auspex-sunos${UNAME_RELEASE}
+
	echo sparc-auspex-sunos"$UNAME_RELEASE"
	exit ;;
    # The situation for MiNT is a little confusing.  The machine name
    # can be virtually everything (everything which is not
@@ -415,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
    # MiNT.  But MiNT is downward compatible to TOS, so this should
    # be no problem.
    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-
	echo m68k-atari-mint${UNAME_RELEASE}
+
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-
	echo m68k-atari-mint${UNAME_RELEASE}
+
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-
	echo m68k-atari-mint${UNAME_RELEASE}
+
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-
	echo m68k-milan-mint${UNAME_RELEASE}
+
	echo m68k-milan-mint"$UNAME_RELEASE"
	exit ;;
    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-
	echo m68k-hades-mint${UNAME_RELEASE}
+
	echo m68k-hades-mint"$UNAME_RELEASE"
	exit ;;
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-
	echo m68k-unknown-mint${UNAME_RELEASE}
+
	echo m68k-unknown-mint"$UNAME_RELEASE"
	exit ;;
    m68k:machten:*:*)
-
	echo m68k-apple-machten${UNAME_RELEASE}
+
	echo m68k-apple-machten"$UNAME_RELEASE"
	exit ;;
    powerpc:machten:*:*)
-
	echo powerpc-apple-machten${UNAME_RELEASE}
+
	echo powerpc-apple-machten"$UNAME_RELEASE"
	exit ;;
    RISC*:Mach:*:*)
	echo mips-dec-mach_bsd4.3
	exit ;;
    RISC*:ULTRIX:*:*)
-
	echo mips-dec-ultrix${UNAME_RELEASE}
+
	echo mips-dec-ultrix"$UNAME_RELEASE"
	exit ;;
    VAX*:ULTRIX*:*:*)
-
	echo vax-dec-ultrix${UNAME_RELEASE}
+
	echo vax-dec-ultrix"$UNAME_RELEASE"
	exit ;;
    2020:CLIX:*:* | 2430:CLIX:*:*)
-
	echo clipper-intergraph-clix${UNAME_RELEASE}
+
	echo clipper-intergraph-clix"$UNAME_RELEASE"
	exit ;;
    mips:*:*:UMIPS | mips:*:*:RISCos)
-
	eval $set_cc_for_build
-
	sed 's/^	//' << EOF >$dummy.c
+
	eval "$set_cc_for_build"
+
	sed 's/^	//' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h>  /* for printf() prototype */
	int main (int argc, char *argv[]) {
@@ -461,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
	#if defined (host_mips) && defined (MIPSEB)
	#if defined (SYSTYPE_SYSV)
-
	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+
	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_SVR4)
-
	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+
	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-
	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+
	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
	#endif
	#endif
	  exit (-1);
	}
EOF
-
	$CC_FOR_BUILD -o $dummy $dummy.c &&
-
	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-
	  SYSTEM_NAME=`$dummy $dummyarg` &&
+
	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+
	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+
	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
	    { echo "$SYSTEM_NAME"; exit; }
-
	echo mips-mips-riscos${UNAME_RELEASE}
+
	echo mips-mips-riscos"$UNAME_RELEASE"
	exit ;;
    Motorola:PowerMAX_OS:*:*)
	echo powerpc-motorola-powermax
@@ -503,17 +534,17 @@ EOF
    AViiON:dgux:*:*)
	# DG/UX returns AViiON for all architectures
	UNAME_PROCESSOR=`/usr/bin/uname -p`
-
	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+
	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
	then
-
	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
-
	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+
	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+
	       [ "$TARGET_BINARY_INTERFACE"x = x ]
	    then
-
		echo m88k-dg-dgux${UNAME_RELEASE}
+
		echo m88k-dg-dgux"$UNAME_RELEASE"
	    else
-
		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+
		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
	    fi
	else
-
	    echo i586-dg-dgux${UNAME_RELEASE}
+
	    echo i586-dg-dgux"$UNAME_RELEASE"
	fi
	exit ;;
    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
@@ -530,7 +561,7 @@ EOF
	echo m68k-tektronix-bsd
	exit ;;
    *:IRIX*:*:*)
-
	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+
	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
	exit ;;
    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
@@ -542,14 +573,14 @@ EOF
	if [ -x /usr/bin/oslevel ] ; then
		IBM_REV=`/usr/bin/oslevel`
	else
-
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+
		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
	fi
-
	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+
	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
	exit ;;
    *:AIX:2:3)
	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-
		eval $set_cc_for_build
-
		sed 's/^		//' << EOF >$dummy.c
+
		eval "$set_cc_for_build"
+
		sed 's/^		//' << EOF > "$dummy.c"
		#include <sys/systemcfg.h>

		main()
@@ -560,7 +591,7 @@ EOF
			exit(0);
			}
EOF
-
		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+
		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
		then
			echo "$SYSTEM_NAME"
		else
@@ -574,7 +605,7 @@ EOF
	exit ;;
    *:AIX:*:[4567])
	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
-
	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+
	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
		IBM_ARCH=rs6000
	else
		IBM_ARCH=powerpc
@@ -583,18 +614,18 @@ EOF
		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
	else
-
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+
		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
	fi
-
	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+
	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
	exit ;;
    *:AIX:*:*)
	echo rs6000-ibm-aix
	exit ;;
-
    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+
    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
	echo romp-ibm-bsd4.4
	exit ;;
    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-
	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+
	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
	exit ;;                             # report: romp-ibm BSD 4.3
    *:BOSX:*:*)
	echo rs6000-bull-bosx
@@ -609,28 +640,28 @@ EOF
	echo m68k-hp-bsd4.4
	exit ;;
    9000/[34678]??:HP-UX:*:*)
-
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-
	case "${UNAME_MACHINE}" in
-
	    9000/31? )            HP_ARCH=m68000 ;;
-
	    9000/[34]?? )         HP_ARCH=m68k ;;
+
	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+
	case "$UNAME_MACHINE" in
+
	    9000/31?)            HP_ARCH=m68000 ;;
+
	    9000/[34]??)         HP_ARCH=m68k ;;
	    9000/[678][0-9][0-9])
		if [ -x /usr/bin/getconf ]; then
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-
		    case "${sc_cpu_version}" in
-
		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-
		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+
		    case "$sc_cpu_version" in
+
		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+
		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
		      532)                      # CPU_PA_RISC2_0
-
			case "${sc_kernel_bits}" in
-
			  32) HP_ARCH="hppa2.0n" ;;
-
			  64) HP_ARCH="hppa2.0w" ;;
-
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+
			case "$sc_kernel_bits" in
+
			  32) HP_ARCH=hppa2.0n ;;
+
			  64) HP_ARCH=hppa2.0w ;;
+
			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
			esac ;;
		    esac
		fi
-
		if [ "${HP_ARCH}" = "" ]; then
-
		    eval $set_cc_for_build
-
		    sed 's/^		//' << EOF >$dummy.c
+
		if [ "$HP_ARCH" = "" ]; then
+
		    eval "$set_cc_for_build"
+
		    sed 's/^		//' << EOF > "$dummy.c"

		#define _HPUX_SOURCE
		#include <stdlib.h>
@@ -663,13 +694,13 @@ EOF
		    exit (0);
		}
EOF
-
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+
		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
		    test -z "$HP_ARCH" && HP_ARCH=hppa
		fi ;;
	esac
-
	if [ ${HP_ARCH} = "hppa2.0w" ]
+
	if [ "$HP_ARCH" = hppa2.0w ]
	then
-
	    eval $set_cc_for_build
+
	    eval "$set_cc_for_build"

	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
@@ -680,23 +711,23 @@ EOF
	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
	    # => hppa64-hp-hpux11.23

-
	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+
	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
		grep -q __LP64__
	    then
-
		HP_ARCH="hppa2.0w"
+
		HP_ARCH=hppa2.0w
	    else
-
		HP_ARCH="hppa64"
+
		HP_ARCH=hppa64
	    fi
	fi
-
	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+
	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
	exit ;;
    ia64:HP-UX:*:*)
-
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-
	echo ia64-hp-hpux${HPUX_REV}
+
	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+
	echo ia64-hp-hpux"$HPUX_REV"
	exit ;;
    3050*:HI-UX:*:*)
-
	eval $set_cc_for_build
-
	sed 's/^	//' << EOF >$dummy.c
+
	eval "$set_cc_for_build"
+
	sed 's/^	//' << EOF > "$dummy.c"
	#include <unistd.h>
	int
	main ()
@@ -721,11 +752,11 @@ EOF
	  exit (0);
	}
EOF
-
	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+
	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
		{ echo "$SYSTEM_NAME"; exit; }
	echo unknown-hitachi-hiuxwe2
	exit ;;
-
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
	echo hppa1.1-hp-bsd
	exit ;;
    9000/8??:4.3bsd:*:*)
@@ -734,7 +765,7 @@ EOF
    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
	echo hppa1.0-hp-mpeix
	exit ;;
-
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
	echo hppa1.1-hp-osf
	exit ;;
    hp8??:OSF1:*:*)
@@ -742,9 +773,9 @@ EOF
	exit ;;
    i*86:OSF1:*:*)
	if [ -x /usr/sbin/sysversion ] ; then
-
	    echo ${UNAME_MACHINE}-unknown-osf1mk
+
	    echo "$UNAME_MACHINE"-unknown-osf1mk
	else
-
	    echo ${UNAME_MACHINE}-unknown-osf1
+
	    echo "$UNAME_MACHINE"-unknown-osf1
	fi
	exit ;;
    parisc*:Lites*:*:*)
@@ -769,127 +800,109 @@ EOF
	echo c4-convex-bsd
	exit ;;
    CRAY*Y-MP:*:*:*)
-
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+
	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*[A-Z]90:*:*:*)
-
	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+
	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
	      -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*TS:*:*:*)
-
	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+
	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*T3E:*:*:*)
-
	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+
	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*SV1:*:*:*)
-
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+
	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    *:UNICOS/mp:*:*)
-
	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+
	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-
	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+
	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+
	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+
	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    5000:UNIX_System_V:4.*:*)
-
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-
	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+
	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+
	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
	exit ;;
    sparc*:BSD/OS:*:*)
-
	echo sparc-unknown-bsdi${UNAME_RELEASE}
+
	echo sparc-unknown-bsdi"$UNAME_RELEASE"
	exit ;;
    *:BSD/OS:*:*)
-
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
	exit ;;
    *:FreeBSD:*:*)
	UNAME_PROCESSOR=`/usr/bin/uname -p`
-
	case ${UNAME_PROCESSOR} in
+
	case "$UNAME_PROCESSOR" in
	    amd64)
-
		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-
	    *)
-
		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+
		UNAME_PROCESSOR=x86_64 ;;
+
	    i386)
+
		UNAME_PROCESSOR=i586 ;;
	esac
+
	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
	exit ;;
    i*:CYGWIN*:*)
-
	echo ${UNAME_MACHINE}-pc-cygwin
+
	echo "$UNAME_MACHINE"-pc-cygwin
	exit ;;
    *:MINGW64*:*)
-
	echo ${UNAME_MACHINE}-pc-mingw64
+
	echo "$UNAME_MACHINE"-pc-mingw64
	exit ;;
    *:MINGW*:*)
-
	echo ${UNAME_MACHINE}-pc-mingw32
+
	echo "$UNAME_MACHINE"-pc-mingw32
	exit ;;
    *:MSYS*:*)
-
	echo ${UNAME_MACHINE}-pc-msys
-
	exit ;;
-
    i*:windows32*:*)
-
	# uname -m includes "-pc" on this system.
-
	echo ${UNAME_MACHINE}-mingw32
+
	echo "$UNAME_MACHINE"-pc-msys
	exit ;;
    i*:PW*:*)
-
	echo ${UNAME_MACHINE}-pc-pw32
+
	echo "$UNAME_MACHINE"-pc-pw32
	exit ;;
    *:Interix*:*)
-
	case ${UNAME_MACHINE} in
+
	case "$UNAME_MACHINE" in
	    x86)
-
		echo i586-pc-interix${UNAME_RELEASE}
+
		echo i586-pc-interix"$UNAME_RELEASE"
		exit ;;
	    authenticamd | genuineintel | EM64T)
-
		echo x86_64-unknown-interix${UNAME_RELEASE}
+
		echo x86_64-unknown-interix"$UNAME_RELEASE"
		exit ;;
	    IA64)
-
		echo ia64-unknown-interix${UNAME_RELEASE}
+
		echo ia64-unknown-interix"$UNAME_RELEASE"
		exit ;;
	esac ;;
-
    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
-
	echo i${UNAME_MACHINE}-pc-mks
-
	exit ;;
-
    8664:Windows_NT:*)
-
	echo x86_64-pc-mks
-
	exit ;;
-
    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-
	# How do we know it's Interix rather than the generic POSIX subsystem?
-
	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-
	# UNAME_MACHINE based on the output of uname instead of i386?
-
	echo i586-pc-interix
-
	exit ;;
    i*:UWIN*:*)
-
	echo ${UNAME_MACHINE}-pc-uwin
+
	echo "$UNAME_MACHINE"-pc-uwin
	exit ;;
    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
	echo x86_64-unknown-cygwin
	exit ;;
-
    p*:CYGWIN*:*)
-
	echo powerpcle-unknown-cygwin
-
	exit ;;
    prep*:SunOS:5.*:*)
-
	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+
	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    *:GNU:*:*)
	# the GNU system
-
	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+
	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
	exit ;;
    *:GNU/*:*:*)
	# other systems with GNU libc and userland
-
	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+
	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
	exit ;;
    i*86:Minix:*:*)
-
	echo ${UNAME_MACHINE}-pc-minix
+
	echo "$UNAME_MACHINE"-pc-minix
	exit ;;
    aarch64:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    aarch64_be:Linux:*:*)
	UNAME_MACHINE=aarch64_be
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    alpha:Linux:*:*)
	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -902,58 +915,64 @@ EOF
	  EV68*) UNAME_MACHINE=alphaev68 ;;
	esac
	objdump --private-headers /bin/sh | grep -q ld.so.1
-
	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    arc:Linux:*:* | arceb:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    arm*:Linux:*:*)
-
	eval $set_cc_for_build
+
	eval "$set_cc_for_build"
	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_EABI__
	then
-
	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	else
	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
		| grep -q __ARM_PCS_VFP
	    then
-
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+
		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
	    else
-
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+
		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
	    fi
	fi
	exit ;;
    avr32*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    cris:Linux:*:*)
-
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
	exit ;;
    crisv32:Linux:*:*)
-
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+
	exit ;;
+
    e2k:Linux:*:*)
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    frv:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    hexagon:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    i*86:Linux:*:*)
-
	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
	exit ;;
    ia64:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+
	exit ;;
+
    k1om:Linux:*:*)
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    m32r*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    m68*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    mips:Linux:*:* | mips64:Linux:*:*)
-
	eval $set_cc_for_build
-
	sed 's/^	//' << EOF >$dummy.c
+
	eval "$set_cc_for_build"
+
	sed 's/^	//' << EOF > "$dummy.c"
	#undef CPU
	#undef ${UNAME_MACHINE}
	#undef ${UNAME_MACHINE}el
@@ -967,64 +986,70 @@ EOF
	#endif
	#endif
EOF
-
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+
	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+
	test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
	;;
+
    mips64el:Linux:*:*)
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+
	exit ;;
    openrisc*:Linux:*:*)
-
	echo or1k-unknown-linux-${LIBC}
+
	echo or1k-unknown-linux-"$LIBC"
	exit ;;
    or32:Linux:*:* | or1k*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    padre:Linux:*:*)
-
	echo sparc-unknown-linux-${LIBC}
+
	echo sparc-unknown-linux-"$LIBC"
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
-
	echo hppa64-unknown-linux-${LIBC}
+
	echo hppa64-unknown-linux-"$LIBC"
	exit ;;
    parisc:Linux:*:* | hppa:Linux:*:*)
	# Look for CPU level
	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-
	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
-
	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
-
	  *)    echo hppa-unknown-linux-${LIBC} ;;
+
	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+
	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+
	  *)    echo hppa-unknown-linux-"$LIBC" ;;
	esac
	exit ;;
    ppc64:Linux:*:*)
-
	echo powerpc64-unknown-linux-${LIBC}
+
	echo powerpc64-unknown-linux-"$LIBC"
	exit ;;
    ppc:Linux:*:*)
-
	echo powerpc-unknown-linux-${LIBC}
+
	echo powerpc-unknown-linux-"$LIBC"
	exit ;;
    ppc64le:Linux:*:*)
-
	echo powerpc64le-unknown-linux-${LIBC}
+
	echo powerpc64le-unknown-linux-"$LIBC"
	exit ;;
    ppcle:Linux:*:*)
-
	echo powerpcle-unknown-linux-${LIBC}
+
	echo powerpcle-unknown-linux-"$LIBC"
+
	exit ;;
+
    riscv32:Linux:*:* | riscv64:Linux:*:*)
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    s390:Linux:*:* | s390x:Linux:*:*)
-
	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
	exit ;;
    sh64*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    sh*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    sparc:Linux:*:* | sparc64:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    tile*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    vax:Linux:*:*)
-
	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
	exit ;;
    x86_64:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
	exit ;;
    xtensa*:Linux:*:*)
-
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    i*86:DYNIX/ptx:4*:*)
	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1038,34 +1063,34 @@ EOF
	# I am not positive that other SVR4 systems won't match this,
	# I just have to hope.  -- rms.
	# Use sysv4.2uw... so that sysv4* matches it.
-
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+
	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
	exit ;;
    i*86:OS/2:*:*)
	# If we were able to find `uname', then EMX Unix compatibility
	# is probably installed.
-
	echo ${UNAME_MACHINE}-pc-os2-emx
+
	echo "$UNAME_MACHINE"-pc-os2-emx
	exit ;;
    i*86:XTS-300:*:STOP)
-
	echo ${UNAME_MACHINE}-unknown-stop
+
	echo "$UNAME_MACHINE"-unknown-stop
	exit ;;
    i*86:atheos:*:*)
-
	echo ${UNAME_MACHINE}-unknown-atheos
+
	echo "$UNAME_MACHINE"-unknown-atheos
	exit ;;
    i*86:syllable:*:*)
-
	echo ${UNAME_MACHINE}-pc-syllable
+
	echo "$UNAME_MACHINE"-pc-syllable
	exit ;;
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-
	echo i386-unknown-lynxos${UNAME_RELEASE}
+
	echo i386-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    i*86:*DOS:*:*)
-
	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+
	echo "$UNAME_MACHINE"-pc-msdosdjgpp
	exit ;;
-
    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
-
	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+
    i*86:*:4.*:*)
+
	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-
		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+
		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
	else
-
		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+
		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
	fi
	exit ;;
    i*86:*:5:[678]*)
@@ -1075,12 +1100,12 @@ EOF
	    *Pentium)	     UNAME_MACHINE=i586 ;;
	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
	esac
-
	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+
	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
	exit ;;
    i*86:*:3.2:*)
	if test -f /usr/options/cb.name; then
		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-
		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+
		echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
	elif /bin/uname -X 2>/dev/null >/dev/null ; then
		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1090,9 +1115,9 @@ EOF
			&& UNAME_MACHINE=i686
		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
			&& UNAME_MACHINE=i686
-
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+
		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
	else
-
		echo ${UNAME_MACHINE}-pc-sysv32
+
		echo "$UNAME_MACHINE"-pc-sysv32
	fi
	exit ;;
    pc:*:*:*)
@@ -1100,7 +1125,7 @@ EOF
	# uname -m prints for DJGPP always 'pc', but it prints nothing about
	# the processor, so we play safe by assuming i586.
	# Note: whatever this is, it MUST be the same as what config.sub
-
	# prints for the "djgpp" host, or else GDB configury will decide that
+
	# prints for the "djgpp" host, or else GDB configure will decide that
	# this is a cross-build.
	echo i586-pc-msdosdjgpp
	exit ;;
@@ -1112,9 +1137,9 @@ EOF
	exit ;;
    i860:*:4.*:*) # i860-SVR4
	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-
	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+
	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
	else # Add other i860-SVR4 vendors below as they are discovered.
-
	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+
	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
	fi
	exit ;;
    mini*:CTIX:SYS*5:*)
@@ -1134,9 +1159,9 @@ EOF
	test -r /etc/.relid \
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-
	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+
	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-
	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+
	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4; exit; } ;;
@@ -1145,28 +1170,28 @@ EOF
	test -r /etc/.relid \
	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-
	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+
	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-
	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+
	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-
	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+
	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-
	echo m68k-unknown-lynxos${UNAME_RELEASE}
+
	echo m68k-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    mc68030:UNIX_System_V:4.*:*)
	echo m68k-atari-sysv4
	exit ;;
    TSUNAMI:LynxOS:2.*:*)
-
	echo sparc-unknown-lynxos${UNAME_RELEASE}
+
	echo sparc-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    rs6000:LynxOS:2.*:*)
-
	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+
	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-
	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+
	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    SM[BE]S:UNIX_SV:*:*)
-
	echo mips-dde-sysv${UNAME_RELEASE}
+
	echo mips-dde-sysv"$UNAME_RELEASE"
	exit ;;
    RM*:ReliantUNIX-*:*:*)
	echo mips-sni-sysv4
@@ -1177,7 +1202,7 @@ EOF
    *:SINIX-*:*:*)
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
-
		echo ${UNAME_MACHINE}-sni-sysv4
+
		echo "$UNAME_MACHINE"-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
@@ -1197,23 +1222,23 @@ EOF
	exit ;;
    i*86:VOS:*:*)
	# From Paul.Green@stratus.com.
-
	echo ${UNAME_MACHINE}-stratus-vos
+
	echo "$UNAME_MACHINE"-stratus-vos
	exit ;;
    *:VOS:*:*)
	# From Paul.Green@stratus.com.
	echo hppa1.1-stratus-vos
	exit ;;
    mc68*:A/UX:*:*)
-
	echo m68k-apple-aux${UNAME_RELEASE}
+
	echo m68k-apple-aux"$UNAME_RELEASE"
	exit ;;
    news*:NEWS-OS:6*:*)
	echo mips-sony-newsos6
	exit ;;
    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
	if [ -d /usr/nec ]; then
-
		echo mips-nec-sysv${UNAME_RELEASE}
+
		echo mips-nec-sysv"$UNAME_RELEASE"
	else
-
		echo mips-unknown-sysv${UNAME_RELEASE}
+
		echo mips-unknown-sysv"$UNAME_RELEASE"
	fi
	exit ;;
    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
@@ -1232,46 +1257,56 @@ EOF
	echo x86_64-unknown-haiku
	exit ;;
    SX-4:SUPER-UX:*:*)
-
	echo sx4-nec-superux${UNAME_RELEASE}
+
	echo sx4-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-5:SUPER-UX:*:*)
-
	echo sx5-nec-superux${UNAME_RELEASE}
+
	echo sx5-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-6:SUPER-UX:*:*)
-
	echo sx6-nec-superux${UNAME_RELEASE}
+
	echo sx6-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-7:SUPER-UX:*:*)
-
	echo sx7-nec-superux${UNAME_RELEASE}
+
	echo sx7-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-8:SUPER-UX:*:*)
-
	echo sx8-nec-superux${UNAME_RELEASE}
+
	echo sx8-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-8R:SUPER-UX:*:*)
-
	echo sx8r-nec-superux${UNAME_RELEASE}
+
	echo sx8r-nec-superux"$UNAME_RELEASE"
+
	exit ;;
+
    SX-ACE:SUPER-UX:*:*)
+
	echo sxace-nec-superux"$UNAME_RELEASE"
	exit ;;
    Power*:Rhapsody:*:*)
-
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+
	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
	exit ;;
    *:Rhapsody:*:*)
-
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
	exit ;;
    *:Darwin:*:*)
	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-
	eval $set_cc_for_build
+
	eval "$set_cc_for_build"
	if test "$UNAME_PROCESSOR" = unknown ; then
	    UNAME_PROCESSOR=powerpc
	fi
-
	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
-
	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+
	if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+
	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-
		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-
		    grep IS_64BIT_ARCH >/dev/null
+
		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+
		       grep IS_64BIT_ARCH >/dev/null
		then
		    case $UNAME_PROCESSOR in
			i386) UNAME_PROCESSOR=x86_64 ;;
			powerpc) UNAME_PROCESSOR=powerpc64 ;;
		    esac
		fi
+
		# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+
		if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+
		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+
		       grep IS_PPC >/dev/null
+
		then
+
		    UNAME_PROCESSOR=powerpc
+
		fi
	    fi
	elif test "$UNAME_PROCESSOR" = i386 ; then
	    # Avoid executing cc on OS X 10.9, as it ships with a stub
@@ -1282,27 +1317,33 @@ EOF
	    # that Apple uses in portable devices.
	    UNAME_PROCESSOR=x86_64
	fi
-
	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+
	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
	exit ;;
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
	UNAME_PROCESSOR=`uname -p`
-
	if test "$UNAME_PROCESSOR" = "x86"; then
+
	if test "$UNAME_PROCESSOR" = x86; then
		UNAME_PROCESSOR=i386
		UNAME_MACHINE=pc
	fi
-
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+
	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
	exit ;;
    *:QNX:*:4*)
	echo i386-pc-qnx
	exit ;;
-
    NEO-?:NONSTOP_KERNEL:*:*)
-
	echo neo-tandem-nsk${UNAME_RELEASE}
+
    NEO-*:NONSTOP_KERNEL:*:*)
+
	echo neo-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    NSE-*:NONSTOP_KERNEL:*:*)
-
	echo nse-tandem-nsk${UNAME_RELEASE}
+
	echo nse-tandem-nsk"$UNAME_RELEASE"
+
	exit ;;
+
    NSR-*:NONSTOP_KERNEL:*:*)
+
	echo nsr-tandem-nsk"$UNAME_RELEASE"
	exit ;;
-
    NSR-?:NONSTOP_KERNEL:*:*)
-
	echo nsr-tandem-nsk${UNAME_RELEASE}
+
    NSV-*:NONSTOP_KERNEL:*:*)
+
	echo nsv-tandem-nsk"$UNAME_RELEASE"
+
	exit ;;
+
    NSX-*:NONSTOP_KERNEL:*:*)
+
	echo nsx-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    *:NonStop-UX:*:*)
	echo mips-compaq-nonstopux
@@ -1311,18 +1352,18 @@ EOF
	echo bs2000-siemens-sysv
	exit ;;
    DS/*:UNIX_System_V:*:*)
-
	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+
	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
	exit ;;
    *:Plan9:*:*)
	# "uname -m" is not consistent, so use $cputype instead. 386
	# is converted to i386 for consistency with other x86
	# operating systems.
-
	if test "$cputype" = "386"; then
+
	if test "$cputype" = 386; then
	    UNAME_MACHINE=i386
	else
	    UNAME_MACHINE="$cputype"
	fi
-
	echo ${UNAME_MACHINE}-unknown-plan9
+
	echo "$UNAME_MACHINE"-unknown-plan9
	exit ;;
    *:TOPS-10:*:*)
	echo pdp10-unknown-tops10
@@ -1343,14 +1384,14 @@ EOF
	echo pdp10-unknown-its
	exit ;;
    SEI:*:*:SEIUX)
-
	echo mips-sei-seiux${UNAME_RELEASE}
+
	echo mips-sei-seiux"$UNAME_RELEASE"
	exit ;;
    *:DragonFly:*:*)
-
	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+
	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
	exit ;;
    *:*VMS:*:*)
	UNAME_MACHINE=`(uname -p) 2>/dev/null`
-
	case "${UNAME_MACHINE}" in
+
	case "$UNAME_MACHINE" in
	    A*) echo alpha-dec-vms ; exit ;;
	    I*) echo ia64-dec-vms ; exit ;;
	    V*) echo vax-dec-vms ; exit ;;
@@ -1359,34 +1400,48 @@ EOF
	echo i386-pc-xenix
	exit ;;
    i*86:skyos:*:*)
-
	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+
	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
	exit ;;
    i*86:rdos:*:*)
-
	echo ${UNAME_MACHINE}-pc-rdos
+
	echo "$UNAME_MACHINE"-pc-rdos
	exit ;;
    i*86:AROS:*:*)
-
	echo ${UNAME_MACHINE}-pc-aros
+
	echo "$UNAME_MACHINE"-pc-aros
	exit ;;
    x86_64:VMkernel:*:*)
-
	echo ${UNAME_MACHINE}-unknown-esx
+
	echo "$UNAME_MACHINE"-unknown-esx
+
	exit ;;
+
    amd64:Isilon\ OneFS:*:*)
+
	echo x86_64-unknown-onefs
	exit ;;
esac

+
echo "$0: unable to guess system type" >&2
+

+
case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+
    mips:Linux | mips64:Linux)
+
	# If we got here on MIPS GNU/Linux, output extra information.
+
	cat >&2 <<EOF
+

+
NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+
the system type. Please install a C compiler and try again.
+
EOF
+
	;;
+
esac
+

cat >&2 <<EOF
-
$0: unable to guess system type

-
This script, last modified $timestamp, has failed to recognize
-
the operating system you are using. It is advised that you
-
download the most up to date version of the config scripts from
+
This script (version $timestamp), has failed to recognize the
+
operating system you are using. If your script is old, overwrite *all*
+
copies of config.guess and config.sub with the latest versions from:

-
  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
-
  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub

-
If the version you run ($0) is already up to date, please
-
send the following data and any information you think might be
-
pertinent to <config-patches@gnu.org> in order to provide the needed
-
information to handle your system.
+
If $0 has already been updated, send the following data and any
+
information you think might be pertinent to config-patches@gnu.org to
+
provide the necessary information to handle your system.

config.guess timestamp = $timestamp

@@ -1405,16 +1460,16 @@ hostinfo = `(hostinfo) 2>/dev/null`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`

-
UNAME_MACHINE = ${UNAME_MACHINE}
-
UNAME_RELEASE = ${UNAME_RELEASE}
-
UNAME_SYSTEM  = ${UNAME_SYSTEM}
-
UNAME_VERSION = ${UNAME_VERSION}
+
UNAME_MACHINE = "$UNAME_MACHINE"
+
UNAME_RELEASE = "$UNAME_RELEASE"
+
UNAME_SYSTEM  = "$UNAME_SYSTEM"
+
UNAME_VERSION = "$UNAME_VERSION"
EOF

exit 1

# Local variables:
-
# eval: (add-hook 'write-file-hooks 'time-stamp)
+
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
modified autosetup/autosetup-config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-
#   Copyright 1992-2014 Free Software Foundation, Inc.
+
#   Copyright 1992-2018 Free Software Foundation, Inc.

-
timestamp='2014-12-03'
+
timestamp='2018-03-08'

# 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
@@ -15,7 +15,7 @@ timestamp='2014-12-03'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-
# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -33,7 +33,7 @@ timestamp='2014-12-03'
# Otherwise, we print the canonical config type on stdout and succeed.

# You can get the latest version of this script from:
-
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub

# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -53,12 +53,11 @@ timestamp='2014-12-03'
me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
-
Usage: $0 [OPTION] CPU-MFR-OPSYS
-
       $0 [OPTION] ALIAS
+
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS

Canonicalize a configuration name.

-
Operation modes:
+
Options:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)

-
Copyright 1992-2014 Free Software Foundation, Inc.
+
Copyright 1992-2018 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."
@@ -95,7 +94,7 @@ while test $# -gt 0 ; do

    *local*)
       # First pass through any local machine types.
-
       echo $1
+
       echo "$1"
       exit ;;

    * )
@@ -113,24 +112,24 @@ esac

# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
-
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+
maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-
  knetbsd*-gnu* | netbsd*-gnu* | \
-
  kopensolaris*-gnu* | \
+
  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+
  kopensolaris*-gnu* | cloudabi*-eabi* | \
  storm-chaos* | os2-emx* | rtmk-nova*)
    os=-$maybe_os
-
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+
    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
    ;;
  android-linux)
    os=-linux-android
-
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+
    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
    ;;
  *)
-
    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-
    if [ $basic_machine != $1 ]
-
    then os=`echo $1 | sed 's/.*-/-/'`
+
    basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
+
    if [ "$basic_machine" != "$1" ]
+
    then os=`echo "$1" | sed 's/.*-/-/'`
    else os=; fi
    ;;
esac
@@ -179,44 +178,44 @@ case $os in
		;;
	-sco6)
		os=-sco5v6
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco5)
		os=-sco3.2v5
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco4)
		os=-sco3.2v4
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco3.2.[4-9]*)
		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco3.2v[4-9]*)
		# Don't forget version if it is 3.2v4 or newer.
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco5v6*)
		# Don't forget version if it is 3.2v4 or newer.
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-sco*)
		os=-sco3.2v2
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-udk*)
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-isc)
		os=-isc2.2
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-clix*)
		basic_machine=clipper-intergraph
		;;
	-isc*)
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
		;;
	-lynx*178)
		os=-lynxos178
@@ -228,10 +227,7 @@ case $os in
		os=-lynxos
		;;
	-ptx*)
-
		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
-
		;;
-
	-windowsnt*)
-
		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+
		basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
		;;
	-psos*)
		os=-psos
@@ -255,15 +251,16 @@ case $basic_machine in
	| arc | arceb \
	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
	| avr | avr32 \
+
	| ba \
	| be32 | be64 \
	| bfin \
	| c4x | c8051 | clipper \
	| d10v | d30v | dlx | dsp16xx \
-
	| epiphany \
-
	| fido | fr30 | frv \
+
	| e2k | epiphany \
+
	| fido | fr30 | frv | ft32 \
	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
	| hexagon \
-
	| i370 | i860 | i960 | ia64 \
+
	| i370 | i860 | i960 | ia16 | ia64 \
	| ip2k | iq2000 \
	| k1om \
	| le32 | le64 \
@@ -299,13 +296,14 @@ case $basic_machine in
	| nios | nios2 | nios2eb | nios2el \
	| ns16k | ns32k \
	| open8 | or1k | or1knd | or32 \
-
	| pdp10 | pdp11 | pj | pjl \
+
	| pdp10 | pj | pjl \
	| powerpc | powerpc64 | powerpc64le | powerpcle \
+
	| pru \
	| pyramid \
	| riscv32 | riscv64 \
	| rl78 | rx \
	| score \
-
	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+
	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
	| sh64 | sh64le \
	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -314,7 +312,7 @@ case $basic_machine in
	| ubicom32 \
	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
	| visium \
-
	| we32k \
+
	| wasm32 \
	| x86 | xc16x | xstormy16 | xtensa \
	| z8k | z80)
		basic_machine=$basic_machine-unknown
@@ -335,7 +333,7 @@ case $basic_machine in
		basic_machine=$basic_machine-unknown
		os=-none
		;;
-
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
		;;
	ms1)
		basic_machine=mt-unknown
@@ -364,7 +362,7 @@ case $basic_machine in
	  ;;
	# Object if more than one company name word.
	*-*-*)
-
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+
		echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
		exit 1
		;;
	# Recognize the basic CPU types with company name.
@@ -376,17 +374,18 @@ case $basic_machine in
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
	| avr-* | avr32-* \
+
	| ba-* \
	| be32-* | be64-* \
	| bfin-* | bs2000-* \
	| c[123]* | c30-* | [cjt]90-* | c4x-* \
	| c8051-* | clipper-* | craynv-* | cydra-* \
	| d10v-* | d30v-* | dlx-* \
-
	| elxsi-* \
+
	| e2k-* | elxsi-* \
	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
	| h8300-* | h8500-* \
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
	| hexagon-* \
-
	| i*86-* | i860-* | i960-* | ia64-* \
+
	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
	| ip2k-* | iq2000-* \
	| k1om-* \
	| le32-* | le64-* \
@@ -427,13 +426,15 @@ case $basic_machine in
	| orion-* \
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+
	| pru-* \
	| pyramid-* \
+
	| riscv32-* | riscv64-* \
	| rl78-* | romp-* | rs6000-* | rx-* \
	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
	| sparclite-* \
-
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
	| tahoe-* \
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
	| tile*-* \
@@ -442,6 +443,7 @@ case $basic_machine in
	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
	| vax-* \
	| visium-* \
+
	| wasm32-* \
	| we32k-* \
	| x86-* | x86_64-* | xc16x-* | xps100-* \
	| xstormy16-* | xtensa*-* \
@@ -455,7 +457,7 @@ case $basic_machine in
	# Recognize the various machine names and aliases which stand
	# for a CPU type and a company and sometimes even an OS.
	386bsd)
-
		basic_machine=i386-unknown
+
		basic_machine=i386-pc
		os=-bsd
		;;
	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
@@ -489,7 +491,7 @@ case $basic_machine in
		basic_machine=x86_64-pc
		;;
	amd64-*)
-
		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	amdahl)
		basic_machine=580-amdahl
@@ -518,6 +520,9 @@ case $basic_machine in
		basic_machine=i386-pc
		os=-aros
		;;
+
	asmjs)
+
		basic_machine=asmjs-unknown
+
		;;
	aux)
		basic_machine=m68k-apple
		os=-aux
@@ -531,7 +536,7 @@ case $basic_machine in
		os=-linux
		;;
	blackfin-*)
-
		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		os=-linux
		;;
	bluegene*)
@@ -539,13 +544,13 @@ case $basic_machine in
		os=-cnk
		;;
	c54x-*)
-
		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	c55x-*)
-
		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	c6x-*)
-
		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	c90)
		basic_machine=c90-cray
@@ -634,10 +639,18 @@ case $basic_machine in
		basic_machine=rs6000-bull
		os=-bosx
		;;
-
	dpx2* | dpx2*-bull)
+
	dpx2*)
		basic_machine=m68k-bull
		os=-sysv3
		;;
+
	e500v[12])
+
		basic_machine=powerpc-unknown
+
		os=$os"spe"
+
		;;
+
	e500v[12]-*)
+
		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+
		os=$os"spe"
+
		;;
	ebmon29k)
		basic_machine=a29k-amd
		os=-ebmon
@@ -727,9 +740,6 @@ case $basic_machine in
	hp9k8[0-9][0-9] | hp8[0-9][0-9])
		basic_machine=hppa1.0-hp
		;;
-
	hppa-next)
-
		os=-nextstep3
-
		;;
	hppaosf)
		basic_machine=hppa1.1-hp
		os=-osf
@@ -742,26 +752,26 @@ case $basic_machine in
		basic_machine=i370-ibm
		;;
	i*86v32)
-
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
		os=-sysv32
		;;
	i*86v4*)
-
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
		os=-sysv4
		;;
	i*86v)
-
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
		os=-sysv
		;;
	i*86sol2)
-
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+
		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
		os=-solaris2
		;;
	i386mach)
		basic_machine=i386-mach
		os=-mach
		;;
-
	i386-vsta | vsta)
+
	vsta)
		basic_machine=i386-unknown
		os=-vsta
		;;
@@ -780,19 +790,16 @@ case $basic_machine in
		os=-sysv
		;;
	leon-*|leon[3-9]-*)
-
		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+
		basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
		;;
	m68knommu)
		basic_machine=m68k-unknown
		os=-linux
		;;
	m68knommu-*)
-
		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		os=-linux
		;;
-
	m88k-omron*)
-
		basic_machine=m88k-omron
-
		;;
	magnum | m3230)
		basic_machine=mips-mips
		os=-sysv
@@ -824,10 +831,10 @@ case $basic_machine in
		os=-mint
		;;
	mips3*-*)
-
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+
		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
		;;
	mips3*)
-
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+
		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
		;;
	monitor)
		basic_machine=m68k-rom68k
@@ -846,7 +853,7 @@ case $basic_machine in
		os=-msdos
		;;
	ms1-*)
-
		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+
		basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
		;;
	msys)
		basic_machine=i686-pc
@@ -888,7 +895,7 @@ case $basic_machine in
		basic_machine=v70-nec
		os=-sysv
		;;
-
	next | m*-next )
+
	next | m*-next)
		basic_machine=m68k-next
		case $os in
		    -nextstep* )
@@ -933,6 +940,12 @@ case $basic_machine in
	nsr-tandem)
		basic_machine=nsr-tandem
		;;
+
	nsv-tandem)
+
		basic_machine=nsv-tandem
+
		;;
+
	nsx-tandem)
+
		basic_machine=nsx-tandem
+
		;;
	op50n-* | op60c-*)
		basic_machine=hppa1.1-oki
		os=-proelf
@@ -965,7 +978,7 @@ case $basic_machine in
		os=-linux
		;;
	parisc-*)
-
		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		os=-linux
		;;
	pbd)
@@ -981,7 +994,7 @@ case $basic_machine in
		basic_machine=i386-pc
		;;
	pc98-*)
-
		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	pentium | p5 | k5 | k6 | nexgen | viac3)
		basic_machine=i586-pc
@@ -996,16 +1009,16 @@ case $basic_machine in
		basic_machine=i786-pc
		;;
	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-
		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	pentiumpro-* | p6-* | 6x86-* | athlon-*)
-
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	pentium4-*)
-
		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	pn)
		basic_machine=pn-gould
@@ -1015,23 +1028,23 @@ case $basic_machine in
	ppc | ppcbe)	basic_machine=powerpc-unknown
		;;
	ppc-* | ppcbe-*)
-
		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
-
	ppcle | powerpclittle | ppc-le | powerpc-little)
+
	ppcle | powerpclittle)
		basic_machine=powerpcle-unknown
		;;
	ppcle-* | powerpclittle-*)
-
		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	ppc64)	basic_machine=powerpc64-unknown
		;;
-
	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+
	ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
-
	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+
	ppc64le | powerpc64little)
		basic_machine=powerpc64le-unknown
		;;
	ppc64le-* | powerpc64little-*)
-
		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	ps2)
		basic_machine=i386-ibm
@@ -1085,17 +1098,10 @@ case $basic_machine in
	sequent)
		basic_machine=i386-sequent
		;;
-
	sh)
-
		basic_machine=sh-hitachi
-
		os=-hms
-
		;;
	sh5el)
		basic_machine=sh5le-unknown
		;;
-
	sh64)
-
		basic_machine=sh64-unknown
-
		;;
-
	sparclite-wrs | simso-wrs)
+
	simso-wrs)
		basic_machine=sparclite-wrs
		os=-vxworks
		;;
@@ -1114,7 +1120,7 @@ case $basic_machine in
		os=-sysv4
		;;
	strongarm-* | thumb-*)
-
		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+
		basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
		;;
	sun2)
		basic_machine=m68000-sun
@@ -1236,6 +1242,9 @@ case $basic_machine in
		basic_machine=hppa1.1-winbond
		os=-proelf
		;;
+
	x64)
+
		basic_machine=x86_64-pc
+
		;;
	xbox)
		basic_machine=i686-pc
		os=-mingw32
@@ -1244,20 +1253,12 @@ case $basic_machine in
		basic_machine=xps100-honeywell
		;;
	xscale-* | xscalee[bl]-*)
-
		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+
		basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
		;;
	ymp)
		basic_machine=ymp-cray
		os=-unicos
		;;
-
	z8k-*-coff)
-
		basic_machine=z8k-unknown
-
		os=-sim
-
		;;
-
	z80-*-coff)
-
		basic_machine=z80-unknown
-
		os=-sim
-
		;;
	none)
		basic_machine=none-none
		os=-none
@@ -1286,10 +1287,6 @@ case $basic_machine in
	vax)
		basic_machine=vax-dec
		;;
-
	pdp10)
-
		# there are many clones, so DEC is not a safe bet
-
		basic_machine=pdp10-unknown
-
		;;
	pdp11)
		basic_machine=pdp11-dec
		;;
@@ -1299,9 +1296,6 @@ case $basic_machine in
	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
		basic_machine=sh-unknown
		;;
-
	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
-
		basic_machine=sparc-sun
-
		;;
	cydra)
		basic_machine=cydra-cydrome
		;;
@@ -1321,7 +1315,7 @@ case $basic_machine in
		# Make sure to match an already-canonicalized machine name.
		;;
	*)
-
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+
		echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
		exit 1
		;;
esac
@@ -1329,10 +1323,10 @@ esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
	*-digital*)
-
		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+
		basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
		;;
	*-commodore*)
-
		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+
		basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
		;;
	*)
		;;
@@ -1343,8 +1337,8 @@ esac
if [ x"$os" != x"" ]
then
case $os in
-
	# First match some system type aliases
-
	# that might get confused with valid system types.
+
	# First match some system type aliases that might get confused
+
	# with valid system types.
	# -solaris* is a basic system type, with this one exception.
	-auroraux)
		os=-auroraux
@@ -1355,45 +1349,48 @@ case $os in
	-solaris)
		os=-solaris2
		;;
-
	-svr4*)
-
		os=-sysv4
-
		;;
	-unixware*)
		os=-sysv4.2uw
		;;
	-gnu/linux*)
		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
		;;
-
	# First accept the basic system types.
+
	# es1800 is here to avoid being matched by es* (a different OS)
+
	-es1800*)
+
		os=-ose
+
		;;
+
	# Now accept the basic system types.
	# The portable systems comes first.
-
	# Each alternative MUST END IN A *, to match a version number.
+
	# Each alternative MUST end in a * to match a version number.
	# -sysv* is not here because it comes later, after sysvr4.
	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
	      | -sym* | -kopensolaris* | -plan9* \
	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-
	      | -aos* | -aros* \
+
	      | -aos* | -aros* | -cloudabi* | -sortix* \
	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-
	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-
	      | -bitrig* | -openbsd* | -solidbsd* \
+
	      | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
+
	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
-
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-
	      | -chorusos* | -chorusrdb* | -cegcc* \
+
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \
+
	      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-
	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+
	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
-
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
-
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+
	      | -morphos* | -superux* | -rtmk* | -windiss* \
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-
	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+
	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+
	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
+
	      | -midnightbsd*)
	# Remember, each alternative MUST END IN *, to match a version number.
		;;
	-qnx*)
@@ -1410,12 +1407,12 @@ case $os in
	-nto*)
		os=`echo $os | sed -e 's|nto|nto-qnx|'`
		;;
-
	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-
	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+
	-sim | -xray | -os68k* | -v88r* \
+
	      | -windows* | -osx | -abug | -netware* | -os9* \
	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
		;;
	-mac*)
-
		os=`echo $os | sed -e 's|mac|macos|'`
+
		os=`echo "$os" | sed -e 's|mac|macos|'`
		;;
	-linux-dietlibc)
		os=-linux-dietlibc
@@ -1424,10 +1421,10 @@ case $os in
		os=`echo $os | sed -e 's|linux|linux-gnu|'`
		;;
	-sunos5*)
-
		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+
		os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
		;;
	-sunos6*)
-
		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+
		os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
		;;
	-opened*)
		os=-openedition
@@ -1438,12 +1435,6 @@ case $os in
	-wince*)
		os=-wince
		;;
-
	-osfrose*)
-
		os=-osfrose
-
		;;
-
	-osf*)
-
		os=-osf
-
		;;
	-utek*)
		os=-bsd
		;;
@@ -1468,7 +1459,7 @@ case $os in
	-nova*)
		os=-rtmk-nova
		;;
-
	-ns2 )
+
	-ns2)
		os=-nextstep2
		;;
	-nsk*)
@@ -1490,7 +1481,7 @@ case $os in
	-oss*)
		os=-sysv3
		;;
-
	-svr4)
+
	-svr4*)
		os=-sysv4
		;;
	-svr3)
@@ -1505,32 +1496,38 @@ case $os in
	-ose*)
		os=-ose
		;;
-
	-es1800*)
-
		os=-ose
-
		;;
-
	-xenix)
-
		os=-xenix
-
		;;
	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
		os=-mint
		;;
-
	-aros*)
-
		os=-aros
-
		;;
	-zvmoe)
		os=-zvmoe
		;;
	-dicos*)
		os=-dicos
		;;
+
	-pikeos*)
+
		# Until real need of OS specific support for
+
		# particular features comes up, bare metal
+
		# configurations are quite functional.
+
		case $basic_machine in
+
		    arm*)
+
			os=-eabi
+
			;;
+
		    *)
+
			os=-elf
+
			;;
+
		esac
+
		;;
	-nacl*)
		;;
+
	-ios)
+
		;;
	-none)
		;;
	*)
		# Get rid of the `-' at the beginning of $os.
		os=`echo $os | sed 's/[^-]*-//'`
-
		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+
		echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
		exit 1
		;;
esac
@@ -1620,12 +1617,12 @@ case $basic_machine in
	sparc-* | *-sun)
		os=-sunos4.1.1
		;;
+
	pru-*)
+
		os=-elf
+
		;;
	*-be)
		os=-beos
		;;
-
	*-haiku)
-
		os=-haiku
-
		;;
	*-ibm)
		os=-aix
		;;
@@ -1665,7 +1662,7 @@ case $basic_machine in
	m88k-omron*)
		os=-luna
		;;
-
	*-next )
+
	*-next)
		os=-nextstep
		;;
	*-sequent)
@@ -1680,9 +1677,6 @@ case $basic_machine in
	i370-*)
		os=-mvs
		;;
-
	*-next)
-
		os=-nextstep3
-
		;;
	*-gould)
		os=-sysv
		;;
@@ -1792,15 +1786,15 @@ case $basic_machine in
				vendor=stratus
				;;
		esac
-
		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+
		basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
		;;
esac

-
echo $basic_machine$os
+
echo "$basic_machine$os"
exit

# Local variables:
-
# eval: (add-hook 'write-file-hooks 'time-stamp)
+
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
modified autosetup/autosetup-test-tclsh
modified autosetup/cc-db.tcl
@@ -8,7 +8,7 @@

use cc

-
module-options {}
+
options {}

# openbsd needs sys/types.h to detect some system headers
cc-include-needs sys/socket.h sys/types.h
modified autosetup/cc-lib.tcl
@@ -7,12 +7,10 @@

use cc

-
module-options {}
-

# @cc-check-lfs
#
# The equivalent of the 'AC_SYS_LARGEFILE' macro.
-
# 
+
#
# defines 'HAVE_LFS' if LFS is available,
# and defines '_FILE_OFFSET_BITS=64' if necessary
#
@@ -38,7 +36,7 @@ proc cc-check-lfs {} {
# @cc-check-endian
#
# The equivalent of the 'AC_C_BIGENDIAN' macro.
-
# 
+
#
# defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
#
modified autosetup/cc-shared.tcl
@@ -9,23 +9,26 @@
## SH_CFLAGS         Flags to use compiling sources destined for a shared library
## SH_LDFLAGS        Flags to use linking (creating) a shared library
## SH_SOPREFIX       Prefix to use to set the soname when creating a shared library
+
## SH_SOFULLPATH     Set to 1 if the shared library soname should include the full install path
## SH_SOEXT          Extension for shared libs
## SH_SOEXTVER       Format for versioned shared libs - %s = version
## SHOBJ_CFLAGS      Flags to use compiling sources destined for a shared object
## SHOBJ_LDFLAGS     Flags to use linking a shared object, undefined symbols allowed
## SHOBJ_LDFLAGS_R   - as above, but all symbols must be resolved
+
## SH_LINKRPATH      Format for setting the rpath when linking an executable, %s = path
## SH_LINKFLAGS      Flags to use linking an executable which will load shared objects
## LD_LIBRARY_PATH   Environment variable which specifies path to shared libraries
## STRIPLIBFLAGS     Arguments to strip a dynamic library

-
module-options {}
+
options {}

# Defaults: gcc on unix
-
define SHOBJ_CFLAGS -fpic
+
define SHOBJ_CFLAGS -fPIC
define SHOBJ_LDFLAGS -shared
-
define SH_CFLAGS -fpic
+
define SH_CFLAGS -fPIC
define SH_LDFLAGS -shared
define SH_LINKFLAGS -rdynamic
+
define SH_LINKRPATH "-Wl,-rpath -Wl,%s"
define SH_SOEXT .so
define SH_SOEXTVER .so.%s
define SH_SOPREFIX -Wl,-soname,
@@ -46,6 +49,7 @@ switch -glob -- [get-define host] {
		define SH_SOEXT .dylib
		define SH_SOEXTVER .%s.dylib
		define SH_SOPREFIX -Wl,-install_name,
+
		define SH_SOFULLPATH
		define LD_LIBRARY_PATH DYLD_LIBRARY_PATH
		define STRIPLIBFLAGS -x
	}
@@ -54,6 +58,7 @@ switch -glob -- [get-define host] {
		define SHOBJ_LDFLAGS -shared
		define SH_CFLAGS ""
		define SH_LDFLAGS -shared
+
		define SH_LINKRPATH ""
		define SH_LINKFLAGS ""
		define SH_SOEXT .dll
		define SH_SOEXTVER .dll
@@ -64,23 +69,19 @@ switch -glob -- [get-define host] {
		if {[msg-quiet cc-check-decls __SUNPRO_C]} {
			msg-result "Found sun stdio compiler"
			# sun stdio compiler
-
			# XXX: These haven't been fully tested. 
+
			# XXX: These haven't been fully tested.
			define SHOBJ_CFLAGS -KPIC
			define SHOBJ_LDFLAGS "-G"
			define SH_CFLAGS -KPIC
			define SH_LINKFLAGS -Wl,-export-dynamic
			define SH_SOPREFIX -Wl,-h,
-
		} else {
-
			# sparc has a very small GOT table limit, so use -fPIC
-
			define SH_CFLAGS -fPIC
-
			define SHOBJ_CFLAGS -fPIC
		}
	}
	*-*-solaris* {
		if {[msg-quiet cc-check-decls __SUNPRO_C]} {
			msg-result "Found sun stdio compiler"
			# sun stdio compiler
-
			# XXX: These haven't been fully tested. 
+
			# XXX: These haven't been fully tested.
			define SHOBJ_CFLAGS -KPIC
			define SHOBJ_LDFLAGS "-G"
			define SH_CFLAGS -KPIC
@@ -105,11 +106,6 @@ switch -glob -- [get-define host] {
		define SH_SOPREFIX ""
		define LD_LIBRARY_PATH LIBRARY_PATH
	}
-
	microblaze* {
-
		# Microblaze generally needs -fPIC rather than -fpic
-
		define SHOBJ_CFLAGS -fPIC
-
		define SH_CFLAGS -fPIC
-
	}
}

if {![is-defined SHOBJ_LDFLAGS_R]} {
modified autosetup/cc.tcl
@@ -11,6 +11,7 @@
#
## CC       - C compiler
## CXX      - C++ compiler
+
## CPP      - C preprocessor
## CCACHE   - Set to "none" to disable automatic use of ccache
## CFLAGS   - Additional C compiler flags
## CXXFLAGS - Additional C++ compiler flags
@@ -28,7 +29,7 @@

use system

-
module-options {}
+
options {}

# Checks for the existence of the given function by linking
#
@@ -213,7 +214,7 @@ proc cc-check-members {args} {
# These libraries are not automatically added to 'LIBS'.
#
# Returns 1 if found or 0 if not.
-
# 
+
#
proc cc-check-function-in-lib {function libs {otherlibs {}}} {
	msg-checking "Checking libs for $function..."
	set found 0
@@ -434,7 +435,7 @@ proc cc-with {settings args} {
}

# @cctest ?settings?
-
# 
+
#
# Low level C/C++ compiler checker. Compiles and or links a small C program
# according to the arguments and returns 1 if OK, or 0 if not.
#
@@ -465,7 +466,6 @@ proc cc-with {settings args} {
# Any failures are recorded in 'config.log'
#
proc cctest {args} {
-
	set src conftest__.c
	set tmp conftest__

	# Easiest way to merge in the settings
@@ -507,9 +507,11 @@ proc cctest {args} {
	lappend cmdline {*}[get-define CCACHE]
	switch -exact -- $opts(-lang) {
		c++ {
+
			set src conftest__.cpp
			lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS]
		}
		c {
+
			set src conftest__.c
			lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS]
		}
		default {
@@ -678,11 +680,11 @@ if {[get-define CC] eq ""} {
define CPP [get-env CPP "[get-define CC] -E"]

# XXX: Could avoid looking for a C++ compiler until requested
-
# Note that if CXX isn't found, we just set it to "false". It might not be needed.
+
# 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++ false]
+
	define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
}

# CXXFLAGS default to CFLAGS if not specified
@@ -697,6 +699,15 @@ if {[get-define CC] eq ""} {

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 AUTOREMAKE [quote-if-needed $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) {}
modified autosetup/jimsh0.c
@@ -59,7 +59,7 @@
#define HAVE_UNISTD_H
#define HAVE_UMASK
#endif
-
#define JIM_VERSION 77
+
#define JIM_VERSION 78
#ifndef JIM_WIN32COMPAT_H
#define JIM_WIN32COMPAT_H

@@ -129,11 +129,6 @@ DIR *opendir(const char *name);
int closedir(DIR *dir);
struct dirent *readdir(DIR *dir);

-
#elif defined(__MINGW32__)
-

-
#include <stdlib.h>
-
#define strtod __strtod
-

#endif

#endif
@@ -376,6 +371,12 @@ typedef struct Jim_Obj {
        } twoPtrValue;

        struct {
+
            void *ptr;
+
            int int1;
+
            int int2;
+
        } ptrIntValue;
+

+
        struct {
            struct Jim_Var *varPtr;
            unsigned long callFrameId;
            int global;
@@ -412,11 +413,6 @@ typedef struct Jim_Obj {
            struct Jim_Obj *varNameObjPtr;
            struct Jim_Obj *indexObjPtr;
        } dictSubstValue;
-

-
        struct {
-
            void *compre;
-
            unsigned flags;
-
        } regexpValue;
        struct {
            int line;
            int argc;
@@ -574,7 +570,7 @@ typedef struct Jim_Interp {
    unsigned long referenceNextId;
    struct Jim_HashTable references;
    unsigned long lastCollectId; /* reference max Id of the last GC
-
                execution. It's set to -1 while the collection
+
                execution. It's set to ~0 while the collection
                is running as sentinel to avoid to recursive
                calls via the [collect] command inside
                finalizers. */
@@ -639,7 +635,7 @@ JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);

JIM_EXPORT char **Jim_GetEnviron(void);
JIM_EXPORT void Jim_SetEnviron(char **env);
-
JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template);
+
JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file);


JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
@@ -847,7 +843,7 @@ JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,


JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
-
        Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
+
        Jim_Obj *exprObjPtr);
JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
        Jim_Obj *exprObjPtr, int *boolPtr);

@@ -904,7 +900,8 @@ JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp);
JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
JIM_EXPORT void Jim_HistoryLoad(const char *filename);
JIM_EXPORT void Jim_HistorySave(const char *filename);
-
JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
+
JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt);
+
JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj);
JIM_EXPORT void Jim_HistoryAdd(const char *line);
JIM_EXPORT void Jim_HistoryShow(void);

@@ -1055,6 +1052,79 @@ void regfree(regex_t *preg);
#endif

#endif
+
#ifndef JIM_SIGNAL_H
+
#define JIM_SIGNAL_H
+

+
#ifdef __cplusplus
+
extern "C" {
+
#endif
+

+
const char *Jim_SignalId(int sig);
+

+
#ifdef __cplusplus
+
}
+
#endif
+

+
#endif
+
#ifndef JIMIOCOMPAT_H
+
#define JIMIOCOMPAT_H
+

+

+
#include <stdio.h>
+
#include <errno.h>
+

+

+
void Jim_SetResultErrno(Jim_Interp *interp, const char *msg);
+

+
int Jim_OpenForWrite(const char *filename, int append);
+

+
int Jim_OpenForRead(const char *filename);
+

+
#if defined(__MINGW32__)
+
    #ifndef STRICT
+
    #define STRICT
+
    #endif
+
    #define WIN32_LEAN_AND_MEAN
+
    #include <windows.h>
+
    #include <fcntl.h>
+
    #include <io.h>
+
    #include <process.h>
+

+
    typedef HANDLE pidtype;
+
    #define JIM_BAD_PID INVALID_HANDLE_VALUE
+

+
    #define JIM_NO_PID INVALID_HANDLE_VALUE
+

+

+
    #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0)
+
    #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff)
+
    #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0)
+
    #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff)
+
    #define WNOHANG 1
+

+
    int Jim_Errno(void);
+
    pidtype waitpid(pidtype pid, int *status, int nohang);
+

+
    #define HAVE_PIPE
+
    #define pipe(P) _pipe((P), 0, O_NOINHERIT)
+

+
#elif defined(HAVE_UNISTD_H)
+
    #include <unistd.h>
+
    #include <fcntl.h>
+
    #include <sys/wait.h>
+
    #include <sys/stat.h>
+

+
    typedef int pidtype;
+
    #define Jim_Errno() errno
+
    #define JIM_BAD_PID -1
+
    #define JIM_NO_PID 0
+

+
    #ifndef HAVE_EXECVPE
+
        #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
+
    #endif
+
#endif
+

+
#endif
int Jim_bootstrapInit(Jim_Interp *interp)
{
	if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
@@ -1063,11 +1133,15 @@ int Jim_bootstrapInit(Jim_Interp *interp)
	return Jim_EvalSource(interp, "bootstrap.tcl", 1,
"\n"
"\n"
-
"proc package {cmd pkg} {\n"
+
"proc package {cmd pkg args} {\n"
"	if {$cmd eq \"require\"} {\n"
"		foreach path $::auto_path {\n"
-
"			if {[file exists $path/$pkg.tcl]} {\n"
-
"				uplevel #0 [list source $path/$pkg.tcl]\n"
+
"			set pkgpath $path/$pkg.tcl\n"
+
"			if {$path eq \".\"} {\n"
+
"				set pkgpath $pkg.tcl\n"
+
"			}\n"
+
"			if {[file exists $pkgpath]} {\n"
+
"				uplevel #0 [list source $pkgpath]\n"
"				return\n"
"			}\n"
"		}\n"
@@ -1374,6 +1448,13 @@ int Jim_stdlibInit(Jim_Interp *interp)
	return Jim_EvalSource(interp, "stdlib.tcl", 1,
"\n"
"\n"
+
"if {![exists -command ref]} {\n"
+
"\n"
+
"	proc ref {args} {{count 0}} {\n"
+
"		format %08x [incr count]\n"
+
"	}\n"
+
"}\n"
+
"\n"
"\n"
"proc lambda {arglist args} {\n"
"	tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
@@ -1435,6 +1516,13 @@ int Jim_stdlibInit(Jim_Interp *interp)
"\n"
"\n"
"\n"
+
"proc defer {script} {\n"
+
"	upvar jim::defer v\n"
+
"	lappend v $script\n"
+
"}\n"
+
"\n"
+
"\n"
+
"\n"
"proc errorInfo {msg {stacktrace \"\"}} {\n"
"	if {$stacktrace eq \"\"} {\n"
"\n"
@@ -1666,7 +1754,7 @@ int Jim_tclcompatInit(Jim_Interp *interp)
"\n"
"\n"
"proc popen {cmd {mode r}} {\n"
-
"	lassign [socket pipe] r w\n"
+
"	lassign [pipe] r w\n"
"	try {\n"
"		if {[string match \"w*\" $mode]} {\n"
"			lappend cmd <@$r &\n"
@@ -1683,11 +1771,26 @@ 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"
-
"				foreach p $pids { os.wait $p }\n"
-
"				return\n"
+
"				set retopts {}\n"
+
"				foreach p $pids {\n"
+
"					lassign [wait $p] status - rc\n"
+
"					if {$status eq \"CHILDSTATUS\"} {\n"
+
"						if {$rc == 0} {\n"
+
"							continue\n"
+
"						}\n"
+
"						set msg \"child process exited abnormally\"\n"
+
"					} else {\n"
+
"						set msg \"child killed: received signal\"\n"
+
"					}\n"
+
"					set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n"
+
"				}\n"
+
"				return {*}$retopts\n"
"			}\n"
"			tailcall $f $cmd {*}$args\n"
"		}\n"
@@ -1720,6 +1823,7 @@ int Jim_tclcompatInit(Jim_Interp *interp)
"\n"
"\n"
"\n"
+
"\n"
"proc try {args} {\n"
"	set catchopts {}\n"
"	while {[string match -* [lindex $args 0]]} {\n"
@@ -1810,11 +1914,15 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
#include <sys/socket.h>
#include <netinet/in.h>
+
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
+
#define HAVE_SOCKETS
+
#elif defined (__MINGW32__)
+

#else
#define JIM_ANSIC
#endif
@@ -1849,7 +1957,11 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#endif
#endif

-
#define JimCheckStreamError(interp, af) af->fops->error(af)
+
#ifdef JIM_ANSIC
+

+
#undef HAVE_PIPE
+
#undef HAVE_SOCKETPAIR
+
#endif


struct AioFile;
@@ -1956,6 +2068,15 @@ static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name)
    }
}

+
static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
+
{
+
	int ret = af->fops->error(af);
+
	if (ret) {
+
		JimAioSetError(interp, af->filename);
+
	}
+
	return ret;
+
}
+

static void JimAioDelProc(Jim_Interp *interp, void *privData)
{
    AioFile *af = privData;
@@ -2068,6 +2189,16 @@ FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
    return af->fp;
}

+
static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
{
+
    AioFile *af = Jim_CmdPrivData(interp);
+

+
    fflush(af->fp);
+
    Jim_SetResultInt(interp, fileno(af->fp));
+

+
    return JIM_OK;
+
}
+

static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);
@@ -2226,7 +2357,7 @@ static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    if (argc == 3) {
-
#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
+
#if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN)
        static const char * const options[] = { "r", "w", NULL };
        enum { OPT_R, OPT_W, };
        int option;
@@ -2317,6 +2448,7 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#endif

+

#ifdef HAVE_FSYNC
static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -2451,6 +2583,13 @@ static const jim_subcmd_type aio_command_table[] = {
        2,

    },
+
    {   "getfd",
+
        NULL,
+
        aio_cmd_getfd,
+
        0,
+
        0,
+

+
    },
    {   "gets",
        "?var?",
        aio_cmd_gets,
@@ -2624,17 +2763,17 @@ static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *fi
    Jim_IncrRefCount(filename);

    if (fh == NULL) {
-
#if !defined(JIM_ANSIC)
        if (fd >= 0) {
+
#ifndef JIM_ANSIC
            fh = fdopen(fd, mode);
+
#endif
        }
        else
-
#endif
            fh = fopen(Jim_String(filename), mode);

        if (fh == NULL) {
            JimAioSetError(interp, filename);
-
#if !defined(JIM_ANSIC)
+
#ifndef JIM_ANSIC
            if (fd >= 0) {
                close(fd);
            }
@@ -2648,14 +2787,16 @@ static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *fi
    af = Jim_Alloc(sizeof(*af));
    memset(af, 0, sizeof(*af));
    af->fp = fh;
-
    af->fd = fileno(fh);
    af->filename = filename;
+
    af->openFlags = openFlags;
+
#ifndef JIM_ANSIC
+
    af->fd = fileno(fh);
#ifdef FD_CLOEXEC
    if ((openFlags & AIO_KEEPOPEN) == 0) {
        (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
    }
#endif
-
    af->openFlags = openFlags;
+
#endif
    af->addr_family = family;
    af->fops = &stdio_fops;
    af->ssl = NULL;
@@ -2674,7 +2815,6 @@ static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
    if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
        Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
        Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
-

        if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) {
            Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
            Jim_SetResult(interp, objPtr);
@@ -2690,46 +2830,26 @@ static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
}
#endif

-

-
int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template)
+
#ifdef HAVE_PIPE
+
static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-
#ifdef HAVE_MKSTEMP
-
    int fd;
-
    mode_t mask;
-
    Jim_Obj *filenameObj;
+
    int p[2];
+
    static const char *mode[2] = { "r", "w" };

-
    if (filename_template == NULL) {
-
        const char *tmpdir = getenv("TMPDIR");
-
        if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
-
            tmpdir = "/tmp/";
-
        }
-
        filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
-
        if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
-
            Jim_AppendString(interp, filenameObj, "/", 1);
-
        }
-
        Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
-
    }
-
    else {
-
        filenameObj = Jim_NewStringObj(interp, filename_template, -1);
+
    if (argc != 1) {
+
        Jim_WrongNumArgs(interp, 1, argv, "");
+
        return JIM_ERR;
    }

-

-
    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
-
    fd = mkstemp(filenameObj->bytes);
-
    umask(mask);
-
    if (fd < 0) {
-
        JimAioSetError(interp, filenameObj);
-
        Jim_FreeNewObj(interp, filenameObj);
-
        return -1;
+
    if (pipe(p) != 0) {
+
        JimAioSetError(interp, NULL);
+
        return JIM_ERR;
    }

-
    Jim_SetResult(interp, filenameObj);
-
    return fd;
-
#else
-
    Jim_SetResultString(interp, "platform has no tempfile support", -1);
-
    return -1;
-
#endif
+
    return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode);
}
+
#endif
+



int Jim_aioInit(Jim_Interp *interp)
@@ -2742,9 +2862,12 @@ int Jim_aioInit(Jim_Interp *interp)
#endif

    Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
-
#ifndef JIM_ANSIC
+
#ifdef HAVE_SOCKETS
    Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
#endif
+
#ifdef HAVE_PIPE
+
    Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL);
+
#endif


    JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
@@ -2828,8 +2951,8 @@ int Jim_readdirInit(Jim_Interp *interp)

static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
-
    regfree(objPtr->internalRep.regexpValue.compre);
-
    Jim_Free(objPtr->internalRep.regexpValue.compre);
+
    regfree(objPtr->internalRep.ptrIntValue.ptr);
+
    Jim_Free(objPtr->internalRep.ptrIntValue.ptr);
}

static const Jim_ObjType regexpObjType = {
@@ -2848,9 +2971,9 @@ static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned f


    if (objPtr->typePtr == &regexpObjType &&
-
        objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
+
        objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) {

-
        return objPtr->internalRep.regexpValue.compre;
+
        return objPtr->internalRep.ptrIntValue.ptr;
    }


@@ -2872,8 +2995,8 @@ static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned f
    Jim_FreeIntRep(interp, objPtr);

    objPtr->typePtr = &regexpObjType;
-
    objPtr->internalRep.regexpValue.flags = flags;
-
    objPtr->internalRep.regexpValue.compre = compre;
+
    objPtr->internalRep.ptrIntValue.int1 = flags;
+
    objPtr->internalRep.ptrIntValue.ptr = compre;

    return compre;
}
@@ -3335,13 +3458,20 @@ int Jim_regexpInit(Jim_Interp *interp)
# define MAXPATHLEN JIM_PATH_LEN
# endif

-
#if defined(__MINGW32__) || defined(_MSC_VER)
+
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
#define ISWINDOWS 1
#else
#define ISWINDOWS 0
#endif


+
#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+
    #define STAT_MTIME_US(STAT) ((STAT).st_mtimespec.tv_sec * 1000000ll + (STAT).st_mtimespec.tv_nsec / 1000)
+
#elif defined(HAVE_STRUCT_STAT_ST_MTIM)
+
    #define STAT_MTIME_US(STAT) ((STAT).st_mtim.tv_sec * 1000000ll + (STAT).st_mtim.tv_nsec / 1000)
+
#endif
+

+

static const char *JimGetFileType(int mode)
{
    if (S_ISREG(mode)) {
@@ -3399,6 +3529,9 @@ static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat
    AppendStatElement(interp, listObj, "atime", sb->st_atime);
    AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
    AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
+
#ifdef STAT_MTIME_US
+
    AppendStatElement(interp, listObj, "mtimeus", STAT_MTIME_US(*sb));
+
#endif
    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));

@@ -3715,7 +3848,7 @@ static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv)

static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-
    int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
+
    int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0);

    if (fd < 0) {
        return JIM_ERR;
@@ -3833,37 +3966,62 @@ static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
    return JIM_OK;
}

+
static int JimSetFileTimes(Jim_Interp *interp, const char *filename, jim_wide us)
+
{
+
#ifdef HAVE_UTIMES
+
    struct timeval times[2];
+

+
    times[1].tv_sec = times[0].tv_sec = us / 1000000;
+
    times[1].tv_usec = times[0].tv_usec = us % 1000000;
+

+
    if (utimes(filename, times) != 0) {
+
        Jim_SetResultFormatted(interp, "can't set time on \"%s\": %s", filename, strerror(errno));
+
        return JIM_ERR;
+
    }
+
    return JIM_OK;
+
#else
+
    Jim_SetResultString(interp, "Not implemented", -1);
+
    return JIM_ERR;
+
#endif
+
}
+

static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    struct stat sb;

    if (argc == 2) {
-
#ifdef HAVE_UTIMES
-
        jim_wide newtime;
-
        struct timeval times[2];
-

-
        if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) {
+
        jim_wide secs;
+
        if (Jim_GetWide(interp, argv[1], &secs) != JIM_OK) {
            return JIM_ERR;
        }
+
        return JimSetFileTimes(interp, Jim_String(argv[0]), secs * 1000000);
+
    }
+
    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+
        return JIM_ERR;
+
    }
+
    Jim_SetResultInt(interp, sb.st_mtime);
+
    return JIM_OK;
+
}

-
        times[1].tv_sec = times[0].tv_sec = newtime;
-
        times[1].tv_usec = times[0].tv_usec = 0;
+
#ifdef STAT_MTIME_US
+
static int file_cmd_mtimeus(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
{
+
    struct stat sb;

-
        if (utimes(Jim_String(argv[0]), times) != 0) {
-
            Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno));
+
    if (argc == 2) {
+
        jim_wide us;
+
        if (Jim_GetWide(interp, argv[1], &us) != JIM_OK) {
            return JIM_ERR;
        }
-
#else
-
        Jim_SetResultString(interp, "Not implemented", -1);
-
        return JIM_ERR;
-
#endif
+
        return JimSetFileTimes(interp, Jim_String(argv[0]), us);
    }
    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
        return JIM_ERR;
    }
-
    Jim_SetResultInt(interp, sb.st_mtime);
+
    Jim_SetResultInt(interp, STAT_MTIME_US(sb));
    return JIM_OK;
}
+
#endif

static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -3988,6 +4146,15 @@ static const jim_subcmd_type file_command_table[] = {
        2,

    },
+
#ifdef STAT_MTIME_US
+
    {   "mtimeus",
+
        "name ?time?",
+
        file_cmd_mtimeus,
+
        1,
+
        2,
+

+
    },
+
#endif
    {   "copy",
        "?-force? source dest",
        file_cmd_copy,
@@ -4286,83 +4453,22 @@ int Jim_execInit(Jim_Interp *interp)

#include <errno.h>
#include <signal.h>
+
#include <sys/stat.h>

-
#if defined(__MINGW32__)
-

-
    #ifndef STRICT
-
    #define STRICT
-
    #endif
-
    #define WIN32_LEAN_AND_MEAN
-
    #include <windows.h>
-
    #include <fcntl.h>
-

-
    typedef HANDLE fdtype;
-
    typedef HANDLE pidtype;
-
    #define JIM_BAD_FD INVALID_HANDLE_VALUE
-
    #define JIM_BAD_PID INVALID_HANDLE_VALUE
-
    #define JimCloseFd CloseHandle
-

-
    #define WIFEXITED(STATUS) 1
-
    #define WEXITSTATUS(STATUS) (STATUS)
-
    #define WIFSIGNALED(STATUS) 0
-
    #define WTERMSIG(STATUS) 0
-
    #define WNOHANG 1
-

-
    static fdtype JimFileno(FILE *fh);
-
    static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
-
    static fdtype JimDupFd(fdtype infd);
-
    static fdtype JimOpenForRead(const char *filename);
-
    static FILE *JimFdOpenForRead(fdtype fd);
-
    static int JimPipe(fdtype pipefd[2]);
-
    static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env,
-
        fdtype inputId, fdtype outputId, fdtype errorId);
-
    static int JimErrno(void);
-
#else
-
    #include <unistd.h>
-
    #include <fcntl.h>
-
    #include <sys/wait.h>
-
    #include <sys/stat.h>
-

-
    typedef int fdtype;
-
    typedef int pidtype;
-
    #define JimPipe pipe
-
    #define JimErrno() errno
-
    #define JIM_BAD_FD -1
-
    #define JIM_BAD_PID -1
-
    #define JimFileno fileno
-
    #define JimReadFd read
-
    #define JimCloseFd close
-
    #define JimWaitPid waitpid
-
    #define JimDupFd dup
-
    #define JimFdOpenForRead(FD) fdopen((FD), "r")
-
    #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
-

-
    #ifndef HAVE_EXECVPE
-
        #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
-
    #endif
-
#endif
+
struct WaitInfoTable;

-
static const char *JimStrError(void);
static char **JimOriginalEnviron(void);
static char **JimSaveEnv(char **env);
static void JimRestoreEnv(char **env);
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
-
    pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
-
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
+
    pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
+
static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr);
static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj);
-
static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
-
static fdtype JimOpenForWrite(const char *filename, int append);
-
static int JimRewindFd(fdtype fd);
-

-
static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
-
{
-
    Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
-
}
+
static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

-
static const char *JimStrError(void)
-
{
-
    return strerror(JimErrno());
-
}
+
#if defined(__MINGW32__)
+
static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId);
+
#endif

static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
{
@@ -4375,10 +4481,10 @@ static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
    }
}

-
static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj)
+
static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj)
{
    char buf[256];
-
    FILE *fh = JimFdOpenForRead(fd);
+
    FILE *fh = fdopen(fd, "r");
    int ret = 0;

    if (fh == NULL) {
@@ -4454,31 +4560,16 @@ static void JimFreeEnv(char **env, char **original_environ)
    }
}

-
#ifndef jim_ext_signal
-

-
const char *Jim_SignalId(int sig)
-
{
-
    static char buf[10];
-
    snprintf(buf, sizeof(buf), "%d", sig);
-
    return buf;
-
}
-

-
const char *Jim_SignalName(int sig)
-
{
-
    return Jim_SignalId(sig);
-
}
-
#endif
-

-
static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
+
static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
{
-
    Jim_Obj *errorCode;
+
    Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);

-
    if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
-
        return JIM_OK;
+
    if (pid == JIM_BAD_PID || pid == JIM_NO_PID) {
+
        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1));
+
        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
+
        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1));
    }
-
    errorCode = Jim_NewListObj(interp, NULL, 0);
-

-
    if (WIFEXITED(waitStatus)) {
+
    else if (WIFEXITED(waitStatus)) {
        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
@@ -4486,14 +4577,17 @@ static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, J
    else {
        const char *type;
        const char *action;
+
        const char *signame;

        if (WIFSIGNALED(waitStatus)) {
            type = "CHILDKILLED";
            action = "killed";
+
            signame = Jim_SignalId(WTERMSIG(waitStatus));
        }
        else {
            type = "CHILDSUSP";
            action = "suspended";
+
            signame = "none";
        }

        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
@@ -4503,10 +4597,17 @@ static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, J
        }

        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
-
        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1));
-
        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1));
+
        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1));
+
    }
+
    return errorCode;
+
}
+

+
static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
+
{
+
    if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
+
        return JIM_OK;
    }
-
    Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
+
    Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj));

    return JIM_ERR;
}
@@ -4519,10 +4620,12 @@ struct WaitInfo
    int flags;
};

+

struct WaitInfoTable {
    struct WaitInfo *info;
    int size;
    int used;
+
    int refcount;
};


@@ -4534,8 +4637,10 @@ static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData)
{
    struct WaitInfoTable *table = privData;

-
    Jim_Free(table->info);
-
    Jim_Free(table);
+
    if (--table->refcount == 0) {
+
        Jim_Free(table->info);
+
        Jim_Free(table);
+
    }
}

static struct WaitInfoTable *JimAllocWaitInfoTable(void)
@@ -4543,27 +4648,46 @@ static struct WaitInfoTable *JimAllocWaitInfoTable(void)
    struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
    table->info = NULL;
    table->size = table->used = 0;
+
    table->refcount = 1;

    return table;
}

-
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid)
{
-
    fdtype outputId;
-
    fdtype errorId;
-
    pidtype *pidPtr;
-
    int numPids, result;
-
    int child_siginfo = 1;
-
    Jim_Obj *childErrObj;
-
    Jim_Obj *errStrObj;
+
    int i;

-
    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
-
        Jim_Obj *listObj;
-
        int i;

-
        argc--;
-
        numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
-
        if (numPids < 0) {
+
    for (i = 0; i < table->used; i++) {
+
        if (pid == table->info[i].pid) {
+
            if (i != table->used - 1) {
+
                table->info[i] = table->info[table->used - 1];
+
            }
+
            table->used--;
+
            return 0;
+
        }
+
    }
+
    return -1;
+
}
+

+
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
{
+
    int outputId;
+
    int errorId;
+
    pidtype *pidPtr;
+
    int numPids, result;
+
    int child_siginfo = 1;
+
    Jim_Obj *childErrObj;
+
    Jim_Obj *errStrObj;
+
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+

+
    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
+
        Jim_Obj *listObj;
+
        int i;
+

+
        argc--;
+
        numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
+
        if (numPids < 0) {
            return JIM_ERR;
        }

@@ -4572,7 +4696,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
            Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
        }
        Jim_SetResult(interp, listObj);
-
        JimDetachPids(interp, numPids, pidPtr);
+
        JimDetachPids(table, numPids, pidPtr);
        Jim_Free(pidPtr);
        return JIM_OK;
    }
@@ -4589,7 +4713,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
    errStrObj = Jim_NewStringObj(interp, "", 0);


-
    if (outputId != JIM_BAD_FD) {
+
    if (outputId != -1) {
        if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
            result = JIM_ERR;
            Jim_SetResultErrno(interp, "error reading from output pipe");
@@ -4604,9 +4728,9 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        result = JIM_ERR;
    }

-
    if (errorId != JIM_BAD_FD) {
+
    if (errorId != -1) {
        int ret;
-
        JimRewindFd(errorId);
+
        lseek(errorId, 0, SEEK_SET);
        ret = JimAppendStreamToString(interp, errorId, errStrObj);
        if (ret < 0) {
            Jim_SetResultErrno(interp, "error reading from error pipe");
@@ -4633,6 +4757,50 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
    return result;
}

+
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
+
{
+
    if (JimWaitRemove(table, pid) == 0) {
+

+
         waitpid(pid, statusPtr, 0);
+
         return pid;
+
    }
+

+

+
    return JIM_BAD_PID;
+
}
+

+
static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr)
+
{
+
    int j;
+

+
    for (j = 0; j < numPids; j++) {
+

+
        int i;
+
        for (i = 0; i < table->used; i++) {
+
            if (pidPtr[j] == table->info[i].pid) {
+
                table->info[i].flags |= WI_DETACHED;
+
                break;
+
            }
+
        }
+
    }
+
}
+

+
static int JimGetChannelFd(Jim_Interp *interp, const char *name)
+
{
+
    Jim_Obj *objv[2];
+

+
    objv[0] = Jim_NewStringObj(interp, name, -1);
+
    objv[1] = Jim_NewStringObj(interp, "getfd", -1);
+

+
    if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) {
+
        jim_wide fd;
+
        if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) {
+
            return fd;
+
        }
+
    }
+
    return -1;
+
}
+

static void JimReapDetachedPids(struct WaitInfoTable *table)
{
    struct WaitInfo *waitPtr;
@@ -4648,7 +4816,7 @@ static void JimReapDetachedPids(struct WaitInfoTable *table)
    for (count = table->used; count > 0; waitPtr++, count--) {
        if (waitPtr->flags & WI_DETACHED) {
            int status;
-
            pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
+
            pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG);
            if (pid == waitPtr->pid) {

                table->used--;
@@ -4662,62 +4830,58 @@ static void JimReapDetachedPids(struct WaitInfoTable *table)
    }
}

-
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
+
static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-
    int i;
-

-

-
    for (i = 0; i < table->used; i++) {
-
        if (pid == table->info[i].pid) {
-

-
            JimWaitPid(pid, statusPtr, 0);
+
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+
    int nohang = 0;
+
    pidtype pid;
+
    long pidarg;
+
    int status;
+
    Jim_Obj *errCodeObj;


-
            if (i != table->used - 1) {
-
                table->info[i] = table->info[table->used - 1];
-
            }
-
            table->used--;
-
            return pid;
-
        }
+
    if (argc == 1) {
+
        JimReapDetachedPids(table);
+
        return JIM_OK;
    }

+
    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) {
+
        nohang = 1;
+
    }
+
    if (argc != nohang + 2) {
+
        Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?");
+
        return JIM_ERR;
+
    }
+
    if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) {
+
        return JIM_ERR;
+
    }

-
    return JIM_BAD_PID;
-
}
+
    pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0);

-
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
-
{
-
    int j;
-
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+
    errCodeObj = JimMakeErrorCode(interp, pid, status, NULL);

-
    for (j = 0; j < numPids; j++) {
+
    if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) {

-
        int i;
-
        for (i = 0; i < table->used; i++) {
-
            if (pidPtr[j] == table->info[i].pid) {
-
                table->info[i].flags |= WI_DETACHED;
-
                break;
-
            }
-
        }
+
        JimWaitRemove(table, pid);
    }
+
    Jim_SetResult(interp, errCodeObj);
+
    return JIM_OK;
}

-
static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name)
+
static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-
    FILE *fh;
-
    Jim_Obj *fhObj;
-

-
    fhObj = Jim_NewStringObj(interp, name, -1);
-
    Jim_IncrRefCount(fhObj);
-
    fh = Jim_AioFilehandle(interp, fhObj);
-
    Jim_DecrRefCount(interp, fhObj);
+
    if (argc != 1) {
+
        Jim_WrongNumArgs(interp, 1, argv, "");
+
        return JIM_ERR;
+
    }

-
    return fh;
+
    Jim_SetResultInt(interp, (jim_wide)getpid());
+
    return JIM_OK;
}

static int
JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
-
    fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
+
    int *inPipePtr, int *outPipePtr, int *errFilePtr)
{
    pidtype *pidPtr = NULL;         /* Points to malloc-ed array holding all
                                 * the pids of child processes. */
@@ -4754,35 +4918,36 @@ JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **
                                 * or NULL if output goes to stdout/pipe. */
    const char *error = NULL;   /* Holds name of stderr file to pipe to,
                                 * or NULL if stderr goes to stderr/pipe. */
-
    fdtype inputId = JIM_BAD_FD;
-
    fdtype outputId = JIM_BAD_FD;
-
    fdtype errorId = JIM_BAD_FD;
-
    fdtype lastOutputId = JIM_BAD_FD;
-
    fdtype pipeIds[2];
+
    int inputId = -1;
+
    int outputId = -1;
+
    int errorId = -1;
+
    int lastOutputId = -1;
+
    int pipeIds[2];
    int firstArg, lastArg;      /* Indexes of first and last arguments in
                                 * current command. */
    int lastBar;
    int i;
    pidtype pid;
    char **save_environ;
+
#ifndef __MINGW32__
+
    char **child_environ;
+
#endif
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);


    char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
    int arg_count = 0;

-
    JimReapDetachedPids(table);
-

    if (inPipePtr != NULL) {
-
        *inPipePtr = JIM_BAD_FD;
+
        *inPipePtr = -1;
    }
    if (outPipePtr != NULL) {
-
        *outPipePtr = JIM_BAD_FD;
+
        *outPipePtr = -1;
    }
    if (errFilePtr != NULL) {
-
        *errFilePtr = JIM_BAD_FD;
+
        *errFilePtr = -1;
    }
-
    pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+
    pipeIds[0] = pipeIds[1] = -1;

    cmdCount = 1;
    lastBar = -1;
@@ -4881,100 +5046,103 @@ badargs:

    if (input != NULL) {
        if (inputFile == FILE_TEXT) {
-
            inputId = JimCreateTemp(interp, input, input_len);
-
            if (inputId == JIM_BAD_FD) {
+
            inputId = Jim_MakeTempFile(interp, NULL, 1);
+
            if (inputId == -1) {
+
                goto error;
+
            }
+
            if (write(inputId, input, input_len) != input_len) {
+
                Jim_SetResultErrno(interp, "couldn't write temp file");
+
                close(inputId);
                goto error;
            }
+
            lseek(inputId, 0L, SEEK_SET);
        }
        else if (inputFile == FILE_HANDLE) {
+
            int fd = JimGetChannelFd(interp, input);

-
            FILE *fh = JimGetAioFilehandle(interp, input);
-

-
            if (fh == NULL) {
+
            if (fd < 0) {
                goto error;
            }
-
            inputId = JimDupFd(JimFileno(fh));
+
            inputId = dup(fd);
        }
        else {
-
            inputId = JimOpenForRead(input);
-
            if (inputId == JIM_BAD_FD) {
-
                Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
+
            inputId = Jim_OpenForRead(input);
+
            if (inputId == -1) {
+
                Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno()));
                goto error;
            }
        }
    }
    else if (inPipePtr != NULL) {
-
        if (JimPipe(pipeIds) != 0) {
+
        if (pipe(pipeIds) != 0) {
            Jim_SetResultErrno(interp, "couldn't create input pipe for command");
            goto error;
        }
        inputId = pipeIds[0];
        *inPipePtr = pipeIds[1];
-
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+
        pipeIds[0] = pipeIds[1] = -1;
    }

    if (output != NULL) {
        if (outputFile == FILE_HANDLE) {
-
            FILE *fh = JimGetAioFilehandle(interp, output);
-
            if (fh == NULL) {
+
            int fd = JimGetChannelFd(interp, output);
+
            if (fd < 0) {
                goto error;
            }
-
            fflush(fh);
-
            lastOutputId = JimDupFd(JimFileno(fh));
+
            lastOutputId = dup(fd);
        }
        else {
-
            lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
-
            if (lastOutputId == JIM_BAD_FD) {
-
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
+
            lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND);
+
            if (lastOutputId == -1) {
+
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno()));
                goto error;
            }
        }
    }
    else if (outPipePtr != NULL) {
-
        if (JimPipe(pipeIds) != 0) {
+
        if (pipe(pipeIds) != 0) {
            Jim_SetResultErrno(interp, "couldn't create output pipe");
            goto error;
        }
        lastOutputId = pipeIds[1];
        *outPipePtr = pipeIds[0];
-
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+
        pipeIds[0] = pipeIds[1] = -1;
    }

    if (error != NULL) {
        if (errorFile == FILE_HANDLE) {
            if (strcmp(error, "1") == 0) {

-
                if (lastOutputId != JIM_BAD_FD) {
-
                    errorId = JimDupFd(lastOutputId);
+
                if (lastOutputId != -1) {
+
                    errorId = dup(lastOutputId);
                }
                else {

                    error = "stdout";
                }
            }
-
            if (errorId == JIM_BAD_FD) {
-
                FILE *fh = JimGetAioFilehandle(interp, error);
-
                if (fh == NULL) {
+
            if (errorId == -1) {
+
                int fd = JimGetChannelFd(interp, error);
+
                if (fd < 0) {
                    goto error;
                }
-
                fflush(fh);
-
                errorId = JimDupFd(JimFileno(fh));
+
                errorId = dup(fd);
            }
        }
        else {
-
            errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
-
            if (errorId == JIM_BAD_FD) {
-
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
+
            errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND);
+
            if (errorId == -1) {
+
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno()));
                goto error;
            }
        }
    }
    else if (errFilePtr != NULL) {
-
        errorId = JimCreateTemp(interp, NULL, 0);
-
        if (errorId == JIM_BAD_FD) {
+
        errorId = Jim_MakeTempFile(interp, NULL, 1);
+
        if (errorId == -1) {
            goto error;
        }
-
        *errFilePtr = JimDupFd(errorId);
+
        *errFilePtr = dup(errorId);
    }


@@ -4984,23 +5152,31 @@ badargs:
    }
    for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
        int pipe_dup_err = 0;
-
        fdtype origErrorId = errorId;
+
        int origErrorId = errorId;

        for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
-
            if (arg_array[lastArg][0] == '|') {
-
                if (arg_array[lastArg][1] == '&') {
-
                    pipe_dup_err = 1;
-
                }
+
            if (strcmp(arg_array[lastArg], "|") == 0) {
                break;
            }
+
            if (strcmp(arg_array[lastArg], "|&") == 0) {
+
                pipe_dup_err = 1;
+
                break;
+
            }
+
        }
+

+
        if (lastArg == firstArg) {
+
            Jim_SetResultString(interp, "missing command to exec", -1);
+
            goto error;
        }

+

        arg_array[lastArg] = NULL;
        if (lastArg == arg_count) {
            outputId = lastOutputId;
+
            lastOutputId = -1;
        }
        else {
-
            if (JimPipe(pipeIds) != 0) {
+
            if (pipe(pipeIds) != 0) {
                Jim_SetResultErrno(interp, "couldn't create pipe");
                goto error;
            }
@@ -5021,6 +5197,9 @@ badargs:
            goto error;
        }
#else
+
        i = strlen(arg_array[firstArg]);
+

+
        child_environ = Jim_GetEnviron();
        pid = vfork();
        if (pid < 0) {
            Jim_SetResultErrno(interp, "couldn't fork child process");
@@ -5029,21 +5208,44 @@ badargs:
        if (pid == 0) {


-
            if (inputId != -1) dup2(inputId, 0);
-
            if (outputId != -1) dup2(outputId, 1);
-
            if (errorId != -1) dup2(errorId, 2);
+
            if (inputId != -1) {
+
                dup2(inputId, fileno(stdin));
+
                close(inputId);
+
            }
+
            if (outputId != -1) {
+
                dup2(outputId, fileno(stdout));
+
                if (outputId != errorId) {
+
                    close(outputId);
+
                }
+
            }
+
            if (errorId != -1) {
+
                dup2(errorId, fileno(stderr));
+
                close(errorId);
+
            }

-
            for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
-
                close(i);
+
            if (outPipePtr) {
+
                close(*outPipePtr);
+
            }
+
            if (errFilePtr) {
+
                close(*errFilePtr);
+
            }
+
            if (pipeIds[0] != -1) {
+
                close(pipeIds[0]);
+
            }
+
            if (lastOutputId != -1) {
+
                close(lastOutputId);
            }


            (void)signal(SIGPIPE, SIG_DFL);

-
            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
+
            execvpe(arg_array[firstArg], &arg_array[firstArg], child_environ);

+
            if (write(fileno(stderr), "couldn't exec \"", 15) &&
+
                write(fileno(stderr), arg_array[firstArg], i) &&
+
                write(fileno(stderr), "\"\n", 2)) {

-
            fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
+
            }
#ifdef JIM_MAINTAINER
            {

@@ -5072,28 +5274,27 @@ badargs:
        errorId = origErrorId;


-
        if (inputId != JIM_BAD_FD) {
-
            JimCloseFd(inputId);
+
        if (inputId != -1) {
+
            close(inputId);
        }
-
        if (outputId != JIM_BAD_FD) {
-
            JimCloseFd(outputId);
-
            outputId = JIM_BAD_FD;
+
        if (outputId != -1) {
+
            close(outputId);
        }
        inputId = pipeIds[0];
-
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+
        pipeIds[0] = pipeIds[1] = -1;
    }
    *pidArrayPtr = pidPtr;


  cleanup:
-
    if (inputId != JIM_BAD_FD) {
-
        JimCloseFd(inputId);
+
    if (inputId != -1) {
+
        close(inputId);
    }
-
    if (lastOutputId != JIM_BAD_FD) {
-
        JimCloseFd(lastOutputId);
+
    if (lastOutputId != -1) {
+
        close(lastOutputId);
    }
-
    if (errorId != JIM_BAD_FD) {
-
        JimCloseFd(errorId);
+
    if (errorId != -1) {
+
        close(errorId);
    }
    Jim_Free(arg_array);

@@ -5103,28 +5304,28 @@ badargs:


  error:
-
    if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
-
        JimCloseFd(*inPipePtr);
-
        *inPipePtr = JIM_BAD_FD;
+
    if ((inPipePtr != NULL) && (*inPipePtr != -1)) {
+
        close(*inPipePtr);
+
        *inPipePtr = -1;
    }
-
    if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
-
        JimCloseFd(*outPipePtr);
-
        *outPipePtr = JIM_BAD_FD;
+
    if ((outPipePtr != NULL) && (*outPipePtr != -1)) {
+
        close(*outPipePtr);
+
        *outPipePtr = -1;
    }
-
    if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
-
        JimCloseFd(*errFilePtr);
-
        *errFilePtr = JIM_BAD_FD;
+
    if ((errFilePtr != NULL) && (*errFilePtr != -1)) {
+
        close(*errFilePtr);
+
        *errFilePtr = -1;
    }
-
    if (pipeIds[0] != JIM_BAD_FD) {
-
        JimCloseFd(pipeIds[0]);
+
    if (pipeIds[0] != -1) {
+
        close(pipeIds[0]);
    }
-
    if (pipeIds[1] != JIM_BAD_FD) {
-
        JimCloseFd(pipeIds[1]);
+
    if (pipeIds[1] != -1) {
+
        close(pipeIds[1]);
    }
    if (pidPtr != NULL) {
        for (i = 0; i < numPids; i++) {
            if (pidPtr[i] != JIM_BAD_PID) {
-
                JimDetachPids(interp, 1, &pidPtr[i]);
+
                JimDetachPids(table, 1, &pidPtr[i]);
            }
        }
        Jim_Free(pidPtr);
@@ -5156,6 +5357,7 @@ static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr,

int Jim_execInit(Jim_Interp *interp)
{
+
    struct WaitInfoTable *waitinfo;
    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
        return JIM_ERR;

@@ -5163,227 +5365,18 @@ int Jim_execInit(Jim_Interp *interp)
    (void)signal(SIGPIPE, SIG_IGN);
#endif

-
    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
+
    waitinfo = JimAllocWaitInfoTable();
+
    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable);
+
    waitinfo->refcount++;
+
    Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable);
+
    Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0);
+

    return JIM_OK;
}

#if defined(__MINGW32__)


-
static SECURITY_ATTRIBUTES *JimStdSecAttrs(void)
-
{
-
    static SECURITY_ATTRIBUTES secAtts;
-

-
    secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
-
    secAtts.lpSecurityDescriptor = NULL;
-
    secAtts.bInheritHandle = TRUE;
-
    return &secAtts;
-
}
-

-
static int JimErrno(void)
-
{
-
    switch (GetLastError()) {
-
    case ERROR_FILE_NOT_FOUND: return ENOENT;
-
    case ERROR_PATH_NOT_FOUND: return ENOENT;
-
    case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
-
    case ERROR_ACCESS_DENIED: return EACCES;
-
    case ERROR_INVALID_HANDLE: return EBADF;
-
    case ERROR_BAD_ENVIRONMENT: return E2BIG;
-
    case ERROR_BAD_FORMAT: return ENOEXEC;
-
    case ERROR_INVALID_ACCESS: return EACCES;
-
    case ERROR_INVALID_DRIVE: return ENOENT;
-
    case ERROR_CURRENT_DIRECTORY: return EACCES;
-
    case ERROR_NOT_SAME_DEVICE: return EXDEV;
-
    case ERROR_NO_MORE_FILES: return ENOENT;
-
    case ERROR_WRITE_PROTECT: return EROFS;
-
    case ERROR_BAD_UNIT: return ENXIO;
-
    case ERROR_NOT_READY: return EBUSY;
-
    case ERROR_BAD_COMMAND: return EIO;
-
    case ERROR_CRC: return EIO;
-
    case ERROR_BAD_LENGTH: return EIO;
-
    case ERROR_SEEK: return EIO;
-
    case ERROR_WRITE_FAULT: return EIO;
-
    case ERROR_READ_FAULT: return EIO;
-
    case ERROR_GEN_FAILURE: return EIO;
-
    case ERROR_SHARING_VIOLATION: return EACCES;
-
    case ERROR_LOCK_VIOLATION: return EACCES;
-
    case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
-
    case ERROR_HANDLE_DISK_FULL: return ENOSPC;
-
    case ERROR_NOT_SUPPORTED: return ENODEV;
-
    case ERROR_REM_NOT_LIST: return EBUSY;
-
    case ERROR_DUP_NAME: return EEXIST;
-
    case ERROR_BAD_NETPATH: return ENOENT;
-
    case ERROR_NETWORK_BUSY: return EBUSY;
-
    case ERROR_DEV_NOT_EXIST: return ENODEV;
-
    case ERROR_TOO_MANY_CMDS: return EAGAIN;
-
    case ERROR_ADAP_HDW_ERR: return EIO;
-
    case ERROR_BAD_NET_RESP: return EIO;
-
    case ERROR_UNEXP_NET_ERR: return EIO;
-
    case ERROR_NETNAME_DELETED: return ENOENT;
-
    case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
-
    case ERROR_BAD_DEV_TYPE: return ENODEV;
-
    case ERROR_BAD_NET_NAME: return ENOENT;
-
    case ERROR_TOO_MANY_NAMES: return ENFILE;
-
    case ERROR_TOO_MANY_SESS: return EIO;
-
    case ERROR_SHARING_PAUSED: return EAGAIN;
-
    case ERROR_REDIR_PAUSED: return EAGAIN;
-
    case ERROR_FILE_EXISTS: return EEXIST;
-
    case ERROR_CANNOT_MAKE: return ENOSPC;
-
    case ERROR_OUT_OF_STRUCTURES: return ENFILE;
-
    case ERROR_ALREADY_ASSIGNED: return EEXIST;
-
    case ERROR_INVALID_PASSWORD: return EPERM;
-
    case ERROR_NET_WRITE_FAULT: return EIO;
-
    case ERROR_NO_PROC_SLOTS: return EAGAIN;
-
    case ERROR_DISK_CHANGE: return EXDEV;
-
    case ERROR_BROKEN_PIPE: return EPIPE;
-
    case ERROR_OPEN_FAILED: return ENOENT;
-
    case ERROR_DISK_FULL: return ENOSPC;
-
    case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
-
    case ERROR_INVALID_TARGET_HANDLE: return EBADF;
-
    case ERROR_INVALID_NAME: return ENOENT;
-
    case ERROR_PROC_NOT_FOUND: return ESRCH;
-
    case ERROR_WAIT_NO_CHILDREN: return ECHILD;
-
    case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
-
    case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
-
    case ERROR_SEEK_ON_DEVICE: return ESPIPE;
-
    case ERROR_BUSY_DRIVE: return EAGAIN;
-
    case ERROR_DIR_NOT_EMPTY: return EEXIST;
-
    case ERROR_NOT_LOCKED: return EACCES;
-
    case ERROR_BAD_PATHNAME: return ENOENT;
-
    case ERROR_LOCK_FAILED: return EACCES;
-
    case ERROR_ALREADY_EXISTS: return EEXIST;
-
    case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
-
    case ERROR_BAD_PIPE: return EPIPE;
-
    case ERROR_PIPE_BUSY: return EAGAIN;
-
    case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
-
    case ERROR_DIRECTORY: return ENOTDIR;
-
    }
-
    return EINVAL;
-
}
-

-
static int JimPipe(fdtype pipefd[2])
-
{
-
    if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) {
-
        return 0;
-
    }
-
    return -1;
-
}
-

-
static fdtype JimDupFd(fdtype infd)
-
{
-
    fdtype dupfd;
-
    pidtype pid = GetCurrentProcess();
-

-
    if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
-
        return dupfd;
-
    }
-
    return JIM_BAD_FD;
-
}
-

-
static int JimRewindFd(fdtype fd)
-
{
-
    return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0;
-
}
-

-
#if 0
-
static int JimReadFd(fdtype fd, char *buffer, size_t len)
-
{
-
    DWORD num;
-

-
    if (ReadFile(fd, buffer, len, &num, NULL)) {
-
        return num;
-
    }
-
    if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) {
-
        return 0;
-
    }
-
    return -1;
-
}
-
#endif
-

-
static FILE *JimFdOpenForRead(fdtype fd)
-
{
-
    return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r");
-
}
-

-
static fdtype JimFileno(FILE *fh)
-
{
-
    return (fdtype)_get_osfhandle(_fileno(fh));
-
}
-

-
static fdtype JimOpenForRead(const char *filename)
-
{
-
    return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
-
        JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
}
-

-
static fdtype JimOpenForWrite(const char *filename, int append)
-
{
-
    fdtype fd = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
-
        JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
-
    if (append && fd != JIM_BAD_FD) {
-
        SetFilePointer(fd, 0, NULL, FILE_END);
-
    }
-
    return fd;
-
}
-

-
static FILE *JimFdOpenForWrite(fdtype fd)
-
{
-
    return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
-
}
-

-
static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
-
{
-
    DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
-
    if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
-

-
        return JIM_BAD_PID;
-
    }
-
    GetExitCodeProcess(pid, &ret);
-
    *status = ret;
-
    CloseHandle(pid);
-
    return pid;
-
}
-

-
static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
-
{
-
    char name[MAX_PATH];
-
    HANDLE handle;
-

-
    if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
-
        return JIM_BAD_FD;
-
    }
-

-
    handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(),
-
            CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
-
            NULL);
-

-
    if (handle == INVALID_HANDLE_VALUE) {
-
        goto error;
-
    }
-

-
    if (contents != NULL) {
-

-
        FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
-
        if (fh == NULL) {
-
            goto error;
-
        }
-

-
        if (fwrite(contents, len, 1, fh) != 1) {
-
            fclose(fh);
-
            goto error;
-
        }
-
        fseek(fh, 0, SEEK_SET);
-
        fclose(fh);
-
    }
-
    return handle;
-

-
  error:
-
    Jim_SetResultErrno(interp, "failed to create temp file");
-
    CloseHandle(handle);
-
    DeleteFile(name);
-
    return JIM_BAD_FD;
-
}
-

static int
JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
{
@@ -5493,11 +5486,11 @@ JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
}

static pidtype
-
JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, fdtype inputId, fdtype outputId, fdtype errorId)
+
JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId)
{
    STARTUPINFO startInfo;
    PROCESS_INFORMATION procInfo;
-
    HANDLE hProcess, h;
+
    HANDLE hProcess;
    char execPath[MAX_PATH];
    pidtype pid = JIM_BAD_PID;
    Jim_Obj *cmdLineObj;
@@ -5519,38 +5512,31 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, fdtype inputId,
    startInfo.hStdOutput= INVALID_HANDLE_VALUE;
    startInfo.hStdError = INVALID_HANDLE_VALUE;

-
    if (inputId == JIM_BAD_FD) {
-
        if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
-
            CloseHandle(h);
-
        }
-
    } else {
-
        DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
-
                0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (inputId == -1) {
+
        inputId = _fileno(stdin);
    }
-
    if (startInfo.hStdInput == JIM_BAD_FD) {
+
    DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput,
+
            0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {
        goto end;
    }

-
    if (outputId == JIM_BAD_FD) {
-
        startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
-
                JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-
    } else {
-
        DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
-
                0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (outputId == -1) {
+
        outputId = _fileno(stdout);
    }
-
    if (startInfo.hStdOutput == JIM_BAD_FD) {
+
    DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput,
+
            0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) {
        goto end;
    }

-
    if (errorId == JIM_BAD_FD) {

-
        startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
-
                JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
    } else {
-
        DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
-
                0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (errorId == -1) {
+
        errorId = _fileno(stderr);
    }
-
    if (startInfo.hStdError == JIM_BAD_FD) {
+
    DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError,
+
            0, TRUE, DUPLICATE_SAME_ACCESS);
+
    if (startInfo.hStdError == INVALID_HANDLE_VALUE) {
        goto end;
    }

@@ -5578,46 +5564,19 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, fdtype inputId,

    end:
    Jim_FreeNewObj(interp, cmdLineObj);
-
    if (startInfo.hStdInput != JIM_BAD_FD) {
+
    if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
        CloseHandle(startInfo.hStdInput);
    }
-
    if (startInfo.hStdOutput != JIM_BAD_FD) {
+
    if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) {
        CloseHandle(startInfo.hStdOutput);
    }
-
    if (startInfo.hStdError != JIM_BAD_FD) {
+
    if (startInfo.hStdError != INVALID_HANDLE_VALUE) {
        CloseHandle(startInfo.hStdError);
    }
    return pid;
}
-
#else
-

-
static int JimOpenForWrite(const char *filename, int append)
-
{
-
    return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
-
}

-
static int JimRewindFd(int fd)
-
{
-
    return lseek(fd, 0L, SEEK_SET);
-
}
-

-
static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
-
{
-
    int fd = Jim_MakeTempFile(interp, NULL);
-

-
    if (fd != JIM_BAD_FD) {
-
        unlink(Jim_String(Jim_GetResult(interp)));
-
        if (contents) {
-
            if (write(fd, contents, len) != len) {
-
                Jim_SetResultErrno(interp, "couldn't write temp file");
-
                close(fd);
-
                return -1;
-
            }
-
            lseek(fd, 0L, SEEK_SET);
-
        }
-
    }
-
    return fd;
-
}
+
#else

static char **JimOriginalEnviron(void)
{
@@ -5640,9 +5599,17 @@ static void JimRestoreEnv(char **env)
#endif


+

+
#ifdef STRPTIME_NEEDS_XOPEN_SOURCE
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif
+
#endif
+

+

+
#ifndef _GNU_SOURCE
+
#define _GNU_SOURCE
+
#endif

#include <stdlib.h>
#include <string.h>
@@ -5654,30 +5621,60 @@ static void JimRestoreEnv(char **env)
#include <sys/time.h>
#endif

+
struct clock_options {
+
    int gmt;
+
    const char *format;
+
};
+

+
static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts)
+
{
+
    static const char * const options[] = { "-gmt", "-format", NULL };
+
    enum { OPT_GMT, OPT_FORMAT, };
+
    int i;
+

+
    for (i = 0; i < argc; i += 2) {
+
        int option;
+
        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+
            return JIM_ERR;
+
        }
+
        switch (option) {
+
            case OPT_GMT:
+
                if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) {
+
                    return JIM_ERR;
+
                }
+
                break;
+
            case OPT_FORMAT:
+
                opts->format = Jim_String(argv[i + 1]);
+
                break;
+
        }
+
    }
+
    return JIM_OK;
+
}
+

static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{

    char buf[100];
    time_t t;
-
    long seconds;
-

-
    const char *format = "%a %b %d %H:%M:%S %Z %Y";
+
    jim_wide seconds;
+
    struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" };
+
    struct tm *tm;

-
    if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
-
        return -1;
+
    if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) {
+
        return JIM_ERR;
    }
-

-
    if (argc == 3) {
-
        format = Jim_String(argv[2]);
+
    if (argc % 2 == 0) {
+
        return -1;
    }
-

-
    if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
+
    if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
        return JIM_ERR;
    }
+

    t = seconds;
+
    tm = options.gmt ? gmtime(&t) : localtime(&t);

-
    if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
-
        Jim_SetResultString(interp, "format string too long", -1);
+
    if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) {
+
        Jim_SetResultString(interp, "format string too long or invalid time", -1);
        return JIM_ERR;
    }

@@ -5687,27 +5684,49 @@ static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}

#ifdef HAVE_STRPTIME
+
static time_t jim_timegm(const struct tm *tm)
+
{
+
    int m = tm->tm_mon + 1;
+
    int y = 1900 + tm->tm_year - (m <= 2);
+
    int era = (y >= 0 ? y : y - 399) / 400;
+
    unsigned yoe = (unsigned)(y - era * 400);
+
    unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + tm->tm_mday - 1;
+
    unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
+
    long days = (era * 146097 + (int)doe - 719468);
+
    int secs = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
+

+
    return days * 24 * 60 * 60 + secs;
+
}
+

static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    char *pt;
    struct tm tm;
-
    time_t now = time(0);
+
    time_t now = time(NULL);
+

+
    struct clock_options options = { 0, NULL };

-
    if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
+
    if (argc % 2 == 0) {
        return -1;
    }

+
    if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) {
+
        return JIM_ERR;
+
    }
+
    if (options.format == NULL) {
+
        return -1;
+
    }

    localtime_r(&now, &tm);

-
    pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
+
    pt = strptime(Jim_String(argv[0]), options.format, &tm);
    if (pt == 0 || *pt != 0) {
        Jim_SetResultString(interp, "Failed to parse time according to format", -1);
        return JIM_ERR;
    }


-
    Jim_SetResultInt(interp, mktime(&tm));
+
    Jim_SetResultInt(interp, options.gmt ? jim_timegm(&tm) : mktime(&tm));

    return JIM_OK;
}
@@ -5743,13 +5762,6 @@ static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}

static const jim_subcmd_type clock_command_table[] = {
-
    {   "seconds",
-
        NULL,
-
        clock_cmd_seconds,
-
        0,
-
        0,
-

-
    },
    {   "clicks",
        NULL,
        clock_cmd_micros,
@@ -5757,6 +5769,13 @@ static const jim_subcmd_type clock_command_table[] = {
        0,

    },
+
    {   "format",
+
        "seconds ?-format string? ?-gmt boolean?",
+
        clock_cmd_format,
+
        1,
+
        5,
+

+
    },
    {   "microseconds",
        NULL,
        clock_cmd_micros,
@@ -5771,22 +5790,22 @@ static const jim_subcmd_type clock_command_table[] = {
        0,

    },
-
    {   "format",
-
        "seconds ?-format format?",
-
        clock_cmd_format,
-
        1,
-
        3,
-

-
    },
#ifdef HAVE_STRPTIME
    {   "scan",
-
        "str -format format",
+
        "str -format format ?-gmt boolean?",
        clock_cmd_scan,
        3,
-
        3,
+
        5,

    },
#endif
+
    {   "seconds",
+
        NULL,
+
        clock_cmd_seconds,
+
        0,
+
        0,
+

+
    },
    { NULL }
};

@@ -6200,7 +6219,7 @@ first:
            pattern += utf8_tounicode_case(pattern, &start, nocase);
            if (pattern[0] == '-' && pattern[1]) {

-
                pattern += utf8_tounicode(pattern, &pchar);
+
                pattern++;
                pattern += utf8_tounicode_case(pattern, &end, nocase);


@@ -7795,23 +7814,19 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc

    start = pc->tstart;
    end = pc->tend;
-
    if (start > end) {
+
    len = (end - start) + 1;
+
    if (len < 0) {
        len = 0;
-
        token = Jim_Alloc(1);
-
        token[0] = '\0';
    }
-
    else {
-
        len = (end - start) + 1;
-
        token = Jim_Alloc(len + 1);
-
        if (pc->tt != JIM_TT_ESC) {
+
    token = Jim_Alloc(len + 1);
+
    if (pc->tt != JIM_TT_ESC) {

-
            memcpy(token, start, len);
-
            token[len] = '\0';
-
        }
-
        else {
+
        memcpy(token, start, len);
+
        token[len] = '\0';
+
    }
+
    else {

-
            len = JimEscape(token, start, len);
-
        }
+
        len = JimEscape(token, start, len);
    }

    return Jim_NewStringObjNoAlloc(interp, token, len);
@@ -8010,7 +8025,6 @@ Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
        dupPtr->bytes = NULL;
    }
    else if (objPtr->length == 0) {
-

        dupPtr->bytes = JimEmptyStringRep;
        dupPtr->length = 0;
        dupPtr->typePtr = NULL;
@@ -8054,8 +8068,7 @@ int Jim_Length(Jim_Obj *objPtr)
{
    if (objPtr->bytes == NULL) {

-
        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
-
        objPtr->typePtr->updateStringProc(objPtr);
+
        Jim_GetString(objPtr, NULL);
    }
    return objPtr->length;
}
@@ -8065,9 +8078,7 @@ const char *Jim_String(Jim_Obj *objPtr)
{
    if (objPtr->bytes == NULL) {

-
        JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value."));
-
        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
-
        objPtr->typePtr->updateStringProc(objPtr);
+
        Jim_GetString(objPtr, NULL);
    }
    return objPtr->bytes;
}
@@ -8089,19 +8100,30 @@ static const Jim_ObjType dictSubstObjType = {
    JIM_TYPE_NONE,
};

-
static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
-
{
-
    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
-
}
+
static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+
static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);

static const Jim_ObjType interpolatedObjType = {
    "interpolated",
    FreeInterpolatedInternalRep,
-
    NULL,
+
    DupInterpolatedInternalRep,
    NULL,
    JIM_TYPE_NONE,
};

+
static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+
{
+
    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
+
}
+

+
static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+
{
+

+
    dupPtr->internalRep = srcPtr->internalRep;
+

+
    Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
+
}
+

static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);

@@ -8168,9 +8190,7 @@ Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
        objPtr->bytes = JimEmptyStringRep;
    }
    else {
-
        objPtr->bytes = Jim_Alloc(len + 1);
-
        memcpy(objPtr->bytes, s, len);
-
        objPtr->bytes[len] = '\0';
+
        objPtr->bytes = Jim_StrDupLen(s, len);
    }
    objPtr->length = len;

@@ -8458,8 +8478,6 @@ static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
    int len;
    const char *str;

-
    SetStringFromAny(interp, strObjPtr);
-

    str = Jim_GetString(strObjPtr, &len);

#ifdef JIM_UTF8
@@ -8476,10 +8494,6 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
    const char *str;
    int len;

-
    if (strObjPtr->typePtr != &stringObjType) {
-
        SetStringFromAny(interp, strObjPtr);
-
    }
-

    str = Jim_GetString(strObjPtr, &len);

#ifdef JIM_UTF8
@@ -8498,9 +8512,7 @@ static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr)
    const char *str;

    str = Jim_GetString(strObjPtr, &len);
-
    if (len == 0) {
-
        return strObjPtr;
-
    }
+

#ifdef JIM_UTF8
    len *= 2;
#endif
@@ -8750,9 +8762,7 @@ int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *
        return 1;
    }
    else {
-
        const char *objStr = Jim_String(objPtr);
-

-
        if (strcmp(str, objStr) != 0)
+
        if (strcmp(str, Jim_String(objPtr)) != 0)
            return 0;

        if (objPtr->typePtr != &comparedStringObjType) {
@@ -8948,7 +8958,7 @@ static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len
    t->line = line;
}

-
static int JimCountWordTokens(ParseToken *t)
+
static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t)
{
    int expand = 1;
    int count = 0;
@@ -8960,6 +8970,13 @@ static int JimCountWordTokens(ParseToken *t)
            expand = -1;
            t++;
        }
+
        else {
+
            if (script->missing == ' ') {
+

+
                script->missing = '}';
+
                script->linenr = t[1].line;
+
            }
+
        }
    }


@@ -9031,7 +9048,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
            i++;
        }

-
        wordtokens = JimCountWordTokens(tokenlist->list + i);
+
        wordtokens = JimCountWordTokens(script, tokenlist->list + i);

        if (wordtokens == 0) {

@@ -9104,7 +9121,7 @@ int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateChar
    if (stateCharPtr) {
        *stateCharPtr = script->missing;
    }
-
    return (script->missing == ' ');
+
    return script->missing == ' ' || script->missing == '}';
}

static int JimParseCheckMissing(Jim_Interp *interp, int ch)
@@ -9122,6 +9139,9 @@ static int JimParseCheckMissing(Jim_Interp *interp, int ch)
        case '{':
            msg = "missing close-brace";
            break;
+
        case '}':
+
            msg = "extra characters after close-brace";
+
            break;
        case '"':
        default:
            msg = "missing quote";
@@ -9262,7 +9282,6 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
    }
}

-

static void JimVariablesHTValDestructor(void *interp, void *val)
{
    Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
@@ -9916,15 +9935,12 @@ int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objP

int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val)
{
-
    Jim_Obj *nameObjPtr, *valObjPtr;
+
    Jim_Obj *valObjPtr;
    int result;

-
    nameObjPtr = Jim_NewStringObj(interp, name, -1);
    valObjPtr = Jim_NewStringObj(interp, val, -1);
-
    Jim_IncrRefCount(nameObjPtr);
    Jim_IncrRefCount(valObjPtr);
-
    result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
-
    Jim_DecrRefCount(interp, nameObjPtr);
+
    result = Jim_SetVariableStr(interp, name, valObjPtr);
    Jim_DecrRefCount(interp, valObjPtr);
    return result;
}
@@ -10237,14 +10253,13 @@ void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
}

-
void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
-
    JIM_NOTUSED(interp);

-
    dupPtr->internalRep.dictSubstValue.varNameObjPtr =
-
        srcPtr->internalRep.dictSubstValue.varNameObjPtr;
-
    dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr;
-
    dupPtr->typePtr = &dictSubstObjType;
+
    dupPtr->internalRep = srcPtr->internalRep;
+

+
    Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr);
+
    Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr);
}


@@ -10296,12 +10311,8 @@ static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)

static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
{
-
    Jim_Obj *resultObjPtr;
-

-
    if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
-

-
        resultObjPtr->refCount--;
-
        return resultObjPtr;
+
    if (Jim_EvalExpression(interp, objPtr) == JIM_OK) {
+
        return Jim_GetResult(interp);
    }
    return NULL;
}
@@ -10382,6 +10393,52 @@ static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
    return JIM_OK;
}

+
static int JimInvokeDefer(Jim_Interp *interp, int retcode)
+
{
+
    Jim_Obj *objPtr;
+

+

+
    if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) {
+
        return retcode;
+
    }
+

+
    objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE);
+

+
    if (objPtr) {
+
        int ret = JIM_OK;
+
        int i;
+
        int listLen = Jim_ListLength(interp, objPtr);
+
        Jim_Obj *resultObjPtr;
+

+
        Jim_IncrRefCount(objPtr);
+

+
        resultObjPtr = Jim_GetResult(interp);
+
        Jim_IncrRefCount(resultObjPtr);
+
        Jim_SetEmptyResult(interp);
+

+

+
        for (i = listLen; i > 0; i--) {
+

+
            Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1);
+
            ret = Jim_EvalObj(interp, scriptObjPtr);
+
            if (ret != JIM_OK) {
+
                break;
+
            }
+
        }
+

+
        if (ret == JIM_OK || retcode == JIM_ERR) {
+

+
            Jim_SetResult(interp, resultObjPtr);
+
        }
+
        else {
+
            retcode = ret;
+
        }
+

+
        Jim_DecrRefCount(interp, resultObjPtr);
+
        Jim_DecrRefCount(interp, objPtr);
+
    }
+
    return retcode;
+
}

#define JIM_FCF_FULL 0
#define JIM_FCF_REUSE 1
@@ -10495,6 +10552,8 @@ void Jim_FreeInterp(Jim_Interp *i)


    for (cf = i->framePtr; cf; cf = cfx) {
+

+
        JimInvokeDefer(i, JIM_OK);
        cfx = cf->parent;
        JimFreeCallFrame(i, cf, JIM_FCF_FULL);
    }
@@ -10525,6 +10584,7 @@ void Jim_FreeInterp(Jim_Interp *i)
        printf("Objects still in the free list:\n");
        while (objPtr) {
            const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
+
            Jim_String(objPtr);

            if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
                printf("%p (%d) %-10s: '%.20s...'\n",
@@ -10945,8 +11005,6 @@ static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
    jim_wide wideValue;
    const char *str;

-
    str = Jim_String(objPtr);
-

#ifdef HAVE_LONG_LONG

#define MIN_INT_IN_DOUBLE -(1LL << 53)
@@ -10960,8 +11018,9 @@ static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
        objPtr->typePtr = &coercedDoubleObjType;
        return JIM_OK;
    }
-
    else
#endif
+
    str = Jim_String(objPtr);
+

    if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {

        Jim_FreeIntRep(interp, objPtr);
@@ -11554,7 +11613,11 @@ static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs,
        ele[dst] = ele[src];
    }

-
    ele[++dst] = ele[src];
+

+
    dst++;
+
    if (dst < listObjPtr->internalRep.listValue.len) {
+
        ele[dst] = ele[src];
+
    }


    listObjPtr->internalRep.listValue.len = dst;
@@ -12331,7 +12394,7 @@ static const char * const jimReturnCodes[] = {
    NULL
};

-
#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
+
#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1)

static const Jim_ObjType returnCodeObjType = {
    "return-code",
@@ -12384,12 +12447,11 @@ static int JimParseExprIrrational(struct JimParserCtx *pc);
static int JimParseExprBoolean(struct JimParserCtx *pc);


-

-

enum
{


+

    JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
    JIM_EXPROP_DIV,
    JIM_EXPROP_MOD,
@@ -12408,28 +12470,10 @@ enum
    JIM_EXPROP_BITAND,
    JIM_EXPROP_BITXOR,
    JIM_EXPROP_BITOR,
-

-

    JIM_EXPROP_LOGICAND,
-
    JIM_EXPROP_LOGICAND_LEFT,
-
    JIM_EXPROP_LOGICAND_RIGHT,
-

-

    JIM_EXPROP_LOGICOR,
-
    JIM_EXPROP_LOGICOR_LEFT,
-
    JIM_EXPROP_LOGICOR_RIGHT,
-

-

-

    JIM_EXPROP_TERNARY,
-
    JIM_EXPROP_TERNARY_LEFT,
-
    JIM_EXPROP_TERNARY_RIGHT,
-

-

    JIM_EXPROP_COLON,
-
    JIM_EXPROP_COLON_LEFT,
-
    JIM_EXPROP_COLON_RIGHT,
-

    JIM_EXPROP_POW,


@@ -12445,8 +12489,7 @@ enum
    JIM_EXPROP_UNARYPLUS,


-
    JIM_EXPROP_FUNC_FIRST,
-
    JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
+
    JIM_EXPROP_FUNC_INT,
    JIM_EXPROP_FUNC_WIDE,
    JIM_EXPROP_FUNC_ABS,
    JIM_EXPROP_FUNC_DOUBLE,
@@ -12476,46 +12519,44 @@ enum
    JIM_EXPROP_FUNC_FMOD,
};

-
struct JimExprState
-
{
-
    Jim_Obj **stack;
-
    int stacklen;
-
    int opcode;
-
    int skip;
+
struct JimExprNode {
+
    int type;
+
    struct Jim_Obj *objPtr;
+

+
    struct JimExprNode *left;
+
    struct JimExprNode *right;
+
    struct JimExprNode *ternary;
};


typedef struct Jim_ExprOperator
{
    const char *name;
-
    int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
+
    int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode);
    unsigned char precedence;
    unsigned char arity;
-
    unsigned char lazy;
+
    unsigned char attr;
    unsigned char namelen;
} Jim_ExprOperator;

-
static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
-
{
-
    Jim_IncrRefCount(obj);
-
    e->stack[e->stacklen++] = obj;
-
}
+
static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr);
+
static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node);
+
static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node);

-
static Jim_Obj *ExprPop(struct JimExprState *e)
-
{
-
    return e->stack[--e->stacklen];
-
}
-

-
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
{
    int intresult = 1;
-
    int rc = JIM_OK;
-
    Jim_Obj *A = ExprPop(e);
+
    int rc;
    double dA, dC = 0;
    jim_wide wA, wC = 0;
+
    Jim_Obj *A;
+

+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }

    if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_FUNC_INT:
            case JIM_EXPROP_FUNC_WIDE:
            case JIM_EXPROP_FUNC_ROUND:
@@ -12540,7 +12581,7 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
        }
    }
    else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_FUNC_INT:
            case JIM_EXPROP_FUNC_WIDE:
                wC = dA;
@@ -12575,10 +12616,10 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)

    if (rc == JIM_OK) {
        if (intresult) {
-
            ExprPush(e, Jim_NewIntObj(interp, wC));
+
            Jim_SetResultInt(interp, wC);
        }
        else {
-
            ExprPush(e, Jim_NewDoubleObj(interp, dC));
+
            Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
        }
    }

@@ -12595,20 +12636,25 @@ static double JimRandDouble(Jim_Interp *interp)
    return (double)x / (unsigned long)~0;
}

-
static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node)
{
-
    Jim_Obj *A = ExprPop(e);
    jim_wide wA;
+
    Jim_Obj *A;
+
    int rc;
+

+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }

-
    int rc = Jim_GetWide(interp, A, &wA);
+
    rc = Jim_GetWide(interp, A, &wA);
    if (rc == JIM_OK) {
-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_BITNOT:
-
                ExprPush(e, Jim_NewIntObj(interp, ~wA));
+
                Jim_SetResultInt(interp, ~wA);
                break;
            case JIM_EXPROP_FUNC_SRAND:
                JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
-
                ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
+
                Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
                break;
            default:
                abort();
@@ -12620,25 +12666,29 @@ static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
    return rc;
}

-
static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node)
{
-
    JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
+
    JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));

-
    ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
+
    Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp)));

    return JIM_OK;
}

#ifdef JIM_MATH_FUNCTIONS
-
static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node)
{
    int rc;
-
    Jim_Obj *A = ExprPop(e);
    double dA, dC;
+
    Jim_Obj *A;
+

+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }

    rc = Jim_GetDouble(interp, A, &dA);
    if (rc == JIM_OK) {
-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_FUNC_SIN:
                dC = sin(dA);
                break;
@@ -12687,7 +12737,7 @@ static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
            default:
                abort();
        }
-
        ExprPush(e, Jim_NewDoubleObj(interp, dC));
+
        Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
    }

    Jim_DecrRefCount(interp, A);
@@ -12697,19 +12747,28 @@ static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
#endif


-
static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node)
{
-
    Jim_Obj *B = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
    jim_wide wA, wB;
-
    int rc = JIM_ERR;
+
    int rc;
+
    Jim_Obj *A, *B;
+

+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }
+
    if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
+
        Jim_DecrRefCount(interp, A);
+
        return rc;
+
    }
+

+
    rc = JIM_ERR;

    if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) {
        jim_wide wC;

        rc = JIM_OK;

-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_LSHIFT:
                wC = wA << wB;
                break;
@@ -12758,7 +12817,7 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)

                    uB %= S;

-
                    if (e->opcode == JIM_EXPROP_ROTR) {
+
                    if (node->type == JIM_EXPROP_ROTR) {
                        uB = S - uB;
                    }
                    wC = (unsigned long)(uA << uB) | (uA >> (S - uB));
@@ -12767,8 +12826,7 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
            default:
                abort();
        }
-
        ExprPush(e, Jim_NewIntObj(interp, wC));
-

+
        Jim_SetResultInt(interp, wC);
    }

    Jim_DecrRefCount(interp, A);
@@ -12779,14 +12837,20 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)



-
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node)
{
    int rc = JIM_OK;
    double dA, dB, dC = 0;
    jim_wide wA, wB, wC = 0;
+
    Jim_Obj *A, *B;

-
    Jim_Obj *B = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }
+
    if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
+
        Jim_DecrRefCount(interp, A);
+
        return rc;
+
    }

    if ((A->typePtr != &doubleObjType || A->bytes) &&
        (B->typePtr != &doubleObjType || B->bytes) &&
@@ -12794,7 +12858,7 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)



-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
                if (wA == 0 && wB < 0) {
@@ -12851,7 +12915,7 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
        }
    }
    if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
-
        switch (e->opcode) {
+
        switch (node->type) {
#ifndef JIM_MATH_FUNCTIONS
            case JIM_EXPROP_POW:
            case JIM_EXPROP_FUNC_POW:
@@ -12923,7 +12987,7 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)

        int i = Jim_StringCompareObj(interp, A, B, 0);

-
        switch (e->opcode) {
+
        switch (node->type) {
            case JIM_EXPROP_LT:
                wC = i < 0;
                goto intresult;
@@ -12951,10 +13015,10 @@ done:
    Jim_DecrRefCount(interp, B);
    return rc;
intresult:
-
    ExprPush(e, Jim_NewIntObj(interp, wC));
+
    Jim_SetResultInt(interp, wC);
    goto done;
doubleresult:
-
    ExprPush(e, Jim_NewDoubleObj(interp, dC));
+
    Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC));
    goto done;
}

@@ -12972,18 +13036,27 @@ static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valOb
    return 0;
}

-
static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
-
{
-
    Jim_Obj *B = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);

+

+
static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
+
{
+
    Jim_Obj *A, *B;
    jim_wide wC;
+
    int rc;
+

+
    if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
+
        return rc;
+
    }
+
    if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) {
+
        Jim_DecrRefCount(interp, A);
+
        return rc;
+
    }

-
    switch (e->opcode) {
+
    switch (node->type) {
        case JIM_EXPROP_STREQ:
        case JIM_EXPROP_STRNE:
            wC = Jim_StringEqObj(A, B);
-
            if (e->opcode == JIM_EXPROP_STRNE) {
+
            if (node->type == JIM_EXPROP_STRNE) {
                wC = !wC;
            }
            break;
@@ -12996,12 +13069,12 @@ static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
        default:
            abort();
    }
-
    ExprPush(e, Jim_NewIntObj(interp, wC));
+
    Jim_SetResultInt(interp, wC);

    Jim_DecrRefCount(interp, A);
    Jim_DecrRefCount(interp, B);

-
    return JIM_OK;
+
    return rc;
}

static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
@@ -13009,166 +13082,82 @@ static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
    long l;
    double d;
    int b;
+
    int ret = -1;
+

+

+
    Jim_IncrRefCount(obj);

    if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
-
        return l != 0;
+
        ret = (l != 0);
    }
-
    if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
-
        return d != 0;
+
    else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
+
        ret = (d != 0);
    }
-
    if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
-
        return b != 0;
-
    }
-
    return -1;
-
}
-

-
static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
-
{
-
    Jim_Obj *skip = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
-
    int rc = JIM_OK;
-

-
    switch (ExprBool(interp, A)) {
-
        case 0:
-

-
            e->skip = JimWideValue(skip);
-
            ExprPush(e, Jim_NewIntObj(interp, 0));
-
            break;
-

-
        case 1:
-

-
            break;
-

-
        case -1:
-

-
            rc = JIM_ERR;
+
    else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) {
+
        ret = (b != 0);
    }
-
    Jim_DecrRefCount(interp, A);
-
    Jim_DecrRefCount(interp, skip);

-
    return rc;
+
    Jim_DecrRefCount(interp, obj);
+
    return ret;
}

-
static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node)
{
-
    Jim_Obj *skip = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
-
    int rc = JIM_OK;
-

-
    switch (ExprBool(interp, A)) {
-
        case 0:

-
            break;
-

-
        case 1:
-

-
            e->skip = JimWideValue(skip);
-
            ExprPush(e, Jim_NewIntObj(interp, 1));
-
            break;
+
    int result = JimExprGetTermBoolean(interp, node->left);

-
        case -1:
+
    if (result == 1) {

-
            rc = JIM_ERR;
-
            break;
+
        result = JimExprGetTermBoolean(interp, node->right);
    }
-
    Jim_DecrRefCount(interp, A);
-
    Jim_DecrRefCount(interp, skip);
-

-
    return rc;
-
}
-

-
static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e)
-
{
-
    Jim_Obj *A = ExprPop(e);
-
    int rc = JIM_OK;
-

-
    switch (ExprBool(interp, A)) {
-
        case 0:
-
            ExprPush(e, Jim_NewIntObj(interp, 0));
-
            break;
-

-
        case 1:
-
            ExprPush(e, Jim_NewIntObj(interp, 1));
-
            break;
-

-
        case -1:
-

-
            rc = JIM_ERR;
-
            break;
+
    if (result == -1) {
+
        return JIM_ERR;
    }
-
    Jim_DecrRefCount(interp, A);
-

-
    return rc;
+
    Jim_SetResultInt(interp, result);
+
    return JIM_OK;
}

-
static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node)
{
-
    Jim_Obj *skip = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
-
    int rc = JIM_OK;
-

-

-
    ExprPush(e, A);
-

-
    switch (ExprBool(interp, A)) {
-
        case 0:
-

-
            e->skip = JimWideValue(skip);
-

-
            ExprPush(e, Jim_NewIntObj(interp, 0));
-
            break;
-

-
        case 1:

-
            break;
+
    int result = JimExprGetTermBoolean(interp, node->left);

-
        case -1:
+
    if (result == 0) {

-
            rc = JIM_ERR;
-
            break;
+
        result = JimExprGetTermBoolean(interp, node->right);
    }
-
    Jim_DecrRefCount(interp, A);
-
    Jim_DecrRefCount(interp, skip);
-

-
    return rc;
+
    if (result == -1) {
+
        return JIM_ERR;
+
    }
+
    Jim_SetResultInt(interp, result);
+
    return JIM_OK;
}

-
static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e)
+
static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node)
{
-
    Jim_Obj *skip = ExprPop(e);
-
    Jim_Obj *B = ExprPop(e);
-
    Jim_Obj *A = ExprPop(e);
-


-
    if (ExprBool(interp, A)) {
+
    int result = JimExprGetTermBoolean(interp, node->left);

-
        e->skip = JimWideValue(skip);
+
    if (result == 1) {

-
        ExprPush(e, B);
+
        return JimExprEvalTermNode(interp, node->right);
    }
+
    else if (result == 0) {

-
    Jim_DecrRefCount(interp, skip);
-
    Jim_DecrRefCount(interp, A);
-
    Jim_DecrRefCount(interp, B);
-
    return JIM_OK;
-
}
+
        return JimExprEvalTermNode(interp, node->ternary);
+
    }

-
static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e)
-
{
-
    return JIM_OK;
+
    return JIM_ERR;
}

enum
{
-
    LAZY_NONE,
-
    LAZY_OP,
-
    LAZY_LEFT,
-
    LAZY_RIGHT,
-
    RIGHT_ASSOC,
+
    OP_FUNC = 0x0001,
+
    OP_RIGHT_ASSOC = 0x0002,
};

#define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1}
-
#define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, LAZY_NONE)
+
#define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0)

static const struct Jim_ExprOperator Jim_ExprOperators[] = {
    OPRINIT("*", 110, 2, JimExprOpBin),
@@ -13196,24 +13185,13 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
    OPRINIT("^", 49, 2, JimExprOpIntBin),
    OPRINIT("|", 48, 2, JimExprOpIntBin),

-
    OPRINIT_ATTR("&&", 10, 2, NULL, LAZY_OP),
-
    OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
-
    OPRINIT_ATTR(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
+
    OPRINIT("&&", 10, 2, JimExprOpAnd),
+
    OPRINIT("||", 9, 2, JimExprOpOr),
+
    OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC),
+
    OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC),

-
    OPRINIT_ATTR("||", 9, 2, NULL, LAZY_OP),
-
    OPRINIT_ATTR(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
-
    OPRINIT_ATTR(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),

-
    OPRINIT_ATTR("?", 5, 2, JimExprOpNull, LAZY_OP),
-
    OPRINIT_ATTR(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
-
    OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
-

-
    OPRINIT_ATTR(":", 5, 2, JimExprOpNull, LAZY_OP),
-
    OPRINIT_ATTR(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
-
    OPRINIT_ATTR(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
-

-

-
    OPRINIT_ATTR("**", 120, 2, JimExprOpBin, RIGHT_ASSOC),
+
    OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC),

    OPRINIT("eq", 60, 2, JimExprOpStrBin),
    OPRINIT("ne", 60, 2, JimExprOpStrBin),
@@ -13221,45 +13199,45 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
    OPRINIT("in", 55, 2, JimExprOpStrBin),
    OPRINIT("ni", 55, 2, JimExprOpStrBin),

-
    OPRINIT("!", 150, 1, JimExprOpNumUnary),
-
    OPRINIT("~", 150, 1, JimExprOpIntUnary),
-
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
-
    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
+
    OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
+
    OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC),
+
    OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
+
    OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),



-
    OPRINIT("int", 200, 1, JimExprOpNumUnary),
-
    OPRINIT("wide", 200, 1, JimExprOpNumUnary),
-
    OPRINIT("abs", 200, 1, JimExprOpNumUnary),
-
    OPRINIT("double", 200, 1, JimExprOpNumUnary),
-
    OPRINIT("round", 200, 1, JimExprOpNumUnary),
-
    OPRINIT("rand", 200, 0, JimExprOpNone),
-
    OPRINIT("srand", 200, 1, JimExprOpIntUnary),
+
    OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC),
+
    OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC),
+
    OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC),
+
    OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC),
+
    OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC),
+
    OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC),
+
    OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC),

#ifdef JIM_MATH_FUNCTIONS
-
    OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("atan2", 200, 2, JimExprOpBin),
-
    OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
-
    OPRINIT("pow", 200, 2, JimExprOpBin),
-
    OPRINIT("hypot", 200, 2, JimExprOpBin),
-
    OPRINIT("fmod", 200, 2, JimExprOpBin),
+
    OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC),
+
    OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC),
+
    OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC),
+
    OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC),
+
    OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC),
#endif
};
#undef OPRINIT
-
#undef OPRINIT_LAZY
+
#undef OPRINIT_ATTR

#define JIM_EXPR_OPERATORS_NUM \
    (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
@@ -13415,31 +13393,40 @@ static int JimParseExprBoolean(struct JimParserCtx *pc)
    return JIM_ERR;
}

+
static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
+
{
+
    static Jim_ExprOperator dummy_op;
+
    if (opcode < JIM_TT_EXPR_OP) {
+
        return &dummy_op;
+
    }
+
    return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
+
}
+

static int JimParseExprOperator(struct JimParserCtx *pc)
{
    int i;
-
    int bestIdx = -1, bestLen = 0;
+
    const struct Jim_ExprOperator *bestOp = NULL;
+
    int bestLen = 0;


    for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
-
        const char * const opname = Jim_ExprOperators[i].name;
-
        const int oplen = Jim_ExprOperators[i].namelen;
+
        const struct Jim_ExprOperator *op = &Jim_ExprOperators[i];

-
        if (opname == NULL || opname[0] != pc->p[0]) {
+
        if (op->name[0] != pc->p[0]) {
            continue;
        }

-
        if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
-
            bestIdx = i + JIM_TT_EXPR_OP;
-
            bestLen = oplen;
+
        if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) {
+
            bestOp = op;
+
            bestLen = op->namelen;
        }
    }
-
    if (bestIdx == -1) {
+
    if (bestOp == NULL) {
        return JIM_ERR;
    }


-
    if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
+
    if (bestOp->attr & OP_FUNC) {
        const char *p = pc->p + bestLen;
        int len = pc->len - bestLen;

@@ -13455,19 +13442,10 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
    pc->p += bestLen;
    pc->len -= bestLen;

-
    pc->tt = bestIdx;
+
    pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP;
    return JIM_OK;
}

-
static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
-
{
-
    static Jim_ExprOperator dummy_op;
-
    if (opcode < JIM_TT_EXPR_OP) {
-
        return &dummy_op;
-
    }
-
    return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
-
}
-

const char *jim_tt_name(int type)
{
    static const char * const tt_names[JIM_TT_EXPR_OP] =
@@ -13507,34 +13485,41 @@ static const Jim_ObjType exprObjType = {
};


-
typedef struct ExprByteCode
+
struct ExprTree
{
-
    ScriptToken *token;
+
    struct JimExprNode *expr;
+
    struct JimExprNode *nodes;
    int len;
    int inUse;
-
} ExprByteCode;
+
};

-
static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
+
static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num)
{
    int i;
-

-
    for (i = 0; i < expr->len; i++) {
-
        Jim_DecrRefCount(interp, expr->token[i].objPtr);
+
    for (i = 0; i < num; i++) {
+
        if (nodes[i].objPtr) {
+
            Jim_DecrRefCount(interp, nodes[i].objPtr);
+
        }
    }
-
    Jim_Free(expr->token);
+
    Jim_Free(nodes);
+
}
+

+
static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr)
+
{
+
    ExprTreeFreeNodes(interp, expr->nodes, expr->len);
    Jim_Free(expr);
}

static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
-
    ExprByteCode *expr = (void *)objPtr->internalRep.ptr;
+
    struct ExprTree *expr = (void *)objPtr->internalRep.ptr;

    if (expr) {
        if (--expr->inUse != 0) {
            return;
        }

-
        ExprFreeByteCode(interp, expr);
+
        ExprTreeFree(interp, expr);
    }
}

@@ -13547,260 +13532,142 @@ static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dup
    dupPtr->typePtr = NULL;
}

-
static int ExprCheckCorrectness(Jim_Interp *interp, Jim_Obj *exprObjPtr, ExprByteCode * expr)
+
struct ExprBuilder {
+
    int parencount;
+
    int level;
+
    ParseToken *token;
+
    ParseToken *first_token;
+
    Jim_Stack stack;
+
    Jim_Obj *exprObjPtr;
+
    Jim_Obj *fileNameObj;
+
    struct JimExprNode *nodes;
+
    struct JimExprNode *next;
+
};
+

+
#ifdef DEBUG_SHOW_EXPR
+
static void JimShowExprNode(struct JimExprNode *node, int level)
{
    int i;
-
    int stacklen = 0;
-
    int ternary = 0;
-
    int lasttt = JIM_TT_NONE;
-
    const char *errmsg;
-

-
    for (i = 0; i < expr->len; i++) {
-
        ScriptToken *t = &expr->token[i];
-
        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
-
        lasttt = t->type;
-

-
        stacklen -= op->arity;
-

-
        if (stacklen < 0) {
-
            break;
-
        }
-
        if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
-
            ternary++;
-
        }
-
        else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
-
            ternary--;
-
        }
-

-

-
        stacklen++;
-
    }
-
    if (stacklen == 1 && ternary == 0) {
-
        return JIM_OK;
+
    for (i = 0; i < level; i++) {
+
        printf("  ");
    }
-

-
    if (stacklen <= 0) {
-

-
        if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
-
            errmsg = "too few arguments for math function";
-
            Jim_SetResultString(interp, "too few arguments for math function", -1);
-
        } else {
-
            errmsg = "premature end of expression";
+
    if (TOKEN_IS_EXPR_OP(node->type)) {
+
        printf("%s\n", jim_tt_name(node->type));
+
        if (node->left) {
+
            JimShowExprNode(node->left, level + 1);
        }
-
    }
-
    else if (stacklen > 1) {
-
        if (lasttt >= JIM_EXPROP_FUNC_FIRST) {
-
            errmsg = "too many arguments for math function";
-
        } else {
-
            errmsg = "extra tokens at end of expression";
+
        if (node->right) {
+
            JimShowExprNode(node->right, level + 1);
+
        }
+
        if (node->ternary) {
+
            JimShowExprNode(node->ternary, level + 1);
        }
    }
    else {
-
        errmsg = "invalid ternary expression";
+
        printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr));
    }
-
    Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": %s", exprObjPtr, errmsg);
-
    return JIM_ERR;
}
+
#endif

-
static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
-
{
-
    int i;
-

-
    int leftindex, arity, offset;
-

-

-
    leftindex = expr->len - 1;
-

-
    arity = 1;
-
    while (arity) {
-
        ScriptToken *tt = &expr->token[leftindex];
-

-
        if (tt->type >= JIM_TT_EXPR_OP) {
-
            arity += JimExprOperatorInfoByOpcode(tt->type)->arity;
-
        }
-
        arity--;
-
        if (--leftindex < 0) {
-
            return JIM_ERR;
-
        }
-
    }
-
    leftindex++;
-

-

-
    memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
-
        sizeof(*expr->token) * (expr->len - leftindex));
-
    expr->len += 2;
-
    offset = (expr->len - leftindex) - 1;
-

-
    expr->token[leftindex + 1].type = t->type + 1;
-
    expr->token[leftindex + 1].objPtr = interp->emptyObj;
-

-
    expr->token[leftindex].type = JIM_TT_EXPR_INT;
-
    expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
-

-

-
    expr->token[expr->len].objPtr = interp->emptyObj;
-
    expr->token[expr->len].type = t->type + 2;
-
    expr->len++;
-

-

-
    for (i = leftindex - 1; i > 0; i--) {
-
        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
-
        if (op->lazy == LAZY_LEFT) {
-
            if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
-
                JimWideValue(expr->token[i - 1].objPtr) += 2;
-
            }
-
        }
-
    }
-
    return JIM_OK;
-
}
+
#define EXPR_UNTIL_CLOSE 0x0001
+
#define EXPR_FUNC_ARGS   0x0002
+
#define EXPR_TERNARY     0x0004

-
static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
+
static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms)
{
-
    struct ScriptToken *token = &expr->token[expr->len];
-
    const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
+
    int rc;
+
    struct JimExprNode *node;

-
    if (op->lazy == LAZY_OP) {
-
        if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) {
-
            Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name);
-
            return JIM_ERR;
-
        }
-
    }
-
    else {
-
        token->objPtr = interp->emptyObj;
-
        token->type = t->type;
-
        expr->len++;
-
    }
-
    return JIM_OK;
-
}
+
    int exp_stacklen = builder->stack.len + exp_numterms;

-
static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
-
{
-
    int ternary_count = 1;
+
    if (builder->level++ > 200) {
+
        Jim_SetResultString(interp, "Expression too complex", -1);
+
        return JIM_ERR;
+
    }

-
    right_index--;
+
    while (builder->token->type != JIM_TT_EOL) {
+
        ParseToken *t = builder->token++;
+
        int prevtt;

-
    while (right_index > 1) {
-
        if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) {
-
            ternary_count--;
-
        }
-
        else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) {
-
            ternary_count++;
+
        if (t == builder->first_token) {
+
            prevtt = JIM_TT_NONE;
        }
-
        else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) {
-
            return right_index;
+
        else {
+
            prevtt = t[-1].type;
        }
-
        right_index--;
-
    }

-

-
    return -1;
-
}
-

-
static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
-
{
-
    int i = right_index - 1;
-
    int ternary_count = 1;
-

-
    while (i > 1) {
-
        if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) {
-
            if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) {
-
                *prev_right_index = i - 2;
-
                *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index);
-
                return 1;
+
        if (t->type == JIM_TT_SUBEXPR_START) {
+
            if (builder->stack.len == exp_stacklen) {
+
                Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr);
+
                return JIM_ERR;
            }
-
        }
-
        else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) {
-
            if (ternary_count == 0) {
-
                return 0;
+
            builder->parencount++;
+
            rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1);
+
            if (rc != JIM_OK) {
+
                return rc;
            }
-
            ternary_count++;
-
        }
-
        i--;
-
    }
-
    return 0;
-
}
-

-
static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
-
{
-
    int i;

-
    for (i = expr->len - 1; i > 1; i--) {
-
        int prev_right_index;
-
        int prev_left_index;
-
        int j;
-
        ScriptToken tmp;
-

-
        if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
-
            continue;
-
        }
-

-

-
        if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
-
            continue;
        }
+
        else if (t->type == JIM_TT_SUBEXPR_END) {
+
            if (!(flags & EXPR_UNTIL_CLOSE)) {
+
                if (builder->stack.len == exp_stacklen && builder->level > 1) {
+
                    builder->token--;
+
                    builder->level--;
+
                    return JIM_OK;
+
                }
+
                Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr);
+
                return JIM_ERR;
+
            }
+
            builder->parencount--;
+
            if (builder->stack.len == exp_stacklen) {

-
        tmp = expr->token[prev_right_index];
-
        for (j = prev_right_index; j < i; j++) {
-
            expr->token[j] = expr->token[j + 1];
+
                break;
+
            }
        }
-
        expr->token[i] = tmp;
-

-
        JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
-

-

-
        i++;
-
    }
-
}
-

-
static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
-
{
-
    Jim_Stack stack;
-
    ExprByteCode *expr;
-
    int ok = 1;
-
    int i;
-
    int prevtt = JIM_TT_NONE;
-
    int have_ternary = 0;
-

-

-
    int count = tokenlist->count - 1;
-

-
    expr = Jim_Alloc(sizeof(*expr));
-
    expr->inUse = 1;
-
    expr->len = 0;
-

-
    Jim_InitStack(&stack);
-

-
    for (i = 0; i < tokenlist->count; i++) {
-
        ParseToken *t = &tokenlist->list[i];
-
        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
+
        else if (t->type == JIM_TT_SUBEXPR_COMMA) {
+
            if (!(flags & EXPR_FUNC_ARGS)) {
+
                if (builder->stack.len == exp_stacklen) {

-
        if (op->lazy == LAZY_OP) {
-
            count += 2;
-

-
            if (t->type == JIM_EXPROP_TERNARY) {
-
                have_ternary = 1;
+
                    builder->token--;
+
                    builder->level--;
+
                    return JIM_OK;
+
                }
+
                Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr);
+
                return JIM_ERR;
            }
-
        }
-
    }
+
            else {

-
    expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
+
                if (builder->stack.len > exp_stacklen) {
+
                    Jim_SetResultFormatted(interp, "too many arguments to math function");
+
                    return JIM_ERR;
+
                }
+
            }

-
    for (i = 0; i < tokenlist->count && ok; i++) {
-
        ParseToken *t = &tokenlist->list[i];
+
        }
+
        else if (t->type == JIM_EXPROP_COLON) {
+
            if (!(flags & EXPR_TERNARY)) {
+
                if (builder->level != 1) {

+
                    builder->token--;
+
                    builder->level--;
+
                    return JIM_OK;
+
                }
+
                Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr);
+
                return JIM_ERR;
+
            }
+
            if (builder->stack.len == exp_stacklen) {

-
        struct ScriptToken *token = &expr->token[expr->len];
+
                builder->token--;
+
                builder->level--;
+
                return JIM_OK;
+
            }

-
        if (t->type == JIM_TT_EOL) {
-
            break;
        }
-

-
        if (TOKEN_IS_EXPR_OP(t->type)) {
+
        else if (TOKEN_IS_EXPR_OP(t->type)) {
            const struct Jim_ExprOperator *op;
-
            ParseToken *tt;


-
            if (prevtt == JIM_TT_NONE || prevtt == JIM_TT_SUBEXPR_START || prevtt == JIM_TT_SUBEXPR_COMMA || prevtt >= JIM_TT_EXPR_OP) {
+
            if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) {
                if (t->type == JIM_EXPROP_SUB) {
                    t->type = JIM_EXPROP_UNARYMINUS;
                }
@@ -13811,66 +13678,82 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList

            op = JimExprOperatorInfoByOpcode(t->type);

+
            if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) {

-
            while ((tt = Jim_StackPeek(&stack)) != NULL) {
-
                const struct Jim_ExprOperator *tt_op =
-
                    JimExprOperatorInfoByOpcode(tt->type);
-

-

-
                if (op->arity != 1 && tt_op->precedence >= op->precedence) {
+
                builder->token--;
+
                break;
+
            }

-
                    if (tt_op->precedence == op->precedence && tt_op->lazy == RIGHT_ASSOC) {
-
                        break;
-
                    }
-
                    if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
-
                        ok = 0;
-
                        goto err;
-
                    }
-
                    Jim_StackPop(&stack);
+
            if (op->attr & OP_FUNC) {
+
                if (builder->token->type != JIM_TT_SUBEXPR_START) {
+
                    Jim_SetResultString(interp, "missing arguments for math function", -1);
+
                    return JIM_ERR;
                }
-
                else {
-
                    break;
+
                builder->token++;
+
                if (op->arity == 0) {
+
                    if (builder->token->type != JIM_TT_SUBEXPR_END) {
+
                        Jim_SetResultString(interp, "too many arguments for math function", -1);
+
                        return JIM_ERR;
+
                    }
+
                    builder->token++;
+
                    goto noargs;
                }
+
                builder->parencount++;
+

+

+
                rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity);
            }
-
            Jim_StackPush(&stack, t);
-
        }
-
        else if (t->type == JIM_TT_SUBEXPR_START) {
-
            Jim_StackPush(&stack, t);
-
        }
-
        else if (t->type == JIM_TT_SUBEXPR_END || t->type == JIM_TT_SUBEXPR_COMMA) {
+
            else if (t->type == JIM_EXPROP_TERNARY) {

-
            ok = 0;
-
            while (Jim_StackLen(&stack)) {
-
                ParseToken *tt = Jim_StackPop(&stack);
+
                rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2);
+
            }
+
            else {
+
                rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1);
+
            }

-
                if (tt->type == JIM_TT_SUBEXPR_START || tt->type == JIM_TT_SUBEXPR_COMMA) {
-
                    if (t->type == JIM_TT_SUBEXPR_COMMA) {
+
            if (rc != JIM_OK) {
+
                return rc;
+
            }

-
                        Jim_StackPush(&stack, tt);
-
                    }
-
                    ok = 1;
-
                    break;
+
noargs:
+
            node = builder->next++;
+
            node->type = t->type;
+

+
            if (op->arity >= 3) {
+
                node->ternary = Jim_StackPop(&builder->stack);
+
                if (node->ternary == NULL) {
+
                    goto missingoperand;
                }
-
                if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
-
                    goto err;
+
            }
+
            if (op->arity >= 2) {
+
                node->right = Jim_StackPop(&builder->stack);
+
                if (node->right == NULL) {
+
                    goto missingoperand;
                }
            }
-
            if (!ok) {
-
                Jim_SetResultFormatted(interp, "Unexpected close parenthesis in expression: \"%#s\"", exprObjPtr);
-
                goto err;
+
            if (op->arity >= 1) {
+
                node->left = Jim_StackPop(&builder->stack);
+
                if (node->left == NULL) {
+
missingoperand:
+
                    Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr);
+
                    builder->next--;
+
                    return JIM_ERR;
+

+
                }
            }
+

+

+
            Jim_StackPush(&builder->stack, node);
        }
        else {
            Jim_Obj *objPtr = NULL;


-
            token->type = t->type;


            if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) {
-
                Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", exprObjPtr);
-
                ok = 0;
-
                goto err;
+
                Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr);
+
                return JIM_ERR;
            }


@@ -13889,64 +13772,103 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
                }
            }

-
            if (objPtr) {
-
                token->objPtr = objPtr;
-
            }
-
            else {
+
            if (!objPtr) {

-
                token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
+
                objPtr = Jim_NewStringObj(interp, t->token, t->len);
                if (t->type == JIM_TT_CMD) {

-
                    JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
+
                    JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line);
                }
            }
-
            expr->len++;
+

+

+
            node = builder->next++;
+
            node->objPtr = objPtr;
+
            Jim_IncrRefCount(node->objPtr);
+
            node->type = t->type;
+
            Jim_StackPush(&builder->stack, node);
        }
-
        prevtt = t->type;
    }

+
    if (builder->stack.len == exp_stacklen) {
+
        builder->level--;
+
        return JIM_OK;
+
    }

-
    while (Jim_StackLen(&stack)) {
-
        ParseToken *tt = Jim_StackPop(&stack);
-

-
        if (tt->type == JIM_TT_SUBEXPR_START) {
-
            ok = 0;
-
            Jim_SetResultString(interp, "Missing close parenthesis", -1);
-
            goto err;
+
    if ((flags & EXPR_FUNC_ARGS)) {
+
        Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many");
+
    }
+
    else {
+
        if (builder->stack.len < exp_stacklen) {
+
            if (builder->level == 0) {
+
                Jim_SetResultFormatted(interp, "empty expression");
+
            }
+
            else {
+
                Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr);
+
            }
        }
-
        if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
-
            ok = 0;
-
            goto err;
+
        else {
+
            Jim_SetResultFormatted(interp, "extra terms after expression");
        }
    }

-
    if (have_ternary) {
-
        ExprTernaryReorderExpression(interp, expr);
-
    }
+
    return JIM_ERR;
+
}

-
  err:
+
static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj)
+
{
+
    struct ExprTree *expr;
+
    struct ExprBuilder builder;
+
    int rc;
+
    struct JimExprNode *top = NULL;
+

+
    builder.parencount = 0;
+
    builder.level = 0;
+
    builder.token = builder.first_token = tokenlist->list;
+
    builder.exprObjPtr = exprObjPtr;
+
    builder.fileNameObj = fileNameObj;
+

+
    builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
+
    memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1));
+
    builder.next = builder.nodes;
+
    Jim_InitStack(&builder.stack);

-
    Jim_FreeStack(&stack);
+
    rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1);

-
    for (i = 0; i < expr->len; i++) {
-
        Jim_IncrRefCount(expr->token[i].objPtr);
+
    if (rc == JIM_OK) {
+
        top = Jim_StackPop(&builder.stack);
+

+
        if (builder.parencount) {
+
            Jim_SetResultString(interp, "missing close parenthesis", -1);
+
            rc = JIM_ERR;
+
        }
    }

-
    if (!ok) {
-
        ExprFreeByteCode(interp, expr);
+

+
    Jim_FreeStack(&builder.stack);
+

+
    if (rc != JIM_OK) {
+
        ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes);
        return NULL;
    }

+
    expr = Jim_Alloc(sizeof(*expr));
+
    expr->inUse = 1;
+
    expr->expr = top;
+
    expr->nodes = builder.nodes;
+
    expr->len = builder.next - builder.nodes;
+

+
    assert(expr->len <= tokenlist->count - 1);
+

    return expr;
}

-

static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
    int exprTextLen;
    const char *exprText;
    struct JimParserCtx parser;
-
    struct ExprByteCode *expr;
+
    struct ExprTree *expr;
    ParseTokenList tokenlist;
    int line;
    Jim_Obj *fileNameObj;
@@ -13999,7 +13921,7 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
    }


-
    expr = ExprCreateByteCode(interp, &tokenlist, objPtr, fileNameObj);
+
    expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj);


    ScriptTokenListFree(&tokenlist);
@@ -14009,26 +13931,10 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
    }

#ifdef DEBUG_SHOW_EXPR
-
    {
-
        int i;
-

-
        printf("==== Expr ====\n");
-
        for (i = 0; i < expr->len; i++) {
-
            ScriptToken *t = &expr->token[i];
-

-
            printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
-
        }
-
    }
+
    printf("==== Expr ====\n");
+
    JimShowExprNode(expr->expr, 0);
#endif

-

-
    if (ExprCheckCorrectness(interp, objPtr, expr) != JIM_OK) {
-

-
        ExprFreeByteCode(interp, expr);
-
        expr = NULL;
-
        goto err;
-
    }
-

    rc = JIM_OK;

  err:
@@ -14040,39 +13946,104 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
    return rc;
}

-
static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
+
static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
{
    if (objPtr->typePtr != &exprObjType) {
        if (SetExprFromAny(interp, objPtr) != JIM_OK) {
            return NULL;
        }
    }
-
    return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
+
    return (struct ExprTree *) Jim_GetIntRepPtr(objPtr);
}

#ifdef JIM_OPTIMIZATION
-
static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
-
{
-
    if (token->type == JIM_TT_EXPR_INT)
-
        return token->objPtr;
-
    else if (token->type == JIM_TT_VAR)
-
        return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
-
    else if (token->type == JIM_TT_DICTSUGAR)
-
        return JimExpandDictSugar(interp, token->objPtr);
+
static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node)
+
{
+
    if (node->type == JIM_TT_EXPR_INT)
+
        return node->objPtr;
+
    else if (node->type == JIM_TT_VAR)
+
        return Jim_GetVariable(interp, node->objPtr, JIM_NONE);
+
    else if (node->type == JIM_TT_DICTSUGAR)
+
        return JimExpandDictSugar(interp, node->objPtr);
    else
        return NULL;
}
#endif

-
#define JIM_EE_STATICSTACK_LEN 10

-
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
+
static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node)
{
-
    ExprByteCode *expr;
-
    Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];
-
    int i;
+
    if (TOKEN_IS_EXPR_OP(node->type)) {
+
        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type);
+
        return op->funcop(interp, node);
+
    }
+
    else {
+
        Jim_Obj *objPtr;
+

+

+
        switch (node->type) {
+
            case JIM_TT_EXPR_INT:
+
            case JIM_TT_EXPR_DOUBLE:
+
            case JIM_TT_EXPR_BOOLEAN:
+
            case JIM_TT_STR:
+
                Jim_SetResult(interp, node->objPtr);
+
                return JIM_OK;
+

+
            case JIM_TT_VAR:
+
                objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG);
+
                if (objPtr) {
+
                    Jim_SetResult(interp, objPtr);
+
                    return JIM_OK;
+
                }
+
                return JIM_ERR;
+

+
            case JIM_TT_DICTSUGAR:
+
                objPtr = JimExpandDictSugar(interp, node->objPtr);
+
                if (objPtr) {
+
                    Jim_SetResult(interp, objPtr);
+
                    return JIM_OK;
+
                }
+
                return JIM_ERR;
+

+
            case JIM_TT_ESC:
+
                if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) {
+
                    Jim_SetResult(interp, objPtr);
+
                    return JIM_OK;
+
                }
+
                return JIM_ERR;
+

+
            case JIM_TT_CMD:
+
                return Jim_EvalObj(interp, node->objPtr);
+

+
            default:
+

+
                return JIM_ERR;
+
        }
+
    }
+
}
+

+
static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr)
+
{
+
    int rc = JimExprEvalTermNode(interp, node);
+
    if (rc == JIM_OK) {
+
        *objPtrPtr = Jim_GetResult(interp);
+
        Jim_IncrRefCount(*objPtrPtr);
+
    }
+
    return rc;
+
}
+

+
static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node)
+
{
+
    if (JimExprEvalTermNode(interp, node) == JIM_OK) {
+
        return ExprBool(interp, Jim_GetResult(interp));
+
    }
+
    return -1;
+
}
+

+
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
+
{
+
    struct ExprTree *expr;
    int retcode = JIM_OK;
-
    struct JimExprState e;

    expr = JimGetExpression(interp, exprObjPtr);
    if (!expr) {
@@ -14086,35 +14057,33 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe

        switch (expr->len) {
            case 1:
-
                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
+
                objPtr = JimExprIntValOrVar(interp, expr->expr);
                if (objPtr) {
-
                    Jim_IncrRefCount(objPtr);
-
                    *exprResultPtrPtr = objPtr;
+
                    Jim_SetResult(interp, objPtr);
                    return JIM_OK;
                }
                break;

            case 2:
-
                if (expr->token[1].type == JIM_EXPROP_NOT) {
-
                    objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
+
                if (expr->expr->type == JIM_EXPROP_NOT) {
+
                    objPtr = JimExprIntValOrVar(interp, expr->expr->left);

                    if (objPtr && JimIsWide(objPtr)) {
-
                        *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
-
                        Jim_IncrRefCount(*exprResultPtrPtr);
+
                        Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj);
                        return JIM_OK;
                    }
                }
                break;

            case 3:
-
                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
+
                objPtr = JimExprIntValOrVar(interp, expr->expr->left);
                if (objPtr && JimIsWide(objPtr)) {
-
                    Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
+
                    Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right);
                    if (objPtr2 && JimIsWide(objPtr2)) {
                        jim_wide wideValueA = JimWideValue(objPtr);
                        jim_wide wideValueB = JimWideValue(objPtr2);
                        int cmpRes;
-
                        switch (expr->token[2].type) {
+
                        switch (expr->expr->type) {
                            case JIM_EXPROP_LT:
                                cmpRes = wideValueA < wideValueB;
                                break;
@@ -14136,8 +14105,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
                            default:
                                goto noopt;
                        }
-
                        *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
-
                        Jim_IncrRefCount(*exprResultPtrPtr);
+
                        Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj);
                        return JIM_OK;
                    }
                }
@@ -14150,122 +14118,33 @@ noopt:
    expr->inUse++;


-

-
    if (expr->len > JIM_EE_STATICSTACK_LEN)
-
        e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
-
    else
-
        e.stack = staticStack;
-

-
    e.stacklen = 0;
-

-

-
    for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
-
        Jim_Obj *objPtr;
-

-
        switch (expr->token[i].type) {
-
            case JIM_TT_EXPR_INT:
-
            case JIM_TT_EXPR_DOUBLE:
-
            case JIM_TT_EXPR_BOOLEAN:
-
            case JIM_TT_STR:
-
                ExprPush(&e, expr->token[i].objPtr);
-
                break;
-

-
            case JIM_TT_VAR:
-
                objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG);
-
                if (objPtr) {
-
                    ExprPush(&e, objPtr);
-
                }
-
                else {
-
                    retcode = JIM_ERR;
-
                }
-
                break;
-

-
            case JIM_TT_DICTSUGAR:
-
                objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr);
-
                if (objPtr) {
-
                    ExprPush(&e, objPtr);
-
                }
-
                else {
-
                    retcode = JIM_ERR;
-
                }
-
                break;
-

-
            case JIM_TT_ESC:
-
                retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE);
-
                if (retcode == JIM_OK) {
-
                    ExprPush(&e, objPtr);
-
                }
-
                break;
-

-
            case JIM_TT_CMD:
-
                retcode = Jim_EvalObj(interp, expr->token[i].objPtr);
-
                if (retcode == JIM_OK) {
-
                    ExprPush(&e, Jim_GetResult(interp));
-
                }
-
                break;
-

-
            default:{
-

-
                    e.skip = 0;
-
                    e.opcode = expr->token[i].type;
-

-
                    retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
-

-
                    i += e.skip;
-
                    continue;
-
                }
-
        }
-
    }
+
    retcode = JimExprEvalTermNode(interp, expr->expr);

    expr->inUse--;

-
    if (retcode == JIM_OK) {
-
        *exprResultPtrPtr = ExprPop(&e);
-
    }
-
    else {
-
        for (i = 0; i < e.stacklen; i++) {
-
            Jim_DecrRefCount(interp, e.stack[i]);
-
        }
-
    }
-
    if (e.stack != staticStack) {
-
        Jim_Free(e.stack);
-
    }
    return retcode;
}

int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
{
-
    int retcode;
-
    jim_wide wideValue;
-
    double doubleValue;
-
    int booleanValue;
-
    Jim_Obj *exprResultPtr;
+
    int retcode = Jim_EvalExpression(interp, exprObjPtr);

-
    retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
-
    if (retcode != JIM_OK)
-
        return retcode;
+
    if (retcode == JIM_OK) {
+
        switch (ExprBool(interp, Jim_GetResult(interp))) {
+
            case 0:
+
                *boolPtr = 0;
+
                break;

-
    if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
-
        if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
-
            if (Jim_GetBoolean(interp, exprResultPtr, &booleanValue) != JIM_OK) {
-
                Jim_DecrRefCount(interp, exprResultPtr);
-
                return JIM_ERR;
-
            } else {
-
                Jim_DecrRefCount(interp, exprResultPtr);
-
                *boolPtr = booleanValue;
-
                return JIM_OK;
-
            }
-
        }
-
        else {
-
            Jim_DecrRefCount(interp, exprResultPtr);
-
            *boolPtr = doubleValue != 0;
-
            return JIM_OK;
+
            case 1:
+
                *boolPtr = 1;
+
                break;
+

+
            case -1:
+
                retcode = JIM_ERR;
+
                break;
        }
    }
-
    *boolPtr = wideValue != 0;
-

-
    Jim_DecrRefCount(interp, exprResultPtr);
-
    return JIM_OK;
+
    return retcode;
}


@@ -14273,8 +14152,8 @@ int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)

typedef struct ScanFmtPartDescr
{
-
    char *arg;
-
    char *prefix;
+
    const char *arg;
+
    const char *prefix;
    size_t width;
    int pos;
    char type;
@@ -14336,8 +14215,8 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
    ScanFmtStringObj *fmtObj;
    char *buffer;
    int maxCount, i, approxSize, lastPos = -1;
-
    const char *fmt = objPtr->bytes;
-
    int maxFmtLen = objPtr->length;
+
    const char *fmt = Jim_String(objPtr);
+
    int maxFmtLen = Jim_Length(objPtr);
    const char *fmtEnd = fmt + maxFmtLen;
    int curr;

@@ -14422,6 +14301,11 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
                        return JIM_ERR;
                    }
                }
+
                if (descr->pos < 0) {
+
                    fmtObj->error =
+
                        "\"%n$\" conversion specifier is negative";
+
                    return JIM_ERR;
+
                }

                if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
                    descr->width = width;
@@ -14473,9 +14357,14 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
        }
        else {

-
            if (strchr("hlL", *fmt) != 0)
+
            if (fmt < fmtEnd && strchr("hlL", *fmt))
                descr->modifier = tolower((int)*fmt++);

+
            if (fmt >= fmtEnd) {
+
                fmtObj->error = "missing scan conversion character";
+
                return JIM_ERR;
+
            }
+

            descr->type = *fmt;
            if (strchr("efgcsndoxui", *fmt) == 0) {
                fmtObj->error = "bad scan conversion character";
@@ -14882,6 +14771,7 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
    int retcode;
    Jim_Cmd *cmdPtr;
+
    void *prevPrivData;

#if 0
    printf("invoke");
@@ -14911,6 +14801,7 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
        goto out;
    }
    interp->evalDepth++;
+
    prevPrivData = interp->cmdPrivData;


    Jim_SetEmptyResult(interp);
@@ -14921,6 +14812,7 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
        interp->cmdPrivData = cmdPtr->u.native.privData;
        retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
    }
+
    interp->cmdPrivData = prevPrivData;
    interp->evalDepth--;

out:
@@ -15085,7 +14977,8 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok


    if (tokens == 1 && intv[0] && intv == sintv) {
-
        Jim_DecrRefCount(interp, intv[0]);
+

+
        intv[0]->refCount--;
        return intv[0];
    }

@@ -15540,6 +15433,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
badargset:


+
    retcode = JimInvokeDefer(interp, retcode);
    interp->framePtr = interp->framePtr->parent;
    JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);

@@ -15828,7 +15722,7 @@ void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const

    listObjPtr = Jim_NewListObj(interp, argv, argc);

-
    if (*msg) {
+
    if (msg && *msg) {
        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
    }
    Jim_IncrRefCount(listObjPtr);
@@ -16068,8 +15962,13 @@ static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, i
        }
        if (op == JIM_EXPROP_SUB)
            res -= wideValue;
-
        else
+
        else {
+
            if (wideValue == 0) {
+
                Jim_SetResultString(interp, "Division by zero", -1);
+
                return JIM_ERR;
+
            }
            res /= wideValue;
+
        }
    }
    Jim_SetResultInt(interp, res);
    return JIM_OK;
@@ -16221,7 +16120,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
#ifdef JIM_OPTIMIZATION
    if (retval == JIM_OK && boolean) {
        ScriptObj *incrScript;
-
        ExprByteCode *expr;
+
        struct ExprTree *expr;
        jim_wide stop, currentVal;
        Jim_Obj *objPtr;
        int cmpOffset;
@@ -16235,47 +16134,53 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
            goto evalstart;
        }

-
        if (incrScript->token[1].type != JIM_TT_ESC ||
-
            expr->token[0].type != JIM_TT_VAR ||
-
            (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
+
        if (incrScript->token[1].type != JIM_TT_ESC) {
            goto evalstart;
        }

-
        if (expr->token[2].type == JIM_EXPROP_LT) {
+
        if (expr->expr->type == JIM_EXPROP_LT) {
            cmpOffset = 0;
        }
-
        else if (expr->token[2].type == JIM_EXPROP_LTE) {
+
        else if (expr->expr->type == JIM_EXPROP_LTE) {
            cmpOffset = 1;
        }
        else {
            goto evalstart;
        }

+
        if (expr->expr->left->type != JIM_TT_VAR) {
+
            goto evalstart;
+
        }
+

+
        if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) {
+
            goto evalstart;
+
        }
+


        if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
            goto evalstart;
        }


-
        if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
+
        if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) {
            goto evalstart;
        }


-
        if (expr->token[1].type == JIM_TT_EXPR_INT) {
-
            if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
+
        if (expr->expr->right->type == JIM_TT_EXPR_INT) {
+
            if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) {
                goto evalstart;
            }
        }
        else {
-
            stopVarNamePtr = expr->token[1].objPtr;
+
            stopVarNamePtr = expr->expr->right->objPtr;
            Jim_IncrRefCount(stopVarNamePtr);

            stop = 0;
        }


-
        varNamePtr = expr->token[0].objPtr;
+
        varNamePtr = expr->expr->left->objPtr;
        Jim_IncrRefCount(varNamePtr);

        objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
@@ -16482,7 +16387,7 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
    }
    if (result != JIM_OK) {
        Jim_SetResultString(interp, "foreach varlist is empty", -1);
-
        return result;
+
        goto empty_varlist;
    }

    if (doMap) {
@@ -16545,6 +16450,7 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
    Jim_SetResult(interp, resultObj);
  err:
    Jim_DecrRefCount(interp, resultObj);
+
  empty_varlist:
    if (numargs > 2) {
        Jim_Free(iters);
    }
@@ -16671,15 +16577,13 @@ int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patter
    return eq;
}

-
enum
-
{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
-


static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
+
    enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
    int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
-
    Jim_Obj *command = 0, *const *caseList = 0, *strObj;
-
    Jim_Obj *script = 0;
+
    Jim_Obj *command = NULL, *scriptObj = NULL, *strObj;
+
    Jim_Obj **caseList;

    if (argc < 3) {
      wrongnumargs:
@@ -16720,16 +16624,13 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
    strObj = argv[opt++];
    patCount = argc - opt;
    if (patCount == 1) {
-
        Jim_Obj **vector;
-

-
        JimListGetElements(interp, argv[opt], &patCount, &vector);
-
        caseList = vector;
+
        JimListGetElements(interp, argv[opt], &patCount, &caseList);
    }
    else
-
        caseList = &argv[opt];
+
        caseList = (Jim_Obj **)&argv[opt];
    if (patCount == 0 || patCount % 2 != 0)
        goto wrongnumargs;
-
    for (i = 0; script == 0 && i < patCount; i += 2) {
+
    for (i = 0; scriptObj == NULL && i < patCount; i += 2) {
        Jim_Obj *patObj = caseList[i];

        if (!Jim_CompareStringImmediate(interp, patObj, "default")
@@ -16737,11 +16638,11 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
            switch (matchOpt) {
                case SWITCH_EXACT:
                    if (Jim_StringEqObj(strObj, patObj))
-
                        script = caseList[i + 1];
+
                        scriptObj = caseList[i + 1];
                    break;
                case SWITCH_GLOB:
                    if (Jim_StringMatchObj(interp, patObj, strObj, 0))
-
                        script = caseList[i + 1];
+
                        scriptObj = caseList[i + 1];
                    break;
                case SWITCH_RE:
                    command = Jim_NewStringObj(interp, "regexp", -1);
@@ -16750,34 +16651,31 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
                        int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);

                        if (argc - opt == 1) {
-
                            Jim_Obj **vector;
-

-
                            JimListGetElements(interp, argv[opt], &patCount, &vector);
-
                            caseList = vector;
+
                            JimListGetElements(interp, argv[opt], &patCount, &caseList);
                        }

                        if (rc < 0) {
                            return -rc;
                        }
                        if (rc)
-
                            script = caseList[i + 1];
+
                            scriptObj = caseList[i + 1];
                        break;
                    }
            }
        }
        else {
-
            script = caseList[i + 1];
+
            scriptObj = caseList[i + 1];
        }
    }
-
    for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2)
-
        script = caseList[i + 1];
-
    if (script && Jim_CompareStringImmediate(interp, script, "-")) {
+
    for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2)
+
        scriptObj = caseList[i + 1];
+
    if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) {
        Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]);
        return JIM_ERR;
    }
    Jim_SetEmptyResult(interp);
-
    if (script) {
-
        return Jim_EvalObj(interp, script);
+
    if (scriptObj) {
+
        return Jim_EvalObj(interp, scriptObj);
    }
    return JIM_OK;
}
@@ -17076,18 +16974,8 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
    JimRelToAbsRange(len, &first, &last, &rangeLen);


-

-
    if (first < len) {
-

-
    }
-
    else if (len == 0) {
-

-
        first = 0;
-
    }
-
    else {
-
        Jim_SetResultString(interp, "list doesn't contain element ", -1);
-
        Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
-
        return JIM_ERR;
+
    if (first > len) {
+
        first = len;
    }


@@ -17131,6 +17019,7 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
    Jim_Obj *resObj;
    int i;
    int retCode;
+
    int shared;

    struct lsort_info info;

@@ -17196,12 +17085,14 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
                break;
        }
    }
-
    resObj = Jim_DuplicateObj(interp, argv[argc - 1]);
+
    resObj = argv[argc - 1];
+
    if ((shared = Jim_IsShared(resObj)))
+
        resObj = Jim_DuplicateObj(interp, resObj);
    retCode = ListSortElements(interp, resObj, &info);
    if (retCode == JIM_OK) {
        Jim_SetResult(interp, resObj);
    }
-
    else {
+
    else if (shared) {
        Jim_FreeNewObj(interp, resObj);
    }
    return retCode;
@@ -17249,6 +17140,7 @@ static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
}


+

static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#if !defined(JIM_DEBUG_COMMAND)
@@ -17329,18 +17221,17 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *

static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-
    Jim_Obj *exprResultPtr;
    int retcode;

    if (argc == 2) {
-
        retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr);
+
        retcode = Jim_EvalExpression(interp, argv[1]);
    }
    else if (argc > 2) {
        Jim_Obj *objPtr;

        objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
        Jim_IncrRefCount(objPtr);
-
        retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr);
+
        retcode = Jim_EvalExpression(interp, objPtr);
        Jim_DecrRefCount(interp, objPtr);
    }
    else {
@@ -17349,8 +17240,6 @@ static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
    }
    if (retcode != JIM_OK)
        return retcode;
-
    Jim_SetResult(interp, exprResultPtr);
-
    Jim_DecrRefCount(interp, exprResultPtr);
    return JIM_OK;
}

@@ -19655,6 +19544,14 @@ int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const
    return JIM_ERR;
}

+
static const Jim_ObjType getEnumObjType = {
+
    "get-enum",
+
    NULL,
+
    NULL,
+
    NULL,
+
    JIM_TYPE_REFERENCES
+
};
+

int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
    const char *const *tablePtr, int *indexPtr, const char *name, int flags)
{
@@ -19663,15 +19560,24 @@ int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
    int i;
    int match = -1;
    int arglen;
-
    const char *arg = Jim_GetString(objPtr, &arglen);
+
    const char *arg;
+

+
    if (objPtr->typePtr == &getEnumObjType) {
+
        if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) {
+
            *indexPtr = objPtr->internalRep.ptrIntValue.int2;
+
            return JIM_OK;
+
        }
+
    }
+

+
    arg = Jim_GetString(objPtr, &arglen);

    *indexPtr = -1;

    for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
        if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {

-
            *indexPtr = i;
-
            return JIM_OK;
+
            match = i;
+
            goto found;
        }
        if (flags & JIM_ENUM_ABBREV) {
            if (strncmp(arg, *entryPtr, arglen) == 0) {
@@ -19689,6 +19595,14 @@ int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,


    if (match >= 0) {
+
  found:
+

+
        Jim_FreeIntRep(interp, objPtr);
+
        objPtr->typePtr = &getEnumObjType;
+
        objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr;
+
        objPtr->internalRep.ptrIntValue.int1 = flags;
+
        objPtr->internalRep.ptrIntValue.int2 = match;
+

        *indexPtr = match;
        return JIM_OK;
    }
@@ -19820,18 +19734,14 @@ static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const c
static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
    Jim_Obj *cmd, Jim_Obj *subcmd)
{
-
    Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-
    Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type,
-
        " command \"", Jim_String(subcmd), "\": should be ", NULL);
+
    Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd);
    add_commands(interp, command_table, ", ");
}

static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
    Jim_Obj *const *argv)
{
-
    Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-
    Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]),
-
        " command ... \", where command is one of: ", NULL);
+
    Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]);
    add_commands(interp, command_table, ", ");
}

@@ -19853,6 +19763,14 @@ static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_t
    Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
}

+
static const Jim_ObjType subcmdLookupObjType = {
+
    "subcmd-lookup",
+
    NULL,
+
    NULL,
+
    NULL,
+
    JIM_TYPE_REFERENCES
+
};
+

const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
    int argc, Jim_Obj *const *argv)
{
@@ -19861,22 +19779,25 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
    int cmdlen;
    Jim_Obj *cmd;
    const char *cmdstr;
-
    const char *cmdname;
    int help = 0;

-
    cmdname = Jim_String(argv[0]);
-

    if (argc < 2) {
-
        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-
        Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
-
            " command ...\"\n", NULL);
-
        Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL);
+
        Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n"
+
            "Use \"%#s -help ?command?\" for help", argv[0], argv[0]);
        return 0;
    }

    cmd = argv[1];


+
    if (cmd->typePtr == &subcmdLookupObjType) {
+
        if (cmd->internalRep.ptrIntValue.ptr == command_table) {
+
            ct = command_table + cmd->internalRep.ptrIntValue.int1;
+
            goto found;
+
        }
+
    }
+

+

    if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
        if (argc == 2) {

@@ -19944,6 +19865,13 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
    }


+
    Jim_FreeIntRep(interp, cmd);
+
    cmd->typePtr = &subcmdLookupObjType;
+
    cmd->internalRep.ptrIntValue.ptr = (void *)command_table;
+
    cmd->internalRep.ptrIntValue.int1 = ct - command_table;
+

+
found:
+

    if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
        Jim_SetResultString(interp, "wrong # args: should be \"", -1);

@@ -20135,7 +20063,8 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
            *p++ = ch;
            format += step;
            step = utf8_tounicode(format, &ch);
-
        } while (sawFlag);
+

+
        } while (sawFlag && (p - spec <= 5));


        width = 0;
@@ -20334,6 +20263,13 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
            *p = '\0';


+
            if (width > 10000 || length > 10000 || precision > 10000) {
+
                Jim_SetResultString(interp, "format too long", -1);
+
                goto error;
+
            }
+

+

+

            if (width > length) {
                length = width;
            }
@@ -20706,6 +20642,10 @@ static int regpiece(regex_t *preg, int *flagp)
		if (*end == '}') {
			max = min;
		}
+
		else if (*end == '\0') {
+
			preg->err = REG_ERR_UNMATCHED_BRACES;
+
			return 0;
+
		}
		else {
			preg->regparse = end;
			max = strtoul(preg->regparse + 1, &end, 10);
@@ -20910,8 +20850,31 @@ static int regatom(regex_t *preg, int *flagp)
				int start;
				int end;

+
				enum {
+
					CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
+
					CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
+
					CC_NUM
+
				};
+
				int cc;
+

				pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
				if (start == '\\') {
+

+
					switch (*pattern) {
+
						case 's':
+
							pattern++;
+
							cc = CC_SPACE;
+
							goto cc_switch;
+
						case 'd':
+
							pattern++;
+
							cc = CC_DIGIT;
+
							goto cc_switch;
+
						case 'w':
+
							pattern++;
+
							reg_addrange(preg, '_', '_');
+
							cc = CC_ALNUM;
+
							goto cc_switch;
+
					}
					pattern += reg_decode_escape(pattern, &start);
					if (start == 0) {
						preg->err = REG_ERR_NULL_CHAR;
@@ -20938,23 +20901,18 @@ static int regatom(regex_t *preg, int *flagp)
						":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:",
						":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:",
					};
-
					enum {
-
						CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
-
						CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
-
						CC_NUM
-
					};
-
					int i;

-
					for (i = 0; i < CC_NUM; i++) {
-
						n = strlen(character_class[i]);
-
						if (strncmp(pattern, character_class[i], n) == 0) {
+
					for (cc = 0; cc < CC_NUM; cc++) {
+
						n = strlen(character_class[cc]);
+
						if (strncmp(pattern, character_class[cc], n) == 0) {

							pattern += n + 1;
							break;
						}
					}
-
					if (i != CC_NUM) {
-
						switch (i) {
+
					if (cc != CC_NUM) {
+
cc_switch:
+
						switch (cc) {
							case CC_ALNUM:
								reg_addrange(preg, '0', '9');

@@ -21809,6 +21767,219 @@ void regfree(regex_t *preg)
}

#endif
+
#include <string.h>
+

+
void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
+
{
+
    Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
+
}
+

+
#if defined(__MINGW32__)
+
#include <sys/stat.h>
+

+
int Jim_Errno(void)
+
{
+
    switch (GetLastError()) {
+
    case ERROR_FILE_NOT_FOUND: return ENOENT;
+
    case ERROR_PATH_NOT_FOUND: return ENOENT;
+
    case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
+
    case ERROR_ACCESS_DENIED: return EACCES;
+
    case ERROR_INVALID_HANDLE: return EBADF;
+
    case ERROR_BAD_ENVIRONMENT: return E2BIG;
+
    case ERROR_BAD_FORMAT: return ENOEXEC;
+
    case ERROR_INVALID_ACCESS: return EACCES;
+
    case ERROR_INVALID_DRIVE: return ENOENT;
+
    case ERROR_CURRENT_DIRECTORY: return EACCES;
+
    case ERROR_NOT_SAME_DEVICE: return EXDEV;
+
    case ERROR_NO_MORE_FILES: return ENOENT;
+
    case ERROR_WRITE_PROTECT: return EROFS;
+
    case ERROR_BAD_UNIT: return ENXIO;
+
    case ERROR_NOT_READY: return EBUSY;
+
    case ERROR_BAD_COMMAND: return EIO;
+
    case ERROR_CRC: return EIO;
+
    case ERROR_BAD_LENGTH: return EIO;
+
    case ERROR_SEEK: return EIO;
+
    case ERROR_WRITE_FAULT: return EIO;
+
    case ERROR_READ_FAULT: return EIO;
+
    case ERROR_GEN_FAILURE: return EIO;
+
    case ERROR_SHARING_VIOLATION: return EACCES;
+
    case ERROR_LOCK_VIOLATION: return EACCES;
+
    case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
+
    case ERROR_HANDLE_DISK_FULL: return ENOSPC;
+
    case ERROR_NOT_SUPPORTED: return ENODEV;
+
    case ERROR_REM_NOT_LIST: return EBUSY;
+
    case ERROR_DUP_NAME: return EEXIST;
+
    case ERROR_BAD_NETPATH: return ENOENT;
+
    case ERROR_NETWORK_BUSY: return EBUSY;
+
    case ERROR_DEV_NOT_EXIST: return ENODEV;
+
    case ERROR_TOO_MANY_CMDS: return EAGAIN;
+
    case ERROR_ADAP_HDW_ERR: return EIO;
+
    case ERROR_BAD_NET_RESP: return EIO;
+
    case ERROR_UNEXP_NET_ERR: return EIO;
+
    case ERROR_NETNAME_DELETED: return ENOENT;
+
    case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
+
    case ERROR_BAD_DEV_TYPE: return ENODEV;
+
    case ERROR_BAD_NET_NAME: return ENOENT;
+
    case ERROR_TOO_MANY_NAMES: return ENFILE;
+
    case ERROR_TOO_MANY_SESS: return EIO;
+
    case ERROR_SHARING_PAUSED: return EAGAIN;
+
    case ERROR_REDIR_PAUSED: return EAGAIN;
+
    case ERROR_FILE_EXISTS: return EEXIST;
+
    case ERROR_CANNOT_MAKE: return ENOSPC;
+
    case ERROR_OUT_OF_STRUCTURES: return ENFILE;
+
    case ERROR_ALREADY_ASSIGNED: return EEXIST;
+
    case ERROR_INVALID_PASSWORD: return EPERM;
+
    case ERROR_NET_WRITE_FAULT: return EIO;
+
    case ERROR_NO_PROC_SLOTS: return EAGAIN;
+
    case ERROR_DISK_CHANGE: return EXDEV;
+
    case ERROR_BROKEN_PIPE: return EPIPE;
+
    case ERROR_OPEN_FAILED: return ENOENT;
+
    case ERROR_DISK_FULL: return ENOSPC;
+
    case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
+
    case ERROR_INVALID_TARGET_HANDLE: return EBADF;
+
    case ERROR_INVALID_NAME: return ENOENT;
+
    case ERROR_PROC_NOT_FOUND: return ESRCH;
+
    case ERROR_WAIT_NO_CHILDREN: return ECHILD;
+
    case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
+
    case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
+
    case ERROR_SEEK_ON_DEVICE: return ESPIPE;
+
    case ERROR_BUSY_DRIVE: return EAGAIN;
+
    case ERROR_DIR_NOT_EMPTY: return EEXIST;
+
    case ERROR_NOT_LOCKED: return EACCES;
+
    case ERROR_BAD_PATHNAME: return ENOENT;
+
    case ERROR_LOCK_FAILED: return EACCES;
+
    case ERROR_ALREADY_EXISTS: return EEXIST;
+
    case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
+
    case ERROR_BAD_PIPE: return EPIPE;
+
    case ERROR_PIPE_BUSY: return EAGAIN;
+
    case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
+
    case ERROR_DIRECTORY: return ENOTDIR;
+
    }
+
    return EINVAL;
+
}
+

+
pidtype waitpid(pidtype pid, int *status, int nohang)
+
{
+
    DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
+
    if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
+

+
        return JIM_BAD_PID;
+
    }
+
    GetExitCodeProcess(pid, &ret);
+
    *status = ret;
+
    CloseHandle(pid);
+
    return pid;
+
}
+

+
int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
+
{
+
    char name[MAX_PATH];
+
    HANDLE handle;
+

+
    if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) {
+
        return -1;
+
    }
+

+
    handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+
            CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0),
+
            NULL);
+

+
    if (handle == INVALID_HANDLE_VALUE) {
+
        goto error;
+
    }
+

+
    Jim_SetResultString(interp, name, -1);
+
    return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT);
+

+
  error:
+
    Jim_SetResultErrno(interp, name);
+
    DeleteFile(name);
+
    return -1;
+
}
+

+
int Jim_OpenForWrite(const char *filename, int append)
+
{
+
    if (strcmp(filename, "/dev/null") == 0) {
+
        filename = "nul:";
+
    }
+
    int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE);
+
    if (fd >= 0 && append) {
+

+
        _lseek(fd, 0L, SEEK_END);
+
    }
+
    return fd;
+
}
+

+
int Jim_OpenForRead(const char *filename)
+
{
+
    if (strcmp(filename, "/dev/null") == 0) {
+
        filename = "nul:";
+
    }
+
    return _open(filename, _O_RDONLY | _O_TEXT, 0);
+
}
+

+
#elif defined(HAVE_UNISTD_H)
+

+

+

+
int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
+
{
+
    int fd;
+
    mode_t mask;
+
    Jim_Obj *filenameObj;
+

+
    if (filename_template == NULL) {
+
        const char *tmpdir = getenv("TMPDIR");
+
        if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
+
            tmpdir = "/tmp/";
+
        }
+
        filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
+
        if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
+
            Jim_AppendString(interp, filenameObj, "/", 1);
+
        }
+
        Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
+
    }
+
    else {
+
        filenameObj = Jim_NewStringObj(interp, filename_template, -1);
+
    }
+

+

+
    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+
#ifdef HAVE_MKSTEMP
+
    fd = mkstemp(filenameObj->bytes);
+
#else
+
    if (mktemp(filenameObj->bytes) == NULL) {
+
        fd = -1;
+
    }
+
    else {
+
        fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC);
+
    }
+
#endif
+
    umask(mask);
+
    if (fd < 0) {
+
        Jim_SetResultErrno(interp, Jim_String(filenameObj));
+
        Jim_FreeNewObj(interp, filenameObj);
+
        return -1;
+
    }
+
    if (unlink_file) {
+
        remove(Jim_String(filenameObj));
+
    }
+

+
    Jim_SetResult(interp, filenameObj);
+
    return fd;
+
}
+

+
int Jim_OpenForWrite(const char *filename, int append)
+
{
+
    return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
+
}
+

+
int Jim_OpenForRead(const char *filename)
+
{
+
    return open(filename, O_RDONLY, 0);
+
}
+

+
#endif

#if defined(_WIN32) || defined(WIN32)
#ifndef STRICT
@@ -21927,6 +22098,32 @@ struct dirent *readdir(DIR * dir)
}
#endif
#endif
+
#include <stdio.h>
+
#include <signal.h>
+

+

+

+

+

+

+
#ifndef SIGPIPE
+
#define SIGPIPE 13
+
#endif
+
#ifndef SIGINT
+
#define SIGINT 2
+
#endif
+

+
const char *Jim_SignalId(int sig)
+
{
+
	static char buf[10];
+
	switch (sig) {
+
		case SIGINT: return "SIGINT";
+
		case SIGPIPE: return "SIGPIPE";
+

+
	}
+
	snprintf(buf, sizeof(buf), "%d", sig);
+
	return buf;
+
}
#ifndef JIM_BOOTSTRAP_LIB_ONLY
#include <errno.h>
#include <string.h>
@@ -21944,10 +22141,30 @@ struct dirent *readdir(DIR * dir)
#define MAX_LINE_LEN 512
#endif

-
char *Jim_HistoryGetline(const char *prompt)
+
#ifdef USE_LINENOISE
+
static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata);
+
static const char completion_callback_assoc_key[] = "interactive-completion";
+
#endif
+

+
char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt)
{
#ifdef USE_LINENOISE
-
    return linenoise(prompt);
+
    struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key);
+
    char *result;
+
    Jim_Obj *objPtr;
+
    long mlmode = 0;
+
    if (compinfo) {
+
        linenoiseSetCompletionCallback(JimCompletionCallback, compinfo);
+
    }
+
    objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE);
+
    if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) {
+
        linenoiseSetMultiLine(mlmode);
+
    }
+

+
    result = linenoise(prompt);
+

+
    linenoiseSetCompletionCallback(NULL, NULL);
+
    return result;
#else
    int len;
    char *line = malloc(MAX_LINE_LEN);
@@ -21991,7 +22208,7 @@ void Jim_HistorySave(const char *filename)
#endif
    linenoiseHistorySave(filename);
#ifdef HAVE_UMASK
-
    mask = umask(mask);
+
    umask(mask);
#endif
#endif
}
@@ -22015,7 +22232,7 @@ struct JimCompletionInfo {
    Jim_Obj *command;
};

-
void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
+
static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
{
    struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
    Jim_Obj *objv[2];
@@ -22036,7 +22253,36 @@ void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void
        }
    }
}
+

+
static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data)
+
{
+
    struct JimCompletionInfo *compinfo = data;
+

+
    Jim_DecrRefCount(interp, compinfo->command);
+

+
    Jim_Free(compinfo);
+
}
+
#endif
+

+
void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj)
+
{
+
#ifdef USE_LINENOISE
+
    if (commandObj) {
+

+
        Jim_IncrRefCount(commandObj);
+
    }
+

+
    Jim_DeleteAssocData(interp, completion_callback_assoc_key);
+

+
    if (commandObj) {
+
        struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo));
+
        compinfo->interp = interp;
+
        compinfo->command = commandObj;
+

+
        Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo);
+
    }
#endif
+
}

int Jim_InteractivePrompt(Jim_Interp *interp)
{
@@ -22044,7 +22290,6 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
    char *history_file = NULL;
#ifdef USE_LINENOISE
    const char *home;
-
    struct JimCompletionInfo compinfo;

    home = getenv("HOME");
    if (home && isatty(STDIN_FILENO)) {
@@ -22054,12 +22299,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
        Jim_HistoryLoad(history_file);
    }

-
    compinfo.interp = interp;
-
    compinfo.command = Jim_NewStringObj(interp, "tcl::autocomplete", -1);
-
    Jim_IncrRefCount(compinfo.command);
-

-

-
    linenoiseSetCompletionCallback(JimCompletionCallback, &compinfo);
+
    Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1));
#endif

    printf("Welcome to Jim version %d.%d\n",
@@ -22092,7 +22332,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
            char state;
            char *line;

-
            line = Jim_HistoryGetline(prompt);
+
            line = Jim_HistoryGetline(interp, prompt);
            if (line == NULL) {
                if (errno == EINTR) {
                    continue;
@@ -22142,11 +22382,6 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
  out:
    Jim_Free(history_file);

-
#ifdef USE_LINENOISE
-
    Jim_DecrRefCount(interp, compinfo.command);
-
    linenoiseSetCompletionCallback(NULL, NULL);
-
#endif
-

    return retcode;
}

modified autosetup/pkg-config.tcl
@@ -15,7 +15,7 @@

use cc

-
module-options {
+
options {
	sysroot:dir => "Override compiler sysroot for pkg-config search path"
}

@@ -73,6 +73,9 @@ proc pkg-config-init {{required 1}} {
			# XXX: It's possible that these should be set only when invoking pkg-config
			global env
			set env(PKG_CONFIG_DIR) ""
+
			# Supposedly setting PKG_CONFIG_LIBDIR means that PKG_CONFIG_PATH is ignored,
+
			# but it doesn't seem to work that way in practice
+
			set env(PKG_CONFIG_PATH) ""
			# Do we need to try /usr/local as well or instead?
			set env(PKG_CONFIG_LIBDIR) $sysroot/usr/lib/pkgconfig:$sysroot/usr/share/pkgconfig
			set env(PKG_CONFIG_SYSROOT_DIR) $sysroot
@@ -95,7 +98,6 @@ proc pkg-config-init {{required 1}} {
## PKG_PANGO_LIBS    to the required libs (--libs-only-l)
## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
## PKG_PANGO_CFLAGS  to the required compiler flags (--cflags)
-
## PKG_PANGO_LIBS_STATIC to the required libs (--libs-only-l -static)
#
# If not found, returns 0.
#
@@ -109,68 +111,30 @@ proc pkg-config {module args} {
		return 0
	}

-
	if {[catch {exec [get-define PKG_CONFIG] --modversion "$module $args"} version]} {
+
	set pkgconfig [get-define PKG_CONFIG]
+

+
	set ret [catch {exec $pkgconfig --modversion "$module $args"} version]
+
	configlog "$pkgconfig --modversion $module $args: $version"
+
	if {$ret} {
		msg-result "not found"
-
		configlog "pkg-config --modversion $module $args: $version"
+
		return 0
+
	}
+
	# Sometimes --modversion succeeds but because of dependencies it isn't usable
+
	# This seems to show up with --cflags
+
	set ret [catch {exec $pkgconfig --cflags $module} cflags]
+
	if {$ret} {
+
		msg-result "unusable ($version - see config.log)"
+
		configlog "$pkgconfig --cflags $module"
+
		configlog $cflags
		return 0
	}
	msg-result $version
	set prefix [feature-define-name $module PKG_]
	define HAVE_${prefix}
	define ${prefix}_VERSION $version
-
	define ${prefix}_LIBS [exec pkg-config --libs-only-l $module]
-

-
# Please enter the commit message for your changes. Lines starting
-
# with '#' will be ignored, and an empty message aborts the commit.
-
#
-
# On branch autosetup
-
# Your branch is up to date with 'origin/autosetup'.
-
#
-
# Changes to be committed:
-
#	modified:   auto.def
-
#
-
# Untracked files:
-
#	..travis.yml.un~
-
#	.Makefile.autosetup.un~
-
#	.auto.def.un~
-
#	autosetup/.pkg-config.tcl.un~
-
#	config.h
-
#	docs/.Makefile.autosetup.un~
-
#	docs/.Makefile.un~
-
#	external/libfetch/.Makefile.autosetup.un~
-
#	external/libfetch/Makefile
-
#	libpkg/.Makefile.autosetup.un~
-
#	libpkg/.Makefile.un~
-
#	mk/.common.mk.un~
-
#	mk/.defs.mk.in.un~
-
#	mk/.defs.mk.un~
-
#	mk/.doc.mk.un~
-
#	mk/doc.mk
-
#	plop.tar.xz
-
#	scripts/.Makefile.autosetup.un~
-
#	scripts/.Makefile.un~
-
#	src/.Makefile.autosetup.un~
-
#	src/.Makefile.un~
-
#	tests/.Makefile.autosetup.un~
-
#	tests/Kyuafile
-
#	tests/checksum
-
#	tests/deps_formula
-
#	tests/frontend/Kyuafile
-
#	tests/frontend/add
-
#	tests/frontend/alias
-
#	tests/frontend/annotate
-
#	tests/frontend/autoremove
-
#	tests/frontend/autoupgrade
-
#	tests/frontend/config
-
#	tests/frontend/configmerge
-
#	tests/frontend/conflicts
-
#	tests/frontend/conflicts-multirepo
-
#	tests/frontend/create
-
#	tests/frontend/delete
-
#	tests/frontend/extract
-
#	tests/frontend/fingerprint
-
	define ${prefix}_LDFLAGS [exec pkg-config --libs-only-L $module]
-
	define ${prefix}_CFLAGS [exec pkg-config --cflags $module]
+
	define ${prefix}_CFLAGS $cflags
+
	define ${prefix}_LIBS [exec $pkgconfig --libs-only-l $module]
+
	define ${prefix}_LDFLAGS [exec $pkgconfig --libs-only-L $module]
	return 1
}

@@ -184,3 +148,20 @@ proc pkg-config-get {module name} {
	set prefix [feature-define-name $module PKG_]
	get-define ${prefix}_${name} ""
}
+

+
# @pkg-config-get-var module variable
+
#
+
# Return the value of the given variable from the given pkg-config module.
+
# The module must already have been successfully detected with pkg-config.
+
# e.g.
+
#
+
## if {[pkg-config harfbuzz >= 2.5]} {
+
##   define harfbuzz_libdir [pkg-config-get-var harfbuzz libdir]
+
## }
+
#
+
# Returns the empty string if the variable isn't defined.
+
proc pkg-config-get-var {module variable} {
+
	set pkgconfig [get-define PKG_CONFIG]
+
	set prefix [feature-define-name $module HAVE_PKG_]
+
	exec $pkgconfig $module --variable $variable
+
}
modified autosetup/system.tcl
@@ -27,7 +27,7 @@ if {[is-defined defaultprefix]} {
	options-defaults [list prefix [get-define defaultprefix]]
}

-
module-options [subst -noc -nob {
+
options {
	host:host-alias =>		{a complete or partial cpu-vendor-opsys for the system where
							the application will run (defaults to the same value as --build)}
	build:build-alias =>	{a complete or partial cpu-vendor-opsys for the system
@@ -48,10 +48,11 @@ module-options [subst -noc -nob {
	sysconfdir:
	sharedstatedir:
	localstatedir:
+
	runstatedir:
	maintainer-mode=0
	dependency-tracking=0
	silent-rules=0
-
}]
+
}

# @check-feature name { script }
#
@@ -132,6 +133,102 @@ proc write-if-changed {file buf {script {}}} {
	}
}

+

+
# @include-file infile mapping
+
#
+
# The core of make-template, called recursively for each @include
+
# directive found within that template so that this proc's result
+
# is the fully-expanded template.
+
#
+
# The mapping parameter is how we expand @varname@ within the template.
+
# We do that inline within this step only for @include directives which
+
# can have variables in the filename arg.  A separate substitution pass
+
# happens when this recursive function returns, expanding the rest of
+
# the variables.
+
#
+
proc include-file {infile mapping} {
+
	# A stack of true/false conditions, one for each nested conditional
+
	# starting with "true"
+
	set condstack {1}
+
	set result {}
+
	set linenum 0
+
	foreach line [split [readfile $infile] \n] {
+
		incr linenum
+
		if {[regexp {^@(if|else|endif)(\s*)(.*)} $line -> condtype condspace condargs]} {
+
			if {$condtype eq "if"} {
+
				if {[string length $condspace] == 0} {
+
					autosetup-error "$infile:$linenum: Invalid expression: $line"
+
				}
+
				if {[llength $condargs] == 1} {
+
					# ABC => [get-define ABC] ni {0 ""}
+
					# !ABC => [get-define ABC] in {0 ""}
+
					lassign $condargs condvar
+
					if {[regexp {^!(.*)} $condvar -> condvar]} {
+
						set op in
+
					} else {
+
						set op ni
+
					}
+
					set condexpr "\[[list get-define $condvar]\] $op {0 {}}"
+
				} else {
+
					# Translate alphanumeric ABC into [get-define ABC] and leave the
+
					# rest of the expression untouched
+
					regsub -all {([A-Z][[:alnum:]_]*)} $condargs {[get-define \1]} condexpr
+
				}
+
				if {[catch [list expr $condexpr] condval]} {
+
					dputs $condval
+
					autosetup-error "$infile:$linenum: Invalid expression: $line"
+
				}
+
				dputs "@$condtype: $condexpr => $condval"
+
			}
+
			if {$condtype ne "if"} {
+
				if {[llength $condstack] <= 1} {
+
					autosetup-error "$infile:$linenum: Error: @$condtype missing @if"
+
				} elseif {[string length $condargs] && [string index $condargs 0] ne "#"} {
+
					autosetup-error "$infile:$linenum: Error: Extra arguments after @$condtype"
+
				}
+
			}
+
			switch -exact $condtype {
+
				if {
+
					# push condval
+
					lappend condstack $condval
+
				}
+
				else {
+
					# Toggle the last entry
+
					set condval [lpop condstack]
+
					set condval [expr {!$condval}]
+
					lappend condstack $condval
+
				}
+
				endif {
+
					if {[llength $condstack] == 0} {
+
						user-notice "$infile:$linenum: Error: @endif missing @if"
+
					}
+
					lpop condstack
+
				}
+
			}
+
			continue
+
		} elseif {[regexp {^@include\s+(.*)} $line -> filearg]} {
+
			set incfile [string map $mapping $filearg]
+
			if {[file exists $incfile]} {
+
				lappend ::autosetup(deps) [file-normalize $incfile]
+
				lappend result {*}[include-file $incfile $mapping]
+
			} else {
+
				user-error "$infile:$linenum: Include file $incfile is missing"
+
			}
+
			continue
+
		} elseif {[regexp {^@define\s+(\w+)\s+(.*)} $line -> var val]} {
+
			define $var $val
+
			continue
+
		}
+
		# Only output this line if the stack contains all "true"
+
		if {"0" in $condstack} {
+
			continue
+
		}
+
		lappend result $line
+
	}
+
	return $result
+
}
+

+

# @make-template template ?outfile?
#
# Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
@@ -141,29 +238,32 @@ proc write-if-changed {file buf {script {}}} {
#
# Each pattern of the form '@define@' is replaced with the corresponding
# "define", if it exists, or left unchanged if not.
-
# 
+
#
# The special value '@srcdir@' is substituted with the relative
# path to the source directory from the directory where the output
# file is created, while the special value '@top_srcdir@' is substituted
# with the relative path to the top level source directory.
#
# Conditional sections may be specified as follows:
-
## @if name == value
+
## @if NAME eq "value"
## lines
## @else
## lines
## @endif
#
-
# Where 'name' is a defined variable name and '@else' is optional.
+
# Where 'NAME' is a defined variable name and '@else' is optional.
+
# Note that variables names *must* start with an uppercase letter.
# If the expression does not match, all lines through '@endif' are ignored.
#
# The alternative forms may also be used:
-
## @if name
-
## @if name != value
+
## @if NAME  (true if the variable is defined, but not empty and not "0")
+
## @if !NAME  (opposite of the form above)
+
## @if <general-tcl-expression>
#
-
# Where the first form is true if the variable is defined, but not empty nor 0.
+
# In the general Tcl expression, any words beginning with an uppercase letter
+
# are translated into [get-define NAME]
#
-
# Currently these expressions can't be nested.
+
# Expressions may be nested
#
proc make-template {template {out {}}} {
	set infile [file join $::autosetup(srcdir) $template]
@@ -191,42 +291,23 @@ proc make-template {template {out {}}} {
	define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir]
	define top_srcdir [relative-path $::autosetup(srcdir) $outdir]

-
	set mapping {}
-
	foreach {n v} [array get ::define] {
-
		lappend mapping @$n@ $v
-
	}
-
	set result {}
-
	foreach line [split [readfile $infile] \n] {
-
		if {[info exists cond]} {
-
			set l [string trimright $line]
-
			if {$l eq "@endif"} {
-
				unset cond
-
				continue
-
			}
-
			if {$l eq "@else"} {
-
				set cond [expr {!$cond}]
-
				continue
-
			}
-
			if {$cond} {
-
				lappend result $line
-
			}
-
			continue
+
	# Build map from global defines to their values so they can be
+
	# substituted into @include file names.
+
	proc build-define-mapping {} {
+
		set mapping {}
+
		foreach {n v} [array get ::define] {
+
			lappend mapping @$n@ $v
		}
-
		if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} {
-
			lassign $expression equal value
-
			set varval [get-define $name ""]
-
			if {$equal eq ""} {
-
				set cond [expr {$varval ni {"" 0}}]
-
			} else {
-
				set cond [expr {$varval eq $value}]
-
				if {$equal ne "=="} {
-
					set cond [expr {!$cond}]
-
				}
-
			}
-
			continue
-
		}
-
		lappend result $line
+
		return $mapping
	}
+
	set mapping [build-define-mapping]
+

+
	set result [include-file $infile $mapping]
+

+
	# Rebuild the define mapping in case we ran across @define
+
	# directives in the template or a file it @included, then
+
	# apply that mapping to the expanded template.
+
	set mapping [build-define-mapping]
	write-if-changed $out [string map $mapping [join $result \n]] {
		msg-result "Created [relative-path $out] from [relative-path $template]"
	}
@@ -301,6 +382,7 @@ if {$prefix ne {/usr}} {
define sysconfdir $sysconfdir

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]]

modified autosetup/tmake.tcl
@@ -11,7 +11,7 @@

use system

-
module-options {}
+
options {}

define CONFIGURED

modified configure
@@ -1,3 +1,3 @@
#!/bin/sh
dir="`dirname "$0"`/autosetup"
-
WRAPPER="$0"; export WRAPPER; exec "`$dir/autosetup-find-tclsh`" "$dir/autosetup" "$@"
+
WRAPPER="$0"; export WRAPPER; exec "`"$dir/autosetup-find-tclsh"`" "$dir/autosetup" "$@"
modified external/Makefile.autosetup
@@ -1,3 +1,9 @@
include @builddir@/mk/defs.mk
-
DIRS=	blake2 picosat linenoise libfetch sqlite libucl liblua msgpuck yxml @libabidir@
+
DIRS=	blake2 picosat linenoise libfetch sqlite libucl liblua msgpuck yxml
+
@if libmachista
+
DIRS+=	libmachista
+
@endif
+
@if libelf-internal
+
DIRS+=	libelf
+
@endif
include $(MK)/dir.mk
modified libpkg/Makefile.autosetup
@@ -109,7 +109,7 @@ LOCAL_LDFLAGS+= -ldl
LOCAL_LDFLAGS+= -lresolv
@endif

-
@if libabidir == libmachista
+
@if libmachista
LOCAL_CFLAGS+= -I$(top_srcdir)/external/libmachista
STATIC_LIBS+=	$(top_builddir)/external/libmachista/libmachista.a
LOCAL_LDFLAGS+=	-L$(top_builddir)/external/libmachista -lmachista_pic \
@@ -120,14 +120,13 @@ SRCS+= pkg_elf.c
LOCAL_LDFLAGS+=	-Wl,--version-script=$(top_builddir)/libpkg/libpkg.ver \
@endif

-
@if libabidir == libelf
+
@if libelf-internal
LOCAL_CFLAGS+= -I$(top_srcdir)/external/libelf
STATIC_LIBS+=	$(top_builddir)/external/libelf/libelf.a
LOCAL_LDFLAGS+=	-L$(top_builddir)/external/libelf -lelf
@endif

-
@if libabidir
-
@else
+
@if libelf-external
LOCAL_LDFLAGS+=	-lelf
@endif

@@ -149,7 +148,7 @@ $(OBJS) $(SHOBJS): $(top_builddir)/pkg_config.h

all: lib$(LIB)_flat.a

-
@if libabidir == libmachista
+
@if libmachista
lib$(LIB)_flat.a:
	libtool -static -o lib$(LIB)_flat.a $(STATIC_LIBS)
@else
modified mk/defs.mk.in
@@ -1,7 +1,7 @@
RANLIB=	@RANLIB@
AR=	@AR@
CC=	@CC@
-
@if coverage == "1"
+
@if coverage
CFLAGS+=	@COVERAGE_CFLAGS@
LDFLAGS+=	@COVERAGE_LDFLAGS@
@endif
modified src/Makefile.autosetup
@@ -65,7 +65,7 @@ OTHER_LIBS+= -ldl
OTHER_LIBS+=	-lresolv
@endif

-
@if libabidir == libmachista
+
@if libmachista
LOCAL_LDFLAGS=	$(LIBPKGFLAT) $(LIBS) $(OTHER_LIBS) -lresolv
STATIC_LDFLAGS=	$(LIBPKGFLAT) $(LIBS) $(OTHER_LIBS) -lresolv
# OSX doesn't support static binaries, sigh
modified tests/Makefile.autosetup
@@ -112,7 +112,7 @@ OTHER_LIBS+= -lresolv
@endif

# Hack to determine we are on osx
-
@if libabidir == libmachista
+
@if libmachista
OTHER_LIBS+=	-lresolv
@endif

modified tests/frontend/test_environment.sh.in
@@ -6,7 +6,7 @@ export PATH=$(atf_get_srcdir)/../../src/:${PATH}
export INSTALL_AS_USER=yes
export PKG_DBDIR=.
export NO_TICK=yes
-
@if coverage == 1
+
@if coverage
export LLVM_PROFILE_FILE=/tmp/pkg.%p.profraw
@endif
jailed=$(sysctl -n security.jail.jailed 2>/dev/null || :)