aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2023-07-10 13:54:31 +1000
committerSteve Bennett <steveb@workware.net.au>2023-07-10 13:57:05 +1000
commit6a1af5b541395f4aa4ab745def9885365d60eb3a (patch)
tree51d9eb7f81364bcf16dcc6ac9eb494934d204d76
parente7872e67777466e71a3df3b06cb60c277f4e63b1 (diff)
downloadjimtcl-6a1af5b541395f4aa4ab745def9885365d60eb3a.zip
jimtcl-6a1af5b541395f4aa4ab745def9885365d60eb3a.tar.gz
jimtcl-6a1af5b541395f4aa4ab745def9885365d60eb3a.tar.bz2
build: update autosetup to v0.7.1-11-g9d20e8a
Mostly for update bootstrap jimsh Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--autosetup/README.autosetup4
-rwxr-xr-xautosetup/autosetup89
-rw-r--r--autosetup/cc.tcl4
-rw-r--r--autosetup/jimsh0.c6032
-rw-r--r--autosetup/system.tcl14
5 files changed, 3982 insertions, 2161 deletions
diff --git a/autosetup/README.autosetup b/autosetup/README.autosetup
index 0a0763d..30bef32 100644
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -1,4 +1,4 @@
-README.autosetup created by autosetup v0.7.1
+README.autosetup created by autosetup v0.7.1+
This is the autosetup directory for a local install of autosetup.
It contains autosetup, support files and loadable modules.
@@ -8,4 +8,4 @@ can be loaded with the 'use' directive.
*.auto files in this directory are auto-loaded.
-For more information, see http://msteveb.github.io/autosetup/
+For more information, see https://msteveb.github.io/autosetup/
diff --git a/autosetup/autosetup b/autosetup/autosetup
index 0dee7a5..e4d5a31 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -6,7 +6,7 @@
dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
# Note that the version has a trailing + on unreleased versions
-set autosetup(version) 0.7.1
+set autosetup(version) 0.7.1+
# Can be set to 1 to debug early-init problems
set autosetup(debug) [expr {"--debug" in $argv}]
@@ -204,19 +204,10 @@ proc main {argv} {
autosetup_add_dep $autosetup(autodef)
- # Add $argv to CONFIGURE_OPTS, but ignore duplicates and quote if needed
- set configure_opts {}
- foreach arg $autosetup(argv) {
- 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 [quote-if-needed $autosetup(exe)]
- define-append AUTOREMAKE [get-define CONFIGURE_OPTS]
-
+ # Add $argv to CONFIGURE_OPTS
+ define-append-argv CONFIGURE_OPTS {*}$autosetup(argv)
+ # Set up AUTOREMAKE to reconfigure with the same args
+ define-append-argv AUTOREMAKE {*}$autosetup(exe) {*}$autosetup(argv)
# Log how we were invoked
configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
@@ -744,24 +735,17 @@ proc undefine {name} {
# If the variable is not defined or empty, it is set to '$value'.
# Otherwise the value is appended, separated by a space.
# Any extra values are similarly appended.
-# If any value is already contained in the variable (as a substring) it is omitted.
+#
+# Note that define-append is not designed to add values containing spaces.
+# If values may contain spaces, consider define-append-argv instead.
#
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} {
- incr found
- }
- }
- if {!$found} {
- append ::define($name) " " $arg
- }
+ append ::define($name) " " $arg
}
} else {
set ::define($name) [join $args]
@@ -769,6 +753,27 @@ proc define-append {name args} {
#dputs "$name += [join $args] => $::define($name)"
}
+# @define-append-argv name value ...
+#
+# Similar to define-append except designed to construct shell command
+# lines, including correct handling of parameters with spaces.
+#
+# Each non-empty value is quoted if necessary and then appended to the given variable
+# if it does not already exist.
+#
+proc define-append-argv {name args} {
+ set seen {}
+ set new {}
+ foreach val [list {*}[get-define $name ""] {*}$args] {
+ if {$val ne {} && ![dict exists $seen $val]} {
+ lappend new [quote-if-needed $val]
+ dict set seen $val 1
+ }
+ }
+ set ::define($name) [join $new " "]
+ #dputs "$name += [join $args] => $::define($name)"
+}
+
# @get-define name ?default=0?
#
# Returns the current value of the "defined" variable, or '$default'
@@ -1487,7 +1492,7 @@ proc autosetup_help {what} {
puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n"
puts "This is [autosetup_version], a build environment \"autoconfigurator\""
- puts "See the documentation online at http://msteveb.github.io/autosetup/\n"
+ puts "See the documentation online at https://msteveb.github.io/autosetup/\n"
if {$what in {all local}} {
# Need to load auto.def now
@@ -1560,8 +1565,8 @@ proc autosetup_reference {{type text}} {
section {Introduction}
p {
- See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup'.
- This documentation can also be accessed locally with `autosetup --ref`.
+ See https://msteveb.github.io/autosetup/ for the online documentation for 'autosetup'.
+ This documentation can also be accessed locally with `autosetup --ref`.
}
p {
@@ -1971,7 +1976,7 @@ can be loaded with the 'use' directive.
*.auto files in this directory are auto-loaded.
-For more information, see http://msteveb.github.io/autosetup/
+For more information, see https://msteveb.github.io/autosetup/
}
dputs "install: autosetup/README.autosetup"
writefile $target $readme
@@ -2105,6 +2110,19 @@ if {$autosetup(istcl)} {
proc isatty? {channel} {
dict exists [fconfigure $channel] -xchar
}
+ # Jim-compatible stacktrace using info frame
+ proc stacktrace {} {
+ set stacktrace {}
+ # 2 to skip the current frame
+ for {set i 2} {$i < [info frame]} {incr i} {
+ set frame [info frame -$i]
+ if {[dict exists $frame file]} {
+ # We don't need proc, so use ""
+ lappend stacktrace "" [dict get $frame file] [dict get $frame line]
+ }
+ }
+ return $stacktrace
+ }
} else {
if {$autosetup(iswin)} {
# On Windows, backslash convert all environment variables
@@ -2158,16 +2176,11 @@ proc error-location {msg} {
return -code error $msg
}
# Search back through the stack trace for the first error in a .def file
- for {set i 1} {$i < [info level]} {incr i} {
- if {$::autosetup(istcl)} {
- array set info [info frame -$i]
- } else {
- lassign [info frame -$i] info(caller) info(file) info(line)
+ foreach {p f l} [stacktrace] {
+ if {[string match *.def $f]} {
+ return "[relative-path $f]:$l: Error: $msg"
}
- if {[string match *.def $info(file)]} {
- return "[relative-path $info(file)]:$info(line): Error: $msg"
- }
- #puts "Skipping $info(file):$info(line)"
+ #puts "Skipping $f:$l"
}
return $msg
}
diff --git a/autosetup/cc.tcl b/autosetup/cc.tcl
index a8aba97..f45cc2e 100644
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -678,7 +678,7 @@ proc calc-define-output-type {name spec} {
}
# Initialise some values from the environment or commandline or default settings
-foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} {
+foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
lassign $i var default
define $var [get-env $var $default]
}
@@ -727,7 +727,7 @@ foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAG
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 ""]]
+ define-append-argv AUTOREMAKE $i=[get-env $i ""]
}
}
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index 63d4596..f3ec997 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -12,6 +12,7 @@
#define jim_ext_file
#define jim_ext_glob
#define jim_ext_exec
+#define jim_ext_posix
#define jim_ext_clock
#define jim_ext_array
#define jim_ext_stdlib
@@ -49,7 +50,7 @@
#else
#define _GNU_SOURCE
#endif
-#define HAVE_VFORK
+#define HAVE_FORK
#define HAVE_WAITPID
#define HAVE_ISATTY
#define HAVE_MKSTEMP
@@ -58,8 +59,10 @@
#define HAVE_DIRENT_H
#define HAVE_UNISTD_H
#define HAVE_UMASK
+#define HAVE_PIPE
+#define _FILE_OFFSET_BITS 64
#endif
-#define JIM_VERSION 78
+#define JIM_VERSION 82
#ifndef JIM_WIN32COMPAT_H
#define JIM_WIN32COMPAT_H
@@ -186,7 +189,6 @@ extern "C" {
#include <time.h>
#include <limits.h>
-#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -225,6 +227,9 @@ extern "C" {
#define UCHAR(c) ((unsigned char)(c))
+
+#define JIM_ABI_VERSION 101
+
#define JIM_OK 0
#define JIM_ERR 1
#define JIM_RETURN 2
@@ -246,6 +251,7 @@ extern "C" {
#define JIM_ENUM_ABBREV 2
#define JIM_UNSHARED 4
#define JIM_MUSTEXIST 8
+#define JIM_NORESULT 16
#define JIM_SUBST_NOVAR 1
@@ -256,6 +262,7 @@ extern "C" {
#define JIM_CASESENS 0
#define JIM_NOCASE 1
+#define JIM_OPT_END 2
#define JIM_PATH_LEN 1024
@@ -324,6 +331,8 @@ typedef struct Jim_HashTableIterator {
(entry)->u.val = (_val_); \
} while(0)
+#define Jim_SetHashIntVal(ht, entry, _val_) (entry)->u.intval = (_val_)
+
#define Jim_FreeEntryKey(ht, entry) \
if ((ht)->type->keyDestructor) \
(ht)->type->keyDestructor((ht)->privdata, (entry)->key)
@@ -344,6 +353,7 @@ typedef struct Jim_HashTableIterator {
#define Jim_GetHashEntryKey(he) ((he)->key)
#define Jim_GetHashEntryVal(he) ((he)->u.val)
+#define Jim_GetHashEntryIntVal(he) ((he)->u.intval)
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
#define Jim_GetHashTableSize(ht) ((ht)->size)
#define Jim_GetHashTableUsed(ht) ((ht)->used)
@@ -377,7 +387,7 @@ typedef struct Jim_Obj {
} ptrIntValue;
struct {
- struct Jim_Var *varPtr;
+ struct Jim_VarVal *vv;
unsigned long callFrameId;
int global;
} varValue;
@@ -394,6 +404,8 @@ typedef struct Jim_Obj {
int maxLen;
} listValue;
+ struct Jim_Dict *dictValue;
+
struct {
int maxLength;
int charLength;
@@ -479,29 +491,55 @@ typedef struct Jim_CallFrame {
Jim_Obj *procBodyObjPtr;
struct Jim_CallFrame *next;
Jim_Obj *nsObj;
- Jim_Obj *fileNameObj;
- int line;
+ Jim_Obj *unused_fileNameObj;
+ int unused_line;
Jim_Stack *localCommands;
struct Jim_Obj *tailcallObj;
struct Jim_Cmd *tailcallCmd;
} Jim_CallFrame;
-typedef struct Jim_Var {
+
+typedef struct Jim_EvalFrame {
+ Jim_CallFrame *framePtr;
+ int level;
+ int procLevel;
+ struct Jim_Cmd *cmd;
+ struct Jim_EvalFrame *parent;
+ Jim_Obj *const *argv;
+ int argc;
+ Jim_Obj *scriptObj;
+} Jim_EvalFrame;
+
+typedef struct Jim_VarVal {
Jim_Obj *objPtr;
struct Jim_CallFrame *linkFramePtr;
-} Jim_Var;
+ int refCount;
+} Jim_VarVal;
typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
Jim_Obj *const *argv);
typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
-
+typedef struct Jim_Dict {
+ struct JimDictHashEntry {
+ int offset;
+ unsigned hash;
+ } *ht;
+ unsigned int size;
+ unsigned int sizemask;
+ unsigned int uniq;
+ Jim_Obj **table;
+ int len;
+ int maxLen;
+ unsigned int dummy;
+} Jim_Dict;
typedef struct Jim_Cmd {
int inUse;
int isproc;
struct Jim_Cmd *prevCmd;
+ Jim_Obj *cmdNameObj;
union {
struct {
@@ -536,9 +574,9 @@ typedef struct Jim_PrngState {
typedef struct Jim_Interp {
Jim_Obj *result;
- int errorLine;
- Jim_Obj *errorFileNameObj;
- int addStackTrace;
+ int unused_errorLine;
+ Jim_Obj *currentFilenameObj;
+ int unused_addStackTrace;
int maxCallFrameDepth;
int maxEvalDepth;
int evalDepth;
@@ -560,9 +598,15 @@ typedef struct Jim_Interp {
'ID' field contained in the Jim_CallFrame
structure. */
int local;
+ int quitting;
+ int safeexpr;
Jim_Obj *liveList;
Jim_Obj *freeList;
- Jim_Obj *currentScriptObj;
+ Jim_Obj *unused_currentScriptObj;
+ Jim_EvalFrame topEvalFrame;
+ Jim_EvalFrame *evalFrame;
+ int procLevel;
+ Jim_Obj * const *unused_argv;
Jim_Obj *nullScriptObj;
Jim_Obj *emptyObj;
Jim_Obj *trueObj;
@@ -574,16 +618,20 @@ typedef struct Jim_Interp {
is running as sentinel to avoid to recursive
calls via the [collect] command inside
finalizers. */
- time_t lastCollectTime;
+ jim_wide lastCollectTime;
Jim_Obj *stackTrace;
Jim_Obj *errorProc;
Jim_Obj *unknown;
+ Jim_Obj *defer;
+ Jim_Obj *traceCmdObj;
int unknown_called;
int errorFlag;
void *cmdPrivData; /* Used to pass the private data pointer to
a command. It is set to what the user specified
via Jim_CreateCommand(). */
+ Jim_Cmd *oldCmdCache;
+ int oldCmdCacheSize;
struct Jim_CallFrame *freeFramesList;
struct Jim_HashTable assocData;
Jim_PrngState *prngState;
@@ -591,7 +639,6 @@ typedef struct Jim_Interp {
Jim_Stack *loadHandles;
} Jim_Interp;
-#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
@@ -623,12 +670,15 @@ typedef struct Jim_Reference {
#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
-#define JIM_EXPORT
+#define JIM_EXPORT extern
+
-JIM_EXPORT void *Jim_Alloc (int size);
-JIM_EXPORT void *Jim_Realloc(void *ptr, int size);
-JIM_EXPORT void Jim_Free (void *ptr);
+JIM_EXPORT void *(*Jim_Allocator)(void *ptr, size_t size);
+
+#define Jim_Free(P) Jim_Allocator((P), 0)
+#define Jim_Realloc(P, S) Jim_Allocator((P), (S))
+#define Jim_Alloc(S) Jim_Allocator(NULL, (S))
JIM_EXPORT char * Jim_StrDup (const char *s);
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
@@ -636,6 +686,16 @@ 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, int unlink_file);
+#ifndef CLOCK_REALTIME
+# define CLOCK_REALTIME 0
+#endif
+#ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC 1
+#endif
+#ifndef CLOCK_MONOTONIC_RAW
+# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+JIM_EXPORT jim_wide Jim_GetTimeUsec(unsigned type);
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
@@ -682,7 +742,6 @@ JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht,
JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht);
JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht,
const void *key);
-JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht);
JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator
(Jim_HashTable *ht);
JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry
@@ -726,8 +785,6 @@ JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp,
Jim_Obj *objPtr, const char *str);
JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
Jim_Obj *secondObjPtr, int nocase);
-JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
- Jim_Obj *secondObjPtr, int nocase);
JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -751,9 +808,9 @@ JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp,
const char *cmdName, Jim_CmdProc *cmdProc, void *privData,
Jim_DelCmdProc *delProc);
JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp,
- const char *cmdName);
+ Jim_Obj *cmdNameObj);
JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
- const char *oldName, const char *newName);
+ Jim_Obj *oldNameObj, Jim_Obj *newNameObj);
JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp,
Jim_Obj *objPtr, int flags);
JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp,
@@ -824,8 +881,8 @@ JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp,
JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp,
Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc,
Jim_Obj *newObjPtr, int flags);
-JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
- Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
+JIM_EXPORT Jim_Obj **Jim_DictPairs(Jim_Interp *interp,
+ Jim_Obj *dictPtr, int *len);
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
@@ -854,6 +911,8 @@ JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr,
JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
jim_wide *widePtr);
+JIM_EXPORT int Jim_GetWideExpr(Jim_Interp *interp, Jim_Obj *objPtr,
+ jim_wide *widePtr);
JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
long *longPtr);
#define Jim_NewWideObj Jim_NewIntObj
@@ -885,6 +944,8 @@ JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key);
JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key,
Jim_InterpDeleteProc *delProc, void *data);
JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key);
+JIM_EXPORT int Jim_CheckAbiVersion(Jim_Interp *interp, int abi_version);
+
@@ -892,6 +953,9 @@ JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp,
const char *name, const char *ver, int flags);
JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp,
const char *name, int flags);
+#define Jim_PackageProvideCheck(INTERP, NAME) \
+ if (Jim_CheckAbiVersion(INTERP, JIM_ABI_VERSION) == JIM_ERR || Jim_PackageProvide(INTERP, NAME, "1.0", JIM_ERRMSG)) \
+ return JIM_ERR
JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp);
@@ -901,9 +965,12 @@ 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(Jim_Interp *interp, const char *prompt);
-JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj);
+JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *completionCommandObj);
+JIM_EXPORT void Jim_HistorySetHints(Jim_Interp *interp, Jim_Obj *hintsCommandObj);
JIM_EXPORT void Jim_HistoryAdd(const char *line);
JIM_EXPORT void Jim_HistoryShow(void);
+JIM_EXPORT void Jim_HistorySetMaxLen(int length);
+JIM_EXPORT int Jim_HistoryGetMaxLen(void);
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
@@ -911,13 +978,14 @@ JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
JIM_EXPORT int Jim_IsBigEndian(void);
#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
+JIM_EXPORT void Jim_SignalSetIgnored(jim_wide mask);
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
-JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
+JIM_EXPORT int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
@@ -954,6 +1022,9 @@ typedef struct {
unsigned short flags;
} jim_subcmd_type;
+#define JIM_DEF_SUBCMD(name, args, minargs, maxargs) { name, args, NULL, minargs, maxargs }
+#define JIM_DEF_SUBCMD_HIDDEN(name, args, minargs, maxargs) { name, args, NULL, minargs, maxargs, JIM_MODFLAG_HIDDEN }
+
const jim_subcmd_type *
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
@@ -961,6 +1032,8 @@ int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);
+void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type *ct, Jim_Obj *subcmd);
+
#ifdef __cplusplus
}
#endif
@@ -1036,16 +1109,17 @@ enum {
REG_ERR_NESTED_COUNT,
REG_ERR_INTERNAL,
REG_ERR_COUNT_FOLLOWS_NOTHING,
- REG_ERR_TRAILING_BACKSLASH,
+ REG_ERR_INVALID_ESCAPE,
REG_ERR_CORRUPTED,
REG_ERR_NULL_CHAR,
+ REG_ERR_UNMATCHED_BRACKET,
REG_ERR_NUM
};
-int regcomp(regex_t *preg, const char *regex, int cflags);
-int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
-void regfree(regex_t *preg);
+int jim_regcomp(regex_t *preg, const char *regex, int cflags);
+int jim_regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+size_t jim_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
+void jim_regfree(regex_t *preg);
#ifdef __cplusplus
}
@@ -1072,6 +1146,7 @@ const char *Jim_SignalId(int sig);
#include <stdio.h>
#include <errno.h>
+#include <sys/stat.h>
void Jim_SetResultErrno(Jim_Interp *interp, const char *msg);
@@ -1090,10 +1165,8 @@ int Jim_OpenForRead(const char *filename);
#include <io.h>
#include <process.h>
- typedef HANDLE pidtype;
- #define JIM_BAD_PID INVALID_HANDLE_VALUE
-
- #define JIM_NO_PID INVALID_HANDLE_VALUE
+ typedef HANDLE phandle_t;
+ #define JIM_BAD_PHANDLE INVALID_HANDLE_VALUE
#define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0)
@@ -1103,27 +1176,71 @@ int Jim_OpenForRead(const char *filename);
#define WNOHANG 1
int Jim_Errno(void);
- pidtype waitpid(pidtype pid, int *status, int nohang);
+
+ long waitpid(phandle_t phandle, int *status, int nohang);
+
+ phandle_t JimWaitPid(long processid, int *status, int nohang);
+
+ long JimProcessPid(phandle_t phandle);
#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 struct __stat64 jim_stat_t;
+ #define Jim_Stat _stat64
+ #define Jim_FileStat _fstat64
+ #define Jim_Lseek _lseeki64
- typedef int pidtype;
- #define Jim_Errno() errno
- #define JIM_BAD_PID -1
- #define JIM_NO_PID 0
+#else
+ #if defined(HAVE_STAT64)
+ typedef struct stat64 jim_stat_t;
+ #define Jim_Stat stat64
+ #if defined(HAVE_FSTAT64)
+ #define Jim_FileStat fstat64
+ #endif
+ #if defined(HAVE_LSTAT64)
+ #define Jim_LinkStat lstat64
+ #endif
+ #else
+ typedef struct stat jim_stat_t;
+ #define Jim_Stat stat
+ #if defined(HAVE_FSTAT)
+ #define Jim_FileStat fstat
+ #endif
+ #if defined(HAVE_LSTAT)
+ #define Jim_LinkStat lstat
+ #endif
+ #endif
+ #if defined(HAVE_LSEEK64)
+ #define Jim_Lseek lseek64
+ #else
+ #define Jim_Lseek lseek
+ #endif
+
+ #if defined(HAVE_UNISTD_H)
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/wait.h>
- #ifndef HAVE_EXECVPE
- #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
+ typedef int phandle_t;
+ #define Jim_Errno() errno
+ #define JIM_BAD_PHANDLE -1
+ #define JimProcessPid(PIDTYPE) (PIDTYPE)
+ #define JimWaitPid waitpid
+
+ #ifndef HAVE_EXECVPE
+ #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
+ #endif
#endif
#endif
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+
+
+int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb);
+
#endif
int Jim_bootstrapInit(Jim_Interp *interp)
{
@@ -1132,21 +1249,21 @@ int Jim_bootstrapInit(Jim_Interp *interp)
return Jim_EvalSource(interp, "bootstrap.tcl", 1,
"\n"
-"\n"
-"proc package {cmd pkg args} {\n"
+"proc package {cmd args} {\n"
" if {$cmd eq \"require\"} {\n"
" foreach path $::auto_path {\n"
+" lassign $args pkg\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"
+" tailcall uplevel #0 [list source $pkgpath]\n"
" }\n"
" }\n"
" }\n"
"}\n"
+"set tcl_platform(bootstrap) 1\n"
);
}
int Jim_initjimshInit(Jim_Interp *interp)
@@ -1201,7 +1318,7 @@ int Jim_initjimshInit(Jim_Interp *interp)
"}\n"
"\n"
"\n"
-"set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n"
+"set tcl::autocomplete_commands {array clock debug dict file history info namespace package signal socket string tcl::prefix zlib}\n"
"\n"
"\n"
"\n"
@@ -1233,6 +1350,63 @@ int Jim_initjimshInit(Jim_Interp *interp)
" }]\n"
"}\n"
"\n"
+"\n"
+"set tcl::stdhint_commands {array clock debug dict file history info namespace package signal string zlib}\n"
+"\n"
+"set tcl::stdhint_cols {\n"
+" none {0}\n"
+" black {30}\n"
+" red {31}\n"
+" green {32}\n"
+" yellow {33}\n"
+" blue {34}\n"
+" purple {35}\n"
+" cyan {36}\n"
+" normal {37}\n"
+" grey {30 1}\n"
+" gray {30 1}\n"
+" lred {31 1}\n"
+" lgreen {32 1}\n"
+" lyellow {33 1}\n"
+" lblue {34 1}\n"
+" lpurple {35 1}\n"
+" lcyan {36 1}\n"
+" white {37 1}\n"
+"}\n"
+"\n"
+"\n"
+"set tcl::stdhint_col $tcl::stdhint_cols(lcyan)\n"
+"\n"
+"\n"
+"proc tcl::stdhint {string} {\n"
+" set result \"\"\n"
+" if {[llength $string] >= 2} {\n"
+" lassign $string cmd arg\n"
+" if {$cmd in $::tcl::stdhint_commands || [info channel $cmd] ne \"\"} {\n"
+" catch {\n"
+" set help [$cmd -help $arg]\n"
+" if {[string match \"Usage: $cmd *\" $help]} {\n"
+" set n [llength $string]\n"
+" set subcmd [lindex $help $n]\n"
+" incr n\n"
+" set hint [join [lrange $help $n end]]\n"
+" set prefix \"\"\n"
+" if {![string match \"* \" $string]} {\n"
+" if {$n == 3 && $subcmd ne $arg} {\n"
+"\n"
+" set prefix \"[string range $subcmd [string length $arg] end] \"\n"
+" } else {\n"
+" set prefix \" \"\n"
+" }\n"
+" }\n"
+" set result [list $prefix$hint {*}$::tcl::stdhint_col]\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" return $result\n"
+"}\n"
+"\n"
"_jimsh_init\n"
);
}
@@ -1482,36 +1656,31 @@ int Jim_stdlibInit(Jim_Interp *interp)
"}\n"
"\n"
"\n"
-"\n"
-"\n"
-"proc stacktrace {{skip 0}} {\n"
-" set trace {}\n"
-" incr skip\n"
-" foreach level [range $skip [info level]] {\n"
-" lappend trace {*}[info frame -$level]\n"
-" }\n"
-" return $trace\n"
-"}\n"
-"\n"
-"\n"
"proc stackdump {stacktrace} {\n"
" set lines {}\n"
-" foreach {l f p} [lreverse $stacktrace] {\n"
+" lappend lines \"Traceback (most recent call last):\"\n"
+" foreach {cmd l f p} [lreverse $stacktrace] {\n"
" set line {}\n"
-" if {$p ne \"\"} {\n"
-" append line \"in procedure '$p' \"\n"
-" if {$f ne \"\"} {\n"
-" append line \"called \"\n"
-" }\n"
-" }\n"
" if {$f ne \"\"} {\n"
-" append line \"at file \\\"$f\\\", line $l\"\n"
+" append line \" File \\\"$f\\\", line $l\"\n"
+" }\n"
+" if {$p ne \"\"} {\n"
+" append line \", in $p\"\n"
" }\n"
" if {$line ne \"\"} {\n"
" lappend lines $line\n"
+" if {$cmd ne \"\"} {\n"
+" set nl [string first \\n $cmd 1]\n"
+" if {$nl >= 0} {\n"
+" set cmd [string range $cmd 0 $nl-1]...\n"
+" }\n"
+" lappend lines \" $cmd\"\n"
+" }\n"
" }\n"
" }\n"
-" join $lines \\n\n"
+" if {[llength $lines] > 1} {\n"
+" return [join $lines \\n]\n"
+" }\n"
"}\n"
"\n"
"\n"
@@ -1527,10 +1696,8 @@ int Jim_stdlibInit(Jim_Interp *interp)
" if {$stacktrace eq \"\"} {\n"
"\n"
" set stacktrace [info stacktrace]\n"
-"\n"
-" lappend stacktrace {*}[stacktrace 1]\n"
" }\n"
-" lassign $stacktrace p f l\n"
+" lassign $stacktrace p f l cmd\n"
" if {$f ne \"\"} {\n"
" set result \"$f:$l: Error: \"\n"
" }\n"
@@ -1643,7 +1810,7 @@ int Jim_tclcompatInit(Jim_Interp *interp)
"set env [env]\n"
"\n"
"\n"
-"if {[info commands stdout] ne \"\"} {\n"
+"if {[exists -command stdout]} {\n"
"\n"
" foreach p {gets flush close eof seek tell} {\n"
" proc $p {chan args} {p} {\n"
@@ -1817,72 +1984,6 @@ int Jim_tclcompatInit(Jim_Interp *interp)
"\n"
"\n"
"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"proc try {args} {\n"
-" set catchopts {}\n"
-" while {[string match -* [lindex $args 0]]} {\n"
-" set args [lassign $args opt]\n"
-" if {$opt eq \"--\"} {\n"
-" break\n"
-" }\n"
-" lappend catchopts $opt\n"
-" }\n"
-" if {[llength $args] == 0} {\n"
-" return -code error {wrong # args: should be \"try ?options? script ?argument ...?\"}\n"
-" }\n"
-" set args [lassign $args script]\n"
-" set code [catch -eval {*}$catchopts {uplevel 1 $script} msg opts]\n"
-"\n"
-" set handled 0\n"
-"\n"
-" foreach {on codes vars script} $args {\n"
-" switch -- $on \\\n"
-" on {\n"
-" if {!$handled && ($codes eq \"*\" || [info returncode $code] in $codes)} {\n"
-" lassign $vars msgvar optsvar\n"
-" if {$msgvar ne \"\"} {\n"
-" upvar $msgvar hmsg\n"
-" set hmsg $msg\n"
-" }\n"
-" if {$optsvar ne \"\"} {\n"
-" upvar $optsvar hopts\n"
-" set hopts $opts\n"
-" }\n"
-"\n"
-" set code [catch {uplevel 1 $script} msg opts]\n"
-" incr handled\n"
-" }\n"
-" } \\\n"
-" finally {\n"
-" set finalcode [catch {uplevel 1 $codes} finalmsg finalopts]\n"
-" if {$finalcode} {\n"
-"\n"
-" set code $finalcode\n"
-" set msg $finalmsg\n"
-" set opts $finalopts\n"
-" }\n"
-" break\n"
-" } \\\n"
-" default {\n"
-" return -code error \"try: expected 'on' or 'finally', got '$on'\"\n"
-" }\n"
-" }\n"
-"\n"
-" if {$code} {\n"
-" incr opts(-level)\n"
-" return {*}$opts $msg\n"
-" }\n"
-" return $msg\n"
-"}\n"
-"\n"
-"\n"
-"\n"
"proc throw {code {msg \"\"}} {\n"
" return -code $code $msg\n"
"}\n"
@@ -1898,17 +1999,21 @@ int Jim_tclcompatInit(Jim_Interp *interp)
}
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <assert.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <sys/stat.h>
#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
@@ -1923,8 +2028,6 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define HAVE_SOCKETS
#elif defined (__MINGW32__)
-#else
-#define JIM_ANSIC
#endif
#if defined(JIM_SSL)
@@ -1938,15 +2041,19 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define AIO_CMD_LEN 32
#define AIO_BUF_LEN 256
-
-#ifndef HAVE_FTELLO
- #define ftello ftell
-#endif
-#ifndef HAVE_FSEEKO
- #define fseeko fseek
-#endif
+#define AIO_WBUF_FULL_SIZE (64 * 1024)
#define AIO_KEEPOPEN 1
+#define AIO_NODELETE 2
+#define AIO_EOF 4
+#define AIO_WBUF_NONE 8
+#define AIO_NONBLOCK 16
+
+enum wbuftype {
+ WBUF_OPT_NONE,
+ WBUF_OPT_LINE,
+ WBUF_OPT_FULL,
+};
#if defined(JIM_IPV6)
#define IPV6 1
@@ -1956,20 +2063,49 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define PF_INET6 0
#endif
#endif
+#if defined(HAVE_SYS_UN_H) && defined(PF_UNIX)
+#define UNIX_SOCKETS 1
+#else
+#define UNIX_SOCKETS 0
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN JIM_PATH_LEN
+#endif
+
+
+
+
+static int JimReadableTimeout(int fd, long ms)
+{
+#ifdef HAVE_SELECT
+ int retval;
+ struct timeval tv;
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+
+ FD_SET(fd, &rfds);
+ tv.tv_sec = ms / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
-#ifdef JIM_ANSIC
+ retval = select(fd + 1, &rfds, NULL, NULL, ms == 0 ? NULL : &tv);
-#undef HAVE_PIPE
-#undef HAVE_SOCKETPAIR
+ if (retval > 0) {
+ return JIM_OK;
+ }
+ return JIM_ERR;
+#else
+ return JIM_OK;
#endif
+}
struct AioFile;
typedef struct {
int (*writer)(struct AioFile *af, const char *buf, int len);
- int (*reader)(struct AioFile *af, char *buf, int len);
- const char *(*getline)(struct AioFile *af, char *buf, int len);
+ int (*reader)(struct AioFile *af, char *buf, int len, int pending);
int (*error)(const struct AioFile *af);
const char *(*strerror)(struct AioFile *af);
int (*verify)(struct AioFile *af);
@@ -1977,55 +2113,60 @@ typedef struct {
typedef struct AioFile
{
- FILE *fp;
Jim_Obj *filename;
- int type;
- int openFlags;
+ int wbuft;
+ int flags;
+ long timeout;
int fd;
- Jim_Obj *rEvent;
- Jim_Obj *wEvent;
- Jim_Obj *eEvent;
int addr_family;
void *ssl;
const JimAioFopsType *fops;
+ Jim_Obj *readbuf;
+ Jim_Obj *writebuf;
} AioFile;
static int stdio_writer(struct AioFile *af, const char *buf, int len)
{
- return fwrite(buf, 1, len, af->fp);
+ return write(af->fd, buf, len);
}
-static int stdio_reader(struct AioFile *af, char *buf, int len)
+static int stdio_reader(struct AioFile *af, char *buf, int len, int nb)
{
- return fread(buf, 1, len, af->fp);
-}
+ if (nb || af->timeout == 0 || JimReadableTimeout(af->fd, af->timeout) == JIM_OK) {
-static const char *stdio_getline(struct AioFile *af, char *buf, int len)
-{
- return fgets(buf, len, af->fp);
+ int ret;
+
+ errno = 0;
+ ret = read(af->fd, buf, len);
+ if (ret <= 0 && errno != EAGAIN && errno != EINTR) {
+ af->flags |= AIO_EOF;
+ }
+ return ret;
+ }
+ errno = ETIMEDOUT;
+ return -1;
}
static int stdio_error(const AioFile *af)
{
- if (!ferror(af->fp)) {
+ if (af->flags & AIO_EOF) {
return JIM_OK;
}
- clearerr(af->fp);
- if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
- return JIM_OK;
- }
+ switch (errno) {
+ case EAGAIN:
+ case EINTR:
+ case ETIMEDOUT:
#ifdef ECONNRESET
- if (errno == ECONNRESET) {
- return JIM_OK;
- }
+ case ECONNRESET:
#endif
#ifdef ECONNABORTED
- if (errno == ECONNABORTED) {
- return JIM_OK;
- }
+ case ECONNABORTED:
#endif
- return JIM_ERR;
+ return JIM_OK;
+ default:
+ return JIM_ERR;
+ }
}
static const char *stdio_strerror(struct AioFile *af)
@@ -2036,16 +2177,43 @@ static const char *stdio_strerror(struct AioFile *af)
static const JimAioFopsType stdio_fops = {
stdio_writer,
stdio_reader,
- stdio_getline,
stdio_error,
stdio_strerror,
- NULL
+ NULL,
};
+static void aio_set_nonblocking(AioFile *af, int nb)
+{
+#ifdef O_NDELAY
+ int old = !!(af->flags & AIO_NONBLOCK);
+ if (old != nb) {
+ int fmode = fcntl(af->fd, F_GETFL);
+ if (nb) {
+ fmode |= O_NDELAY;
+ af->flags |= AIO_NONBLOCK;
+ }
+ else {
+ fmode &= ~O_NDELAY;
+ af->flags &= ~AIO_NONBLOCK;
+ }
+ (void)fcntl(af->fd, F_SETFL, fmode);
+ }
+#endif
+}
+
+static int aio_start_nonblocking(AioFile *af)
+{
+ int old = !!(af->flags & AIO_NONBLOCK);
+ if (af->timeout) {
+ aio_set_nonblocking(af, 1);
+ }
+ return old;
+}
+
static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
- const char *hdlfmt, int family, const char *mode);
+static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
+ const char *hdlfmt, int family, int flags);
static const char *JimAioErrorString(AioFile *af)
@@ -2068,13 +2236,141 @@ static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name)
}
}
+static int aio_eof(AioFile *af)
+{
+ return af->flags & AIO_EOF;
+}
+
static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
{
- int ret = af->fops->error(af);
- if (ret) {
- JimAioSetError(interp, af->filename);
- }
- return ret;
+ int ret = 0;
+ if (!aio_eof(af)) {
+ ret = af->fops->error(af);
+ if (ret) {
+ JimAioSetError(interp, af->filename);
+ }
+ }
+ return ret;
+}
+
+static void aio_consume(Jim_Obj *objPtr, int n)
+{
+ assert(objPtr->bytes);
+ assert(n <= objPtr->length);
+
+
+ memmove(objPtr->bytes, objPtr->bytes + n, objPtr->length - n + 1);
+ objPtr->length -= n;
+}
+
+
+static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask);
+
+static int aio_flush(Jim_Interp *interp, AioFile *af)
+{
+ int len;
+ const char *pt = Jim_GetString(af->writebuf, &len);
+ if (len) {
+ int ret = af->fops->writer(af, pt, len);
+ if (ret > 0) {
+
+ aio_consume(af->writebuf, ret);
+ }
+ if (ret < 0) {
+ return JimCheckStreamError(interp, af);
+ }
+ if (Jim_Length(af->writebuf)) {
+#ifdef jim_ext_eventloop
+ void *handler = Jim_FindFileHandler(interp, af->fd, JIM_EVENT_WRITABLE);
+ if (handler == NULL) {
+ Jim_CreateFileHandler(interp, af->fd, JIM_EVENT_WRITABLE, aio_autoflush, af, NULL);
+ return JIM_OK;
+ }
+ else if (handler == af) {
+
+ return JIM_OK;
+ }
+#endif
+
+ Jim_SetResultString(interp, "send buffer is full", -1);
+ return JIM_ERR;
+ }
+ }
+ return JIM_OK;
+}
+
+static int aio_autoflush(Jim_Interp *interp, void *clientData, int mask)
+{
+ AioFile *af = clientData;
+
+ aio_flush(interp, af);
+ if (Jim_Length(af->writebuf) == 0) {
+
+ return -1;
+ }
+ return 0;
+}
+
+static int aio_read_len(Jim_Interp *interp, AioFile *af, int nb, char *buf, size_t buflen, int neededLen)
+{
+ if (!af->readbuf) {
+ af->readbuf = Jim_NewStringObj(interp, NULL, 0);
+ }
+
+ if (neededLen >= 0) {
+ neededLen -= Jim_Length(af->readbuf);
+ if (neededLen <= 0) {
+ return JIM_OK;
+ }
+ }
+
+ while (neededLen && !aio_eof(af)) {
+ int retval;
+ int readlen;
+
+ if (neededLen == -1) {
+ readlen = AIO_BUF_LEN;
+ }
+ else {
+ readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
+ }
+ retval = af->fops->reader(af, buf, readlen, nb);
+ if (retval > 0) {
+ Jim_AppendString(interp, af->readbuf, buf, retval);
+ if (neededLen != -1) {
+ neededLen -= retval;
+ }
+ continue;
+ }
+ if (JimCheckStreamError(interp, af)) {
+ return JIM_ERR;
+ }
+ if (nb || af->timeout) {
+ return JIM_OK;
+ }
+ }
+
+ return JIM_OK;
+}
+
+static Jim_Obj *aio_read_consume(Jim_Interp *interp, AioFile *af, int neededLen)
+{
+ Jim_Obj *objPtr = NULL;
+
+ if (neededLen < 0 || af->readbuf == NULL || Jim_Length(af->readbuf) <= neededLen) {
+ objPtr = af->readbuf;
+ af->readbuf = NULL;
+ }
+ else if (af->readbuf) {
+
+ int len;
+ const char *pt = Jim_GetString(af->readbuf, &len);
+
+ objPtr = Jim_NewStringObj(interp, pt, neededLen);
+ aio_consume(af->readbuf, neededLen);
+ }
+
+ return objPtr;
}
static void JimAioDelProc(Jim_Interp *interp, void *privData)
@@ -2083,6 +2379,23 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
JIM_NOTUSED(interp);
+
+ aio_flush(interp, af);
+ Jim_DecrRefCount(interp, af->writebuf);
+
+#if UNIX_SOCKETS
+ if (af->addr_family == PF_UNIX && (af->flags & AIO_NODELETE) == 0) {
+
+ Jim_Obj *filenameObj = aio_sockname(interp, af->fd);
+ if (filenameObj) {
+ if (Jim_Length(filenameObj)) {
+ remove(Jim_String(filenameObj));
+ }
+ Jim_FreeNewObj(interp, filenameObj);
+ }
+ }
+#endif
+
Jim_DecrRefCount(interp, af->filename);
#ifdef jim_ext_eventloop
@@ -2095,8 +2408,11 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
SSL_free(af->ssl);
}
#endif
- if (!(af->openFlags & AIO_KEEPOPEN)) {
- fclose(af->fp);
+ if (!(af->flags & AIO_KEEPOPEN)) {
+ close(af->fd);
+ }
+ if (af->readbuf) {
+ Jim_FreeNewObj(interp, af->readbuf);
}
Jim_Free(af);
@@ -2105,96 +2421,93 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- char buf[AIO_BUF_LEN];
- Jim_Obj *objPtr;
int nonewline = 0;
jim_wide neededLen = -1;
+ static const char * const options[] = { "-pending", "-nonewline", NULL };
+ enum { OPT_PENDING, OPT_NONEWLINE };
+ int option;
+ int nb;
+ Jim_Obj *objPtr;
+ char buf[AIO_BUF_LEN];
- if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
- nonewline = 1;
- argv++;
- argc--;
- }
- if (argc == 1) {
- if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK)
- return JIM_ERR;
- if (neededLen < 0) {
- Jim_SetResultString(interp, "invalid parameter: negative len", -1);
- return JIM_ERR;
- }
- }
- else if (argc) {
- return -1;
- }
- objPtr = Jim_NewStringObj(interp, NULL, 0);
- while (neededLen != 0) {
- int retval;
- int readlen;
+ if (argc) {
+ if (*Jim_String(argv[0]) == '-') {
+ if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ switch (option) {
+ case OPT_PENDING:
- if (neededLen == -1) {
- readlen = AIO_BUF_LEN;
+ break;
+ case OPT_NONEWLINE:
+ nonewline++;
+ break;
+ }
}
else {
- readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
- }
- retval = af->fops->reader(af, buf, readlen);
- if (retval > 0) {
- Jim_AppendString(interp, objPtr, buf, retval);
- if (neededLen != -1) {
- neededLen -= retval;
+ if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK)
+ return JIM_ERR;
+ if (neededLen < 0) {
+ Jim_SetResultString(interp, "invalid parameter: negative len", -1);
+ return JIM_ERR;
}
}
- if (retval != readlen)
- break;
+ argc--;
+ argv++;
+ }
+ if (argc) {
+ return -1;
}
- if (JimCheckStreamError(interp, af)) {
- Jim_FreeNewObj(interp, objPtr);
+
+ nb = aio_start_nonblocking(af);
+
+ if (aio_read_len(interp, af, nb, buf, sizeof(buf), neededLen) != JIM_OK) {
+ aio_set_nonblocking(af, nb);
return JIM_ERR;
}
- if (nonewline) {
- int len;
- const char *s = Jim_GetString(objPtr, &len);
+ objPtr = aio_read_consume(interp, af, neededLen);
+
+ aio_set_nonblocking(af, nb);
+
+ if (objPtr) {
+ if (nonewline) {
+ int len;
+ const char *s = Jim_GetString(objPtr, &len);
- if (len > 0 && s[len - 1] == '\n') {
- objPtr->length--;
- objPtr->bytes[objPtr->length] = '\0';
+ if (len > 0 && s[len - 1] == '\n') {
+ objPtr->length--;
+ objPtr->bytes[objPtr->length] = '\0';
+ }
}
+ Jim_SetResult(interp, objPtr);
+ }
+ else {
+ Jim_SetEmptyResult(interp);
}
- Jim_SetResult(interp, objPtr);
return JIM_OK;
}
-AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
+int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
{
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
- return (AioFile *) cmdPtr->u.native.privData;
+ return ((AioFile *) cmdPtr->u.native.privData)->fd;
}
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
- return NULL;
-}
-
-FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
-{
- AioFile *af;
-
- af = Jim_AioFile(interp, command);
- if (af == NULL) {
- return NULL;
- }
-
- return af->fp;
+ return -1;
}
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));
+
+ aio_flush(interp, af);
+
+ Jim_SetResultInt(interp, af->fd);
return JIM_OK;
}
@@ -2204,11 +2517,13 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
AioFile *af = Jim_CmdPrivData(interp);
jim_wide count = 0;
jim_wide maxlen = JIM_WIDE_MAX;
- AioFile *outf = Jim_AioFile(interp, argv[0]);
- if (outf == NULL) {
- return JIM_ERR;
- }
+ char buf[AIO_BUF_LEN];
+
+ char *bufp = buf;
+ int buflen = sizeof(buf);
+ int ok = 1;
+ Jim_Obj *objv[4];
if (argc == 2) {
if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) {
@@ -2216,19 +2531,53 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
}
- while (count < maxlen) {
- char ch;
+ objv[0] = argv[0];
+ objv[1] = Jim_NewStringObj(interp, "flush", -1);
+ if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) {
+ Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", argv[0]);
+ return JIM_ERR;
+ }
+
+
+ objv[0] = argv[0];
+ objv[1] = Jim_NewStringObj(interp, "puts", -1);
+ objv[2] = Jim_NewStringObj(interp, "-nonewline", -1);
+ Jim_IncrRefCount(objv[1]);
+ Jim_IncrRefCount(objv[2]);
- if (af->fops->reader(af, &ch, 1) != 1) {
+ while (count < maxlen) {
+ jim_wide len = maxlen - count;
+ if (len > buflen) {
+ len = buflen;
+ }
+ if (aio_read_len(interp, af, 0, bufp, buflen, len) != JIM_OK) {
+ ok = 0;
break;
}
- if (outf->fops->writer(outf, &ch, 1) != 1) {
+ objv[3] = aio_read_consume(interp, af, len);
+ count += Jim_Length(objv[3]);
+ if (Jim_EvalObjVector(interp, 4, objv) != JIM_OK) {
+ ok = 0;
break;
}
- count++;
+ if (aio_eof(af)) {
+ break;
+ }
+ if (count >= 16384 && bufp == buf) {
+
+ buflen = 65536;
+ bufp = Jim_Alloc(buflen);
+ }
}
- if (JimCheckStreamError(interp, af) || JimCheckStreamError(interp, outf)) {
+ if (bufp != buf) {
+ Jim_Free(bufp);
+ }
+
+ Jim_DecrRefCount(interp, objv[1]);
+ Jim_DecrRefCount(interp, objv[2]);
+
+ if (!ok) {
return JIM_ERR;
}
@@ -2241,38 +2590,54 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
char buf[AIO_BUF_LEN];
- Jim_Obj *objPtr;
+ Jim_Obj *objPtr = NULL;
int len;
+ int nb;
+ char *nl = NULL;
+ int offset = 0;
errno = 0;
- objPtr = Jim_NewStringObj(interp, NULL, 0);
- while (1) {
- buf[AIO_BUF_LEN - 1] = '_';
- if (af->fops->getline(af, buf, AIO_BUF_LEN) == NULL)
- break;
+ nb = aio_start_nonblocking(af);
- if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') {
- Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1);
- }
- else {
- len = strlen(buf);
+ if (!af->readbuf) {
+ af->readbuf = Jim_NewStringObj(interp, NULL, 0);
+ }
- if (len && (buf[len - 1] == '\n')) {
+ while (!aio_eof(af)) {
+ const char *pt = Jim_GetString(af->readbuf, &len);
+ nl = memchr(pt + offset, '\n', len - offset);
+ if (nl) {
- len--;
- }
+ objPtr = Jim_NewStringObj(interp, pt, nl - pt);
- Jim_AppendString(interp, objPtr, buf, len);
+ aio_consume(af->readbuf, nl - pt + 1);
break;
}
+
+ offset = len;
+ len = af->fops->reader(af, buf, AIO_BUF_LEN, nb);
+ if (len <= 0) {
+ if (nb || af->timeout) {
+
+ break;
+ }
+ }
+ else {
+ Jim_AppendString(interp, af->readbuf, buf, len);
+ }
}
- if (JimCheckStreamError(interp, af)) {
+ aio_set_nonblocking(af, nb);
- Jim_FreeNewObj(interp, objPtr);
- return JIM_ERR;
+ if (!nl && aio_eof(af)) {
+
+ objPtr = af->readbuf;
+ af->readbuf = NULL;
+ }
+ else if (!objPtr) {
+ objPtr = Jim_NewStringObj(interp, NULL, 0);
}
if (argc) {
@@ -2283,7 +2648,7 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
len = Jim_Length(objPtr);
- if (len == 0 && feof(af->fp)) {
+ if (!nl && len == 0) {
len = -1;
}
@@ -2301,32 +2666,58 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int wlen;
const char *wdata;
Jim_Obj *strObj;
+ int wnow = 0;
+ int nl = 1;
if (argc == 2) {
if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
return -1;
}
strObj = argv[1];
+ nl = 0;
}
else {
strObj = argv[0];
}
- wdata = Jim_GetString(strObj, &wlen);
- if (af->fops->writer(af, wdata, wlen) == wlen) {
- if (argc == 2 || af->fops->writer(af, "\n", 1) == 1) {
- return JIM_OK;
- }
+ Jim_AppendObj(interp, af->writebuf, strObj);
+ if (nl) {
+ Jim_AppendString(interp, af->writebuf, "\n", 1);
}
- JimAioSetError(interp, af->filename);
- return JIM_ERR;
+
+
+ wdata = Jim_GetString(af->writebuf, &wlen);
+ switch (af->wbuft) {
+ case WBUF_OPT_NONE:
+
+ wnow = 1;
+ break;
+
+ case WBUF_OPT_LINE:
+
+ if (nl || memchr(wdata, '\n', wlen) != NULL) {
+ wnow = 1;
+ }
+ break;
+
+ case WBUF_OPT_FULL:
+ if (wlen >= AIO_WBUF_FULL_SIZE) {
+ wnow = 1;
+ }
+ break;
+ }
+
+ if (wnow) {
+ return aio_flush(interp, af);
+ }
+ return JIM_OK;
}
static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef HAVE_ISATTY
AioFile *af = Jim_CmdPrivData(interp);
- Jim_SetResultInt(interp, isatty(fileno(af->fp)));
+ Jim_SetResultInt(interp, isatty(af->fd));
#else
Jim_SetResultInt(interp, 0);
#endif
@@ -2338,45 +2729,58 @@ static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
-
- if (fflush(af->fp) == EOF) {
- JimAioSetError(interp, af->filename);
- return JIM_ERR;
- }
- return JIM_OK;
+ return aio_flush(interp, af);
}
static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- Jim_SetResultInt(interp, feof(af->fp));
+ Jim_SetResultInt(interp, !!aio_eof(af));
return JIM_OK;
}
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
+ AioFile *af = Jim_CmdPrivData(interp);
if (argc == 3) {
-#if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN)
- static const char * const options[] = { "r", "w", NULL };
- enum { OPT_R, OPT_W, };
- int option;
- AioFile *af = Jim_CmdPrivData(interp);
+ int option = -1;
+#if defined(HAVE_SOCKETS)
+ static const char * const options[] = { "r", "w", "-nodelete", NULL };
+ enum { OPT_R, OPT_W, OPT_NODELETE };
if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
return JIM_ERR;
}
- if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
- return JIM_OK;
- }
- JimAioSetError(interp, NULL);
-#else
- Jim_SetResultString(interp, "async close not supported", -1);
#endif
- return JIM_ERR;
+ switch (option) {
+#if defined(HAVE_SHUTDOWN)
+ case OPT_R:
+ case OPT_W:
+ if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
+ return JIM_OK;
+ }
+ JimAioSetError(interp, NULL);
+ return JIM_ERR;
+#endif
+#if UNIX_SOCKETS
+ case OPT_NODELETE:
+ if (af->addr_family == PF_UNIX) {
+ af->flags |= AIO_NODELETE;
+ break;
+ }
+
+#endif
+ default:
+ Jim_SetResultString(interp, "not supported", -1);
+ return JIM_ERR;
+ }
}
- return Jim_DeleteCommand(interp, Jim_String(argv[0]));
+
+ af->flags &= ~AIO_KEEPOPEN;
+
+ return Jim_DeleteCommand(interp, argv[0]);
}
static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -2399,10 +2803,19 @@ static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) {
return JIM_ERR;
}
- if (fseeko(af->fp, offset, orig) == -1) {
+ if (orig != SEEK_CUR || offset != 0) {
+
+ aio_flush(interp, af);
+ }
+ if (Jim_Lseek(af->fd, offset, orig) == -1) {
JimAioSetError(interp, af->filename);
return JIM_ERR;
}
+ if (af->readbuf) {
+ Jim_FreeNewObj(interp, af->readbuf);
+ af->readbuf = NULL;
+ }
+ af->flags &= ~AIO_EOF;
return JIM_OK;
}
@@ -2410,7 +2823,7 @@ static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- Jim_SetResultInt(interp, ftello(af->fp));
+ Jim_SetResultInt(interp, Jim_Lseek(af->fd, 0, SEEK_CUR));
return JIM_OK;
}
@@ -2427,23 +2840,15 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- int fmode = fcntl(af->fd, F_GETFL);
-
if (argc) {
long nb;
if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
return JIM_ERR;
}
- if (nb) {
- fmode |= O_NDELAY;
- }
- else {
- fmode &= ~O_NDELAY;
- }
- (void)fcntl(af->fd, F_SETFL, fmode);
+ aio_set_nonblocking(af, nb);
}
- Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
+ Jim_SetResultInt(interp, (af->flags & AIO_NONBLOCK) ? 1 : 0);
return JIM_OK;
}
#endif
@@ -2454,7 +2859,9 @@ static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- fflush(af->fp);
+ if (aio_flush(interp, af) != JIM_OK) {
+ return JIM_ERR;
+ }
fsync(af->fd);
return JIM_OK;
}
@@ -2470,76 +2877,56 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
"full",
NULL
};
- enum
- {
- OPT_NONE,
- OPT_LINE,
- OPT_FULL,
- };
- int option;
- if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+ if (Jim_GetEnum(interp, argv[0], options, &af->wbuft, NULL, JIM_ERRMSG) != JIM_OK) {
return JIM_ERR;
}
- switch (option) {
- case OPT_NONE:
- setvbuf(af->fp, NULL, _IONBF, 0);
- break;
- case OPT_LINE:
- setvbuf(af->fp, NULL, _IOLBF, BUFSIZ);
- break;
- case OPT_FULL:
- setvbuf(af->fp, NULL, _IOFBF, BUFSIZ);
- break;
- }
- return JIM_OK;
-}
-#ifdef jim_ext_eventloop
-static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
-{
- Jim_Obj **objPtrPtr = clientData;
+ if (af->wbuft == WBUF_OPT_NONE) {
+ return aio_flush(interp, af);
+ }
- Jim_DecrRefCount(interp, *objPtrPtr);
- *objPtrPtr = NULL;
+ return JIM_OK;
}
-static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
+static int aio_cmd_timeout(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- Jim_Obj **objPtrPtr = clientData;
-
- return Jim_EvalObjBackground(interp, *objPtrPtr);
+#ifdef HAVE_SELECT
+ AioFile *af = Jim_CmdPrivData(interp);
+ if (argc == 1) {
+ if (Jim_GetLong(interp, argv[0], &af->timeout) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+ Jim_SetResultInt(interp, af->timeout);
+ return JIM_OK;
+#else
+ Jim_SetResultString(interp, "timeout not supported", -1);
+ return JIM_ERR;
+#endif
}
-static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
+#ifdef jim_ext_eventloop
+static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask,
int argc, Jim_Obj * const *argv)
{
if (argc == 0) {
- if (*scriptHandlerObj) {
- Jim_SetResult(interp, *scriptHandlerObj);
+ Jim_Obj *objPtr = Jim_FindFileHandler(interp, af->fd, mask);
+ if (objPtr) {
+ Jim_SetResult(interp, objPtr);
}
return JIM_OK;
}
- if (*scriptHandlerObj) {
-
- Jim_DeleteFileHandler(interp, af->fd, mask);
- }
+ Jim_DeleteFileHandler(interp, af->fd, mask);
- if (Jim_Length(argv[0]) == 0) {
- return JIM_OK;
+ if (Jim_Length(argv[0])) {
+ Jim_CreateScriptFileHandler(interp, af->fd, mask, argv[0]);
}
-
- Jim_IncrRefCount(argv[0]);
- *scriptHandlerObj = argv[0];
-
- Jim_CreateFileHandler(interp, af->fd, mask,
- JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
-
return JIM_OK;
}
@@ -2547,21 +2934,35 @@ static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv);
+ return aio_eventinfo(interp, af, JIM_EVENT_READABLE, argc, argv);
}
static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv);
+ return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, argc, argv);
}
static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
+ return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, argc, argv);
+}
+#endif
+
+#if defined(jim_ext_file) && defined(Jim_FileStat)
+static int aio_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ jim_stat_t sb;
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ if (Jim_FileStat(af->fd, &sb) == -1) {
+ JimAioSetError(interp, NULL);
+ return JIM_ERR;
+ }
+ return Jim_FileStoreStatData(interp, argc == 0 ? NULL : argv[0], &sb);
}
#endif
@@ -2570,7 +2971,7 @@ static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *arg
static const jim_subcmd_type aio_command_table[] = {
{ "read",
- "?-nonewline? ?len?",
+ "?-nonewline|len?",
aio_cmd_read,
0,
2,
@@ -2679,6 +3080,15 @@ static const jim_subcmd_type aio_command_table[] = {
1,
},
+#if defined(jim_ext_file) && defined(Jim_FileStat)
+ { "stat",
+ "?var?",
+ aio_cmd_stat,
+ 0,
+ 1,
+
+ },
+#endif
#ifdef jim_ext_eventloop
{ "readable",
"?readable-script?",
@@ -2701,6 +3111,13 @@ static const jim_subcmd_type aio_command_table[] = {
1,
},
+ { "timeout",
+ "?ms?",
+ aio_cmd_timeout,
+ 0,
+ 1,
+
+ },
#endif
{ NULL }
};
@@ -2710,112 +3127,214 @@ static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv);
}
+static int parse_posix_open_mode(Jim_Interp *interp, Jim_Obj *modeObj)
+{
+ int i;
+ int flags = 0;
+ #ifndef O_NOCTTY
+
+ #define O_NOCTTY 0
+ #endif
+ static const char * const modetypes[] = {
+ "RDONLY", "WRONLY", "RDWR", "APPEND", "BINARY", "CREAT", "EXCL", "NOCTTY", "TRUNC", NULL
+ };
+ static const int modeflags[] = {
+ O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, 0, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC,
+ };
+
+ for (i = 0; i < Jim_ListLength(interp, modeObj); i++) {
+ int opt;
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, modeObj, i);
+ if (Jim_GetEnum(interp, objPtr, modetypes, &opt, "access mode", JIM_ERRMSG) != JIM_OK) {
+ return -1;
+ }
+ flags |= modeflags[opt];
+ }
+ return flags;
+}
+
+static int parse_open_mode(Jim_Interp *interp, Jim_Obj *filenameObj, Jim_Obj *modeObj)
+{
+
+ int flags;
+ const char *mode = Jim_String(modeObj);
+ if (*mode == 'R' || *mode == 'W') {
+ return parse_posix_open_mode(interp, modeObj);
+ }
+ if (*mode == 'r') {
+ flags = O_RDONLY;
+ }
+ else if (*mode == 'w') {
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
+ }
+ else if (*mode == 'a') {
+ flags = O_WRONLY | O_CREAT | O_APPEND;
+ }
+ else {
+ Jim_SetResultFormatted(interp, "%s: invalid open mode '%s'", Jim_String(filenameObj), mode);
+ return -1;
+ }
+ mode++;
+
+ if (*mode == 'b') {
+#ifdef O_BINARY
+ flags |= O_BINARY;
+#endif
+ mode++;
+ }
+
+ if (*mode == 't') {
+#ifdef O_TEXT
+ flags |= O_TEXT;
+#endif
+ mode++;
+ }
+
+ if (*mode == '+') {
+ mode++;
+
+ flags &= ~(O_RDONLY | O_WRONLY);
+ flags |= O_RDWR;
+ }
+
+ if (*mode == 'x') {
+ mode++;
+#ifdef O_EXCL
+ flags |= O_EXCL;
+#endif
+ }
+
+ if (*mode == 'F') {
+ mode++;
+#ifdef O_LARGEFILE
+ flags |= O_LARGEFILE;
+#endif
+ }
+
+ if (*mode == 'e') {
+
+ mode++;
+ }
+ return flags;
+}
+
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
Jim_Obj *const *argv)
{
- const char *mode;
+ int openflags;
+ const char *filename;
+ int fd = -1;
+ int n = 0;
+ int flags = 0;
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
+ if (argc > 2 && Jim_CompareStringImmediate(interp, argv[2], "-noclose")) {
+ flags = AIO_KEEPOPEN;
+ n++;
+ }
+ if (argc < 2 || argc > 3 + n) {
+ Jim_WrongNumArgs(interp, 1, argv, "filename ?-noclose? ?mode?");
return JIM_ERR;
}
- mode = (argc == 3) ? Jim_String(argv[2]) : "r";
+ filename = Jim_String(argv[1]);
#ifdef jim_ext_tclcompat
{
- const char *filename = Jim_String(argv[1]);
if (*filename == '|') {
Jim_Obj *evalObj[3];
+ int i = 0;
- evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
- evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
- evalObj[2] = Jim_NewStringObj(interp, mode, -1);
+ evalObj[i++] = Jim_NewStringObj(interp, "::popen", -1);
+ evalObj[i++] = Jim_NewStringObj(interp, filename + 1, -1);
+ if (argc == 3 + n) {
+ evalObj[i++] = argv[2 + n];
+ }
- return Jim_EvalObjVector(interp, 3, evalObj);
+ return Jim_EvalObjVector(interp, i, evalObj);
}
}
#endif
- return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode) ? JIM_OK : JIM_ERR;
+ if (argc == 3 + n) {
+ openflags = parse_open_mode(interp, argv[1], argv[2 + n]);
+ if (openflags == -1) {
+ return JIM_ERR;
+ }
+ }
+ else {
+ openflags = O_RDONLY;
+ }
+ fd = open(filename, openflags, 0666);
+ if (fd < 0) {
+ JimAioSetError(interp, argv[1]);
+ return JIM_ERR;
+ }
+
+ return JimMakeChannel(interp, fd, argv[1], "aio.handle%ld", 0, flags) ? JIM_OK : JIM_ERR;
}
-static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
- const char *hdlfmt, int family, const char *mode)
+static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
+ const char *hdlfmt, int family, int flags)
{
AioFile *af;
char buf[AIO_CMD_LEN];
- int openFlags = 0;
-
- snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
-
- if (fh) {
- openFlags = AIO_KEEPOPEN;
- }
+ Jim_Obj *cmdname;
snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
+ cmdname = Jim_NewStringObj(interp, buf, -1);
if (!filename) {
- filename = Jim_NewStringObj(interp, buf, -1);
+ filename = cmdname;
}
-
Jim_IncrRefCount(filename);
- if (fh == NULL) {
- if (fd >= 0) {
-#ifndef JIM_ANSIC
- fh = fdopen(fd, mode);
-#endif
- }
- else
- fh = fopen(Jim_String(filename), mode);
-
- if (fh == NULL) {
- JimAioSetError(interp, filename);
-#ifndef JIM_ANSIC
- if (fd >= 0) {
- close(fd);
- }
-#endif
- Jim_DecrRefCount(interp, filename);
- return NULL;
- }
- }
-
af = Jim_Alloc(sizeof(*af));
memset(af, 0, sizeof(*af));
- af->fp = fh;
af->filename = filename;
- af->openFlags = openFlags;
-#ifndef JIM_ANSIC
- af->fd = fileno(fh);
+ af->fd = fd;
+ af->addr_family = family;
+ af->fops = &stdio_fops;
+ af->ssl = NULL;
+ if (flags & AIO_WBUF_NONE) {
+ af->wbuft = WBUF_OPT_NONE;
+ }
+ else {
+#ifdef HAVE_ISATTY
+ af->wbuft = isatty(af->fd) ? WBUF_OPT_LINE : WBUF_OPT_FULL;
+#else
+ af->wbuft = WBUF_OPT_FULL;
+#endif
+ }
+
#ifdef FD_CLOEXEC
- if ((openFlags & AIO_KEEPOPEN) == 0) {
+ if ((flags & AIO_KEEPOPEN) == 0) {
(void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
}
#endif
-#endif
- af->addr_family = family;
- af->fops = &stdio_fops;
- af->ssl = NULL;
+ aio_set_nonblocking(af, !!(flags & AIO_NONBLOCK));
+
+ af->flags |= flags;
+
+ af->writebuf = Jim_NewStringObj(interp, NULL, 0);
+ Jim_IncrRefCount(af->writebuf);
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
- Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
+ Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, cmdname));
return af;
}
-#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H))
+#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && UNIX_SOCKETS) || defined(HAVE_OPENPTY)
static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
- const char *hdlfmt, int family, const char *mode[2])
+ const char *hdlfmt, int family, int flags)
{
- if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
+ if (JimMakeChannel(interp, p[0], filename, hdlfmt, family, flags)) {
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])) {
+ if (JimMakeChannel(interp, p[1], filename, hdlfmt, family, flags)) {
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
Jim_SetResult(interp, objPtr);
return JIM_OK;
@@ -2831,22 +3350,48 @@ static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
#endif
#ifdef HAVE_PIPE
+static int JimCreatePipe(Jim_Interp *interp, Jim_Obj *filenameObj, int flags)
+{
+ int p[2];
+
+ if (pipe(p) != 0) {
+ JimAioSetError(interp, NULL);
+ return JIM_ERR;
+ }
+
+ return JimMakeChannelPair(interp, p, filenameObj, "aio.pipe%ld", 0, flags);
+}
+
+
static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
+ if (argc != 1) {
+ Jim_WrongNumArgs(interp, 1, argv, "");
+ return JIM_ERR;
+ }
+ return JimCreatePipe(interp, argv[0], 0);
+}
+#endif
+
+#ifdef HAVE_OPENPTY
+static int JimAioOpenPtyCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
int p[2];
- static const char *mode[2] = { "r", "w" };
+ char path[MAXPATHLEN];
if (argc != 1) {
Jim_WrongNumArgs(interp, 1, argv, "");
return JIM_ERR;
}
- if (pipe(p) != 0) {
+ if (openpty(&p[0], &p[1], path, NULL, NULL) != 0) {
JimAioSetError(interp, NULL);
return JIM_ERR;
}
- return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode);
+
+ return JimMakeChannelPair(interp, p, Jim_NewStringObj(interp, path, -1), "aio.pty%ld", 0, 0);
+ return JimMakeChannelPair(interp, p, Jim_NewStringObj(interp, path, -1), "aio.pty%ld", 0, 0);
}
#endif
@@ -2870,9 +3415,9 @@ int Jim_aioInit(Jim_Interp *interp)
#endif
- JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
- JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
- JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
+ JimMakeChannel(interp, fileno(stdin), NULL, "stdin", 0, AIO_KEEPOPEN);
+ JimMakeChannel(interp, fileno(stdout), NULL, "stdout", 0, AIO_KEEPOPEN);
+ JimMakeChannel(interp, fileno(stderr), NULL, "stderr", 0, AIO_KEEPOPEN | AIO_WBUF_NONE);
return JIM_OK;
}
@@ -2934,9 +3479,7 @@ int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int Jim_readdirInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
- return JIM_ERR;
-
+ Jim_PackageProvideCheck(interp, "readdir");
Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
return JIM_OK;
}
@@ -2947,11 +3490,15 @@ int Jim_readdirInit(Jim_Interp *interp)
#if defined(JIM_REGEXP)
#else
#include <regex.h>
+ #define jim_regcomp regcomp
+ #define jim_regexec regexec
+ #define jim_regerror regerror
+ #define jim_regfree regfree
#endif
static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
- regfree(objPtr->internalRep.ptrIntValue.ptr);
+ jim_regfree(objPtr->internalRep.ptrIntValue.ptr);
Jim_Free(objPtr->internalRep.ptrIntValue.ptr);
}
@@ -2982,12 +3529,12 @@ static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned f
pattern = Jim_String(objPtr);
compre = Jim_Alloc(sizeof(regex_t));
- if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
+ if ((ret = jim_regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
char buf[100];
- regerror(ret, compre, buf, sizeof(buf));
+ jim_regerror(ret, compre, buf, sizeof(buf));
Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf);
- regfree(compre);
+ jim_regfree(compre);
Jim_Free(compre);
return NULL;
}
@@ -3112,7 +3659,7 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
source_str += source_len;
}
else if (offset > 0) {
- source_str += offset;
+ source_str += utf8_index(source_str, offset);
}
eflags |= REG_NOTBOL;
}
@@ -3122,11 +3669,11 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
next_match:
- match = regexec(regex, source_str, num_vars + 1, pmatch, eflags);
+ match = jim_regexec(regex, source_str, num_vars + 1, pmatch, eflags);
if (match >= REG_BADPAT) {
char buf[100];
- regerror(match, regex, buf, sizeof(buf));
+ jim_regerror(match, regex, buf, sizeof(buf));
Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf);
result = JIM_ERR;
goto done;
@@ -3162,16 +3709,15 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
}
else {
- int len = pmatch[j].rm_eo - pmatch[j].rm_so;
-
if (opt_indices) {
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
- offset + pmatch[j].rm_so));
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
- offset + pmatch[j].rm_so + len - 1));
+
+ int so = utf8_strlen(source_str, pmatch[j].rm_so);
+ int eo = utf8_strlen(source_str, pmatch[j].rm_eo);
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + so));
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + eo - 1));
}
else {
- Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len);
+ Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, pmatch[j].rm_eo - pmatch[j].rm_so);
}
}
@@ -3192,7 +3738,7 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
try_next_match:
if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) {
if (pmatch[0].rm_eo) {
- offset += pmatch[0].rm_eo;
+ offset += utf8_strlen(source_str, pmatch[0].rm_eo);
source_str += pmatch[0].rm_eo;
}
else {
@@ -3321,6 +3867,8 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
}
+ offset = utf8_index(source_str, offset);
+
Jim_AppendString(interp, resultObj, source_str, offset);
@@ -3328,12 +3876,12 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
n = source_len - offset;
p = source_str + offset;
do {
- int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags);
+ int match = jim_regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags);
if (match >= REG_BADPAT) {
char buf[100];
- regerror(match, regex, buf, sizeof(buf));
+ jim_regerror(match, regex, buf, sizeof(buf));
Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf);
return JIM_ERR;
}
@@ -3398,7 +3946,14 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
n--;
}
- regexec_flags |= REG_NOTBOL;
+ if (pmatch[0].rm_eo == pmatch[0].rm_so) {
+
+ regexec_flags = REG_NOTBOL;
+ }
+ else {
+ regexec_flags = 0;
+ }
+
} while (n);
Jim_AppendString(interp, resultObj, p, -1);
@@ -3424,9 +3979,7 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int Jim_regexpInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG))
- return JIM_ERR;
-
+ Jim_PackageProvideCheck(interp, "regexp");
Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL);
Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
return JIM_OK;
@@ -3437,7 +3990,6 @@ int Jim_regexpInit(Jim_Interp *interp)
#include <string.h>
#include <stdio.h>
#include <errno.h>
-#include <sys/stat.h>
#ifdef HAVE_UTIMES
@@ -3455,11 +4007,17 @@ int Jim_regexpInit(Jim_Interp *interp)
#endif
# ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# else
# define MAXPATHLEN JIM_PATH_LEN
# endif
+# endif
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
#define ISWINDOWS 1
+
+#undef HAVE_SYMLINK
#else
#define ISWINDOWS 0
#endif
@@ -3472,6 +4030,18 @@ int Jim_regexpInit(Jim_Interp *interp)
#endif
+static void JimFixPath(char *path)
+{
+ if (ISWINDOWS) {
+
+ char *p = path;
+ while ((p = strchr(p, '\\')) != NULL) {
+ *p++ = '/';
+ }
+ }
+}
+
+
static const char *JimGetFileType(int mode)
{
if (S_ISREG(mode)) {
@@ -3514,7 +4084,7 @@ static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
}
-static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
+int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb)
{
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
@@ -3568,16 +4138,44 @@ static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat
return JIM_OK;
}
+static int JimPathLenNoTrailingSlashes(const char *path, int len)
+{
+ int i;
+ for (i = len; i > 1 && path[i - 1] == '/'; i--) {
+
+ if (ISWINDOWS && path[i - 2] == ':') {
+
+ break;
+ }
+ }
+ return i;
+}
+
+static Jim_Obj *JimStripTrailingSlashes(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+ int len = Jim_Length(objPtr);
+ const char *path = Jim_String(objPtr);
+ int i = JimPathLenNoTrailingSlashes(path, len);
+ if (i != len) {
+ objPtr = Jim_NewStringObj(interp, path, i);
+ }
+ Jim_IncrRefCount(objPtr);
+ return objPtr;
+}
+
static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *p = strrchr(path, '/');
- if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') {
- Jim_SetResultString(interp, "..", -1);
- } else if (!p) {
+ if (!p) {
Jim_SetResultString(interp, ".", -1);
}
+ else if (p[1] == 0) {
+
+ Jim_SetResult(interp, objPtr);
+ }
else if (p == path) {
Jim_SetResultString(interp, "/", -1);
}
@@ -3586,8 +4184,40 @@ static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_SetResultString(interp, path, p - path + 1);
}
else {
- Jim_SetResultString(interp, path, p - path);
+
+ int len = JimPathLenNoTrailingSlashes(path, p - path);
+ Jim_SetResultString(interp, path, len);
}
+ Jim_DecrRefCount(interp, objPtr);
+ return JIM_OK;
+}
+
+static int file_cmd_split(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+ const char *path = Jim_String(argv[0]);
+
+ if (*path == '/') {
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "/", 1));
+ }
+
+ while (1) {
+
+ while (*path == '/') {
+ path++;
+ }
+ if (*path) {
+ const char *pt = strchr(path, '/');
+ if (pt) {
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, path, pt - path));
+ path = pt;
+ continue;
+ }
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, path, -1));
+ }
+ break;
+ }
+ Jim_SetResult(interp, listObj);
return JIM_OK;
}
@@ -3608,7 +4238,8 @@ static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *lastSlash = strrchr(path, '/');
const char *p = strrchr(path, '.');
@@ -3616,42 +4247,54 @@ static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv
p = "";
}
Jim_SetResultString(interp, p, -1);
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}
static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *lastSlash = strrchr(path, '/');
if (lastSlash) {
Jim_SetResultString(interp, lastSlash + 1, -1);
}
else {
- Jim_SetResult(interp, argv[0]);
+ Jim_SetResult(interp, objPtr);
}
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}
+#ifndef HAVE_RESTRICT
+#define restrict
+#endif
+
+static char *JimRealPath(const char *restrict path, char *restrict resolved_path, size_t len)
+{
+#if defined(HAVE__FULLPATH)
+ return _fullpath(resolved_path, path, len);
+#elif defined(HAVE_REALPATH)
+ return realpath(path, resolved_path);
+#else
+ return NULL;
+#endif
+}
+
static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-#ifdef HAVE_REALPATH
const char *path = Jim_String(argv[0]);
- char *newname = Jim_Alloc(MAXPATHLEN + 1);
+ char *newname = Jim_Alloc(MAXPATHLEN);
- if (realpath(path, newname)) {
+ if (JimRealPath(path, newname, MAXPATHLEN)) {
+ JimFixPath(newname);
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1));
return JIM_OK;
}
- else {
- Jim_Free(newname);
- Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno));
- return JIM_ERR;
- }
-#else
- Jim_SetResultString(interp, "Not implemented", -1);
+ Jim_Free(newname);
+ Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno));
return JIM_ERR;
-#endif
}
static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3757,8 +4400,8 @@ 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--;
+ argc--;
+ argv++;
}
while (argc--) {
@@ -3815,9 +4458,9 @@ static int mkdir_all(char *path)
}
if (errno == EEXIST) {
- struct stat sb;
+ jim_stat_t sb;
- if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+ if (Jim_Stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
return 0;
}
@@ -3881,7 +4524,12 @@ static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
argv[1]);
return JIM_ERR;
}
+#if ISWINDOWS
+ if (access(dest, F_OK) == 0) {
+ remove(dest);
+ }
+#endif
if (rename(source, dest) != 0) {
Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1],
strerror(errno));
@@ -3929,23 +4577,23 @@ static int file_cmd_link(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#endif
-static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
+static int file_stat(Jim_Interp *interp, Jim_Obj *filename, jim_stat_t *sb)
{
const char *path = Jim_String(filename);
- if (stat(path, sb) == -1) {
+ if (Jim_Stat(path, sb) == -1) {
Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
return JIM_ERR;
}
return JIM_OK;
}
-#ifdef HAVE_LSTAT
-static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
+#ifdef Jim_LinkStat
+static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, jim_stat_t *sb)
{
const char *path = Jim_String(filename);
- if (lstat(path, sb) == -1) {
+ if (Jim_LinkStat(path, sb) == -1) {
Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
return JIM_ERR;
}
@@ -3957,7 +4605,7 @@ static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
@@ -3987,7 +4635,7 @@ static int JimSetFileTimes(Jim_Interp *interp, const char *filename, jim_wide us
static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (argc == 2) {
jim_wide secs;
@@ -4006,7 +4654,7 @@ static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
#ifdef STAT_MTIME_US
static int file_cmd_mtimeus(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (argc == 2) {
jim_wide us;
@@ -4030,7 +4678,7 @@ static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
@@ -4041,7 +4689,7 @@ static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
int ret = 0;
if (file_stat(interp, argv[0], &sb) == JIM_OK) {
@@ -4053,7 +4701,7 @@ static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *ar
static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
int ret = 0;
if (file_stat(interp, argv[0], &sb) == JIM_OK) {
@@ -4066,7 +4714,7 @@ static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
#ifdef HAVE_GETEUID
static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
int ret = 0;
if (file_stat(interp, argv[0], &sb) == JIM_OK) {
@@ -4087,7 +4735,7 @@ static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (linkLength == -1) {
Jim_Free(linkValue);
- Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno));
+ Jim_SetResultFormatted(interp, "could not read link \"%#s\": %s", argv[0], strerror(errno));
return JIM_ERR;
}
linkValue[linkLength] = 0;
@@ -4098,7 +4746,7 @@ static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
@@ -4107,15 +4755,15 @@ static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
-#ifdef HAVE_LSTAT
+#ifdef Jim_LinkStat
static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
- return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
+ return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}
#else
#define file_cmd_lstat file_cmd_stat
@@ -4123,12 +4771,12 @@ static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct stat sb;
+ jim_stat_t sb;
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
- return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
+ return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}
static const jim_subcmd_type file_command_table[] = {
@@ -4190,6 +4838,13 @@ static const jim_subcmd_type file_command_table[] = {
1,
},
+ { "split",
+ "name",
+ file_cmd_split,
+ 1,
+ 1,
+
+ },
{ "normalize",
"name",
file_cmd_normalize,
@@ -4362,14 +5017,7 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_Free(cwd);
return JIM_ERR;
}
- else if (ISWINDOWS) {
-
- char *p = cwd;
- while ((p = strchr(p, '\\')) != NULL) {
- *p++ = '/';
- }
- }
-
+ JimFixPath(cwd);
Jim_SetResultString(interp, cwd, -1);
Jim_Free(cwd);
@@ -4378,23 +5026,18 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int Jim_fileInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG))
- return JIM_ERR;
-
+ Jim_PackageProvideCheck(interp, "file");
Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL);
Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
return JIM_OK;
}
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
#include <string.h>
#include <ctype.h>
-#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
+#if (!(defined(HAVE_VFORK) || defined(HAVE_FORK)) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
@@ -4442,9 +5085,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int Jim_execInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
- return JIM_ERR;
-
+ Jim_PackageProvideCheck(interp, "exec");
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
return JIM_OK;
}
@@ -4461,13 +5102,13 @@ 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, 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);
+ phandle_t **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
+static void JimDetachPids(struct WaitInfoTable *table, int numPids, const phandle_t *pidPtr);
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj);
static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
#if defined(__MINGW32__)
-static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId);
+static phandle_t JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId);
#endif
static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
@@ -4484,24 +5125,19 @@ static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj)
{
char buf[256];
- FILE *fh = fdopen(fd, "r");
int ret = 0;
- if (fh == NULL) {
- return -1;
- }
-
while (1) {
- int retval = fread(buf, 1, sizeof(buf), fh);
+ int retval = read(fd, buf, sizeof(buf));
if (retval > 0) {
ret = 1;
Jim_AppendString(interp, strObj, buf, retval);
}
- if (retval != sizeof(buf)) {
+ if (retval <= 0) {
break;
}
}
- fclose(fh);
+ close(fd);
return ret;
}
@@ -4560,18 +5196,18 @@ static void JimFreeEnv(char **env, char **original_environ)
}
}
-static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
+static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, long pid, int waitStatus, Jim_Obj *errStrObj)
{
Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
- if (pid == JIM_BAD_PID || pid == JIM_NO_PID) {
+ if (pid <= 0) {
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, pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1));
}
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, pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
}
else {
@@ -4596,13 +5232,13 @@ static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus
Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL);
}
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1));
}
return errorCode;
}
-static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
+static int JimCheckWaitStatus(Jim_Interp *interp, long pid, int waitStatus, Jim_Obj *errStrObj)
{
if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
return JIM_OK;
@@ -4615,7 +5251,7 @@ static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, J
struct WaitInfo
{
- pidtype pid;
+ phandle_t phandle;
int status;
int flags;
};
@@ -4653,13 +5289,13 @@ static struct WaitInfoTable *JimAllocWaitInfoTable(void)
return table;
}
-static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid)
+static int JimWaitRemove(struct WaitInfoTable *table, phandle_t phandle)
{
int i;
for (i = 0; i < table->used; i++) {
- if (pid == table->info[i].pid) {
+ if (phandle == table->info[i].phandle) {
if (i != table->used - 1) {
table->info[i] = table->info[table->used - 1];
}
@@ -4674,7 +5310,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int outputId;
int errorId;
- pidtype *pidPtr;
+ phandle_t *pidPtr;
int numPids, result;
int child_siginfo = 1;
Jim_Obj *childErrObj;
@@ -4693,7 +5329,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
listObj = Jim_NewListObj(interp, NULL, 0);
for (i = 0; i < numPids; i++) {
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, JimProcessPid(pidPtr[i])));
}
Jim_SetResult(interp, listObj);
JimDetachPids(table, numPids, pidPtr);
@@ -4730,7 +5366,7 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (errorId != -1) {
int ret;
- lseek(errorId, 0, SEEK_SET);
+ Jim_Lseek(errorId, 0, SEEK_SET);
ret = JimAppendStreamToString(interp, errorId, errStrObj);
if (ret < 0) {
Jim_SetResultErrno(interp, "error reading from error pipe");
@@ -4757,19 +5393,18 @@ 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)
+static long JimWaitForProcess(struct WaitInfoTable *table, phandle_t phandle, int *statusPtr)
{
- if (JimWaitRemove(table, pid) == 0) {
+ if (JimWaitRemove(table, phandle) == 0) {
- waitpid(pid, statusPtr, 0);
- return pid;
+ return waitpid(phandle, statusPtr, 0);
}
- return JIM_BAD_PID;
+ return -1;
}
-static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr)
+static void JimDetachPids(struct WaitInfoTable *table, int numPids, const phandle_t *pidPtr)
{
int j;
@@ -4777,7 +5412,7 @@ static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtyp
int i;
for (i = 0; i < table->used; i++) {
- if (pidPtr[j] == table->info[i].pid) {
+ if (pidPtr[j] == table->info[i].phandle) {
table->info[i].flags |= WI_DETACHED;
break;
}
@@ -4816,8 +5451,8 @@ static void JimReapDetachedPids(struct WaitInfoTable *table)
for (count = table->used; count > 0; waitPtr++, count--) {
if (waitPtr->flags & WI_DETACHED) {
int status;
- pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG);
- if (pid == waitPtr->pid) {
+ long pid = waitpid(waitPtr->phandle, &status, WNOHANG);
+ if (pid > 0) {
table->used--;
continue;
@@ -4834,8 +5469,8 @@ static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
int nohang = 0;
- pidtype pid;
- long pidarg;
+ long pid;
+ phandle_t phandle;
int status;
Jim_Obj *errCodeObj;
@@ -4852,17 +5487,26 @@ static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?");
return JIM_ERR;
}
- if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) {
+ if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) {
return JIM_ERR;
}
- pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0);
+
+ phandle = JimWaitPid(pid, &status, nohang ? WNOHANG : 0);
+ if (phandle == JIM_BAD_PHANDLE) {
+ pid = -1;
+ }
+#ifndef __MINGW32__
+ else if (pid < 0) {
+ pid = phandle;
+ }
+#endif
errCodeObj = JimMakeErrorCode(interp, pid, status, NULL);
- if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) {
+ if (phandle != JIM_BAD_PHANDLE && (WIFEXITED(status) || WIFSIGNALED(status))) {
- JimWaitRemove(table, pid);
+ JimWaitRemove(table, phandle);
}
Jim_SetResult(interp, errCodeObj);
return JIM_OK;
@@ -4880,10 +5524,10 @@ static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
static int
-JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
+JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, phandle_t **pidArrayPtr,
int *inPipePtr, int *outPipePtr, int *errFilePtr)
{
- pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all
+ phandle_t *pidPtr = NULL; /* Points to alloc-ed array holding all
* the pids of child processes. */
int numPids = 0; /* Actual number of processes that exist
* at *pidPtr right now. */
@@ -4927,9 +5571,9 @@ JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **
* current command. */
int lastBar;
int i;
- pidtype pid;
+ phandle_t phandle;
char **save_environ;
-#ifndef __MINGW32__
+#if defined(HAVE_EXECVPE) && !defined(__MINGW32__)
char **child_environ;
#endif
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -5055,7 +5699,7 @@ badargs:
close(inputId);
goto error;
}
- lseek(inputId, 0L, SEEK_SET);
+ Jim_Lseek(inputId, 0L, SEEK_SET);
}
else if (inputFile == FILE_HANDLE) {
int fd = JimGetChannelFd(interp, input);
@@ -5147,9 +5791,6 @@ badargs:
pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
- for (i = 0; i < numPids; i++) {
- pidPtr[i] = JIM_BAD_PID;
- }
for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
int pipe_dup_err = 0;
int origErrorId = errorId;
@@ -5191,42 +5832,48 @@ badargs:
#ifdef __MINGW32__
- pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
- if (pid == JIM_BAD_PID) {
+ phandle = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
+ if (phandle == JIM_BAD_PHANDLE) {
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
goto error;
}
#else
i = strlen(arg_array[firstArg]);
+#ifdef HAVE_EXECVPE
child_environ = Jim_GetEnviron();
- pid = vfork();
- if (pid < 0) {
+#endif
+#ifdef HAVE_VFORK
+ phandle = vfork();
+#else
+ phandle = fork();
+#endif
+ if (phandle < 0) {
Jim_SetResultErrno(interp, "couldn't fork child process");
goto error;
}
- if (pid == 0) {
+ if (phandle == 0) {
- if (inputId != -1) {
+ if (inputId != -1 && inputId != fileno(stdin)) {
dup2(inputId, fileno(stdin));
close(inputId);
}
- if (outputId != -1) {
+ if (outputId != -1 && outputId != fileno(stdout)) {
dup2(outputId, fileno(stdout));
if (outputId != errorId) {
close(outputId);
}
}
- if (errorId != -1) {
+ if (errorId != -1 && errorId != fileno(stderr)) {
dup2(errorId, fileno(stderr));
close(errorId);
}
- if (outPipePtr) {
+ if (outPipePtr && *outPipePtr != -1) {
close(*outPipePtr);
}
- if (errFilePtr) {
+ if (errFilePtr && *errFilePtr != -1) {
close(*errFilePtr);
}
if (pipeIds[0] != -1) {
@@ -5236,9 +5883,6 @@ badargs:
close(lastOutputId);
}
-
- (void)signal(SIGPIPE, SIG_DFL);
-
execvpe(arg_array[firstArg], &arg_array[firstArg], child_environ);
if (write(fileno(stderr), "couldn't exec \"", 15) &&
@@ -5264,11 +5908,11 @@ badargs:
table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
}
- table->info[table->used].pid = pid;
+ table->info[table->used].phandle = phandle;
table->info[table->used].flags = 0;
table->used++;
- pidPtr[numPids] = pid;
+ pidPtr[numPids] = phandle;
errorId = origErrorId;
@@ -5324,7 +5968,7 @@ badargs:
}
if (pidPtr != NULL) {
for (i = 0; i < numPids; i++) {
- if (pidPtr[i] != JIM_BAD_PID) {
+ if (pidPtr[i] != JIM_BAD_PHANDLE) {
JimDetachPids(table, 1, &pidPtr[i]);
}
}
@@ -5335,7 +5979,7 @@ badargs:
}
-static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj)
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj)
{
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
int result = JIM_OK;
@@ -5344,8 +5988,9 @@ static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr,
for (i = 0; i < numPids; i++) {
int waitStatus = 0;
- if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
- if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
+ long pid = JimWaitForProcess(table, pidPtr[i], &waitStatus);
+ if (pid > 0) {
+ if (JimCheckWaitStatus(interp, pid, waitStatus, errStrObj) != JIM_OK) {
result = JIM_ERR;
}
}
@@ -5358,12 +6003,8 @@ 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;
-#ifdef SIGPIPE
- (void)signal(SIGPIPE, SIG_IGN);
-#endif
+ Jim_PackageProvideCheck(interp, "exec");
waitinfo = JimAllocWaitInfoTable();
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable);
@@ -5485,19 +6126,19 @@ JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
return strObj;
}
-static pidtype
+static phandle_t
JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId)
{
STARTUPINFO startInfo;
PROCESS_INFORMATION procInfo;
HANDLE hProcess;
char execPath[MAX_PATH];
- pidtype pid = JIM_BAD_PID;
+ phandle_t phandle = INVALID_HANDLE_VALUE;
Jim_Obj *cmdLineObj;
char *winenv;
if (JimWinFindExecutable(argv[0], execPath) < 0) {
- return JIM_BAD_PID;
+ return phandle;
}
argv[0] = execPath;
@@ -5560,7 +6201,7 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int
WaitForInputIdle(procInfo.hProcess, 5000);
CloseHandle(procInfo.hThread);
- pid = procInfo.hProcess;
+ phandle = procInfo.hProcess;
end:
Jim_FreeNewObj(interp, cmdLineObj);
@@ -5573,7 +6214,7 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int
if (startInfo.hStdError != INVALID_HANDLE_VALUE) {
CloseHandle(startInfo.hStdError);
}
- return pid;
+ return phandle;
}
#else
@@ -5599,18 +6240,6 @@ 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>
#include <stdio.h>
@@ -5734,37 +6363,32 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- Jim_SetResultInt(interp, time(NULL));
+ Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000000);
+ return JIM_OK;
+}
+static int clock_cmd_clicks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW));
return JIM_OK;
}
static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec);
-
+ Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME));
return JIM_OK;
}
static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000);
-
+ Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000);
return JIM_OK;
}
static const jim_subcmd_type clock_command_table[] = {
{ "clicks",
NULL,
- clock_cmd_micros,
+ clock_cmd_clicks,
0,
0,
@@ -5811,9 +6435,7 @@ static const jim_subcmd_type clock_command_table[] = {
int Jim_clockInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG))
- return JIM_ERR;
-
+ Jim_PackageProvideCheck(interp, "clock");
Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
return JIM_OK;
}
@@ -5888,7 +6510,8 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
- if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
+ dictValuesObj = Jim_DictPairs(interp, objPtr, &len);
+ if (dictValuesObj == NULL) {
Jim_SetResultString(interp, "", -1);
return JIM_OK;
@@ -5902,7 +6525,6 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
}
}
- Jim_Free(dictValuesObj);
Jim_SetVariable(interp, argv[0], resultObj);
return JIM_OK;
@@ -6033,10 +6655,55 @@ static const jim_subcmd_type array_command_table[] = {
int Jim_arrayInit(Jim_Interp *interp)
{
- if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
+ Jim_PackageProvideCheck(interp, "array");
+ Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
+ return JIM_OK;
+}
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+
+#ifdef HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+
+static void Jim_PosixSetError(Jim_Interp *interp)
+{
+ Jim_SetResultString(interp, strerror(errno), -1);
+}
+
+#if defined(HAVE_FORK)
+static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ pid_t pid;
+
+ JIM_NOTUSED(argv);
+
+ if (argc != 1) {
+ Jim_WrongNumArgs(interp, 1, argv, "");
+ return JIM_ERR;
+ }
+ if ((pid = fork()) == -1) {
+ Jim_PosixSetError(interp);
return JIM_ERR;
+ }
+ Jim_SetResultInt(interp, (jim_wide) pid);
+ return JIM_OK;
+}
+#endif
- Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
+
+int Jim_posixInit(Jim_Interp *interp)
+{
+ Jim_PackageProvideCheck(interp, "posix");
+#ifdef HAVE_FORK
+ Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL);
+#endif
return JIM_OK;
}
int Jim_InitStaticExtensions(Jim_Interp *interp)
@@ -6048,6 +6715,7 @@ extern int Jim_regexpInit(Jim_Interp *);
extern int Jim_fileInit(Jim_Interp *);
extern int Jim_globInit(Jim_Interp *);
extern int Jim_execInit(Jim_Interp *);
+extern int Jim_posixInit(Jim_Interp *);
extern int Jim_clockInit(Jim_Interp *);
extern int Jim_arrayInit(Jim_Interp *);
extern int Jim_stdlibInit(Jim_Interp *);
@@ -6059,6 +6727,7 @@ Jim_regexpInit(interp);
Jim_fileInit(interp);
Jim_globInit(interp);
Jim_execInit(interp);
+Jim_posixInit(interp);
Jim_clockInit(interp);
Jim_arrayInit(interp);
Jim_stdlibInit(interp);
@@ -6066,9 +6735,6 @@ Jim_tclcompatInit(interp);
return JIM_OK;
}
#define JIM_OPTIMIZATION
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
#include <stdio.h>
#include <stdlib.h>
@@ -6086,7 +6752,7 @@ return JIM_OK;
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_BACKTRACE
+#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#ifdef HAVE_CRT_EXTERNS_H
@@ -6138,6 +6804,7 @@ static void JimPanicDump(int fail_condition, const char *fmt, ...);
#endif
#ifdef JIM_OPTIMIZATION
+static int JimIsWide(Jim_Obj *objPtr);
#define JIM_IF_OPTIM(X) X
#else
#define JIM_IF_OPTIM(X)
@@ -6149,18 +6816,25 @@ static char JimEmptyStringRep[] = "";
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
int flags);
+static int Jim_ListIndices(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *const *indexv, int indexc,
+ Jim_Obj **resultObj, int flags);
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
-static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
const char *prefix, const char *const *tablePtr, const char *name);
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
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 int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv);
+static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr);
+static void JimSetErrorStack(Jim_Interp *interp);
+static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+#define JIM_DICT_SUGAR 100
+
@@ -6177,16 +6851,28 @@ static int utf8_tounicode_case(const char *s, int *uc, int upper)
return l;
}
+static Jim_Obj *JimPushInterpObjImpl(Jim_Obj **iop, Jim_Obj *no)
+{
+ Jim_Obj *io = *iop;
+ Jim_IncrRefCount(no);
+ *iop = no;
+ return io;
+}
+
+#define JimPushInterpObj(IO, NO) JimPushInterpObjImpl(&(IO), NO)
+#define JimPopInterpObj(I, IO, SO) do { Jim_DecrRefCount(I, IO); IO = SO; } while (0)
+
#define JIM_CHARSET_SCAN 2
#define JIM_CHARSET_GLOB 0
-static const char *JimCharsetMatch(const char *pattern, int c, int flags)
+static const char *JimCharsetMatch(const char *pattern, int plen, int c, int flags)
{
int not = 0;
int pchar;
int match = 0;
int nocase = 0;
+ int n;
if (flags & JIM_NOCASE) {
nocase++;
@@ -6197,6 +6883,7 @@ static const char *JimCharsetMatch(const char *pattern, int c, int flags)
if (*pattern == '^') {
not++;
pattern++;
+ plen--;
}
@@ -6205,22 +6892,27 @@ static const char *JimCharsetMatch(const char *pattern, int c, int flags)
}
}
- while (*pattern && *pattern != ']') {
+ while (plen && *pattern != ']') {
if (pattern[0] == '\\') {
first:
- pattern += utf8_tounicode_case(pattern, &pchar, nocase);
+ n = utf8_tounicode_case(pattern, &pchar, nocase);
+ pattern += n;
+ plen -= n;
}
else {
int start;
int end;
- pattern += utf8_tounicode_case(pattern, &start, nocase);
- if (pattern[0] == '-' && pattern[1]) {
+ n = utf8_tounicode_case(pattern, &start, nocase);
+ pattern += n;
+ plen -= n;
+ if (pattern[0] == '-' && plen > 1) {
- pattern++;
- pattern += utf8_tounicode_case(pattern, &end, nocase);
+ n = 1 + utf8_tounicode_case(pattern + 1, &end, nocase);
+ pattern += n;
+ plen -= n;
if ((c >= start && c <= end) || (c >= end && c <= start)) {
@@ -6244,39 +6936,52 @@ first:
-static int JimGlobMatch(const char *pattern, const char *string, int nocase)
+static int JimGlobMatch(const char *pattern, int plen, const char *string, int slen, int nocase)
{
int c;
int pchar;
- while (*pattern) {
+ int n;
+ const char *p;
+ while (plen) {
switch (pattern[0]) {
case '*':
- while (pattern[1] == '*') {
+ while (pattern[1] == '*' && plen) {
pattern++;
+ plen--;
}
pattern++;
- if (!pattern[0]) {
+ plen--;
+ if (!plen) {
return 1;
}
- while (*string) {
+ while (slen) {
- if (JimGlobMatch(pattern, string, nocase))
+ if (JimGlobMatch(pattern, plen, string, slen, nocase))
return 1;
- string += utf8_tounicode(string, &c);
+ n = utf8_tounicode(string, &c);
+ string += n;
+ slen -= n;
}
return 0;
case '?':
- string += utf8_tounicode(string, &c);
+ n = utf8_tounicode(string, &c);
+ string += n;
+ slen -= n;
break;
case '[': {
- string += utf8_tounicode(string, &c);
- pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
- if (!pattern) {
+ n = utf8_tounicode(string, &c);
+ string += n;
+ slen -= n;
+ p = JimCharsetMatch(pattern + 1, plen - 1, c, nocase ? JIM_NOCASE : 0);
+ if (!p) {
return 0;
}
- if (!*pattern) {
+ plen -= p - pattern;
+ pattern = p;
+
+ if (!plen) {
continue;
}
@@ -6285,64 +6990,58 @@ static int JimGlobMatch(const char *pattern, const char *string, int nocase)
case '\\':
if (pattern[1]) {
pattern++;
+ plen--;
}
default:
- string += utf8_tounicode_case(string, &c, nocase);
+ n = utf8_tounicode_case(string, &c, nocase);
+ string += n;
+ slen -= n;
utf8_tounicode_case(pattern, &pchar, nocase);
if (pchar != c) {
return 0;
}
break;
}
- pattern += utf8_tounicode_case(pattern, &pchar, nocase);
- if (!*string) {
- while (*pattern == '*') {
+ n = utf8_tounicode_case(pattern, &pchar, nocase);
+ pattern += n;
+ plen -= n;
+ if (!slen) {
+ while (*pattern == '*' && plen) {
pattern++;
+ plen--;
}
break;
}
}
- if (!*pattern && !*string) {
+ if (!plen && !slen) {
return 1;
}
return 0;
}
-static int JimStringCompare(const char *s1, int l1, const char *s2, int l2)
+static int JimStringCompareUtf8(const char *s1, int l1, const char *s2, int l2, int nocase)
{
- if (l1 < l2) {
- return memcmp(s1, s2, l1) <= 0 ? -1 : 1;
+ int minlen = l1;
+ if (l2 < l1) {
+ minlen = l2;
}
- else if (l2 < l1) {
- return memcmp(s1, s2, l2) >= 0 ? 1 : -1;
- }
- else {
- return JimSign(memcmp(s1, s2, l1));
- }
-}
-
-static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase)
-{
- while (*s1 && *s2 && maxchars) {
+ while (minlen) {
int c1, c2;
s1 += utf8_tounicode_case(s1, &c1, nocase);
s2 += utf8_tounicode_case(s2, &c2, nocase);
if (c1 != c2) {
return JimSign(c1 - c2);
}
- maxchars--;
- }
- if (!maxchars) {
- return 0;
+ minlen--;
}
- if (*s1) {
- return 1;
- }
- if (*s2) {
+ if (l1 < l2) {
return -1;
}
+ if (l1 > l2) {
+ return 1;
+ }
return 0;
}
@@ -6418,7 +7117,7 @@ static int JimNumberBase(const char *str, int *base, int *sign)
{
int i = 0;
- *base = 10;
+ *base = 0;
while (isspace(UCHAR(str[i]))) {
i++;
@@ -6445,6 +7144,7 @@ static int JimNumberBase(const char *str, int *base, int *sign)
case 'x': case 'X': *base = 16; break;
case 'o': case 'O': *base = 8; break;
case 'b': case 'B': *base = 2; break;
+ case 'd': case 'D': *base = 10; break;
default: return 0;
}
i += 2;
@@ -6454,7 +7154,7 @@ static int JimNumberBase(const char *str, int *base, int *sign)
return i;
}
- *base = 10;
+ *base = 0;
return 0;
}
@@ -6464,7 +7164,7 @@ static long jim_strtol(const char *str, char **endptr)
int base;
int i = JimNumberBase(str, &base, &sign);
- if (base != 10) {
+ if (base != 0) {
long value = strtol(str + i, endptr, base);
if (endptr == NULL || *endptr != str + i) {
return value * sign;
@@ -6483,7 +7183,7 @@ static jim_wide jim_strtoull(const char *str, char **endptr)
int base;
int i = JimNumberBase(str, &base, &sign);
- if (base != 10) {
+ if (base != 0) {
jim_wide value = strtoull(str + i, endptr, base);
if (endptr == NULL || *endptr != str + i) {
return value * sign;
@@ -6565,7 +7265,7 @@ static void JimPanicDump(int condition, const char *fmt, ...)
fprintf(stderr, "\n\n");
va_end(ap);
-#ifdef HAVE_BACKTRACE
+#if defined(HAVE_BACKTRACE)
{
void *array[40];
int size, i;
@@ -6585,47 +7285,63 @@ static void JimPanicDump(int condition, const char *fmt, ...)
#endif
-void *Jim_Alloc(int size)
-{
- return size ? malloc(size) : NULL;
-}
-
-void Jim_Free(void *ptr)
+void *JimDefaultAllocator(void *ptr, size_t size)
{
- free(ptr);
+ if (size == 0) {
+ free(ptr);
+ return NULL;
+ }
+ else if (ptr) {
+ return realloc(ptr, size);
+ }
+ else {
+ return malloc(size);
+ }
}
-void *Jim_Realloc(void *ptr, int size)
-{
- return realloc(ptr, size);
-}
+void *(*Jim_Allocator)(void *ptr, size_t size) = JimDefaultAllocator;
char *Jim_StrDup(const char *s)
{
- return strdup(s);
+ return Jim_StrDupLen(s, strlen(s));
}
char *Jim_StrDupLen(const char *s, int l)
{
char *copy = Jim_Alloc(l + 1);
- memcpy(copy, s, l + 1);
+ memcpy(copy, s, l);
copy[l] = 0;
return copy;
}
-
-static jim_wide JimClock(void)
+jim_wide Jim_GetTimeUsec(unsigned type)
{
+ long long now;
struct timeval tv;
- gettimeofday(&tv, NULL);
- return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec;
+#if defined(HAVE_CLOCK_GETTIME)
+ struct timespec ts;
+
+ if (clock_gettime(type, &ts) == 0) {
+ now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
+ }
+ else
+#endif
+ {
+ gettimeofday(&tv, NULL);
+
+ now = tv.tv_sec * 1000000LL + tv.tv_usec;
+ }
+
+ return now;
}
+
+
static void JimExpandHashTableIfNeeded(Jim_HashTable *ht);
static unsigned int JimHashTableNextPower(unsigned int size);
static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace);
@@ -6644,18 +7360,19 @@ unsigned int Jim_IntHashFunction(unsigned int key)
return key;
}
-unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
-{
- unsigned int h = 0;
- while (len--)
- h += (h << 3) + *buf++;
- return h;
+unsigned int Jim_GenHashFunction(const unsigned char *string, int length)
+{
+ unsigned result = 0;
+ string += length;
+ while (length--) {
+ result += (result << 3) + (unsigned char)(*--string);
+ }
+ return result;
}
-
static void JimResetHashTable(Jim_HashTable *ht)
{
ht->table = NULL;
@@ -6687,15 +7404,6 @@ int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *pr
return JIM_OK;
}
-void Jim_ResizeHashTable(Jim_HashTable *ht)
-{
- int minimal = ht->used;
-
- if (minimal < JIM_HT_INITIAL_SIZE)
- minimal = JIM_HT_INITIAL_SIZE;
- Jim_ExpandHashTable(ht, minimal);
-}
-
void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
{
@@ -6744,12 +7452,9 @@ void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
*ht = n;
}
-
int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
- Jim_HashEntry *entry;
-
- entry = JimInsertHashEntry(ht, key, 0);
+ Jim_HashEntry *entry = JimInsertHashEntry(ht, key, 0);;
if (entry == NULL)
return JIM_ERR;
@@ -6788,39 +7493,35 @@ int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
return existed;
}
-
int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
{
- unsigned int h;
- Jim_HashEntry *he, *prevHe;
-
- if (ht->used == 0)
- return JIM_ERR;
- h = Jim_HashKey(ht, key) & ht->sizemask;
- he = ht->table[h];
+ if (ht->used) {
+ unsigned int h = Jim_HashKey(ht, key) & ht->sizemask;
+ Jim_HashEntry *prevHe = NULL;
+ Jim_HashEntry *he = ht->table[h];
- prevHe = NULL;
- while (he) {
- if (Jim_CompareHashKeys(ht, key, he->key)) {
+ while (he) {
+ if (Jim_CompareHashKeys(ht, key, he->key)) {
- if (prevHe)
- prevHe->next = he->next;
- else
- ht->table[h] = he->next;
- Jim_FreeEntryKey(ht, he);
- Jim_FreeEntryVal(ht, he);
- Jim_Free(he);
- ht->used--;
- return JIM_OK;
+ if (prevHe)
+ prevHe->next = he->next;
+ else
+ ht->table[h] = he->next;
+ ht->used--;
+ Jim_FreeEntryKey(ht, he);
+ Jim_FreeEntryVal(ht, he);
+ Jim_Free(he);
+ return JIM_OK;
+ }
+ prevHe = he;
+ he = he->next;
}
- prevHe = he;
- he = he->next;
}
+
return JIM_ERR;
}
-
-int Jim_FreeHashTable(Jim_HashTable *ht)
+void Jim_ClearHashTable(Jim_HashTable *ht)
{
unsigned int i;
@@ -6828,8 +7529,7 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
for (i = 0; ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
- if ((he = ht->table[i]) == NULL)
- continue;
+ he = ht->table[i];
while (he) {
nextHe = he->next;
Jim_FreeEntryKey(ht, he);
@@ -6838,7 +7538,13 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
ht->used--;
he = nextHe;
}
+ ht->table[i] = NULL;
}
+}
+
+int Jim_FreeHashTable(Jim_HashTable *ht)
+{
+ Jim_ClearHashTable(ht);
Jim_Free(ht->table);
@@ -7142,6 +7848,9 @@ static int JimParseScript(struct JimParserCtx *pc)
pc->tend = pc->p - 1;
pc->tline = pc->linenr;
pc->tt = JIM_TT_EOL;
+ if (pc->inquote) {
+ pc->missing.ch = '"';
+ }
pc->eof = 1;
return JIM_OK;
}
@@ -7356,6 +8065,9 @@ static void JimParseSubCmd(struct JimParserCtx *pc)
case '"':
if (startofword) {
JimParseSubQuote(pc);
+ if (pc->missing.ch == '"') {
+ return;
+ }
continue;
}
break;
@@ -8307,33 +9019,24 @@ int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
{
- return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
+ int plen, slen;
+ const char *pattern = Jim_GetString(patternObjPtr, &plen);
+ const char *string = Jim_GetString(objPtr, &slen);
+ return JimGlobMatch(pattern, plen, string, slen, nocase);
}
int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
{
- int l1, l2;
- const char *s1 = Jim_GetString(firstObjPtr, &l1);
- const char *s2 = Jim_GetString(secondObjPtr, &l2);
-
- if (nocase) {
-
- return JimStringCompareLen(s1, s2, -1, nocase);
- }
- return JimStringCompare(s1, l1, s2, l2);
-}
-
-int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
-{
const char *s1 = Jim_String(firstObjPtr);
+ int l1 = Jim_Utf8Length(interp, firstObjPtr);
const char *s2 = Jim_String(secondObjPtr);
-
- return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase);
+ int l2 = Jim_Utf8Length(interp, secondObjPtr);
+ return JimStringCompareUtf8(s1, l1, s2, l2, nocase);
}
static int JimRelToAbsIndex(int len, int idx)
{
- if (idx < 0)
+ if (idx < 0 && idx > -INT_MAX)
return len + idx;
return idx;
}
@@ -8851,7 +9554,7 @@ static const Jim_ObjType scriptObjType = {
FreeScriptInternalRep,
DupScriptInternalRep,
NULL,
- JIM_TYPE_REFERENCES,
+ JIM_TYPE_NONE,
};
typedef struct ScriptToken
@@ -9225,8 +9928,6 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
objPtr->typePtr = &scriptObjType;
}
-static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
-
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
if (objPtr == interp->emptyObj) {
@@ -9241,16 +9942,19 @@ static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
return (ScriptObj *)Jim_GetIntRepPtr(objPtr);
}
-static int JimScriptValid(Jim_Interp *interp, ScriptObj *script)
+void Jim_InterpIncrProcEpoch(Jim_Interp *interp)
{
- if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
- JimAddErrorToStack(interp, script);
- return 0;
+ interp->procEpoch++;
+
+
+ while (interp->oldCmdCache) {
+ Jim_Cmd *next = interp->oldCmdCache->prevCmd;
+ Jim_Free(interp->oldCmdCache);
+ interp->oldCmdCache = next;
}
- return 1;
+ interp->oldCmdCacheSize = 0;
}
-
static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
{
cmdPtr->inUse++;
@@ -9278,61 +9982,152 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
}
- Jim_Free(cmdPtr);
+
+ cmdPtr->prevCmd = interp->oldCmdCache;
+ interp->oldCmdCache = cmdPtr;
+ if (!interp->quitting && ++interp->oldCmdCacheSize >= 1000) {
+ Jim_InterpIncrProcEpoch(interp);
+ }
+ }
+}
+
+static void JimIncrVarRef(Jim_VarVal *vv)
+{
+ vv->refCount++;
+}
+
+static void JimDecrVarRef(Jim_Interp *interp, Jim_VarVal *vv)
+{
+ assert(vv->refCount > 0);
+ if (--vv->refCount == 0) {
+ if (vv->objPtr) {
+ Jim_DecrRefCount(interp, vv->objPtr);
+ }
+ Jim_Free(vv);
}
}
static void JimVariablesHTValDestructor(void *interp, void *val)
{
- Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
- Jim_Free(val);
+ JimDecrVarRef(interp, val);
+}
+
+static unsigned int JimObjectHTHashFunction(const void *key)
+{
+ Jim_Obj *keyObj = (Jim_Obj *)key;
+ int length;
+ const char *string;
+
+#ifdef JIM_OPTIMIZATION
+ if (JimIsWide(keyObj) && keyObj->bytes == NULL) {
+
+ jim_wide objValue = JimWideValue(keyObj);
+ if (objValue > INT_MIN && objValue < INT_MAX) {
+ unsigned result = 0;
+ unsigned value = (unsigned)objValue;
+
+ if (objValue < 0) {
+ value = (unsigned)-objValue;
+ }
+
+
+ do {
+ result += (result << 3) + (value % 10 + '0');
+ value /= 10;
+ } while (value);
+
+ if (objValue < 0) {
+ result += (result << 3) + '-';
+ }
+ return result;
+ }
+ }
+#endif
+ string = Jim_GetString(keyObj, &length);
+ return Jim_GenHashFunction((const unsigned char *)string, length);
+}
+
+static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+ return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
+}
+
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
+{
+ Jim_IncrRefCount((Jim_Obj *)val);
+ return (void *)val;
+}
+
+static void JimObjectHTKeyValDestructor(void *interp, void *val)
+{
+ Jim_DecrRefCount(interp, (Jim_Obj *)val);
+}
+
+
+static void *JimVariablesHTValDup(void *privdata, const void *val)
+{
+ JimIncrVarRef((Jim_VarVal *)val);
+ return (void *)val;
}
static const Jim_HashTableType JimVariablesHashTableType = {
- JimStringCopyHTHashFunction,
- JimStringCopyHTDup,
- NULL,
- JimStringCopyHTKeyCompare,
- JimStringCopyHTKeyDestructor,
+ JimObjectHTHashFunction,
+ JimObjectHTKeyValDup,
+ JimVariablesHTValDup,
+ JimObjectHTKeyCompare,
+ JimObjectHTKeyValDestructor,
JimVariablesHTValDestructor
};
+
+static const char *Jim_GetStringNoQualifier(Jim_Obj *objPtr, int *length)
+{
+ int len;
+ const char *str = Jim_GetString(objPtr, &len);
+ if (len >= 2 && str[0] == ':' && str[1] == ':') {
+ while (len && *str == ':') {
+ len--;
+ str++;
+ }
+ }
+ *length = len;
+ return str;
+}
+
+static unsigned int JimCommandsHT_HashFunction(const void *key)
+{
+ int len;
+ const char *str = Jim_GetStringNoQualifier((Jim_Obj *)key, &len);
+ return Jim_GenHashFunction((const unsigned char *)str, len);
+}
+
+static int JimCommandsHT_KeyCompare(void *privdata, const void *key1, const void *key2)
+{
+ int len1, len2;
+ const char *str1 = Jim_GetStringNoQualifier((Jim_Obj *)key1, &len1);
+ const char *str2 = Jim_GetStringNoQualifier((Jim_Obj *)key2, &len2);
+ return len1 == len2 && memcmp(str1, str2, len1) == 0;
+}
+
static void JimCommandsHT_ValDestructor(void *interp, void *val)
{
JimDecrCmdRefCount(interp, val);
}
static const Jim_HashTableType JimCommandsHashTableType = {
- JimStringCopyHTHashFunction,
- JimStringCopyHTDup,
+ JimCommandsHT_HashFunction,
+ JimObjectHTKeyValDup,
NULL,
- JimStringCopyHTKeyCompare,
- JimStringCopyHTKeyDestructor,
+ JimCommandsHT_KeyCompare,
+ JimObjectHTKeyValDestructor,
JimCommandsHT_ValDestructor
};
-#ifdef jim_ext_namespace
-static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
-{
- const char *name = Jim_String(nsObj);
- if (name[0] == ':' && name[1] == ':') {
-
- while (*++name == ':') {
- }
- nsObj = Jim_NewStringObj(interp, name, -1);
- }
- else if (Jim_Length(interp->framePtr->nsObj)) {
-
- nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
- Jim_AppendStrings(interp, nsObj, "::", name, NULL);
- }
- return nsObj;
-}
-
Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
{
+#ifdef jim_ext_namespace
Jim_Obj *resultObj;
const char *name = Jim_String(nameObjPtr);
@@ -9345,67 +10140,50 @@ Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
Jim_DecrRefCount(interp, nameObjPtr);
return resultObj;
+#else
+ return nameObjPtr;
+#endif
}
-static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
+static Jim_Obj *JimQualifyName(Jim_Interp *interp, Jim_Obj *objPtr)
{
- Jim_Obj *objPtr = interp->emptyObj;
-
- if (name[0] == ':' && name[1] == ':') {
+#ifdef jim_ext_namespace
+ if (Jim_Length(interp->framePtr->nsObj)) {
+ int len;
+ const char *name = Jim_GetString(objPtr, &len);
+ if (len < 2 || name[0] != ':' || name[1] != ':') {
- while (*++name == ':') {
+ objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+ Jim_AppendStrings(interp, objPtr, "::", name, NULL);
}
}
- else if (Jim_Length(interp->framePtr->nsObj)) {
-
- objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
- Jim_AppendStrings(interp, objPtr, "::", name, NULL);
- name = Jim_String(objPtr);
- }
+#endif
Jim_IncrRefCount(objPtr);
- *objPtrPtr = objPtr;
- return name;
-}
-
- #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
-
-#else
-
- #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
- #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
-
-Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
-{
- return nameObjPtr;
+ return objPtr;
}
-#endif
-static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
+static void JimCreateCommand(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Cmd *cmd)
{
- Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
- if (he) {
+ JimPanic((nameObjPtr->refCount == 0, "JimCreateCommand called with zero ref count name"));
- Jim_InterpIncrProcEpoch(interp);
- }
+ if (interp->local) {
+ Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, nameObjPtr);
+ if (he) {
- if (he && interp->local) {
+ cmd->prevCmd = Jim_GetHashEntryVal(he);
+ Jim_SetHashVal(&interp->commands, he, cmd);
- cmd->prevCmd = Jim_GetHashEntryVal(he);
- Jim_SetHashVal(&interp->commands, he, cmd);
+ Jim_InterpIncrProcEpoch(interp);
+ return;
+ }
}
- else {
- if (he) {
- Jim_DeleteHashEntry(&interp->commands, name);
- }
- Jim_AddHashEntry(&interp->commands, name, cmd);
- }
- return JIM_OK;
-}
+ Jim_ReplaceHashEntry(&interp->commands, nameObjPtr, cmd);
+}
-int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
+int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj,
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
{
Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
@@ -9417,11 +10195,20 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
cmdPtr->u.native.cmdProc = cmdProc;
cmdPtr->u.native.privData = privData;
- JimCreateCommand(interp, cmdNameStr, cmdPtr);
+ Jim_IncrRefCount(cmdNameObj);
+ JimCreateCommand(interp, cmdNameObj, cmdPtr);
+ Jim_DecrRefCount(interp, cmdNameObj);
return JIM_OK;
}
+
+int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
+ Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
+{
+ return Jim_CreateCommandObj(interp, Jim_NewStringObj(interp, cmdNameStr, -1), cmdProc, privData, delProc);
+}
+
static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr)
{
int len, i;
@@ -9434,68 +10221,125 @@ static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Ob
cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
for (i = 0; i < len; i++) {
- Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
- Jim_Var *varPtr;
- int subLen;
-
- objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
-
- subLen = Jim_ListLength(interp, objPtr);
- if (subLen == 1 || subLen == 2) {
- nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
- if (subLen == 1) {
- initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
- if (initObjPtr == NULL) {
+ Jim_Obj *initObjPtr = NULL;
+ Jim_Obj *nameObjPtr;
+ Jim_VarVal *vv = NULL;
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
+ int subLen = Jim_ListLength(interp, objPtr);
+ int byref = 0;
+
+
+ if (subLen != 1 && subLen != 2) {
+ Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"",
+ objPtr);
+ return JIM_ERR;
+ }
+
+ nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
+
+
+ if (subLen == 1) {
+ int len;
+ const char *pt = Jim_GetString(nameObjPtr, &len);
+ if (*pt == '&') {
+
+ nameObjPtr = Jim_NewStringObj(interp, pt + 1, len - 1);
+ byref = 1;
+ }
+ }
+ Jim_IncrRefCount(nameObjPtr);
+
+ if (subLen == 1) {
+ switch (SetVariableFromAny(interp, nameObjPtr)) {
+ case JIM_DICT_SUGAR:
+
+ if (byref) {
+ Jim_SetResultFormatted(interp, "Can't link to array element \"%#s\"", nameObjPtr);
+ }
+ else {
+ Jim_SetResultFormatted(interp, "Can't initialise array element \"%#s\"", nameObjPtr);
+ }
+ Jim_DecrRefCount(interp, nameObjPtr);
+ return JIM_ERR;
+
+ case JIM_OK:
+ if (byref) {
+ vv = nameObjPtr->internalRep.varValue.vv;
+ }
+ else {
+ initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
+ }
+ break;
+
+ case JIM_ERR:
+
Jim_SetResultFormatted(interp,
"variable for initialization of static \"%#s\" not found in the local context",
nameObjPtr);
+ Jim_DecrRefCount(interp, nameObjPtr);
return JIM_ERR;
- }
- }
- else {
- initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
- }
- if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
- return JIM_ERR;
- }
-
- varPtr = Jim_Alloc(sizeof(*varPtr));
- varPtr->objPtr = initObjPtr;
- Jim_IncrRefCount(initObjPtr);
- varPtr->linkFramePtr = NULL;
- if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars,
- Jim_String(nameObjPtr), varPtr) != JIM_OK) {
- Jim_SetResultFormatted(interp,
- "static variable name \"%#s\" duplicated in statics list", nameObjPtr);
- Jim_DecrRefCount(interp, initObjPtr);
- Jim_Free(varPtr);
- return JIM_ERR;
}
}
else {
- Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"",
- objPtr);
+ initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
+ }
+
+ if (vv == NULL) {
+ vv = Jim_Alloc(sizeof(*vv));
+ vv->objPtr = initObjPtr;
+ Jim_IncrRefCount(vv->objPtr);
+ vv->linkFramePtr = NULL;
+ vv->refCount = 0;
+ }
+
+ if (JimSetNewVariable(cmdPtr->u.proc.staticVars, nameObjPtr, vv) != JIM_OK) {
+ Jim_SetResultFormatted(interp,
+ "static variable name \"%#s\" duplicated in statics list", nameObjPtr);
+ JimIncrVarRef(vv);
+ JimDecrVarRef(interp, vv);
+ Jim_DecrRefCount(interp, nameObjPtr);
return JIM_ERR;
}
+
+ Jim_DecrRefCount(interp, nameObjPtr);
}
return JIM_OK;
}
-static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
+
+#ifdef jim_ext_namespace
+static const char *Jim_memrchr(const char *p, int c, int len)
+{
+ int i;
+ for (i = len; i > 0; i--) {
+ if (p[i] == c) {
+ return p + i;
+ }
+ }
+ return NULL;
+}
+#endif
+
+static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *nameObjPtr)
{
#ifdef jim_ext_namespace
if (cmdPtr->isproc) {
+ int len;
+ const char *cmdname = Jim_GetStringNoQualifier(nameObjPtr, &len);
- const char *pt = strrchr(cmdname, ':');
+ const char *pt = Jim_memrchr(cmdname, ':', len);
if (pt && pt != cmdname && pt[-1] == ':') {
+ pt++;
Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
- cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
+ cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 2);
Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
- if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
+ Jim_Obj *tempObj = Jim_NewStringObj(interp, pt, len - (pt - cmdname));
+ if (Jim_FindHashEntry(&interp->commands, tempObj)) {
Jim_InterpIncrProcEpoch(interp);
}
+ Jim_FreeNewObj(interp, tempObj);
}
}
#endif
@@ -9512,6 +10356,7 @@ static Jim_Cmd *JimCreateProcedureCmd(Jim_Interp *interp, Jim_Obj *argListObjPtr
cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
+ assert(cmdPtr);
memset(cmdPtr, 0, sizeof(*cmdPtr));
cmdPtr->inUse = 1;
cmdPtr->isproc = 1;
@@ -9587,68 +10432,67 @@ err:
return cmdPtr;
}
-int Jim_DeleteCommand(Jim_Interp *interp, const char *name)
+int Jim_DeleteCommand(Jim_Interp *interp, Jim_Obj *nameObj)
{
int ret = JIM_OK;
- Jim_Obj *qualifiedNameObj;
- const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj);
- if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) {
- Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name);
+ nameObj = JimQualifyName(interp, nameObj);
+
+ if (Jim_DeleteHashEntry(&interp->commands, nameObj) == JIM_ERR) {
+ Jim_SetResultFormatted(interp, "can't delete \"%#s\": command doesn't exist", nameObj);
ret = JIM_ERR;
}
- else {
- Jim_InterpIncrProcEpoch(interp);
- }
-
- JimFreeQualifiedName(interp, qualifiedNameObj);
+ Jim_DecrRefCount(interp, nameObj);
return ret;
}
-int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName)
+int Jim_RenameCommand(Jim_Interp *interp, Jim_Obj *oldNameObj, Jim_Obj *newNameObj)
{
int ret = JIM_ERR;
Jim_HashEntry *he;
Jim_Cmd *cmdPtr;
- Jim_Obj *qualifiedOldNameObj;
- Jim_Obj *qualifiedNewNameObj;
- const char *fqold;
- const char *fqnew;
- if (newName[0] == 0) {
- return Jim_DeleteCommand(interp, oldName);
+ if (Jim_Length(newNameObj) == 0) {
+ return Jim_DeleteCommand(interp, oldNameObj);
}
- fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
- fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
- he = Jim_FindHashEntry(&interp->commands, fqold);
+ oldNameObj = JimQualifyName(interp, oldNameObj);
+ newNameObj = JimQualifyName(interp, newNameObj);
+
+
+ he = Jim_FindHashEntry(&interp->commands, oldNameObj);
if (he == NULL) {
- Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
+ Jim_SetResultFormatted(interp, "can't rename \"%#s\": command doesn't exist", oldNameObj);
}
- else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
- Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
+ else if (Jim_FindHashEntry(&interp->commands, newNameObj)) {
+ Jim_SetResultFormatted(interp, "can't rename to \"%#s\": command already exists", newNameObj);
}
else {
-
cmdPtr = Jim_GetHashEntryVal(he);
- JimIncrCmdRefCount(cmdPtr);
- JimUpdateProcNamespace(interp, cmdPtr, fqnew);
- Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
+ if (cmdPtr->prevCmd) {
+ Jim_SetResultFormatted(interp, "can't rename local command \"%#s\"", oldNameObj);
+ }
+ else {
+ JimIncrCmdRefCount(cmdPtr);
+ JimUpdateProcNamespace(interp, cmdPtr, newNameObj);
+ Jim_AddHashEntry(&interp->commands, newNameObj, cmdPtr);
- Jim_DeleteHashEntry(&interp->commands, fqold);
+ Jim_DeleteHashEntry(&interp->commands, oldNameObj);
- Jim_InterpIncrProcEpoch(interp);
- ret = JIM_OK;
+ Jim_InterpIncrProcEpoch(interp);
+
+ ret = JIM_OK;
+ }
}
- JimFreeQualifiedName(interp, qualifiedOldNameObj);
- JimFreeQualifiedName(interp, qualifiedNewNameObj);
+ Jim_DecrRefCount(interp, oldNameObj);
+ Jim_DecrRefCount(interp, newNameObj);
return ret;
}
@@ -9678,48 +10522,34 @@ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
{
Jim_Cmd *cmd;
- if (objPtr->typePtr != &commandObjType ||
- objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
+ if (objPtr->typePtr == &commandObjType
+ && objPtr->internalRep.cmdValue.procEpoch == interp->procEpoch
#ifdef jim_ext_namespace
- || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
+ && Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
#endif
- ) {
-
-
-
- const char *name = Jim_String(objPtr);
- Jim_HashEntry *he;
+ && objPtr->internalRep.cmdValue.cmdPtr->inUse) {
- if (name[0] == ':' && name[1] == ':') {
- while (*++name == ':') {
- }
- }
+ cmd = objPtr->internalRep.cmdValue.cmdPtr;
+ }
+ else {
+ Jim_Obj *qualifiedNameObj = JimQualifyName(interp, objPtr);
+ Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, qualifiedNameObj);
#ifdef jim_ext_namespace
- else if (Jim_Length(interp->framePtr->nsObj)) {
-
- Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
- Jim_AppendStrings(interp, nameObj, "::", name, NULL);
- he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
- Jim_FreeNewObj(interp, nameObj);
- if (he) {
- goto found;
- }
+ if (he == NULL && Jim_Length(interp->framePtr->nsObj)) {
+ he = Jim_FindHashEntry(&interp->commands, objPtr);
}
#endif
-
-
- he = Jim_FindHashEntry(&interp->commands, name);
if (he == NULL) {
if (flags & JIM_ERRMSG) {
Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
}
+ Jim_DecrRefCount(interp, qualifiedNameObj);
return NULL;
}
-#ifdef jim_ext_namespace
-found:
-#endif
cmd = Jim_GetHashEntryVal(he);
+ cmd->cmdNameObj = Jim_GetHashEntryKey(he);
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &commandObjType;
@@ -9727,9 +10557,7 @@ found:
objPtr->internalRep.cmdValue.cmdPtr = cmd;
objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
Jim_IncrRefCount(interp->framePtr->nsObj);
- }
- else {
- cmd = objPtr->internalRep.cmdValue.cmdPtr;
+ Jim_DecrRefCount(interp, qualifiedNameObj);
}
while (cmd->u.proc.upcall) {
cmd = cmd->prevCmd;
@@ -9739,10 +10567,6 @@ found:
-#define JIM_DICT_SUGAR 100
-
-static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
-
static const Jim_ObjType variableObjType = {
"variable",
NULL,
@@ -9751,27 +10575,13 @@ static const Jim_ObjType variableObjType = {
JIM_TYPE_REFERENCES,
};
-static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
-{
-
- if (nameObjPtr->typePtr != &variableObjType) {
- int len;
- const char *str = Jim_GetString(nameObjPtr, &len);
- if (memchr(str, '\0', len)) {
- Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
- return JIM_ERR;
- }
- }
- return JIM_OK;
-}
-
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
const char *varName;
Jim_CallFrame *framePtr;
- Jim_HashEntry *he;
int global;
int len;
+ Jim_VarVal *vv;
if (objPtr->typePtr == &variableObjType) {
@@ -9785,10 +10595,6 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
else if (objPtr->typePtr == &dictSubstObjType) {
return JIM_DICT_SUGAR;
}
- else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
- return JIM_ERR;
- }
-
varName = Jim_GetString(objPtr, &len);
@@ -9798,33 +10604,37 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
if (varName[0] == ':' && varName[1] == ':') {
- while (*++varName == ':') {
+ while (*varName == ':') {
+ varName++;
+ len--;
}
global = 1;
framePtr = interp->topFramePtr;
+
+ Jim_Obj *tempObj = Jim_NewStringObj(interp, varName, len);
+ vv = JimFindVariable(&framePtr->vars, tempObj);
+ Jim_FreeNewObj(interp, tempObj);
}
else {
global = 0;
framePtr = interp->framePtr;
- }
-
- he = Jim_FindHashEntry(&framePtr->vars, varName);
- if (he == NULL) {
- if (!global && framePtr->staticVars) {
+ vv = JimFindVariable(&framePtr->vars, objPtr);
+ if (vv == NULL && framePtr->staticVars) {
- he = Jim_FindHashEntry(framePtr->staticVars, varName);
- }
- if (he == NULL) {
- return JIM_ERR;
+ vv = JimFindVariable(framePtr->staticVars, objPtr);
}
}
+ if (vv == NULL) {
+ return JIM_ERR;
+ }
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &variableObjType;
objPtr->internalRep.varValue.callFrameId = framePtr->id;
- objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
+ objPtr->internalRep.varValue.vv = vv;
objPtr->internalRep.varValue.global = global;
return JIM_OK;
}
@@ -9833,74 +10643,92 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
-static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
+static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv)
+{
+ return Jim_AddHashEntry(ht, nameObjPtr, vv);
+}
+
+static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr)
+{
+ Jim_HashEntry *he = Jim_FindHashEntry(ht, nameObjPtr);
+ if (he) {
+ return (Jim_VarVal *)Jim_GetHashEntryVal(he);
+ }
+ return NULL;
+}
+
+static int JimUnsetVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr)
+{
+ return Jim_DeleteHashEntry(ht, nameObjPtr);
+}
+
+static Jim_VarVal *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
{
const char *name;
Jim_CallFrame *framePtr;
int global;
+ int len;
- Jim_Var *var = Jim_Alloc(sizeof(*var));
+ Jim_VarVal *vv = Jim_Alloc(sizeof(*vv));
- var->objPtr = valObjPtr;
+ vv->objPtr = valObjPtr;
Jim_IncrRefCount(valObjPtr);
- var->linkFramePtr = NULL;
+ vv->linkFramePtr = NULL;
+ vv->refCount = 0;
- name = Jim_String(nameObjPtr);
+ name = Jim_GetString(nameObjPtr, &len);
if (name[0] == ':' && name[1] == ':') {
- while (*++name == ':') {
+ while (*name == ':') {
+ name++;
+ len--;
}
framePtr = interp->topFramePtr;
global = 1;
+ JimSetNewVariable(&framePtr->vars, Jim_NewStringObj(interp, name, len), vv);
}
else {
framePtr = interp->framePtr;
global = 0;
+ JimSetNewVariable(&framePtr->vars, nameObjPtr, vv);
}
- Jim_AddHashEntry(&framePtr->vars, name, var);
-
-
Jim_FreeIntRep(interp, nameObjPtr);
nameObjPtr->typePtr = &variableObjType;
nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
- nameObjPtr->internalRep.varValue.varPtr = var;
+ nameObjPtr->internalRep.varValue.vv = vv;
nameObjPtr->internalRep.varValue.global = global;
- return var;
+ return vv;
}
-
int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
{
int err;
- Jim_Var *var;
+ Jim_VarVal *vv;
switch (SetVariableFromAny(interp, nameObjPtr)) {
case JIM_DICT_SUGAR:
return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
case JIM_ERR:
- if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) {
- return JIM_ERR;
- }
JimCreateVariable(interp, nameObjPtr, valObjPtr);
break;
case JIM_OK:
- var = nameObjPtr->internalRep.varValue.varPtr;
- if (var->linkFramePtr == NULL) {
+ vv = nameObjPtr->internalRep.varValue.vv;
+ if (vv->linkFramePtr == NULL) {
Jim_IncrRefCount(valObjPtr);
- Jim_DecrRefCount(interp, var->objPtr);
- var->objPtr = valObjPtr;
+ Jim_DecrRefCount(interp, vv->objPtr);
+ vv->objPtr = valObjPtr;
}
else {
Jim_CallFrame *savedCallFrame;
savedCallFrame = interp->framePtr;
- interp->framePtr = var->linkFramePtr;
- err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
+ interp->framePtr = vv->linkFramePtr;
+ err = Jim_SetVariable(interp, vv->objPtr, valObjPtr);
interp->framePtr = savedCallFrame;
if (err != JIM_OK)
return err;
@@ -9951,7 +10779,9 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
const char *varName;
const char *targetName;
Jim_CallFrame *framePtr;
- Jim_Var *varPtr;
+ Jim_VarVal *vv;
+ int len;
+ int varnamelen;
switch (SetVariableFromAny(interp, nameObjPtr)) {
@@ -9961,24 +10791,26 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
return JIM_ERR;
case JIM_OK:
- varPtr = nameObjPtr->internalRep.varValue.varPtr;
+ vv = nameObjPtr->internalRep.varValue.vv;
- if (varPtr->linkFramePtr == NULL) {
+ if (vv->linkFramePtr == NULL) {
Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
return JIM_ERR;
}
- varPtr->linkFramePtr = NULL;
+ vv->linkFramePtr = NULL;
break;
}
- varName = Jim_String(nameObjPtr);
+ varName = Jim_GetString(nameObjPtr, &varnamelen);
if (varName[0] == ':' && varName[1] == ':') {
- while (*++varName == ':') {
+ while (*varName == ':') {
+ varName++;
+ varnamelen--;
}
framePtr = interp->topFramePtr;
@@ -9987,11 +10819,13 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
framePtr = interp->framePtr;
}
- targetName = Jim_String(targetNameObjPtr);
+ targetName = Jim_GetString(targetNameObjPtr, &len);
if (targetName[0] == ':' && targetName[1] == ':') {
- while (*++targetName == ':') {
+ while (*targetName == ':') {
+ targetName++;
+ len--;
}
- targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1);
+ targetNameObjPtr = Jim_NewStringObj(interp, targetName, len);
targetCallFrame = interp->topFramePtr;
}
Jim_IncrRefCount(targetNameObjPtr);
@@ -10010,36 +10844,39 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
while (1) {
- if (strcmp(Jim_String(objPtr), varName) == 0) {
+ if (Jim_Length(objPtr) == varnamelen && memcmp(Jim_String(objPtr), varName, varnamelen) == 0) {
Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
Jim_DecrRefCount(interp, targetNameObjPtr);
return JIM_ERR;
}
if (SetVariableFromAny(interp, objPtr) != JIM_OK)
break;
- varPtr = objPtr->internalRep.varValue.varPtr;
- if (varPtr->linkFramePtr != targetCallFrame)
+ vv = objPtr->internalRep.varValue.vv;
+ if (vv->linkFramePtr != targetCallFrame)
break;
- objPtr = varPtr->objPtr;
+ objPtr = vv->objPtr;
}
}
Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
- nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
+ nameObjPtr->internalRep.varValue.vv->linkFramePtr = targetCallFrame;
Jim_DecrRefCount(interp, targetNameObjPtr);
return JIM_OK;
}
Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
{
+ if (interp->safeexpr) {
+ return nameObjPtr;
+ }
switch (SetVariableFromAny(interp, nameObjPtr)) {
case JIM_OK:{
- Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr;
+ Jim_VarVal *vv = nameObjPtr->internalRep.varValue.vv;
- if (varPtr->linkFramePtr == NULL) {
- return varPtr->objPtr;
+ if (vv->linkFramePtr == NULL) {
+ return vv->objPtr;
}
else {
Jim_Obj *objPtr;
@@ -10047,8 +10884,8 @@ Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
Jim_CallFrame *savedCallFrame = interp->framePtr;
- interp->framePtr = varPtr->linkFramePtr;
- objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
+ interp->framePtr = vv->linkFramePtr;
+ objPtr = Jim_GetVariable(interp, vv->objPtr, flags);
interp->framePtr = savedCallFrame;
if (objPtr) {
return objPtr;
@@ -10107,7 +10944,7 @@ Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flag
int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
{
- Jim_Var *varPtr;
+ Jim_VarVal *vv;
int retval;
Jim_CallFrame *framePtr;
@@ -10117,26 +10954,33 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
return JimDictSugarSet(interp, nameObjPtr, NULL);
}
else if (retval == JIM_OK) {
- varPtr = nameObjPtr->internalRep.varValue.varPtr;
+ vv = nameObjPtr->internalRep.varValue.vv;
- if (varPtr->linkFramePtr) {
+ if (vv->linkFramePtr) {
framePtr = interp->framePtr;
- interp->framePtr = varPtr->linkFramePtr;
- retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
+ interp->framePtr = vv->linkFramePtr;
+ retval = Jim_UnsetVariable(interp, vv->objPtr, JIM_NONE);
interp->framePtr = framePtr;
}
else {
- const char *name = Jim_String(nameObjPtr);
if (nameObjPtr->internalRep.varValue.global) {
- name += 2;
+ int len;
+ const char *name = Jim_GetString(nameObjPtr, &len);
+ while (*name == ':') {
+ name++;
+ len--;
+ }
framePtr = interp->topFramePtr;
+ Jim_Obj *tempObj = Jim_NewStringObj(interp, name, len);
+ retval = JimUnsetVariable(&framePtr->vars, tempObj);
+ Jim_FreeNewObj(interp, tempObj);
}
else {
framePtr = interp->framePtr;
+ retval = JimUnsetVariable(&framePtr->vars, nameObjPtr);
}
- retval = Jim_DeleteHashEntry(&framePtr->vars, name);
if (retval == JIM_OK) {
framePtr->id = interp->callFrameEpoch++;
@@ -10293,6 +11137,10 @@ static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_Obj *resObjPtr = NULL;
Jim_Obj *substKeyObjPtr = NULL;
+ if (interp->safeexpr) {
+ return objPtr;
+ }
+
SetDictSubstFromAny(interp, objPtr);
if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr,
@@ -10309,14 +11157,6 @@ static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)
return resObjPtr;
}
-static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
-{
- if (Jim_EvalExpression(interp, objPtr) == JIM_OK) {
- return Jim_GetResult(interp);
- }
- return NULL;
-}
-
static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj)
{
@@ -10359,14 +11199,8 @@ static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
Jim_Obj *cmdNameObj;
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
- Jim_HashEntry *he;
- Jim_Obj *fqObjName;
Jim_HashTable *ht = &interp->commands;
-
- const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
-
- he = Jim_FindHashEntry(ht, fqname);
-
+ Jim_HashEntry *he = Jim_FindHashEntry(ht, cmdNameObj);
if (he) {
Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
if (cmd->prevCmd) {
@@ -10380,12 +11214,10 @@ static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
Jim_SetHashVal(ht, he, prevCmd);
}
else {
- Jim_DeleteHashEntry(ht, fqname);
+ Jim_DeleteHashEntry(ht, cmdNameObj);
}
- Jim_InterpIncrProcEpoch(interp);
}
Jim_DecrRefCount(interp, cmdNameObj);
- JimFreeQualifiedName(interp, fqObjName);
}
Jim_FreeStack(localCommands);
Jim_Free(localCommands);
@@ -10398,11 +11230,10 @@ static int JimInvokeDefer(Jim_Interp *interp, int retcode)
Jim_Obj *objPtr;
- if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) {
+ if (JimFindVariable(&interp->framePtr->vars, interp->defer) == NULL) {
return retcode;
}
-
- objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE);
+ objPtr = Jim_GetVariable(interp, interp->defer, JIM_NONE);
if (objPtr) {
int ret = JIM_OK;
@@ -10454,24 +11285,7 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
Jim_FreeHashTable(&cf->vars);
else {
- int i;
- Jim_HashEntry **table = cf->vars.table, *he;
-
- for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
- he = table[i];
- while (he != NULL) {
- Jim_HashEntry *nextEntry = he->next;
- Jim_Var *varPtr = Jim_GetHashEntryVal(he);
-
- Jim_DecrRefCount(interp, varPtr->objPtr);
- Jim_Free(Jim_GetHashEntryKey(he));
- Jim_Free(varPtr);
- Jim_Free(he);
- table[i] = NULL;
- he = nextEntry;
- }
- }
- cf->vars.used = 0;
+ Jim_ClearHashTable(&cf->vars);
}
cf->next = interp->freeFramesList;
interp->freeFramesList = cf;
@@ -10498,7 +11312,7 @@ Jim_Interp *Jim_CreateInterp(void)
i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH;
i->maxEvalDepth = JIM_MAX_EVAL_DEPTH;
- i->lastCollectTime = time(NULL);
+ i->lastCollectTime = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i);
#ifdef JIM_REFERENCES
@@ -10510,23 +11324,24 @@ Jim_Interp *Jim_CreateInterp(void)
i->trueObj = Jim_NewIntObj(i, 1);
i->falseObj = Jim_NewIntObj(i, 0);
i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj);
- i->errorFileNameObj = i->emptyObj;
i->result = i->emptyObj;
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
+ i->defer = Jim_NewStringObj(i, "jim::defer", -1);
i->errorProc = i->emptyObj;
- i->currentScriptObj = Jim_NewEmptyStringObj(i);
i->nullScriptObj = Jim_NewEmptyStringObj(i);
+ i->evalFrame = &i->topEvalFrame;
+ i->currentFilenameObj = Jim_NewEmptyStringObj(i);
Jim_IncrRefCount(i->emptyObj);
- Jim_IncrRefCount(i->errorFileNameObj);
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
- Jim_IncrRefCount(i->currentScriptObj);
+ Jim_IncrRefCount(i->defer);
Jim_IncrRefCount(i->nullScriptObj);
Jim_IncrRefCount(i->errorProc);
Jim_IncrRefCount(i->trueObj);
Jim_IncrRefCount(i->falseObj);
+ Jim_IncrRefCount(i->currentFilenameObj);
Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
@@ -10538,8 +11353,10 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
+ Jim_SetVariableStrWithStr(i, "tcl_platform(bootstrap)", "0");
Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
+ Jim_SetVariableStr(i, "tcl_platform(stackFormat)", Jim_NewIntObj(i, 4));
return i;
}
@@ -10550,6 +11367,8 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_Obj *objPtr, *nextObjPtr;
+ i->quitting = 1;
+
for (cf = i->framePtr; cf; cf = cfx) {
@@ -10565,9 +11384,13 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->stackTrace);
Jim_DecrRefCount(i, i->errorProc);
Jim_DecrRefCount(i, i->unknown);
- Jim_DecrRefCount(i, i->errorFileNameObj);
- Jim_DecrRefCount(i, i->currentScriptObj);
+ Jim_DecrRefCount(i, i->defer);
Jim_DecrRefCount(i, i->nullScriptObj);
+ Jim_DecrRefCount(i, i->currentFilenameObj);
+
+
+ Jim_InterpIncrProcEpoch(i);
+
Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
Jim_FreeHashTable(&i->references);
@@ -10575,6 +11398,9 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_FreeHashTable(&i->packages);
Jim_Free(i->prngState);
Jim_FreeHashTable(&i->assocData);
+ if (i->traceCmdObj) {
+ Jim_DecrRefCount(i, i->traceCmdObj);
+ }
#ifdef JIM_MAINTAINER
if (i->liveList != NULL) {
@@ -10673,21 +11499,20 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
return NULL;
}
-static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr)
+static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, long level)
{
- long level;
Jim_CallFrame *framePtr;
- if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
- if (level <= 0) {
+ if (level == 0) {
+ return interp->framePtr;
+ }
- level = interp->framePtr->level + level;
- }
+ if (level < 0) {
- if (level == 0) {
- return interp->topFramePtr;
- }
+ level = interp->framePtr->level + level;
+ }
+ if (level > 0) {
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
if (framePtr->level == level) {
@@ -10695,76 +11520,90 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *leve
}
}
}
-
- Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
return NULL;
}
-static void JimResetStackTrace(Jim_Interp *interp)
+static Jim_EvalFrame *JimGetEvalFrameByProcLevel(Jim_Interp *interp, int proclevel)
{
- Jim_DecrRefCount(interp, interp->stackTrace);
- interp->stackTrace = Jim_NewListObj(interp, NULL, 0);
- Jim_IncrRefCount(interp->stackTrace);
-}
+ Jim_EvalFrame *evalFrame;
-static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
-{
- int len;
+ if (proclevel == 0) {
+ return interp->evalFrame;
+ }
+ if (proclevel < 0) {
- Jim_IncrRefCount(stackTraceObj);
- Jim_DecrRefCount(interp, interp->stackTrace);
- interp->stackTrace = stackTraceObj;
- interp->errorFlag = 1;
+ proclevel = interp->procLevel + proclevel;
+ }
+
+ if (proclevel >= 0) {
- len = Jim_ListLength(interp, interp->stackTrace);
- if (len >= 3) {
- if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
- interp->addStackTrace = 1;
+ for (evalFrame = interp->evalFrame; evalFrame; evalFrame = evalFrame->parent) {
+ if (evalFrame->procLevel == proclevel) {
+ return evalFrame;
+ }
}
}
+ return NULL;
}
-static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
- Jim_Obj *fileNameObj, int linenr)
+static Jim_Obj *JimProcForEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame)
{
- if (strcmp(procname, "unknown") == 0) {
- procname = "";
+ if (frame == interp->evalFrame || (frame->cmd && frame->cmd->cmdNameObj)) {
+ Jim_EvalFrame *e;
+ for (e = frame->parent; e; e = e->parent) {
+ if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) {
+ break;
+ }
+ }
+ if (e && e->cmd && e->cmd->cmdNameObj) {
+ return e->cmd->cmdNameObj;
+ }
}
- if (!*procname && !Jim_Length(fileNameObj)) {
+ return NULL;
+}
- return;
- }
+static void JimAddStackFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *listObj)
+{
+ Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame);
+ Jim_Obj *fileNameObj = interp->emptyObj;
+ int linenr = 1;
- if (Jim_IsShared(interp->stackTrace)) {
- Jim_DecrRefCount(interp, interp->stackTrace);
- interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
- Jim_IncrRefCount(interp->stackTrace);
+ if (frame->scriptObj) {
+ ScriptObj *script = JimGetScript(interp, frame->scriptObj);
+ fileNameObj = script->fileNameObj;
+ linenr = script->linenr;
}
+ Jim_ListAppendElement(interp, listObj, procNameObj ? procNameObj : interp->emptyObj);
+ Jim_ListAppendElement(interp, listObj, fileNameObj);
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, linenr));
+ Jim_ListAppendElement(interp, listObj, Jim_NewListObj(interp, frame->argv, frame->argc));
+}
- if (!*procname && Jim_Length(fileNameObj)) {
-
- int len = Jim_ListLength(interp, interp->stackTrace);
+static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
+{
- if (len >= 3) {
- Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
- if (Jim_Length(objPtr)) {
+ Jim_IncrRefCount(stackTraceObj);
+ Jim_DecrRefCount(interp, interp->stackTrace);
+ interp->stackTrace = stackTraceObj;
+ interp->errorFlag = 1;
+}
- objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
- if (Jim_Length(objPtr) == 0) {
+static void JimSetErrorStack(Jim_Interp *interp)
+{
+ if (!interp->errorFlag) {
+ int i;
+ Jim_Obj *stackTrace = Jim_NewListObj(interp, NULL, 0);
- ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
- ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
- return;
- }
+ for (i = 0; i <= interp->procLevel; i++) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
+ if (frame) {
+ JimAddStackFrame(interp, frame, stackTrace);
}
}
+ JimSetStackTrace(interp, stackTrace);
}
-
- Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1));
- Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj);
- Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr));
}
int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc,
@@ -10899,6 +11738,32 @@ int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
return JIM_OK;
}
+int Jim_GetWideExpr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
+{
+ int ret = JIM_OK;
+
+ if (objPtr->typePtr == &sourceObjType || objPtr->typePtr == NULL) {
+ SetIntFromAny(interp, objPtr, 0);
+ }
+ if (objPtr->typePtr == &intObjType) {
+ *widePtr = JimWideValue(objPtr);
+ }
+ else {
+ JimPanic((interp->safeexpr, "interp->safeexpr is set"));
+ interp->safeexpr++;
+ ret = Jim_EvalExpression(interp, objPtr);
+ interp->safeexpr--;
+
+ if (ret == JIM_OK) {
+ ret = Jim_GetWide(interp, Jim_GetResult(interp), widePtr);
+ }
+ if (ret != JIM_OK) {
+ Jim_SetResultFormatted(interp, "expected integer expression but got \"%#s\"", objPtr);
+ }
+ }
+ return ret;
+}
+
static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
{
@@ -10945,11 +11810,11 @@ static const Jim_ObjType doubleObjType = {
JIM_TYPE_NONE,
};
-#ifndef HAVE_ISNAN
+#if !HAVE_DECL_ISNAN
#undef isnan
#define isnan(X) ((X) != (X))
#endif
-#ifndef HAVE_ISINF
+#if !HAVE_DECL_ISINF
#undef isinf
#define isinf(X) (1.0 / (X) == 0.0)
#endif
@@ -11081,23 +11946,21 @@ int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr)
return JIM_OK;
}
-static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
-{
- static const char * const falses[] = {
- "0", "false", "no", "off", NULL
- };
- static const char * const trues[] = {
- "1", "true", "yes", "on", NULL
- };
+static const char * const jim_true_false_strings[8] = {
+ "1", "true", "yes", "on",
+ "0", "false", "no", "off"
+};
- int boolean;
+static const int jim_true_false_lens[8] = {
+ 1, 4, 3, 2,
+ 1, 5, 2, 3,
+};
- int index;
- if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) {
- boolean = 0;
- } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) {
- boolean = 1;
- } else {
+static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+{
+ int index = Jim_FindByName(Jim_String(objPtr), jim_true_false_strings,
+ sizeof(jim_true_false_strings) / sizeof(*jim_true_false_strings));
+ if (index < 0) {
if (flags & JIM_ERRMSG) {
Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr);
}
@@ -11107,7 +11970,8 @@ static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &intObjType;
- objPtr->internalRep.wideValue = boolean;
+
+ objPtr->internalRep.wideValue = index < 4 ? 1 : 0;
return JIM_OK;
}
@@ -11407,23 +12271,21 @@ static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
return JIM_OK;
}
- if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
- Jim_Obj **listObjPtrPtr;
- int len;
- int i;
- listObjPtrPtr = JimDictPairs(objPtr, &len);
- for (i = 0; i < len; i++) {
- Jim_IncrRefCount(listObjPtrPtr[i]);
- }
+ if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
+ Jim_Dict *dict = objPtr->internalRep.dictValue;
- Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &listObjType;
- objPtr->internalRep.listValue.len = len;
- objPtr->internalRep.listValue.maxLen = len;
- objPtr->internalRep.listValue.ele = listObjPtrPtr;
+ objPtr->internalRep.listValue.len = dict->len;
+ objPtr->internalRep.listValue.maxLen = dict->maxLen;
+ objPtr->internalRep.listValue.ele = dict->table;
+
+
+ Jim_Free(dict->ht);
+
+ Jim_Free(dict);
return JIM_OK;
}
@@ -11515,8 +12377,8 @@ struct lsort_info {
JIM_LSORT_COMMAND
} type;
int order;
- int index;
- int indexed;
+ Jim_Obj **indexv;
+ int indexc;
int unique;
int (*subfn)(Jim_Obj **, Jim_Obj **);
};
@@ -11527,8 +12389,8 @@ static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
Jim_Obj *lObj, *rObj;
- if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK ||
- Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) {
+ if (Jim_ListIndices(sort_info->interp, *lhsObj, sort_info->indexv, sort_info->indexc, &lObj, JIM_ERRMSG) != JIM_OK ||
+ Jim_ListIndices(sort_info->interp, *rhsObj, sort_info->indexv, sort_info->indexc, &rObj, JIM_ERRMSG) != JIM_OK) {
longjmp(sort_info->jmpbuf, JIM_ERR);
}
return sort_info->subfn(&lObj, &rObj);
@@ -11665,7 +12527,7 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
return -1;
}
- if (info->indexed) {
+ if (info->indexc) {
info->subfn = fn;
fn = ListSortIndexHelper;
@@ -11685,6 +12547,22 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
return rc;
}
+
+static void ListEnsureLength(Jim_Obj *listPtr, int idx)
+{
+ assert(idx >= 0);
+ if (idx >= listPtr->internalRep.listValue.maxLen) {
+ if (idx < 4) {
+
+ idx = 4;
+ }
+ listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
+ sizeof(Jim_Obj *) * idx);
+
+ listPtr->internalRep.listValue.maxLen = idx;
+ }
+}
+
static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
{
int currentLen = listPtr->internalRep.listValue.len;
@@ -11693,18 +12571,11 @@ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *co
Jim_Obj **point;
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
- if (requiredLen < 2) {
+ if (currentLen) {
- requiredLen = 4;
- }
- else {
requiredLen *= 2;
}
-
- listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
- sizeof(Jim_Obj *) * requiredLen);
-
- listPtr->internalRep.listValue.maxLen = requiredLen;
+ ListEnsureLength(listPtr, requiredLen);
}
if (idx < 0) {
idx = currentLen;
@@ -11789,6 +12660,47 @@ int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPt
return JIM_OK;
}
+static int Jim_ListIndices(Jim_Interp *interp, Jim_Obj *listPtr,
+ Jim_Obj *const *indexv, int indexc, Jim_Obj **resultObj, int flags)
+{
+ int i;
+ int static_idxes[5];
+ int *idxes = static_idxes;
+ int ret = JIM_OK;
+
+ if (indexc > sizeof(static_idxes) / sizeof(*static_idxes)) {
+ idxes = Jim_Alloc(indexc * sizeof(*idxes));
+ }
+
+ for (i = 0; i < indexc; i++) {
+ ret = Jim_GetIndex(interp, indexv[i], &idxes[i]);
+ if (ret != JIM_OK) {
+ goto err;
+ }
+ }
+
+ for (i = 0; i < indexc; i++) {
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, listPtr, idxes[i]);
+ if (!objPtr) {
+ if (flags & JIM_ERRMSG) {
+ if (idxes[i] < 0 || idxes[i] > Jim_ListLength(interp, listPtr)) {
+ Jim_SetResultFormatted(interp, "index \"%#s\" out of range", indexv[i]);
+ }
+ else {
+ Jim_SetResultFormatted(interp, "element %#s missing from sublist \"%#s\"", indexv[i], listPtr);
+ }
+ }
+ return -1;
+ }
+ listPtr = objPtr;
+ }
+ *resultObj = listPtr;
+err:
+ if (idxes != static_idxes)
+ Jim_Free(idxes);
+ return ret;
+}
+
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
Jim_Obj *newObjPtr, int flags)
{
@@ -11823,7 +12735,10 @@ int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
listObjPtr = objPtr;
if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK)
goto err;
- if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) {
+
+ objPtr = Jim_ListGetIndex(interp, listObjPtr, idx);
+ if (objPtr == NULL) {
+ Jim_SetResultFormatted(interp, "index \"%#s\" out of range", indexv[i]);
goto err;
}
if (Jim_IsShared(objPtr)) {
@@ -11950,38 +12865,6 @@ static void UpdateStringOfDict(struct Jim_Obj *objPtr);
static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
-static unsigned int JimObjectHTHashFunction(const void *key)
-{
- int len;
- const char *str = Jim_GetString((Jim_Obj *)key, &len);
- return Jim_GenHashFunction((const unsigned char *)str, len);
-}
-
-static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
-{
- return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
-}
-
-static void *JimObjectHTKeyValDup(void *privdata, const void *val)
-{
- Jim_IncrRefCount((Jim_Obj *)val);
- return (void *)val;
-}
-
-static void JimObjectHTKeyValDestructor(void *interp, void *val)
-{
- Jim_DecrRefCount(interp, (Jim_Obj *)val);
-}
-
-static const Jim_HashTableType JimDictHashTableType = {
- JimObjectHTHashFunction,
- JimObjectHTKeyValDup,
- JimObjectHTKeyValDup,
- JimObjectHTKeyCompare,
- JimObjectHTKeyValDestructor,
- JimObjectHTKeyValDestructor
-};
-
static const Jim_ObjType dictObjType = {
"dict",
FreeDictInternalRep,
@@ -11990,68 +12873,174 @@ static const Jim_ObjType dictObjType = {
JIM_TYPE_NONE,
};
-void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+static void JimFreeDict(Jim_Interp *interp, Jim_Dict *dict)
{
- JIM_NOTUSED(interp);
-
- Jim_FreeHashTable(objPtr->internalRep.ptr);
- Jim_Free(objPtr->internalRep.ptr);
+ int i;
+ for (i = 0; i < dict->len; i++) {
+ Jim_DecrRefCount(interp, dict->table[i]);
+ }
+ Jim_Free(dict->table);
+ Jim_Free(dict->ht);
+ Jim_Free(dict);
}
-void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+enum {
+ DICT_HASH_FIND = -1,
+ DICT_HASH_REMOVE = -2,
+ DICT_HASH_ADD = -3,
+};
+
+static int JimDictHashFind(Jim_Dict *dict, Jim_Obj *keyObjPtr, int op_tvoffset)
{
- Jim_HashTable *ht, *dupHt;
- Jim_HashTableIterator htiter;
- Jim_HashEntry *he;
+ unsigned h = (JimObjectHTHashFunction(keyObjPtr) + dict->uniq);
+ unsigned idx = h & dict->sizemask;
+ int tvoffset = 0;
+ unsigned peturb = h;
+ unsigned first_removed = ~0;
+
+ if (dict->len) {
+ while ((tvoffset = dict->ht[idx].offset)) {
+ if (tvoffset == -1) {
+ if (first_removed == ~0) {
+ first_removed = idx;
+ }
+ }
+ else if (dict->ht[idx].hash == h) {
+ if (Jim_StringEqObj(keyObjPtr, dict->table[tvoffset - 1])) {
+ break;
+ }
+ }
+
+ peturb >>= 5;
+ idx = (5 * idx + 1 + peturb) & dict->sizemask;
+ }
+ }
+
+ switch (op_tvoffset) {
+ case DICT_HASH_FIND:
+
+ break;
+ case DICT_HASH_REMOVE:
+ if (tvoffset) {
+
+ dict->ht[idx].offset = -1;
+ dict->dummy++;
+ }
+
+ break;
+ case DICT_HASH_ADD:
+ if (tvoffset == 0) {
+ if (first_removed != ~0) {
+ idx = first_removed;
+ dict->dummy--;
+ }
+ dict->ht[idx].offset = dict->len + 1;
+ dict->ht[idx].hash = h;
+ }
- ht = srcPtr->internalRep.ptr;
- dupHt = Jim_Alloc(sizeof(*dupHt));
- Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
- if (ht->size != 0)
- Jim_ExpandHashTable(dupHt, ht->size);
+ break;
+ default:
+ assert(tvoffset);
- JimInitHashTableIterator(ht, &htiter);
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
- Jim_AddHashEntry(dupHt, he->key, he->u.val);
+ dict->ht[idx].offset = op_tvoffset;
+ break;
}
- dupPtr->internalRep.ptr = dupHt;
- dupPtr->typePtr = &dictObjType;
+ return tvoffset;
}
-static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
+static void JimDictExpandHashTable(Jim_Dict *dict, unsigned int size)
{
- Jim_HashTable *ht;
- Jim_HashTableIterator htiter;
- Jim_HashEntry *he;
- Jim_Obj **objv;
int i;
+ struct JimDictHashEntry *prevht = dict->ht;
+ int prevsize = dict->size;
+
+ dict->size = JimHashTableNextPower(size);
+ dict->sizemask = dict->size - 1;
+
- ht = dictPtr->internalRep.ptr;
+ dict->ht = Jim_Alloc(dict->size * sizeof(*dict->ht));
+ memset(dict->ht, 0, dict->size * sizeof(*dict->ht));
- objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
- JimInitHashTableIterator(ht, &htiter);
- i = 0;
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
- objv[i++] = Jim_GetHashEntryKey(he);
- objv[i++] = Jim_GetHashEntryVal(he);
+ for (i = 0; i < prevsize; i++) {
+ if (prevht[i].offset > 0) {
+
+ unsigned h = prevht[i].hash;
+ unsigned idx = h & dict->sizemask;
+ unsigned peturb = h;
+
+ while (dict->ht[idx].offset) {
+ peturb >>= 5;
+ idx = (5 * idx + 1 + peturb) & dict->sizemask;
+ }
+ dict->ht[idx].offset = prevht[i].offset;
+ dict->ht[idx].hash = h;
+ }
}
- *len = i;
- return objv;
+ Jim_Free(prevht);
}
-static void UpdateStringOfDict(struct Jim_Obj *objPtr)
+static int JimDictAdd(Jim_Dict *dict, Jim_Obj *keyObjPtr)
{
+ if (dict->size <= dict->len + dict->dummy) {
+ JimDictExpandHashTable(dict, dict->size ? dict->size * 2 : 8);
+ }
+ return JimDictHashFind(dict, keyObjPtr, DICT_HASH_ADD);
+}
+
+static Jim_Dict *JimDictNew(Jim_Interp *interp, int table_size, int ht_size)
+{
+ Jim_Dict *dict = Jim_Alloc(sizeof(*dict));
+ memset(dict, 0, sizeof(*dict));
+
+ if (ht_size) {
+ JimDictExpandHashTable(dict, ht_size);
+ }
+ if (table_size) {
+ dict->table = Jim_Alloc(table_size * sizeof(*dict->table));
+ dict->maxLen = table_size;
+ }
+#ifdef JIM_RANDOMISE_HASH
+ dict->uniq = (rand() ^ time(NULL) ^ clock());
+#endif
+ return dict;
+}
+
+static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+ JimFreeDict(interp, objPtr->internalRep.dictValue);
+}
+
+static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+ Jim_Dict *oldDict = srcPtr->internalRep.dictValue;
+ int i;
- int len;
- Jim_Obj **objv = JimDictPairs(objPtr, &len);
+ Jim_Dict *newDict = JimDictNew(interp, oldDict->maxLen, oldDict->size);
- JimMakeListStringRep(objPtr, objv, len);
- Jim_Free(objv);
+ for (i = 0; i < oldDict->len; i++) {
+ newDict->table[i] = oldDict->table[i];
+ Jim_IncrRefCount(newDict->table[i]);
+ }
+ newDict->len = oldDict->len;
+
+
+ newDict->uniq = oldDict->uniq;
+
+
+ memcpy(newDict->ht, oldDict->ht, sizeof(*oldDict->ht) * oldDict->size);
+
+ dupPtr->internalRep.dictValue = newDict;
+ dupPtr->typePtr = &dictObjType;
+}
+
+static void UpdateStringOfDict(struct Jim_Obj *objPtr)
+{
+ JimMakeListStringRep(objPtr, objPtr->internalRep.dictValue->table, objPtr->internalRep.dictValue->len);
}
static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
@@ -12066,7 +13055,6 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
Jim_String(objPtr);
}
-
listlen = Jim_ListLength(interp, objPtr);
if (listlen % 2) {
Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -12074,22 +13062,38 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
else {
- Jim_HashTable *ht;
+ Jim_Dict *dict = JimDictNew(interp, 0, listlen);
int i;
- ht = Jim_Alloc(sizeof(*ht));
- Jim_InitHashTable(ht, &JimDictHashTableType, interp);
+
+ dict->table = objPtr->internalRep.listValue.ele;
+ dict->maxLen = objPtr->internalRep.listValue.maxLen;
+
for (i = 0; i < listlen; i += 2) {
- Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
- Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
+ int tvoffset = JimDictAdd(dict, dict->table[i]);
+ if (tvoffset) {
+
+
+ Jim_DecrRefCount(interp, dict->table[tvoffset]);
+
+ dict->table[tvoffset] = dict->table[i + 1];
- Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
+ Jim_DecrRefCount(interp, dict->table[i]);
+ }
+ else {
+ if (dict->len != i) {
+ dict->table[dict->len++] = dict->table[i];
+ dict->table[dict->len++] = dict->table[i + 1];
+ }
+ else {
+ dict->len += 2;
+ }
+ }
}
- Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &dictObjType;
- objPtr->internalRep.ptr = ht;
+ objPtr->internalRep.dictValue = dict;
return JIM_OK;
}
@@ -12100,13 +13104,56 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
- Jim_HashTable *ht = objPtr->internalRep.ptr;
-
+ Jim_Dict *dict = objPtr->internalRep.dictValue;
if (valueObjPtr == NULL) {
- return Jim_DeleteHashEntry(ht, keyObjPtr);
+
+ int tvoffset = JimDictHashFind(dict, keyObjPtr, DICT_HASH_REMOVE);
+ if (tvoffset) {
+
+ Jim_DecrRefCount(interp, dict->table[tvoffset - 1]);
+ Jim_DecrRefCount(interp, dict->table[tvoffset]);
+ dict->len -= 2;
+ if (tvoffset != dict->len + 1) {
+
+ dict->table[tvoffset - 1] = dict->table[dict->len];
+ dict->table[tvoffset] = dict->table[dict->len + 1];
+
+
+ JimDictHashFind(dict, dict->table[tvoffset - 1], tvoffset);
+ }
+ return JIM_OK;
+ }
+ return JIM_ERR;
+ }
+ else {
+
+ int tvoffset = JimDictAdd(dict, keyObjPtr);
+ if (tvoffset) {
+
+ Jim_IncrRefCount(valueObjPtr);
+ Jim_DecrRefCount(interp, dict->table[tvoffset]);
+ dict->table[tvoffset] = valueObjPtr;
+ }
+ else {
+ if (dict->maxLen == dict->len) {
+
+ if (dict->maxLen < 4) {
+ dict->maxLen = 4;
+ }
+ else {
+ dict->maxLen *= 2;
+ }
+ dict->table = Jim_Realloc(dict->table, dict->maxLen * sizeof(*dict->table));
+ }
+ Jim_IncrRefCount(keyObjPtr);
+ Jim_IncrRefCount(valueObjPtr);
+
+ dict->table[dict->len++] = keyObjPtr;
+ dict->table[dict->len++] = valueObjPtr;
+
+ }
+ return JIM_OK;
}
- Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
- return JIM_OK;
}
int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
@@ -12130,8 +13177,8 @@ Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
objPtr = Jim_NewObj(interp);
objPtr->typePtr = &dictObjType;
objPtr->bytes = NULL;
- objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable));
- Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp);
+
+ objPtr->internalRep.dictValue = JimDictNew(interp, len, len);
for (i = 0; i < len; i += 2)
DictAddElement(interp, objPtr, elements[i], elements[i + 1]);
return objPtr;
@@ -12140,38 +13187,45 @@ Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
Jim_Obj **objPtrPtr, int flags)
{
- Jim_HashEntry *he;
- Jim_HashTable *ht;
+ int tvoffset;
+ Jim_Dict *dict;
if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
return -1;
}
- ht = dictPtr->internalRep.ptr;
- if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) {
+ dict = dictPtr->internalRep.dictValue;
+ tvoffset = JimDictHashFind(dict, keyPtr, DICT_HASH_FIND);
+ if (tvoffset == 0) {
if (flags & JIM_ERRMSG) {
Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
}
return JIM_ERR;
}
- else {
- *objPtrPtr = Jim_GetHashEntryVal(he);
- return JIM_OK;
- }
+ *objPtrPtr = dict->table[tvoffset];
+ return JIM_OK;
}
-
-int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
+Jim_Obj **Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, int *len)
{
- if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
- return JIM_ERR;
+
+ if (Jim_IsList(dictPtr)) {
+ Jim_Obj **table;
+ JimListGetElements(interp, dictPtr, len, &table);
+ if (*len % 2 == 0) {
+ return table;
+ }
+
}
- *objPtrPtr = JimDictPairs(dictPtr, len);
+ if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
- return JIM_OK;
+ *len = 1;
+ return NULL;
+ }
+ *len = dictPtr->internalRep.dictValue->len;
+ return dictPtr->internalRep.dictValue->table;
}
-
int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags)
{
@@ -12256,7 +13310,10 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
goto err;
}
- Jim_SetResult(interp, varObjPtr);
+
+ if (!(flags & JIM_NORESULT)) {
+ Jim_SetResult(interp, varObjPtr);
+ }
return JIM_OK;
err:
if (shared) {
@@ -12283,7 +13340,7 @@ static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
}
else {
char buf[JIM_INTEGER_SPACE + 1];
- if (objPtr->internalRep.intValue >= 0) {
+ if (objPtr->internalRep.intValue >= 0 || objPtr->internalRep.intValue == -INT_MAX) {
sprintf(buf, "%d", objPtr->internalRep.intValue);
}
else {
@@ -12296,9 +13353,12 @@ static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
- int idx, end = 0;
+ jim_wide idx;
+ int end = 0;
const char *str;
- char *endptr;
+ Jim_Obj *exprObj = objPtr;
+
+ JimPanic((objPtr->refCount == 0, "SetIndexFromAny() called with zero refcount object"));
str = Jim_String(objPtr);
@@ -12308,33 +13368,30 @@ static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
end = 1;
str += 3;
idx = 0;
- }
- else {
- idx = jim_strtol(str, &endptr);
+ switch (*str) {
+ case '\0':
+ exprObj = NULL;
+ break;
- if (endptr == str) {
- goto badindex;
+ case '-':
+ case '+':
+ exprObj = Jim_NewStringObj(interp, str, -1);
+ break;
+
+ default:
+ goto badindex;
}
- str = endptr;
}
-
-
- if (*str == '+' || *str == '-') {
- int sign = (*str == '+' ? 1 : -1);
-
- idx += sign * jim_strtol(++str, &endptr);
- if (str == endptr || *endptr) {
+ if (exprObj) {
+ int ret;
+ Jim_IncrRefCount(exprObj);
+ ret = Jim_GetWideExpr(interp, exprObj, &idx);
+ Jim_DecrRefCount(interp, exprObj);
+ if (ret != JIM_OK) {
goto badindex;
}
- str = endptr;
}
- while (isspace(UCHAR(*str))) {
- str++;
- }
- if (*str) {
- goto badindex;
- }
if (end) {
if (idx > 0) {
idx = INT_MAX;
@@ -12356,7 +13413,7 @@ static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
badindex:
Jim_SetResultFormatted(interp,
- "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr);
+ "bad index \"%#s\": must be intexpr or end?[+-]intexpr?", objPtr);
return JIM_ERR;
}
@@ -12481,6 +13538,10 @@ enum
JIM_EXPROP_STRNE,
JIM_EXPROP_STRIN,
JIM_EXPROP_STRNI,
+ JIM_EXPROP_STRLT,
+ JIM_EXPROP_STRGT,
+ JIM_EXPROP_STRLE,
+ JIM_EXPROP_STRGE,
JIM_EXPROP_NOT,
@@ -12546,7 +13607,7 @@ static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node);
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
{
int intresult = 1;
- int rc;
+ int rc, bA = 0;
double dA, dC = 0;
jim_wide wA, wC = 0;
Jim_Obj *A;
@@ -12613,6 +13674,15 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node)
abort();
}
}
+ else if ((rc = Jim_GetBoolean(interp, A, &bA)) == JIM_OK) {
+ switch (node->type) {
+ case JIM_EXPROP_NOT:
+ wC = !bA;
+ break;
+ default:
+ abort();
+ }
+ }
if (rc == JIM_OK) {
if (intresult) {
@@ -12633,7 +13703,7 @@ static double JimRandDouble(Jim_Interp *interp)
unsigned long x;
JimRandomBytes(interp, &x, sizeof(x));
- return (double)x / (unsigned long)~0;
+ return (double)x / (double)~0UL;
}
static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node)
@@ -13042,7 +14112,7 @@ static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
{
Jim_Obj *A, *B;
jim_wide wC;
- int rc;
+ int comp, rc;
if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) {
return rc;
@@ -13060,6 +14130,21 @@ static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
wC = !wC;
}
break;
+ case JIM_EXPROP_STRLT:
+ case JIM_EXPROP_STRGT:
+ case JIM_EXPROP_STRLE:
+ case JIM_EXPROP_STRGE:
+ comp = Jim_StringCompareObj(interp, A, B, 0);
+ if (node->type == JIM_EXPROP_STRLT) {
+ wC = comp == -1;
+ } else if (node->type == JIM_EXPROP_STRGT) {
+ wC = comp == 1;
+ } else if (node->type == JIM_EXPROP_STRLE) {
+ wC = comp == -1 || comp == 0;
+ } else {
+ wC = comp == 0 || comp == 1;
+ }
+ break;
case JIM_EXPROP_STRIN:
wC = JimSearchList(interp, B, A);
break;
@@ -13199,6 +14284,11 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
OPRINIT("in", 55, 2, JimExprOpStrBin),
OPRINIT("ni", 55, 2, JimExprOpStrBin),
+ OPRINIT("lt", 75, 2, JimExprOpStrBin),
+ OPRINIT("gt", 75, 2, JimExprOpStrBin),
+ OPRINIT("le", 75, 2, JimExprOpStrBin),
+ OPRINIT("ge", 75, 2, JimExprOpStrBin),
+
OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC),
OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC),
@@ -13244,13 +14334,22 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
static int JimParseExpression(struct JimParserCtx *pc)
{
+ while (1) {
- while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
- if (*pc->p == '\n') {
- pc->linenr++;
+ while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
+ if (*pc->p == '\n') {
+ pc->linenr++;
+ }
+ pc->p++;
+ pc->len--;
}
- pc->p++;
- pc->len--;
+
+ if (*pc->p == '#') {
+ JimParseComment(pc);
+
+ continue;
+ }
+ break;
}
@@ -13374,17 +14473,11 @@ static int JimParseExprIrrational(struct JimParserCtx *pc)
static int JimParseExprBoolean(struct JimParserCtx *pc)
{
- const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL };
- const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 };
int i;
-
- for (i = 0; booleans[i]; i++) {
- const char *boolean = booleans[i];
- int length = lengths[i];
-
- if (strncmp(boolean, pc->p, length) == 0) {
- pc->p += length;
- pc->len -= length;
+ for (i = 0; i < sizeof(jim_true_false_strings) / sizeof(*jim_true_false_strings); i++) {
+ if (strncmp(pc->p, jim_true_false_strings[i], jim_true_false_lens[i]) == 0) {
+ pc->p += jim_true_false_lens[i];
+ pc->len -= jim_true_false_lens[i];
pc->tend = pc->p - 1;
pc->tt = JIM_TT_EXPR_BOOLEAN;
return JIM_OK;
@@ -13481,7 +14574,7 @@ static const Jim_ObjType exprObjType = {
FreeExprInternalRep,
DupExprInternalRep,
NULL,
- JIM_TYPE_REFERENCES,
+ JIM_TYPE_NONE,
};
@@ -13573,8 +14666,7 @@ static void JimShowExprNode(struct JimExprNode *node, int level)
#define EXPR_FUNC_ARGS 0x0002
#define EXPR_TERNARY 0x0004
-static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms)
-{
+static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) {
int rc;
struct JimExprNode *node;
@@ -13828,7 +14920,7 @@ static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenL
builder.exprObjPtr = exprObjPtr;
builder.fileNameObj = fileNameObj;
- builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
+ builder.nodes = Jim_Alloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1));
builder.next = builder.nodes;
Jim_InitStack(&builder.stack);
@@ -14006,6 +15098,9 @@ static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node)
return JIM_ERR;
case JIM_TT_ESC:
+ if (interp->safeexpr) {
+ return JIM_ERR;
+ }
if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) {
Jim_SetResult(interp, objPtr);
return JIM_OK;
@@ -14013,6 +15108,9 @@ static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node)
return JIM_ERR;
case JIM_TT_CMD:
+ if (interp->safeexpr) {
+ return JIM_ERR;
+ }
return Jim_EvalObj(interp, node->objPtr);
default:
@@ -14045,13 +15143,15 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
struct ExprTree *expr;
int retcode = JIM_OK;
+ Jim_IncrRefCount(exprObjPtr);
expr = JimGetExpression(interp, exprObjPtr);
if (!expr) {
- return JIM_ERR;
+ retcode = JIM_ERR;
+ goto done;
}
#ifdef JIM_OPTIMIZATION
- {
+ if (!interp->safeexpr) {
Jim_Obj *objPtr;
@@ -14060,7 +15160,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
objPtr = JimExprIntValOrVar(interp, expr->expr);
if (objPtr) {
Jim_SetResult(interp, objPtr);
- return JIM_OK;
+ goto done;
}
break;
@@ -14070,7 +15170,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
if (objPtr && JimIsWide(objPtr)) {
Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj);
- return JIM_OK;
+ goto done;
}
}
break;
@@ -14106,7 +15206,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr)
goto noopt;
}
Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj);
- return JIM_OK;
+ goto done;
}
}
break;
@@ -14120,7 +15220,13 @@ noopt:
retcode = JimExprEvalTermNode(interp, expr->expr);
- expr->inUse--;
+
+ Jim_FreeIntRep(interp, exprObjPtr);
+ exprObjPtr->typePtr = &exprObjType;
+ Jim_SetIntRepPtr(exprObjPtr, expr);
+
+done:
+ Jim_DecrRefCount(interp, exprObjPtr);
return retcode;
}
@@ -14407,7 +15513,7 @@ static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const cha
break;
n = utf8_tounicode(str, &c);
- if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
+ if (sdescr && !JimCharsetMatch(sdescr, strlen(sdescr), c, JIM_CHARSET_SCAN))
break;
while (n--)
*p++ = *str++;
@@ -14417,7 +15523,7 @@ static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const cha
}
-static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen,
+static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int str_bytelen,
ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr)
{
const char *tok;
@@ -14430,17 +15536,17 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
*valObjPtr = 0;
if (descr->prefix) {
- for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
+ for (i = 0; pos < str_bytelen && descr->prefix[i]; ++i) {
if (isspace(UCHAR(descr->prefix[i])))
- while (pos < strLen && isspace(UCHAR(str[pos])))
+ while (pos < str_bytelen && isspace(UCHAR(str[pos])))
++pos;
else if (descr->prefix[i] != str[pos])
break;
else
++pos;
}
- if (pos >= strLen) {
+ if (pos >= str_bytelen) {
return -1;
}
else if (descr->prefix[i] != 0)
@@ -14451,6 +15557,7 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
while (isspace(UCHAR(str[pos])))
++pos;
+
scanned = pos - anchor;
@@ -14458,20 +15565,20 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
*valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
}
- else if (pos >= strLen) {
+ else if (pos >= str_bytelen) {
return -1;
}
else if (descr->type == 'c') {
- int c;
- scanned += utf8_tounicode(&str[pos], &c);
- *valObjPtr = Jim_NewIntObj(interp, c);
- return scanned;
+ int c;
+ scanned += utf8_tounicode(&str[pos], &c);
+ *valObjPtr = Jim_NewIntObj(interp, c);
+ return scanned;
}
else {
if (descr->width > 0) {
- size_t sLen = utf8_strlen(&str[pos], strLen - pos);
+ size_t sLen = utf8_strlen(&str[pos], str_bytelen - pos);
size_t tLen = descr->width > sLen ? sLen : descr->width;
tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
@@ -14550,7 +15657,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
size_t i, pos;
int scanned = 1;
const char *str = Jim_String(strObjPtr);
- int strLen = Jim_Utf8Length(interp, strObjPtr);
+ int str_bytelen = Jim_Length(strObjPtr);
Jim_Obj *resultList = 0;
Jim_Obj **resultVec = 0;
int resultc;
@@ -14587,7 +15694,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
continue;
if (scanned > 0)
- scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
+ scanned = ScanOneEntry(interp, str, pos, str_bytelen, fmtObj, i, &value);
if (scanned == -1 && i == 0)
goto eof;
@@ -14709,7 +15816,7 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
if (argc == 3) {
- if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
+ if (Jim_GetWideExpr(interp, argv[2], &increment) != JIM_OK)
return JIM_ERR;
}
intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
@@ -14745,6 +15852,45 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
#define JIM_EVAL_SARGV_LEN 8
#define JIM_EVAL_SINTV_LEN 8
+static int JimTraceCallback(Jim_Interp *interp, const char *type, int argc, Jim_Obj *const *argv)
+{
+ JimPanic((interp->traceCmdObj == NULL, "xtrace invoked with no object"));
+
+ int ret;
+ Jim_Obj *nargv[7];
+ Jim_Obj *traceCmdObj = interp->traceCmdObj;
+ Jim_Obj *resultObj = Jim_GetResult(interp);
+
+ ScriptObj *script = JimGetScript(interp, interp->evalFrame->scriptObj);
+
+ nargv[0] = traceCmdObj;
+ nargv[1] = Jim_NewStringObj(interp, type, -1);
+ nargv[2] = script->fileNameObj;
+ nargv[3] = Jim_NewIntObj(interp, script->linenr);
+ nargv[4] = resultObj;
+ nargv[5] = argv[0];
+ nargv[6] = Jim_NewListObj(interp, argv + 1, argc - 1);
+
+
+ interp->traceCmdObj = NULL;
+
+ Jim_IncrRefCount(resultObj);
+ ret = Jim_EvalObjVector(interp, 7, nargv);
+ Jim_DecrRefCount(interp, resultObj);
+
+ if (ret == JIM_OK || ret == JIM_RETURN) {
+
+ interp->traceCmdObj = traceCmdObj;
+ Jim_SetEmptyResult(interp);
+ ret = JIM_OK;
+ }
+ else {
+
+ Jim_DecrRefCount(interp, traceCmdObj);
+ }
+ return ret;
+}
+
static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -14767,11 +15913,39 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return retcode;
}
+static void JimPushEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *scriptObj)
+{
+ memset(frame, 0, sizeof(*frame));
+ frame->parent = interp->evalFrame;
+ frame->level = frame->parent->level + 1;
+ frame->procLevel = interp->procLevel;
+ frame->framePtr = interp->framePtr;
+ if (scriptObj) {
+ frame->scriptObj = scriptObj;
+ }
+ else {
+ frame->scriptObj = frame->parent->scriptObj;
+ }
+ interp->evalFrame = frame;
+#if 0
+ if (frame->scriptObj) {
+ printf("script: %.*s\n", 20, Jim_String(frame->scriptObj));
+ }
+#endif
+}
+
+static void JimPopEvalFrame(Jim_Interp *interp)
+{
+ interp->evalFrame = interp->evalFrame->parent;
+}
+
+
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
int retcode;
Jim_Cmd *cmdPtr;
void *prevPrivData;
+ Jim_Obj *tailcallObj = NULL;
#if 0
printf("invoke");
@@ -14782,18 +15956,11 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
printf("\n");
#endif
- if (interp->framePtr->tailcallCmd) {
-
- cmdPtr = interp->framePtr->tailcallCmd;
- interp->framePtr->tailcallCmd = NULL;
- }
- else {
- cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
- if (cmdPtr == NULL) {
- return JimUnknown(interp, objc, objv);
- }
- JimIncrCmdRefCount(cmdPtr);
+ cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
+ if (cmdPtr == NULL) {
+ return JimUnknown(interp, objc, objv);
}
+ JimIncrCmdRefCount(cmdPtr);
if (interp->evalDepth == interp->maxEvalDepth) {
Jim_SetResultString(interp, "Infinite eval recursion", -1);
@@ -14803,34 +15970,87 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
interp->evalDepth++;
prevPrivData = interp->cmdPrivData;
+tailcall:
- Jim_SetEmptyResult(interp);
- if (cmdPtr->isproc) {
- retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
+ interp->evalFrame->argc = objc;
+ interp->evalFrame->argv = objv;
+ interp->evalFrame->cmd = cmdPtr;
+
+ if (!interp->traceCmdObj ||
+ (retcode = JimTraceCallback(interp, "cmd", objc, objv)) == JIM_OK) {
+
+ Jim_SetEmptyResult(interp);
+ if (cmdPtr->isproc) {
+ retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
+ }
+ else {
+ interp->cmdPrivData = cmdPtr->u.native.privData;
+ retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+ }
+ if (retcode == JIM_ERR) {
+ JimSetErrorStack(interp);
+ }
}
- else {
- interp->cmdPrivData = cmdPtr->u.native.privData;
- retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+
+ if (tailcallObj) {
+
+ Jim_DecrRefCount(interp, tailcallObj);
+ tailcallObj = NULL;
}
+
+
+ interp->evalFrame->argc = 0;
+ interp->evalFrame->argv = NULL;
+
+
+ if (retcode == JIM_EVAL && interp->framePtr->tailcallObj) {
+ JimDecrCmdRefCount(interp, cmdPtr);
+
+
+ cmdPtr = interp->framePtr->tailcallCmd;
+ interp->framePtr->tailcallCmd = NULL;
+ tailcallObj = interp->framePtr->tailcallObj;
+ interp->framePtr->tailcallObj = NULL;
+ objc = tailcallObj->internalRep.listValue.len;
+ objv = tailcallObj->internalRep.listValue.ele;
+ goto tailcall;
+ }
+
interp->cmdPrivData = prevPrivData;
interp->evalDepth--;
out:
JimDecrCmdRefCount(interp, cmdPtr);
+ if (retcode == JIM_ERR) {
+ JimSetErrorStack(interp);
+ }
+
+ if (interp->framePtr->tailcallObj) {
+ JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
+ Jim_DecrRefCount(interp, interp->framePtr->tailcallObj);
+ interp->framePtr->tailcallCmd = NULL;
+ interp->framePtr->tailcallObj = NULL;
+ }
+
return retcode;
}
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
int i, retcode;
+ Jim_EvalFrame frame;
for (i = 0; i < objc; i++)
Jim_IncrRefCount(objv[i]);
+ JimPushEvalFrame(interp, &frame, NULL);
+
retcode = JimInvokeCommand(interp, objc, objv);
+ JimPopEvalFrame(interp);
+
for (i = 0; i < objc; i++)
Jim_DecrRefCount(interp, objv[i]);
@@ -14850,40 +16070,10 @@ int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *co
return ret;
}
-static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
-{
- if (!interp->errorFlag) {
-
- interp->errorFlag = 1;
- Jim_IncrRefCount(script->fileNameObj);
- Jim_DecrRefCount(interp, interp->errorFileNameObj);
- interp->errorFileNameObj = script->fileNameObj;
- interp->errorLine = script->linenr;
-
- JimResetStackTrace(interp);
-
- interp->addStackTrace++;
- }
-
-
- if (interp->addStackTrace > 0) {
-
-
- JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
-
- if (Jim_Length(script->fileNameObj)) {
- interp->addStackTrace = 0;
- }
-
- Jim_DecrRefCount(interp, interp->errorProc);
- interp->errorProc = interp->emptyObj;
- Jim_IncrRefCount(interp->errorProc);
- }
-}
-
static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr)
{
Jim_Obj *objPtr;
+ int ret = JIM_ERR;
switch (token->type) {
case JIM_TT_STR:
@@ -14897,22 +16087,21 @@ static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Ob
objPtr = JimExpandDictSugar(interp, token->objPtr);
break;
case JIM_TT_EXPRSUGAR:
- objPtr = JimExpandExprSugar(interp, token->objPtr);
+ ret = Jim_EvalExpression(interp, token->objPtr);
+ if (ret == JIM_OK) {
+ objPtr = Jim_GetResult(interp);
+ }
+ else {
+ objPtr = NULL;
+ }
break;
case JIM_TT_CMD:
- switch (Jim_EvalObj(interp, token->objPtr)) {
- case JIM_OK:
- case JIM_RETURN:
- objPtr = interp->result;
- break;
- case JIM_BREAK:
-
- return JIM_BREAK;
- case JIM_CONTINUE:
+ ret = Jim_EvalObj(interp, token->objPtr);
+ if (ret == JIM_OK || ret == JIM_RETURN) {
+ objPtr = interp->result;
+ } else {
- return JIM_CONTINUE;
- default:
- return JIM_ERR;
+ objPtr = NULL;
}
break;
default:
@@ -14925,7 +16114,7 @@ static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Ob
*objPtrPtr = objPtr;
return JIM_OK;
}
- return JIM_ERR;
+ return ret;
}
static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags)
@@ -15020,9 +16209,12 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
{
int retcode = JIM_OK;
+ Jim_EvalFrame frame;
JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list."));
+ JimPushEvalFrame(interp, &frame, NULL);
+
if (listPtr->internalRep.listValue.len) {
Jim_IncrRefCount(listPtr);
retcode = JimInvokeCommand(interp,
@@ -15030,6 +16222,9 @@ static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
listPtr->internalRep.listValue.ele);
Jim_DecrRefCount(interp, listPtr);
}
+
+ JimPopEvalFrame(interp);
+
return retcode;
}
@@ -15046,7 +16241,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
ScriptToken *token;
int retcode = JIM_OK;
Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL;
- Jim_Obj *prevScriptObj;
+ Jim_EvalFrame frame;
if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
return JimEvalObjList(interp, scriptObjPtr);
@@ -15054,7 +16249,8 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
Jim_IncrRefCount(scriptObjPtr);
script = JimGetScript(interp, scriptObjPtr);
- if (!JimScriptValid(interp, script)) {
+ if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
+ JimSetErrorStack(interp);
Jim_DecrRefCount(interp, scriptObjPtr);
return JIM_ERR;
}
@@ -15088,9 +16284,8 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
script->inUse++;
+ JimPushEvalFrame(interp, &frame, scriptObjPtr);
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
interp->errorFlag = 0;
argv = sargv;
@@ -15134,7 +16329,13 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG);
break;
case JIM_TT_EXPRSUGAR:
- wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr);
+ retcode = Jim_EvalExpression(interp, token[i].objPtr);
+ if (retcode == JIM_OK) {
+ wordObjPtr = Jim_GetResult(interp);
+ }
+ else {
+ wordObjPtr = NULL;
+ }
break;
case JIM_TT_DICTSUGAR:
wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr);
@@ -15221,16 +16422,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
if (retcode == JIM_ERR) {
- JimAddErrorToStack(interp, script);
- }
-
- else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
-
- interp->addStackTrace = 0;
+ JimSetErrorStack(interp);
}
-
- interp->currentScriptObj = prevScriptObj;
+ JimPopEvalFrame(interp);
Jim_FreeIntRep(interp, scriptObjPtr);
scriptObjPtr->typePtr = &scriptObjType;
@@ -15287,7 +16482,7 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
}
else {
- Jim_AppendString(interp, argmsg, "?arg...?", -1);
+ Jim_AppendString(interp, argmsg, "?arg ...?", -1);
}
}
else {
@@ -15316,13 +16511,11 @@ int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
- callFramePtr->argv = &interp->emptyObj;
- callFramePtr->argc = 0;
+ callFramePtr->argv = interp->evalFrame->argv;
+ callFramePtr->argc = interp->evalFrame->argc;
callFramePtr->procArgsObjPtr = NULL;
callFramePtr->procBodyObjPtr = scriptObj;
callFramePtr->staticVars = NULL;
- callFramePtr->fileNameObj = interp->emptyObj;
- callFramePtr->line = 0;
Jim_IncrRefCount(scriptObj);
interp->framePtr = callFramePtr;
@@ -15348,7 +16541,6 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
{
Jim_CallFrame *callFramePtr;
int i, d, retcode, optargs;
- ScriptObj *script;
if (argc - 1 < cmd->u.proc.reqArity ||
@@ -15376,10 +16568,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
callFramePtr->staticVars = cmd->u.proc.staticVars;
-
- script = JimGetScript(interp, interp->currentScriptObj);
- callFramePtr->fileNameObj = script->fileNameObj;
- callFramePtr->line = script->linenr;
+ interp->procLevel++;
Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
@@ -15427,8 +16616,11 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
}
}
+ if (interp->traceCmdObj == NULL ||
+ (retcode = JimTraceCallback(interp, "proc", argc, argv)) == JIM_OK) {
- retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
+ retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
+ }
badargset:
@@ -15438,29 +16630,6 @@ badargset:
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
- if (interp->framePtr->tailcallObj) {
- do {
- Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
-
- interp->framePtr->tailcallObj = NULL;
-
- if (retcode == JIM_EVAL) {
- retcode = Jim_EvalObjList(interp, tailcallObj);
- if (retcode == JIM_RETURN) {
- interp->returnLevel++;
- }
- }
- Jim_DecrRefCount(interp, tailcallObj);
- } while (interp->framePtr->tailcallObj);
-
-
- if (interp->framePtr->tailcallCmd) {
- JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
- interp->framePtr->tailcallCmd = NULL;
- }
- }
-
-
if (retcode == JIM_RETURN) {
if (--interp->returnLevel <= 0) {
retcode = interp->returnCode;
@@ -15468,12 +16637,7 @@ badargset:
interp->returnLevel = 0;
}
}
- else if (retcode == JIM_ERR) {
- interp->addStackTrace++;
- Jim_DecrRefCount(interp, interp->errorProc);
- interp->errorProc = argv[0];
- Jim_IncrRefCount(interp->errorProc);
- }
+ interp->procLevel--;
return retcode;
}
@@ -15485,22 +16649,10 @@ int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const c
scriptObjPtr = Jim_NewStringObj(interp, script, -1);
Jim_IncrRefCount(scriptObjPtr);
-
if (filename) {
- Jim_Obj *prevScriptObj;
-
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
-
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
-
- retval = Jim_EvalObj(interp, scriptObjPtr);
-
- interp->currentScriptObj = prevScriptObj;
- }
- else {
- retval = Jim_EvalObj(interp, scriptObjPtr);
}
+ retval = Jim_EvalObj(interp, scriptObjPtr);
Jim_DecrRefCount(interp, scriptObjPtr);
return retval;
}
@@ -15537,45 +16689,57 @@ int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename)
#include <sys/stat.h>
-int Jim_EvalFile(Jim_Interp *interp, const char *filename)
+static Jim_Obj *JimReadTextFile(Jim_Interp *interp, const char *filename)
{
- FILE *fp;
+ jim_stat_t sb;
+ int fd;
char *buf;
- Jim_Obj *scriptObjPtr;
- Jim_Obj *prevScriptObj;
- struct stat sb;
- int retcode;
int readlen;
- if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
+ if (Jim_Stat(filename, &sb) == -1 || (fd = open(filename, O_RDONLY | O_TEXT, 0666)) < 0) {
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
- return JIM_ERR;
- }
- if (sb.st_size == 0) {
- fclose(fp);
- return JIM_OK;
+ return NULL;
}
-
buf = Jim_Alloc(sb.st_size + 1);
- readlen = fread(buf, 1, sb.st_size, fp);
- if (ferror(fp)) {
- fclose(fp);
+ readlen = read(fd, buf, sb.st_size);
+ close(fd);
+ if (readlen < 0) {
Jim_Free(buf);
Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
+ return NULL;
+ }
+ else {
+ Jim_Obj *objPtr;
+ buf[readlen] = 0;
+
+ objPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
+
+ return objPtr;
+ }
+}
+
+
+int Jim_EvalFile(Jim_Interp *interp, const char *filename)
+{
+ Jim_Obj *filenameObj;
+ Jim_Obj *oldFilenameObj;
+ Jim_Obj *scriptObjPtr;
+ int retcode;
+
+ scriptObjPtr = JimReadTextFile(interp, filename);
+ if (!scriptObjPtr) {
return JIM_ERR;
}
- fclose(fp);
- buf[readlen] = 0;
- scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
- JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
- Jim_IncrRefCount(scriptObjPtr);
+ filenameObj = Jim_NewStringObj(interp, filename, -1);
+ JimSetSourceInfo(interp, scriptObjPtr, filenameObj, 1);
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
+ oldFilenameObj = JimPushInterpObj(interp->currentFilenameObj, filenameObj);
retcode = Jim_EvalObj(interp, scriptObjPtr);
+ JimPopInterpObj(interp, interp->currentFilenameObj, oldFilenameObj);
+
if (retcode == JIM_RETURN) {
if (--interp->returnLevel <= 0) {
@@ -15584,14 +16748,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
interp->returnLevel = 0;
}
}
- if (retcode == JIM_ERR) {
-
- interp->addStackTrace++;
- }
-
- interp->currentScriptObj = prevScriptObj;
-
- Jim_DecrRefCount(interp, scriptObjPtr);
return retcode;
}
@@ -15698,7 +16854,11 @@ static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
{
- ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
+ ScriptObj *script;
+
+ JimPanic((substObjPtr->refCount == 0, "Jim_SubstObj() called with zero refcount object"));
+
+ script = Jim_GetSubst(interp, substObjPtr, flags);
Jim_IncrRefCount(substObjPtr);
script->inUse++;
@@ -15733,7 +16893,7 @@ void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const
}
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
- Jim_HashEntry *he, int type);
+ Jim_Obj *keyObjPtr, void *value, Jim_Obj *patternObjPtr, int type);
#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
@@ -15745,18 +16905,18 @@ static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht,
if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
- he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
+ he = Jim_FindHashEntry(ht, patternObjPtr);
if (he) {
- callback(interp, listObjPtr, he, type);
+ callback(interp, listObjPtr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he),
+ patternObjPtr, type);
}
}
else {
Jim_HashTableIterator htiter;
JimInitHashTableIterator(ht, &htiter);
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
- if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
- callback(interp, listObjPtr, he, type);
- }
+ callback(interp, listObjPtr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he),
+ patternObjPtr, type);
}
}
return listObjPtr;
@@ -15768,26 +16928,37 @@ static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht,
#define JIM_CMDLIST_CHANNELS 2
static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
- Jim_HashEntry *he, int type)
+ Jim_Obj *keyObj, void *value, Jim_Obj *patternObj, int type)
{
- Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
- Jim_Obj *objPtr;
+ Jim_Cmd *cmdPtr = (Jim_Cmd *)value;
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
return;
}
- objPtr = Jim_NewStringObj(interp, he->key, -1);
- Jim_IncrRefCount(objPtr);
+ Jim_IncrRefCount(keyObj);
- if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) {
- Jim_ListAppendElement(interp, listObjPtr, objPtr);
+ if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, keyObj) >= 0) {
+ int match = 1;
+ if (patternObj) {
+ int plen, slen;
+ const char *pattern = Jim_GetStringNoQualifier(patternObj, &plen);
+ const char *str = Jim_GetStringNoQualifier(keyObj, &slen);
+#ifdef JIM_NO_INTROSPECTION
+
+ match = (JimStringCompareUtf8(pattern, plen, str, slen, 0) == 0);
+#else
+ match = JimGlobMatch(pattern, plen, str, slen, 0);
+#endif
+ }
+ if (match) {
+ Jim_ListAppendElement(interp, listObjPtr, keyObj);
+ }
}
- Jim_DecrRefCount(interp, objPtr);
+ Jim_DecrRefCount(interp, keyObj);
}
-
static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type)
{
return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type);
@@ -15797,18 +16968,21 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
#define JIM_VARLIST_GLOBALS 0
#define JIM_VARLIST_LOCALS 1
#define JIM_VARLIST_VARS 2
+#define JIM_VARLIST_MASK 0x000f
#define JIM_VARLIST_VALUES 0x1000
static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
- Jim_HashEntry *he, int type)
+ Jim_Obj *keyObj, void *value, Jim_Obj *patternObj, int type)
{
- Jim_Var *varPtr = Jim_GetHashEntryVal(he);
+ Jim_VarVal *vv = (Jim_VarVal *)value;
- if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
- Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
- if (type & JIM_VARLIST_VALUES) {
- Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
+ if ((type & JIM_VARLIST_MASK) != JIM_VARLIST_LOCALS || vv->linkFramePtr == NULL) {
+ if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, keyObj, 0)) {
+ Jim_ListAppendElement(interp, listObjPtr, keyObj);
+ if (type & JIM_VARLIST_VALUES) {
+ Jim_ListAppendElement(interp, listObjPtr, vv->objPtr);
+ }
}
}
}
@@ -15821,40 +16995,76 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
}
else {
Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
- return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode);
+ return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch,
+ mode);
}
}
-static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr,
- Jim_Obj **objPtrPtr, int info_level_cmd)
+static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objPtrPtr)
{
- Jim_CallFrame *targetCallFrame;
+ long level;
- targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
- if (targetCallFrame == NULL) {
- return JIM_ERR;
- }
+ if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
+ Jim_CallFrame *targetCallFrame = JimGetCallFrameByInteger(interp, level);
+ if (targetCallFrame && targetCallFrame != interp->topFramePtr) {
+#ifdef JIM_NO_INTROSPECTION
- if (targetCallFrame == interp->topFramePtr) {
- Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
- return JIM_ERR;
- }
- if (info_level_cmd) {
- *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc);
+ *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, 1);
+#else
+ *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc);
+#endif
+ return JIM_OK;
+ }
}
- else {
- Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
+ return JIM_ERR;
+}
+
+static int JimInfoFrame(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objPtrPtr)
+{
+ long level;
- Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]);
- Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj);
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line));
- *objPtrPtr = listObj;
+ if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, level);
+ if (frame) {
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "source", -1));
+ if (frame->scriptObj) {
+ ScriptObj *script = JimGetScript(interp, frame->scriptObj);
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "line", -1));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, script->linenr));
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "file", -1));
+ Jim_ListAppendElement(interp, listObj, script->fileNameObj);
+ }
+#ifndef JIM_NO_INTROSPECTION
+ {
+ Jim_Obj *cmdObj = Jim_NewListObj(interp, frame->argv, frame->argc);
+
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "cmd", -1));
+ Jim_ListAppendElement(interp, listObj, cmdObj);
+ }
+#endif
+ {
+ Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame);
+ if (procNameObj) {
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1));
+ Jim_ListAppendElement(interp, listObj, procNameObj);
+ }
+ }
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "level", -1));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - frame->framePtr->level));
+
+ *objPtrPtr = listObj;
+ return JIM_OK;
+ }
}
- return JIM_OK;
+ Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
+ return JIM_ERR;
}
-
static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2 && argc != 3) {
@@ -16058,9 +17268,21 @@ static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
i++;
}
+
+ Jim_SetEmptyResult(interp);
return JIM_OK;
}
+static int JimCheckLoopRetcode(Jim_Interp *interp, int retval)
+{
+ if (retval == JIM_BREAK || retval == JIM_CONTINUE) {
+ if (--interp->returnLevel > 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -16071,7 +17293,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
while (1) {
- int boolean, retval;
+ int boolean = 0, retval;
if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
return retval;
@@ -16079,13 +17301,14 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
break;
if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) {
+ if (JimCheckLoopRetcode(interp, retval)) {
+ return retval;
+ }
switch (retval) {
case JIM_BREAK:
goto out;
- break;
case JIM_CONTINUE:
continue;
- break;
default:
return retval;
}
@@ -16101,6 +17324,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
{
int retval;
int boolean = 1;
+ int immediate = 0;
Jim_Obj *varNamePtr = NULL;
Jim_Obj *stopVarNamePtr = NULL;
@@ -16168,7 +17392,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
if (expr->expr->right->type == JIM_TT_EXPR_INT) {
- if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) {
+ if (Jim_GetWideExpr(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) {
goto evalstart;
}
}
@@ -16207,6 +17431,10 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
retval = Jim_EvalObj(interp, argv[4]);
+ if (JimCheckLoopRetcode(interp, retval)) {
+ immediate++;
+ goto out;
+ }
if (retval == JIM_OK || retval == JIM_CONTINUE) {
retval = JIM_OK;
@@ -16243,6 +17471,10 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
JIM_IF_OPTIM(evalnext:)
retval = Jim_EvalObj(interp, argv[3]);
+ if (JimCheckLoopRetcode(interp, retval)) {
+ immediate++;
+ goto out;
+ }
if (retval == JIM_OK || retval == JIM_CONTINUE) {
JIM_IF_OPTIM(testcond:)
@@ -16258,9 +17490,11 @@ JIM_IF_OPTIM(out:)
Jim_DecrRefCount(interp, varNamePtr);
}
- if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) {
- Jim_SetEmptyResult(interp);
- return JIM_OK;
+ if (!immediate) {
+ if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) {
+ Jim_SetEmptyResult(interp);
+ return JIM_OK;
+ }
}
return retval;
@@ -16275,22 +17509,34 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
jim_wide incr = 1;
Jim_Obj *bodyObjPtr;
- if (argc != 5 && argc != 6) {
- Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body");
+ if (argc < 4 || argc > 6) {
+ Jim_WrongNumArgs(interp, 1, argv, "var ?first? limit ?incr? body");
return JIM_ERR;
}
- if (Jim_GetWide(interp, argv[2], &i) != JIM_OK ||
- Jim_GetWide(interp, argv[3], &limit) != JIM_OK ||
- (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) {
- return JIM_ERR;
+ retval = Jim_GetWideExpr(interp, argv[2], &i);
+ if (argc > 4 && retval == JIM_OK) {
+ retval = Jim_GetWideExpr(interp, argv[3], &limit);
+ }
+ if (argc > 5 && retval == JIM_OK) {
+ Jim_GetWideExpr(interp, argv[4], &incr);
}
- bodyObjPtr = (argc == 5) ? argv[4] : argv[5];
+ if (retval != JIM_OK) {
+ return retval;
+ }
+ if (argc == 4) {
+ limit = i;
+ i = 0;
+ }
+ bodyObjPtr = argv[argc - 1];
- retval = Jim_SetVariable(interp, argv[1], argv[2]);
+ retval = Jim_SetVariable(interp, argv[1], Jim_NewIntObj(interp, i));
while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) {
retval = Jim_EvalObj(interp, bodyObjPtr);
+ if (JimCheckLoopRetcode(interp, retval)) {
+ return retval;
+ }
if (retval == JIM_OK || retval == JIM_CONTINUE) {
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
@@ -16431,7 +17677,11 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
}
}
- switch (result = Jim_EvalObj(interp, script)) {
+ result = Jim_EvalObj(interp, script);
+ if (JimCheckLoopRetcode(interp, result)) {
+ goto err;
+ }
+ switch (result) {
case JIM_OK:
if (doMap) {
Jim_ListAppendElement(interp, resultObj, interp->result);
@@ -16552,19 +17802,21 @@ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
-
int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj,
- Jim_Obj *stringObj, int nocase)
+ Jim_Obj *stringObj, int flags)
{
- Jim_Obj *parms[4];
+ Jim_Obj *parms[5];
int argc = 0;
long eq;
int rc;
parms[argc++] = commandObj;
- if (nocase) {
+ if (flags & JIM_NOCASE) {
parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1);
}
+ if (flags & JIM_OPT_END) {
+ parms[argc++] = Jim_NewStringObj(interp, "--", -1);
+ }
parms[argc++] = patternObj;
parms[argc++] = stringObj;
@@ -16582,6 +17834,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
{
enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
+ int match_flags = 0;
Jim_Obj *command = NULL, *scriptObj = NULL, *strObj;
Jim_Obj **caseList;
@@ -16604,8 +17857,10 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
matchOpt = SWITCH_EXACT;
else if (strncmp(option, "-glob", 2) == 0)
matchOpt = SWITCH_GLOB;
- else if (strncmp(option, "-regexp", 2) == 0)
+ else if (strncmp(option, "-regexp", 2) == 0) {
matchOpt = SWITCH_RE;
+ match_flags |= JIM_OPT_END;
+ }
else if (strncmp(option, "-command", 2) == 0) {
matchOpt = SWITCH_CMD;
if ((argc - opt) < 2)
@@ -16648,7 +17903,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
command = Jim_NewStringObj(interp, "regexp", -1);
case SWITCH_CMD:{
- int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
+ int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, match_flags);
if (argc - opt == 1) {
JimListGetElements(interp, argv[opt], &patCount, &caseList);
@@ -16693,33 +17948,22 @@ static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- Jim_Obj *objPtr, *listObjPtr;
- int i;
- int idx;
+ Jim_Obj *objPtr;
+ int ret;
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
return JIM_ERR;
}
- objPtr = argv[1];
- Jim_IncrRefCount(objPtr);
- for (i = 2; i < argc; i++) {
- listObjPtr = objPtr;
- if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) {
- Jim_DecrRefCount(interp, listObjPtr);
- return JIM_ERR;
- }
- if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) {
- Jim_DecrRefCount(interp, listObjPtr);
- Jim_SetEmptyResult(interp);
- return JIM_OK;
- }
- Jim_IncrRefCount(objPtr);
- Jim_DecrRefCount(interp, listObjPtr);
+ ret = Jim_ListIndices(interp, argv[1], argv + 2, argc - 2, &objPtr, JIM_NONE);
+ if (ret < 0) {
+ ret = JIM_OK;
+ Jim_SetEmptyResult(interp);
}
- Jim_SetResult(interp, objPtr);
- Jim_DecrRefCount(interp, objPtr);
- return JIM_OK;
+ else if (ret == JIM_OK) {
+ Jim_SetResult(interp, objPtr);
+ }
+ return ret;
}
@@ -16738,15 +17982,14 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
{
static const char * const options[] = {
"-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command",
- NULL
+ "-stride", "-index", NULL
};
enum
{ OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE,
- OPT_COMMAND };
+ OPT_COMMAND, OPT_STRIDE, OPT_INDEX };
int i;
int opt_bool = 0;
int opt_not = 0;
- int opt_nocase = 0;
int opt_all = 0;
int opt_inline = 0;
int opt_match = OPT_EXACT;
@@ -16754,11 +17997,14 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
int rc = JIM_OK;
Jim_Obj *listObjPtr = NULL;
Jim_Obj *commandObj = NULL;
+ Jim_Obj *indexObj = NULL;
+ int match_flags = 0;
+ long stride = 1;
if (argc < 3) {
wrongargs:
Jim_WrongNumArgs(interp, 1, argv,
- "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value");
+ "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? ?-stride len? ?-index val? list value");
return JIM_ERR;
}
@@ -16777,7 +18023,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
opt_not = 1;
break;
case OPT_NOCASE:
- opt_nocase = 1;
+ match_flags |= JIM_NOCASE;
break;
case OPT_INLINE:
opt_inline = 1;
@@ -16786,6 +18032,10 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
case OPT_ALL:
opt_all = 1;
break;
+ case OPT_REGEXP:
+ opt_match = option;
+ match_flags |= JIM_OPT_END;
+ break;
case OPT_COMMAND:
if (i >= argc - 2) {
goto wrongargs;
@@ -16794,14 +18044,41 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
case OPT_EXACT:
case OPT_GLOB:
- case OPT_REGEXP:
opt_match = option;
break;
+ case OPT_INDEX:
+ if (i >= argc - 2) {
+ goto wrongargs;
+ }
+ indexObj = argv[++i];
+ break;
+ case OPT_STRIDE:
+ if (i >= argc - 2) {
+ goto wrongargs;
+ }
+ if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) {
+ return JIM_ERR;
+ }
+ if (stride < 1) {
+ Jim_SetResultString(interp, "stride length must be at least 1", -1);
+ return JIM_ERR;
+ }
+ break;
}
}
+ argc -= i;
+ if (argc < 2) {
+ goto wrongargs;
+ }
argv += i;
+ listlen = Jim_ListLength(interp, argv[0]);
+ if (listlen % stride) {
+ Jim_SetResultString(interp, "list size must be a multiple of the stride length", -1);
+ return JIM_ERR;
+ }
+
if (opt_all) {
listObjPtr = Jim_NewListObj(interp, NULL, 0);
}
@@ -16812,27 +18089,52 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
Jim_IncrRefCount(commandObj);
}
- listlen = Jim_ListLength(interp, argv[0]);
- for (i = 0; i < listlen; i++) {
+ for (i = 0; i < listlen; i += stride) {
int eq = 0;
- Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
+ Jim_Obj *searchListObj;
+ Jim_Obj *objPtr;
+ int offset;
+
+ if (indexObj) {
+ int indexlen = Jim_ListLength(interp, indexObj);
+ if (stride == 1) {
+ searchListObj = Jim_ListGetIndex(interp, argv[0], i);
+ }
+ else {
+ searchListObj = Jim_NewListObj(interp, argv[0]->internalRep.listValue.ele + i, stride);
+ }
+ Jim_IncrRefCount(searchListObj);
+ rc = Jim_ListIndices(interp, searchListObj, indexObj->internalRep.listValue.ele, indexlen, &objPtr, JIM_ERRMSG);
+ if (rc != JIM_OK) {
+ Jim_DecrRefCount(interp, searchListObj);
+ rc = JIM_ERR;
+ goto done;
+ }
+
+ offset = 0;
+ }
+ else {
+
+ searchListObj = argv[0];
+ offset = i;
+ objPtr = Jim_ListGetIndex(interp, searchListObj, i);
+ Jim_IncrRefCount(searchListObj);
+ }
switch (opt_match) {
case OPT_EXACT:
- eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
+ eq = Jim_StringCompareObj(interp, argv[1], objPtr, match_flags) == 0;
break;
case OPT_GLOB:
- eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase);
+ eq = Jim_StringMatchObj(interp, argv[1], objPtr, match_flags);
break;
case OPT_REGEXP:
case OPT_COMMAND:
- eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase);
+ eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, match_flags);
if (eq < 0) {
- if (listObjPtr) {
- Jim_FreeNewObj(interp, listObjPtr);
- }
+ Jim_DecrRefCount(interp, searchListObj);
rc = JIM_ERR;
goto done;
}
@@ -16840,12 +18142,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
- if (!eq && opt_bool && opt_not && !opt_all) {
- continue;
- }
-
if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
-
Jim_Obj *resultObj;
if (opt_bool) {
@@ -16854,22 +18151,38 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
else if (!opt_inline) {
resultObj = Jim_NewIntObj(interp, i);
}
- else {
+ else if (stride == 1) {
resultObj = objPtr;
}
+ else if (opt_all) {
+
+ ListInsertElements(listObjPtr, -1, stride,
+ searchListObj->internalRep.listValue.ele + offset);
+
+ resultObj = NULL;
+ }
+ else {
+ resultObj = Jim_NewListObj(interp, searchListObj->internalRep.listValue.ele + offset, stride);
+ }
if (opt_all) {
- Jim_ListAppendElement(interp, listObjPtr, resultObj);
+
+ if (stride == 1) {
+ Jim_ListAppendElement(interp, listObjPtr, resultObj);
+ }
}
else {
Jim_SetResult(interp, resultObj);
+ Jim_DecrRefCount(interp, searchListObj);
goto done;
}
}
+ Jim_DecrRefCount(interp, searchListObj);
}
if (opt_all) {
Jim_SetResult(interp, listObjPtr);
+ listObjPtr = NULL;
}
else {
@@ -16882,6 +18195,9 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
done:
+ if (listObjPtr) {
+ Jim_FreeNewObj(interp, listObjPtr);
+ }
if (commandObj) {
Jim_DecrRefCount(interp, commandObj);
}
@@ -16995,7 +18311,7 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
+ Jim_WrongNumArgs(interp, 1, argv, "listVar ?index ...? value");
return JIM_ERR;
}
else if (argc == 3) {
@@ -17012,25 +18328,30 @@ static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
{
static const char * const options[] = {
- "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
+ "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique",
+ "-stride", NULL
+ };
+ enum {
+ OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE,
+ OPT_STRIDE
};
- enum
- { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
Jim_Obj *resObj;
int i;
int retCode;
int shared;
+ long stride = 1;
struct lsort_info info;
if (argc < 2) {
+wrongargs:
Jim_WrongNumArgs(interp, 1, argv, "?options? list");
return JIM_ERR;
}
info.type = JIM_LSORT_ASCII;
info.order = 1;
- info.indexed = 0;
+ info.indexc = 0;
info.unique = 0;
info.command = NULL;
info.interp = interp;
@@ -17072,28 +18393,72 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
info.command = argv[i + 1];
i++;
break;
+ case OPT_STRIDE:
+ if (i >= argc - 2) {
+ goto wrongargs;
+ }
+ if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) {
+ return JIM_ERR;
+ }
+ if (stride < 2) {
+ Jim_SetResultString(interp, "stride length must be at least 2", -1);
+ return JIM_ERR;
+ }
+ break;
case OPT_INDEX:
if (i >= (argc - 2)) {
+badindex:
Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1);
return JIM_ERR;
}
- if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) {
- return JIM_ERR;
+ JimListGetElements(interp, argv[i + 1], &info.indexc, &info.indexv);
+ if (info.indexc == 0) {
+ goto badindex;
}
- info.indexed = 1;
i++;
break;
}
}
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);
+ if (stride > 1) {
+ Jim_Obj *tmpListObj;
+ Jim_Obj **elements;
+ int listlen;
+ int i;
+
+ JimListGetElements(interp, resObj, &listlen, &elements);
+ if (listlen % stride) {
+ Jim_SetResultString(interp, "list size must be a multiple of the stride length", -1);
+ return JIM_ERR;
+ }
+
+ tmpListObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_IncrRefCount(tmpListObj);
+ for (i = 0; i < listlen; i += stride) {
+ Jim_ListAppendElement(interp, tmpListObj, Jim_NewListObj(interp, elements + i, stride));
+ }
+ retCode = ListSortElements(interp, tmpListObj, &info);
+ if (retCode == JIM_OK) {
+ resObj = Jim_NewListObj(interp, NULL, 0);
+
+ for (i = 0; i < listlen; i += stride) {
+ Jim_ListAppendList(interp, resObj, Jim_ListGetIndex(interp, tmpListObj, i / stride));
+ }
+ Jim_SetResult(interp, resObj);
+ }
+ Jim_DecrRefCount(interp, tmpListObj);
}
- else if (shared) {
- Jim_FreeNewObj(interp, resObj);
+ else {
+ if ((shared = Jim_IsShared(resObj))) {
+ resObj = Jim_DuplicateObj(interp, resObj);
+ }
+ retCode = ListSortElements(interp, resObj, &info);
+ if (retCode == JIM_OK) {
+ Jim_SetResult(interp, resObj);
+ }
+ else if (shared) {
+ Jim_FreeNewObj(interp, resObj);
+ }
}
return retCode;
}
@@ -17141,13 +18506,6 @@ 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)
- Jim_SetResultString(interp, "unsupported", -1);
- return JIM_ERR;
-#endif
-}
static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -17166,10 +18524,6 @@ static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
}
- if (rc == JIM_ERR) {
-
- interp->addStackTrace++;
- }
return rc;
}
@@ -17226,6 +18580,12 @@ static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
if (argc == 2) {
retcode = Jim_EvalExpression(interp, argv[1]);
}
+#ifndef JIM_COMPAT
+ else {
+ Jim_WrongNumArgs(interp, 1, argv, "expression");
+ retcode = JIM_ERR;
+ }
+#else
else if (argc > 2) {
Jim_Obj *objPtr;
@@ -17238,29 +18598,68 @@ static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
return JIM_ERR;
}
- if (retcode != JIM_OK)
- return retcode;
- return JIM_OK;
+#endif
+ return retcode;
}
-
-static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int JimBreakContinueHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int retcode)
{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
+ if (argc != 1 && argc != 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "?level?");
return JIM_ERR;
}
- return JIM_BREAK;
+ if (argc == 2) {
+ long level;
+ int ret = Jim_GetLong(interp, argv[1], &level);
+ if (ret != JIM_OK) {
+ return ret;
+ }
+ interp->returnLevel = level;
+ }
+ return retcode;
+}
+
+
+static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ return JimBreakContinueHelper(interp, argc, argv, JIM_BREAK);
}
static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
- return JIM_ERR;
+ return JimBreakContinueHelper(interp, argc, argv, JIM_CONTINUE);
+}
+
+
+static int Jim_StacktraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_Obj *listObj;
+ int i;
+ jim_wide skip = 0;
+ jim_wide last = 0;
+
+ if (argc > 1) {
+ if (Jim_GetWideExpr(interp, argv[1], &skip) != JIM_OK) {
+ return JIM_ERR;
+ }
}
- return JIM_CONTINUE;
+ if (argc > 2) {
+ if (Jim_GetWideExpr(interp, argv[2], &last) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+
+ listObj = Jim_NewListObj(interp, NULL, 0);
+ for (i = skip; i <= interp->procLevel; i++) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
+ if (frame->procLevel < last) {
+ break;
+ }
+ JimAddStackFrame(interp, frame, listObj);
+ }
+ Jim_SetResult(interp, listObj);
+ return JIM_OK;
}
@@ -17314,7 +18713,7 @@ static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
if (i == argc - 1) {
Jim_SetResult(interp, argv[i]);
}
- return JIM_RETURN;
+ return level == 0 ? returnCode : JIM_RETURN;
}
@@ -17372,7 +18771,6 @@ static void JimAliasCmdDelete(Jim_Interp *interp, void *privData)
static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *prefixListObj;
- const char *newname;
if (argc < 3) {
Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?");
@@ -17381,15 +18779,9 @@ static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2);
Jim_IncrRefCount(prefixListObj);
- newname = Jim_String(argv[1]);
- if (newname[0] == ':' && newname[1] == ':') {
- while (*++newname == ':') {
- }
- }
-
Jim_SetResult(interp, argv[1]);
- return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete);
+ return Jim_CreateCommandObj(interp, argv[1], JimAliasCmd, prefixListObj, JimAliasCmdDelete);
}
@@ -17402,10 +18794,6 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
- if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) {
- return JIM_ERR;
- }
-
if (argc == 4) {
cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL);
}
@@ -17415,15 +18803,12 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
if (cmd) {
- Jim_Obj *qualifiedCmdNameObj;
- const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
-
- JimCreateCommand(interp, cmdname, cmd);
+ Jim_Obj *nameObjPtr = JimQualifyName(interp, argv[1]);
+ JimCreateCommand(interp, nameObjPtr, cmd);
- JimUpdateProcNamespace(interp, cmd, cmdname);
-
- JimFreeQualifiedName(interp, qualifiedCmdNameObj);
+ JimUpdateProcNamespace(interp, cmd, nameObjPtr);
+ Jim_DecrRefCount(interp, nameObjPtr);
Jim_SetResult(interp, argv[1]);
@@ -17433,6 +18818,27 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
+static int Jim_XtraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ if (argc != 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "callback");
+ return JIM_ERR;
+ }
+
+ if (interp->traceCmdObj) {
+ Jim_DecrRefCount(interp, interp->traceCmdObj);
+ interp->traceCmdObj = NULL;
+ }
+
+ if (Jim_Length(argv[1])) {
+
+ interp->traceCmdObj = argv[1];
+ Jim_IncrRefCount(interp->traceCmdObj);
+ }
+ return JIM_OK;
+}
+
+
static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int retcode;
@@ -17520,7 +18926,7 @@ static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
if (len == 3) {
#ifdef jim_ext_namespace
- nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
+ nsObj = Jim_ListGetIndex(interp, argv[1], 2);
#else
Jim_SetResultString(interp, "namespaces not enabled", -1);
return JIM_ERR;
@@ -17643,7 +19049,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
if (strLen >= kl && kl) {
int rc;
- rc = JimStringCompareLen(str, k, kl, nocase);
+ rc = JimStringCompareUtf8(str, kl, k, kl, nocase);
if (rc == 0) {
if (noMatchStart) {
Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
@@ -17676,17 +19082,6 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
int len;
int opt_case = 1;
int option;
- static const char * const options[] = {
- "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace",
- "map", "repeat", "reverse", "index", "first", "last", "cat",
- "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL
- };
- enum
- {
- OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE,
- OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, OPT_CAT,
- OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE
- };
static const char * const nocase_options[] = {
"-nocase", NULL
};
@@ -17694,28 +19089,74 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
"-nocase", "-length", NULL
};
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
+ enum {
+ OPT_BYTELENGTH,
+ OPT_BYTERANGE,
+ OPT_CAT,
+ OPT_COMPARE,
+ OPT_EQUAL,
+ OPT_FIRST,
+ OPT_INDEX,
+ OPT_IS,
+ OPT_LAST,
+ OPT_LENGTH,
+ OPT_MAP,
+ OPT_MATCH,
+ OPT_RANGE,
+ OPT_REPEAT,
+ OPT_REPLACE,
+ OPT_REVERSE,
+ OPT_TOLOWER,
+ OPT_TOTITLE,
+ OPT_TOUPPER,
+ OPT_TRIM,
+ OPT_TRIMLEFT,
+ OPT_TRIMRIGHT,
+ OPT_COUNT
+ };
+ static const jim_subcmd_type cmds[OPT_COUNT + 1] = {
+ JIM_DEF_SUBCMD("bytelength", "string", 1, 1),
+ JIM_DEF_SUBCMD("byterange", "string first last", 3, 3),
+ JIM_DEF_SUBCMD("cat", "?...?", 0, -1),
+ JIM_DEF_SUBCMD("compare", "?-nocase? ?-length int? string1 string2", 2, 5),
+ JIM_DEF_SUBCMD("equal", "?-nocase? ?-length int? string1 string2", 2, 5),
+ JIM_DEF_SUBCMD("first", "subString string ?index?", 2, 3),
+ JIM_DEF_SUBCMD("index", "string index", 2, 2),
+ JIM_DEF_SUBCMD("is", "class ?-strict? str", 2, 3),
+ JIM_DEF_SUBCMD("last", "subString string ?index?", 2, 3),
+ JIM_DEF_SUBCMD("length","string", 1, 1),
+ JIM_DEF_SUBCMD("map", "?-nocase? mapList string", 2, 3),
+ JIM_DEF_SUBCMD("match", "?-nocase? pattern string", 2, 3),
+ JIM_DEF_SUBCMD("range", "string first last", 3, 3),
+ JIM_DEF_SUBCMD("repeat", "string count", 2, 2),
+ JIM_DEF_SUBCMD("replace", "string first last ?string?", 3, 4),
+ JIM_DEF_SUBCMD("reverse", "string", 1, 1),
+ JIM_DEF_SUBCMD("tolower", "string", 1, 1),
+ JIM_DEF_SUBCMD("totitle", "string", 1, 1),
+ JIM_DEF_SUBCMD("toupper", "string", 1, 1),
+ JIM_DEF_SUBCMD("trim", "string ?trimchars?", 1, 2),
+ JIM_DEF_SUBCMD("trimleft", "string ?trimchars?", 1, 2),
+ JIM_DEF_SUBCMD("trimright", "string ?trimchars?", 1, 2),
+ { }
+ };
+ const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
+ if (!ct) {
return JIM_ERR;
}
- if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
- JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
- return Jim_CheckShowCommands(interp, argv[1], options);
+ if (ct->function) {
+
+ return ct->function(interp, argc, argv);
+ }
+
+ option = ct - cmds;
switch (option) {
case OPT_LENGTH:
+ Jim_SetResultInt(interp, Jim_Utf8Length(interp, argv[2]));
+ return JIM_OK;
+
case OPT_BYTELENGTH:
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "string");
- return JIM_ERR;
- }
- if (option == OPT_LENGTH) {
- len = Jim_Utf8Length(interp, argv[2]);
- }
- else {
- len = Jim_Length(argv[2]);
- }
- Jim_SetResultInt(interp, len);
+ Jim_SetResultInt(interp, Jim_Length(argv[2]));
return JIM_OK;
case OPT_CAT:{
@@ -17749,7 +19190,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL,
JIM_ENUM_ABBREV) != JIM_OK) {
badcompareargs:
- Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
+ Jim_SubCmdArgError(interp, ct, argv[0]);
return JIM_ERR;
}
if (subopt == 0) {
@@ -17777,12 +19218,19 @@ badcompareargs:
Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
}
else {
+ const char *s1 = Jim_String(argv[0]);
+ int l1 = Jim_Utf8Length(interp, argv[0]);
+ const char *s2 = Jim_String(argv[1]);
+ int l2 = Jim_Utf8Length(interp, argv[1]);
if (opt_length >= 0) {
- n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
- }
- else {
- n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case);
+ if (l1 > opt_length) {
+ l1 = opt_length;
+ }
+ if (l2 > opt_length) {
+ l2 = opt_length;
+ }
}
+ n = JimStringCompareUtf8(s1, l1, s2, l2, !opt_case);
Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0);
}
return JIM_OK;
@@ -17824,22 +19272,17 @@ badcompareargs:
return JIM_OK;
}
- case OPT_RANGE:
- case OPT_BYTERANGE:{
- Jim_Obj *objPtr;
-
- if (argc != 5) {
- Jim_WrongNumArgs(interp, 2, argv, "string first last");
+ case OPT_RANGE:{
+ Jim_Obj *objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]);
+ if (objPtr == NULL) {
return JIM_ERR;
}
- if (option == OPT_RANGE) {
- objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]);
- }
- else
- {
- objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]);
- }
+ Jim_SetResult(interp, objPtr);
+ return JIM_OK;
+ }
+ case OPT_BYTERANGE:{
+ Jim_Obj *objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]);
if (objPtr == NULL) {
return JIM_ERR;
}
@@ -17848,13 +19291,7 @@ badcompareargs:
}
case OPT_REPLACE:{
- Jim_Obj *objPtr;
-
- if (argc != 5 && argc != 6) {
- Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?");
- return JIM_ERR;
- }
- objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL);
+ Jim_Obj *objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL);
if (objPtr == NULL) {
return JIM_ERR;
}
@@ -17867,11 +19304,7 @@ badcompareargs:
Jim_Obj *objPtr;
jim_wide count;
- if (argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "string count");
- return JIM_ERR;
- }
- if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) {
+ if (Jim_GetWideExpr(interp, argv[3], &count) != JIM_OK) {
return JIM_ERR;
}
objPtr = Jim_NewStringObj(interp, "", 0);
@@ -17889,13 +19322,9 @@ badcompareargs:
const char *str;
int i;
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "string");
- return JIM_ERR;
- }
-
str = Jim_GetString(argv[2], &len);
buf = Jim_Alloc(len + 1);
+ assert(buf);
p = buf + len;
*p = 0;
for (i = 0; i < len; ) {
@@ -17914,18 +19343,12 @@ badcompareargs:
int idx;
const char *str;
- if (argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "string index");
- return JIM_ERR;
- }
if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) {
return JIM_ERR;
}
str = Jim_String(argv[2]);
len = Jim_Utf8Length(interp, argv[2]);
- if (idx != INT_MIN && idx != INT_MAX) {
- idx = JimRelToAbsIndex(len, idx);
- }
+ idx = JimRelToAbsIndex(len, idx);
if (idx < 0 || idx >= len || str == NULL) {
Jim_SetResultString(interp, "", 0);
}
@@ -17946,10 +19369,6 @@ badcompareargs:
int idx = 0, l1, l2;
const char *s1, *s2;
- if (argc != 4 && argc != 5) {
- Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?");
- return JIM_ERR;
- }
s1 = Jim_String(argv[2]);
s2 = Jim_String(argv[3]);
l1 = Jim_Utf8Length(interp, argv[2]);
@@ -17959,6 +19378,9 @@ badcompareargs:
return JIM_ERR;
}
idx = JimRelToAbsIndex(l2, idx);
+ if (idx < 0) {
+ idx = 0;
+ }
}
else if (option == OPT_LAST) {
idx = l2;
@@ -17977,51 +19399,32 @@ badcompareargs:
}
case OPT_TRIM:
+ Jim_SetResult(interp, JimStringTrim(interp, argv[2], argc == 4 ? argv[3] : NULL));
+ return JIM_OK;
case OPT_TRIMLEFT:
+ Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], argc == 4 ? argv[3] : NULL));
+ return JIM_OK;
case OPT_TRIMRIGHT:{
- Jim_Obj *trimchars;
-
- if (argc != 3 && argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?");
- return JIM_ERR;
- }
- trimchars = (argc == 4 ? argv[3] : NULL);
- if (option == OPT_TRIM) {
- Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars));
- }
- else if (option == OPT_TRIMLEFT) {
- Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars));
- }
- else if (option == OPT_TRIMRIGHT) {
- Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars));
- }
+ Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], argc == 4 ? argv[3] : NULL));
return JIM_OK;
- }
+ }
case OPT_TOLOWER:
- case OPT_TOUPPER:
- case OPT_TOTITLE:
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "string");
- return JIM_ERR;
- }
- if (option == OPT_TOLOWER) {
Jim_SetResult(interp, JimStringToLower(interp, argv[2]));
- }
- else if (option == OPT_TOUPPER) {
+ return JIM_OK;
+ case OPT_TOUPPER:
Jim_SetResult(interp, JimStringToUpper(interp, argv[2]));
- }
- else {
+ return JIM_OK;
+ case OPT_TOTITLE:
Jim_SetResult(interp, JimStringToTitle(interp, argv[2]));
- }
- return JIM_OK;
+ return JIM_OK;
case OPT_IS:
- if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) {
- return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5);
+ if (argc == 5 && !Jim_CompareStringImmediate(interp, argv[3], "-strict")) {
+ Jim_SubCmdArgError(interp, ct, argv[0]);
+ return JIM_ERR;
}
- Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str");
- return JIM_ERR;
+ return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5);
}
return JIM_OK;
}
@@ -18031,8 +19434,6 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
{
long i, count = 1;
jim_wide start, elapsed;
- char buf[60];
- const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration";
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "script ?count?");
@@ -18045,7 +19446,7 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
if (count < 0)
return JIM_OK;
i = count;
- start = JimClock();
+ start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
while (i-- > 0) {
int retval;
@@ -18054,9 +19455,79 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return retval;
}
}
- elapsed = JimClock() - start;
- sprintf(buf, fmt, count == 0 ? 0 : elapsed / count);
- Jim_SetResultString(interp, buf, -1);
+ elapsed = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
+ if (elapsed < count * 10) {
+ Jim_SetResult(interp, Jim_NewDoubleObj(interp, elapsed * 1.0 / count));
+ }
+ else {
+ Jim_SetResultInt(interp, count == 0 ? 0 : elapsed / count);
+ }
+ Jim_AppendString(interp, Jim_GetResult(interp)," microseconds per iteration", -1);
+ return JIM_OK;
+}
+
+
+static int Jim_TimeRateCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ long us = 0;
+ jim_wide start, delta, overhead;
+ Jim_Obj *objPtr;
+ double us_per_iter;
+ int count;
+ int n;
+
+ if (argc < 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "script ?milliseconds?");
+ return JIM_ERR;
+ }
+ if (argc == 3) {
+ if (Jim_GetLong(interp, argv[2], &us) != JIM_OK)
+ return JIM_ERR;
+ us *= 1000;
+ }
+ if (us < 1) {
+
+ us = 1000 * 1000;
+ }
+
+
+ start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
+ count = 0;
+ do {
+ int retval = Jim_EvalObj(interp, argv[1]);
+ delta = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
+ if (retval != JIM_OK) {
+ return retval;
+ }
+ count++;
+ } while (delta < us);
+
+
+ start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
+ n = 0;
+ do {
+ int retval = Jim_EvalObj(interp, interp->nullScriptObj);
+ overhead = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
+ if (retval != JIM_OK) {
+ return retval;
+ }
+ n++;
+ } while (n < count);
+
+ delta -= overhead;
+
+ us_per_iter = (double)delta / count;
+ objPtr = Jim_NewListObj(interp, NULL, 0);
+
+ Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "us_per_iter", -1));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewDoubleObj(interp, us_per_iter));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "iters_per_sec", -1));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewDoubleObj(interp, 1e6 / us_per_iter));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "count", -1));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewIntObj(interp, count));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, "elapsed_us", -1));
+ Jim_ListAppendElement(interp, objPtr, Jim_NewIntObj(interp, delta));
+ Jim_SetResult(interp, objPtr);
return JIM_OK;
}
@@ -18072,22 +19543,52 @@ static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
if (argc == 2) {
if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK)
return JIM_ERR;
+ Jim_SetResult(interp, argv[1]);
}
interp->exitCode = exitCode;
return JIM_EXIT;
}
+static int JimMatchReturnCodes(Jim_Interp *interp, Jim_Obj *retcodeListObj, int rc)
+{
+ int len = Jim_ListLength(interp, retcodeListObj);
+ int i;
+ for (i = 0; i < len; i++) {
+ int returncode;
+ if (Jim_GetReturnCode(interp, Jim_ListGetIndex(interp, retcodeListObj, i), &returncode) != JIM_OK) {
+ return JIM_ERR;
+ }
+ if (rc == returncode) {
+ return JIM_OK;
+ }
+ }
+ return -1;
+}
-static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
+static int JimCatchTryHelper(Jim_Interp *interp, int istry, int argc, Jim_Obj *const *argv)
{
+ static const char * const wrongargs_catchtry[2] = {
+ "?-?no?code ... --? script ?resultVarName? ?optionVarName?",
+ "?-?no?code ... --? script ?on|trap codes vars script? ... ?finally script?"
+ };
int exitCode = 0;
int i;
int sig = 0;
+ int ok;
+ Jim_Obj *finallyScriptObj = NULL;
+ Jim_Obj *msgVarObj = NULL;
+ Jim_Obj *optsVarObj = NULL;
+ Jim_Obj *handlerScriptObj = NULL;
+ Jim_Obj *errorCodeObj;
+ int idx;
jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
static const int max_ignore_code = sizeof(ignore_mask) * 8;
+ JimPanic((istry != 0 && istry != 1, "wrong args to JimCatchTryHelper"));
+
Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
for (i = 1; i < argc - 1; i++) {
@@ -18131,14 +19632,13 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
}
- argc -= i;
- if (argc < 1 || argc > 3) {
- wrongargs:
- Jim_WrongNumArgs(interp, 1, argv,
- "?-?no?code ... --? script ?resultVarName? ?optionVarName?");
+ idx = i;
+
+ if (argc - idx < 1) {
+wrongargs:
+ Jim_WrongNumArgs(interp, 1, argv, wrongargs_catchtry[istry]);
return JIM_ERR;
}
- argv += i;
if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
sig++;
@@ -18150,15 +19650,91 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
exitCode = JIM_SIGNAL;
}
else {
- exitCode = Jim_EvalObj(interp, argv[0]);
+ exitCode = Jim_EvalObj(interp, argv[idx]);
interp->errorFlag = 0;
}
interp->signal_level -= sig;
+ errorCodeObj = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE);
+
+ idx++;
+ if (istry) {
+ while (idx < argc) {
+ int option;
+ int ret;
+ static const char * const try_options[] = { "on", "trap", "finally", NULL };
+ enum { TRY_ON, TRY_TRAP, TRY_FINALLY, };
+
+ if (Jim_GetEnum(interp, argv[idx], try_options, &option, "handler", JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ switch (option) {
+ case TRY_ON:
+ case TRY_TRAP:
+ if (idx + 4 > argc) {
+ goto wrongargs;
+ }
+ if (option == TRY_ON) {
+ ret = JimMatchReturnCodes(interp, argv[idx + 1], exitCode);
+ if (ret > JIM_OK) {
+ goto wrongargs;
+ }
+ }
+ else if (errorCodeObj) {
+ int len = Jim_ListLength(interp, argv[idx + 1]);
+ int i;
+
+ ret = JIM_OK;
+
+ for (i = 0; i < len; i++) {
+ Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i);
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i);
+ if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) {
+ ret = -1;
+ break;
+ }
+ }
+ }
+ else {
+
+ ret = -1;
+ }
+
+ if (ret == JIM_OK && handlerScriptObj == NULL) {
+ msgVarObj = Jim_ListGetIndex(interp, argv[idx + 2], 0);
+ optsVarObj = Jim_ListGetIndex(interp, argv[idx + 2], 1);
+ handlerScriptObj = argv[idx + 3];
+ }
+ idx += 4;
+ break;
+ case TRY_FINALLY:
+ if (idx + 2 != argc) {
+ goto wrongargs;
+ }
+ finallyScriptObj = argv[idx + 1];
+ idx += 2;
+ break;
+ }
+ }
+ }
+ else {
+ if (argc - idx >= 1) {
+ msgVarObj = argv[idx];
+ idx++;
+ if (argc - idx >= 1) {
+ optsVarObj = argv[idx];
+ idx++;
+ }
+ }
+ }
+
if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
+ if (finallyScriptObj) {
+ Jim_EvalObj(interp, finallyScriptObj);
+ }
return exitCode;
}
@@ -18167,43 +19743,75 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
if (interp->signal_set_result) {
interp->signal_set_result(interp, interp->sigmask);
}
- else {
+ else if (!istry) {
Jim_SetResultInt(interp, interp->sigmask);
}
interp->sigmask = 0;
}
- if (argc >= 2) {
- if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) {
- return JIM_ERR;
+ ok = 1;
+ if (msgVarObj && Jim_Length(msgVarObj)) {
+ if (Jim_SetVariable(interp, msgVarObj, Jim_GetResult(interp)) != JIM_OK) {
+ ok = 0;
}
- if (argc == 3) {
- Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0);
-
- Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1));
- Jim_ListAppendElement(interp, optListObj,
- Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode));
- Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1));
- Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel));
- if (exitCode == JIM_ERR) {
- Jim_Obj *errorCode;
- Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo",
- -1));
- Jim_ListAppendElement(interp, optListObj, interp->stackTrace);
-
- errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE);
- if (errorCode) {
- Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1));
- Jim_ListAppendElement(interp, optListObj, errorCode);
- }
- }
- if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) {
- return JIM_ERR;
+ }
+ if (ok && optsVarObj && Jim_Length(optsVarObj)) {
+ Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0);
+
+ Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1));
+ Jim_ListAppendElement(interp, optListObj,
+ Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode));
+ Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1));
+ Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel));
+ if (exitCode == JIM_ERR) {
+ Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo",
+ -1));
+ Jim_ListAppendElement(interp, optListObj, interp->stackTrace);
+
+ if (errorCodeObj) {
+ Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1));
+ Jim_ListAppendElement(interp, optListObj, errorCodeObj);
}
}
+ if (Jim_SetVariable(interp, optsVarObj, optListObj) != JIM_OK) {
+ ok = 0;
+ }
}
- Jim_SetResultInt(interp, exitCode);
- return JIM_OK;
+ if (ok && handlerScriptObj) {
+
+ exitCode = Jim_EvalObj(interp, handlerScriptObj);
+ }
+
+ if (finallyScriptObj) {
+
+ Jim_Obj *prevResultObj = Jim_GetResult(interp);
+ Jim_IncrRefCount(prevResultObj);
+ int ret = Jim_EvalObj(interp, finallyScriptObj);
+ if (ret == JIM_OK) {
+ Jim_SetResult(interp, prevResultObj);
+ }
+ else {
+ exitCode = ret;
+ }
+ Jim_DecrRefCount(interp, prevResultObj);
+ }
+ if (!istry) {
+ Jim_SetResultInt(interp, exitCode);
+ exitCode = JIM_OK;
+ }
+ return exitCode;
+}
+
+
+static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ return JimCatchTryHelper(interp, 0, argc, argv);
+}
+
+
+static int Jim_TryCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ return JimCatchTryHelper(interp, 1, argc, argv);
}
@@ -18215,11 +19823,7 @@ static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_ERR;
}
- if (JimValidName(interp, "new procedure", argv[2])) {
- return JIM_ERR;
- }
-
- return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
+ return Jim_RenameCommand(interp, argv[1], argv[2]);
}
#define JIM_DICTMATCH_KEYS 0x0001
@@ -18227,30 +19831,32 @@ static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types)
{
- Jim_HashEntry *he;
Jim_Obj *listObjPtr;
- Jim_HashTableIterator htiter;
+ Jim_Dict *dict;
+ int i;
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
return JIM_ERR;
}
+ dict = objPtr->internalRep.dictValue;
listObjPtr = Jim_NewListObj(interp, NULL, 0);
- JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter);
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+ for (i = 0; i < dict->len; i += 2 ) {
+ Jim_Obj *keyObj = dict->table[i];
+ Jim_Obj *valObj = dict->table[i + 1];
if (patternObj) {
- Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
- if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
+ Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? keyObj : valObj;
+ if (!Jim_StringMatchObj(interp, patternObj, matchObj, 0)) {
continue;
}
}
if (return_types & JIM_DICTMATCH_KEYS) {
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
+ Jim_ListAppendElement(interp, listObjPtr, keyObj);
}
if (return_types & JIM_DICTMATCH_VALUES) {
- Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
+ Jim_ListAppendElement(interp, listObjPtr, valObj);
}
}
@@ -18263,7 +19869,7 @@ int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
return -1;
}
- return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
+ return objPtr->internalRep.dictValue->len / 2;
}
Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
@@ -18276,18 +19882,17 @@ Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
for (i = 0; i < objc; i++) {
- Jim_HashTable *ht;
- Jim_HashTableIterator htiter;
- Jim_HashEntry *he;
+ Jim_Obj **table;
+ int tablelen;
+ int j;
- if (SetDictFromAny(interp, objv[i]) != JIM_OK) {
+ table = Jim_DictPairs(interp, objv[i], &tablelen);
+ if (tablelen && !table) {
Jim_FreeNewObj(interp, objPtr);
return NULL;
}
- ht = objv[i]->internalRep.ptr;
- JimInitHashTableIterator(ht, &htiter);
- while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
- Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he));
+ for (j = 0; j < tablelen; j += 2) {
+ DictAddElement(interp, objPtr, table[j], table[j + 1]);
}
}
return objPtr;
@@ -18295,50 +19900,19 @@ Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
{
- Jim_HashTable *ht;
- unsigned int i;
char buffer[100];
- int sum = 0;
- int nonzero_count = 0;
Jim_Obj *output;
- int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ Jim_Dict *dict;
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
return JIM_ERR;
}
- ht = (Jim_HashTable *)objPtr->internalRep.ptr;
+ dict = objPtr->internalRep.dictValue;
- snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
+ snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets", dict->len, dict->size);
output = Jim_NewStringObj(interp, buffer, -1);
-
- for (i = 0; i < ht->size; i++) {
- Jim_HashEntry *he = ht->table[i];
- int entries = 0;
- while (he) {
- entries++;
- he = he->next;
- }
- if (entries > 9) {
- bucket_counts[10]++;
- }
- else {
- bucket_counts[entries]++;
- }
- if (entries) {
- sum += entries;
- nonzero_count++;
- }
- }
- for (i = 0; i < 10; i++) {
- snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
- Jim_AppendString(interp, output, buffer, -1);
- }
- snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
- Jim_AppendString(interp, output, buffer, -1);
- snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
- Jim_AppendString(interp, output, buffer, -1);
Jim_SetResult(interp, output);
return JIM_OK;
}
@@ -18368,12 +19942,12 @@ static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const
return JIM_ERR;
}
- if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) {
+ dictValues = Jim_DictPairs(interp, objPtr, &len);
+ if (len && dictValues == NULL) {
return JIM_ERR;
}
for (i = 0; i < len; i += 2) {
if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) {
- Jim_Free(dictValues);
return JIM_ERR;
}
}
@@ -18392,16 +19966,17 @@ static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const
for (i = 0; i < len; i += 2) {
- objPtr = Jim_GetVariable(interp, dictValues[i], 0);
- newkeyv[keyc] = dictValues[i];
- Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0);
+ if (Jim_StringCompareObj(interp, dictVarName, dictValues[i], 0) != 0) {
+
+ objPtr = Jim_GetVariable(interp, dictValues[i], 0);
+ newkeyv[keyc] = dictValues[i];
+ Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, JIM_NORESULT);
+ }
}
Jim_Free(newkeyv);
}
}
- Jim_Free(dictValues);
-
return ret;
}
@@ -18410,34 +19985,65 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
{
Jim_Obj *objPtr;
int types = JIM_DICTMATCH_KEYS;
- int option;
- static const char * const options[] = {
- "create", "get", "set", "unset", "exists", "keys", "size", "info",
- "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
- "replace", "update", NULL
+
+ enum {
+ OPT_CREATE,
+ OPT_GET,
+ OPT_GETDEF,
+ OPT_GETWITHDEFAULT,
+ OPT_SET,
+ OPT_UNSET,
+ OPT_EXISTS,
+ OPT_KEYS,
+ OPT_SIZE,
+ OPT_INFO,
+ OPT_MERGE,
+ OPT_WITH,
+ OPT_APPEND,
+ OPT_LAPPEND,
+ OPT_INCR,
+ OPT_REMOVE,
+ OPT_VALUES,
+ OPT_FOR,
+ OPT_REPLACE,
+ OPT_UPDATE,
+ OPT_COUNT
};
- enum
- {
- OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
- OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
- OPT_REPLACE, OPT_UPDATE,
+ static const jim_subcmd_type cmds[OPT_COUNT + 1] = {
+ JIM_DEF_SUBCMD("create", "?key value ...?", 0, -2),
+ JIM_DEF_SUBCMD("get", "dictionary ?key ...?", 1, -1),
+ JIM_DEF_SUBCMD_HIDDEN("getdef", "dictionary ?key ...? key default", 3, -1),
+ JIM_DEF_SUBCMD("getwithdefault", "dictionary ?key ...? key default", 3, -1),
+ JIM_DEF_SUBCMD("set", "varName key ?key ...? value", 3, -1),
+ JIM_DEF_SUBCMD("unset", "varName key ?key ...?", 2, -1),
+ JIM_DEF_SUBCMD("exists", "dictionary key ?key ...?", 2, -1),
+ JIM_DEF_SUBCMD("keys", "dictionary ?pattern?", 1, 2),
+ JIM_DEF_SUBCMD("size", "dictionary", 1, 1),
+ JIM_DEF_SUBCMD("info", "dictionary", 1, 1),
+ JIM_DEF_SUBCMD("merge", "?...?", 0, -1),
+ JIM_DEF_SUBCMD("with", "dictVar ?key ...? script", 2, -1),
+ JIM_DEF_SUBCMD("append", "varName key ?value ...?", 2, -1),
+ JIM_DEF_SUBCMD("lappend", "varName key ?value ...?", 2, -1),
+ JIM_DEF_SUBCMD("incr", "varName key ?increment?", 2, 3),
+ JIM_DEF_SUBCMD("remove", "dictionary ?key ...?", 1, -1),
+ JIM_DEF_SUBCMD("values", "dictionary ?pattern?", 1, 2),
+ JIM_DEF_SUBCMD("for", "vars dictionary script", 3, 3),
+ JIM_DEF_SUBCMD("replace", "dictionary ?key value ...?", 1, -1),
+ JIM_DEF_SUBCMD("update", "varName ?arg ...? script", 2, -1),
+ { }
};
-
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
+ const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
+ if (!ct) {
return JIM_ERR;
}
+ if (ct->function) {
- if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
- return Jim_CheckShowCommands(interp, argv[1], options);
+ return ct->function(interp, argc, argv);
}
- switch (option) {
+
+ switch (ct - cmds) {
case OPT_GET:
- if (argc < 3) {
- Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
- return JIM_ERR;
- }
if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
JIM_ERRMSG) != JIM_OK) {
return JIM_ERR;
@@ -18445,20 +20051,27 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResult(interp, objPtr);
return JIM_OK;
- case OPT_SET:
- if (argc < 5) {
- Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
- return JIM_ERR;
- }
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
+ case OPT_GETDEF:
+ case OPT_GETWITHDEFAULT:{
+ int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 4, &objPtr, JIM_ERRMSG);
+ if (rc == -1) {
- case OPT_EXISTS:
- if (argc < 4) {
- Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
return JIM_ERR;
}
+ if (rc == JIM_ERR) {
+ Jim_SetResult(interp, argv[argc - 1]);
+ }
else {
- int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
+ Jim_SetResult(interp, objPtr);
+ }
+ return JIM_OK;
+ }
+
+ case OPT_SET:
+ return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
+
+ case OPT_EXISTS:{
+ int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_NONE);
if (rc < 0) {
return JIM_ERR;
}
@@ -18467,11 +20080,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
case OPT_UNSET:
- if (argc < 4) {
- Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
- return JIM_ERR;
- }
- if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
+ if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE) != JIM_OK) {
return JIM_ERR;
}
return JIM_OK;
@@ -18480,18 +20089,10 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
types = JIM_DICTMATCH_VALUES;
case OPT_KEYS:
- if (argc != 3 && argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
- return JIM_ERR;
- }
return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types);
case OPT_SIZE:
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "dictionary");
- return JIM_ERR;
- }
- else if (Jim_DictSize(interp, argv[2]) < 0) {
+ if (Jim_DictSize(interp, argv[2]) < 0) {
return JIM_ERR;
}
Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
@@ -18508,38 +20109,26 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResult(interp, objPtr);
return JIM_OK;
- case OPT_UPDATE:
- if (argc < 6 || argc % 2) {
-
- argc = 2;
- }
- break;
-
case OPT_CREATE:
- if (argc % 2) {
- Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
- return JIM_ERR;
- }
objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
Jim_SetResult(interp, objPtr);
return JIM_OK;
case OPT_INFO:
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "dictionary");
- return JIM_ERR;
- }
return Jim_DictInfo(interp, argv[2]);
case OPT_WITH:
- if (argc < 4) {
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
- return JIM_ERR;
- }
return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]);
- }
- return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
+ case OPT_UPDATE:
+ if (argc < 6 || argc % 2) {
+
+ argc = 2;
+ }
+
+ default:
+ return Jim_EvalEnsemble(interp, "dict", Jim_String(argv[1]), argc - 2, argv + 2);
+ }
}
@@ -18584,26 +20173,75 @@ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
+#ifdef jim_ext_namespace
+static int JimIsGlobalNamespace(Jim_Obj *objPtr)
+{
+ int len;
+ const char *str = Jim_GetString(objPtr, &len);
+ return len >= 2 && str[0] == ':' && str[1] == ':';
+}
+#endif
+
static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- int cmd;
Jim_Obj *objPtr;
int mode = 0;
- static const char * const commands[] = {
- "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals",
- "vars", "version", "patchlevel", "complete", "args", "hostname",
- "script", "source", "stacktrace", "nameofexecutable", "returncodes",
- "references", "alias", NULL
+
+ enum {
+ INFO_ALIAS,
+ INFO_ARGS,
+ INFO_BODY,
+ INFO_CHANNELS,
+ INFO_COMMANDS,
+ INFO_COMPLETE,
+ INFO_EXISTS,
+ INFO_FRAME,
+ INFO_GLOBALS,
+ INFO_HOSTNAME,
+ INFO_LEVEL,
+ INFO_LOCALS,
+ INFO_NAMEOFEXECUTABLE,
+ INFO_PATCHLEVEL,
+ INFO_PROCS,
+ INFO_REFERENCES,
+ INFO_RETURNCODES,
+ INFO_SCRIPT,
+ INFO_SOURCE,
+ INFO_STACKTRACE,
+ INFO_STATICS,
+ INFO_VARS,
+ INFO_VERSION,
+ INFO_COUNT
};
- enum
- { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
- INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
- INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
- INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
+ static const jim_subcmd_type cmds[INFO_COUNT + 1] = {
+ JIM_DEF_SUBCMD("alias", "command", 1, 1),
+ JIM_DEF_SUBCMD("args", "procname", 1, 1),
+ JIM_DEF_SUBCMD("body", "procname", 1, 1),
+ JIM_DEF_SUBCMD("channels", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("commands", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("complete", "script ?missing?", 1, 2),
+ JIM_DEF_SUBCMD("exists", "varName", 1, 1),
+ JIM_DEF_SUBCMD("frame", "?levelNum?", 0, 1),
+ JIM_DEF_SUBCMD("globals", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("hostname", NULL, 0, 0),
+ JIM_DEF_SUBCMD("level", "?levelNum?", 0, 1),
+ JIM_DEF_SUBCMD("locals", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("nameofexecutable", NULL, 0, 0),
+ JIM_DEF_SUBCMD("patchlevel", NULL, 0, 0),
+ JIM_DEF_SUBCMD("procs", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("references", NULL, 0, 0),
+ JIM_DEF_SUBCMD("returncodes", "?code?", 0, 1),
+ JIM_DEF_SUBCMD("script", "?filename?", 0, 1),
+ JIM_DEF_SUBCMD("source", "source ?filename line?", 1, 3),
+ JIM_DEF_SUBCMD("stacktrace", NULL, 0, 0),
+ JIM_DEF_SUBCMD("statics", "procname", 1, 1),
+ JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("version", NULL, 0, 0),
+ { }
};
-
+ const jim_subcmd_type *ct;
#ifdef jim_ext_namespace
int nons = 0;
@@ -18614,32 +20252,25 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
nons = 1;
}
#endif
-
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
+ ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
+ if (!ct) {
return JIM_ERR;
}
- if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
- return Jim_CheckShowCommands(interp, argv[1], commands);
+ if (ct->function) {
+
+ return ct->function(interp, argc, argv);
}
+ int option = ct - cmds;
- switch (cmd) {
+ switch (option) {
case INFO_EXISTS:
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "varName");
- return JIM_ERR;
- }
Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL);
- break;
+ return JIM_OK;
case INFO_ALIAS:{
Jim_Cmd *cmdPtr;
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "command");
- return JIM_ERR;
- }
if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
return JIM_ERR;
}
@@ -18663,19 +20294,15 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
case INFO_COMMANDS:
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
- return JIM_ERR;
- }
#ifdef jim_ext_namespace
if (!nons) {
- if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+ if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) {
return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
}
}
#endif
Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
- break;
+ return JIM_OK;
case INFO_VARS:
mode++;
@@ -18685,35 +20312,32 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
case INFO_GLOBALS:
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
- return JIM_ERR;
- }
#ifdef jim_ext_namespace
if (!nons) {
- if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+ if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) {
return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
}
}
#endif
Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode));
- break;
+ return JIM_OK;
case INFO_SCRIPT:
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
- return JIM_ERR;
+ if (argc == 3) {
+ Jim_IncrRefCount(argv[2]);
+ Jim_DecrRefCount(interp, interp->currentFilenameObj);
+ interp->currentFilenameObj = argv[2];
}
- Jim_SetResult(interp, JimGetScript(interp, interp->currentScriptObj)->fileNameObj);
- break;
+ Jim_SetResult(interp, interp->currentFilenameObj);
+ return JIM_OK;
case INFO_SOURCE:{
jim_wide line;
Jim_Obj *resObjPtr;
Jim_Obj *fileNameObj;
- if (argc != 3 && argc != 5) {
- Jim_WrongNumArgs(interp, 2, argv, "source ?filename line?");
+ if (argc == 4) {
+ Jim_SubCmdArgError(interp, ct, argv[0]);
return JIM_ERR;
}
if (argc == 5) {
@@ -18742,42 +20366,42 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line));
}
Jim_SetResult(interp, resObjPtr);
- break;
+ return JIM_OK;
}
case INFO_STACKTRACE:
Jim_SetResult(interp, interp->stackTrace);
- break;
+ return JIM_OK;
case INFO_LEVEL:
- case INFO_FRAME:
- switch (argc) {
- case 2:
- Jim_SetResultInt(interp, interp->framePtr->level);
- break;
-
- case 3:
- if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) {
- return JIM_ERR;
- }
- Jim_SetResult(interp, objPtr);
- break;
+ if (argc == 2) {
+ Jim_SetResultInt(interp, interp->framePtr->level);
+ }
+ else {
+ if (JimInfoLevel(interp, argv[2], &objPtr) != JIM_OK) {
+ return JIM_ERR;
+ }
+ Jim_SetResult(interp, objPtr);
+ }
+ return JIM_OK;
- default:
- Jim_WrongNumArgs(interp, 2, argv, "?levelNum?");
+ case INFO_FRAME:
+ if (argc == 2) {
+ Jim_SetResultInt(interp, interp->procLevel + 1);
+ }
+ else {
+ if (JimInfoFrame(interp, argv[2], &objPtr) != JIM_OK) {
return JIM_ERR;
+ }
+ Jim_SetResult(interp, objPtr);
}
- break;
+ return JIM_OK;
case INFO_BODY:
case INFO_STATICS:
case INFO_ARGS:{
Jim_Cmd *cmdPtr;
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "procname");
- return JIM_ERR;
- }
if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
return JIM_ERR;
}
@@ -18785,13 +20409,19 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]);
return JIM_ERR;
}
- switch (cmd) {
+ switch (option) {
+#ifdef JIM_NO_INTROSPECTION
+ default:
+ Jim_SetResultString(interp, "unsupported", -1);
+ return JIM_ERR;
+#else
case INFO_BODY:
Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr);
break;
case INFO_ARGS:
Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
break;
+#endif
case INFO_STATICS:
if (cmdPtr->u.proc.staticVars) {
Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
@@ -18799,7 +20429,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
break;
}
- break;
+ return JIM_OK;
}
case INFO_VERSION:
@@ -18808,23 +20438,18 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100);
Jim_SetResultString(interp, buf, -1);
- break;
+ return JIM_OK;
}
- case INFO_COMPLETE:
- if (argc != 3 && argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "script ?missing?");
- return JIM_ERR;
- }
- else {
+ case INFO_COMPLETE: {
char missing;
Jim_SetResultBool(interp, Jim_ScriptIsComplete(interp, argv[2], &missing));
if (missing != ' ' && argc == 4) {
Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1));
}
+ return JIM_OK;
}
- break;
case INFO_HOSTNAME:
@@ -18862,11 +20487,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResultString(interp, name, -1);
}
}
- else {
- Jim_WrongNumArgs(interp, 2, argv, "?code?");
- return JIM_ERR;
- }
- break;
+ return JIM_OK;
case INFO_REFERENCES:
#ifdef JIM_REFERENCES
return JimInfoReferences(interp, argc, argv);
@@ -18874,8 +20495,9 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResultString(interp, "not supported", -1);
return JIM_ERR;
#endif
+ default:
+ abort();
}
- return JIM_OK;
}
@@ -19147,7 +20769,6 @@ static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
JimSetStackTrace(interp, argv[2]);
return JIM_ERR;
}
- interp->addStackTrace++;
return JIM_ERR;
}
@@ -19170,22 +20791,23 @@ static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
- long count;
+ jim_wide count;
- if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) {
+ if (argc < 2 || Jim_GetWideExpr(interp, argv[1], &count) != JIM_OK || count < 0) {
Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?");
return JIM_ERR;
}
-
if (count == 0 || argc == 2) {
+ Jim_SetEmptyResult(interp);
return JIM_OK;
}
argc -= 2;
argv += 2;
- objPtr = Jim_NewListObj(interp, argv, argc);
- while (--count) {
+ objPtr = Jim_NewListObj(interp, NULL, 0);
+ ListEnsureLength(objPtr, argc * count);
+ while (count--) {
ListInsertElements(objPtr, -1, argc, argv);
}
@@ -19245,7 +20867,7 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
return JIM_OK;
}
- if (argc < 2) {
+ if (argc > 3) {
Jim_WrongNumArgs(interp, 1, argv, "varName ?default?");
return JIM_ERR;
}
@@ -19288,8 +20910,9 @@ static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_ERR;
}
JimListGetElements(interp, argv[1], &len, &ele);
- len--;
revObjPtr = Jim_NewListObj(interp, NULL, 0);
+ ListEnsureLength(revObjPtr, len);
+ len--;
while (len >= 0)
ListAppendElement(revObjPtr, ele[len--]);
Jim_SetResult(interp, revObjPtr);
@@ -19331,14 +20954,14 @@ static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
if (argc == 2) {
- if (Jim_GetWide(interp, argv[1], &end) != JIM_OK)
+ if (Jim_GetWideExpr(interp, argv[1], &end) != JIM_OK)
return JIM_ERR;
}
else {
- if (Jim_GetWide(interp, argv[1], &start) != JIM_OK ||
- Jim_GetWide(interp, argv[2], &end) != JIM_OK)
+ if (Jim_GetWideExpr(interp, argv[1], &start) != JIM_OK ||
+ Jim_GetWideExpr(interp, argv[2], &end) != JIM_OK)
return JIM_ERR;
- if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK)
+ if (argc == 4 && Jim_GetWideExpr(interp, argv[3], &step) != JIM_OK)
return JIM_ERR;
}
if ((len = JimRangeLen(start, end, step)) == -1) {
@@ -19346,6 +20969,7 @@ static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
objPtr = Jim_NewListObj(interp, NULL, 0);
+ ListEnsureLength(objPtr, len);
for (i = 0; i < len; i++)
ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step));
Jim_SetResult(interp, objPtr);
@@ -19364,11 +20988,11 @@ static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
if (argc == 1) {
max = JIM_WIDE_MAX;
} else if (argc == 2) {
- if (Jim_GetWide(interp, argv[1], &max) != JIM_OK)
+ if (Jim_GetWideExpr(interp, argv[1], &max) != JIM_OK)
return JIM_ERR;
} else if (argc == 3) {
- if (Jim_GetWide(interp, argv[1], &min) != JIM_OK ||
- Jim_GetWide(interp, argv[2], &max) != JIM_OK)
+ if (Jim_GetWideExpr(interp, argv[1], &min) != JIM_OK ||
+ Jim_GetWideExpr(interp, argv[2], &max) != JIM_OK)
return JIM_ERR;
}
len = max-min;
@@ -19419,21 +21043,23 @@ static const struct {
{"lreplace", Jim_LreplaceCoreCommand},
{"lsort", Jim_LsortCoreCommand},
{"append", Jim_AppendCoreCommand},
- {"debug", Jim_DebugCoreCommand},
{"eval", Jim_EvalCoreCommand},
{"uplevel", Jim_UplevelCoreCommand},
{"expr", Jim_ExprCoreCommand},
{"break", Jim_BreakCoreCommand},
{"continue", Jim_ContinueCoreCommand},
{"proc", Jim_ProcCoreCommand},
+ {"xtrace", Jim_XtraceCoreCommand},
{"concat", Jim_ConcatCoreCommand},
{"return", Jim_ReturnCoreCommand},
{"upvar", Jim_UpvarCoreCommand},
{"global", Jim_GlobalCoreCommand},
{"string", Jim_StringCoreCommand},
{"time", Jim_TimeCoreCommand},
+ {"timerate", Jim_TimeRateCoreCommand},
{"exit", Jim_ExitCoreCommand},
{"catch", Jim_CatchCoreCommand},
+ {"try", Jim_TryCoreCommand},
#ifdef JIM_REFERENCES
{"ref", Jim_RefCoreCommand},
{"getref", Jim_GetrefCoreCommand},
@@ -19462,6 +21088,7 @@ static const struct {
{"local", Jim_LocalCoreCommand},
{"upcall", Jim_UpcallCoreCommand},
{"apply", Jim_ApplyCoreCommand},
+ {"stacktrace", Jim_StacktraceCoreCommand},
{NULL, NULL},
};
@@ -19689,6 +21316,15 @@ void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
}
}
+int Jim_CheckAbiVersion(Jim_Interp *interp, int abi_version)
+{
+ if (abi_version != JIM_ABI_VERSION) {
+ Jim_SetResultString(interp, "ABI version mismatch", -1);
+ return JIM_ERR;
+ }
+ return JIM_OK;
+}
+
#ifndef jim_ext_package
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
@@ -19697,10 +21333,9 @@ int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, in
}
#endif
#ifndef jim_ext_aio
-FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj)
+int Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj)
{
- Jim_SetResultString(interp, "aio not enabled", -1);
- return NULL;
+ return -1;
}
#endif
@@ -19719,30 +21354,41 @@ static const jim_subcmd_type dummy_subcmd = {
"dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
};
-static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep)
+static Jim_Obj *subcmd_cmd_list(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep)
{
- const char *s = "";
+
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_Obj *sortCmd[2];
for (; ct->cmd; ct++) {
if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
- Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL);
- s = sep;
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, ct->cmd, -1));
}
}
+
+
+ sortCmd[0] = Jim_NewStringObj(interp, "lsort", -1);
+ sortCmd[1] = listObj;
+
+ if (Jim_EvalObjVector(interp, 2, sortCmd) == JIM_OK) {
+ return Jim_ListJoin(interp, Jim_GetResult(interp), sep, strlen(sep));
+ }
+
+ return Jim_GetResult(interp);
}
static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
Jim_Obj *cmd, Jim_Obj *subcmd)
{
- Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd);
- add_commands(interp, command_table, ", ");
+ Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be %#s", cmd, type,
+ subcmd, subcmd_cmd_list(interp, command_table, ", "));
}
static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
Jim_Obj *const *argv)
{
- Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]);
- add_commands(interp, command_table, ", ");
+ Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: %#s",
+ argv[0], subcmd_cmd_list(interp, command_table, ", "));
}
static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
@@ -19756,10 +21402,10 @@ static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Ob
}
}
-static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd)
+void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *subcmd)
{
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
- add_cmd_usage(interp, command_table, subcmd);
+ add_cmd_usage(interp, ct, subcmd);
Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
}
@@ -19780,6 +21426,7 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
Jim_Obj *cmd;
const char *cmdstr;
int help = 0;
+ int argsok = 1;
if (argc < 2) {
Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n"
@@ -19812,9 +21459,7 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
-
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- add_commands(interp, command_table, " ");
+ Jim_SetResult(interp, subcmd_cmd_list(interp, command_table, " "));
return &dummy_subcmd;
}
@@ -19872,7 +21517,18 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
found:
- if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
+
+ if (argc - 2 < ct->minargs) {
+ argsok = 0;
+ }
+ else if (ct->maxargs >= 0 && argc - 2 > ct->maxargs) {
+ argsok = 0;
+ }
+ else if (ct->maxargs < -1 && (argc - 2) % -ct->maxargs != 0) {
+
+ argsok = 0;
+ }
+ if (!argsok) {
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
add_cmd_usage(interp, ct, argv[0]);
@@ -19897,7 +21553,7 @@ int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim
ret = ct->function(interp, argc - 2, argv + 2);
}
if (ret < 0) {
- set_wrong_args(interp, ct, argv[0]);
+ Jim_SubCmdArgError(interp, ct, argv[0]);
ret = JIM_ERR;
}
}
@@ -19948,6 +21604,7 @@ int utf8_fromunicode(char *p, unsigned uc)
#include <ctype.h>
#include <string.h>
+#include <stdio.h>
#define JIM_INTEGER_SPACE 24
@@ -20194,7 +21851,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
j = 0;
for (i = length; i > 0; ) {
i--;
- if (w & ((unsigned jim_wide)1 << i)) {
+ if (w & ((unsigned jim_wide)1 << i)) {
num_buffer[j++] = '1';
}
else if (j || i == 0) {
@@ -20430,7 +22087,7 @@ static int str_int_len(const int *seq)
return n;
}
-int regcomp(regex_t *preg, const char *exp, int cflags)
+int jim_regcomp(regex_t *preg, const char *exp, int cflags)
{
int scan;
int longest;
@@ -20845,7 +22502,7 @@ static int regatom(regex_t *preg, int *flagp)
pattern++;
}
- while (*pattern && *pattern != ']') {
+ while (*pattern != ']') {
int start;
int end;
@@ -20857,6 +22514,11 @@ static int regatom(regex_t *preg, int *flagp)
};
int cc;
+ if (!*pattern) {
+ preg->err = REG_ERR_UNMATCHED_BRACKET;
+ return 0;
+ }
+
pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
if (start == '\\') {
@@ -20880,6 +22542,10 @@ static int regatom(regex_t *preg, int *flagp)
preg->err = REG_ERR_NULL_CHAR;
return 0;
}
+ if (start == '\\' && *pattern == 0) {
+ preg->err = REG_ERR_INVALID_ESCAPE;
+ return 0;
+ }
}
if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
@@ -20891,6 +22557,10 @@ static int regatom(regex_t *preg, int *flagp)
preg->err = REG_ERR_NULL_CHAR;
return 0;
}
+ if (end == '\\' && *pattern == 0) {
+ preg->err = REG_ERR_INVALID_ESCAPE;
+ return 0;
+ }
}
reg_addrange(preg, start, end);
@@ -20905,6 +22575,10 @@ static int regatom(regex_t *preg, int *flagp)
for (cc = 0; cc < CC_NUM; cc++) {
n = strlen(character_class[cc]);
if (strncmp(pattern, character_class[cc], n) == 0) {
+ if (pattern[n] != ']') {
+ preg->err = REG_ERR_UNMATCHED_BRACKET;
+ return 0;
+ }
pattern += n + 1;
break;
@@ -20995,7 +22669,7 @@ cc_switch:
ch = *preg->regparse++;
switch (ch) {
case '\0':
- preg->err = REG_ERR_TRAILING_BACKSLASH;
+ preg->err = REG_ERR_INVALID_ESCAPE;
return 0;
case 'A':
ret = regnode(preg, BOLX);
@@ -21182,7 +22856,7 @@ static int regtry(regex_t *preg, const char *string );
static int regmatch(regex_t *preg, int prog);
static int regrepeat(regex_t *preg, int p, int max);
-int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
+int jim_regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
{
const char *s;
int scan;
@@ -21523,7 +23197,7 @@ static int regmatch(regex_t *preg, int prog)
if (preg->reginput > preg->regbol) {
- if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
+ if (reg_iseol(preg, c) || !(isalnum(UCHAR(c)) || c == '_')) {
c = preg->reginput[-1];
if (isalnum(UCHAR(c)) || c == '_') {
@@ -21619,6 +23293,8 @@ static int regmatch(regex_t *preg, int prog)
}
return(1);
}
+
+ preg->reginput = save;
return(0);
}
return REG_ERR_INTERNAL;
@@ -21642,10 +23318,9 @@ static int regrepeat(regex_t *preg, int p, int max)
opnd = OPERAND(p);
switch (OP(preg, p)) {
case ANY:
-
while (!reg_iseol(preg, *scan) && count < max) {
count++;
- scan++;
+ scan += utf8_charlen(*scan);
}
break;
case EXACTLY:
@@ -21726,7 +23401,7 @@ static int regopsize(regex_t *preg, int p )
}
-size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+size_t jim_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
{
static const char *error_strings[] = {
"success",
@@ -21745,9 +23420,10 @@ size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_s
"nested count",
"internal error",
"count follows nothing",
- "trailing backslash",
+ "invalid escape \\ sequence",
"corrupted program",
"contains null char",
+ "brackets [] not balanced",
};
const char *err;
@@ -21761,7 +23437,7 @@ size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_s
return snprintf(errbuf, errbuf_size, "%s", err);
}
-void regfree(regex_t *preg)
+void jim_regfree(regex_t *preg)
{
free(preg->program);
}
@@ -21858,16 +23534,42 @@ int Jim_Errno(void)
return EINVAL;
}
-pidtype waitpid(pidtype pid, int *status, int nohang)
+long JimProcessPid(phandle_t pid)
{
- DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
+ if (pid == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+ return GetProcessId(pid);
+}
+
+phandle_t JimWaitPid(long pid, int *status, int nohang)
+{
+ if (pid > 0) {
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid);
+ if (h) {
+ long pid = waitpid(h, status, nohang);
+ CloseHandle(h);
+ if (pid > 0) {
+ return h;
+ }
+ }
+ }
+ return JIM_BAD_PHANDLE;
+}
+
+long waitpid(phandle_t phandle, int *status, int nohang)
+{
+ long pid;
+ DWORD ret = WaitForSingleObject(phandle, nohang ? 0 : INFINITE);
if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
- return JIM_BAD_PID;
+ return -1;
}
- GetExitCodeProcess(pid, &ret);
+ GetExitCodeProcess(phandle, &ret);
*status = ret;
- CloseHandle(pid);
+
+ pid = GetProcessId(phandle);
+ CloseHandle(phandle);
return pid;
}
@@ -21889,7 +23591,7 @@ int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unli
}
Jim_SetResultString(interp, name, -1);
- return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT);
+ return _open_osfhandle((intptr_t)handle, _O_RDWR | _O_TEXT);
error:
Jim_SetResultErrno(interp, name);
@@ -22127,6 +23829,7 @@ const char *Jim_SignalId(int sig)
#ifndef JIM_BOOTSTRAP_LIB_ONLY
#include <errno.h>
#include <string.h>
+#include <stdio.h>
#ifdef USE_LINENOISE
@@ -22142,20 +23845,34 @@ const char *Jim_SignalId(int sig)
#endif
#ifdef USE_LINENOISE
+struct JimCompletionInfo {
+ Jim_Interp *interp;
+ Jim_Obj *completion_command;
+ Jim_Obj *hints_command;
+
+};
+
+static struct JimCompletionInfo *JimGetCompletionInfo(Jim_Interp *interp);
static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata);
static const char completion_callback_assoc_key[] = "interactive-completion";
+static char *JimHintsCallback(const char *prefix, int *color, int *bold, void *userdata);
+static void JimFreeHintsCallback(void *hint, void *userdata);
#endif
char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt)
{
#ifdef USE_LINENOISE
- struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key);
+ struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp);
char *result;
Jim_Obj *objPtr;
long mlmode = 0;
- if (compinfo) {
+ if (compinfo->completion_command) {
linenoiseSetCompletionCallback(JimCompletionCallback, compinfo);
}
+ if (compinfo->hints_command) {
+ linenoiseSetHintsCallback(JimHintsCallback, compinfo);
+ linenoiseSetFreeHintsCallback(JimFreeHintsCallback);
+ }
objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE);
if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) {
linenoiseSetMultiLine(mlmode);
@@ -22164,16 +23881,18 @@ char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt)
result = linenoise(prompt);
linenoiseSetCompletionCallback(NULL, NULL);
+ linenoiseSetHintsCallback(NULL, NULL);
+ linenoiseSetFreeHintsCallback(NULL);
return result;
#else
int len;
- char *line = malloc(MAX_LINE_LEN);
+ char *line = Jim_Alloc(MAX_LINE_LEN);
fputs(prompt, stdout);
fflush(stdout);
if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
- free(line);
+ Jim_Free(line);
return NULL;
}
len = strlen(line);
@@ -22226,19 +23945,29 @@ void Jim_HistoryShow(void)
#endif
}
+void Jim_HistorySetMaxLen(int length)
+{
#ifdef USE_LINENOISE
-struct JimCompletionInfo {
- Jim_Interp *interp;
- Jim_Obj *command;
-};
+ linenoiseHistorySetMaxLen(length);
+#endif
+}
+
+int Jim_HistoryGetMaxLen(void)
+{
+#ifdef USE_LINENOISE
+ return linenoiseHistoryGetMaxLen();
+#endif
+ return 0;
+}
+#ifdef USE_LINENOISE
static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata)
{
struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
Jim_Obj *objv[2];
int ret;
- objv[0] = info->command;
+ objv[0] = info->completion_command;
objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
ret = Jim_EvalObjVector(info->interp, 2, objv);
@@ -22254,33 +23983,101 @@ static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp
}
}
+static char *JimHintsCallback(const char *prefix, int *color, int *bold, void *userdata)
+{
+ struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata;
+ Jim_Obj *objv[2];
+ int ret;
+ char *result = NULL;
+
+ objv[0] = info->hints_command;
+ objv[1] = Jim_NewStringObj(info->interp, prefix, -1);
+
+ ret = Jim_EvalObjVector(info->interp, 2, objv);
+
+
+ if (ret == JIM_OK) {
+ Jim_Obj *listObj = Jim_GetResult(info->interp);
+ Jim_IncrRefCount(listObj);
+
+ int len = Jim_ListLength(info->interp, listObj);
+ if (len >= 1) {
+ long x;
+ result = Jim_StrDup(Jim_String(Jim_ListGetIndex(info->interp, listObj, 0)));
+ if (len >= 2 && Jim_GetLong(info->interp, Jim_ListGetIndex(info->interp, listObj, 1), &x) == JIM_OK) {
+ *color = x;
+ }
+ if (len >= 3 && Jim_GetLong(info->interp, Jim_ListGetIndex(info->interp, listObj, 2), &x) == JIM_OK) {
+ *bold = x;
+ }
+ }
+ Jim_DecrRefCount(info->interp, listObj);
+ }
+ return result;
+}
+
+static void JimFreeHintsCallback(void *hint, void *userdata)
+{
+ Jim_Free(hint);
+}
+
static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data)
{
struct JimCompletionInfo *compinfo = data;
- Jim_DecrRefCount(interp, compinfo->command);
+ if (compinfo->completion_command) {
+ Jim_DecrRefCount(interp, compinfo->completion_command);
+ }
+ if (compinfo->hints_command) {
+ Jim_DecrRefCount(interp, compinfo->hints_command);
+ }
Jim_Free(compinfo);
}
+
+static struct JimCompletionInfo *JimGetCompletionInfo(Jim_Interp *interp)
+{
+ struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key);
+ if (compinfo == NULL) {
+ compinfo = Jim_Alloc(sizeof(*compinfo));
+ compinfo->interp = interp;
+ compinfo->completion_command = NULL;
+ compinfo->hints_command = NULL;
+ Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo);
+ }
+ return compinfo;
+}
#endif
-void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj)
+void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *completionCommandObj)
{
#ifdef USE_LINENOISE
- if (commandObj) {
+ struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp);
- Jim_IncrRefCount(commandObj);
+ if (completionCommandObj) {
+
+ Jim_IncrRefCount(completionCommandObj);
+ }
+ if (compinfo->completion_command) {
+ Jim_DecrRefCount(interp, compinfo->completion_command);
}
+ compinfo->completion_command = completionCommandObj;
+#endif
+}
- Jim_DeleteAssocData(interp, completion_callback_assoc_key);
+void Jim_HistorySetHints(Jim_Interp *interp, Jim_Obj *hintsCommandObj)
+{
+#ifdef USE_LINENOISE
+ struct JimCompletionInfo *compinfo = JimGetCompletionInfo(interp);
- if (commandObj) {
- struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo));
- compinfo->interp = interp;
- compinfo->command = commandObj;
+ if (hintsCommandObj) {
- Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo);
+ Jim_IncrRefCount(hintsCommandObj);
+ }
+ if (compinfo->hints_command) {
+ Jim_DecrRefCount(interp, compinfo->hints_command);
}
+ compinfo->hints_command = hintsCommandObj;
#endif
}
@@ -22300,6 +24097,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
}
Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1));
+ Jim_HistorySetHints(interp, Jim_NewStringObj(interp, "tcl::stdhint", -1));
#endif
printf("Welcome to Jim version %d.%d\n",
@@ -22346,7 +24144,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
Jim_AppendString(interp, scriptObjPtr, "\n", 1);
}
Jim_AppendString(interp, scriptObjPtr, line, -1);
- free(line);
+ Jim_Free(line);
if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
break;
@@ -22376,7 +24174,10 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
}
result = Jim_GetString(Jim_GetResult(interp), &reslen);
if (reslen) {
- printf("%s\n", result);
+ if (fwrite(result, reslen, 1, stdout) == 0) {
+
+ }
+ putchar('\n');
}
}
out:
@@ -22478,7 +24279,12 @@ int main(int argc, char *const argv[])
JimSetArgv(interp, argc - 3, argv + 3);
retcode = Jim_Eval(interp, argv[2]);
if (retcode != JIM_ERR) {
- printf("%s\n", Jim_String(Jim_GetResult(interp)));
+ int len;
+ const char *msg = Jim_GetString(Jim_GetResult(interp), &len);
+ if (fwrite(msg, len, 1, stdout) == 0) {
+
+ }
+ putchar('\n');
}
}
else {
diff --git a/autosetup/system.tcl b/autosetup/system.tcl
index 739a637..f23781b 100644
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -209,7 +209,12 @@ proc include-file {infile mapping} {
}
}
continue
- } elseif {[regexp {^@include\s+(.*)} $line -> filearg]} {
+ }
+ # Only continue if the stack contains all "true"
+ if {"0" in $condstack} {
+ continue
+ }
+ if {[regexp {^@include\s+(.*)} $line -> filearg]} {
set incfile [string map $mapping $filearg]
if {[file exists $incfile]} {
lappend ::autosetup(deps) [file-normalize $incfile]
@@ -218,12 +223,9 @@ proc include-file {infile mapping} {
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} {
+ if {[regexp {^@define\s+(\w+)\s+(.*)} $line -> var val]} {
+ define $var $val
continue
}
lappend result $line