aboutsummaryrefslogtreecommitdiff
path: root/autosetup
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2011-07-08 04:25:39 +1000
committerSteve Bennett <steveb@workware.net.au>2011-07-08 04:27:33 +1000
commit6bc94edee1076301fd02854c8b3298900896ea49 (patch)
tree83d90b79b82fabd05109149c047765ed14020788 /autosetup
parentd7d212111b459181a89a4c14554f85265c430340 (diff)
downloadjimtcl-6bc94edee1076301fd02854c8b3298900896ea49.zip
jimtcl-6bc94edee1076301fd02854c8b3298900896ea49.tar.gz
jimtcl-6bc94edee1076301fd02854c8b3298900896ea49.tar.bz2
Update to the latest autosetup
Mainly for msys/mingw support Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'autosetup')
-rw-r--r--autosetup/README.autosetup2
-rwxr-xr-xautosetup/autosetup129
-rw-r--r--autosetup/cc-lib.tcl41
-rw-r--r--autosetup/cc.tcl147
-rwxr-xr-xautosetup/find-tclsh7
-rw-r--r--autosetup/jimsh0.c970
6 files changed, 788 insertions, 508 deletions
diff --git a/autosetup/README.autosetup b/autosetup/README.autosetup
index 2237234..6be3d77 100644
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -1 +1 @@
-This is autosetup v0.6.1. See http://msteveb.github.com/autosetup/
+This is autosetup v0.6.2. See http://msteveb.github.com/autosetup/
diff --git a/autosetup/autosetup b/autosetup/autosetup
index 68aa6f8..ef822d6 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -1,10 +1,11 @@
#!/bin/sh
# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
+# vim:se syntax=tcl:
# \
exec $($(dirname "$0")/find-tclsh || echo false) "$0" "$@"
-set autosetup(version) 0.6.1
+set autosetup(version) 0.6.2
# Can be set to 1 to debug early-init problems
set autosetup(debug) 0
@@ -27,7 +28,7 @@ proc main {argv} {
# c. The build directory, where output files are created
# This is also complicated by the fact that autosetup may
- # have been run via the configure wrapper ([env WRAPPER] is set)
+ # have been run via the configure wrapper ([getenv WRAPPER] is set)
# Here are the rules.
# a. This script is $::argv0
@@ -46,7 +47,7 @@ proc main {argv} {
# (a)
set autosetup(dir) [realdir [file dirname [realpath $::argv0]]]
set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]]
- set autosetup(exe) [env WRAPPER $autosetup(prog)]
+ set autosetup(exe) [getenv WRAPPER $autosetup(prog)]
if {$autosetup(installed)} {
set autosetup(libdir) $autosetup(dir)
} else {
@@ -55,7 +56,7 @@ proc main {argv} {
autosetup_add_dep $autosetup(prog)
# (b)
- if {[env WRAPPER ""] eq ""} {
+ if {[getenv WRAPPER ""] eq ""} {
# Invoked directly
set autosetup(srcdir) [pwd]
} else {
@@ -92,6 +93,7 @@ proc main {argv} {
nopager
quiet
timing
+ conf:
}
#parray ::useropts
@@ -100,6 +102,11 @@ proc main {argv} {
exit 0
}
+ # autosetup --conf=alternate-auto.def
+ if {[opt-val conf] ne ""} {
+ set autosetup(autodef) [opt-val conf]
+ }
+
# Debugging output (set this early)
incr autosetup(debug) [opt-bool debug]
incr autosetup(force) [opt-bool force]
@@ -152,7 +159,7 @@ proc main {argv} {
define AUTOREMAKE $cmd
# Log how we were invoked
- configlog "Invoked as: [env WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
+ configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
source $autosetup(autodef)
@@ -283,6 +290,9 @@ proc options-add {opts {header ""}} {
}
}
+# @module-options optionlist
+#
+# Like 'options', but used within a module.
proc module-options {opts} {
set header ""
if {$::autosetup(showhelp) > 1 && [llength $opts]} {
@@ -335,7 +345,11 @@ proc options-show {} {
set max [max $max [string length $opt]]
}
set indent [string repeat " " [expr $max+4]]
-
+ set cols [env COLUMNS 80]
+ catch {
+ lassign [exec stty size] rows cols
+ }
+ incr cols -1
# Now output
foreach {opt desc} $::autosetup(optionhelp) {
if {[string match =* $opt]} {
@@ -346,11 +360,39 @@ proc options-show {} {
if {[string match \n* $desc]} {
puts $desc
} else {
- options-wrap-desc [string trim $desc] 90 " " $indent [expr $max + 2]
+ options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2]
}
}
}
+# @options options-spec
+#
+# Specifies configuration-time options which may be selected by the user
+# and checked with opt-val and opt-bool. The format of options-spec follows.
+#
+# A boolean option is of the form:
+#
+## name[=0|1] => "Description of this boolean option"
+#
+# The default is name=0, meaning that the option is disabled by default.
+# 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:
+#
+## name:[=]value => "Description of this option"
+#
+# 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 is not provided.
+#
+# Undocumented options are also supported by omitting the "=> description.
+# These options are not displayed with --help and can be useful for internal options or as aliases.
+#
+# For example, --disable-lfs is an alias for --disable=largefile:
+#
+## lfs=1 largefile=1 => "Disable large file support"
+#
proc options {optlist} {
# Allow options as a list or args
options-add $optlist "Local Options:"
@@ -371,8 +413,8 @@ proc options {optlist} {
}
proc config_guess {} {
- if {[file executable $::autosetup(dir)/config.guess]} {
- exec $::autosetup(dir)/config.guess
+ if {[file-isexec $::autosetup(dir)/config.guess]} {
+ exec-with-stderr sh $::autosetup(dir)/config.guess
} else {
configlog "No config.guess, so using uname"
string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
@@ -380,8 +422,8 @@ proc config_guess {} {
}
proc config_sub {alias} {
- if {[file executable $::autosetup(dir)/config.sub]} {
- exec $::autosetup(dir)/config.sub $alias
+ if {[file-isexec $::autosetup(dir)/config.sub]} {
+ exec-with-stderr sh $::autosetup(dir)/config.sub $alias
} else {
return $alias
}
@@ -464,7 +506,7 @@ proc get-env {name default} {
if {[dict exists $::autosetup(cmdline) $name]} {
return [dict get $::autosetup(cmdline) $name]
}
- env $name $default
+ getenv $name $default
}
# @env-is-set name
@@ -533,9 +575,10 @@ proc find-executable {name} {
# The empty string is never a valid executable
return 0
}
- foreach p [split [env PATH .] :] {
+ foreach p [split-path] {
+ dputs "Looking for $name in $p"
set exec [file join $p $name]
- if {[file isfile $exec] && [file executable $exec]} {
+ if {[file-isexec $exec]} {
dputs "Found $name -> $exec"
return 1
}
@@ -713,7 +756,6 @@ proc realdir {dir} {
# Follow symlinks until we get to something which is not a symlink
proc realpath {path} {
- #puts -nonewline "$path -> "
while {1} {
if {[catch {
set path [file link $path]
@@ -722,7 +764,6 @@ proc realpath {path} {
break
}
}
- #puts "$path"
return $path
}
@@ -1412,12 +1453,42 @@ set modsource(misc) {
# All rights reserved
# Module containing misc procs useful to modules
+# Largely for platform compatibility
+
+set autosetup(istcl) [info exists ::tcl_library]
+set autosetup(iswin) [string equal windows $tcl_platform(platform)]
+
+if {$autosetup(iswin)} {
+ # mingw/windows separates $PATH with semicolons
+ # and doesn't have an executable bit
+ proc split-path {} {
+ split [getenv PATH .] {;}
+ }
+ proc file-isexec {exec} {
+ # Basic test for windows. We ignore .bat
+ if {[file isfile $exec] || [file isfile $exec.exe]} {
+ return 1
+ }
+ return 0
+ }
+} else {
+ # unix separates $PATH with colons and has and executable bit
+ proc split-path {} {
+ split [env PATH .] :
+ }
+ proc file-isexec {exec} {
+ file executable $exec
+ }
+}
-set ::autosetup(istcl) [info exists ::tcl_library]
+# Assume that exec can return stdout and stderr
+proc exec-with-stderr {args} {
+ exec {*}$args 2>@1
+}
-# Tcl doesn't have the env command
-if {$::autosetup(istcl)} {
- proc env {var args} {
+if {$autosetup(istcl)} {
+ # Tcl doesn't have the env command
+ proc getenv {name args} {
if {[info exists ::env($var)]} {
return $::env($var)
}
@@ -1426,6 +1497,24 @@ if {$::autosetup(istcl)} {
}
return -code error "environment variable \"$var\" does not exist"
}
+} elseif {$autosetup(iswin)} {
+ # On Windows, backslash convert all environment variables
+ # (Assume that Tcl does this for us)
+ proc getenv {name args} {
+ string map {\\ /} [env $name {*}$args]
+ }
+ # Jim uses system() for exec under mingw, so
+ # we need to fetch the output ourselves
+ proc exec-with-stderr {args} {
+ set tmpfile /tmp/autosetup.[format %05x [rand 10000]].tmp
+ set rc [catch [list exec {*}$args >$tmpfile 2>&1] result]
+ set result [readfile $tmpfile]
+ file delete $tmpfile
+ return -code $rc $result
+ }
+} else {
+ # Jim on unix is simple
+ alias getenv env
}
# In case 'file normalize' doesn't exist
diff --git a/autosetup/cc-lib.tcl b/autosetup/cc-lib.tcl
index e769db9..f4fb0db 100644
--- a/autosetup/cc-lib.tcl
+++ b/autosetup/cc-lib.tcl
@@ -34,3 +34,44 @@ proc cc-check-lfs {} {
define-feature lfs $lfs
return $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.
+#
+# Returns 1 if determined, or 0 if not.
+#
+proc cc-check-endian {} {
+ cc-check-includes sys/types.h sys/param.h
+ set rc 0
+ msg-checking "Checking endian..."
+ cc-with {-includes {sys/types.h sys/param.h}} {
+ if {[cctest -code {
+ #if! defined(BIG_ENDIAN) || !defined(BYTE_ORDER)
+ #error unknown
+ #elif BYTE_ORDER != BIG_ENDIAN
+ #error little
+ #endif
+ }]} {
+ define-feature big-endian
+ msg-result "big"
+ set rc 1
+ } elseif {[cctest -code {
+ #if! defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER)
+ #error unknown
+ #elif BYTE_ORDER != LITTLE_ENDIAN
+ #error big
+ #endif
+ }]} {
+ define-feature little-endian
+ msg-result "little"
+ set rc 1
+ } else {
+ msg-result "unknown"
+ }
+ }
+ return $rc
+}
diff --git a/autosetup/cc.tcl b/autosetup/cc.tcl
index 54c4e8f..c95f8dd 100644
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -59,6 +59,13 @@ proc cctest_define {name} {
cctest -code "#ifndef $name\n#error not defined\n#endif"
}
+# Checks for the existence of the given name either as
+# a macro (#define) or an rvalue (such as an enum)
+#
+proc cctest_decl {name} {
+ cctest -code "#ifndef $name\n(void)$name;\n#endif"
+}
+
# @cc-check-sizeof type ...
#
# Checks the size of the given types (between 1 and 32, inclusive).
@@ -128,6 +135,27 @@ proc cc-check-defines {args} {
}
}
+# @cc-check-decls name ...
+#
+# Checks that each given name is either a preprocessor symbol or rvalue
+# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx
+# rather than HAVE_xxx
+proc cc-check-decls {args} {
+ set ret 1
+ foreach name $args {
+ msg-checking "Checking for $name..."
+ set r [cctest_decl $name]
+ define-feature "decl $name" $r
+ if {$r} {
+ msg-result "ok"
+ } else {
+ msg-result "not found"
+ set ret 0
+ }
+ }
+ return $ret
+}
+
# @cc-check-functions function ...
#
# Checks that the given functions exist (can be linked)
@@ -149,7 +177,7 @@ proc cc-check-members {args} {
# @cc-check-function-in-lib function libs ?otherlibs?
#
-# Checks that the given given function can be found on one of the libs.
+# Checks that the given given function can be found in one of the libs.
#
# First checks for no library required, then checks each of the libraries
# in turn.
@@ -158,7 +186,7 @@ proc cc-check-members {args} {
# to -l$lib where the function was found, or "" if no library required.
# In addition, -l$lib is added to the LIBS define.
#
-# If additional libraries may be needed to linked, they should be specified
+# If additional libraries may be needed for linking, they should be specified
# as $extralibs as "-lotherlib1 -lotherlib2".
# These libraries are not automatically added to LIBS.
#
@@ -299,6 +327,22 @@ proc cc-get-settings {} {
return $::autosetup(ccsettings)
}
+# Similar to cc-add-settings, but each given setting
+# simply replaces the existing value.
+#
+# Returns the previous settings
+proc cc-update-settings {args} {
+ set prev [cc-get-settings]
+ array set new $prev
+
+ foreach {name value} $args {
+ set new($name) $value
+ }
+ cc-store-settings $new
+
+ return $prev
+}
+
# @cc-with settings ?{ script }?
#
# Sets the given 'cctest' settings and then runs the tests in 'script'.
@@ -388,10 +432,17 @@ proc cctest {args} {
set lines $opts(-source)
} else {
foreach i $opts(-includes) {
+ if {$opts(-code) ne "" && ![feature-checked $i]} {
+ # Compiling real code with an unchecked header file
+ # Quickly (and silently) check for it now
+
+ # Remove all -includes from settings before checking
+ set saveopts [cc-update-settings -includes {}]
+ msg-quiet cc-check-includes $i
+ cc-store-settings $saveopts
+ }
if {$opts(-code) eq "" || [have-feature $i]} {
lappend source "#include <$i>"
- } elseif {![feature-checked $i]} {
- user-notice "Warning: using #include <$i> which has not been checked -- ignoring"
}
}
lappend source {*}$opts(-declare)
@@ -435,6 +486,7 @@ proc cctest {args} {
# complete source to be compiled. Get the result from cache if
# we can
if {[info exists ::cc_cache($cmdline,$lines)]} {
+ msg-checking "(cached) "
set ok $::cc_cache($cmdline,$lines)
if {$::autosetup(debug)} {
configlog "From cache (ok=$ok): [join $cmdline]"
@@ -448,7 +500,7 @@ proc cctest {args} {
writefile $src $lines\n
set ok 1
- if {[catch {exec {*}$cmdline 2>@1} result errinfo]} {
+ if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} {
configlog "Failed: [join $cmdline]"
configlog $result
configlog "============"
@@ -471,51 +523,73 @@ proc cctest {args} {
return $ok
}
-# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?unquoted-patterns=SIZEOF_*?
+# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
+#
+# Deprecated - see make-config-header
+proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
+ user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
+ make-config-header $file -auto $autopatterns -bare $barepatterns
+}
+
+# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
#
# Examines all defined variables which match the given patterns
# and writes an include file, $file, which defines each of these.
-# Variables which match 'auto-patterns' are output as follows:
+# Variables which match '-auto' are output as follows:
# - defines which have the value "0" are ignored.
# - defines which have integer values are defined as the integer value.
# - any other value is defined as a string, e.g. "value"
+# Variables which match '-bare' are defined as-is.
+# Variables which match '-str' are defined as a string, e.g. "value"
+# Variables which match '-none' are omitted.
+#
+# Note that order is important. The first pattern which matches is selected
+# Default behaviour is:
+#
+# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
#
-# Variables which match 'unquoted-patterns' are defined unquoted.
-#
# If the file would be unchanged, it is not written.
-proc make-autoconf-h {file {autopatterns {HAVE_*}} {unquotedpatterns {SIZEOF_*}}} {
+proc make-config-header {file args} {
set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
file mkdir [file dirname $file]
set lines {}
lappend lines "#ifndef $guard"
lappend lines "#define $guard"
- # Work out the type of each variable
- array set types {}
- foreach pattern $autopatterns {
- foreach n [array names ::define $pattern] {
- set types($n) auto
- }
- }
- foreach pattern $unquotedpatterns {
- foreach n [array names ::define $pattern] {
- set types($n) unquoted
- }
- }
- foreach n [lsort [array names types]] {
- if {$types($n) eq "auto"} {
- # Automatically determine the type
- if {$::define($n) eq "0"} {
- lappend lines "/* #undef $n */"
+ # Add some defaults
+ lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_*
+
+ foreach n [lsort [dict keys [all-defines]]] {
+ set value [get-define $n]
+ set type [calc-define-output-type $n $args]
+ switch -exact -- $type {
+ -bare {
+ # Just output the value unchanged
+ }
+ -none {
continue
}
- if {![string is integer -strict $::define($n)]} {
- lappend lines "#define $n \"$::define($n)\""
+ -str {
+ set value \"$value\"
+ }
+ -auto {
+ # Automatically determine the type
+ if {$value eq "0"} {
+ lappend lines "/* #undef $n */"
+ continue
+ }
+ if {![string is integer -strict $value]} {
+ set value \"$value\"
+ }
+ }
+ "" {
continue
}
+ default {
+ autosetup-error "Unknown type in make-config-header: $type"
+ }
}
- # Unquoted
- lappend lines "#define $n $::define($n)"
+ lappend lines "#define $n $value"
}
lappend lines "#endif"
set buf [join $lines \n]
@@ -524,6 +598,17 @@ proc make-autoconf-h {file {autopatterns {HAVE_*}} {unquotedpatterns {SIZEOF_*}}
}
}
+proc calc-define-output-type {name spec} {
+ foreach {type patterns} $spec {
+ foreach pattern $patterns {
+ if {[string match $pattern $name]} {
+ return $type
+ }
+ }
+ }
+ return ""
+}
+
# Initialise some values from the environment or commandline or default settings
foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"} {CC_FOR_BUILD cc}} {
lassign $i var default
diff --git a/autosetup/find-tclsh b/autosetup/find-tclsh
index 5c01fcc..d133513 100755
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -7,5 +7,8 @@ for tclsh in jimsh tclsh8.5 tclsh8.6 jimsh0; do
$tclsh "$d/test-tclsh" 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
-${CC_FOR_BUILD:-cc} -o "$d/jimsh0" "$d/jimsh0.c" || exit 1
-"$d/jimsh0" "$d/test-tclsh"
+for cc in ${CC_FOR_BUILD:-cc} gcc; do
+ $cc -o "$d/jimsh0" "$d/jimsh0.c" 2>/dev/null || continue
+ "$d/jimsh0" "$d/test-tclsh" && exit 0
+done
+echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index c2e9435..4b831d0 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -3,7 +3,6 @@
#define JIM_TCL_COMPAT
#define JIM_REFERENCES
#define JIM_ANSIC
-#define HAVE_VFORK
#define JIM_REGEXP
#define HAVE_NO_AUTOCONF
#define _JIMAUTOCONF_H
@@ -19,10 +18,14 @@
#define jim_ext_array
#define jim_ext_stdlib
#define jim_ext_tclcompat
-#ifdef __MINGW32__
-#define MKDIR_ONE_ARG
+#if defined(__MINGW32__)
+#define TCL_PLATFORM_OS "mingw"
+#define TCL_PLATFORM_PLATFORM "windows"
+#define HAVE_MKDIR_ONE_ARG
#define HAVE_SYSTEM
#else
+#define TCL_PLATFORM_OS "unknown"
+#define TCL_PLATFORM_PLATFORM "unix"
#define HAVE_VFORK
#define HAVE_WAITPID
#endif
@@ -327,7 +330,10 @@ typedef struct Jim_Stack {
typedef struct Jim_HashEntry {
const void *key;
- void *val;
+ union {
+ void *val;
+ int intval;
+ } u;
struct Jim_HashEntry *next;
} Jim_HashEntry;
@@ -362,13 +368,13 @@ typedef struct Jim_HashTableIterator {
/* ------------------------------- Macros ------------------------------------*/
#define Jim_FreeEntryVal(ht, entry) \
if ((ht)->type->valDestructor) \
- (ht)->type->valDestructor((ht)->privdata, (entry)->val)
+ (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
#define Jim_SetHashVal(ht, entry, _val_) do { \
if ((ht)->type->valDup) \
- entry->val = (ht)->type->valDup((ht)->privdata, _val_); \
+ entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
else \
- entry->val = (_val_); \
+ entry->u.val = (_val_); \
} while(0)
#define Jim_FreeEntryKey(ht, entry) \
@@ -1176,14 +1182,14 @@ typedef struct regexp {
int err; /* Any error which occurred during compile */
int regstart; /* Internal use only. */
int reganch; /* Internal use only. */
- const int *regmust; /* Internal use only. */
+ int regmust; /* Internal use only. */
int regmlen; /* Internal use only. */
int *program; /* Allocated */
/* working state - compile */
const char *regparse; /* Input-scan pointer. */
- int *regcode; /* Code-emit pointer; &regdummy = don't. */
- long regsize; /* Code size. */
+ int p; /* Current output pos in program */
+ int proglen; /* Allocated program size */
/* working state - exec */
int eflags; /* Flags used when executing */
@@ -1285,7 +1291,16 @@ int Jim_globInit(Jim_Interp *interp)
" }\n"
"\n"
"\n"
-" foreach name [readdir -nocomplain $dir] {\n"
+" if {[string match {*[*?]*} $pattern]} {\n"
+"\n"
+" set files [readdir -nocomplain $dir]\n"
+" } elseif {[file isdir $dir] && [file exists $dir/$pattern]} {\n"
+" set files [list $pattern]\n"
+" } else {\n"
+" set files \"\"\n"
+" }\n"
+"\n"
+" foreach name $files {\n"
" if {[string match $pattern $name]} {\n"
"\n"
" if {[string index $name 0] eq \".\" && [string index $pattern 0] ne \".\"} {\n"
@@ -1300,54 +1315,54 @@ int Jim_globInit(Jim_Interp *interp)
"\n"
"\n"
"\n"
-" local proc glob.do {dir rem} {\n"
"\n"
"\n"
-" set i [string first / $rem]\n"
-" if {$i < 0} {\n"
-" set pattern $rem\n"
-" set rempattern \"\"\n"
-" } else {\n"
-" set pattern [string range $rem 0 $i-1]\n"
-" set rempattern [string range $rem $i+1 end]\n"
-" }\n"
+" proc glob.expandbraces {pattern} {\n"
"\n"
"\n"
-" set sep /\n"
-" set globdir $dir\n"
-" if {[string match \"*/\" $dir]} {\n"
-" set sep \"\"\n"
-" } elseif {$dir eq \"\"} {\n"
-" set globdir .\n"
-" set sep \"\"\n"
+" if {[set fb [string first \"\\{\" $pattern]] < 0} {\n"
+" return $pattern\n"
" }\n"
+" if {[set nb [string first \"\\}\" $pattern $fb]] < 0} {\n"
+" return $pattern\n"
+" }\n"
+" set before [string range $pattern 0 $fb-1]\n"
+" set braced [string range $pattern $fb+1 $nb-1]\n"
+" set after [string range $pattern $nb+1 end]\n"
"\n"
-" set result {}\n"
-"\n"
-"\n"
+" lmap part [split $braced ,] {\n"
+" set pat $before$part$after\n"
+" }\n"
+" }\n"
"\n"
"\n"
-" if {[set fb [string first \"\\{\" $pattern]] >= 0} {\n"
-" if {[set nb [string first \"\\}\" $pattern $fb]] >= 0} {\n"
-" set before [string range $pattern 0 $fb-1]\n"
-" set braced [string range $pattern $fb+1 $nb-1]\n"
-" set after [string range $pattern $nb+1 end]\n"
+" proc glob.glob {pattern} {\n"
+" set dir [file dirname $pattern]\n"
+" if {$dir eq $pattern} {\n"
"\n"
-" foreach part [split $braced ,] {\n"
-" lappend result {*}[glob.do $dir $before$part$after]\n"
-" }\n"
-" return $result\n"
-" }\n"
+" return [list $dir]\n"
" }\n"
"\n"
"\n"
-" foreach f [glob.readdir_pattern $globdir $pattern] {\n"
-" if {$rempattern eq \"\"} {\n"
+" set dirlist [glob.glob $dir]\n"
+" set pattern [file tail $pattern]\n"
"\n"
-" lappend result $dir$sep$f\n"
-" } else {\n"
"\n"
-" lappend result {*}[glob.do $dir$sep$f $rempattern]\n"
+" set result {}\n"
+" foreach dir $dirlist {\n"
+" set globdir $dir\n"
+" if {[string match \"*/\" $dir]} {\n"
+" set sep \"\"\n"
+" } elseif {$dir eq \".\"} {\n"
+" set globdir \"\"\n"
+" set sep \"\"\n"
+" } else {\n"
+" set sep /\n"
+" }\n"
+" foreach pat [glob.expandbraces $pattern] {\n"
+" foreach name [glob.readdir_pattern $dir $pat] {\n"
+" lappend result $globdir$sep$name\n"
+" }\n"
" }\n"
" }\n"
" return $result\n"
@@ -1363,13 +1378,7 @@ int Jim_globInit(Jim_Interp *interp)
"\n"
" set result {}\n"
" foreach pattern $args {\n"
-" if {$pattern eq \"/\"} {\n"
-" lappend result /\n"
-" } elseif {[string match \"/*\" $pattern]} {\n"
-" lappend result {*}[glob.do / [string range $pattern 1 end]]\n"
-" } else {\n"
-" lappend result {*}[glob.do \"\" $pattern]\n"
-" }\n"
+" lappend result {*}[glob.glob $pattern]\n"
" }\n"
"\n"
" if {$nocomplain == 0 && [llength $result] == 0} {\n"
@@ -1591,6 +1600,9 @@ int Jim_tclcompatInit(Jim_Interp *interp)
" -bu* {\n"
" $f buffering $v\n"
" }\n"
+" -tr* {\n"
+"\n"
+" }\n"
" default {\n"
" return -code error \"fconfigure: unknown option $n\"\n"
" }\n"
@@ -1812,6 +1824,14 @@ int Jim_tclcompatInit(Jim_Interp *interp)
"proc throw {code {msg \"\"}} {\n"
" return -code $code $msg\n"
"}\n"
+"\n"
+"\n"
+"proc {file delete force} {path} {\n"
+" foreach e [readdir $path] {\n"
+" file delete -force $path/$e\n"
+" }\n"
+" file delete $path\n"
+"}\n"
,"tclcompat.tcl", 1);
}
@@ -1861,7 +1881,7 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#include <fcntl.h>
-#if !defined(JIM_ANSIC)
+#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 <arpa/inet.h>
@@ -1869,6 +1889,8 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
+#else
+#define JIM_ANSIC
#endif
@@ -4037,6 +4059,12 @@ static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
else if (p == path) {
Jim_SetResultString(interp, "/", -1);
}
+#if defined(__MINGW32__)
+ else if (p[-1] == ':') {
+ /* z:/dir => z:/ */
+ Jim_SetResultString(interp, path, p - path + 1);
+ }
+#endif
else {
Jim_SetResultString(interp, path, p - path);
}
@@ -4122,6 +4150,12 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
/* Absolute component, so go back to the start */
last = newname;
}
+#if defined(__MINGW32__)
+ else if (strchr(part, ':')) {
+ /* Absolute compontent on mingw, so go back to the start */
+ last = newname;
+ }
+#endif
/* Add a slash if needed */
if (last != newname) {
@@ -4185,14 +4219,24 @@ static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
+ int force = Jim_CompareStringImmediate(interp, argv[0], "-force");
+
+ if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) {
+ argc++;
+ argv--;
+ }
+
while (argc--) {
const char *path = Jim_String(argv[0]);
if (unlink(path) == -1 && errno != ENOENT) {
if (rmdir(path) == -1) {
- Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
- strerror(errno));
- return JIM_ERR;
+ /* Maybe try using the script helper */
+ if (!force || Jim_EvalObjPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
+ Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
+ strerror(errno));
+ return JIM_ERR;
+ }
}
}
argv++;
@@ -4200,7 +4244,7 @@ static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
-#ifdef MKDIR_ONE_ARG
+#ifdef HAVE_MKDIR_ONE_ARG
#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME)
#else
#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755)
@@ -4574,11 +4618,11 @@ static const jim_subcmd_type file_command_table[] = {
.description = "Does file exist"
},
{ .cmd = "delete",
- .args = "name ...",
+ .args = "?-force|--? name ...",
.function = file_cmd_delete,
.minargs = 1,
.maxargs = -1,
- .description = "Deletes the files or empty directories"
+ .description = "Deletes the files or directories (must be empty unless -force)"
},
{ .cmd = "mkdir",
.args = "dir ...",
@@ -4696,6 +4740,15 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_SetResultString(interp, "Failed to get pwd", -1);
return JIM_ERR;
}
+#if defined(__MINGW32__)
+ {
+ /* Try to keep backlashes out of paths */
+ char *p = cwd;
+ while ((p = strchr(p, '\\')) != NULL) {
+ *p++ = '/';
+ }
+ }
+#endif
Jim_SetResultString(interp, cwd, -1);
@@ -5577,15 +5630,6 @@ badargs:
(void)signal(SIGPIPE, SIG_IGN);
}
- /*
- * Enlarge the wait table if there isn't enough space for a new
- * entry.
- */
- if (table->used == table->size) {
- table->size += WAIT_TABLE_GROW_BY;
- table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
- }
-
/* Need to do this befor vfork() */
if (pipe_dup_err) {
errorId = outputId;
@@ -5623,6 +5667,16 @@ badargs:
}
/* parent */
+
+ /*
+ * Enlarge the wait table if there isn't enough space for a new
+ * entry.
+ */
+ if (table->used == table->size) {
+ table->size += WAIT_TABLE_GROW_BY;
+ table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
+ }
+
table->info[table->used].pid = pid;
table->info[table->used].flags = 0;
table->used++;
@@ -6412,6 +6466,9 @@ static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
static int JimSign(jim_wide w);
static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr);
+static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
+static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
+
static const Jim_HashTableType JimVariablesHashTableType;
@@ -7402,9 +7459,8 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
* Tcl scripts and lists. */
struct JimParserCtx
{
- const char *prg; /* Program text */
const char *p; /* Pointer to the point of the program we are parsing */
- int len; /* Left length of 'prg' */
+ int len; /* Remaining length */
int linenr; /* Current line number */
const char *tstart;
const char *tend; /* Returned token is at tstart-tend in 'prg'. */
@@ -7414,6 +7470,15 @@ struct JimParserCtx
int state; /* Parser state */
int comment; /* Non zero if the next chars may be a comment. */
char missing; /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */
+ int missingline; /* Line number starting the missing token */
+};
+
+/**
+ * Results of missing quotes, braces, etc. from parsing.
+ */
+struct JimParseResult {
+ char missing; /* From JimParserCtx.missing */
+ int line; /* From JimParserCtx.missingline */
};
static int JimParseScript(struct JimParserCtx *pc);
@@ -7435,7 +7500,6 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
* number of the first line contained in the program. */
static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
{
- pc->prg = prg;
pc->p = prg;
pc->len = len;
pc->tstart = NULL;
@@ -7447,6 +7511,7 @@ static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int
pc->linenr = linenr;
pc->comment = 1;
pc->missing = ' ';
+ pc->missingline = linenr;
}
static int JimParseScript(struct JimParserCtx *pc)
@@ -7622,6 +7687,7 @@ static void JimParseSubBrace(struct JimParserCtx *pc)
pc->len--;
}
pc->missing = '{';
+ pc->missingline = pc->tline;
pc->tend = pc->p - 1;
}
@@ -7638,6 +7704,7 @@ static void JimParseSubBrace(struct JimParserCtx *pc)
static int JimParseSubQuote(struct JimParserCtx *pc)
{
int tt = JIM_TT_STR;
+ int line = pc->tline;
/* Skip the quote */
pc->p++;
@@ -7677,6 +7744,7 @@ static int JimParseSubQuote(struct JimParserCtx *pc)
pc->len--;
}
pc->missing = '"';
+ pc->missingline = line;
pc->tend = pc->p - 1;
return tt;
}
@@ -7691,6 +7759,7 @@ static void JimParseSubCmd(struct JimParserCtx *pc)
{
int level = 1;
int startofword = 1;
+ int line = pc->tline;
/* Skip the bracket */
pc->p++;
@@ -7740,6 +7809,7 @@ static void JimParseSubCmd(struct JimParserCtx *pc)
pc->len--;
}
pc->missing = '[';
+ pc->missingline = line;
pc->tend = pc->p - 1;
}
@@ -7871,6 +7941,8 @@ static int JimParseStr(struct JimParserCtx *pc)
pc->state = JIM_PS_QUOTE;
pc->p++;
pc->len--;
+ /* In case the end quote is missing */
+ pc->missingline = pc->tline;
}
pc->tstart = pc->p;
pc->tline = pc->linenr;
@@ -8182,11 +8254,11 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
/* Parses the given string to determine if it represents a complete script.
*
- * This is useful for interactive shells implementation, for [info complete]
- * and is used by source/Jim_EvalFile().
+ * This is useful for interactive shells implementation, for [info complete].
*
* If 'stateCharPtr' != NULL, the function stores ' ' on complete script,
* '{' on scripts incomplete missing one or more '}' to be balanced.
+ * '[' on scripts incomplete missing one or more ']' to be balanced.
* '"' on scripts incomplete missing a '"' char.
*
* If the script is complete, 1 is returned, otherwise 0.
@@ -9232,7 +9304,7 @@ static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
static const Jim_ObjType scriptObjType = {
"script",
@@ -9629,39 +9701,48 @@ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
/* This method takes the string representation of an object
* as a Tcl script, and generates the pre-parsed internal representation
* of the script. */
-int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
{
int scriptTextLen;
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
struct JimParserCtx parser;
- struct ScriptObj *script = Jim_Alloc(sizeof(*script));
+ struct ScriptObj *script;
ParseTokenList tokenlist;
+ int line = 1;
/* Try to get information about filename / line number */
if (objPtr->typePtr == &sourceObjType) {
- script->fileName = Jim_GetSharedString(interp, objPtr->internalRep.sourceValue.fileName);
- script->line = objPtr->internalRep.sourceValue.lineNumber;
- }
- else {
- script->fileName = NULL;
- script->line = 1;
+ line = objPtr->internalRep.sourceValue.lineNumber;
}
/* Initially parse the script into tokens (in tokenlist) */
ScriptTokenListInit(&tokenlist);
- JimParserInit(&parser, scriptText, scriptTextLen, script->line);
+ JimParserInit(&parser, scriptText, scriptTextLen, line);
while (!parser.eof) {
JimParseScript(&parser);
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
parser.tline);
}
+ if (result && parser.missing != ' ') {
+ ScriptTokenListFree(&tokenlist);
+ result->missing = parser.missing;
+ result->line = parser.missingline;
+ return JIM_ERR;
+ }
+
/* Add a final EOF token */
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
/* Create the "real" script tokens from the initial token list */
- script->substFlags = 0;
+ script = Jim_Alloc(sizeof(*script));
+ memset(script, 0, sizeof(*script));
script->inUse = 1;
+ script->line = line;
+ if (objPtr->typePtr == &sourceObjType) {
+ script->fileName = Jim_GetSharedString(interp, objPtr->internalRep.sourceValue.fileName);
+ }
+
ScriptObjAddTokens(interp, script, &tokenlist);
/* No longer need the token list */
@@ -9684,7 +9765,7 @@ ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
struct ScriptObj *script = Jim_GetIntRepPtr(objPtr);
if (objPtr->typePtr != &scriptObjType || script->substFlags) {
- SetScriptFromAny(interp, objPtr);
+ SetScriptFromAny(interp, objPtr, NULL);
}
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
}
@@ -9872,8 +9953,8 @@ static int JimCreateProcedure(Jim_Interp *interp, const char *cmdName,
if (he && interp->local) {
/* Just push this proc over the top of the previous one */
- cmdPtr->u.proc.prevCmd = he->val;
- he->val = cmdPtr;
+ cmdPtr->u.proc.prevCmd = he->u.val;
+ he->u.val = cmdPtr;
}
else {
if (he) {
@@ -9927,8 +10008,8 @@ int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newNa
}
/* Add the new name first */
- JimIncrCmdRefCount(he->val);
- Jim_AddHashEntry(&interp->commands, newName, he->val);
+ JimIncrCmdRefCount(he->u.val);
+ Jim_AddHashEntry(&interp->commands, newName, he->u.val);
/* Now remove the old name */
Jim_DeleteHashEntry(&interp->commands, oldName);
@@ -9968,7 +10049,7 @@ int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &commandObjType;
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
- objPtr->internalRep.cmdValue.cmdPtr = (void *)he->val;
+ objPtr->internalRep.cmdValue.cmdPtr = (void *)he->u.val;
return JIM_OK;
}
@@ -10124,7 +10205,7 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &variableObjType;
objPtr->internalRep.varValue.callFrameId = framePtr->id;
- objPtr->internalRep.varValue.varPtr = (void *)he->val;
+ objPtr->internalRep.varValue.varPtr = (void *)he->u.val;
return JIM_OK;
}
@@ -10687,10 +10768,10 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
he = table[i];
while (he != NULL) {
Jim_HashEntry *nextEntry = he->next;
- Jim_Var *varPtr = (void *)he->val;
+ Jim_Var *varPtr = (void *)he->u.val;
Jim_DecrRefCount(interp, varPtr->objPtr);
- Jim_Free(he->val);
+ Jim_Free(he->u.val);
Jim_Free((void *)he->key); /* ATTENTION: const cast */
Jim_Free(he);
table[i] = NULL;
@@ -10862,7 +10943,7 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
return JIM_ERR;
}
- refPtr = he->val;
+ refPtr = he->u.val;
/* Free the old internal repr and set the new one. */
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &referenceObjType;
@@ -11056,7 +11137,7 @@ int Jim_Collect(Jim_Interp *interp)
collected++;
/* Drop the reference, but call the
* finalizer first if registered. */
- refPtr = he->val;
+ refPtr = he->u.val;
if (refPtr->finalizerCmdNamePtr) {
char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1);
Jim_Obj *objv[3], *oldResult;
@@ -11132,33 +11213,16 @@ Jim_Interp *Jim_CreateInterp(void)
{
Jim_Interp *i = Jim_Alloc(sizeof(*i));
- i->errorLine = 0;
+ memset(i, 0, sizeof(*i));
+
i->errorFileName = Jim_StrDup("");
- i->addStackTrace = 0;
i->maxNestingDepth = JIM_MAX_NESTING_DEPTH;
- i->returnCode = JIM_OK;
- i->returnLevel = 0;
- i->exitCode = 0;
- i->procEpoch = 0;
- i->callFrameEpoch = 0;
- i->liveList = i->freeList = NULL;
- i->referenceNextId = 0;
- i->lastCollectId = 0;
i->lastCollectTime = time(NULL);
- i->freeFramesList = NULL;
- i->prngState = NULL;
- i->id = 0;
- i->sigmask = 0;
- i->signal_level = 0;
- i->signal_set_result = NULL;
- i->localProcs = NULL;
- i->loadHandles = NULL;
/* Note that we can create objects only after the
* interpreter liveList and freeList pointers are
* initialized to NULL. */
Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i);
- i->local = 0;
#ifdef JIM_REFERENCES
Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i);
#endif
@@ -11172,7 +11236,6 @@ Jim_Interp *Jim_CreateInterp(void)
i->result = i->emptyObj;
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
- i->unknown_called = 0;
i->errorProc = i->emptyObj;
i->currentScriptObj = Jim_NewEmptyStringObj(i);
Jim_IncrRefCount(i->emptyObj);
@@ -11476,7 +11539,7 @@ void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
if (entryPtr != NULL) {
- AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->val;
+ AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
return assocEntryPtr->data;
}
@@ -11515,33 +11578,26 @@ const char *Jim_GetSharedString(Jim_Interp *interp, const char *str)
if (he == NULL) {
char *strCopy = Jim_StrDup(str);
- Jim_AddHashEntry(&interp->sharedStrings, strCopy, (void *)1);
+ Jim_AddHashEntry(&interp->sharedStrings, strCopy, NULL);
+ he = Jim_FindHashEntry(&interp->sharedStrings, strCopy);
+ he->u.intval = 1;
return strCopy;
}
else {
- long refCount = (long)he->val;
-
- refCount++;
- he->val = (void *)refCount;
+ he->u.intval++;
return he->key;
}
}
void Jim_ReleaseSharedString(Jim_Interp *interp, const char *str)
{
- long refCount;
Jim_HashEntry *he = Jim_FindHashEntry(&interp->sharedStrings, str);
JimPanic((he == NULL, interp, "Jim_ReleaseSharedString called with " "unknown shared string '%s'", str));
- refCount = (long)he->val;
- refCount--;
- if (refCount == 0) {
+ if (--he->u.intval == 0) {
Jim_DeleteHashEntry(&interp->sharedStrings, str);
}
- else {
- he->val = (void *)refCount;
- }
}
/* -----------------------------------------------------------------------------
@@ -12499,6 +12555,9 @@ Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstOb
first = JimRelToAbsIndex(len, first);
last = JimRelToAbsIndex(len, last);
JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
+ if (first == 0 && last == len) {
+ return listObjPtr;
+ }
return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen);
}
@@ -12585,7 +12644,7 @@ void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
htiter = Jim_GetHashTableIterator(ht);
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
const Jim_Obj *keyObjPtr = he->key;
- Jim_Obj *valObjPtr = he->val;
+ Jim_Obj *valObjPtr = he->u.val;
Jim_IncrRefCount((Jim_Obj *)keyObjPtr); /* ATTENTION: const cast */
Jim_IncrRefCount(valObjPtr);
@@ -12616,7 +12675,7 @@ void UpdateStringOfDict(struct Jim_Obj *objPtr)
i = 0;
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
- objv[i++] = he->val;
+ objv[i++] = he->u.val;
}
Jim_FreeHashTableIterator(htiter);
/* (Over) Estimate the space needed. */
@@ -12724,8 +12783,8 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
he = Jim_FindHashEntry(ht, keyObjPtr);
Jim_DecrRefCount(interp, keyObjPtr);
/* ATTENTION: const cast */
- Jim_DecrRefCount(interp, (Jim_Obj *)he->val);
- he->val = valObjPtr;
+ Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
+ he->u.val = valObjPtr;
}
}
@@ -12760,8 +12819,8 @@ static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_DecrRefCount(interp, keyObjPtr);
/* ATTENTION: const cast */
- Jim_DecrRefCount(interp, (Jim_Obj *)he->val);
- he->val = valueObjPtr;
+ Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
+ he->u.val = valueObjPtr;
}
return JIM_OK;
}
@@ -12820,7 +12879,7 @@ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
}
return JIM_ERR;
}
- *objPtrPtr = he->val;
+ *objPtrPtr = he->u.val;
return JIM_OK;
}
@@ -12845,7 +12904,7 @@ int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, in
i = 0;
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
- objv[i++] = he->val;
+ objv[i++] = he->u.val;
}
*len = i;
Jim_FreeHashTableIterator(htiter);
@@ -13206,6 +13265,8 @@ enum
JIM_EXPROP_FUNC_ABS,
JIM_EXPROP_FUNC_DOUBLE,
JIM_EXPROP_FUNC_ROUND,
+ JIM_EXPROP_FUNC_RAND,
+ JIM_EXPROP_FUNC_SRAND,
#ifdef JIM_MATH_FUNCTIONS
/* math functions from libm */
@@ -13339,25 +13400,32 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
return rc;
}
+static double JimRandDouble(Jim_Interp *interp)
+{
+ unsigned long x;
+ JimRandomBytes(interp, &x, sizeof(x));
+
+ return (double)x / (unsigned long)~0;
+}
+
static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
{
Jim_Obj *A = ExprPop(e);
jim_wide wA;
- int rc = JIM_ERR;
-
-
- if (Jim_GetWide(interp, A, &wA) == JIM_OK) {
- jim_wide wC;
+ int rc = Jim_GetWide(interp, A, &wA);
+ if (rc == JIM_OK) {
switch (e->opcode) {
case JIM_EXPROP_BITNOT:
- wC = ~wA;
+ ExprPush(e, Jim_NewIntObj(interp, ~wA));
+ break;
+ case JIM_EXPROP_FUNC_SRAND:
+ JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
+ ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
break;
default:
abort();
}
- ExprPush(e, Jim_NewIntObj(interp, wC));
- rc = JIM_OK;
}
Jim_DecrRefCount(interp, A);
@@ -13365,6 +13433,15 @@ static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
return rc;
}
+static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
+{
+ JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND));
+
+ ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
+
+ return JIM_OK;
+}
+
#ifdef JIM_MATH_FUNCTIONS
static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
{
@@ -13928,6 +14005,8 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
[JIM_EXPROP_FUNC_DOUBLE] = {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
[JIM_EXPROP_FUNC_ABS] = {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
[JIM_EXPROP_FUNC_ROUND] = {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
+ [JIM_EXPROP_FUNC_RAND] = {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
+ [JIM_EXPROP_FUNC_SRAND] = {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
#ifdef JIM_MATH_FUNCTIONS
[JIM_EXPROP_FUNC_SIN] = {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
@@ -14734,13 +14813,19 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
struct ExprByteCode *expr;
ParseTokenList tokenlist;
int rc = JIM_ERR;
+ int line = 1;
+
+ /* Try to get information about filename / line number */
+ if (objPtr->typePtr == &sourceObjType) {
+ line = objPtr->internalRep.sourceValue.lineNumber;
+ }
exprText = Jim_GetString(objPtr, &exprTextLen);
/* Initially tokenise the expression into tokenlist */
ScriptTokenListInit(&tokenlist);
- JimParserInit(&parser, exprText, exprTextLen, 0);
+ JimParserInit(&parser, exprText, exprTextLen, line);
while (!parser.eof) {
if (JimParseExpression(&parser) != JIM_OK) {
ScriptTokenListFree(&tokenlist);
@@ -15616,8 +15701,6 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
/* -----------------------------------------------------------------------------
* Pseudo Random Number Generation
* ---------------------------------------------------------------------------*/
-static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
-
/* Initialize the sbox with the numbers from 0 to 255 */
static void JimPrngInit(Jim_Interp *interp)
{
@@ -15905,7 +15988,7 @@ static void JimDeleteLocalProcs(Jim_Interp *interp)
Jim_Cmd *prevCmd = NULL;
Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, procname);
if (he) {
- Jim_Cmd *cmd = (Jim_Cmd *)he->val;
+ Jim_Cmd *cmd = (Jim_Cmd *)he->u.val;
if (cmd->isproc && cmd->u.proc.prevCmd) {
prevCmd = cmd->u.proc.prevCmd;
cmd->u.proc.prevCmd = NULL;
@@ -16621,7 +16704,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
struct stat sb;
int retcode;
int readlen;
- char missing;
+ struct JimParseResult result;
if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
@@ -16643,17 +16726,36 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
fclose(fp);
buf[readlen] = 0;
- if (!Jim_ScriptIsComplete(buf, sb.st_size, &missing)) {
- Jim_SetResultFormatted(interp, "missing %s in \"%s\"",
- missing == '{' ? "close-brace" : "\"", filename);
- Jim_Free(buf);
- return JIM_ERR;
- }
-
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
JimSetSourceInfo(interp, scriptObjPtr, filename, 1);
Jim_IncrRefCount(scriptObjPtr);
+ /* Now check the script for unmatched braces, etc. */
+ if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
+ const char *msg;
+ char linebuf[20];
+
+ switch (result.missing) {
+ case '[':
+ msg = "unmatched \"[\"";
+ break;
+ case '{':
+ msg = "missing close-brace";
+ break;
+ case '"':
+ default:
+ msg = "missing quote";
+ break;
+ }
+
+ snprintf(linebuf, sizeof(linebuf), "%d", result.line);
+
+ Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
+ msg, filename, linebuf);
+ Jim_DecrRefCount(interp, scriptObjPtr);
+ return JIM_ERR;
+ }
+
prevScriptObj = interp->currentScriptObj;
interp->currentScriptObj = scriptObjPtr;
@@ -16895,7 +16997,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
htiter = Jim_GetHashTableIterator(&interp->commands);
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
- Jim_Cmd *cmdPtr = he->val;
+ Jim_Cmd *cmdPtr = he->u.val;
Jim_Obj *cmdNameObj;
if (type == 1 && !cmdPtr->isproc) {
@@ -16941,7 +17043,7 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
htiter = Jim_GetHashTableIterator(&interp->framePtr->vars);
}
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
- Jim_Var *varPtr = (Jim_Var *)he->val;
+ Jim_Var *varPtr = (Jim_Var *)he->u.val;
if (mode == JIM_VARLIST_LOCALS) {
if (varPtr->linkFramePtr != NULL)
@@ -19515,7 +19617,7 @@ static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
htiter = Jim_GetHashTableIterator(&interp->references);
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
char buf[JIM_REFERENCE_SPACE];
- Jim_Reference *refPtr = he->val;
+ Jim_Reference *refPtr = he->u.val;
const jim_wide *refId = he->key;
JimFormatReference(buf, refPtr, *refId);
@@ -19910,10 +20012,10 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
else {
int len;
const char *s = Jim_GetString(argv[2], &len);
- char missing = '\0';
+ char missing;
Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing));
- if (missing && argc == 4) {
+ if (missing != ' ' && argc == 4) {
Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1));
}
}
@@ -20076,13 +20178,13 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
* Optimise by sharing common (ASCII) characters
*/
Jim_Obj **commonObj = NULL;
-#define NUM_COMMON (128 - 32)
+#define NUM_COMMON (128 - 9)
while (strLen--) {
int n = utf8_tounicode(str, &c);
#ifdef JIM_OPTIMIZATION
- if (c >= 32 && c < 128) {
- /* Common ASCII char */
- c -= 32;
+ if (c >= 9 && c < 128) {
+ /* Common ASCII char. Note that 9 is the tab character */
+ c -= 9;
if (!commonObj) {
commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
@@ -21952,8 +22054,8 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
* Using two bytes for the "next" pointer is vast overkill for most things,
* but allows patterns to get big without disasters.
*/
-#define OP(p) ((p)[0])
-#define NEXT(p) ((p)[1])
+#define OP(preg, p) (preg->program[p])
+#define NEXT(preg, p) (preg->program[p + 1])
#define OPERAND(p) ((p) + 2)
/*
@@ -21982,16 +22084,17 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
/*
* Forward declarations for regcomp()'s friends.
*/
-static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp );
-static int *regpiece(regex_t *preg, int *flagp );
-static int *regbranch(regex_t *preg, int *flagp );
-static int *regatom(regex_t *preg, int *flagp );
-static int *regnode(regex_t *preg, int op );
-static const int *regnext(regex_t *preg, const int *p );
+static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp );
+static int regpiece(regex_t *preg, int *flagp );
+static int regbranch(regex_t *preg, int *flagp );
+static int regatom(regex_t *preg, int *flagp );
+static int regnode(regex_t *preg, int op );
+static int regnext(regex_t *preg, int p );
static void regc(regex_t *preg, int b );
-static int *reginsert(regex_t *preg, int op, int size, int *opnd );
-static void regtail(regex_t *preg, int *p, const int *val );
-static void regoptail(regex_t *preg, int *p, const int *val );
+static int reginsert(regex_t *preg, int op, int size, int opnd );
+static void regtail_(regex_t *preg, int p, int val, int line );
+static void regoptail(regex_t *preg, int p, int val );
+#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
static int reg_range_find(const int *string, int c);
static const char *str_find(const char *string, int c, int nocase);
@@ -22001,12 +22104,10 @@ static int prefix_cmp(const int *prog, int proglen, const char *string, int noca
#ifdef DEBUG
int regnarrate = 0;
static void regdump(regex_t *preg);
-static const char *regprop( const int *op );
+static const char *regprop( int op );
#endif
-static int regdummy;
-
/**
* Returns the length of the null-terminated integer sequence.
*/
@@ -22036,8 +22137,8 @@ static int str_int_len(const int *seq)
*/
int regcomp(regex_t *preg, const char *exp, int cflags)
{
- const int *scan;
- const int *longest;
+ int scan;
+ int longest;
unsigned len;
int flags;
@@ -22052,45 +22153,44 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
/* First pass: determine size, legality. */
preg->cflags = cflags;
preg->regparse = exp;
- preg->re_nsub = 0;
- preg->regsize = 0L;
- preg->regcode = &regdummy;
- regc(preg, REG_MAGIC);
- if (reg(preg, 0, &flags) == NULL)
- return preg->err;
-
- /* Small enough for pointer-storage convention? */
- if (preg->regsize >= 32767L || preg->re_nsub >= REG_MAX_PAREN) /* Probably could be 65535L. */
- FAIL(preg,REG_ERR_TOO_BIG);
+ /* XXX: For now, start unallocated */
+ preg->program = NULL;
+ preg->proglen = 0;
+#if 1
/* Allocate space. */
- preg->program = malloc(preg->regsize * sizeof(*preg->program));
+ preg->proglen = (strlen(exp) + 1) * 5;
+ preg->program = malloc(preg->proglen * sizeof(int));
if (preg->program == NULL)
FAIL(preg, REG_ERR_NOMEM);
+#endif
- /* Second pass: emit code. */
- preg->regparse = exp;
- preg->re_nsub = 0;
- preg->regsize = 0L;
- preg->regcode = preg->program;
+ /* Note that since we store a magic value as the first item in the program,
+ * program offsets will never be 0
+ */
regc(preg, REG_MAGIC);
- if (reg(preg, 0, &flags) == NULL)
+ if (reg(preg, 0, &flags) == 0) {
return preg->err;
+ }
+
+ /* Small enough for pointer-storage convention? */
+ if (preg->re_nsub >= REG_MAX_PAREN) /* Probably could be 65535L. */
+ FAIL(preg,REG_ERR_TOO_BIG);
/* Dig out information for optimizations. */
preg->regstart = 0; /* Worst-case defaults. */
preg->reganch = 0;
- preg->regmust = NULL;
+ preg->regmust = 0;
preg->regmlen = 0;
- scan = preg->program+1; /* First BRANCH. */
- if (OP(regnext(preg, scan)) == END) { /* Only one top-level choice. */
+ scan = 1; /* First BRANCH. */
+ if (OP(preg, regnext(preg, scan)) == END) { /* Only one top-level choice. */
scan = OPERAND(scan);
/* Starting-point info. */
- if (OP(scan) == EXACTLY) {
- preg->regstart = *OPERAND(scan);
+ if (OP(preg, scan) == EXACTLY) {
+ preg->regstart = preg->program[OPERAND(scan)];
}
- else if (OP(scan) == BOL)
+ else if (OP(preg, scan) == BOL)
preg->reganch++;
/*
@@ -22102,11 +22202,11 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
* strong reason, but sufficient in the absence of others.
*/
if (flags&SPSTART) {
- longest = NULL;
+ longest = 0;
len = 0;
- for (; scan != NULL; scan = regnext(preg, scan)) {
- if (OP(scan) == EXACTLY) {
- int plen = str_int_len(OPERAND(scan));
+ for (; scan != 0; scan = regnext(preg, scan)) {
+ if (OP(preg, scan) == EXACTLY) {
+ int plen = str_int_len(preg->program + OPERAND(scan));
if (plen >= len) {
longest = OPERAND(scan);
len = plen;
@@ -22134,11 +22234,11 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
* is a trifle forced, but the need to tie the tails of the branches to what
* follows makes it hard to avoid.
*/
-static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
+static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
{
- int *ret;
- int *br;
- const int *ender;
+ int ret;
+ int br;
+ int ender;
int parno = 0;
int flags;
@@ -22149,13 +22249,13 @@ static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
parno = ++preg->re_nsub;
ret = regnode(preg, OPEN+parno);
} else
- ret = NULL;
+ ret = 0;
/* Pick up the branches, linking them together. */
br = regbranch(preg, &flags);
- if (br == NULL)
- return(NULL);
- if (ret != NULL)
+ if (br == 0)
+ return 0;
+ if (ret != 0)
regtail(preg, ret, br); /* OPEN -> first. */
else
ret = br;
@@ -22165,8 +22265,8 @@ static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
while (*preg->regparse == '|') {
preg->regparse++;
br = regbranch(preg, &flags);
- if (br == NULL)
- return(NULL);
+ if (br == 0)
+ return 0;
regtail(preg, ret, br); /* BRANCH -> BRANCH. */
if (!(flags&HASWIDTH))
*flagp &= ~HASWIDTH;
@@ -22174,24 +22274,24 @@ static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
}
/* Make a closing node, and hook it on the end. */
- ender = regnode(preg, (paren) ? CLOSE+parno : END);
+ ender = regnode(preg, (paren) ? CLOSE+parno : END);
regtail(preg, ret, ender);
/* Hook the tails of the branches to the closing node. */
- for (br = ret; br != NULL; br = (int *)regnext(preg, br))
+ for (br = ret; br != 0; br = regnext(preg, br))
regoptail(preg, br, ender);
/* Check for proper termination. */
if (paren && *preg->regparse++ != ')') {
preg->err = REG_ERR_UNMATCHED_PAREN;
- return NULL;
+ return 0;
} else if (!paren && *preg->regparse != '\0') {
if (*preg->regparse == ')') {
preg->err = REG_ERR_UNMATCHED_PAREN;
- return NULL;
+ return 0;
} else {
preg->err = REG_ERR_JUNK_ON_END;
- return NULL;
+ return 0;
}
}
@@ -22203,24 +22303,24 @@ static int *reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
*
* Implements the concatenation operator.
*/
-static int *regbranch(regex_t *preg, int *flagp )
+static int regbranch(regex_t *preg, int *flagp )
{
- int *ret;
- int *chain;
- int *latest;
+ int ret;
+ int chain;
+ int latest;
int flags;
*flagp = WORST; /* Tentatively. */
ret = regnode(preg, BRANCH);
- chain = NULL;
+ chain = 0;
while (*preg->regparse != '\0' && *preg->regparse != ')' &&
*preg->regparse != '|') {
latest = regpiece(preg, &flags);
- if (latest == NULL)
- return(NULL);
+ if (latest == 0)
+ return 0;
*flagp |= flags&HASWIDTH;
- if (chain == NULL) {/* First piece. */
+ if (chain == 0) {/* First piece. */
*flagp |= flags&SPSTART;
}
else {
@@ -22228,7 +22328,7 @@ static int *regbranch(regex_t *preg, int *flagp )
}
chain = latest;
}
- if (chain == NULL) /* Loop ran zero times. */
+ if (chain == 0) /* Loop ran zero times. */
(void) regnode(preg, NOTHING);
return(ret);
@@ -22243,22 +22343,19 @@ static int *regbranch(regex_t *preg, int *flagp )
* It might seem that this node could be dispensed with entirely, but the
* endmarker role is not redundant.
*/
-static int *regpiece(regex_t *preg, int *flagp)
+static int regpiece(regex_t *preg, int *flagp)
{
- int *ret;
+ int ret;
char op;
- int *next;
+ int next;
int flags;
- int size = preg->regsize;
- int *chain = NULL;
+ int chain = 0;
int min;
int max;
ret = regatom(preg, &flags);
- if (ret == NULL)
- return(NULL);
-
- size = preg->regsize - size;
+ if (ret == 0)
+ return 0;
op = *preg->regparse;
if (!ISMULT(op)) {
@@ -22268,7 +22365,7 @@ static int *regpiece(regex_t *preg, int *flagp)
if (!(flags&HASWIDTH) && op != '?') {
preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
- return NULL;
+ return 0;
}
/* Handle braces (counted repetition) by expansion */
@@ -22278,7 +22375,7 @@ static int *regpiece(regex_t *preg, int *flagp)
min = strtoul(preg->regparse + 1, &end, 10);
if (end == preg->regparse + 1) {
preg->err = REG_ERR_BAD_COUNT;
- return NULL;
+ return 0;
}
if (*end == '}') {
max = min;
@@ -22288,7 +22385,7 @@ static int *regpiece(regex_t *preg, int *flagp)
max = strtoul(preg->regparse + 1, &end, 10);
if (*end != '}') {
preg->err = REG_ERR_UNMATCHED_BRACES;
- return NULL;
+ return 0;
}
}
if (end == preg->regparse + 1) {
@@ -22296,11 +22393,11 @@ static int *regpiece(regex_t *preg, int *flagp)
}
else if (max < min || max >= 100) {
preg->err = REG_ERR_BAD_COUNT;
- return NULL;
+ return 0;
}
if (min >= 100) {
preg->err = REG_ERR_BAD_COUNT;
- return NULL;
+ return 0;
}
preg->regparse = strchr(preg->regparse, '}');
@@ -22317,16 +22414,14 @@ static int *regpiece(regex_t *preg, int *flagp)
else {
next = reginsert(preg, flags & SIMPLE ? REP: REPX, 5, ret);
}
- if (preg->regcode != &regdummy) {
- ret[2] = max;
- ret[3] = min;
- ret[4] = 0;
- }
+ preg->program[ret + 2] = max;
+ preg->program[ret + 3] = min;
+ preg->program[ret + 4] = 0;
*flagp = (min) ? (WORST|HASWIDTH) : (WORST|SPSTART);
if (!(flags & SIMPLE)) {
- int *back = regnode(preg, BACK);
+ int back = regnode(preg, BACK);
regtail(preg, back, ret);
regtail(preg, next, back);
}
@@ -22334,7 +22429,7 @@ static int *regpiece(regex_t *preg, int *flagp)
preg->regparse++;
if (ISMULT(*preg->regparse)) {
preg->err = REG_ERR_NESTED_COUNT;
- return NULL;
+ return 0;
}
return chain ? chain : ret;
@@ -22468,9 +22563,9 @@ static int reg_decode_escape(const char *s, int *ch)
* faster to run. Backslashed characters are exceptions, each becoming a
* separate node; the code is simpler that way and it's not worth fixing.
*/
-static int *regatom(regex_t *preg, int *flagp)
+static int regatom(regex_t *preg, int *flagp)
{
- int *ret;
+ int ret;
int flags;
int nocase = (preg->cflags & REG_ICASE);
@@ -22517,7 +22612,7 @@ static int *regatom(regex_t *preg, int *flagp)
pattern += reg_decode_escape(pattern, &start);
if (start == 0) {
preg->err = REG_ERR_NULL_CHAR;
- return NULL;
+ return 0;
}
}
if (pattern[0] == '-' && pattern[1]) {
@@ -22528,7 +22623,7 @@ static int *regatom(regex_t *preg, int *flagp)
pattern += reg_decode_escape(pattern, &end);
if (end == 0) {
preg->err = REG_ERR_NULL_CHAR;
- return NULL;
+ return 0;
}
}
@@ -22574,27 +22669,26 @@ static int *regatom(regex_t *preg, int *flagp)
break;
case '(':
ret = reg(preg, 1, &flags);
- if (ret == NULL)
- return(NULL);
+ if (ret == 0)
+ return 0;
*flagp |= flags&(HASWIDTH|SPSTART);
break;
case '\0':
case '|':
case ')':
preg->err = REG_ERR_INTERNAL;
- return NULL; /* Supposed to be caught earlier. */
+ return 0; /* Supposed to be caught earlier. */
case '?':
case '+':
case '*':
case '{':
preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
- return NULL;
+ return 0;
case '\\':
switch (*preg->regparse++) {
case '\0':
preg->err = REG_ERR_TRAILING_BACKSLASH;
- return NULL;
- break;
+ return 0;
case '<':
case 'm':
ret = regnode(preg, WORDA);
@@ -22670,7 +22764,7 @@ static int *regatom(regex_t *preg, int *flagp)
n += reg_decode_escape(preg->regparse + n, &ch);
if (ch == 0) {
preg->err = REG_ERR_NULL_CHAR;
- return NULL;
+ return 0;
}
}
@@ -22709,27 +22803,27 @@ static int *regatom(regex_t *preg, int *flagp)
return(ret);
}
+static void reg_grow(regex_t *preg, int n)
+{
+ if (preg->p + n >= preg->proglen) {
+ preg->proglen = (preg->p + n) * 2;
+ preg->program = realloc(preg->program, preg->proglen * sizeof(int));
+ }
+}
+
/*
- regnode - emit a node
*/
/* Location. */
-static int *regnode(regex_t *preg, int op)
+static int regnode(regex_t *preg, int op)
{
- int *ret;
- int *ptr;
-
- preg->regsize += 2;
- ret = preg->regcode;
- if (ret == &regdummy) {
- return(ret);
- }
+ reg_grow(preg, 2);
- ptr = ret;
- *ptr++ = op;
- *ptr++ = 0; /* Null "next" pointer. */
- preg->regcode = ptr;
+ preg->program[preg->p++] = op;
+ preg->program[preg->p++] = 0;
- return(ret);
+ /* Return the start of the node */
+ return preg->p - 2;
}
/*
@@ -22737,9 +22831,8 @@ static int *regnode(regex_t *preg, int op)
*/
static void regc(regex_t *preg, int b )
{
- preg->regsize++;
- if (preg->regcode != &regdummy)
- *preg->regcode++ = b;
+ reg_grow(preg, 1);
+ preg->program[preg->p++] = b;
}
/*
@@ -22748,72 +22841,58 @@ static void regc(regex_t *preg, int b )
* Means relocating the operand.
* Returns the new location of the original operand.
*/
-static int *reginsert(regex_t *preg, int op, int size, int *opnd )
+static int reginsert(regex_t *preg, int op, int size, int opnd )
{
- int *src;
- int *dst;
- int *place;
-
- preg->regsize += size;
+ reg_grow(preg, size);
- if (preg->regcode == &regdummy) {
- return opnd;
- }
+ /* Move everything from opnd up */
+ memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
+ /* Zero out the new space */
+ memset(preg->program + opnd, 0, sizeof(int) * size);
- src = preg->regcode;
- preg->regcode += size;
- dst = preg->regcode;
- while (src > opnd)
- *--dst = *--src;
+ preg->program[opnd] = op;
- place = opnd; /* Op node, where operand used to be. */
- *place++ = op;
- while (--size) {
- *place++ = 0;
- }
+ preg->p += size;
- return place;
+ return opnd + size;
}
/*
- regtail - set the next-pointer at the end of a node chain
*/
-static void regtail(regex_t *preg, int *p, const int *val )
+static void regtail_(regex_t *preg, int p, int val, int line )
{
- int *scan;
- int *temp;
+ int scan;
+ int temp;
int offset;
- if (p == &regdummy)
- return;
-
/* Find last node. */
scan = p;
for (;;) {
- temp = (int *)regnext(preg, scan);
- if (temp == NULL)
+ temp = regnext(preg, scan);
+ if (temp == 0)
break;
scan = temp;
}
- if (OP(scan) == BACK)
+ if (OP(preg, scan) == BACK)
offset = scan - val;
else
offset = val - scan;
- scan[1] = offset;
+ preg->program[scan + 1] = offset;
}
/*
- regoptail - regtail on operand of first argument; nop if operandless
*/
-static void regoptail(regex_t *preg, int *p, const int *val )
+static void regoptail(regex_t *preg, int p, int val )
{
/* "Operandless" and "op != BRANCH" are synonymous in practice. */
- if (p == NULL || p == &regdummy || OP(p) != BRANCH)
- return;
- regtail(preg, OPERAND(p), val);
+ if (p != 0 && OP(preg, p) == BRANCH) {
+ regtail(preg, OPERAND(p), val);
+ }
}
/*
@@ -22824,8 +22903,8 @@ static void regoptail(regex_t *preg, int *p, const int *val )
* Forwards.
*/
static int regtry(regex_t *preg, const char *string );
-static int regmatch(regex_t *preg, const int *prog);
-static int regrepeat(regex_t *preg, const int *p, int max);
+static int regmatch(regex_t *preg, int prog);
+static int regrepeat(regex_t *preg, int p, int max);
/*
- regexec - match a regexp against a string
@@ -22833,7 +22912,7 @@ static int regrepeat(regex_t *preg, const int *p, int max);
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
{
const char *s;
- const int *scan;
+ int scan;
/* Be paranoid... */
if (preg == NULL || preg->program == NULL || string == NULL) {
@@ -22856,22 +22935,22 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat
preg->start = string; /* All offsets are computed from here */
/* Must clear out the embedded repeat counts */
- for (scan = OPERAND(preg->program + 1); scan != NULL; scan = regnext(preg, scan)) {
- switch (OP(scan)) {
+ for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) {
+ switch (OP(preg, scan)) {
case REP:
case REPMIN:
case REPX:
case REPXMIN:
- *(int *)(scan + 4) = 0;
+ preg->program[scan + 4] = 0;
break;
}
}
/* If there is a "must appear" string, look for it. */
- if (preg->regmust != NULL) {
+ if (preg->regmust != 0) {
s = string;
- while ((s = str_find(s, preg->regmust[0], preg->cflags & REG_ICASE)) != NULL) {
- if (prefix_cmp(preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
+ while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
+ if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
break;
}
s++;
@@ -22948,7 +23027,7 @@ static int regtry( regex_t *preg, const char *string )
preg->pmatch[i].rm_so = -1;
preg->pmatch[i].rm_eo = -1;
}
- if (regmatch(preg, preg->program + 1)) {
+ if (regmatch(preg, 1)) {
preg->pmatch[0].rm_so = string - preg->start;
preg->pmatch[0].rm_eo = preg->reginput - preg->start;
return(1);
@@ -23041,23 +23120,23 @@ static int reg_iseol(regex_t *preg, int ch)
}
}
-static int regmatchsimplerepeat(regex_t *preg, const int *scan, int matchmin)
+static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin)
{
int nextch = '\0';
const char *save;
int no;
int c;
- int max = scan[2];
- int min = scan[3];
- const int *next = regnext(preg, scan);
+ int max = preg->program[scan + 2];
+ int min = preg->program[scan + 3];
+ int next = regnext(preg, scan);
/*
* Lookahead to avoid useless match attempts
* when we know what character comes next.
*/
- if (OP(next) == EXACTLY) {
- nextch = *OPERAND(next);
+ if (OP(preg, next) == EXACTLY) {
+ nextch = preg->program[OPERAND(next)];
}
save = preg->reginput;
no = regrepeat(preg, scan + 5, max);
@@ -23101,26 +23180,24 @@ static int regmatchsimplerepeat(regex_t *preg, const int *scan, int matchmin)
return(0);
}
-static int regmatchrepeat(regex_t *preg, int *scan, int matchmin)
+static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
{
- const char *save;
+ int *scanpt = preg->program + scan;
- int max = scan[2];
- int min = scan[3];
-
- save = preg->reginput;
+ int max = scanpt[2];
+ int min = scanpt[3];
/* Have we reached min? */
- if (scan[4] < min) {
+ if (scanpt[4] < min) {
/* No, so get another one */
- scan[4]++;
+ scanpt[4]++;
if (regmatch(preg, scan + 5)) {
return 1;
}
- scan[4]--;
+ scanpt[4]--;
return 0;
}
- if (scan[4] > max) {
+ if (scanpt[4] > max) {
return 0;
}
@@ -23130,26 +23207,23 @@ static int regmatchrepeat(regex_t *preg, int *scan, int matchmin)
return 1;
}
/* No, so try one more */
- scan[4]++;
+ scanpt[4]++;
if (regmatch(preg, scan + 5)) {
return 1;
}
- scan[4]--;
+ scanpt[4]--;
return 0;
}
/* maximal, so try this branch again */
- save = preg->reginput;
- if (scan[4] < max) {
- scan[4]++;
+ if (scanpt[4] < max) {
+ scanpt[4]++;
if (regmatch(preg, scan + 5)) {
return 1;
}
- scan[4]--;
+ scanpt[4]--;
}
- /* At this point we are at max with no match. Back up by one and try the other branch */
- preg->reginput = save;
- int ret = regmatch(preg, regnext(preg, scan));
- return ret;
+ /* At this point we are at max with no match. Try the other branch */
+ return regmatch(preg, regnext(preg, scan));
}
/*
@@ -23163,31 +23237,30 @@ static int regmatchrepeat(regex_t *preg, int *scan, int matchmin)
* by recursion.
*/
/* 0 failure, 1 success */
-static int regmatch(regex_t *preg, const int *prog)
+static int regmatch(regex_t *preg, int prog)
{
- const int *scan; /* Current node. */
- const int *next; /* Next node. */
+ int scan; /* Current node. */
+ int next; /* Next node. */
scan = prog;
#ifdef DEBUG
- if (scan != NULL && regnarrate)
+ if (scan != 0 && regnarrate)
fprintf(stderr, "%s(\n", regprop(scan));
#endif
- while (scan != NULL) {
+ while (scan != 0) {
int n;
int c;
#ifdef DEBUG
if (regnarrate) {
//fprintf(stderr, "%s...\n", regprop(scan));
- int op = OP(scan);
- fprintf(stderr, "%2d{%02x}%s...\n", (int)(scan-preg->program), op, regprop(scan)); /* Where, what. */
+ fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); /* Where, what. */
}
#endif
next = regnext(preg, scan);
n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
- switch (OP(scan)) {
+ switch (OP(preg, scan)) {
case BOL:
if (preg->reginput != preg->regbol)
return(0);
@@ -23227,14 +23300,14 @@ static int regmatch(regex_t *preg, const int *prog)
preg->reginput += n;
break;
case EXACTLY: {
- const int *opnd;
+ int opnd;
int len;
int slen;
opnd = OPERAND(scan);
- len = str_int_len(opnd);
+ len = str_int_len(preg->program + opnd);
- slen = prefix_cmp(opnd, len, preg->reginput, preg->cflags & REG_ICASE);
+ slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE);
if (slen < 0) {
return(0);
}
@@ -23242,13 +23315,13 @@ static int regmatch(regex_t *preg, const int *prog)
}
break;
case ANYOF:
- if (reg_iseol(preg, c) || reg_range_find(OPERAND(scan), c) == 0) {
+ if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) {
return(0);
}
preg->reginput += n;
break;
case ANYBUT:
- if (reg_iseol(preg, c) || reg_range_find(OPERAND(scan), c) != 0) {
+ if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) {
return(0);
}
preg->reginput += n;
@@ -23260,7 +23333,7 @@ static int regmatch(regex_t *preg, const int *prog)
case BRANCH: {
const char *save;
- if (OP(next) != BRANCH) /* No choice. */
+ if (OP(preg, next) != BRANCH) /* No choice. */
next = OPERAND(scan); /* Avoid recursion. */
else {
do {
@@ -23270,7 +23343,7 @@ static int regmatch(regex_t *preg, const int *prog)
}
preg->reginput = save;
scan = regnext(preg, scan);
- } while (scan != NULL && OP(scan) == BRANCH);
+ } while (scan != 0 && OP(preg, scan) == BRANCH);
return(0);
/* NOTREACHED */
}
@@ -23278,17 +23351,17 @@ static int regmatch(regex_t *preg, const int *prog)
break;
case REP:
case REPMIN:
- return regmatchsimplerepeat(preg, scan, OP(scan) == REPMIN);
+ return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
case REPX:
case REPXMIN:
- return regmatchrepeat(preg, (int *)scan, OP(scan) == REPXMIN);
+ return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
case END:
return(1); /* Success! */
break;
default:
- if (OP(scan) >= OPEN+1 && OP(scan) < CLOSE_END) {
+ if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
const char *save;
save = preg->reginput;
@@ -23300,14 +23373,14 @@ static int regmatch(regex_t *preg, const int *prog)
* invocation of the same parentheses
* already has.
*/
- if (OP(scan) < CLOSE) {
- no = OP(scan) - OPEN;
+ if (OP(preg, scan) < CLOSE) {
+ no = OP(preg, scan) - OPEN;
if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
preg->pmatch[no].rm_so = save - preg->start;
}
}
else {
- no = OP(scan) - CLOSE;
+ no = OP(preg, scan) - CLOSE;
if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
preg->pmatch[no].rm_eo = save - preg->start;
}
@@ -23332,17 +23405,17 @@ static int regmatch(regex_t *preg, const int *prog)
/*
- regrepeat - repeatedly match something simple, report how many
*/
-static int regrepeat(regex_t *preg, const int *p, int max)
+static int regrepeat(regex_t *preg, int p, int max)
{
int count = 0;
const char *scan;
- const int *opnd;
+ int opnd;
int ch;
int n;
scan = preg->reginput;
opnd = OPERAND(p);
- switch (OP(p)) {
+ switch (OP(preg, p)) {
case ANY:
/* No need to handle utf8 specially here */
while (!reg_iseol(preg, *scan) && count < max) {
@@ -23353,7 +23426,7 @@ static int regrepeat(regex_t *preg, const int *p, int max)
case EXACTLY:
while (count < max) {
n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
- if (*opnd != ch) {
+ if (preg->program[opnd] != ch) {
break;
}
count++;
@@ -23363,7 +23436,7 @@ static int regrepeat(regex_t *preg, const int *p, int max)
case ANYOF:
while (count < max) {
n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
- if (reg_iseol(preg, ch) || reg_range_find(opnd, ch) == 0) {
+ if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) == 0) {
break;
}
count++;
@@ -23373,7 +23446,7 @@ static int regrepeat(regex_t *preg, const int *p, int max)
case ANYBUT:
while (count < max) {
n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
- if (reg_iseol(preg, ch) || reg_range_find(opnd, ch) != 0) {
+ if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) != 0) {
break;
}
count++;
@@ -23393,19 +23466,16 @@ static int regrepeat(regex_t *preg, const int *p, int max)
/*
- regnext - dig the "next" pointer out of a node
*/
-static const int *regnext(regex_t *preg, const int *p )
+static int regnext(regex_t *preg, int p )
{
int offset;
- if (p == &regdummy)
- return(NULL);
-
- offset = NEXT(p);
+ offset = NEXT(preg, p);
if (offset == 0)
- return(NULL);
+ return 0;
- if (OP(p) == BACK)
+ if (OP(preg, p) == BACK)
return(p-offset);
else
return(p+offset);
@@ -23418,42 +23488,48 @@ static const int *regnext(regex_t *preg, const int *p )
*/
static void regdump(regex_t *preg)
{
- const int *s;
- char op = EXACTLY; /* Arbitrary non-END op. */
- const int *next;
+ int s;
+ int op = EXACTLY; /* Arbitrary non-END op. */
+ int next;
char buf[4];
- if (preg->regcode == &regdummy)
- return;
+ int i;
+ for (i = 1; i < preg->p; i++) {
+ printf("%02x ", preg->program[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
- s = preg->program + 1;
- while (op != END && s < preg->regcode) { /* While that wasn't END last time... */
- op = OP(s);
- printf("%2d{%02x}%s", (int)(s-preg->program), op, regprop(s)); /* Where, what. */
+ s = 1;
+ while (op != END && s < preg->p) { /* While that wasn't END last time... */
+ op = OP(preg, s);
+ printf("%3d: %s", s, regprop(op)); /* Where, what. */
next = regnext(preg, s);
- if (next == NULL) /* Next ptr. */
+ if (next == 0) /* Next ptr. */
printf("(0)");
- else
- printf("(%d)", (int)((s-preg->program)+(next-s)));
+ else
+ printf("(%d)", next);
s += 2;
if (op == REP || op == REPMIN || op == REPX || op == REPXMIN) {
- int max = s[0];
- int min = s[1];
+ int max = preg->program[s];
+ int min = preg->program[s + 1];
if (max == 65535) {
printf("{%d,*}", min);
}
else {
printf("{%d,%d}", min, max);
}
- printf(" %d", s[2]);
+ printf(" %d", preg->program[s + 2]);
s += 3;
}
else if (op == ANYOF || op == ANYBUT) {
/* set of ranges */
- while (*s) {
- int len = *s++;
- int first = *s++;
+ while (preg->program[s]) {
+ int len = preg->program[s++];
+ int first = preg->program[s++];
buf[utf8_fromunicode(buf, first)] = 0;
printf("%s", buf);
if (len > 1) {
@@ -23466,8 +23542,8 @@ static void regdump(regex_t *preg)
else if (op == EXACTLY) {
/* Literal string, where present. */
- while (*s) {
- buf[utf8_fromunicode(buf, *s)] = 0;
+ while (preg->program[s]) {
+ buf[utf8_fromunicode(buf, preg->program[s])] = 0;
printf("%s", buf);
s++;
}
@@ -23484,11 +23560,11 @@ static void regdump(regex_t *preg)
}
if (preg->reganch)
printf("anchored ");
- if (preg->regmust != NULL) {
+ if (preg->regmust != 0) {
int i;
printf("must have:");
for (i = 0; i < preg->regmlen; i++) {
- putchar(preg->regmust[i]);
+ putchar(preg->program[preg->regmust + i]);
}
putchar('\n');
}
@@ -23499,78 +23575,55 @@ static void regdump(regex_t *preg)
/*
- regprop - printable representation of opcode
*/
-static const char *regprop( const int *op )
+static const char *regprop( int op )
{
- char *p;
static char buf[50];
- (void) strcpy(buf, ":");
-
- switch (OP(op)) {
+ switch (op) {
case BOL:
- p = "BOL";
- break;
+ return "BOL";
case EOL:
- p = "EOL";
- break;
+ return "EOL";
case ANY:
- p = "ANY";
- break;
+ return "ANY";
case ANYOF:
- p = "ANYOF";
- break;
+ return "ANYOF";
case ANYBUT:
- p = "ANYBUT";
- break;
+ return "ANYBUT";
case BRANCH:
- p = "BRANCH";
- break;
+ return "BRANCH";
case EXACTLY:
- p = "EXACTLY";
- break;
+ return "EXACTLY";
case NOTHING:
- p = "NOTHING";
- break;
+ return "NOTHING";
case BACK:
- p = "BACK";
- break;
+ return "BACK";
case END:
- p = "END";
- break;
+ return "END";
case REP:
- p = "REP";
- break;
+ return "REP";
case REPMIN:
- p = "REPMIN";
- break;
+ return "REPMIN";
case REPX:
- p = "REPX";
- break;
+ return "REPX";
case REPXMIN:
- p = "REPXMIN";
- break;
+ return "REPXMIN";
case WORDA:
- p = "WORDA";
- break;
+ return "WORDA";
case WORDZ:
- p = "WORDZ";
- break;
+ return "WORDZ";
default:
- if (OP(op) >= OPEN && OP(op) < CLOSE) {
- sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+ if (op >= OPEN && op < CLOSE) {
+ snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN);
}
- else if (OP(op) >= CLOSE && OP(op) < CLOSE_END) {
- sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ else if (op >= CLOSE && op < CLOSE_END) {
+ snprintf(buf, sizeof(buf), "CLOSE%d", op-CLOSE);
}
else {
- abort();
+ snprintf(buf, sizeof(buf), "?%d?\n", op);
}
- p = NULL;
- break;
+ return(buf);
}
- if (p != NULL)
- (void) strcat(buf, p);
- return(buf);
}
#endif
@@ -23645,7 +23698,12 @@ void regfree(regex_t *preg)
static const char jimsh_init[] = \
"proc _init {} {\n"
"\trename _init {}\n"
+/* XXX This is a big ugly */
+#if defined(__MINGW32__)
+"\tlappend p {*}[split [env JIMLIB {}] {;}]\n"
+#else
"\tlappend p {*}[split [env JIMLIB {}] :]\n"
+#endif
"\tlappend p {*}$::auto_path\n"
"\tlappend p [file dirname [info nameofexecutable]]\n"
"\tset ::auto_path $p\n"
@@ -23659,6 +23717,10 @@ static const char jimsh_init[] = \
"\t\t}\n"
"\t}\n"
"}\n"
+/* XXX This is a big ugly */
+#if defined(__MINGW32__)
+"set jim_argv0 [string map {\\\\ /} $jim_argv0]\n"
+#endif
"_init\n";
static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])