aboutsummaryrefslogtreecommitdiff
path: root/autosetup/jimsh0.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2011-09-12 15:15:21 +1000
committerSteve Bennett <steveb@workware.net.au>2011-09-12 16:58:56 +1000
commita709491086f168457e728b9d090fcf0ca16ffb75 (patch)
treeb1468b8026bf46afbb09b5dd6cb20e4975409a69 /autosetup/jimsh0.c
parentd9c7cb8ee1548b7b94ca9758ae6501cd9a1e0ee6 (diff)
downloadjimtcl-a709491086f168457e728b9d090fcf0ca16ffb75.zip
jimtcl-a709491086f168457e728b9d090fcf0ca16ffb75.tar.gz
jimtcl-a709491086f168457e728b9d090fcf0ca16ffb75.tar.bz2
Update autosetup to v0.6.3
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'autosetup/jimsh0.c')
-rw-r--r--autosetup/jimsh0.c7700
1 files changed, 2230 insertions, 5470 deletions
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index 738195d..e45a492 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -24,6 +24,8 @@
#define TCL_PLATFORM_PATH_SEPARATOR ";"
#define HAVE_MKDIR_ONE_ARG
#define HAVE_SYSTEM
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
#else
#define TCL_PLATFORM_OS "unknown"
#define TCL_PLATFORM_PLATFORM "unix"
@@ -33,26 +35,13 @@
#endif
#ifndef UTF8_UTIL_H
#define UTF8_UTIL_H
-/**
- * UTF-8 utility functions
- *
- * (c) 2010 Steve Bennett <steveb@workware.net.au>
- *
- * See LICENCE for licence details.
- */
-
-/**
- * Converts the given unicode codepoint (0 - 0xffff) to utf-8
- * and stores the result at 'p'.
- *
- * Returns the number of utf-8 characters (1-3).
- */
+
int utf8_fromunicode(char *p, unsigned short uc);
#ifndef JIM_UTF8
#include <ctype.h>
-/* No utf-8 support. 1 byte = 1 char */
+
#define utf8_strlen(S, B) (B) < 0 ? strlen(S) : (B)
#define utf8_tounicode(S, CP) (*(CP) = *(S), 1)
#define utf8_upper(C) toupper(C)
@@ -61,147 +50,9 @@ int utf8_fromunicode(char *p, unsigned short uc);
#define utf8_charlen(C) 1
#define utf8_prev_len(S, L) 1
-#else
-/**
- * Returns the length of the utf-8 sequence starting with 'c'.
- *
- * Returns 1-4, or -1 if this is not a valid start byte.
- *
- * Note that charlen=4 is not supported by the rest of the API.
- */
-int utf8_charlen(int c);
-
-/**
- * Returns the number of characters in the utf-8
- * string of the given byte length.
- *
- * Any bytes which are not part of an valid utf-8
- * sequence are treated as individual characters.
- *
- * The string *must* be null terminated.
- *
- * Does not support unicode code points > \uffff
- */
-int utf8_strlen(const char *str, int bytelen);
-
-/**
- * Returns the byte index of the given character in the utf-8 string.
- *
- * The string *must* be null terminated.
- *
- * This will return the byte length of a utf-8 string
- * if given the char length.
- */
-int utf8_index(const char *str, int charindex);
-
-/**
- * Returns the unicode codepoint corresponding to the
- * utf-8 sequence 'str'.
- *
- * Stores the result in *uc and returns the number of bytes
- * consumed.
- *
- * If 'str' is null terminated, then an invalid utf-8 sequence
- * at the end of the string will be returned as individual bytes.
- *
- * If it is not null terminated, the length *must* be checked first.
- *
- * Does not support unicode code points > \uffff
- */
-int utf8_tounicode(const char *str, int *uc);
-
-/**
- * Returns the number of bytes before 'str' that the previous
- * utf-8 character sequence starts (which may be the middle of a sequence).
- *
- * Looks back at most 'len' bytes backwards, which must be > 0.
- * If no start char is found, returns -len
- */
-int utf8_prev_len(const char *str, int len);
-
-/**
- * Returns the upper-case variant of the given unicode codepoint.
- *
- * Does not support unicode code points > \uffff
- */
-int utf8_upper(int uc);
-
-/**
- * Returns the lower-case variant of the given unicode codepoint.
- *
- * NOTE: Use utf8_upper() in preference for case-insensitive matching.
- *
- * Does not support unicode code points > \uffff
- */
-int utf8_lower(int uc);
#endif
-#endif
-/* Jim - A small embeddable Tcl interpreter
- *
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
- * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
- * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
- * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- *--- Inline Header File Documentation ---
- * [By Duane Ellis, openocd@duaneellis.com, 8/18/8]
- *
- * Belief is "Jim" would greatly benifit if Jim Internals where
- * documented in some way - form whatever, and perhaps - the package:
- * 'doxygen' is the correct approach to do that.
- *
- * Details, see: http://www.stack.nl/~dimitri/doxygen/
- *
- * To that end please follow these guide lines:
- *
- * (A) Document the PUBLIC api in the .H file.
- *
- * (B) Document JIM Internals, in the .C file.
- *
- * (C) Remember JIM is embedded in other packages, to that end do
- * not assume that your way of documenting is the right way, Jim's
- * public documentation should be agnostic, such that it is some
- * what agreeable with the "package" that is embedding JIM inside
- * of it's own doxygen documentation.
- *
- * (D) Use minimal Doxygen tags.
- *
- * This will be an "ongoing work in progress" for some time.
- **/
-
#ifndef __JIM__H
#define __JIM__H
@@ -211,23 +62,16 @@ extern "C" {
#include <time.h>
#include <limits.h>
-#include <stdio.h> /* for the FILE typedef definition */
-#include <stdlib.h> /* In order to export the Jim_Free() macro */
-#include <stdarg.h> /* In order to get type va_list */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
-/* -----------------------------------------------------------------------------
- * System configuration
- * autoconf (configure) will set these
- * ---------------------------------------------------------------------------*/
#ifndef HAVE_NO_AUTOCONF
#endif
-/* -----------------------------------------------------------------------------
- * Compiler specific fixes.
- * ---------------------------------------------------------------------------*/
-/* Long Long type and related issues */
+
#ifndef jim_wide
# ifdef HAVE_LONG_LONG
# define jim_wide long long
@@ -245,9 +89,6 @@ extern "C" {
# define JIM_WIDE_MAX LONG_MAX
# endif
-/* -----------------------------------------------------------------------------
- * LIBC specific fixes
- * ---------------------------------------------------------------------------*/
# ifdef HAVE_LONG_LONG
# define JIM_WIDE_MODIFIER "lld"
@@ -259,14 +100,8 @@ extern "C" {
#define UCHAR(c) ((unsigned char)(c))
-/* -----------------------------------------------------------------------------
- * Exported defines
- * ---------------------------------------------------------------------------*/
-/* Jim version numbering: every version of jim is marked with a
- * successive integer number. This is version 0. The first
- * stable version will be 1, then 2, 3, and so on. */
-#define JIM_VERSION 71
+#define JIM_VERSION 72
#define JIM_OK 0
#define JIM_ERR 1
@@ -275,38 +110,36 @@ extern "C" {
#define JIM_CONTINUE 4
#define JIM_SIGNAL 5
#define JIM_EXIT 6
-/* The following are internal codes and should never been seen/used */
+
#define JIM_EVAL 7
-#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */
+#define JIM_MAX_NESTING_DEPTH 1000
-/* Some function get an integer argument with flags to change
- * the behaviour. */
-#define JIM_NONE 0 /* no flags set */
-#define JIM_ERRMSG 1 /* set an error message in the interpreter. */
+#define JIM_NONE 0
+#define JIM_ERRMSG 1
-#define JIM_UNSHARED 4 /* Flag to Jim_GetVariable() */
+#define JIM_UNSHARED 4
+
+
+#define JIM_SUBST_NOVAR 1
+#define JIM_SUBST_NOCMD 2
+#define JIM_SUBST_NOESC 4
+#define JIM_SUBST_FLAG 128
-/* Flags for Jim_SubstObj() */
-#define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */
-#define JIM_SUBST_NOCMD 2 /* don't perform command substitutions */
-#define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */
-#define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */
-/* Unused arguments generate annoying warnings... */
#define JIM_NOTUSED(V) ((void) V)
-/* Flags for Jim_GetEnum() */
-#define JIM_ENUM_ABBREV 2 /* Allow unambiguous abbreviation */
-/* Flags used by API calls getting a 'nocase' argument. */
-#define JIM_CASESENS 0 /* case sensitive */
-#define JIM_NOCASE 1 /* no case */
+#define JIM_ENUM_ABBREV 2
+
+
+#define JIM_CASESENS 0
+#define JIM_NOCASE 1
+
-/* Filesystem related */
#define JIM_PATH_LEN 1024
-/* Newline, some embedded system may need -DJIM_CRLF */
+
#ifdef JIM_CRLF
#define JIM_NL "\r\n"
#else
@@ -316,9 +149,6 @@ extern "C" {
#define JIM_LIBPATH "auto_path"
#define JIM_INTERACTIVE "tcl_interactive"
-/* -----------------------------------------------------------------------------
- * Stack
- * ---------------------------------------------------------------------------*/
typedef struct Jim_Stack {
int len;
@@ -326,9 +156,6 @@ typedef struct Jim_Stack {
void **vector;
} Jim_Stack;
-/* -----------------------------------------------------------------------------
- * Hash table
- * ---------------------------------------------------------------------------*/
typedef struct Jim_HashEntry {
const void *key;
@@ -364,10 +191,10 @@ typedef struct Jim_HashTableIterator {
Jim_HashEntry *entry, *nextEntry;
} Jim_HashTableIterator;
-/* This is the initial size of every hash table */
+
#define JIM_HT_INITIAL_SIZE 16
-/* ------------------------------- Macros ------------------------------------*/
+
#define Jim_FreeEntryVal(ht, entry) \
if ((ht)->type->valDestructor) \
(ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
@@ -403,103 +230,87 @@ typedef struct Jim_HashTableIterator {
#define Jim_GetHashTableSize(ht) ((ht)->size)
#define Jim_GetHashTableUsed(ht) ((ht)->used)
-/* -----------------------------------------------------------------------------
- * Jim_Obj structure
- * ---------------------------------------------------------------------------*/
-
-/* -----------------------------------------------------------------------------
- * Jim object. This is mostly the same as Tcl_Obj itself,
- * with the addition of the 'prev' and 'next' pointers.
- * In Jim all the objects are stored into a linked list for GC purposes,
- * so that it's possible to access every object living in a given interpreter
- * sequentially. When an object is freed, it's moved into a different
- * linked list, used as object pool.
- *
- * The refcount of a freed object is always -1.
- * ---------------------------------------------------------------------------*/
+
typedef struct Jim_Obj {
- int refCount; /* reference count */
- char *bytes; /* string representation buffer. NULL = no string repr. */
- int length; /* number of bytes in 'bytes', not including the numterm. */
- const struct Jim_ObjType *typePtr; /* object type. */
- /* Internal representation union */
+ int refCount;
+ char *bytes;
+ int length;
+ const struct Jim_ObjType *typePtr;
+
union {
- /* integer number type */
+
jim_wide wideValue;
- /* hashed object type value */
+
int hashValue;
- /* index type */
+
int indexValue;
- /* return code type */
+
int returnCode;
- /* double number type */
+
double doubleValue;
- /* Generic pointer */
+
void *ptr;
- /* Generic two pointers value */
+
struct {
void *ptr1;
void *ptr2;
} twoPtrValue;
- /* Variable object */
+
struct {
unsigned jim_wide callFrameId;
struct Jim_Var *varPtr;
} varValue;
- /* Command object */
+
struct {
unsigned jim_wide procEpoch;
struct Jim_Cmd *cmdPtr;
} cmdValue;
- /* List object */
+
struct {
- struct Jim_Obj **ele; /* Elements vector */
- int len; /* Length */
- int maxLen; /* Allocated 'ele' length */
+ struct Jim_Obj **ele;
+ int len;
+ int maxLen;
} listValue;
- /* String type */
+
struct {
int maxLength;
- int charLength; /* utf-8 char length. -1 if unknown */
+ int charLength;
} strValue;
- /* Reference type */
+
struct {
jim_wide id;
struct Jim_Reference *refPtr;
} refValue;
- /* Source type */
+
struct {
- const char *fileName;
+ struct Jim_Obj *fileNameObj;
int lineNumber;
} sourceValue;
- /* Dict substitution type */
+
struct {
struct Jim_Obj *varNameObjPtr;
struct Jim_Obj *indexObjPtr;
} dictSubstValue;
- /* tagged binary type */
+
struct {
unsigned char *data;
size_t len;
} binaryValue;
- /* Regular expression pattern */
+
struct {
unsigned flags;
- void *compre; /* really an allocated (regex_t *) */
+ void *compre;
} regexpValue;
struct {
int line;
int argc;
} scriptLineValue;
} internalRep;
- /* This are 8 or 16 bytes more for every object
- * but this is required for efficient garbage collection
- * of Jim references. */
- struct Jim_Obj *prevObjPtr; /* pointer to the prev object. */
- struct Jim_Obj *nextObjPtr; /* pointer to the next object. */
+ struct Jim_Obj *prevObjPtr;
+ struct Jim_Obj *nextObjPtr;
} Jim_Obj;
-/* Jim_Obj related macros */
+
#define Jim_IncrRefCount(objPtr) \
++(objPtr)->refCount
#define Jim_DecrRefCount(interp, objPtr) \
@@ -507,40 +318,20 @@ typedef struct Jim_Obj {
#define Jim_IsShared(objPtr) \
((objPtr)->refCount > 1)
-/* This macro is used when we allocate a new object using
- * Jim_New...Obj(), but for some error we need to destroy it.
- * Instead to use Jim_IncrRefCount() + Jim_DecrRefCount() we
- * can just call Jim_FreeNewObj. To call Jim_Free directly
- * seems too raw, the object handling may change and we want
- * that Jim_FreeNewObj() can be called only against objects
- * that are belived to have refcount == 0. */
#define Jim_FreeNewObj Jim_FreeObj
-/* Free the internal representation of the object. */
+
#define Jim_FreeIntRep(i,o) \
if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \
(o)->typePtr->freeIntRepProc(i, o)
-/* Get the internal representation pointer */
+
#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr
-/* Set the internal representation pointer */
+
#define Jim_SetIntRepPtr(o, p) \
(o)->internalRep.ptr = (p)
-/* The object type structure.
- * There are four methods.
- *
- * - FreeIntRep is used to free the internal representation of the object.
- * Can be NULL if there is nothing to free.
- * - DupIntRep is used to duplicate the internal representation of the object.
- * If NULL, when an object is duplicated, the internalRep union is
- * directly copied from an object to another.
- * Note that it's up to the caller to free the old internal repr of the
- * object before to call the Dup method.
- * - UpdateString is used to create the string from the internal repr.
- * - setFromAny is used to convert the current object into one of this type.
- */
struct Jim_Interp;
@@ -549,121 +340,101 @@ typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp,
typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
-
+
typedef struct Jim_ObjType {
- const char *name; /* The name of the type. */
+ const char *name;
Jim_FreeInternalRepProc *freeIntRepProc;
Jim_DupInternalRepProc *dupIntRepProc;
Jim_UpdateStringProc *updateStringProc;
int flags;
} Jim_ObjType;
-/* Jim_ObjType flags */
-#define JIM_TYPE_NONE 0 /* No flags */
-#define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */
-/* Starting from 1 << 20 flags are reserved for private uses of
- * different calls. This way the same 'flags' argument may be used
- * to pass both global flags and private flags. */
+#define JIM_TYPE_NONE 0
+#define JIM_TYPE_REFERENCES 1
+
#define JIM_PRIV_FLAG_SHIFT 20
-/* -----------------------------------------------------------------------------
- * Call frame, vars, commands structures
- * ---------------------------------------------------------------------------*/
-/* Call frame */
+
typedef struct Jim_CallFrame {
- unsigned jim_wide id; /* Call Frame ID. Used for caching. */
- int level; /* Level of this call frame. 0 = global */
- struct Jim_HashTable vars; /* Where local vars are stored */
- struct Jim_HashTable *staticVars; /* pointer to procedure static vars */
+ unsigned jim_wide id;
+ int level;
+ struct Jim_HashTable vars;
+ struct Jim_HashTable *staticVars;
struct Jim_CallFrame *parentCallFrame;
- Jim_Obj *const *argv; /* object vector of the current procedure call. */
- int argc; /* number of args of the current procedure call. */
- Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */
- Jim_Obj *procBodyObjPtr; /* body object of the running procedure */
+ Jim_Obj *const *argv;
+ int argc;
+ Jim_Obj *procArgsObjPtr;
+ Jim_Obj *procBodyObjPtr;
struct Jim_CallFrame *nextFramePtr;
- const char *filename; /* file and line of caller of this proc (if available) */
+ Jim_Obj *fileNameObj;
int line;
} Jim_CallFrame;
-/* The var structure. It just holds the pointer of the referenced
- * object. If linkFramePtr is not NULL the variable is a link
- * to a variable of name store on objPtr living on the given callframe
- * (this happens when the [global] or [upvar] command is used).
- * The interp in order to always know how to free the Jim_Obj associated
- * with a given variable because In Jim objects memory managment is
- * bound to interpreters. */
typedef struct Jim_Var {
Jim_Obj *objPtr;
struct Jim_CallFrame *linkFramePtr;
} Jim_Var;
-/* The cmd structure. */
+
typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
Jim_Obj *const *argv);
typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
-/* A command is implemented in C if funcPtr is != NULL, otherwise
- * it's a Tcl procedure with the arglist and body represented by the
- * two objects referenced by arglistObjPtr and bodyoObjPtr. */
typedef struct Jim_Cmd {
- int inUse; /* Reference count */
- int isproc; /* Is this a procedure? */
+ int inUse;
+ int isproc;
union {
struct {
- /* native (C) command */
- Jim_CmdProc cmdProc; /* The command implementation */
- Jim_DelCmdProc delProc; /* Called when the command is deleted if != NULL */
- void *privData; /* command-private data available via Jim_CmdPrivData() */
+
+ Jim_CmdProc cmdProc;
+ Jim_DelCmdProc delProc;
+ void *privData;
} native;
struct {
- /* Tcl procedure */
+
Jim_Obj *argListObjPtr;
Jim_Obj *bodyObjPtr;
- Jim_HashTable *staticVars; /* Static vars hash table. NULL if no statics. */
- struct Jim_Cmd *prevCmd; /* Previous command defn if proc created 'local' */
- int argListLen; /* Length of argListObjPtr */
- int reqArity; /* Number of required parameters */
- int optArity; /* Number of optional parameters */
- int argsPos; /* Position of 'args', if specified, or -1 */
- int upcall; /* True if proc is currently in upcall */
+ Jim_HashTable *staticVars;
+ struct Jim_Cmd *prevCmd;
+ int argListLen;
+ int reqArity;
+ int optArity;
+ int argsPos;
+ int upcall;
struct Jim_ProcArg {
- Jim_Obj *nameObjPtr; /* Name of this arg */
- Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */
+ Jim_Obj *nameObjPtr;
+ Jim_Obj *defaultObjPtr;
} *arglist;
} proc;
} u;
} Jim_Cmd;
-/* Pseudo Random Number Generator State structure */
+
typedef struct Jim_PrngState {
unsigned char sbox[256];
unsigned int i, j;
} Jim_PrngState;
-/* -----------------------------------------------------------------------------
- * Jim interpreter structure.
- * Fields similar to the real Tcl interpreter structure have the same names.
- * ---------------------------------------------------------------------------*/
typedef struct Jim_Interp {
- Jim_Obj *result; /* object returned by the last command called. */
- int errorLine; /* Error line where an error occurred. */
- char *errorFileName; /* Error file where an error occurred. */
- int addStackTrace; /* > 0 If a level should be added to the stack trace */
- int maxNestingDepth; /* Used for infinite loop detection. */
- int returnCode; /* Completion code to return on JIM_RETURN. */
- int returnLevel; /* Current level of 'return -level' */
- int exitCode; /* Code to return to the OS on JIM_EXIT. */
- long id; /* Hold unique id for various purposes */
- int signal_level; /* A nesting level of catch -signal */
- jim_wide sigmask; /* Bit mask of caught signals, or 0 if none */
- int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); /* Set a result for the sigmask */
- Jim_CallFrame *framePtr; /* Pointer to the current call frame */
- Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */
- struct Jim_HashTable commands; /* Commands hash table */
+ Jim_Obj *result;
+ int errorLine;
+ Jim_Obj *errorFileNameObj;
+ int addStackTrace;
+ int maxNestingDepth;
+ int returnCode;
+ int returnLevel;
+ int exitCode;
+ long id;
+ int signal_level;
+ jim_wide sigmask;
+ int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask);
+ Jim_CallFrame *framePtr;
+ Jim_CallFrame *topFramePtr;
+ struct Jim_HashTable commands;
unsigned jim_wide procEpoch; /* Incremented every time the result
of procedures names lookup caching
may no longer be valid. */
@@ -671,55 +442,48 @@ typedef struct Jim_Interp {
callframe is created. This id is used for the
'ID' field contained in the Jim_CallFrame
structure. */
- int local; /* If 'local' is in effect, newly defined procs keep a reference to the old defn */
- Jim_Obj *liveList; /* Linked list of all the live objects. */
- Jim_Obj *freeList; /* Linked list of all the unused objects. */
- Jim_Obj *currentScriptObj; /* Script currently in execution. */
- Jim_Obj *emptyObj; /* Shared empty string object. */
- Jim_Obj *trueObj; /* Shared true int object. */
- Jim_Obj *falseObj; /* Shared false int object. */
- unsigned jim_wide referenceNextId; /* Next id for reference. */
- struct Jim_HashTable references; /* References hash table. */
+ int local;
+ Jim_Obj *liveList;
+ Jim_Obj *freeList;
+ Jim_Obj *currentScriptObj;
+ Jim_Obj *emptyObj;
+ Jim_Obj *trueObj;
+ Jim_Obj *falseObj;
+ unsigned jim_wide referenceNextId;
+ struct Jim_HashTable references;
jim_wide lastCollectId; /* reference max Id of the last GC
execution. It's set to -1 while the collection
is running as sentinel to avoid to recursive
calls via the [collect] command inside
finalizers. */
- time_t lastCollectTime; /* unix time of the last GC execution */
- struct Jim_HashTable sharedStrings; /* Shared Strings hash table */
- Jim_Obj *stackTrace; /* Stack trace object. */
- Jim_Obj *errorProc; /* Name of last procedure which returned an error */
- Jim_Obj *unknown; /* Unknown command cache */
- int unknown_called; /* The unknown command has been invoked */
- int errorFlag; /* Set if an error occurred during execution. */
+ time_t lastCollectTime;
+ Jim_Obj *stackTrace;
+ Jim_Obj *errorProc;
+ Jim_Obj *unknown;
+ 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(). */
- struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */
- struct Jim_HashTable assocData; /* per-interp storage for use by packages */
- Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */
- struct Jim_HashTable packages; /* Provided packages hash table */
- Jim_Stack *localProcs; /* procs to be destroyed on end of evaluation */
- Jim_Stack *loadHandles; /* handles of loaded modules [load] */
+ struct Jim_CallFrame *freeFramesList;
+ struct Jim_HashTable assocData;
+ Jim_PrngState *prngState;
+ struct Jim_HashTable packages;
+ Jim_Stack *localProcs;
+ Jim_Stack *loadHandles;
} Jim_Interp;
-/* Currently provided as macro that performs the increment.
- * At some point may be a real function doing more work.
- * The proc epoch is used in order to know when a command lookup
- * cached can no longer considered valid. */
#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))
-/* Note: Using trueObj and falseObj here makes some things slower...*/
+
#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b)
#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj)
#define Jim_GetResult(i) ((i)->result)
#define Jim_CmdPrivData(i) ((i)->cmdPrivData)
#define Jim_String(o) Jim_GetString((o), NULL)
-/* Note that 'o' is expanded only one time inside this macro,
- * so it's safe to use side effects. */
#define Jim_SetResult(i,o) do { \
Jim_Obj *_resultObjPtr_ = (o); \
Jim_IncrRefCount(_resultObjPtr_); \
@@ -727,10 +491,10 @@ typedef struct Jim_Interp {
(i)->result = _resultObjPtr_; \
} while(0)
-/* Use this for filehandles, etc. which need a unique id */
+
#define Jim_GetId(i) (++(i)->id)
-/* Reference structure. The interpreter pointer is held within privdata member in HashTable */
+
#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference
string representation must be fixed length. */
typedef struct Jim_Reference {
@@ -739,56 +503,48 @@ typedef struct Jim_Reference {
char tag[JIM_REFERENCE_TAGLEN+1];
} Jim_Reference;
-/* -----------------------------------------------------------------------------
- * Exported API prototypes.
- * ---------------------------------------------------------------------------*/
-/* Macros that are common for extensions and core. */
+
#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
-/* The core includes real prototypes, extensions instead
- * include a global function pointer for every function exported.
- * Once the extension calls Jim_InitExtension(), the global
- * functon pointers are set to the value of the STUB table
- * contained in the Jim_Interp structure.
- *
- * This makes Jim able to load extensions even if it is statically
- * linked itself, and to load extensions compiled with different
- * versions of Jim (as long as the API is still compatible.) */
-
-/* Macros are common for core and extensions */
+
+
#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
#define JIM_EXPORT
-/* Memory allocation */
+
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 char * Jim_StrDup (const char *s);
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
-/* environment */
+
JIM_EXPORT char **Jim_GetEnviron(void);
JIM_EXPORT void Jim_SetEnviron(char **env);
-/* evaluation */
+
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
-/* in C code, you can do this and get better error messages */
-/* Jim_Eval_Named( interp, "some tcl commands", __FILE__, __LINE__ ); */
-JIM_EXPORT int Jim_Eval_Named(Jim_Interp *interp, const char *script,const char *filename, int lineno);
+
+
+JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script);
+
+#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S))
+
JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script);
JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename);
JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename);
JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr);
JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc,
Jim_Obj *const *objv);
-JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, const char *prefix,
+JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix,
int objc, Jim_Obj *const *objv);
+#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov))
JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr,
Jim_Obj **resObjPtrPtr, int flags);
-/* stack */
+
JIM_EXPORT void Jim_InitStack(Jim_Stack *stack);
JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack);
JIM_EXPORT int Jim_StackLen(Jim_Stack *stack);
@@ -797,7 +553,7 @@ JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack);
JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack);
JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr));
-/* hash table */
+
JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht,
const Jim_HashTableType *type, void *privdata);
JIM_EXPORT int Jim_ExpandHashTable (Jim_HashTable *ht,
@@ -817,7 +573,7 @@ JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator
JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry
(Jim_HashTableIterator *iter);
-/* objects */
+
JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
@@ -829,7 +585,7 @@ JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
int *lenPtr);
JIM_EXPORT int Jim_Length(Jim_Obj *objPtr);
-/* string object */
+
JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp,
const char *s, int len);
JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp,
@@ -858,7 +614,7 @@ JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
Jim_Obj *secondObjPtr, int nocase);
JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr);
-/* reference object */
+
JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp,
Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr);
JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp,
@@ -866,21 +622,21 @@ JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp,
JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr);
JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr);
-/* interpreter */
+
JIM_EXPORT Jim_Interp * Jim_CreateInterp (void);
JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i);
JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp);
JIM_EXPORT const char *Jim_ReturnCode(int code);
JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...);
-/* commands */
+
JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp);
-JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp,
+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_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
+JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
const char *oldName, const char *newName);
JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp,
Jim_Obj *objPtr, int flags);
@@ -906,19 +662,19 @@ JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp,
JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp,
Jim_Obj *nameObjPtr, int flags);
-/* call frame */
+
JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp,
Jim_Obj *levelObjPtr);
-/* garbage collection */
+
JIM_EXPORT int Jim_Collect (Jim_Interp *interp);
JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp);
-/* index object */
+
JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr,
int *indexPtr);
-/* list object */
+
JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp,
Jim_Obj *const *elements, int len);
JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp,
@@ -936,7 +692,7 @@ JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp,
JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc,
Jim_Obj *const *objv);
-/* dict object */
+
JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp,
Jim_Obj *const *elements, int len);
JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr,
@@ -946,7 +702,7 @@ JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp,
Jim_Obj **objPtrPtr, int flags);
JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp,
Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc,
- Jim_Obj *newObjPtr);
+ Jim_Obj *newObjPtr, int flags);
JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
@@ -954,17 +710,17 @@ JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
-/* return code object */
+
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
int *intPtr);
-/* expression object */
+
JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
Jim_Obj *exprObjPtr, int *boolPtr);
-/* integer object */
+
JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
jim_wide *widePtr);
JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
@@ -973,68 +729,61 @@ JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp,
jim_wide wideValue);
-/* double object */
+
JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
double *doublePtr);
JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
double doubleValue);
JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
-/* shared strings */
-JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
+
+JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
const char *str);
JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp,
const char *str);
-/* commands utilities */
+
JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
Jim_Obj *const *argv, const char *msg);
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
const char * const *tablePtr, int *indexPtr, const char *name, int flags);
JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len,
char *stateCharPtr);
-/**
- * Find a matching name in the array of the given length.
- *
- * NULL entries are ignored.
- *
- * Returns the matching index if found, or -1 if not.
- */
JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
-/* package utilities */
+
typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data);
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);
-/* Packages C API */
-/* jim-package.c */
+
+
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);
-/* error messages */
+
JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp);
-/* interactive mode */
+
JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
-/* Misc */
+
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
-/* jim-load.c */
+
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
-/* jim-aio.c */
+
JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
-/* type inspection - avoid where possible */
+
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
@@ -1042,95 +791,48 @@ JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
}
#endif
-#endif /* __JIM__H */
-
-/*
- * Local Variables: ***
- * c-basic-offset: 4 ***
- * tab-width: 4 ***
- * End: ***
- */
-/* Provides a common approach to implementing Tcl commands
- * which implement subcommands
- */
+#endif
+
#ifndef JIM_SUBCMD_H
#define JIM_SUBCMD_H
-#define JIM_MODFLAG_HIDDEN 0x0001 /* Don't show the subcommand in usage or commands */
-#define JIM_MODFLAG_FULLARGV 0x0002 /* Subcmd proc gets called with full argv */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define JIM_MODFLAG_HIDDEN 0x0001
+#define JIM_MODFLAG_FULLARGV 0x0002
+
-/* Custom flags start at 0x0100 */
-/**
- * Returns JIM_OK if OK, JIM_ERR (etc.) on error, break, continue, etc.
- * Returns -1 if invalid args.
- */
typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
typedef struct {
- const char *cmd; /* Name of the (sub)command */
- const char *args; /* Textual description of allowed args */
- tclmod_cmd_function *function; /* Function implementing the subcommand */
- short minargs; /* Minimum required arguments */
- short maxargs; /* Maximum allowed arguments or -1 if no limit */
- unsigned flags; /* JIM_MODFLAG_... plus custom flags */
- const char *description; /* Description of the subcommand */
+ const char *cmd;
+ const char *args;
+ tclmod_cmd_function *function;
+ short minargs;
+ short maxargs;
+ unsigned flags;
+ const char *description;
} jim_subcmd_type;
-/**
- * Looks up the appropriate subcommand in the given command table and return
- * the command function which implements the subcommand.
- * NULL will be returned and an appropriate error will be set if the subcommand or
- * arguments are invalid.
- *
- * Typical usage is:
- * {
- * const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, command_table, argc, argv);
- *
- * return Jim_CallSubCmd(interp, ct, argc, argv);
- * }
- *
- */
const jim_subcmd_type *
Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
-/**
- * Parses the args against the given command table and executes the subcommand if found
- * or sets an appropriate error if the subcommand or arguments is invalid.
- *
- * Can be used directly with Jim_CreateCommand() where the ClientData is the command table.
- *
- * e.g. Jim_CreateCommand(interp, "mycmd", Jim_SubCmdProc, command_table, NULL);
- */
int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-/**
- * Invokes the given subcmd with the given args as returned
- * by Jim_ParseSubCmd()
- *
- * If ct is NULL, returns JIM_ERR, leaving any message.
- * Otherwise invokes ct->function
- *
- * If ct->function returns -1, sets an error message and returns JIM_ERR.
- * Otherwise returns the result of ct->function.
- */
int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);
-/**
- * Standard processing for a command.
- *
- * This does the '-help' and '-usage' check and the number of args checks.
- * for a top level command against a single 'jim_subcmd_type' structure.
- *
- * Additionally, if command_table->function is set, it should point to a sub command table
- * and '-subhelp ?subcmd?', '-subusage' and '-subcommands' are then also recognised.
- *
- * Returns 0 if user requested usage, -1 on arg error, 1 if OK to process.
- */
int
Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
+#ifdef __cplusplus
+}
+#endif
+
#endif
#ifndef JIMREGEXP_H
#define JIMREGEXP_H
@@ -1140,74 +842,47 @@ Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type *command_table, int
#endif
#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
-/* Use POSIX regex */
+
#include <regex.h>
#else
#include <stdlib.h>
-/*
- * Definitions etc. for regexp(3) routines.
- *
- * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
- * not the System V one.
- *
- * 11/04/02 (seiwald) - const-ing for string literals
- */
typedef struct {
int rm_so;
int rm_eo;
} regmatch_t;
-/*
- * The "internal use only" fields in regexp.h are present to pass info from
- * compile to execute that permits the execute phase to run lots faster on
- * simple cases. They are:
- *
- * regstart char that must begin a match; '\0' if none obvious
- * reganch is the match anchored (at beginning-of-line only)?
- * regmust string (pointer into program) that match must include, or NULL
- * regmlen length of regmust string
- *
- * Regstart and reganch permit very fast decisions on suitable starting points
- * for a match, cutting down the work a lot. Regmust permits fast rejection
- * of lines that cannot possibly match. The regmust tests are costly enough
- * that regcomp() supplies a regmust only if the r.e. contains something
- * potentially expensive (at present, the only such thing detected is * or +
- * at the start of the r.e., which can involve a lot of backup). Regmlen is
- * supplied because the test in regexec() needs it and regcomp() is computing
- * it anyway.
- */
typedef struct regexp {
- /* -- public -- */
- int re_nsub; /* number of parenthesized subexpressions */
-
- /* -- private -- */
- int cflags; /* Flags used when compiling */
- int err; /* Any error which occurred during compile */
- int regstart; /* Internal use only. */
- int reganch; /* Internal use only. */
- int regmust; /* Internal use only. */
- int regmlen; /* Internal use only. */
- int *program; /* Allocated */
-
- /* working state - compile */
- const char *regparse; /* Input-scan pointer. */
- int p; /* Current output pos in program */
- int proglen; /* Allocated program size */
-
- /* working state - exec */
- int eflags; /* Flags used when executing */
- const char *start; /* Initial string pointer. */
- const char *reginput; /* Current input pointer. */
- const char *regbol; /* Beginning of input, for ^ check. */
-
- /* Input to regexec() */
- regmatch_t *pmatch; /* submatches will be stored here */
- int nmatch; /* size of pmatch[] */
+
+ int re_nsub;
+
+
+ int cflags;
+ int err;
+ int regstart;
+ int reganch;
+ int regmust;
+ int regmlen;
+ int *program;
+
+
+ const char *regparse;
+ int p;
+ int proglen;
+
+
+ int eflags;
+ const char *start;
+ const char *reginput;
+ const char *regbol;
+
+
+ regmatch_t *pmatch;
+ int nmatch;
} regexp;
typedef regexp regex_t;
@@ -1219,9 +894,9 @@ typedef regexp regex_t;
#define REG_NOTBOL 16
enum {
- REG_NOERROR, /* Success. */
- REG_NOMATCH, /* Didn't find a match (for regexec). */
- REG_BADPAT, /* >= REG_BADPAT is an error */
+ REG_NOERROR,
+ REG_NOMATCH,
+ REG_BADPAT,
REG_ERR_NULL_ARGUMENT,
REG_ERR_UNKNOWN,
REG_ERR_TOO_BIG,
@@ -1254,18 +929,18 @@ int Jim_bootstrapInit(Jim_Interp *interp)
if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
return JIM_ERR;
- return Jim_Eval_Named(interp,
+ return Jim_EvalSource(interp, "bootstrap.tcl", 1,
"\n"
"\n"
"proc package {args} {}\n"
-,"bootstrap.tcl", 1);
+);
}
int Jim_initjimshInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "initjimsh", "1.0", JIM_ERRMSG))
return JIM_ERR;
- return Jim_Eval_Named(interp,
+ return Jim_EvalSource(interp, "initjimsh.tcl", 1,
"\n"
"\n"
"\n"
@@ -1293,14 +968,14 @@ int Jim_initjimshInit(Jim_Interp *interp)
"}\n"
"\n"
"_jimsh_init\n"
-,"initjimsh.tcl", 1);
+);
}
int Jim_globInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "glob", "1.0", JIM_ERRMSG))
return JIM_ERR;
- return Jim_Eval_Named(interp,
+ return Jim_EvalSource(interp, "glob.tcl", 1,
"\n"
"\n"
"\n"
@@ -1430,14 +1105,14 @@ int Jim_globInit(Jim_Interp *interp)
"\n"
" return $result\n"
"}\n"
-,"glob.tcl", 1);
+);
}
int Jim_stdlibInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
return JIM_ERR;
- return Jim_Eval_Named(interp,
+ return Jim_EvalSource(interp, "stdlib.tcl", 1,
"\n"
"\n"
"\n"
@@ -1588,14 +1263,14 @@ int Jim_stdlibInit(Jim_Interp *interp)
" }\n"
" return $dict\n"
"}\n"
-,"stdlib.tcl", 1);
+);
}
int Jim_tclcompatInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
return JIM_ERR;
- return Jim_Eval_Named(interp,
+ return Jim_EvalSource(interp, "tclcompat.tcl", 1,
"\n"
"\n"
"\n"
@@ -1875,47 +1550,9 @@ int Jim_tclcompatInit(Jim_Interp *interp)
" }\n"
" file delete $path\n"
"}\n"
-,"tclcompat.tcl", 1);
-}
-
-/* Jim - A small embeddable Tcl interpreter
- *
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
- * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
- * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
- * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- **/
+);
+}
+
#include <unistd.h>
#include <stdio.h>
@@ -1937,8 +1574,8 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#endif
-#define AIO_CMD_LEN 32 /* e.g. aio.handleXXXXXX */
-#define AIO_BUF_LEN 256 /* Can keep this small and rely on stdio buffering */
+#define AIO_CMD_LEN 32
+#define AIO_BUF_LEN 256
#define AIO_KEEPOPEN 1
@@ -1951,33 +1588,13 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#endif
#endif
-#ifndef JIM_ANSIC
-union sockaddr_any {
- struct sockaddr sa;
- struct sockaddr_in sin;
-#if IPV6
- struct sockaddr_in6 sin6;
-#endif
-};
-
-#ifndef HAVE_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, int size)
-{
- if (af != PF_INET) {
- return NULL;
- }
- snprintf(dst, size, "%s", inet_ntoa(((struct sockaddr_in *)src)->sin_addr));
- return dst;
-}
-#endif
-#endif
typedef struct AioFile
{
FILE *fp;
Jim_Obj *filename;
int type;
- int OpenFlags; /* AIO_KEEPOPEN? keep FILE* */
+ int OpenFlags;
int fd;
#ifdef O_NDELAY
int flags;
@@ -1992,149 +1609,6 @@ typedef struct AioFile
static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-#ifndef JIM_ANSIC
-static int JimParseIPv6Address(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen)
-{
-#if IPV6
- /*
- * An IPv6 addr/port looks like:
- * [::1]
- * [::1]:2000
- * [fe80::223:6cff:fe95:bdc0%en1]:2000
- * [::]:2000
- * 2000
- *
- * Note that the "any" address is ::, which is the same as when no address is specified.
- */
- char *sthost = NULL;
- const char *stport;
- int ret = JIM_OK;
- struct addrinfo req;
- struct addrinfo *ai;
-
- stport = strrchr(hostport, ':');
- if (!stport) {
- /* No : so, the whole thing is the port */
- stport = hostport;
- hostport = "::";
- sthost = Jim_StrDup(hostport);
- }
- else {
- stport++;
- }
-
- if (*hostport == '[') {
- /* This is a numeric ipv6 address */
- char *pt = strchr(++hostport, ']');
- if (pt) {
- sthost = Jim_StrDupLen(hostport, pt - hostport);
- }
- }
-
- if (!sthost) {
- sthost = Jim_StrDupLen(hostport, stport - hostport - 1);
- }
-
- memset(&req, '\0', sizeof(req));
- req.ai_family = PF_INET6;
-
- if (getaddrinfo(sthost, NULL, &req, &ai)) {
- Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport);
- ret = JIM_ERR;
- }
- else {
- memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen);
- *salen = ai->ai_addrlen;
-
- sa->sin.sin_port = htons(atoi(stport));
-
- freeaddrinfo(ai);
- }
- Jim_Free(sthost);
-
- return ret;
-#else
- Jim_SetResultString(interp, "ipv6 not supported", -1);
- return JIM_ERR;
-#endif
-}
-
-static int JimParseIpAddress(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen)
-{
- /* An IPv4 addr/port looks like:
- * 192.168.1.5
- * 192.168.1.5:2000
- * 2000
- *
- * If the address is missing, INADDR_ANY is used.
- * If the port is missing, 0 is used (only useful for server sockets).
- */
- char *sthost = NULL;
- const char *stport;
- int ret = JIM_OK;
-
- stport = strrchr(hostport, ':');
- if (!stport) {
- /* No : so, the whole thing is the port */
- stport = hostport;
- sthost = Jim_StrDup("0.0.0.0");
- }
- else {
- sthost = Jim_StrDupLen(hostport, stport - hostport);
- stport++;
- }
-
- {
-#ifdef HAVE_GETADDRINFO
- struct addrinfo req;
- struct addrinfo *ai;
- memset(&req, '\0', sizeof(req));
- req.ai_family = PF_INET;
-
- if (getaddrinfo(sthost, NULL, &req, &ai)) {
- ret = JIM_ERR;
- }
- else {
- memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen);
- *salen = ai->ai_addrlen;
- freeaddrinfo(ai);
- }
-#else
- struct hostent *he;
-
- ret = JIM_ERR;
-
- if ((he = gethostbyname(sthost)) != NULL) {
- if (he->h_length == sizeof(sa->sin.sin_addr)) {
- *salen = sizeof(sa->sin);
- sa->sin.sin_family= he->h_addrtype;
- memcpy(&sa->sin.sin_addr, he->h_addr, he->h_length); /* set address */
- ret = JIM_OK;
- }
- }
-#endif
-
- sa->sin.sin_port = htons(atoi(stport));
- }
- Jim_Free(sthost);
-
- if (ret != JIM_OK) {
- Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport);
- }
-
- return ret;
-}
-
-#ifdef HAVE_SYS_UN_H
-static int JimParseDomainAddress(Jim_Interp *interp, const char *path, struct sockaddr_un *sa)
-{
- sa->sun_family = PF_UNIX;
- snprintf(sa->sun_path, sizeof(sa->sun_path), "%s", path);
-
- return JIM_OK;
-}
-#endif
-#endif
static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name)
{
@@ -2158,7 +1632,7 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
fclose(af->fp);
}
#ifdef jim_ext_eventloop
- /* remove existing EventHandlers */
+
if (af->rEvent) {
Jim_DeleteFileHandler(interp, af->fp);
}
@@ -2178,7 +1652,7 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
char buf[AIO_BUF_LEN];
Jim_Obj *objPtr;
int nonewline = 0;
- int neededLen = -1; /* -1 is "read as much as possible" */
+ int neededLen = -1;
if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
nonewline = 1;
@@ -2220,12 +1694,12 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (retval != readlen)
break;
}
- /* Check for error conditions */
+
if (ferror(af->fp)) {
clearerr(af->fp);
- /* eof and EAGAIN are not error conditions */
+
if (!feof(af->fp) && errno != EAGAIN) {
- /* I/O error */
+
Jim_FreeNewObj(interp, objPtr);
JimAioSetError(interp, af->filename);
return JIM_ERR;
@@ -2313,7 +1787,7 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (len) {
int hasnl = (buf[len - 1] == '\n');
- /* strip "\n" */
+
Jim_AppendString(interp, objPtr, buf, strlen(buf) - hasnl);
}
}
@@ -2321,13 +1795,13 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
break;
}
if (ferror(af->fp) && errno != EAGAIN && errno != EINTR) {
- /* I/O error */
+
Jim_FreeNewObj(interp, objPtr);
JimAioSetError(interp, af->filename);
clearerr(af->fp);
return JIM_ERR;
}
- /* On EOF returns -1 if varName was specified, or the empty string. */
+
if (feof(af->fp) && Jim_Length(objPtr) == 0) {
Jim_FreeNewObj(interp, objPtr);
if (argc) {
@@ -2378,127 +1852,6 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
-#ifndef JIM_ANSIC
-static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- AioFile *af = Jim_CmdPrivData(interp);
- char *buf;
- union sockaddr_any sa;
- long len;
- socklen_t salen = sizeof(sa);
- int rlen;
-
- if (Jim_GetLong(interp, argv[0], &len) != JIM_OK) {
- return JIM_ERR;
- }
-
- buf = Jim_Alloc(len + 1);
-
- rlen = recvfrom(fileno(af->fp), buf, len, 0, &sa.sa, &salen);
- if (rlen < 0) {
- Jim_Free(buf);
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- buf[rlen] = 0;
- Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, rlen));
-
- if (argc > 1) {
- /* INET6_ADDRSTRLEN is 46. Add some for [] and port */
- char addrbuf[60];
-
-#if IPV6
- if (sa.sa.sa_family == PF_INET6) {
- addrbuf[0] = '[';
- /* Allow 9 for []:65535\0 */
- inet_ntop(sa.sa.sa_family, &sa.sin6.sin6_addr, addrbuf + 1, sizeof(addrbuf) - 9);
- snprintf(addrbuf + strlen(addrbuf), 8, "]:%d", ntohs(sa.sin.sin_port));
- }
- else
-#endif
- {
- /* Allow 7 for :65535\0 */
- inet_ntop(sa.sa.sa_family, &sa.sin.sin_addr, addrbuf, sizeof(addrbuf) - 7);
- snprintf(addrbuf + strlen(addrbuf), 7, ":%d", ntohs(sa.sin.sin_port));
- }
-
- if (Jim_SetVariable(interp, argv[1], Jim_NewStringObj(interp, addrbuf, -1)) != JIM_OK) {
- return JIM_ERR;
- }
- }
-
- return JIM_OK;
-}
-
-
-static int aio_cmd_sendto(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- AioFile *af = Jim_CmdPrivData(interp);
- int wlen;
- int len;
- const char *wdata;
- union sockaddr_any sa;
- const char *addr = Jim_String(argv[1]);
- int salen;
-
- if (IPV6 && af->addr_family == PF_INET6) {
- if (JimParseIPv6Address(interp, addr, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- }
- else if (JimParseIpAddress(interp, addr, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- wdata = Jim_GetString(argv[0], &wlen);
-
- /* Note that we don't validate the socket type. Rely on sendto() failing if appropriate */
- len = sendto(fileno(af->fp), wdata, wlen, 0, &sa.sa, salen);
- if (len < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- Jim_SetResultInt(interp, len);
- return JIM_OK;
-}
-
-static int aio_cmd_accept(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- AioFile *serv_af = Jim_CmdPrivData(interp);
- int sock;
- union sockaddr_any sa;
- socklen_t addrlen = sizeof(sa);
- AioFile *af;
- char buf[AIO_CMD_LEN];
-
- sock = accept(serv_af->fd, &sa.sa, &addrlen);
- if (sock < 0)
- return JIM_ERR;
-
- /* Create the file command */
- af = Jim_Alloc(sizeof(*af));
- af->fd = sock;
-#ifdef FD_CLOEXEC
- fcntl(af->fd, F_SETFD, FD_CLOEXEC);
-#endif
- af->filename = Jim_NewStringObj(interp, "accept", -1);
- Jim_IncrRefCount(af->filename);
- af->fp = fdopen(sock, "r+");
-
- af->OpenFlags = 0;
-#ifdef O_NDELAY
- af->flags = fcntl(af->fd, F_GETFL);
-#endif
- af->rEvent = NULL;
- af->wEvent = NULL;
- af->eEvent = NULL;
- af->addr_family = serv_af->addr_family;
- snprintf(buf, sizeof(buf), "aio.sockstream%ld", Jim_GetId(interp));
- Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
- Jim_SetResultString(interp, buf, -1);
- return JIM_OK;
-}
-
-#endif
static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -2651,7 +2004,7 @@ static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Ob
int scriptlen = 0;
if (argc == 0) {
- /* Return current script */
+
if (*scriptHandlerObj) {
Jim_SetResult(interp, *scriptHandlerObj);
}
@@ -2659,19 +2012,19 @@ static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Ob
}
if (*scriptHandlerObj) {
- /* Delete old handler */
+
Jim_DeleteFileHandler(interp, af->fp);
*scriptHandlerObj = NULL;
}
- /* Now possibly add the new script(s) */
+
Jim_GetString(argv[0], &scriptlen);
if (scriptlen == 0) {
- /* Empty script, so done */
+
return JIM_OK;
}
- /* A new script to add */
+
Jim_IncrRefCount(argv[0]);
*scriptHandlerObj = argv[0];
@@ -2732,26 +2085,6 @@ static const jim_subcmd_type aio_command_table[] = {
.maxargs = 2,
.description = "Write the string, with newline unless -nonewline"
},
-#ifndef JIM_ANSIC
- { .cmd = "recvfrom",
- .args = "len ?addrvar?",
- .function = aio_cmd_recvfrom,
- .minargs = 1,
- .maxargs = 2,
- .description = "Receive up to 'len' bytes on the socket. Sets 'addrvar' with receive address, if set"
- },
- { .cmd = "sendto",
- .args = "str address",
- .function = aio_cmd_sendto,
- .minargs = 2,
- .maxargs = 2,
- .description = "Send 'str' to the given address (dgram only)"
- },
- { .cmd = "accept",
- .function = aio_cmd_accept,
- .description = "Server socket only: Accept a connection and return stream"
- },
-#endif
{ .cmd = "flush",
.function = aio_cmd_flush,
.description = "Flush the stream"
@@ -2827,7 +2160,7 @@ 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 JimAioOpenCommand(Jim_Interp *interp, int argc,
+static int JimAioOpenCommand(Jim_Interp *interp, int argc,
Jim_Obj *const *argv)
{
FILE *fp;
@@ -2858,7 +2191,7 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
const char *filename = Jim_String(argv[1]);
#ifdef jim_ext_tclcompat
- /* If the filename starts with '|', use popen instead */
+
if (*filename == '|') {
Jim_Obj *evalObj[3];
@@ -2874,12 +2207,12 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
JimAioSetError(interp, argv[1]);
return JIM_ERR;
}
- /* Get the next file id */
+
snprintf(buf, sizeof(buf), "aio.handle%ld", Jim_GetId(interp));
cmdname = buf;
}
- /* Create the file command */
+
af = Jim_Alloc(sizeof(*af));
af->fp = fp;
af->fd = fileno(fp);
@@ -2902,310 +2235,6 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
return JIM_OK;
}
-#ifndef JIM_ANSIC
-
-/**
- * Creates a channel for fd.
- *
- * hdlfmt is a sprintf format for the filehandle. Anything with %ld at the end will do.
- * mode is usual "r+", but may be another fdopen() mode as required.
- *
- * Creates the command and lappends the name of the command to the current result.
- *
- */
-static int JimMakeChannel(Jim_Interp *interp, Jim_Obj *filename, const char *hdlfmt, int fd, int family,
- const char *mode)
-{
- AioFile *af;
- char buf[AIO_CMD_LEN];
-
- FILE *fp = fdopen(fd, mode);
-
- if (fp == NULL) {
- close(fd);
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
-
- /* Create the file command */
- af = Jim_Alloc(sizeof(*af));
- af->fp = fp;
- af->fd = fd;
- fcntl(af->fd, F_SETFD, FD_CLOEXEC);
- af->OpenFlags = 0;
- af->filename = filename;
- Jim_IncrRefCount(af->filename);
-#ifdef O_NDELAY
- af->flags = fcntl(af->fd, F_GETFL);
-#endif
- af->rEvent = NULL;
- af->wEvent = NULL;
- af->eEvent = NULL;
- af->addr_family = family;
- snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
- Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
-
- Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, buf, -1));
-
- return JIM_OK;
-}
-
-static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *hdlfmt = "aio.unknown%ld";
- const char *socktypes[] = {
- "unix",
- "unix.server",
- "dgram",
- "dgram.server",
- "stream",
- "stream.server",
- "pipe",
- NULL
- };
- enum
- {
- SOCK_UNIX,
- SOCK_UNIX_SERVER,
- SOCK_DGRAM_CLIENT,
- SOCK_DGRAM_SERVER,
- SOCK_STREAM_CLIENT,
- SOCK_STREAM_SERVER,
- SOCK_STREAM_PIPE,
- SOCK_DGRAM6_CLIENT,
- SOCK_DGRAM6_SERVER,
- SOCK_STREAM6_CLIENT,
- SOCK_STREAM6_SERVER,
- };
- int socktype;
- int sock;
- const char *hostportarg = NULL;
- int res;
- int on = 1;
- const char *mode = "r+";
- int family = PF_INET;
- Jim_Obj *argv0 = argv[0];
- int ipv6 = 0;
-
- if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-ipv6")) {
- if (!IPV6) {
- Jim_SetResultString(interp, "ipv6 not supported", -1);
- return JIM_ERR;
- }
- ipv6 = 1;
- family = PF_INET6;
- }
- argc -= ipv6;
- argv += ipv6;
-
- if (argc < 2) {
- wrongargs:
- Jim_WrongNumArgs(interp, 1, &argv0, "?-ipv6? type ?address?");
- return JIM_ERR;
- }
-
- if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type", JIM_ERRMSG) != JIM_OK)
- return JIM_ERR;
-
- Jim_SetResultString(interp, "", 0);
-
- hdlfmt = "aio.sock%ld";
-
- if (argc > 2) {
- hostportarg = Jim_String(argv[2]);
- }
-
- switch (socktype) {
- case SOCK_DGRAM_CLIENT:
- if (argc == 2) {
- /* No address, so an unconnected dgram socket */
- sock = socket(family, SOCK_DGRAM, 0);
- if (sock < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- break;
- }
- /* fall through */
- case SOCK_STREAM_CLIENT:
- {
- union sockaddr_any sa;
- int salen;
-
- if (argc != 3) {
- goto wrongargs;
- }
-
- if (ipv6) {
- if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- }
- else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- sock = socket(family, (socktype == SOCK_DGRAM_CLIENT) ? SOCK_DGRAM : SOCK_STREAM, 0);
- if (sock < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- res = connect(sock, &sa.sa, salen);
- if (res) {
- JimAioSetError(interp, argv[2]);
- close(sock);
- return JIM_ERR;
- }
- }
- break;
-
- case SOCK_STREAM_SERVER:
- case SOCK_DGRAM_SERVER:
- {
- union sockaddr_any sa;
- int salen;
-
- if (argc != 3) {
- goto wrongargs;
- }
-
- if (ipv6) {
- if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- }
- else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) {
- return JIM_ERR;
- }
- sock = socket(family, (socktype == SOCK_DGRAM_SERVER) ? SOCK_DGRAM : SOCK_STREAM, 0);
- if (sock < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
-
- /* Enable address reuse */
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
-
- res = bind(sock, &sa.sa, salen);
- if (res) {
- JimAioSetError(interp, argv[2]);
- close(sock);
- return JIM_ERR;
- }
- if (socktype == SOCK_STREAM_SERVER) {
- res = listen(sock, 5);
- if (res) {
- JimAioSetError(interp, NULL);
- close(sock);
- return JIM_ERR;
- }
- }
- hdlfmt = "aio.socksrv%ld";
- }
- break;
-
-#ifdef HAVE_SYS_UN_H
- case SOCK_UNIX:
- {
- struct sockaddr_un sa;
- socklen_t len;
-
- if (argc != 3 || ipv6) {
- goto wrongargs;
- }
-
- if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) {
- JimAioSetError(interp, argv[2]);
- return JIM_ERR;
- }
- family = PF_UNIX;
- sock = socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family);
- res = connect(sock, (struct sockaddr *)&sa, len);
- if (res) {
- JimAioSetError(interp, argv[2]);
- close(sock);
- return JIM_ERR;
- }
- hdlfmt = "aio.sockunix%ld";
- break;
- }
-
- case SOCK_UNIX_SERVER:
- {
- struct sockaddr_un sa;
- socklen_t len;
-
- if (argc != 3 || ipv6) {
- goto wrongargs;
- }
-
- if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) {
- JimAioSetError(interp, argv[2]);
- return JIM_ERR;
- }
- family = PF_UNIX;
- sock = socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family);
- res = bind(sock, (struct sockaddr *)&sa, len);
- if (res) {
- JimAioSetError(interp, argv[2]);
- close(sock);
- return JIM_ERR;
- }
- res = listen(sock, 5);
- if (res) {
- JimAioSetError(interp, NULL);
- close(sock);
- return JIM_ERR;
- }
- hdlfmt = "aio.sockunixsrv%ld";
- break;
- }
-#endif
-
-#ifdef HAVE_PIPE
- case SOCK_STREAM_PIPE:
- {
- int p[2];
-
- if (argc != 2 || ipv6) {
- goto wrongargs;
- }
-
- if (pipe(p) < 0) {
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
-
- hdlfmt = "aio.pipe%ld";
- if (JimMakeChannel(interp, argv[1], hdlfmt, p[0], family, "r") != JIM_OK) {
- close(p[0]);
- close(p[1]);
- JimAioSetError(interp, NULL);
- return JIM_ERR;
- }
- /* Note, if this fails it will leave p[0] open, but this should never happen */
- mode = "w";
- sock = p[1];
- }
- break;
-#endif
- default:
- Jim_SetResultString(interp, "Unsupported socket type", -1);
- return JIM_ERR;
- }
-
- return JimMakeChannel(interp, argv[1], hdlfmt, sock, family, mode);
-}
-#endif
FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
{
@@ -3228,57 +2257,12 @@ int Jim_aioInit(Jim_Interp *interp)
Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
#endif
- /* Takeover stdin, stdout and stderr */
+
Jim_EvalGlobal(interp, "open stdin; open stdout; open stderr");
return JIM_OK;
}
-/*
- * Tcl readdir command.
- *
- * (c) 2008 Steve Bennett <steveb@worware.net.au>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on original work by:
- *-----------------------------------------------------------------------------
- * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies. Karl Lehenbauer and
- * Mark Diekhans make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *-----------------------------------------------------------------------------
- */
#include <errno.h>
#include <stdio.h>
@@ -3286,17 +2270,6 @@ int Jim_aioInit(Jim_Interp *interp)
#include <dirent.h>
-/*
- *-----------------------------------------------------------------------------
- *
- * Jim_ReaddirCmd --
- * Implements the rename TCL command:
- * readdir ?-nocomplain? dirPath
- *
- * Results:
- * Standard TCL result.
- *-----------------------------------------------------------------------------
- */
int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *dirPath;
@@ -3350,52 +2323,6 @@ int Jim_readdirInit(Jim_Interp *interp)
Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
return JIM_OK;
}
-/*
- * Implements the regexp and regsub commands for Jim
- *
- * (c) 2008 Steve Bennett <steveb@workware.net.au>
- *
- * Uses C library regcomp()/regexec() for the matching.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on code originally from Tcl 6.7:
- *
- * Copyright 1987-1991 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
#include <stdlib.h>
#include <string.h>
@@ -3421,20 +2348,16 @@ static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned f
const char *pattern;
int ret;
- /* Check if the object is already an uptodate variable */
+
if (objPtr->typePtr == &regexpObjType &&
objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
- /* nothing to do */
+
return objPtr->internalRep.regexpValue.compre;
}
- /* Not a regexp or the flags do not match */
- if (objPtr->typePtr == &regexpObjType) {
- FreeRegexpInternalRep(interp, objPtr);
- objPtr->typePtr = NULL;
- }
+
- /* Get the string representation */
+
pattern = Jim_String(objPtr);
compre = Jim_Alloc(sizeof(regex_t));
@@ -3448,6 +2371,8 @@ static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned f
return NULL;
}
+ Jim_FreeIntRep(interp, objPtr);
+
objPtr->typePtr = &regexpObjType;
objPtr->internalRep.regexpValue.flags = flags;
objPtr->internalRep.regexpValue.compre = compre;
@@ -3558,9 +2483,6 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch));
- /* If an offset has been specified, adjust for that now.
- * If it points past the end of the string, point to the terminating null
- */
if (offset) {
if (offset < 0) {
offset += source_len + 1;
@@ -3596,14 +2518,10 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
num_matches++;
if (opt_all && !opt_inline) {
- /* Just count the number of matches, so skip the substitution h */
+
goto try_next_match;
}
- /*
- * If additional variable names have been specified, return
- * index information in those variables.
- */
j = 0;
for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) {
@@ -3640,7 +2558,7 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_ListAppendElement(interp, resultListObj, resultObj);
}
else {
- /* And now set the result variable */
+
result = Jim_SetVariable(interp, argv[i], resultObj);
if (result != JIM_OK) {
@@ -3767,12 +2685,9 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
replace_str = Jim_GetString(argv[i + 2], &replace_len);
varname = argv[i + 3];
- /* Create the result string */
+
resultObj = Jim_NewStringObj(interp, "", 0);
- /* If an offset has been specified, adjust for that now.
- * If it points past the end of the string, point to the terminating null
- */
if (offset) {
if (offset < 0) {
offset += source_len + 1;
@@ -3785,15 +2700,9 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
}
- /* Copy the part before -start */
+
Jim_AppendString(interp, resultObj, source_str, offset);
- /*
- * The following loop is to handle multiple matches within the
- * same source string; each iteration handles one match and its
- * corresponding substitution. If "-all" hasn't been specified
- * then the loop body only gets executed once.
- */
n = source_len - offset;
p = source_str + offset;
@@ -3813,18 +2722,8 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
num_matches++;
- /*
- * Copy the portion of the source string before the match to the
- * result variable.
- */
Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
- /*
- * Append the subSpec (replace_str) argument to the variable, making appropriate
- * substitutions. This code is a bit hairy because of the backslash
- * conventions and because the code saves up ranges of characters in
- * subSpec to reduce the number of calls to Jim_SetVar.
- */
for (j = 0; j < replace_len; j++) {
int idx;
@@ -3860,34 +2759,30 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
p += pmatch[0].rm_eo;
n -= pmatch[0].rm_eo;
- /* If -all is not specified, or there is no source left, we are done */
+
if (!opt_all || n == 0) {
break;
}
- /* An anchored pattern without -line must be done */
+
if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
break;
}
- /* If the pattern is empty, need to step forwards */
+
if (pattern[0] == '\0' && n) {
- /* Need to copy the char we are moving over */
+
Jim_AppendString(interp, resultObj, p, 1);
p++;
n--;
}
-
+
regexec_flags |= REG_NOTBOL;
} while (n);
- /*
- * Copy the portion of the string after the last match to the
- * result variable.
- */
Jim_AppendString(interp, resultObj, p, -1);
- /* And now set or return the result variable */
+
if (argc - i == 4) {
result = Jim_SetVariable(interp, varname, resultObj);
@@ -3915,50 +2810,6 @@ int Jim_regexpInit(Jim_Interp *interp)
Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
return JIM_OK;
}
-/*
- * Implements the file command for jim
- *
- * (c) 2008 Steve Bennett <steveb@workware.net.au>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on code originally from Tcl 6.7:
- *
- * Copyright 1987-1991 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
#include <limits.h>
#include <stdlib.h>
@@ -3968,28 +2819,13 @@ int Jim_regexpInit(Jim_Interp *interp)
#include <errno.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/time.h>
# ifndef MAXPATHLEN
# define MAXPATHLEN JIM_PATH_LEN
# endif
-/*
- *----------------------------------------------------------------------
- *
- * JimGetFileType --
- *
- * Given a mode word, returns a string identifying the type of a
- * file.
- *
- * Results:
- * A static text string giving the file type from mode.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
static const char *JimGetFileType(int mode)
{
@@ -4021,24 +2857,6 @@ static const char *JimGetFileType(int mode)
return "unknown";
}
-/*
- *----------------------------------------------------------------------
- *
- * StoreStatData --
- *
- * This is a utility procedure that breaks out the fields of a
- * "stat" structure and stores them in textual form into the
- * elements of an associative array.
- *
- * Results:
- * Returns a standard Tcl return value. If an error occurs then
- * a message is left in interp->result.
- *
- * Side effects:
- * Elements of the associative array given by "varName" are modified.
- *
- *----------------------------------------------------------------------
- */
static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
jim_wide value)
@@ -4046,7 +2864,7 @@ static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const cha
Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
Jim_Obj *valobj = Jim_NewWideObj(interp, value);
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj) != JIM_OK) {
+ if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
Jim_FreeObj(interp, nameobj);
Jim_FreeObj(interp, valobj);
return JIM_ERR;
@@ -4060,7 +2878,7 @@ static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const
Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj) != JIM_OK) {
+ if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
Jim_FreeObj(interp, nameobj);
Jim_FreeObj(interp, valobj);
return JIM_ERR;
@@ -4085,7 +2903,7 @@ static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat
set_array_int_value(interp, varName, "ctime", sb->st_ctime);
set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
- /* And also return the value */
+
Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
return JIM_OK;
@@ -4104,7 +2922,7 @@ static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#if defined(__MINGW32__)
else if (p[-1] == ':') {
- /* z:/dir => z:/ */
+
Jim_SetResultString(interp, path, p - path + 1);
}
#endif
@@ -4184,18 +3002,18 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
*newname = 0;
- /* Simple implementation for now */
+
for (i = 0; i < argc; i++) {
int len;
const char *part = Jim_GetString(argv[i], &len);
if (*part == '/') {
- /* Absolute component, so go back to the start */
+
last = newname;
}
#if defined(__MINGW32__)
else if (strchr(part, ':')) {
- /* Absolute compontent on mingw, so go back to the start */
+
last = newname;
}
#endif
@@ -4205,12 +3023,12 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
len -= 2;
}
else if (part[1] == 0 && last != newname) {
- /* Adding '.' to an existing path does nothing */
+
continue;
}
}
- /* Add a slash if needed */
+
if (last != newname && last[-1] != '/') {
*last++ = '/';
}
@@ -4225,7 +3043,7 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
last += len;
}
- /* Remove a slash if needed */
+
if (last > newname + 1 && last[-1] == '/') {
*--last = 0;
}
@@ -4233,7 +3051,7 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
*last = 0;
- /* Probably need to handle some special cases ... */
+
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
@@ -4284,8 +3102,8 @@ static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (unlink(path) == -1 && errno != ENOENT) {
if (rmdir(path) == -1) {
- /* Maybe try using the script helper */
- if (!force || Jim_EvalObjPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
+
+ if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
strerror(errno));
return JIM_ERR;
@@ -4303,22 +3121,15 @@ static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755)
#endif
-/**
- * Create directory, creating all intermediate paths if necessary.
- *
- * Returns 0 if OK or -1 on failure (and sets errno)
- *
- * Note: The path may be modified.
- */
static int mkdir_all(char *path)
{
int ok = 1;
- /* First time just try to make the dir */
+
goto first;
while (ok--) {
- /* Must have failed the first time, so recursively make the parent and try again */
+
char *slash = strrchr(path, '/');
if (slash && slash != path) {
@@ -4333,20 +3144,20 @@ static int mkdir_all(char *path)
return 0;
}
if (errno == ENOENT) {
- /* Create the parent and try again */
+
continue;
}
- /* Maybe it already exists as a directory */
+
if (errno == EEXIST) {
struct stat sb;
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
return 0;
}
- /* Restore errno */
+
errno = EEXIST;
}
- /* Failed */
+
break;
}
return -1;
@@ -4467,6 +3278,27 @@ static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct stat sb;
+ if (argc == 2) {
+#ifdef HAVE_UTIMES
+ jim_wide newtime;
+ struct timeval times[2];
+
+ if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) {
+ return JIM_ERR;
+ }
+
+ times[1].tv_sec = times[0].tv_sec = newtime;
+ times[1].tv_usec = times[0].tv_usec = 0;
+
+ if (utimes(Jim_String(argv[0]), times) != 0) {
+ Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno));
+ return JIM_ERR;
+ }
+#else
+ Jim_SetResultString(interp, "Not implemented", -1);
+ return JIM_ERR;
+#endif
+ }
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
@@ -4476,7 +3308,7 @@ static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- return Jim_EvalObjPrefix(interp, "file copy", argc, argv);
+ return Jim_EvalPrefix(interp, "file copy", argc, argv);
}
static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -4538,7 +3370,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, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno));
return JIM_ERR;
}
linkValue[linkLength] = 0;
@@ -4587,11 +3419,11 @@ static const jim_subcmd_type file_command_table[] = {
.description = "Last access time"
},
{ .cmd = "mtime",
- .args = "name",
+ .args = "name ?time?",
.function = file_cmd_mtime,
.minargs = 1,
- .maxargs = 1,
- .description = "Last modification time"
+ .maxargs = 2,
+ .description = "Get or set last modification time"
},
{ .cmd = "copy",
.args = "?-force? source dest",
@@ -4795,7 +3627,7 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#if defined(__MINGW32__)
{
- /* Try to keep backlashes out of paths */
+
char *p = cwd;
while ((p = strchr(p, '\\')) != NULL) {
*p++ = '/';
@@ -4820,50 +3652,135 @@ int Jim_fileInit(Jim_Interp *interp)
return JIM_OK;
}
-/*
- * (c) 2008 Steve Bennett <steveb@workware.net.au>
- *
- * Implements the exec command for Jim
- *
- * Based on code originally from Tcl 6.7 by John Ousterhout.
- * From that code:
- *
- * The Tcl_Fork and Tcl_WaitPids procedures are based on code
- * contributed by Karl Lehenbauer, Mark Diekhans and Peter
- * da Silva.
- *
- * Copyright 1987-1991 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
#include <string.h>
-#include <signal.h>
+#include <ctype.h>
-#if defined(HAVE_VFORK) && defined(HAVE_WAITPID)
+#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
+static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
+ int i, j;
+ int rc;
+
+
+ for (i = 1; i < argc; i++) {
+ int len;
+ const char *arg = Jim_GetString(argv[i], &len);
+
+ if (i > 1) {
+ Jim_AppendString(interp, cmdlineObj, " ", 1);
+ }
+ if (strpbrk(arg, "\\\" ") == NULL) {
+
+ Jim_AppendString(interp, cmdlineObj, arg, len);
+ continue;
+ }
+
+ Jim_AppendString(interp, cmdlineObj, "\"", 1);
+ for (j = 0; j < len; j++) {
+ if (arg[j] == '\\' || arg[j] == '"') {
+ Jim_AppendString(interp, cmdlineObj, "\\", 1);
+ }
+ Jim_AppendString(interp, cmdlineObj, &arg[j], 1);
+ }
+ Jim_AppendString(interp, cmdlineObj, "\"", 1);
+ }
+ rc = system(Jim_String(cmdlineObj));
+
+ Jim_FreeNewObj(interp, cmdlineObj);
+
+ if (rc) {
+ Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc));
+ Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
+ return JIM_ERR;
+ }
+
+ return JIM_OK;
+}
+
+int Jim_execInit(Jim_Interp *interp)
+{
+ if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
+ return JIM_ERR;
+ Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
+ return JIM_OK;
+}
+#else
-#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
-#include <sys/wait.h>
+#include <signal.h>
-#if defined(__GNUC__) && !defined(__clang__)
-#define IGNORE_RC(EXPR) ((EXPR) < 0 ? -1 : 0)
+#define XXX printf("@%s:%d\n", __FILE__, __LINE__); fflush(stdout);
+
+#if defined(__MINGW32__)
+
+ #include <fcntl.h>
+
+ typedef HANDLE fdtype;
+ typedef HANDLE pidtype;
+ #define JIM_BAD_FD INVALID_HANDLE_VALUE
+ #define JIM_BAD_PID INVALID_HANDLE_VALUE
+ #define JimCloseFd CloseHandle
+
+ #define WIFEXITED(STATUS) 1
+ #define WEXITSTATUS(STATUS) (STATUS)
+ #define WIFSIGNALED(STATUS) 0
+ #define WTERMSIG(STATUS) 0
+ #define WNOHANG 1
+
+ static fdtype JimFileno(FILE *fh);
+ static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
+ static fdtype JimDupFd(fdtype infd);
+ static fdtype JimOpenForRead(const char *filename);
+ static FILE *JimFdOpenForRead(fdtype fd);
+ static int JimPipe(fdtype pipefd[2]);
+ static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
+ fdtype inputId, fdtype outputId, fdtype errorId);
+ static int JimErrno(void);
#else
-#define IGNORE_RC(EXPR) EXPR
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/wait.h>
+
+ typedef int fdtype;
+ typedef int pidtype;
+ #define JimPipe pipe
+ #define JimErrno() errno
+ #define JIM_BAD_FD -1
+ #define JIM_BAD_PID -1
+ #define JimFileno fileno
+ #define JimReadFd read
+ #define JimCloseFd close
+ #define JimWaitPid waitpid
+ #define JimDupFd dup
+ #define JimFdOpenForRead(FD) fdopen((FD), "r")
+ #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
#endif
-/* These two could be moved into the Tcl core */
+static const char *JimStrError(void);
+static char **JimSaveEnv(char **env);
+static void JimRestoreEnv(char **env);
+static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
+ pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
+static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
+static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents);
+static fdtype JimOpenForWrite(const char *filename, int append);
+static int JimRewindFd(fdtype fd);
+
static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
{
- Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(errno));
+ Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
+}
+
+static const char *JimStrError(void)
+{
+ return strerror(JimErrno());
}
static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
@@ -4877,36 +3794,28 @@ static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
}
}
-/**
- * Read from 'fd' and append the data to strObj
- * Returns JIM_OK if OK, or JIM_ERR on error.
- */
-static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj)
+static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj)
{
- while (1) {
- char buffer[256];
- int count;
-
- count = read(fd, buffer, sizeof(buffer));
+ char buf[256];
+ FILE *fh = JimFdOpenForRead(fd);
+ if (fh == NULL) {
+ return JIM_ERR;
+ }
- if (count == 0) {
- Jim_RemoveTrailingNewline(strObj);
- return JIM_OK;
+ while (1) {
+ int retval = fread(buf, 1, sizeof(buf), fh);
+ if (retval > 0) {
+ Jim_AppendString(interp, strObj, buf, retval);
}
- if (count < 0) {
- return JIM_ERR;
+ if (retval != sizeof(buf)) {
+ break;
}
- Jim_AppendString(interp, strObj, buffer, count);
}
+ Jim_RemoveTrailingNewline(strObj);
+ fclose(fh);
+ return JIM_OK;
}
-/*
- * If the last character of the result is a newline, then remove
- * the newline character (the newline would just confuse things).
- *
- * Note: Ideally we could do this by just reducing the length of stringrep
- * by 1, but there is no API for this :-(
- */
static void JimTrimTrailingNewline(Jim_Interp *interp)
{
int len;
@@ -4917,22 +3826,15 @@ static void JimTrimTrailingNewline(Jim_Interp *interp)
}
}
-/**
- * Builds the environment array from $::env
- *
- * If $::env is not set, simply returns environ.
- *
- * Otherwise allocates the environ array from the contents of $::env
- *
- * If the exec fails, memory can be freed via JimFreeEnv()
- */
static char **JimBuildEnv(Jim_Interp *interp)
{
-#ifdef jim_ext_tclcompat
+#if defined(jim_ext_tclcompat)
int i;
- int len;
+ int size;
+ int num;
int n;
- char **env;
+ char **envptr;
+ char *envdata;
Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
@@ -4940,62 +3842,52 @@ static char **JimBuildEnv(Jim_Interp *interp)
return Jim_GetEnviron();
}
- /* Calculate the required size */
- len = Jim_ListLength(interp, objPtr);
- if (len % 2) {
- len--;
+
+
+ num = Jim_ListLength(interp, objPtr);
+ if (num % 2) {
+ num--;
}
+ size = Jim_Length(objPtr);
+ size++;
- env = Jim_Alloc(sizeof(*env) * (len / 2 + 1));
+ envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
+ envdata = (char *)&envptr[num / 2 + 1];
n = 0;
- for (i = 0; i < len; i += 2) {
- int l1, l2;
+ for (i = 0; i < num; i += 2) {
const char *s1, *s2;
Jim_Obj *elemObj;
Jim_ListIndex(interp, objPtr, i, &elemObj, JIM_NONE);
- s1 = Jim_GetString(elemObj, &l1);
+ s1 = Jim_String(elemObj);
Jim_ListIndex(interp, objPtr, i + 1, &elemObj, JIM_NONE);
- s2 = Jim_GetString(elemObj, &l2);
+ s2 = Jim_String(elemObj);
- env[n] = Jim_Alloc(l1 + l2 + 2);
- sprintf(env[n], "%s=%s", s1, s2);
+ envptr[n] = envdata;
+ envdata += sprintf(envdata, "%s=%s", s1, s2);
+ envdata++;
n++;
}
- env[n] = NULL;
+ envptr[n] = NULL;
+ *envdata = 0;
- return env;
+ return envptr;
#else
return Jim_GetEnviron();
#endif
}
-/**
- * Frees the environment allocated by JimBuildEnv()
- *
- * Must pass original_environ.
- */
-static void JimFreeEnv(Jim_Interp *interp, char **env, char **original_environ)
+static void JimFreeEnv(char **env, char **original_environ)
{
#ifdef jim_ext_tclcompat
if (env != original_environ) {
- int i;
- for (i = 0; env[i]; i++) {
- Jim_Free(env[i]);
- }
Jim_Free(env);
}
#endif
}
-/*
- * Create error messages for unusual process exits. An
- * extra newline gets appended to each error message, but
- * it gets removed below (in the same fashion that an
- * extra newline in the command's output is removed).
- */
-static int JimCheckWaitStatus(Jim_Interp *interp, int pid, int waitStatus)
+static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
{
Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
int rc = JIM_ERR;
@@ -5007,7 +3899,7 @@ static int JimCheckWaitStatus(Jim_Interp *interp, int pid, int waitStatus)
}
else {
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
}
}
@@ -5034,7 +3926,7 @@ static int JimCheckWaitStatus(Jim_Interp *interp, int pid, int waitStatus)
#else
Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus));
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
#endif
}
@@ -5042,16 +3934,12 @@ static int JimCheckWaitStatus(Jim_Interp *interp, int pid, int waitStatus)
return rc;
}
-/*
- * Data structures of the following type are used by JimFork and
- * JimWaitPids to keep track of child processes.
- */
struct WaitInfo
{
- int pid; /* Process id of child. */
- int status; /* Status returned when child exited or suspended. */
- int flags; /* Various flag bits; see below for definitions. */
+ pidtype pid;
+ int status;
+ int flags;
};
struct WaitInfoTable {
@@ -5060,13 +3948,6 @@ struct WaitInfoTable {
int used;
};
-/*
- * Flag bits in WaitInfo structures:
- *
- * WI_DETACHED - Non-zero means no-one cares about the
- * process anymore. Ignore it until it
- * exits, then forget about it.
- */
#define WI_DETACHED 2
@@ -5089,37 +3970,28 @@ static struct WaitInfoTable *JimAllocWaitInfoTable(void)
return table;
}
-static int Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
- int **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
-static void JimDetachPids(Jim_Interp *interp, int numPids, const int *pidPtr);
-static int Jim_CleanupChildren(Jim_Interp *interp, int numPids, int *pidPtr, int errorId);
-
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- int outputId; /* File id for output pipe. -1
+ fdtype outputId; /* File id for output pipe. -1
* means command overrode. */
- int errorId; /* File id for temporary file
+ fdtype errorId; /* File id for temporary file
* containing error output. */
- int *pidPtr;
+ pidtype *pidPtr;
int numPids, result;
- /*
- * See if the command is to be run in background; if so, create
- * the command, detach it, and return.
- */
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
Jim_Obj *listObj;
int i;
argc--;
- numPids = Jim_CreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
+ numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
if (numPids < 0) {
return JIM_ERR;
}
- /* The return value is a list of the pids */
+
listObj = Jim_NewListObj(interp, NULL, 0);
for (i = 0; i < numPids; i++) {
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pidPtr[i]));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
}
Jim_SetResult(interp, listObj);
JimDetachPids(interp, numPids, pidPtr);
@@ -5127,36 +3999,30 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
- /*
- * Create the command's pipeline.
- */
numPids =
- Jim_CreatePipeline(interp, argc - 1, argv + 1, &pidPtr, (int *)NULL, &outputId, &errorId);
+ JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId);
+
if (numPids < 0) {
return JIM_ERR;
}
- /*
- * Read the child's output (if any) and put it into the result.
- */
Jim_SetResultString(interp, "", 0);
result = JIM_OK;
- if (outputId != -1) {
+ if (outputId != JIM_BAD_FD) {
result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp));
if (result < 0) {
Jim_SetResultErrno(interp, "error reading from output pipe");
}
- close(outputId);
}
- if (Jim_CleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) {
+ if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) {
result = JIM_ERR;
}
return result;
}
-void Jim_ReapDetachedPids(struct WaitInfoTable *table)
+static void JimReapDetachedPids(struct WaitInfoTable *table)
{
struct WaitInfo *waitPtr;
int count;
@@ -5168,8 +4034,8 @@ void Jim_ReapDetachedPids(struct WaitInfoTable *table)
for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
if (waitPtr->flags & WI_DETACHED) {
int status;
- int pid = waitpid(waitPtr->pid, &status, WNOHANG);
- if (pid > 0) {
+ pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
+ if (pid != JIM_BAD_PID) {
if (waitPtr != &table->info[table->used - 1]) {
*waitPtr = table->info[table->used - 1];
}
@@ -5179,24 +4045,17 @@ void Jim_ReapDetachedPids(struct WaitInfoTable *table)
}
}
-/**
- * Does waitpid() on the given pid, and then removes the
- * entry from the wait table.
- *
- * Returns the pid if OK and updates *statusPtr with the status,
- * or -1 if the pid was not in the table.
- */
-static int JimWaitPid(struct WaitInfoTable *table, int pid, int *statusPtr)
+static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
{
int i;
- /* Find it in the table */
+
for (i = 0; i < table->used; i++) {
if (pid == table->info[i].pid) {
- /* wait for it */
- waitpid(pid, statusPtr, 0);
+
+ JimWaitPid(pid, statusPtr, 0);
- /* Remove it from the table */
+
if (i != table->used - 1) {
table->info[i] = table->info[table->used - 1];
}
@@ -5205,35 +4064,18 @@ static int JimWaitPid(struct WaitInfoTable *table, int pid, int *statusPtr)
}
}
- /* Not found */
- return -1;
+
+ return JIM_BAD_PID;
}
-/*
- *----------------------------------------------------------------------
- *
- * JimDetachPids --
- *
- * This procedure is called to indicate that one or more child
- * processes have been placed in background and are no longer
- * cared about. These children can be cleaned up with JimReapDetachedPids().
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void JimDetachPids(Jim_Interp *interp, int numPids, const int *pidPtr)
+
+static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
{
int j;
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
for (j = 0; j < numPids; j++) {
- /* Find it in the table */
+
int i;
for (i = 0; i < table->used; i++) {
if (pidPtr[j] == table->info[i].pid) {
@@ -5244,39 +4086,11 @@ static void JimDetachPids(Jim_Interp *interp, int numPids, const int *pidPtr)
}
}
-/*
- *----------------------------------------------------------------------
- *
- * Jim_CreatePipeline --
- *
- * Given an argc/argv array, instantiate a pipeline of processes
- * as described by the argv.
- *
- * Results:
- * The return value is a count of the number of new processes
- * created, or -1 if an error occurred while creating the pipeline.
- * *pidArrayPtr is filled in with the address of a dynamically
- * allocated array giving the ids of all of the processes. It
- * is up to the caller to free this array when it isn't needed
- * anymore. If inPipePtr is non-NULL, *inPipePtr is filled in
- * with the file id for the input pipe for the pipeline (if any):
- * the caller must eventually close this file. If outPipePtr
- * isn't NULL, then *outPipePtr is filled in with the file id
- * for the output pipe from the pipeline: the caller must close
- * this file. If errFilePtr isn't NULL, then *errFilePtr is filled
- * with a file id that may be used to read error output after the
- * pipeline completes.
- *
- * Side effects:
- * Processes and pipes are created.
- *
- *----------------------------------------------------------------------
- */
static int
-Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int **pidArrayPtr,
- int *inPipePtr, int *outPipePtr, int *errFilePtr)
+JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
+ fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
{
- int *pidPtr = NULL; /* Points to malloc-ed array holding all
+ pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all
* the pids of child processes. */
int numPids = 0; /* Actual number of processes that exist
* at *pidPtr right now. */
@@ -5286,10 +4100,10 @@ Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int **pid
* on "inputFile". NULL means take input
* from stdin/pipe. */
-#define FILE_NAME 0 /* input/output: filename */
-#define FILE_APPEND 1 /* output only: filename, append */
-#define FILE_HANDLE 2 /* input/output: filehandle */
-#define FILE_TEXT 3 /* input only: input is actual text */
+#define FILE_NAME 0
+#define FILE_APPEND 1
+#define FILE_HANDLE 2
+#define FILE_TEXT 3
int inputFile = FILE_NAME; /* 1 means input is name of input file.
* 2 means input is filehandle name.
@@ -5310,51 +4124,36 @@ Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int **pid
* or NULL if output goes to stdout/pipe. */
const char *error = NULL; /* Holds name of stderr file to pipe to,
* or NULL if stderr goes to stderr/pipe. */
- int inputId = -1; /* Readable file id input to current command in
- * pipeline (could be file or pipe). -1
- * means use stdin. */
- int outputId = -1; /* Writable file id for output from current
- * command in pipeline (could be file or pipe).
- * -1 means use stdout. */
- int errorId = -1; /* Writable file id for all standard error
- * output from all commands in pipeline. -1
- * means use stderr. */
- int lastOutputId = -1; /* Write file id for output from last command
- * in pipeline (could be file or pipe).
- * -1 means use stdout. */
- int pipeIds[2]; /* File ids for pipe that's being created. */
+ fdtype inputId = JIM_BAD_FD;
+ fdtype outputId = JIM_BAD_FD;
+ fdtype errorId = JIM_BAD_FD;
+ fdtype lastOutputId = JIM_BAD_FD;
+ fdtype pipeIds[2];
int firstArg, lastArg; /* Indexes of first and last arguments in
* current command. */
int lastBar;
- char *execName;
- int i, pid;
- char **orig_environ;
+ int i;
+ pidtype pid;
+ char **save_environ;
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
- /* Holds the args which will be used to exec */
+
char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
int arg_count = 0;
- Jim_ReapDetachedPids(table);
+ JimReapDetachedPids(table);
if (inPipePtr != NULL) {
- *inPipePtr = -1;
+ *inPipePtr = JIM_BAD_FD;
}
if (outPipePtr != NULL) {
- *outPipePtr = -1;
+ *outPipePtr = JIM_BAD_FD;
}
if (errFilePtr != NULL) {
- *errFilePtr = -1;
+ *errFilePtr = JIM_BAD_FD;
}
- pipeIds[0] = pipeIds[1] = -1;
+ pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
- /*
- * First, scan through all the arguments to figure out the structure
- * of the pipeline. Count the number of distinct processes (it's the
- * number of "|" arguments). If there are "<", "<<", or ">" arguments
- * then make note of input and output redirection and remove these
- * arguments and the arguments that follow them.
- */
cmdCount = 1;
lastBar = -1;
for (i = 0; i < argc; i++) {
@@ -5387,7 +4186,7 @@ Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int **pid
output++;
}
if (*output == '&') {
- /* Redirect stderr too */
+
output++;
dup_error = 1;
}
@@ -5428,7 +4227,7 @@ Jim_CreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int **pid
lastBar = i;
cmdCount++;
}
- /* Either |, |& or a "normal" arg, so store it in the arg array */
+
arg_array[arg_count++] = (char *)arg;
continue;
}
@@ -5446,43 +4245,18 @@ badargs:
return -1;
}
- /* Must do this before vfork(), so do it now */
- orig_environ = Jim_GetEnviron();
- Jim_SetEnviron(JimBuildEnv(interp));
+
+ save_environ = JimSaveEnv(JimBuildEnv(interp));
- /*
- * Set up the redirected input source for the pipeline, if
- * so requested.
- */
if (input != NULL) {
if (inputFile == FILE_TEXT) {
- /*
- * Immediate data in command. Create temporary file and
- * put data into file.
- */
-
-#define TMP_STDIN_NAME "/tmp/tcl.in.XXXXXX"
- char inName[sizeof(TMP_STDIN_NAME) + 1];
- int length;
-
- strcpy(inName, TMP_STDIN_NAME);
- inputId = mkstemp(inName);
- if (inputId < 0) {
- Jim_SetResultErrno(interp, "couldn't create input file for command");
- goto error;
- }
- length = strlen(input);
- if (write(inputId, input, length) != length) {
- Jim_SetResultErrno(interp, "couldn't write file input for command");
- goto error;
- }
- if (lseek(inputId, 0L, SEEK_SET) == -1 || unlink(inName) == -1) {
- Jim_SetResultErrno(interp, "couldn't reset or remove input file for command");
+ inputId = JimCreateTemp(interp, input);
+ if (inputId == JIM_BAD_FD) {
goto error;
}
}
else if (inputFile == FILE_HANDLE) {
- /* Should be a file descriptor */
+
Jim_Obj *fhObj = Jim_NewStringObj(interp, input, -1);
FILE *fh = Jim_AioFilehandle(interp, fhObj);
@@ -5490,34 +4264,26 @@ badargs:
if (fh == NULL) {
goto error;
}
- inputId = dup(fileno(fh));
+ inputId = JimDupFd(JimFileno(fh));
}
else {
- /*
- * File redirection. Just open the file.
- */
- inputId = open(input, O_RDONLY, 0);
- if (inputId < 0) {
- Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input,
- strerror(errno));
+ inputId = JimOpenForRead(input);
+ if (inputId == JIM_BAD_FD) {
+ Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
goto error;
}
}
}
else if (inPipePtr != NULL) {
- if (pipe(pipeIds) != 0) {
+ if (JimPipe(pipeIds) != 0) {
Jim_SetResultErrno(interp, "couldn't create input pipe for command");
goto error;
}
inputId = pipeIds[0];
*inPipePtr = pipeIds[1];
- pipeIds[0] = pipeIds[1] = -1;
+ pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
}
- /*
- * Set up the redirected output sink for the pipeline from one
- * of two places, if requested.
- */
if (output != NULL) {
if (outputFile == FILE_HANDLE) {
Jim_Obj *fhObj = Jim_NewStringObj(interp, output, -1);
@@ -5528,53 +4294,39 @@ badargs:
goto error;
}
fflush(fh);
- lastOutputId = dup(fileno(fh));
+ lastOutputId = JimDupFd(JimFileno(fh));
}
else {
- /*
- * Output is to go to a file.
- */
- int mode = O_WRONLY | O_CREAT | O_TRUNC;
-
- if (outputFile == FILE_APPEND) {
- mode = O_WRONLY | O_CREAT | O_APPEND;
- }
-
- lastOutputId = open(output, mode, 0666);
- if (lastOutputId < 0) {
- Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output,
- strerror(errno));
+ lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
+ if (lastOutputId == JIM_BAD_FD) {
+ Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
goto error;
}
}
}
else if (outPipePtr != NULL) {
- /*
- * Output is to go to a pipe.
- */
- if (pipe(pipeIds) != 0) {
+ if (JimPipe(pipeIds) != 0) {
Jim_SetResultErrno(interp, "couldn't create output pipe");
goto error;
}
lastOutputId = pipeIds[1];
*outPipePtr = pipeIds[0];
- pipeIds[0] = pipeIds[1] = -1;
+ pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
}
-
- /* If we are redirecting stderr with 2>filename or 2>@fileId, then we ignore errFilePtr */
+
if (error != NULL) {
if (errorFile == FILE_HANDLE) {
if (strcmp(error, "1") == 0) {
- /* Special 2>@1 */
- if (lastOutputId >= 0) {
- errorId = dup(lastOutputId);
+
+ if (lastOutputId != JIM_BAD_FD) {
+ errorId = JimDupFd(lastOutputId);
}
else {
- /* No redirection of stdout, so just use 2>@stdout */
+
error = "stdout";
}
}
- if (errorId < 0) {
+ if (errorId == JIM_BAD_FD) {
Jim_Obj *fhObj = Jim_NewStringObj(interp, error, -1);
FILE *fh = Jim_AioFilehandle(interp, fhObj);
@@ -5583,70 +4335,33 @@ badargs:
goto error;
}
fflush(fh);
- errorId = dup(fileno(fh));
+ errorId = JimDupFd(JimFileno(fh));
}
}
else {
- /*
- * Output is to go to a file.
- */
- int mode = O_WRONLY | O_CREAT | O_TRUNC;
-
- if (errorFile == FILE_APPEND) {
- mode = O_WRONLY | O_CREAT | O_APPEND;
- }
-
- errorId = open(error, mode, 0666);
- if (errorId < 0) {
- Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error,
- strerror(errno));
+ errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
+ if (errorId == JIM_BAD_FD) {
+ Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
+ goto error;
}
}
}
else if (errFilePtr != NULL) {
- /*
- * Set up the standard error output sink for the pipeline, if
- * requested. Use a temporary file which is opened, then deleted.
- * Could potentially just use pipe, but if it filled up it could
- * cause the pipeline to deadlock: we'd be waiting for processes
- * to complete before reading stderr, and processes couldn't complete
- * because stderr was backed up.
- */
-
-#define TMP_STDERR_NAME "/tmp/tcl.err.XXXXXX"
- char errName[sizeof(TMP_STDERR_NAME) + 1];
-
- strcpy(errName, TMP_STDERR_NAME);
- errorId = mkstemp(errName);
- if (errorId < 0) {
- errFileError:
- Jim_SetResultErrno(interp, "couldn't create error file for command");
- goto error;
- }
- *errFilePtr = open(errName, O_RDONLY, 0);
- if (*errFilePtr < 0) {
- goto errFileError;
- }
- if (unlink(errName) == -1) {
- Jim_SetResultErrno(interp, "couldn't remove error file for command");
+ errorId = JimCreateTemp(interp, NULL);
+ if (errorId == JIM_BAD_FD) {
goto error;
}
+ *errFilePtr = JimDupFd(errorId);
}
- /*
- * Scan through the argc array, forking off a process for each
- * group of arguments between "|" arguments.
- */
- pidPtr = (int *)Jim_Alloc(cmdCount * sizeof(*pidPtr));
+ pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
for (i = 0; i < numPids; i++) {
- pidPtr[i] = -1;
+ pidPtr[i] = JIM_BAD_PID;
}
for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
int pipe_dup_err = 0;
- int origErrorId = errorId;
- char execerr[64];
- int execerrlen;
+ fdtype origErrorId = errorId;
for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
if (arg_array[lastArg][0] == '|') {
@@ -5656,53 +4371,44 @@ badargs:
break;
}
}
- /* Replace | with NULL for execv() */
+
arg_array[lastArg] = NULL;
if (lastArg == arg_count) {
outputId = lastOutputId;
}
else {
- if (pipe(pipeIds) != 0) {
+ if (JimPipe(pipeIds) != 0) {
Jim_SetResultErrno(interp, "couldn't create pipe");
goto error;
}
outputId = pipeIds[1];
}
- execName = arg_array[firstArg];
- /* Now fork the child */
+
- /*
- * Disable SIGPIPE signals: if they were allowed, this process
- * might go away unexpectedly if children misbehave. This code
- * can potentially interfere with other application code that
- * expects to handle SIGPIPEs; what's really needed is an
- * arbiter for signals to allow them to be "shared".
- */
+#ifdef __MINGW32__
+ pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
+ if (pid == JIM_BAD_PID) {
+ Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
+ goto error;
+ }
+#else
if (table->info == NULL) {
(void)signal(SIGPIPE, SIG_IGN);
}
- /* Need to do this befor vfork() */
+
if (pipe_dup_err) {
errorId = outputId;
}
- /* Need to prep an error message before vfork(), just in case */
- snprintf(execerr, sizeof(execerr), "couldn't exec \"%s\"", execName);
- execerrlen = strlen(execerr);
-
- /*
- * Make a new process and enter it into the table if the fork
- * is successful.
- */
pid = vfork();
if (pid < 0) {
Jim_SetResultErrno(interp, "couldn't fork child process");
goto error;
}
if (pid == 0) {
- /* Child */
+
if (inputId != -1) dup2(inputId, 0);
if (outputId != -1) dup2(outputId, 1);
@@ -5712,19 +4418,16 @@ badargs:
close(i);
}
- execvp(execName, &arg_array[firstArg]);
+ execvp(arg_array[firstArg], &arg_array[firstArg]);
- /* we really can ignore the error here! */
- IGNORE_RC(write(2, execerr, execerrlen));
+
+ fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
_exit(127);
}
+#endif
- /* parent */
+
- /*
- * Enlarge the wait table if there isn't enough space for a new
- * entry.
- */
if (table->used == table->size) {
table->size += WAIT_TABLE_GROW_BY;
table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
@@ -5736,74 +4439,61 @@ badargs:
pidPtr[numPids] = pid;
- /* Restore in case of pipe_dup_err */
+
errorId = origErrorId;
- /*
- * Close off our copies of file descriptors that were set up for
- * this child, then set up the input for the next child.
- */
- if (inputId != -1) {
- close(inputId);
+ if (inputId != JIM_BAD_FD) {
+ JimCloseFd(inputId);
}
- if (outputId != -1) {
- close(outputId);
+ if (outputId != JIM_BAD_FD) {
+ JimCloseFd(outputId);
}
inputId = pipeIds[0];
- pipeIds[0] = pipeIds[1] = -1;
+ pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
}
*pidArrayPtr = pidPtr;
- /*
- * All done. Cleanup open files lying around and then return.
- */
cleanup:
- if (inputId != -1) {
- close(inputId);
+ if (inputId != JIM_BAD_FD) {
+ JimCloseFd(inputId);
}
- if (lastOutputId != -1) {
- close(lastOutputId);
+ if (lastOutputId != JIM_BAD_FD) {
+ JimCloseFd(lastOutputId);
}
- if (errorId != -1) {
- close(errorId);
+ if (errorId != JIM_BAD_FD) {
+ JimCloseFd(errorId);
}
Jim_Free(arg_array);
- JimFreeEnv(interp, Jim_GetEnviron(), orig_environ);
- Jim_SetEnviron(orig_environ);
+ JimRestoreEnv(save_environ);
return numPids;
- /*
- * An error occurred. There could have been extra files open, such
- * as pipes between children. Clean them all up. Detach any child
- * processes that have been created.
- */
error:
- if ((inPipePtr != NULL) && (*inPipePtr != -1)) {
- close(*inPipePtr);
- *inPipePtr = -1;
+ if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
+ JimCloseFd(*inPipePtr);
+ *inPipePtr = JIM_BAD_FD;
}
- if ((outPipePtr != NULL) && (*outPipePtr != -1)) {
- close(*outPipePtr);
- *outPipePtr = -1;
+ if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
+ JimCloseFd(*outPipePtr);
+ *outPipePtr = JIM_BAD_FD;
}
- if ((errFilePtr != NULL) && (*errFilePtr != -1)) {
- close(*errFilePtr);
- *errFilePtr = -1;
+ if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
+ JimCloseFd(*errFilePtr);
+ *errFilePtr = JIM_BAD_FD;
}
- if (pipeIds[0] != -1) {
- close(pipeIds[0]);
+ if (pipeIds[0] != JIM_BAD_FD) {
+ JimCloseFd(pipeIds[0]);
}
- if (pipeIds[1] != -1) {
- close(pipeIds[1]);
+ if (pipeIds[1] != JIM_BAD_FD) {
+ JimCloseFd(pipeIds[1]);
}
if (pidPtr != NULL) {
for (i = 0; i < numPids; i++) {
- if (pidPtr[i] != -1) {
+ if (pidPtr[i] != JIM_BAD_PID) {
JimDetachPids(interp, 1, &pidPtr[i]);
}
}
@@ -5813,29 +4503,8 @@ badargs:
goto cleanup;
}
-/*
- *----------------------------------------------------------------------
- *
- * CleanupChildren --
- *
- * This is a utility procedure used to wait for child processes
- * to exit, record information about abnormal exits, and then
- * collect any stderr output generated by them.
- *
- * Results:
- * The return value is a standard Tcl result. If anything at
- * weird happened with the child processes, JIM_ERROR is returned
- * and a message is left in interp->result.
- *
- * Side effects:
- * If the last character of interp->result is a newline, then it
- * is removed. File errorId gets closed, and pidPtr is freed
- * back to the storage allocator.
- *
- *----------------------------------------------------------------------
- */
-
-static int Jim_CleanupChildren(Jim_Interp *interp, int numPids, int *pidPtr, int errorId)
+
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId)
{
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
int result = JIM_OK;
@@ -5843,7 +4512,7 @@ static int Jim_CleanupChildren(Jim_Interp *interp, int numPids, int *pidPtr, int
for (i = 0; i < numPids; i++) {
int waitStatus = 0;
- if (JimWaitPid(table, pidPtr[i], &waitStatus) > 0) {
+ if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) {
result = JIM_ERR;
}
@@ -5851,17 +4520,11 @@ static int Jim_CleanupChildren(Jim_Interp *interp, int numPids, int *pidPtr, int
}
Jim_Free(pidPtr);
- /*
- * Read the standard error file. If there's anything there,
- * then add the file's contents to the result
- * string.
- */
- if (errorId >= 0) {
+ if (errorId != JIM_BAD_FD) {
+ JimRewindFd(errorId);
if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
- Jim_SetResultErrno(interp, "error reading from stderr output file");
result = JIM_ERR;
}
- close(errorId);
}
JimTrimTrailingNewline(interp);
@@ -5873,78 +4536,464 @@ int Jim_execInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
return JIM_ERR;
-
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
return JIM_OK;
}
-#else
-/* e.g. Windows. Poor mans implementation of exec with system()
- * The system() call *may* do command line redirection, etc.
- * The standard output is not available.
- * Can't redirect filehandles.
- */
-static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
+#if defined(__MINGW32__)
+
+
+static SECURITY_ATTRIBUTES *JimStdSecAttrs(void)
+{
+ static SECURITY_ATTRIBUTES secAtts;
+
+ secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secAtts.lpSecurityDescriptor = NULL;
+ secAtts.bInheritHandle = TRUE;
+ return &secAtts;
+}
+
+static int JimErrno(void)
+{
+ switch (GetLastError()) {
+ case ERROR_FILE_NOT_FOUND: return ENOENT;
+ case ERROR_PATH_NOT_FOUND: return ENOENT;
+ case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
+ case ERROR_ACCESS_DENIED: return EACCES;
+ case ERROR_INVALID_HANDLE: return EBADF;
+ case ERROR_BAD_ENVIRONMENT: return E2BIG;
+ case ERROR_BAD_FORMAT: return ENOEXEC;
+ case ERROR_INVALID_ACCESS: return EACCES;
+ case ERROR_INVALID_DRIVE: return ENOENT;
+ case ERROR_CURRENT_DIRECTORY: return EACCES;
+ case ERROR_NOT_SAME_DEVICE: return EXDEV;
+ case ERROR_NO_MORE_FILES: return ENOENT;
+ case ERROR_WRITE_PROTECT: return EROFS;
+ case ERROR_BAD_UNIT: return ENXIO;
+ case ERROR_NOT_READY: return EBUSY;
+ case ERROR_BAD_COMMAND: return EIO;
+ case ERROR_CRC: return EIO;
+ case ERROR_BAD_LENGTH: return EIO;
+ case ERROR_SEEK: return EIO;
+ case ERROR_WRITE_FAULT: return EIO;
+ case ERROR_READ_FAULT: return EIO;
+ case ERROR_GEN_FAILURE: return EIO;
+ case ERROR_SHARING_VIOLATION: return EACCES;
+ case ERROR_LOCK_VIOLATION: return EACCES;
+ case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
+ case ERROR_HANDLE_DISK_FULL: return ENOSPC;
+ case ERROR_NOT_SUPPORTED: return ENODEV;
+ case ERROR_REM_NOT_LIST: return EBUSY;
+ case ERROR_DUP_NAME: return EEXIST;
+ case ERROR_BAD_NETPATH: return ENOENT;
+ case ERROR_NETWORK_BUSY: return EBUSY;
+ case ERROR_DEV_NOT_EXIST: return ENODEV;
+ case ERROR_TOO_MANY_CMDS: return EAGAIN;
+ case ERROR_ADAP_HDW_ERR: return EIO;
+ case ERROR_BAD_NET_RESP: return EIO;
+ case ERROR_UNEXP_NET_ERR: return EIO;
+ case ERROR_NETNAME_DELETED: return ENOENT;
+ case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
+ case ERROR_BAD_DEV_TYPE: return ENODEV;
+ case ERROR_BAD_NET_NAME: return ENOENT;
+ case ERROR_TOO_MANY_NAMES: return ENFILE;
+ case ERROR_TOO_MANY_SESS: return EIO;
+ case ERROR_SHARING_PAUSED: return EAGAIN;
+ case ERROR_REDIR_PAUSED: return EAGAIN;
+ case ERROR_FILE_EXISTS: return EEXIST;
+ case ERROR_CANNOT_MAKE: return ENOSPC;
+ case ERROR_OUT_OF_STRUCTURES: return ENFILE;
+ case ERROR_ALREADY_ASSIGNED: return EEXIST;
+ case ERROR_INVALID_PASSWORD: return EPERM;
+ case ERROR_NET_WRITE_FAULT: return EIO;
+ case ERROR_NO_PROC_SLOTS: return EAGAIN;
+ case ERROR_DISK_CHANGE: return EXDEV;
+ case ERROR_BROKEN_PIPE: return EPIPE;
+ case ERROR_OPEN_FAILED: return ENOENT;
+ case ERROR_DISK_FULL: return ENOSPC;
+ case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
+ case ERROR_INVALID_TARGET_HANDLE: return EBADF;
+ case ERROR_INVALID_NAME: return ENOENT;
+ case ERROR_PROC_NOT_FOUND: return ESRCH;
+ case ERROR_WAIT_NO_CHILDREN: return ECHILD;
+ case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
+ case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
+ case ERROR_SEEK_ON_DEVICE: return ESPIPE;
+ case ERROR_BUSY_DRIVE: return EAGAIN;
+ case ERROR_DIR_NOT_EMPTY: return EEXIST;
+ case ERROR_NOT_LOCKED: return EACCES;
+ case ERROR_BAD_PATHNAME: return ENOENT;
+ case ERROR_LOCK_FAILED: return EACCES;
+ case ERROR_ALREADY_EXISTS: return EEXIST;
+ case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
+ case ERROR_BAD_PIPE: return EPIPE;
+ case ERROR_PIPE_BUSY: return EAGAIN;
+ case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
+ case ERROR_DIRECTORY: return ENOTDIR;
+ }
+ return EINVAL;
+}
+
+static int JimPipe(fdtype pipefd[2])
+{
+ if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) {
+ return 0;
+ }
+ return -1;
+}
+
+static fdtype JimDupFd(fdtype infd)
{
- Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
- int i, j;
- int rc;
+ fdtype dupfd;
+ pidtype pid = GetCurrentProcess();
- /* Create a quoted command line */
- for (i = 1; i < argc; i++) {
- int len;
- const char *arg = Jim_GetString(argv[i], &len);
+ if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ return dupfd;
+ }
+ return JIM_BAD_FD;
+}
- if (i > 1) {
- Jim_AppendString(interp, cmdlineObj, " ", 1);
+static int JimRewindFd(fdtype fd)
+{
+ return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0;
+}
+
+#if 0
+static int JimReadFd(fdtype fd, char *buffer, size_t len)
+{
+ DWORD num;
+
+ if (ReadFile(fd, buffer, len, &num, NULL)) {
+ return num;
+ }
+ if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) {
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+static FILE *JimFdOpenForRead(fdtype fd)
+{
+ return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r");
+}
+
+static fdtype JimFileno(FILE *fh)
+{
+ return (fdtype)_get_osfhandle(_fileno(fh));
+}
+
+static fdtype JimOpenForRead(const char *filename)
+{
+ return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
+}
+
+static fdtype JimOpenForWrite(const char *filename, int append)
+{
+ return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
+}
+
+static FILE *JimFdOpenForWrite(fdtype fd)
+{
+ return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
+}
+
+static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
+{
+ DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
+ if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
+
+ return JIM_BAD_PID;
+ }
+ GetExitCodeProcess(pid, &ret);
+ *status = ret;
+ CloseHandle(pid);
+ return pid;
+}
+
+static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
+{
+ char name[MAX_PATH];
+ HANDLE handle;
+
+ if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
+ return JIM_BAD_FD;
+ }
+
+ handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(),
+ CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ goto error;
+ }
+
+ if (contents != NULL) {
+
+ FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
+ if (fh == NULL) {
+ goto error;
}
- if (strpbrk(arg, "\\\" ") == NULL) {
- /* No quoting required */
- Jim_AppendString(interp, cmdlineObj, arg, len);
+
+ if (fwrite(contents, strlen(contents), 1, fh) != 1) {
+ fclose(fh);
+ goto error;
+ }
+ fseek(fh, 0, SEEK_SET);
+ fclose(fh);
+ }
+ return handle;
+
+ error:
+ Jim_SetResultErrno(interp, "failed to create temp file");
+ CloseHandle(handle);
+ DeleteFile(name);
+ return JIM_BAD_FD;
+}
+
+static int
+JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
+{
+ int i;
+ static char extensions[][5] = {".exe", "", ".bat"};
+
+ for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
+ lstrcpyn(fullPath, originalName, MAX_PATH - 5);
+ lstrcat(fullPath, extensions[i]);
+
+ if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) {
continue;
}
+ if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) {
+ continue;
+ }
+ return 0;
+ }
- Jim_AppendString(interp, cmdlineObj, "\"", 1);
- for (j = 0; j < len; j++) {
- if (arg[j] == '\\' || arg[j] == '"') {
- Jim_AppendString(interp, cmdlineObj, "\\", 1);
+ return -1;
+}
+
+static char **JimSaveEnv(char **env)
+{
+ return env;
+}
+
+static void JimRestoreEnv(char **env)
+{
+ JimFreeEnv(env, NULL);
+}
+
+static Jim_Obj *
+JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
+{
+ char *start, *special;
+ int quote, i;
+
+ Jim_Obj *strObj = Jim_NewStringObj(interp, "", 0);
+
+ for (i = 0; argv[i]; i++) {
+ if (i > 0) {
+ Jim_AppendString(interp, strObj, " ", 1);
+ }
+
+ if (argv[i][0] == '\0') {
+ quote = 1;
+ }
+ else {
+ quote = 0;
+ for (start = argv[i]; *start != '\0'; start++) {
+ if (isspace(UCHAR(*start))) {
+ quote = 1;
+ break;
+ }
}
- Jim_AppendString(interp, cmdlineObj, &arg[j], 1);
}
- Jim_AppendString(interp, cmdlineObj, "\"", 1);
+ if (quote) {
+ Jim_AppendString(interp, strObj, "\"" , 1);
+ }
+
+ start = argv[i];
+ for (special = argv[i]; ; ) {
+ if ((*special == '\\') && (special[1] == '\\' ||
+ special[1] == '"' || (quote && special[1] == '\0'))) {
+ Jim_AppendString(interp, strObj, start, special - start);
+ start = special;
+ while (1) {
+ special++;
+ if (*special == '"' || (quote && *special == '\0')) {
+
+ Jim_AppendString(interp, strObj, start, special - start);
+ break;
+ }
+ if (*special != '\\') {
+ break;
+ }
+ }
+ Jim_AppendString(interp, strObj, start, special - start);
+ start = special;
+ }
+ if (*special == '"') {
+ if (special == start) {
+ Jim_AppendString(interp, strObj, "\"", 1);
+ }
+ else {
+ Jim_AppendString(interp, strObj, start, special - start);
+ }
+ Jim_AppendString(interp, strObj, "\\\"", 2);
+ start = special + 1;
+ }
+ if (*special == '\0') {
+ break;
+ }
+ special++;
+ }
+ Jim_AppendString(interp, strObj, start, special - start);
+ if (quote) {
+ Jim_AppendString(interp, strObj, "\"", 1);
+ }
}
- rc = system(Jim_String(cmdlineObj));
+ return strObj;
+}
- Jim_FreeNewObj(interp, cmdlineObj);
+static pidtype
+JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
+{
+ STARTUPINFO startInfo;
+ PROCESS_INFORMATION procInfo;
+ HANDLE hProcess, h;
+ char execPath[MAX_PATH];
+ char *originalName;
+ pidtype pid = JIM_BAD_PID;
+ Jim_Obj *cmdLineObj;
- if (rc) {
- Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
- Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc));
- Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
- return JIM_ERR;
+ if (JimWinFindExecutable(argv[0], execPath) < 0) {
+ return JIM_BAD_PID;
}
+ originalName = argv[0];
+ argv[0] = execPath;
- return JIM_OK;
+ hProcess = GetCurrentProcess();
+ cmdLineObj = JimWinBuildCommandLine(interp, argv);
+
+
+ ZeroMemory(&startInfo, sizeof(startInfo));
+ startInfo.cb = sizeof(startInfo);
+ startInfo.dwFlags = STARTF_USESTDHANDLES;
+ startInfo.hStdInput = INVALID_HANDLE_VALUE;
+ startInfo.hStdOutput= INVALID_HANDLE_VALUE;
+ startInfo.hStdError = INVALID_HANDLE_VALUE;
+
+ if (inputId == JIM_BAD_FD) {
+ if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
+ CloseHandle(h);
+ }
+ } else {
+ DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ }
+ if (startInfo.hStdInput == JIM_BAD_FD) {
+ goto end;
+ }
+
+ if (outputId == JIM_BAD_FD) {
+ startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
+ JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ } else {
+ DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ }
+ if (startInfo.hStdOutput == JIM_BAD_FD) {
+ goto end;
+ }
+
+ if (errorId == JIM_BAD_FD) {
+
+ startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
+ JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ } else {
+ DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ }
+ if (startInfo.hStdError == JIM_BAD_FD) {
+ goto end;
+ }
+
+ if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
+ 0, env, NULL, &startInfo, &procInfo)) {
+ goto end;
+ }
+
+
+ WaitForInputIdle(procInfo.hProcess, 5000);
+ CloseHandle(procInfo.hThread);
+
+ pid = procInfo.hProcess;
+
+ end:
+ Jim_FreeNewObj(interp, cmdLineObj);
+ if (startInfo.hStdInput != JIM_BAD_FD) {
+ CloseHandle(startInfo.hStdInput);
+ }
+ if (startInfo.hStdOutput != JIM_BAD_FD) {
+ CloseHandle(startInfo.hStdOutput);
+ }
+ if (startInfo.hStdError != JIM_BAD_FD) {
+ CloseHandle(startInfo.hStdError);
+ }
+ return pid;
}
+#else
-int Jim_execInit(Jim_Interp *interp)
+static int JimOpenForWrite(const char *filename, int append)
{
- if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
- return JIM_ERR;
+ return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
+}
- Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
- return JIM_OK;
+static int JimRewindFd(int fd)
+{
+ return lseek(fd, 0L, SEEK_SET);
+}
+
+static int JimCreateTemp(Jim_Interp *interp, const char *contents)
+{
+ char inName[] = "/tmp/tcl.tmp.XXXXXX";
+
+ int fd = mkstemp(inName);
+ if (fd == JIM_BAD_FD) {
+ Jim_SetResultErrno(interp, "couldn't create temp file");
+ return -1;
+ }
+ if (contents) {
+ int length = strlen(contents);
+ if (unlink(inName) == -1 || write(fd, contents, length) != length) {
+ Jim_SetResultErrno(interp, "couldn't write temp file");
+ close(fd);
+ return -1;
+ }
+ lseek(fd, 0L, SEEK_SET);
+ }
+ return fd;
+}
+
+static char **JimSaveEnv(char **env)
+{
+ char **saveenv = Jim_GetEnviron();
+ Jim_SetEnviron(env);
+ return saveenv;
+}
+
+static void JimRestoreEnv(char **env)
+{
+ JimFreeEnv(Jim_GetEnviron(), env);
+ Jim_SetEnviron(env);
}
#endif
+#endif
+
-/*
- * tcl_clock.c
- *
- * Implements the clock command
- */
-/* For strptime() */
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif
@@ -5958,7 +5007,7 @@ int Jim_execInit(Jim_Interp *interp)
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- /* How big is big enough? */
+
char buf[100];
time_t t;
long seconds;
@@ -5996,7 +5045,7 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return -1;
}
- /* Initialise with the current date/time */
+
localtime_r(&now, &tm);
pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
@@ -6005,7 +5054,7 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
- /* Now convert into a time_t */
+
Jim_SetResultInt(interp, mktime(&tm));
return JIM_OK;
@@ -6094,50 +5143,6 @@ int Jim_clockInit(Jim_Interp *interp)
return JIM_OK;
}
-/*
- * Implements the array command for jim
- *
- * (c) 2008 Steve Bennett <steveb@workware.net.au>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on code originally from Tcl 6.7:
- *
- * Copyright 1987-1991 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
#include <limits.h>
#include <stdlib.h>
@@ -6149,7 +5154,7 @@ int Jim_clockInit(Jim_Interp *interp)
static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- /* Just a regular [info exists] */
+
Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
return JIM_OK;
}
@@ -6172,7 +5177,7 @@ static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
all = 1;
}
- /* If it is a dictionary or list with an even number of elements, nothing else to do */
+
if (all) {
if (Jim_IsDict(objPtr) || (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0)) {
Jim_SetResult(interp, objPtr);
@@ -6189,11 +5194,11 @@ static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
if (all) {
- /* Return the whole array */
+
Jim_SetResult(interp, dictObj);
}
else {
- /* Only return the matching values */
+
resultObj = Jim_NewListObj(interp, NULL, 0);
for (i = 0; i < len; i += 2) {
@@ -6231,7 +5236,7 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_Obj **dictValuesObj;
if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
- /* Unset the whole array */
+
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
return JIM_OK;
}
@@ -6246,7 +5251,7 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
- /* Create a new object with the values which don't match */
+
resultObj = Jim_NewDictObj(interp, NULL, 0);
for (i = 0; i < len; i += 2) {
@@ -6265,7 +5270,7 @@ static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_Obj *objPtr;
int len = 0;
- /* Not found means zero length */
+
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
if (objPtr) {
len = Jim_DictSize(interp, objPtr);
@@ -6287,7 +5292,7 @@ static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_Obj *listObj = argv[1];
if (Jim_GetVariable(interp, argv[0], JIM_NONE) == NULL) {
- /* Doesn't exist, so just set the list directly */
+
return Jim_SetVariable(interp, argv[0], listObj);
}
@@ -6303,7 +5308,7 @@ static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
- rc = Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj);
+ rc = Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj, JIM_ERRMSG);
}
return rc;
@@ -6391,49 +5396,7 @@ Jim_tclcompatInit(interp);
return JIM_OK;
}
-/* Jim - A small embeddable Tcl interpreter
- *
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008,2009 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
- * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
- * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
- * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
- * Copyright 2008 Steve Bennett <steveb@workware.net.au>
- * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
- * Copyright 2009 Zachary T Welch zw@superlucidity.net
- * Copyright 2009 David Brownell
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- **/
-#define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */
+#define JIM_OPTIMIZATION
#include <stdio.h>
#include <stdlib.h>
@@ -6458,13 +5421,13 @@ return JIM_OK;
#include <crt_externs.h>
#endif
-/* For INFINITY, even if math functions are not enabled */
+
#include <math.h>
-/* We may decide to switch to using $[...] after all, so leave it as an option */
-/*#define EXPRSUGAR_BRACKET*/
-/* For the no-autoconf case */
+
+
+
#ifndef TCL_LIBRARY
#define TCL_LIBRARY "."
#endif
@@ -6478,12 +5441,12 @@ return JIM_OK;
#define TCL_PLATFORM_PATH_SEPARATOR ":"
#endif
-/*#define DEBUG_SHOW_SCRIPT*/
-/*#define DEBUG_SHOW_SCRIPT_TOKENS*/
-/*#define DEBUG_SHOW_SUBST*/
-/*#define DEBUG_SHOW_EXPR*/
-/*#define DEBUG_SHOW_EXPR_TOKENS*/
-/*#define JIM_DEBUG_GC*/
+
+
+
+
+
+
#ifdef JIM_MAINTAINER
#define JIM_DEBUG_COMMAND
#define JIM_DEBUG_PANIC
@@ -6492,23 +5455,15 @@ return JIM_OK;
const char *jim_tt_name(int type);
#ifdef JIM_DEBUG_PANIC
-static void JimPanicDump(int panic_condition, Jim_Interp *interp, const char *fmt, ...);
+static void JimPanicDump(int panic_condition, const char *fmt, ...);
#define JimPanic(X) JimPanicDump X
#else
#define JimPanic(X)
#endif
-/* -----------------------------------------------------------------------------
- * Global variables
- * ---------------------------------------------------------------------------*/
-/* A shared empty string for the objects string representation.
- * Jim_InvalidateStringRep knows about it and doesn't try to free it. */
static char JimEmptyStringRep[] = "";
-/* -----------------------------------------------------------------------------
- * Required prototypes of not exported functions
- * ---------------------------------------------------------------------------*/
static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
@@ -6518,10 +5473,10 @@ static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
const char *prefix, const char *const *tablePtr, const char *name);
static void JimDeleteLocalProcs(Jim_Interp *interp);
-static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filename, int linenr,
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr,
int argc, Jim_Obj *const *argv);
static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
- const char *filename, int linenr);
+ Jim_Obj *fileNameObj, int linenr);
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);
@@ -6531,10 +5486,10 @@ static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
static const Jim_HashTableType JimVariablesHashTableType;
-/* Fast access to the int (wide) value of an object which is known to be of int type */
+
#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue
-#define JimObjTypeName(O) (objPtr->typePtr ? objPtr->typePtr->name : "none")
+#define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none")
static int utf8_tounicode_case(const char *s, int *uc, int upper)
{
@@ -6545,26 +5500,10 @@ static int utf8_tounicode_case(const char *s, int *uc, int upper)
return l;
}
-/* These can be used in addition to JIM_CASESENS/JIM_NOCASE */
+
#define JIM_CHARSET_SCAN 2
#define JIM_CHARSET_GLOB 0
-/**
- * pattern points to a string like "[^a-z\ub5]"
- *
- * The pattern may contain trailing chars, which are ignored.
- *
- * The pattern is matched against unicode char 'c'.
- *
- * If (flags & JIM_NOCASE), case is ignored when matching.
- * If (flags & JIM_CHARSET_SCAN), the considers ^ and ] special at the start
- * of the charset, per scan, rather than glob/string match.
- *
- * If the unicode char 'c' matches that set, returns a pointer to the ']' character,
- * or the null character if the ']' is missing.
- *
- * Returns NULL on no match.
- */
static const char *JimCharsetMatch(const char *pattern, int c, int flags)
{
int not = 0;
@@ -6583,30 +5522,30 @@ static const char *JimCharsetMatch(const char *pattern, int c, int flags)
pattern++;
}
- /* Special case. If the first char is ']', it is part of the set */
+
if (*pattern == ']') {
goto first;
}
}
while (*pattern && *pattern != ']') {
- /* Exact match */
+
if (pattern[0] == '\\') {
first:
pattern += utf8_tounicode_case(pattern, &pchar, nocase);
}
else {
- /* Is this a range? a-z */
+
int start;
int end;
pattern += utf8_tounicode_case(pattern, &start, nocase);
if (pattern[0] == '-' && pattern[1]) {
- /* skip '-' */
+
pattern += utf8_tounicode(pattern, &pchar);
pattern += utf8_tounicode_case(pattern, &end, nocase);
- /* Handle reversed range too */
+
if ((c >= start && c <= end) || (c >= end && c <= start)) {
match = 1;
}
@@ -6626,11 +5565,8 @@ first:
return match ? pattern : NULL;
}
-/* Glob-style pattern matching. */
-/* Note: string *must* be valid UTF-8 sequences
- * slen is a char length, not byte counts.
- */
+
static int GlobMatch(const char *pattern, const char *string, int nocase)
{
int c;
@@ -6643,15 +5579,15 @@ static int GlobMatch(const char *pattern, const char *string, int nocase)
}
pattern++;
if (!pattern[0]) {
- return 1; /* match */
+ return 1;
}
while (*string) {
- /* Recursive call - Does the remaining pattern match anywhere? */
+
if (GlobMatch(pattern, string, nocase))
- return 1; /* match */
+ return 1;
string += utf8_tounicode(string, &c);
}
- return 0; /* no match */
+ return 0;
case '?':
string += utf8_tounicode(string, &c);
@@ -6664,7 +5600,7 @@ static int GlobMatch(const char *pattern, const char *string, int nocase)
return 0;
}
if (!*pattern) {
- /* Ran out of pattern (no ']') */
+
continue;
}
break;
@@ -6673,7 +5609,7 @@ static int GlobMatch(const char *pattern, const char *string, int nocase)
if (pattern[1]) {
pattern++;
}
- /* fall through */
+
default:
string += utf8_tounicode_case(string, &c, nocase);
utf8_tounicode_case(pattern, &pchar, nocase);
@@ -6701,11 +5637,6 @@ static int JimStringMatch(Jim_Interp *interp, Jim_Obj *patternObj, const char *s
return GlobMatch(Jim_String(patternObj), string, nocase);
}
-/**
- * string comparison works on binary data.
- *
- * Note that the lengths are byte lengths, not char lengths.
- */
static int JimStringCompare(const char *s1, int l1, const char *s2, int l2)
{
if (l1 < l2) {
@@ -6719,12 +5650,6 @@ static int JimStringCompare(const char *s1, int l1, const char *s2, int l2)
}
}
-/**
- * No-case version.
- *
- * If maxchars is -1, compares to end of string.
- * Otherwise compares at most 'maxchars' characters.
- */
static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars)
{
while (*s1 && *s2 && maxchars) {
@@ -6739,7 +5664,7 @@ static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars)
if (!maxchars) {
return 0;
}
- /* One string or both terminated */
+
if (*s1) {
return 1;
}
@@ -6749,9 +5674,6 @@ static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars)
return 0;
}
-/* Search 's1' inside 's2', starting to search from char 'index' of 's2'.
- * The index of the first occurrence of s1 in s2 is returned.
- * If s1 is not found inside s2, -1 is returned. */
static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx)
{
int i;
@@ -6776,9 +5698,6 @@ static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int id
return -1;
}
-/**
- * Note: Lengths and return value are in bytes, not chars.
- */
static int JimStringLast(const char *s1, int l1, const char *s2, int l2)
{
const char *p;
@@ -6786,7 +5705,7 @@ static int JimStringLast(const char *s1, int l1, const char *s2, int l2)
if (!l1 || !l2 || l1 > l2)
return -1;
- /* Now search for the needle */
+
for (p = s2 + l2 - 1; p != s2 - 1; p--) {
if (*p == *s1 && memcmp(s1, p, l1) == 0) {
return p - s2;
@@ -6796,9 +5715,6 @@ static int JimStringLast(const char *s1, int l1, const char *s2, int l2)
}
#ifdef JIM_UTF8
-/**
- * Note: Lengths and return value are in chars.
- */
static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2)
{
int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2));
@@ -6816,13 +5732,6 @@ int Jim_WideToString(char *buf, jim_wide wideValue)
return sprintf(buf, fmt, wideValue);
}
-/**
- * After an strtol()/strtod()-like conversion,
- * check whether something was converted and that
- * the only thing left is white space.
- *
- * Returns JIM_OK or JIM_ERR.
- */
static int JimCheckConversion(const char *str, const char *endptr)
{
if (str[0] == '\0' || str == endptr) {
@@ -6856,16 +5765,14 @@ int Jim_DoubleToString(char *buf, double doubleValue)
len = sprintf(buf, "%.12g", doubleValue);
- /* Add a final ".0" if it's a number. But not
- * for NaN or InF */
while (*buf) {
if (*buf == '.' || isalpha(UCHAR(*buf))) {
- /* inf -> Inf, nan -> Nan */
+
if (*buf == 'i' || *buf == 'n') {
*buf = toupper(UCHAR(*buf));
}
if (*buf == 'I') {
- /* Infinity -> Inf */
+
buf[3] = '\0';
len = buf - buf0 + 3;
}
@@ -6885,7 +5792,7 @@ int Jim_StringToDouble(const char *str, double *doublePtr)
{
char *endptr;
- /* Callers can check for underflow via ERANGE */
+
errno = 0;
*doublePtr = strtod(str, &endptr);
@@ -6905,14 +5812,8 @@ static jim_wide JimPowWide(jim_wide b, jim_wide e)
return res;
}
-/* -----------------------------------------------------------------------------
- * Special functions
- * ---------------------------------------------------------------------------*/
#ifdef JIM_DEBUG_PANIC
-/* Note that 'interp' may be NULL if not available in the
- * context of the panic. It's only useful to get the error
- * file descriptor, it will default to stderr otherwise. */
-void JimPanicDump(int condition, Jim_Interp *interp, const char *fmt, ...)
+void JimPanicDump(int condition, const char *fmt, ...)
{
va_list ap;
@@ -6921,9 +5822,7 @@ void JimPanicDump(int condition, Jim_Interp *interp, const char *fmt, ...)
}
va_start(ap, fmt);
- /*
- * Send it here first.. Assuming STDIO still works
- */
+
fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, JIM_NL JIM_NL);
@@ -6948,9 +5847,6 @@ void JimPanicDump(int condition, Jim_Interp *interp, const char *fmt, ...)
}
#endif
-/* -----------------------------------------------------------------------------
- * Memory allocation
- * ---------------------------------------------------------------------------*/
void *Jim_Alloc(int size)
{
@@ -6977,15 +5873,12 @@ char *Jim_StrDupLen(const char *s, int l)
char *copy = Jim_Alloc(l + 1);
memcpy(copy, s, l + 1);
- copy[l] = 0; /* Just to be sure, original could be substring */
+ copy[l] = 0;
return copy;
}
-/* -----------------------------------------------------------------------------
- * Time related functions
- * ---------------------------------------------------------------------------*/
-/* Returns microseconds of CPU used since start. */
+
static jim_wide JimClock(void)
{
struct timeval tv;
@@ -6994,18 +5887,15 @@ static jim_wide JimClock(void)
return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec;
}
-/* -----------------------------------------------------------------------------
- * Hash Tables
- * ---------------------------------------------------------------------------*/
-/* -------------------------- private prototypes ---------------------------- */
+
static int JimExpandHashTableIfNeeded(Jim_HashTable *ht);
static unsigned int JimHashTableNextPower(unsigned int size);
static int JimInsertHashEntry(Jim_HashTable *ht, const void *key);
-/* -------------------------- hash functions -------------------------------- */
-/* Thomas Wang's 32 bit Mix Function */
+
+
unsigned int Jim_IntHashFunction(unsigned int key)
{
key += ~(key << 15);
@@ -7017,8 +5907,6 @@ unsigned int Jim_IntHashFunction(unsigned int key)
return key;
}
-/* Generic hash function (we are using to multiply by 9 and add the byte
- * as Tcl) */
unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
{
unsigned int h = 0;
@@ -7028,10 +5916,8 @@ unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
return h;
}
-/* ----------------------------- API implementation ------------------------- */
-/* reset a hashtable already initialized with ht_init().
- * NOTE: This function should only called by ht_destroy(). */
+
static void JimResetHashTable(Jim_HashTable *ht)
{
ht->table = NULL;
@@ -7041,7 +5927,7 @@ static void JimResetHashTable(Jim_HashTable *ht)
ht->collisions = 0;
}
-/* Initialize the hash table */
+
int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
{
JimResetHashTable(ht);
@@ -7050,8 +5936,6 @@ int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *pr
return JIM_OK;
}
-/* Resize the table to the minimal size that contains all the elements,
- * but with the invariant of a USER/BUCKETS ration near to <= 1 */
int Jim_ResizeHashTable(Jim_HashTable *ht)
{
int minimal = ht->used;
@@ -7061,14 +5945,12 @@ int Jim_ResizeHashTable(Jim_HashTable *ht)
return Jim_ExpandHashTable(ht, minimal);
}
-/* Expand or create the hashtable */
+
int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
{
- Jim_HashTable n; /* the new hashtable */
+ Jim_HashTable n;
unsigned int realsize = JimHashTableNextPower(size), i;
- /* the size is invalid if it is smaller than the number of
- * elements already inside the hashtable */
if (ht->used >= size)
return JIM_ERR;
@@ -7077,89 +5959,82 @@ int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
n.sizemask = realsize - 1;
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
- /* Initialize all the pointers to NULL */
+
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
- /* Copy all the elements from the old to the new table:
- * note that if the old hash table is empty ht->size is zero,
- * so Jim_ExpandHashTable just creates an hash table. */
n.used = ht->used;
- for (i = 0; i < ht->size && ht->used > 0; i++) {
+ for (i = 0; ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
if (ht->table[i] == NULL)
continue;
- /* For each hash entry on this slot... */
+
he = ht->table[i];
while (he) {
unsigned int h;
nextHe = he->next;
- /* Get the new element index */
+
h = Jim_HashKey(ht, he->key) & n.sizemask;
he->next = n.table[h];
n.table[h] = he;
ht->used--;
- /* Pass to the next element */
+
he = nextHe;
}
}
assert(ht->used == 0);
Jim_Free(ht->table);
- /* Remap the new hashtable in the old */
+
*ht = n;
return JIM_OK;
}
-/* Add an element to the target hash table */
+
int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
int idx;
Jim_HashEntry *entry;
- /* Get the index of the new element, or -1 if
- * the element already exists. */
if ((idx = JimInsertHashEntry(ht, key)) == -1)
return JIM_ERR;
- /* Allocates the memory and stores key */
+
entry = Jim_Alloc(sizeof(*entry));
entry->next = ht->table[idx];
ht->table[idx] = entry;
- /* Set the hash entry fields. */
+
Jim_SetHashKey(ht, entry, key);
Jim_SetHashVal(ht, entry, val);
ht->used++;
return JIM_OK;
}
-/* Add an element, discarding the old if the key already exists */
+
int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
Jim_HashEntry *entry;
- /* Try to add the element. If the key
- * does not exists Jim_AddHashEntry will suceed. */
if (Jim_AddHashEntry(ht, key, val) == JIM_OK)
return JIM_OK;
- /* It already exists, get the entry */
+
entry = Jim_FindHashEntry(ht, key);
- /* Free the old value and set the new one */
+
Jim_FreeEntryVal(ht, entry);
Jim_SetHashVal(ht, entry, val);
return JIM_OK;
}
-/* Search and remove an element */
+
int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
{
unsigned int h;
Jim_HashEntry *he, *prevHe;
- if (ht->size == 0)
+ if (ht->used == 0)
return JIM_ERR;
h = Jim_HashKey(ht, key) & ht->sizemask;
he = ht->table[h];
@@ -7167,7 +6042,7 @@ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
prevHe = NULL;
while (he) {
if (Jim_CompareHashKeys(ht, key, he->key)) {
- /* Unlink the element from the list */
+
if (prevHe)
prevHe->next = he->next;
else
@@ -7181,16 +6056,16 @@ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
prevHe = he;
he = he->next;
}
- return JIM_ERR; /* not found */
+ return JIM_ERR;
}
-/* Destroy an entire hash table */
+
int Jim_FreeHashTable(Jim_HashTable *ht)
{
unsigned int i;
- /* Free all the elements */
- for (i = 0; i < ht->size && ht->used > 0; i++) {
+
+ for (i = 0; ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
if ((he = ht->table[i]) == NULL)
@@ -7204,11 +6079,11 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
he = nextHe;
}
}
- /* Free the table and the allocated cache structure */
+
Jim_Free(ht->table);
- /* Re-initialize the table */
+
JimResetHashTable(ht);
- return JIM_OK; /* never fails */
+ return JIM_OK;
}
Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
@@ -7216,7 +6091,7 @@ Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
Jim_HashEntry *he;
unsigned int h;
- if (ht->size == 0)
+ if (ht->used == 0)
return NULL;
h = Jim_HashKey(ht, key) & ht->sizemask;
he = ht->table[h];
@@ -7252,8 +6127,6 @@ Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
iter->entry = iter->nextEntry;
}
if (iter->entry) {
- /* We need to save the 'next' here, the iterator user
- * may delete the entry we are returning. */
iter->nextEntry = iter->entry->next;
return iter->entry;
}
@@ -7261,13 +6134,11 @@ Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
return NULL;
}
-/* ------------------------- private functions ------------------------------ */
-/* Expand the hash table if needed */
+
+
static int JimExpandHashTableIfNeeded(Jim_HashTable *ht)
{
- /* If the hash table is empty expand it to the intial size,
- * if the table is "full" dobule its size. */
if (ht->size == 0)
return Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE);
if (ht->size == ht->used)
@@ -7275,7 +6146,7 @@ static int JimExpandHashTableIfNeeded(Jim_HashTable *ht)
return JIM_OK;
}
-/* Our hash table capability is a power of two */
+
static unsigned int JimHashTableNextPower(unsigned int size)
{
unsigned int i = JIM_HT_INITIAL_SIZE;
@@ -7289,20 +6160,17 @@ static unsigned int JimHashTableNextPower(unsigned int size)
}
}
-/* Returns the index of a free slot that can be populated with
- * an hash entry for the given 'key'.
- * If the key already exists, -1 is returned. */
static int JimInsertHashEntry(Jim_HashTable *ht, const void *key)
{
unsigned int h;
Jim_HashEntry *he;
- /* Expand the hashtable if needed */
+
if (JimExpandHashTableIfNeeded(ht) == JIM_ERR)
return -1;
- /* Compute the key hash value */
+
h = Jim_HashKey(ht, key) & ht->sizemask;
- /* Search if this slot does not already contain the given key */
+
he = ht->table[h];
while (he) {
if (Jim_CompareHashKeys(ht, key, he->key))
@@ -7312,7 +6180,7 @@ static int JimInsertHashEntry(Jim_HashTable *ht, const void *key)
return h;
}
-/* ----------------------- StringCopy Hash Table Type ------------------------*/
+
static unsigned int JimStringCopyHTHashFunction(const void *key)
{
@@ -7354,47 +6222,43 @@ static void JimStringCopyHTKeyDestructor(void *privdata, const void *key)
{
JIM_NOTUSED(privdata);
- Jim_Free((void *)key); /* ATTENTION: const cast */
+ Jim_Free((void *)key);
}
static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val)
{
JIM_NOTUSED(privdata);
- Jim_Free((void *)val); /* ATTENTION: const cast */
+ Jim_Free((void *)val);
}
#if 0
static Jim_HashTableType JimStringCopyHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- NULL /* val destructor */
+ JimStringCopyHTHashFunction,
+ JimStringCopyHTKeyDup,
+ NULL,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ NULL
};
#endif
-/* This is like StringCopy but does not auto-duplicate the key.
- * It's used for intepreter's shared strings. */
static const Jim_HashTableType JimSharedStringsHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- NULL, /* key dup */
- NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- NULL /* val destructor */
+ JimStringCopyHTHashFunction,
+ NULL,
+ NULL,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ NULL
};
-/* This is like StringCopy but also automatically handle dynamic
- * allocated C strings as values. */
static const Jim_HashTableType JimStringKeyValCopyHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTKeyDup, /* key dup */
- JimStringKeyValCopyHTValDup, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- JimStringKeyValCopyHTValDestructor, /* val destructor */
+ JimStringCopyHTHashFunction,
+ JimStringCopyHTKeyDup,
+ JimStringKeyValCopyHTValDup,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ JimStringKeyValCopyHTValDestructor,
};
typedef struct AssocDataValue
@@ -7413,18 +6277,14 @@ static void JimAssocDataHashTableValueDestructor(void *privdata, void *data)
}
static const Jim_HashTableType JimAssocDataHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- JimAssocDataHashTableValueDestructor /* val destructor */
+ JimStringCopyHTHashFunction,
+ JimStringCopyHTKeyDup,
+ NULL,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ JimAssocDataHashTableValueDestructor
};
-/* -----------------------------------------------------------------------------
- * Stack - This is a simple generic stack implementation. It is used for
- * example in the 'expr' expression compiler.
- * ---------------------------------------------------------------------------*/
void Jim_InitStack(Jim_Stack *stack)
{
stack->len = 0;
@@ -7477,67 +6337,59 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
freeFunc(stack->vector[i]);
}
-/* -----------------------------------------------------------------------------
- * Parser
- * ---------------------------------------------------------------------------*/
-/* Token types */
-#define JIM_TT_NONE 0 /* No token returned */
-#define JIM_TT_STR 1 /* simple string */
-#define JIM_TT_ESC 2 /* string that needs escape chars conversion */
-#define JIM_TT_VAR 3 /* var substitution */
-#define JIM_TT_DICTSUGAR 4 /* Syntax sugar for [dict get], $foo(bar) */
-#define JIM_TT_CMD 5 /* command substitution */
-/* Note: Keep these three together for TOKEN_IS_SEP() */
-#define JIM_TT_SEP 6 /* word separator. arg is # of tokens. -ve if {*} */
-#define JIM_TT_EOL 7 /* line separator */
-#define JIM_TT_EOF 8 /* end of script */
-#define JIM_TT_LINE 9 /* special 'start-of-line' token. arg is # of arguments to the command. -ve if {*} */
-#define JIM_TT_WORD 10 /* special 'start-of-word' token. arg is # of tokens to combine. -ve if {*} */
+#define JIM_TT_NONE 0
+#define JIM_TT_STR 1
+#define JIM_TT_ESC 2
+#define JIM_TT_VAR 3
+#define JIM_TT_DICTSUGAR 4
+#define JIM_TT_CMD 5
+
+#define JIM_TT_SEP 6
+#define JIM_TT_EOL 7
+#define JIM_TT_EOF 8
+
+#define JIM_TT_LINE 9
+#define JIM_TT_WORD 10
+
-/* Additional token types needed for expressions */
#define JIM_TT_SUBEXPR_START 11
#define JIM_TT_SUBEXPR_END 12
#define JIM_TT_EXPR_INT 13
#define JIM_TT_EXPR_DOUBLE 14
-#define JIM_TT_EXPRSUGAR 15 /* $(expression) */
+#define JIM_TT_EXPRSUGAR 15
+
-/* Operator token types start here */
#define JIM_TT_EXPR_OP 20
#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
-/* Parser states */
-#define JIM_PS_DEF 0 /* Default state */
-#define JIM_PS_QUOTE 1 /* Inside "" */
-#define JIM_PS_DICTSUGAR 2 /* Tokenising abc(def) into 4 separate tokens */
-/* Parser context structure. The same context is used both to parse
- * Tcl scripts and lists. */
+#define JIM_PS_DEF 0
+#define JIM_PS_QUOTE 1
+#define JIM_PS_DICTSUGAR 2
+
struct JimParserCtx
{
- const char *p; /* Pointer to the point of the program we are parsing */
- int len; /* Remaining length */
- int linenr; /* Current line number */
+ const char *p;
+ int len;
+ int linenr;
const char *tstart;
- const char *tend; /* Returned token is at tstart-tend in 'prg'. */
- int tline; /* Line number of the returned token */
- int tt; /* Token type */
- int eof; /* Non zero if EOF condition is true. */
- int state; /* Parser state */
- int comment; /* Non zero if the next chars may be a comment. */
- char missing; /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */
- int missingline; /* Line number starting the missing token */
+ const char *tend;
+ int tline;
+ int tt;
+ int eof;
+ int state;
+ int comment;
+ char missing;
+ int missingline;
};
-/**
- * Results of missing quotes, braces, etc. from parsing.
- */
struct JimParseResult {
- char missing; /* From JimParserCtx.missing */
- int line; /* From JimParserCtx.missingline */
+ char missing;
+ int line;
};
static int JimParseScript(struct JimParserCtx *pc);
@@ -7554,9 +6406,6 @@ static int JimParseSubQuote(struct JimParserCtx *pc);
static void JimParseSubCmd(struct JimParserCtx *pc);
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
-/* Initialize a parser context.
- * 'prg' is a pointer to the program text, linenr is the line
- * number of the first line contained in the program. */
static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
{
pc->p = prg;
@@ -7575,7 +6424,7 @@ static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int
static int JimParseScript(struct JimParserCtx *pc)
{
- while (1) { /* the while is used to reiterate with continue if needed */
+ while (1) {
if (!pc->len) {
pc->tstart = pc->p;
pc->tend = pc->p - 1;
@@ -7679,39 +6528,12 @@ static int JimParseEol(struct JimParserCtx *pc)
return JIM_OK;
}
-/*
-** Here are the rules for parsing:
-** {braced expression}
-** - Count open and closing braces
-** - Backslash escapes meaning of braces
-**
-** "quoted expression"
-** - First double quote at start of word terminates the expression
-** - Backslash escapes quote and bracket
-** - [commands brackets] are counted/nested
-** - command rules apply within [brackets], not quoting rules (i.e. quotes have their own rules)
-**
-** [command expression]
-** - Count open and closing brackets
-** - Backslash escapes quote, bracket and brace
-** - [commands brackets] are counted/nested
-** - "quoted expressions" are parsed according to quoting rules
-** - {braced expressions} are parsed according to brace rules
-**
-** For everything, backslash escapes the next char, newline increments current line
-*/
-
-/**
- * Parses a braced expression starting at pc->p.
- *
- * Positions the parser at the end of the braced expression,
- * sets pc->tend and possibly pc->missing.
- */
+
static void JimParseSubBrace(struct JimParserCtx *pc)
{
int level = 1;
- /* Skip the brace */
+
pc->p++;
pc->len--;
while (pc->len) {
@@ -7750,22 +6572,12 @@ static void JimParseSubBrace(struct JimParserCtx *pc)
pc->tend = pc->p - 1;
}
-/**
- * Parses a quoted expression starting at pc->p.
- *
- * Positions the parser at the end of the quoted expression,
- * sets pc->tend and possibly pc->missing.
- *
- * Returns the type of the token of the string,
- * either JIM_TT_ESC (if it contains values which need to be [subst]ed)
- * or JIM_TT_STR.
- */
static int JimParseSubQuote(struct JimParserCtx *pc)
{
int tt = JIM_TT_STR;
int line = pc->tline;
- /* Skip the quote */
+
pc->p++;
pc->len--;
while (pc->len) {
@@ -7808,19 +6620,13 @@ static int JimParseSubQuote(struct JimParserCtx *pc)
return tt;
}
-/**
- * Parses a [command] expression starting at pc->p.
- *
- * Positions the parser at the end of the command expression,
- * sets pc->tend and possibly pc->missing.
- */
static void JimParseSubCmd(struct JimParserCtx *pc)
{
int level = 1;
int startofword = 1;
int line = pc->tline;
- /* Skip the bracket */
+
pc->p++;
pc->len--;
while (pc->len) {
@@ -7900,13 +6706,13 @@ static int JimParseQuote(struct JimParserCtx *pc)
static int JimParseVar(struct JimParserCtx *pc)
{
- /* skip the $ */
+
pc->p++;
pc->len--;
#ifdef EXPRSUGAR_BRACKET
if (*pc->p == '[') {
- /* Parse $[...] expr shorthand syntax */
+
JimParseCmd(pc);
pc->tt = JIM_TT_EXPRSUGAR;
return JIM_OK;
@@ -7936,7 +6742,7 @@ static int JimParseVar(struct JimParserCtx *pc)
}
else {
while (1) {
- /* Skip double colon, but not single colon! */
+
if (pc->p[0] == ':' && pc->p[1] == ':') {
pc->p += 2;
pc->len -= 2;
@@ -7949,7 +6755,7 @@ static int JimParseVar(struct JimParserCtx *pc)
}
break;
}
- /* Parse [dict get] syntax sugar. */
+
if (*pc->p == '(') {
int count = 1;
const char *paren = NULL;
@@ -7976,7 +6782,7 @@ static int JimParseVar(struct JimParserCtx *pc)
pc->len--;
}
else if (paren) {
- /* Did not find a matching paren. Back up */
+
paren++;
pc->len += (pc->p - paren);
pc->p = paren;
@@ -7989,10 +6795,6 @@ static int JimParseVar(struct JimParserCtx *pc)
}
pc->tend = pc->p - 1;
}
- /* Check if we parsed just the '$' character.
- * That's not a variable so an error is returned
- * to tell the state machine to consider this '$' just
- * a string. */
if (pc->tstart == pc->p) {
pc->p--;
pc->len++;
@@ -8012,7 +6814,7 @@ static int JimParseStr(struct JimParserCtx *pc)
pc->state = JIM_PS_QUOTE;
pc->p++;
pc->len--;
- /* In case the end quote is missing */
+
pc->missingline = pc->tline;
}
pc->tstart = pc->p;
@@ -8042,15 +6844,15 @@ static int JimParseStr(struct JimParserCtx *pc)
}
break;
case '(':
- /* If the following token is not '$' just keep going */
+
if (pc->len > 1 && pc->p[1] != '$') {
break;
}
case ')':
- /* Only need a separate ')' token if the previous was a var */
+
if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
if (pc->p == pc->tstart) {
- /* At the start of the token, so just return this char */
+
pc->p++;
pc->len--;
}
@@ -8093,7 +6895,7 @@ static int JimParseStr(struct JimParserCtx *pc)
pc->p++;
pc->len--;
}
- return JIM_OK; /* unreached */
+ return JIM_OK;
}
static int JimParseComment(struct JimParserCtx *pc)
@@ -8113,7 +6915,7 @@ static int JimParseComment(struct JimParserCtx *pc)
return JIM_OK;
}
-/* xdigitval and odigitval are helper functions for JimEscape() */
+
static int xdigitval(int c)
{
if (c >= '0' && c <= '9')
@@ -8132,13 +6934,6 @@ static int odigitval(int c)
return -1;
}
-/* Perform Tcl escape substitution of 's', storing the result
- * string into 'dest'. The escaped string is guaranteed to
- * be the same length or shorted than the source string.
- * Slen is the length of the string at 's', if it's -1 the string
- * length will be calculated by the function.
- *
- * The function returns the length of the resulting string. */
static int JimEscape(char *dest, const char *s, int slen)
{
char *p = dest;
@@ -8177,11 +6972,6 @@ static int JimEscape(char *dest, const char *s, int slen)
break;
case 'u':
case 'x':
- /* A unicode or hex sequence.
- * \u Expect 1-4 hex chars and convert to utf-8.
- * \x Expect 1-2 hex chars and convert to hex.
- * An invalid sequence means simply the escaped char.
- */
{
int val = 0;
int k;
@@ -8196,7 +6986,7 @@ static int JimEscape(char *dest, const char *s, int slen)
val = (val << 4) | c;
}
if (k) {
- /* Got a valid sequence, so convert */
+
if (s[i] == 'u') {
p += utf8_fromunicode(p, val);
}
@@ -8206,7 +6996,7 @@ static int JimEscape(char *dest, const char *s, int slen)
i += k;
break;
}
- /* Not a valid codepoint, just an escaped char */
+
*p++ = s[i];
}
break;
@@ -8219,7 +7009,7 @@ static int JimEscape(char *dest, const char *s, int slen)
i++;
break;
case '\n':
- /* Replace all spaces and tabs after backslash newline with a single space*/
+
*p++ = ' ';
do {
i++;
@@ -8233,7 +7023,7 @@ static int JimEscape(char *dest, const char *s, int slen)
case '5':
case '6':
case '7':
- /* octal escape */
+
{
int val = 0;
int c = odigitval(s[i + 1]);
@@ -8273,26 +7063,6 @@ static int JimEscape(char *dest, const char *s, int slen)
return len;
}
-/* Returns a dynamically allocated copy of the current token in the
- * parser context. The function performs conversion of escapes if
- * the token is of type JIM_TT_ESC.
- *
- * Note that after the conversion, tokens that are grouped with
- * braces in the source code, are always recognizable from the
- * identical string obtained in a different way from the type.
- *
- * For example the string:
- *
- * {*}$a
- *
- * will return as first token "*", of type JIM_TT_STR
- *
- * While the string:
- *
- * *$a
- *
- * will return as first token "*", of type JIM_TT_ESC
- */
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc)
{
const char *start, *end;
@@ -8310,12 +7080,12 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
len = (end - start) + 1;
token = Jim_Alloc(len + 1);
if (pc->tt != JIM_TT_ESC) {
- /* No escape conversion needed? Just copy it. */
+
memcpy(token, start, len);
token[len] = '\0';
}
else {
- /* Else convert the escape chars. */
+
len = JimEscape(token, start, len);
}
}
@@ -8323,17 +7093,6 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
return Jim_NewStringObjNoAlloc(interp, token, len);
}
-/* Parses the given string to determine if it represents a complete script.
- *
- * This is useful for interactive shells implementation, for [info complete].
- *
- * If 'stateCharPtr' != NULL, the function stores ' ' on complete script,
- * '{' on scripts incomplete missing one or more '}' to be balanced.
- * '[' on scripts incomplete missing one or more ']' to be balanced.
- * '"' on scripts incomplete missing a '"' char.
- *
- * If the script is complete, 1 is returned, otherwise 0.
- */
int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
{
struct JimParserCtx parser;
@@ -8348,9 +7107,6 @@ int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
return parser.missing == ' ';
}
-/* -----------------------------------------------------------------------------
- * Tcl Lists parsing
- * ---------------------------------------------------------------------------*/
static int JimParseListSep(struct JimParserCtx *pc);
static int JimParseListStr(struct JimParserCtx *pc);
static int JimParseListQuote(struct JimParserCtx *pc);
@@ -8414,7 +7170,7 @@ static int JimParseListQuote(struct JimParserCtx *pc)
case '\\':
pc->tt = JIM_TT_ESC;
if (--pc->len == 0) {
- /* Trailing backslash */
+
pc->tend = pc->p;
return JIM_OK;
}
@@ -8447,7 +7203,7 @@ static int JimParseListStr(struct JimParserCtx *pc)
switch (*pc->p) {
case '\\':
if (--pc->len == 0) {
- /* Trailing backslash */
+
pc->tend = pc->p;
return JIM_OK;
}
@@ -8468,35 +7224,26 @@ static int JimParseListStr(struct JimParserCtx *pc)
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Jim_Obj related functions
- * ---------------------------------------------------------------------------*/
-/* Return a new initialized object. */
+
Jim_Obj *Jim_NewObj(Jim_Interp *interp)
{
Jim_Obj *objPtr;
- /* -- Check if there are objects in the free list -- */
+
if (interp->freeList != NULL) {
- /* -- Unlink the object from the free list -- */
+
objPtr = interp->freeList;
interp->freeList = objPtr->nextObjPtr;
}
else {
- /* -- No ready to use objects: allocate a new one -- */
+
objPtr = Jim_Alloc(sizeof(*objPtr));
}
- /* Object is returned with refCount of 0. Every
- * kind of GC implemented should take care to don't try
- * to scan objects with refCount == 0. */
objPtr->refCount = 0;
- /* All the other fields are left not initialized to save time.
- * The caller will probably want to set them to the right
- * value anyway. */
- /* -- Put the object into the live list -- */
+
objPtr->prevObjPtr = NULL;
objPtr->nextObjPtr = interp->liveList;
if (interp->liveList)
@@ -8506,30 +7253,27 @@ Jim_Obj *Jim_NewObj(Jim_Interp *interp)
return objPtr;
}
-/* Free an object. Actually objects are never freed, but
- * just moved to the free objects list, where they will be
- * reused by Jim_NewObj(). */
void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
{
- /* Check if the object was already freed, panic. */
- JimPanic((objPtr->refCount != 0, interp, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
+
+ JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
- /* Free the internal representation */
+
Jim_FreeIntRep(interp, objPtr);
- /* Free the string representation */
+
if (objPtr->bytes != NULL) {
if (objPtr->bytes != JimEmptyStringRep)
Jim_Free(objPtr->bytes);
}
- /* Unlink the object from the live objects list */
+
if (objPtr->prevObjPtr)
objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
if (objPtr->nextObjPtr)
objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
if (interp->liveList == objPtr)
interp->liveList = objPtr->nextObjPtr;
- /* Link the object into the free objects list */
+
objPtr->prevObjPtr = NULL;
objPtr->nextObjPtr = interp->freeList;
if (interp->freeList)
@@ -8538,7 +7282,7 @@ void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
objPtr->refCount = -1;
}
-/* Invalidate the string representation of an object. */
+
void Jim_InvalidateStringRep(Jim_Obj *objPtr)
{
if (objPtr->bytes != NULL) {
@@ -8551,8 +7295,6 @@ void Jim_InvalidateStringRep(Jim_Obj *objPtr)
#define Jim_SetStringRep(o, b, l) \
do { (o)->bytes = b; (o)->length = l; } while (0)
-/* Set the initial string representation for an object.
- * Does not try to free an old one. */
void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length)
{
if (length == 0) {
@@ -8567,42 +7309,39 @@ void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length)
}
}
-/* Duplicate an object. The returned object has refcount = 0. */
+
Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
{
Jim_Obj *dupPtr;
dupPtr = Jim_NewObj(interp);
if (objPtr->bytes == NULL) {
- /* Object does not have a valid string representation. */
+
dupPtr->bytes = NULL;
}
else {
Jim_InitStringRep(dupPtr, objPtr->bytes, objPtr->length);
}
- /* By default, the new object has the same type as the old object */
+
dupPtr->typePtr = objPtr->typePtr;
if (objPtr->typePtr != NULL) {
if (objPtr->typePtr->dupIntRepProc == NULL) {
dupPtr->internalRep = objPtr->internalRep;
}
else {
- /* The dup proc may set a different type, e.g. NULL */
+
objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
}
}
return dupPtr;
}
-/* Return the string representation for objPtr. If the object
- * string representation is invalid, calls the method to create
- * a new one starting from the internal representation of the object. */
const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
{
if (objPtr->bytes == NULL) {
- /* Invalid string repr. Generate it. */
- JimPanic((objPtr->typePtr->updateStringProc == NULL, NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+
+ JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
objPtr->typePtr->updateStringProc(objPtr);
}
if (lenPtr)
@@ -8610,7 +7349,7 @@ const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
return objPtr->bytes;
}
-/* Just returns the length of the object's string rep */
+
int Jim_Length(Jim_Obj *objPtr)
{
int len;
@@ -8643,9 +7382,6 @@ static const Jim_ObjType interpolatedObjType = {
JIM_TYPE_NONE,
};
-/* -----------------------------------------------------------------------------
- * String Object
- * ---------------------------------------------------------------------------*/
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
@@ -8661,11 +7397,6 @@ static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *d
{
JIM_NOTUSED(interp);
- /* This is a bit subtle: the only caller of this function
- * should be Jim_DuplicateObj(), that will copy the
- * string representaion. After the copy, the duplicated
- * object will not have more room in teh buffer than
- * srcPtr->length bytes. So we just set it to length. */
dupPtr->internalRep.strValue.maxLength = srcPtr->length;
dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
@@ -8673,23 +7404,18 @@ static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *d
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
- /* Get a fresh string representation. */
+
(void)Jim_String(objPtr);
- /* Free any other internal representation. */
+
Jim_FreeIntRep(interp, objPtr);
- /* Set it as string, i.e. just set the maxLength field. */
+
objPtr->typePtr = &stringObjType;
objPtr->internalRep.strValue.maxLength = objPtr->length;
- /* Don't know the utf-8 length yet */
+
objPtr->internalRep.strValue.charLength = -1;
return JIM_OK;
}
-/**
- * Returns the length of the object string in chars, not bytes.
- *
- * These may be different for a utf-8 string.
- */
int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr)
{
#ifdef JIM_UTF8
@@ -8705,15 +7431,15 @@ int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr)
#endif
}
-/* len is in bytes -- see also Jim_NewStringObjUtf8() */
+
Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
{
Jim_Obj *objPtr = Jim_NewObj(interp);
- /* Need to find out how many bytes the string requires */
+
if (len == -1)
len = strlen(s);
- /* Alloc/Set the string rep. */
+
if (len == 0) {
objPtr->bytes = JimEmptyStringRep;
objPtr->length = 0;
@@ -8725,21 +7451,21 @@ Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
objPtr->bytes[len] = '\0';
}
- /* No typePtr field for the vanilla string object. */
+
objPtr->typePtr = NULL;
return objPtr;
}
-/* charlen is in characters -- see also Jim_NewStringObj() */
+
Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
{
#ifdef JIM_UTF8
- /* Need to find out how many bytes the string requires */
+
int bytelen = utf8_index(s, charlen);
Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
- /* Remember the utf8 length, so set the type */
+
objPtr->typePtr = &stringObjType;
objPtr->internalRep.strValue.maxLength = bytelen;
objPtr->internalRep.strValue.charLength = charlen;
@@ -8750,8 +7476,6 @@ Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
#endif
}
-/* This version does not try to duplicate the 's' pointer, but
- * use it directly. */
Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
{
Jim_Obj *objPtr = Jim_NewObj(interp);
@@ -8763,8 +7487,6 @@ Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
return objPtr;
}
-/* Low-level string append. Use it only against objects
- * of type "string". */
static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
{
int needlen;
@@ -8775,7 +7497,7 @@ static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
if (objPtr->internalRep.strValue.maxLength < needlen ||
objPtr->internalRep.strValue.maxLength == 0) {
needlen *= 2;
- /* Inefficient to malloc() for less than 8 bytes */
+
if (needlen < 7) {
needlen = 7;
}
@@ -8790,16 +7512,16 @@ static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
memcpy(objPtr->bytes + objPtr->length, str, len);
objPtr->bytes[objPtr->length + len] = '\0';
if (objPtr->internalRep.strValue.charLength >= 0) {
- /* Update the utf-8 char length */
+
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
}
objPtr->length += len;
}
-/* Higher level API to append strings to objects. */
+
void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
{
- JimPanic((Jim_IsShared(objPtr), interp, "Jim_AppendString called with shared object"));
+ JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
if (objPtr->typePtr != &stringObjType)
SetStringFromAny(interp, objPtr);
StringAppendString(objPtr, str, len);
@@ -8864,11 +7586,6 @@ int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *seco
return JimStringCompare(s1, l1, s2, l2);
}
-/* Convert a range, as returned by Jim_GetRange(), into
- * an absolute index into an object of the specified length.
- * This function may return negative values, or values
- * bigger or equal to the length of the list if the index
- * is out of range. */
static int JimRelToAbsIndex(int len, int idx)
{
if (idx < 0)
@@ -8876,12 +7593,6 @@ static int JimRelToAbsIndex(int len, int idx)
return idx;
}
-/* Convert a pair of index as normalize by JimRelToAbsIndex(),
- * into a range stored in *firstPtr, *lastPtr, *rangeLenPtr, suitable
- * for implementation of commands like [string range] and [lrange].
- *
- * The resulting range is guaranteed to address valid elements of
- * the structure. */
static void JimRelToAbsRange(int len, int first, int last,
int *firstPtr, int *lastPtr, int *rangeLenPtr)
{
@@ -8953,7 +7664,7 @@ Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp,
return strObjPtr;
}
if (len == bytelen) {
- /* ASCII optimisation */
+
return Jim_NewStringObj(interp, str + first, rangeLen);
}
return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
@@ -9006,10 +7717,6 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
return Jim_NewStringObjNoAlloc(interp, buf, len);
}
-/* Similar to memchr() except searches a UTF-8 string 'str' of byte length 'len'
- * for unicode character 'c'.
- * Returns the position if found or NULL if not
- */
static const char *utf8_memchr(const char *str, int len, int c)
{
#ifdef JIM_UTF8
@@ -9028,13 +7735,6 @@ static const char *utf8_memchr(const char *str, int len, int c)
#endif
}
-/**
- * Searches for the first non-trim char in string (str, len)
- *
- * If none is found, returns just past the last char.
- *
- * Lengths are in bytes.
- */
static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen)
{
while (len) {
@@ -9042,7 +7742,7 @@ static const char *JimFindTrimLeft(const char *str, int len, const char *trimcha
int n = utf8_tounicode(str, &c);
if (utf8_memchr(trimchars, trimlen, c) == NULL) {
- /* Not a trim char, so stop */
+
break;
}
str += n;
@@ -9051,13 +7751,6 @@ static const char *JimFindTrimLeft(const char *str, int len, const char *trimcha
return str;
}
-/**
- * Searches backwards for a non-trim char in string (str, len).
- *
- * Returns a pointer to just after the non-trim char, or NULL if not found.
- *
- * Lengths are in bytes.
- */
static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen)
{
str += len;
@@ -9080,7 +7773,7 @@ static const char *JimFindTrimRight(const char *str, int len, const char *trimch
}
static const char default_trim_chars[] = " \t\n\r";
-/* sizeof() here includes the null byte */
+
static int default_trim_chars_len = sizeof(default_trim_chars);
static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
@@ -9121,7 +7814,7 @@ static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_O
nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
if (nontrim == NULL) {
- /* All trim, so return a zero-length string */
+
return Jim_NewEmptyStringObj(interp);
}
if (nontrim == strObjPtr->bytes + len) {
@@ -9132,7 +7825,7 @@ static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_O
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
}
else {
- /* Can modify this string in place */
+
strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
strObjPtr->length = (nontrim - strObjPtr->bytes);
}
@@ -9142,14 +7835,14 @@ static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_O
static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
{
- /* First trim left. */
+
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
- /* Now trim right */
+
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
if (objPtr != strObjPtr) {
- /* Note that we don't want this object to be leaked */
+
Jim_IncrRefCount(objPtr);
Jim_DecrRefCount(interp, objPtr);
}
@@ -9228,20 +7921,7 @@ static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Compared String Object
- * ---------------------------------------------------------------------------*/
-/* This is strange object that allows to compare a C literal string
- * with a Jim object in very short time if the same comparison is done
- * multiple times. For example every time the [if] command is executed,
- * Jim has to check if a given argument is "else". This comparions if
- * the code has no errors are true most of the times, so we can cache
- * inside the object the pointer of the string of the last matching
- * comparison. Because most C compilers perform literal sharing,
- * so that: char *x = "foo", char *y = "foo", will lead to x == y,
- * this works pretty well even if comparisons are at different places
- * inside the C code. */
static const Jim_ObjType comparedStringObjType = {
"compared-string",
@@ -9251,11 +7931,6 @@ static const Jim_ObjType comparedStringObjType = {
JIM_TYPE_REFERENCES,
};
-/* The only way this object is exposed to the API is via the following
- * function. Returns true if the string and the object string repr.
- * are the same, otherwise zero is returned.
- *
- * Note: this isn't binary safe, but it hardly needs to be.*/
int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
{
if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
@@ -9269,7 +7944,7 @@ int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &comparedStringObjType;
}
- objPtr->internalRep.ptr = (char *)str; /*ATTENTION: const cast */
+ objPtr->internalRep.ptr = (char *)str;
return 1;
}
}
@@ -9283,27 +7958,6 @@ static int qsortCompareStringPointers(const void *a, const void *b)
}
-/* -----------------------------------------------------------------------------
- * Source Object
- *
- * This object is just a string from the language point of view, but
- * in the internal representation it contains the filename and line number
- * where this given token was read. This information is used by
- * Jim_EvalObj() if the object passed happens to be of type "source".
- *
- * This allows to propagate the information about line numbers and file
- * names and give error messages with absolute line numbers.
- *
- * Note that this object uses shared strings for filenames, and the
- * pointer to the filename together with the line number is taken into
- * the space for the "inline" internal representation of the Jim_Object,
- * so there is almost memory zero-overhead.
- *
- * Also the object will be converted to something else if the given
- * token it represents in the source file is not something to be
- * evaluated (not a script), and will be specialized in some other way,
- * so the time overhead is also null.
- * ---------------------------------------------------------------------------*/
static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -9318,32 +7972,26 @@ static const Jim_ObjType sourceObjType = {
void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
- Jim_ReleaseSharedString(interp, objPtr->internalRep.sourceValue.fileName);
+ Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj);
}
void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
- dupPtr->internalRep.sourceValue.fileName =
- Jim_GetSharedString(interp, srcPtr->internalRep.sourceValue.fileName);
- dupPtr->internalRep.sourceValue.lineNumber = dupPtr->internalRep.sourceValue.lineNumber;
- dupPtr->typePtr = &sourceObjType;
+ dupPtr->internalRep = srcPtr->internalRep;
+ Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
}
static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
- const char *fileName, int lineNumber)
+ Jim_Obj *fileNameObj, int lineNumber)
{
- if (fileName) {
- JimPanic((Jim_IsShared(objPtr), interp, "JimSetSourceInfo called with shared object"));
- JimPanic((objPtr->typePtr != NULL, interp, "JimSetSourceInfo called with typePtr != NULL"));
- objPtr->internalRep.sourceValue.fileName = Jim_GetSharedString(interp, fileName);
- objPtr->internalRep.sourceValue.lineNumber = lineNumber;
- objPtr->typePtr = &sourceObjType;
- }
+ JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
+ JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL"));
+ Jim_IncrRefCount(fileNameObj);
+ objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
+ objPtr->internalRep.sourceValue.lineNumber = lineNumber;
+ objPtr->typePtr = &sourceObjType;
}
-/* -----------------------------------------------------------------------------
- * Script Object
- * ---------------------------------------------------------------------------*/
static const Jim_ObjType scriptLineObjType = {
"scriptline",
@@ -9385,94 +8033,22 @@ static const Jim_ObjType scriptObjType = {
JIM_TYPE_REFERENCES,
};
-/* The ScriptToken structure represents every token into a scriptObj.
- * Every token contains an associated Jim_Obj that can be specialized
- * by commands operating on it. */
typedef struct ScriptToken
{
int type;
Jim_Obj *objPtr;
} ScriptToken;
-/* This is the script object internal representation. An array of
- * ScriptToken structures, including a pre-computed representation of the
- * command length and arguments.
- *
- * For example the script:
- *
- * puts hello
- * set $i $x$y [foo]BAR
- *
- * will produce a ScriptObj with the following Tokens:
- *
- * LIN 2
- * ESC puts
- * ESC hello
- * LIN 4
- * ESC set
- * VAR i
- * WRD 2
- * VAR x
- * VAR y
- * WRD 2
- * CMD foo
- * ESC BAR
- *
- * "puts hello" has two args (LIN 2), composed of single tokens.
- * (Note that the WRD token is omitted for the common case of a single token.)
- *
- * "set $i $x$y [foo]BAR" has four (LIN 4) args, the first word
- * has 1 token (ESC SET), and the last has two tokens (WRD 2 CMD foo ESC BAR)
- *
- * The precomputation of the command structure makes Jim_Eval() faster,
- * and simpler because there aren't dynamic lengths / allocations.
- *
- * -- {expand}/{*} handling --
- *
- * Expand is handled in a special way.
- *
- * If a "word" begins with {*}, the word token count is -ve.
- *
- * For example the command:
- *
- * list {*}{a b}
- *
- * Will produce the following cmdstruct array:
- *
- * LIN 2
- * ESC list
- * WRD -1
- * STR a b
- *
- * Note that the 'LIN' token also contains the source information for the
- * first word of the line for error reporting purposes
- *
- * -- the substFlags field of the structure --
- *
- * The scriptObj structure is used to represent both "script" objects
- * and "subst" objects. In the second case, the there are no LIN and WRD
- * tokens. Instead SEP and EOL tokens are added as-is.
- * In addition, the field 'substFlags' is used to represent the flags used to turn
- * the string into the internal representation used to perform the
- * substitution. If this flags are not what the application requires
- * the scriptObj is created again. For example the script:
- *
- * subst -nocommands $string
- * subst -novariables $string
- *
- * Will recreate the internal representation of the $string object
- * two times.
- */
typedef struct ScriptObj
{
- int len; /* Length as number of tokens. */
- ScriptToken *token; /* Tokens array. */
- int substFlags; /* flags used for the compilation of "subst" objects */
+ int len;
+ ScriptToken *token;
+ int substFlags;
int inUse; /* Used to share a ScriptObj. Currently
only used by Jim_EvalObj() as protection against
shimmering of the currently evaluated object. */
- const char *fileName;
- int line; /* Line number of the first line */
+ Jim_Obj *fileNameObj;
+ int line;
} ScriptObj;
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
@@ -9487,9 +8063,7 @@ void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_DecrRefCount(interp, script->token[i].objPtr);
}
Jim_Free(script->token);
- if (script->fileName) {
- Jim_ReleaseSharedString(interp, script->fileName);
- }
+ Jim_DecrRefCount(interp, script->fileNameObj);
Jim_Free(script);
}
@@ -9498,32 +8072,25 @@ void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
JIM_NOTUSED(interp);
JIM_NOTUSED(srcPtr);
- /* Just returns an simple string. */
+
dupPtr->typePtr = NULL;
}
-/* A simple parser token.
- * All the simple tokens for the script point into the same script string rep.
- */
typedef struct
{
- const char *token; /* Pointer to the start of the token */
- int len; /* Length of this token */
- int type; /* Token type */
- int line; /* Line number */
+ const char *token;
+ int len;
+ int type;
+ int line;
} ParseToken;
-/* A list of parsed tokens representing a script.
- * Tokens are added to this list as the script is parsed.
- * It grows as needed.
- */
typedef struct
{
- /* Start with a statically allocated list of tokens which will be expanded with realloc if needed */
- ParseToken *list; /* Array of tokens */
- int size; /* Current size of the list */
- int count; /* Number of entries used */
- ParseToken static_list[20]; /* Small initial token space to avoid allocation */
+
+ ParseToken *list;
+ int size;
+ int count;
+ ParseToken static_list[20];
} ParseTokenList;
static void ScriptTokenListInit(ParseTokenList *tokenlist)
@@ -9540,25 +8107,20 @@ static void ScriptTokenListFree(ParseTokenList *tokenlist)
}
}
-/**
- * Adds the new token to the tokenlist.
- * The token has the given length, type and line number.
- * The token list is resized as necessary.
- */
static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type,
int line)
{
ParseToken *t;
if (tokenlist->count == tokenlist->size) {
- /* Resize the list */
+
tokenlist->size *= 2;
if (tokenlist->list != tokenlist->static_list) {
tokenlist->list =
Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
}
else {
- /* The list needs to become allocated */
+
tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
memcpy(tokenlist->list, tokenlist->static_list,
tokenlist->count * sizeof(*tokenlist->list));
@@ -9571,27 +8133,21 @@ static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len
t->line = line;
}
-/* Counts the number of adjoining non-separator.
- *
- * Returns -ve if the first token is the expansion
- * operator (in which case the count doesn't include
- * that token).
- */
static int JimCountWordTokens(ParseToken *t)
{
int expand = 1;
int count = 0;
- /* Is the first word {*} or {expand}? */
+
if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
- /* Create an expand token */
+
expand = -1;
t++;
}
}
- /* Now count non-separator words */
+
while (!TOKEN_IS_SEP(t->type)) {
t++;
count++;
@@ -9600,46 +8156,31 @@ static int JimCountWordTokens(ParseToken *t)
return count * expand;
}
-/**
- * Create a script/subst object from the given token.
- */
static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
{
Jim_Obj *objPtr;
if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
- /* Convert the backlash escapes . */
+
int len = t->len;
char *str = Jim_Alloc(len + 1);
len = JimEscape(str, t->token, len);
objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
}
else {
- /* REVIST: Strictly, JIM_TT_STR should replace <backslash><newline><whitespace>
- * with a single space. This is currently not done.
- */
objPtr = Jim_NewStringObj(interp, t->token, t->len);
}
return objPtr;
}
-/**
- * Takes a tokenlist and creates the allocated list of script tokens
- * in script->token, of length script->len.
- *
- * Unnecessary tokens are discarded, and LINE and WORD tokens are inserted
- * as required.
- *
- * Also sets script->line to the line number of the first token
- */
static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
ParseTokenList *tokenlist)
{
int i;
struct ScriptToken *token;
- /* Number of tokens so far for the current command */
+
int lineargs = 0;
- /* This is the first token for the current command */
+
ScriptToken *linefirst;
int count;
int linenr;
@@ -9652,7 +8193,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
}
#endif
- /* May need up to one extra script token for each EOL in the worst case */
+
count = tokenlist->count;
for (i = 0; i < tokenlist->count; i++) {
if (tokenlist->list[i].type == JIM_TT_EOL) {
@@ -9663,14 +8204,14 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
- /* This is the first token for the current command */
+
linefirst = token++;
for (i = 0; i < tokenlist->count; ) {
- /* Look ahead to find out how many tokens make up the next word */
+
int wordtokens;
- /* Skip any leading separators */
+
while (tokenlist->list[i].type == JIM_TT_SEP) {
i++;
}
@@ -9678,13 +8219,13 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
wordtokens = JimCountWordTokens(tokenlist->list + i);
if (wordtokens == 0) {
- /* None, so at end of line */
+
if (lineargs) {
linefirst->type = JIM_TT_LINE;
linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
Jim_IncrRefCount(linefirst->objPtr);
- /* Reset for new line */
+
lineargs = 0;
linefirst = token++;
}
@@ -9692,13 +8233,13 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
continue;
}
else if (wordtokens != 1) {
- /* More than 1, or {expand}, so insert a WORD token */
+
token->type = JIM_TT_WORD;
token->objPtr = Jim_NewIntObj(interp, wordtokens);
Jim_IncrRefCount(token->objPtr);
token++;
if (wordtokens < 0) {
- /* Skip the expand token */
+
i++;
wordtokens = -wordtokens - 1;
lineargs--;
@@ -9706,12 +8247,12 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
}
if (lineargs == 0) {
- /* First real token on the line, so record the line number */
+
linenr = tokenlist->list[i].line;
}
lineargs++;
- /* Add each non-separator word token to the line */
+
while (wordtokens--) {
const ParseToken *t = &tokenlist->list[i++];
@@ -9719,10 +8260,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
token->objPtr = JimMakeScriptObj(interp, t);
Jim_IncrRefCount(token->objPtr);
- /* Every object is initially a string, but the
- * internal type may be specialized during execution of the
- * script. */
- JimSetSourceInfo(interp, token->objPtr, script->fileName, t->line);
+ JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line);
token++;
}
}
@@ -9736,7 +8274,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
assert(script->len < count);
#ifdef DEBUG_SHOW_SCRIPT
- printf("==== Script (%s) ====\n", script->fileName);
+ printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
for (i = 0; i < script->len; i++) {
const ScriptToken *t = &script->token[i];
printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
@@ -9745,9 +8283,6 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
}
-/**
- * Similar to ScriptObjAddTokens(), but for subst objects.
- */
static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
ParseTokenList *tokenlist)
{
@@ -9759,7 +8294,7 @@ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
for (i = 0; i < tokenlist->count; i++) {
const ParseToken *t = &tokenlist->list[i];
- /* Create a token for 't' */
+
token->type = t->type;
token->objPtr = JimMakeScriptObj(interp, t);
Jim_IncrRefCount(token->objPtr);
@@ -9769,9 +8304,6 @@ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
script->len = i;
}
-/* This method takes the string representation of an object
- * as a Tcl script, and generates the pre-parsed internal representation
- * of the script. */
static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
{
int scriptTextLen;
@@ -9781,12 +8313,12 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
ParseTokenList tokenlist;
int line = 1;
- /* Try to get information about filename / line number */
+
if (objPtr->typePtr == &sourceObjType) {
line = objPtr->internalRep.sourceValue.lineNumber;
}
- /* Initially parse the script into tokens (in tokenlist) */
+
ScriptTokenListInit(&tokenlist);
JimParserInit(&parser, scriptText, scriptTextLen, line);
@@ -9802,28 +8334,28 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
return JIM_ERR;
}
- /* Add a final EOF token */
+
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
- /* Create the "real" script tokens from the initial token list */
+
script = Jim_Alloc(sizeof(*script));
memset(script, 0, sizeof(*script));
script->inUse = 1;
script->line = line;
if (objPtr->typePtr == &sourceObjType) {
- script->fileName = Jim_GetSharedString(interp, objPtr->internalRep.sourceValue.fileName);
+ script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
+ }
+ else {
+ script->fileNameObj = interp->emptyObj;
}
+ Jim_IncrRefCount(script->fileNameObj);
ScriptObjAddTokens(interp, script, &tokenlist);
- /* No longer need the token list */
+
ScriptTokenListFree(&tokenlist);
- if (!script->fileName) {
- script->fileName = Jim_GetSharedString(interp, "");
- }
-
- /* Free the old internal rep and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, script);
objPtr->typePtr = &scriptObjType;
@@ -9841,9 +8373,6 @@ ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
}
-/* -----------------------------------------------------------------------------
- * Commands
- * ---------------------------------------------------------------------------*/
static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
{
cmdPtr->inUse++;
@@ -9860,12 +8389,12 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
Jim_Free(cmdPtr->u.proc.staticVars);
}
if (cmdPtr->u.proc.prevCmd) {
- /* Delete any pushed command too */
+
JimDecrCmdRefCount(interp, cmdPtr->u.proc.prevCmd);
}
}
else {
- /* native (C) */
+
if (cmdPtr->u.native.delProc) {
cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
}
@@ -9874,24 +8403,21 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
}
}
-/* Commands HashTable Type.
- *
- * Keys are dynamic allocated strings, Values are Jim_Cmd structures. */
static void JimCommandsHT_ValDestructor(void *interp, void *val)
{
JimDecrCmdRefCount(interp, val);
}
static const Jim_HashTableType JimCommandsHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- JimCommandsHT_ValDestructor /* val destructor */
+ JimStringCopyHTHashFunction,
+ JimStringCopyHTKeyDup,
+ NULL,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ JimCommandsHT_ValDestructor
};
-/* ------------------------- Commands related functions --------------------- */
+
int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName,
Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc)
@@ -9899,13 +8425,13 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName,
Jim_Cmd *cmdPtr;
if (Jim_DeleteHashEntry(&interp->commands, cmdName) != JIM_ERR) {
- /* Command existed so incr proc epoch */
+
Jim_InterpIncrProcEpoch(interp);
}
cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
- /* Store the new details for this proc */
+
memset(cmdPtr, 0, sizeof(*cmdPtr));
cmdPtr->inUse = 1;
cmdPtr->u.native.delProc = delProc;
@@ -9914,9 +8440,6 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName,
Jim_AddHashEntry(&interp->commands, cmdName, cmdPtr);
- /* There is no need to increment the 'proc epoch' because
- * creation of a new procedure can never affect existing
- * cached commands. We don't do negative caching. */
return JIM_OK;
}
@@ -9934,7 +8457,7 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
argListLen = Jim_ListLength(interp, argListObjPtr);
- /* Allocate space for both the command pointer and the arg list */
+
cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
memset(cmdPtr, 0, sizeof(*cmdPtr));
cmdPtr->inUse = 1;
@@ -9947,7 +8470,7 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
Jim_IncrRefCount(argListObjPtr);
Jim_IncrRefCount(bodyObjPtr);
- /* Create the statics hash table. */
+
if (staticsListObjPtr) {
int len, i;
@@ -9961,11 +8484,9 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
int subLen;
Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
- /* Check if it's composed of two elements. */
+
subLen = Jim_ListLength(interp, objPtr);
if (subLen == 1 || subLen == 2) {
- /* Try to get the variable value from the current
- * environment. */
Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
if (subLen == 1) {
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
@@ -10005,8 +8526,8 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
}
}
- /* Parse the args out into arglist, validating as we go */
- /* Examine the argument list for default parameters and 'args' */
+
+
for (i = 0; i < argListLen; i++) {
Jim_Obj *argPtr;
Jim_Obj *nameObjPtr;
@@ -10014,7 +8535,7 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
int len;
int n = 1;
- /* Examine a parameter */
+
Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
len = Jim_ListLength(interp, argPtr);
if (len == 0) {
@@ -10027,12 +8548,12 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
}
if (len == 2) {
- /* Optional parameter */
+
Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
}
else {
- /* Required parameter */
+
nameObjPtr = argPtr;
defaultObjPtr = NULL;
}
@@ -10058,42 +8579,29 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr;
}
- /* Add the new command */
+
- /* It may already exist, so we try to delete the old one.
- * Note that reference count means that it won't be deleted yet if
- * it exists in the call stack.
- *
- * BUT, if 'local' is in force, instead of deleting the existing
- * proc, we stash a reference to the old proc here.
- */
he = Jim_FindHashEntry(&interp->commands, Jim_String(cmdName));
if (he) {
- /* There was an old procedure with the same name, this requires
- * a 'proc epoch' update. */
- /* If a procedure with the same name didn't existed there is no need
- * to increment the 'proc epoch' because creation of a new procedure
- * can never affect existing cached commands. We don't do
- * negative caching. */
Jim_InterpIncrProcEpoch(interp);
}
if (he && interp->local) {
- /* Just push this proc over the top of the previous one */
+
cmdPtr->u.proc.prevCmd = he->u.val;
he->u.val = cmdPtr;
}
else {
if (he) {
- /* Replace the existing proc */
+
Jim_DeleteHashEntry(&interp->commands, Jim_String(cmdName));
}
Jim_AddHashEntry(&interp->commands, Jim_String(cmdName), cmdPtr);
}
- /* Unlike Tcl, set the name of the proc as the result */
+
Jim_SetResult(interp, cmdName);
return JIM_OK;
@@ -10120,7 +8628,7 @@ int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newNa
{
Jim_HashEntry *he;
- /* Does it exist? */
+
he = Jim_FindHashEntry(&interp->commands, oldName);
if (he == NULL) {
Jim_SetResultFormatted(interp, "can't %s \"%s\": command doesn't exist",
@@ -10128,30 +8636,27 @@ int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newNa
return JIM_ERR;
}
- if (newName[0] == '\0') /* Delete! */
+ if (newName[0] == '\0')
return Jim_DeleteCommand(interp, oldName);
- /* rename */
+
if (Jim_FindHashEntry(&interp->commands, newName)) {
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
return JIM_ERR;
}
- /* Add the new name first */
+
JimIncrCmdRefCount(he->u.val);
Jim_AddHashEntry(&interp->commands, newName, he->u.val);
- /* Now remove the old name */
+
Jim_DeleteHashEntry(&interp->commands, oldName);
- /* Increment the epoch */
+
Jim_InterpIncrProcEpoch(interp);
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Command object
- * ---------------------------------------------------------------------------*/
static int SetCommandFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
@@ -10168,14 +8673,14 @@ int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_HashEntry *he;
const char *cmdName;
- /* Get the string representation */
+
cmdName = Jim_String(objPtr);
- /* Lookup this name into the commands hash table */
+
he = Jim_FindHashEntry(&interp->commands, cmdName);
if (he == NULL)
return JIM_ERR;
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &commandObjType;
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -10183,14 +8688,6 @@ int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
return JIM_OK;
}
-/* This function returns the command structure for the command name
- * stored in objPtr. It tries to specialize the objPtr to contain
- * a cached info instead to perform the lookup into the hash table
- * every time. The information cached may not be uptodate, in such
- * a case the lookup is performed and the cache updated.
- *
- * Respects the 'upcall' setting
- */
Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
{
Jim_Cmd *cmd;
@@ -10210,13 +8707,7 @@ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
return cmd;
}
-/* -----------------------------------------------------------------------------
- * Variables
- * ---------------------------------------------------------------------------*/
-/* Variables HashTable Type.
- *
- * Keys are dynamic allocated strings, Values are Jim_Var structures. */
static void JimVariablesHTValDestructor(void *interp, void *val)
{
Jim_Var *varPtr = (void *)val;
@@ -10226,19 +8717,16 @@ static void JimVariablesHTValDestructor(void *interp, void *val)
}
static const Jim_HashTableType JimVariablesHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
- JimVariablesHTValDestructor /* val destructor */
+ JimStringCopyHTHashFunction,
+ JimStringCopyHTKeyDup,
+ NULL,
+ JimStringCopyHTKeyCompare,
+ JimStringCopyHTKeyDestructor,
+ JimVariablesHTValDestructor
};
-/* -----------------------------------------------------------------------------
- * Variable object
- * ---------------------------------------------------------------------------*/
-#define JIM_DICT_SUGAR 100 /* Only returned by SetVariableFromAny() */
+#define JIM_DICT_SUGAR 100
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
@@ -10250,8 +8738,6 @@ static const Jim_ObjType variableObjType = {
JIM_TYPE_REFERENCES,
};
-/* Return true if the string "str" looks like syntax sugar for [dict]. I.e.
- * is in the form "varname(key)". */
static int JimNameIsDictSugar(const char *str, int len)
{
if (len && str[len - 1] == ')' && strchr(str, '(') != NULL)
@@ -10259,15 +8745,9 @@ static int JimNameIsDictSugar(const char *str, int len)
return 0;
}
-/**
- * Check that the name does not contain embedded nulls.
- *
- * Variable and procedure names are maniplated as null terminated strings, so
- * don't allow names with embedded nulls.
- */
static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
{
- /* Variable names and proc names can't contain embedded nulls */
+
if (nameObjPtr->typePtr != &variableObjType) {
int len;
const char *str = Jim_GetString(nameObjPtr, &len);
@@ -10279,11 +8759,6 @@ static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPt
return JIM_OK;
}
-/* This method should be called only by the variable API.
- * It returns JIM_OK on success (variable already exists),
- * JIM_ERR if it does not exists, JIM_DICT_SUGAR if it's not
- * a variable name, but syntax glue for [dict] i.e. the last
- * character is ')' */
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
Jim_HashEntry *he;
@@ -10291,10 +8766,10 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
int len;
Jim_CallFrame *framePtr = interp->framePtr;
- /* Check if the object is already an uptodate variable */
+
if (objPtr->typePtr == &variableObjType &&
objPtr->internalRep.varValue.callFrameId == framePtr->id) {
- return JIM_OK; /* nothing to do */
+ return JIM_OK;
}
if (objPtr->typePtr == &dictSubstObjType) {
@@ -10305,10 +8780,10 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
return JIM_ERR;
}
- /* Get the string representation */
+
varName = Jim_GetString(objPtr, &len);
- /* Make sure it's not syntax glue to get/set dict. */
+
if (JimNameIsDictSugar(varName, len)) {
return JIM_DICT_SUGAR;
}
@@ -10321,17 +8796,17 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
}
else {
- /* Lookup this name into the variables hash table */
+
he = Jim_FindHashEntry(&framePtr->vars, varName);
if (he == NULL) {
- /* Try with static vars. */
+
if (framePtr->staticVars == NULL)
return JIM_ERR;
if (!(he = Jim_FindHashEntry(framePtr->staticVars, varName)))
return JIM_ERR;
}
}
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &variableObjType;
objPtr->internalRep.varValue.callFrameId = framePtr->id;
@@ -10339,15 +8814,10 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
return JIM_OK;
}
-/* -------------------- Variables related functions ------------------------- */
+
static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
-/* For now that's dummy. Variables lookup should be optimized
- * in many ways, with caching of lookups, and possibly with
- * a table of pre-allocated vars in every CallFrame for local vars.
- * All the caching should also have an 'epoch' mechanism similar
- * to the one used by Tcl for procedures lookup caching. */
int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
{
@@ -10358,7 +8828,7 @@ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
if ((err = SetVariableFromAny(interp, nameObjPtr)) != JIM_OK) {
Jim_CallFrame *framePtr = interp->framePtr;
- /* Check for [dict] syntax sugar. */
+
if (err == JIM_DICT_SUGAR)
return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
@@ -10366,23 +8836,23 @@ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
return JIM_ERR;
}
- /* New variable to create */
+
name = Jim_String(nameObjPtr);
var = Jim_Alloc(sizeof(*var));
var->objPtr = valObjPtr;
Jim_IncrRefCount(valObjPtr);
var->linkFramePtr = NULL;
- /* Insert the new variable */
+
if (name[0] == ':' && name[1] == ':') {
- /* Into the top level frame */
+
framePtr = interp->topFramePtr;
Jim_AddHashEntry(&framePtr->vars, name + 2, var);
}
else {
Jim_AddHashEntry(&framePtr->vars, name, var);
}
- /* Make the object int rep a variable */
+
Jim_FreeIntRep(interp, nameObjPtr);
nameObjPtr->typePtr = &variableObjType;
nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
@@ -10395,7 +8865,7 @@ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
Jim_DecrRefCount(interp, var->objPtr);
var->objPtr = valObjPtr;
}
- else { /* Else handle the link */
+ else {
Jim_CallFrame *savedCallFrame;
savedCallFrame = interp->framePtr;
@@ -10457,7 +8927,7 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
varName = Jim_GetString(nameObjPtr, &len);
if (varName[0] == ':' && varName[1] == ':') {
- /* Linking a global var does nothing */
+
return JIM_OK;
}
@@ -10466,7 +8936,7 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
return JIM_ERR;
}
- /* Check for an existing variable or link */
+
if (SetVariableFromAny(interp, nameObjPtr) == JIM_OK) {
Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr;
@@ -10475,16 +8945,16 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
return JIM_ERR;
}
- /* It exists, but is a link, so delete the link */
+
varPtr->linkFramePtr = NULL;
}
- /* Check for cycles. */
+
if (interp->framePtr == targetCallFrame) {
Jim_Obj *objPtr = targetNameObjPtr;
Jim_Var *varPtr;
- /* Cycles are only possible with 'uplevel 0' */
+
while (1) {
if (Jim_StringEqObj(objPtr, nameObjPtr)) {
Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
@@ -10499,23 +8969,13 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
}
}
- /* Perform the binding */
+
Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
- /* We are now sure 'nameObjPtr' type is variableObjType */
+
nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
return JIM_OK;
}
-/* Return the Jim_Obj pointer associated with a variable name,
- * or NULL if the variable was not found in the current context.
- * The same optimization discussed in the comment to the
- * 'SetVariable' function should apply here.
- *
- * If JIM_UNSHARED is set and the variable is an array element (dict sugar)
- * in a dictionary which is shared, the array variable value is duplicated first.
- * This allows the array element to be updated (e.g. append, lappend) without
- * affecting other references to the dictionary.
- */
Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
{
switch (SetVariableFromAny(interp, nameObjPtr)) {
@@ -10528,7 +8988,7 @@ Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
else {
Jim_Obj *objPtr;
- /* The variable is a link? Resolve it. */
+
Jim_CallFrame *savedCallFrame = interp->framePtr;
interp->framePtr = varPtr->linkFramePtr;
@@ -10537,13 +8997,13 @@ Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
if (objPtr) {
return objPtr;
}
- /* Error, so fall through to the error message */
+
}
}
break;
case JIM_DICT_SUGAR:
- /* [dict] syntax sugar. */
+
return JimDictSugarGet(interp, nameObjPtr, flags);
}
if (flags & JIM_ERRMSG) {
@@ -10589,9 +9049,6 @@ Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flag
return objPtr;
}
-/* Unset a variable.
- * Note: On success unset invalidates all the variable objects created
- * in the current call frame incrementing. */
int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
{
const char *name;
@@ -10600,13 +9057,13 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
retval = SetVariableFromAny(interp, nameObjPtr);
if (retval == JIM_DICT_SUGAR) {
- /* [dict] syntax sugar. */
+
return JimDictSugarSet(interp, nameObjPtr, NULL);
}
else if (retval == JIM_OK) {
varPtr = nameObjPtr->internalRep.varValue.varPtr;
- /* If it's a link call UnsetVariable recursively */
+
if (varPtr->linkFramePtr) {
Jim_CallFrame *savedCallFrame;
@@ -10625,7 +9082,7 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
}
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
if (retval == JIM_OK) {
- /* Change the callframe id, invalidating var lookup caching */
+
JimChangeCallFrameId(interp, framePtr);
}
}
@@ -10636,15 +9093,8 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
return retval;
}
-/* ---------- Dict syntax sugar (similar to array Tcl syntax) -------------- */
-/* Given a variable name for [dict] operation syntax sugar,
- * this function returns two objects, the first with the name
- * of the variable to set, and the second with the rispective key.
- * For example "foo(bar)" will return objects with string repr. of
- * "foo" and "bar".
- *
- * The returned objects have refcount = 1. The function can't fail. */
+
static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr)
{
@@ -10655,7 +9105,7 @@ static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr,
str = Jim_GetString(objPtr, &len);
p = strchr(str, '(');
- JimPanic((p == NULL, interp, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str));
+ JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str));
varObjPtr = Jim_NewStringObj(interp, str, p - str);
@@ -10665,7 +9115,7 @@ static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr,
keyLen--;
}
- /* Create the objects with the variable name and key. */
+
keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
Jim_IncrRefCount(varObjPtr);
@@ -10674,8 +9124,6 @@ static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr,
*keyPtrPtr = keyObjPtr;
}
-/* Helper of Jim_SetVariable() to deal with dict-syntax variable names.
- * Also used by Jim_UnsetVariable() with valObjPtr = NULL. */
static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr)
{
int err;
@@ -10683,34 +9131,28 @@ static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjP
SetDictSubstFromAny(interp, objPtr);
err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
- &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr);
+ &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_ERRMSG);
if (err == JIM_OK) {
- /* Don't keep an extra ref to the result */
+
Jim_SetEmptyResult(interp);
}
else {
if (!valObjPtr) {
- /* Better error message for unset a(2) where a exists but a(2) doesn't */
+
if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
objPtr);
return err;
}
}
- /* Make the error more informative and Tcl-compatible */
+
Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
(valObjPtr ? "set" : "unset"), objPtr);
}
return err;
}
-/**
- * Expands the array variable (dict sugar) and returns the result, or NULL on error.
- *
- * If JIM_UNSHARED is set and the dictionary is shared, it will be duplicated
- * and stored back to the variable before expansion.
- */
static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr,
Jim_Obj *keyObjPtr, int flags)
{
@@ -10738,17 +9180,17 @@ static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPt
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
- /* This can probably never happen */
- JimPanic((1, interp, "SetVariable failed for JIM_UNSHARED"));
+
+ JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
}
- /* We know that the key exists. Get the result in the now-unshared dictionary */
+
Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
}
return resObjPtr;
}
-/* Helper of Jim_GetVariable() to deal with dict-syntax variable names */
+
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
{
SetDictSubstFromAny(interp, objPtr);
@@ -10758,7 +9200,7 @@ static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
objPtr->internalRep.dictSubstValue.indexObjPtr, flags);
}
-/* --------- $var(INDEX) substitution, using a specialized object ----------- */
+
void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
@@ -10776,14 +9218,14 @@ void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPt
dupPtr->typePtr = &dictSubstObjType;
}
-/* Note: The object *must* be in dict-sugar format */
+
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
if (objPtr->typePtr != &dictSubstObjType) {
Jim_Obj *varObjPtr, *keyObjPtr;
if (objPtr->typePtr == &interpolatedObjType) {
- /* An interpolated object in dict-sugar form */
+
const ScriptToken *token = objPtr->internalRep.twoPtrValue.ptr1;
@@ -10804,12 +9246,6 @@ static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
}
}
-/* This function is used to expand [dict get] sugar in the form
- * of $var(INDEX). The function is mainly used by Jim_EvalObj()
- * to deal with tokens of type JIM_TT_DICTSUGAR. objPtr points to an
- * object that is *guaranteed* to be in the form VARNAME(INDEX).
- * The 'index' part is [subst]ituted, and is used to lookup a key inside
- * the [dict]ionary contained in variable VARNAME. */
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)
{
Jim_Obj *resObjPtr = NULL;
@@ -10836,16 +9272,13 @@ static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_Obj *resultObjPtr;
if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
- /* Note that the result has a ref count of 1, but we need a ref count of 0 */
+
resultObjPtr->refCount--;
return resultObjPtr;
}
return NULL;
}
-/* -----------------------------------------------------------------------------
- * CallFrame
- * ---------------------------------------------------------------------------*/
static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent)
{
@@ -10874,14 +9307,14 @@ static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *pare
return cf;
}
-/* Used to invalidate every caching related to callframe stability. */
+
static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
{
cf->id = interp->callFrameEpoch++;
}
-#define JIM_FCF_NONE 0 /* no flags */
-#define JIM_FCF_NOHT 1 /* don't free the hash table */
+#define JIM_FCF_NONE 0
+#define JIM_FCF_NOHT 1
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
{
if (cf->procArgsObjPtr)
@@ -10902,7 +9335,7 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
Jim_DecrRefCount(interp, varPtr->objPtr);
Jim_Free(he->u.val);
- Jim_Free((void *)he->key); /* ATTENTION: const cast */
+ Jim_Free((void *)he->key);
Jim_Free(he);
table[i] = NULL;
he = nextEntry;
@@ -10914,16 +9347,8 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
interp->freeFramesList = cf;
}
-/* -----------------------------------------------------------------------------
- * References
- * ---------------------------------------------------------------------------*/
#ifdef JIM_REFERENCES
-/* References HashTable Type.
- *
- * Keys are jim_wide integers, dynamically allocated for now but in the
- * future it's worth to cache this 8 bytes objects. Values are poitners
- * to Jim_References. */
static void JimReferencesHTValDestructor(void *interp, void *val)
{
Jim_Reference *refPtr = (void *)val;
@@ -10937,7 +9362,7 @@ static void JimReferencesHTValDestructor(void *interp, void *val)
static unsigned int JimReferencesHTHashFunction(const void *key)
{
- /* Only the least significant bits are used. */
+
const jim_wide *widePtr = key;
unsigned int intValue = (unsigned int)*widePtr;
@@ -10969,24 +9394,15 @@ static void JimReferencesHTKeyDestructor(void *privdata, const void *key)
}
static const Jim_HashTableType JimReferencesHashTableType = {
- JimReferencesHTHashFunction, /* hash function */
- JimReferencesHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimReferencesHTKeyCompare, /* key compare */
- JimReferencesHTKeyDestructor, /* key destructor */
- JimReferencesHTValDestructor /* val destructor */
+ JimReferencesHTHashFunction,
+ JimReferencesHTKeyDup,
+ NULL,
+ JimReferencesHTKeyCompare,
+ JimReferencesHTKeyDestructor,
+ JimReferencesHTValDestructor
};
-/* -----------------------------------------------------------------------------
- * Reference object type and References API
- * ---------------------------------------------------------------------------*/
-/* The string representation of references has two features in order
- * to make the GC faster. The first is that every reference starts
- * with a non common character '<', in order to make the string matching
- * faster. The second is that the reference string rep is 42 characters
- * in length, this allows to avoid to check every object with a string
- * repr < 42, and usually there aren't many of these objects. */
#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
@@ -11021,8 +9437,6 @@ void UpdateStringOfReference(struct Jim_Obj *objPtr)
objPtr->length = len;
}
-/* returns true if 'c' is a valid reference tag character.
- * i.e. inside the range [_a-zA-Z0-9] */
static int isrefchar(int c)
{
return (c == '_' || isalnum(c));
@@ -11037,12 +9451,12 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Jim_Reference *refPtr;
Jim_HashEntry *he;
- /* Get the string representation */
+
str = Jim_GetString(objPtr, &len);
- /* Check if it looks like a reference */
+
if (len < JIM_REFERENCE_SPACE)
goto badformat;
- /* Trim spaces */
+
start = str;
end = str + len - 1;
while (*start == ' ')
@@ -11051,30 +9465,30 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
end--;
if (end - start + 1 != JIM_REFERENCE_SPACE)
goto badformat;
- /* <reference.<1234567>.%020> */
+
if (memcmp(start, "<reference.<", 12) != 0)
goto badformat;
if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
goto badformat;
- /* The tag can't contain chars other than a-zA-Z0-9 + '_'. */
+
for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
if (!isrefchar(start[12 + i]))
goto badformat;
}
- /* Extract info from the reference. */
+
memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
refId[20] = '\0';
- /* Try to convert the ID into a jim_wide */
+
if (Jim_StringToWide(refId, &wideValue, 10) != JIM_OK)
goto badformat;
- /* Check if the reference really exists! */
+
he = Jim_FindHashEntry(&interp->references, &wideValue);
if (he == NULL) {
Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
return JIM_ERR;
}
refPtr = he->u.val;
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &referenceObjType;
objPtr->internalRep.refValue.id = wideValue;
@@ -11086,9 +9500,6 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
return JIM_ERR;
}
-/* Returns a new reference pointing to objPtr, having cmdNamePtr
- * as finalizer command (or NULL if there is no finalizer).
- * The returned reference object has refcount = 0. */
Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
{
struct Jim_Reference *refPtr;
@@ -11097,7 +9508,7 @@ Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr,
const char *tag;
int tagLen, i;
- /* Perform the Garbage Collection if needed. */
+
Jim_CollectIfNeeded(interp);
refPtr = Jim_Alloc(sizeof(*refPtr));
@@ -11113,8 +9524,6 @@ Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr,
refObjPtr->internalRep.refValue.id = interp->referenceNextId;
refObjPtr->internalRep.refValue.refPtr = refPtr;
interp->referenceNextId++;
- /* Set the tag. Trimmed at JIM_REFERENCE_TAGLEN. Everything
- * that does not pass the 'isrefchar' test is replaced with '_' */
tag = Jim_GetString(tagPtr, &tagLen);
if (tagLen > JIM_REFERENCE_TAGLEN)
tagLen = JIM_REFERENCE_TAGLEN;
@@ -11158,152 +9567,21 @@ int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPt
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * References Garbage Collection
- * ---------------------------------------------------------------------------*/
-/* This the hash table type for the "MARK" phase of the GC */
+
static const Jim_HashTableType JimRefMarkHashTableType = {
- JimReferencesHTHashFunction, /* hash function */
- JimReferencesHTKeyDup, /* key dup */
- NULL, /* val dup */
- JimReferencesHTKeyCompare, /* key compare */
- JimReferencesHTKeyDestructor, /* key destructor */
- NULL /* val destructor */
+ JimReferencesHTHashFunction,
+ JimReferencesHTKeyDup,
+ NULL,
+ JimReferencesHTKeyCompare,
+ JimReferencesHTKeyDestructor,
+ NULL
};
-/* Performs the garbage collection. */
+
int Jim_Collect(Jim_Interp *interp)
{
- Jim_HashTable marks;
- Jim_HashTableIterator *htiter;
- Jim_HashEntry *he;
- Jim_Obj *objPtr;
int collected = 0;
-
- /* Avoid recursive calls */
- if (interp->lastCollectId == -1) {
- /* Jim_Collect() already running. Return just now. */
- return 0;
- }
- interp->lastCollectId = -1;
-
- /* Mark all the references found into the 'mark' hash table.
- * The references are searched in every live object that
- * is of a type that can contain references. */
- Jim_InitHashTable(&marks, &JimRefMarkHashTableType, NULL);
- objPtr = interp->liveList;
- while (objPtr) {
- if (objPtr->typePtr == NULL || objPtr->typePtr->flags & JIM_TYPE_REFERENCES) {
- const char *str, *p;
- int len;
-
- /* If the object is of type reference, to get the
- * Id is simple... */
- if (objPtr->typePtr == &referenceObjType) {
- Jim_AddHashEntry(&marks, &objPtr->internalRep.refValue.id, NULL);
-#ifdef JIM_DEBUG_GC
- printf("MARK (reference): %d refcount: %d" JIM_NL,
- (int)objPtr->internalRep.refValue.id, objPtr->refCount);
-#endif
- objPtr = objPtr->nextObjPtr;
- continue;
- }
- /* Get the string repr of the object we want
- * to scan for references. */
- p = str = Jim_GetString(objPtr, &len);
- /* Skip objects too little to contain references. */
- if (len < JIM_REFERENCE_SPACE) {
- objPtr = objPtr->nextObjPtr;
- continue;
- }
- /* Extract references from the object string repr. */
- while (1) {
- int i;
- jim_wide id;
- char buf[21];
-
- if ((p = strstr(p, "<reference.<")) == NULL)
- break;
- /* Check if it's a valid reference. */
- if (len - (p - str) < JIM_REFERENCE_SPACE)
- break;
- if (p[41] != '>' || p[19] != '>' || p[20] != '.')
- break;
- for (i = 21; i <= 40; i++)
- if (!isdigit(UCHAR(p[i])))
- break;
- /* Get the ID */
- memcpy(buf, p + 21, 20);
- buf[20] = '\0';
- Jim_StringToWide(buf, &id, 10);
-
- /* Ok, a reference for the given ID
- * was found. Mark it. */
- Jim_AddHashEntry(&marks, &id, NULL);
-#ifdef JIM_DEBUG_GC
- printf("MARK: %d" JIM_NL, (int)id);
-#endif
- p += JIM_REFERENCE_SPACE;
- }
- }
- objPtr = objPtr->nextObjPtr;
- }
-
- /* Run the references hash table to destroy every reference that
- * is not referenced outside (not present in the mark HT). */
- htiter = Jim_GetHashTableIterator(&interp->references);
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
- const jim_wide *refId;
- Jim_Reference *refPtr;
-
- refId = he->key;
- /* Check if in the mark phase we encountered
- * this reference. */
- if (Jim_FindHashEntry(&marks, refId) == NULL) {
-#ifdef JIM_DEBUG_GC
- printf("COLLECTING %d" JIM_NL, (int)*refId);
-#endif
- collected++;
- /* Drop the reference, but call the
- * finalizer first if registered. */
- refPtr = he->u.val;
- if (refPtr->finalizerCmdNamePtr) {
- char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1);
- Jim_Obj *objv[3], *oldResult;
-
- JimFormatReference(refstr, refPtr, *refId);
-
- objv[0] = refPtr->finalizerCmdNamePtr;
- objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, 32);
- objv[2] = refPtr->objPtr;
- Jim_IncrRefCount(objv[0]);
- Jim_IncrRefCount(objv[1]);
- Jim_IncrRefCount(objv[2]);
-
- /* Drop the reference itself */
- Jim_DeleteHashEntry(&interp->references, refId);
-
- /* Call the finalizer. Errors ignored. */
- oldResult = interp->result;
- Jim_IncrRefCount(oldResult);
- Jim_EvalObjVector(interp, 3, objv);
- Jim_SetResult(interp, oldResult);
- Jim_DecrRefCount(interp, oldResult);
-
- Jim_DecrRefCount(interp, objv[0]);
- Jim_DecrRefCount(interp, objv[1]);
- Jim_DecrRefCount(interp, objv[2]);
- }
- else {
- Jim_DeleteHashEntry(&interp->references, refId);
- }
- }
- }
- Jim_FreeHashTableIterator(htiter);
- Jim_FreeHashTable(&marks);
- interp->lastCollectId = interp->referenceNextId;
- interp->lastCollectTime = time(NULL);
return collected;
}
@@ -11335,9 +9613,6 @@ static int JimIsBigEndian(void)
return uval.c[0] == 1;
}
-/* -----------------------------------------------------------------------------
- * Interpreter related functions
- * ---------------------------------------------------------------------------*/
Jim_Interp *Jim_CreateInterp(void)
{
@@ -11345,30 +9620,27 @@ Jim_Interp *Jim_CreateInterp(void)
memset(i, 0, sizeof(*i));
- i->errorFileName = Jim_StrDup("");
i->maxNestingDepth = JIM_MAX_NESTING_DEPTH;
i->lastCollectTime = time(NULL);
- /* Note that we can create objects only after the
- * interpreter liveList and freeList pointers are
- * initialized to NULL. */
Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i);
#ifdef JIM_REFERENCES
Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i);
#endif
- Jim_InitHashTable(&i->sharedStrings, &JimSharedStringsHashTableType, NULL);
Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i);
Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL);
i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL);
i->emptyObj = Jim_NewEmptyStringObj(i);
i->trueObj = Jim_NewIntObj(i, 1);
i->falseObj = Jim_NewIntObj(i, 0);
+ i->errorFileNameObj = i->emptyObj;
i->result = i->emptyObj;
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
i->errorProc = i->emptyObj;
i->currentScriptObj = Jim_NewEmptyStringObj(i);
Jim_IncrRefCount(i->emptyObj);
+ Jim_IncrRefCount(i->errorFileNameObj);
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
@@ -11377,7 +9649,7 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_IncrRefCount(i->trueObj);
Jim_IncrRefCount(i->falseObj);
- /* Initialize key variables every interpreter should contain */
+
Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
@@ -11404,7 +9676,7 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->stackTrace);
Jim_DecrRefCount(i, i->errorProc);
Jim_DecrRefCount(i, i->unknown);
- Jim_Free((void *)i->errorFileName);
+ Jim_DecrRefCount(i, i->errorFileNameObj);
Jim_DecrRefCount(i, i->currentScriptObj);
Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
@@ -11415,14 +9687,12 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_FreeHashTable(&i->assocData);
JimDeleteLocalProcs(i);
- /* Free the call frames list */
+
while (cf) {
prevcf = cf->parentCallFrame;
JimFreeCallFrame(i, cf, JIM_FCF_NONE);
cf = prevcf;
}
- /* Check that the live object list is empty, otherwise
- * there is a memory leak. */
if (i->liveList != NULL) {
objPtr = i->liveList;
@@ -11435,22 +9705,22 @@ void Jim_FreeInterp(Jim_Interp *i)
(void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
if (objPtr->typePtr == &sourceObjType) {
printf("FILE %s LINE %d" JIM_NL,
- objPtr->internalRep.sourceValue.fileName,
+ Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
objPtr->internalRep.sourceValue.lineNumber);
}
objPtr = objPtr->nextObjPtr;
}
printf("-------------------------------------" JIM_NL JIM_NL);
- JimPanic((1, i, "Live list non empty freeing the interpreter! Leak?"));
+ JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
}
- /* Free all the freed objects. */
+
objPtr = i->freeList;
while (objPtr) {
nextObjPtr = objPtr->nextObjPtr;
Jim_Free(objPtr);
objPtr = nextObjPtr;
}
- /* Free cached CallFrame structures */
+
cf = i->freeFramesList;
while (cf) {
nextcf = cf->nextFramePtr;
@@ -11463,25 +9733,10 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_FreeLoadHandles(i);
#endif
- /* Free the sharedString hash table. Make sure to free it
- * after every other Jim_Object was freed. */
- Jim_FreeHashTable(&i->sharedStrings);
- /* Free the interpreter structure. */
+
Jim_Free(i);
}
-/* Returns the call frame relative to the level represented by
- * levelObjPtr. If levelObjPtr == NULL, the * level is assumed to be '1'.
- *
- * This function accepts the 'level' argument in the form
- * of the commands [uplevel] and [upvar].
- *
- * For a function accepting a relative integer as level suitable
- * for implementation of [info level ?level?] check the
- * JimGetCallFrameByInteger() function.
- *
- * Returns NULL on error.
- */
Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
{
long level;
@@ -11503,13 +9758,13 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
level = -1;
}
else {
- /* Convert from a relative to an absolute level */
+
level = interp->framePtr->level - level;
}
}
}
else {
- str = "1"; /* Needed to format the error message. */
+ str = "1";
level = interp->framePtr->level - 1;
}
@@ -11517,7 +9772,7 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
return interp->topFramePtr;
}
if (level > 0) {
- /* Lookup */
+
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) {
if (framePtr->level == level) {
return framePtr;
@@ -11529,9 +9784,6 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
return NULL;
}
-/* Similar to Jim_GetCallFrameByLevel() but the level is specified
- * as a relative integer like in the [info level ?level?] command.
- **/
static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr)
{
long level;
@@ -11539,7 +9791,7 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *leve
if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
if (level <= 0) {
- /* Convert from a relative to an absolute level */
+
level = interp->framePtr->level + level;
}
@@ -11547,7 +9799,7 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *leve
return interp->topFramePtr;
}
- /* Lookup */
+
for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) {
if (framePtr->level == level) {
return framePtr;
@@ -11559,17 +9811,6 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *leve
return NULL;
}
-static void JimSetErrorFileName(Jim_Interp *interp, const char *filename)
-{
- Jim_Free((void *)interp->errorFileName);
- interp->errorFileName = Jim_StrDup(filename);
-}
-
-static void JimSetErrorLineNumber(Jim_Interp *interp, int linenr)
-{
- interp->errorLine = linenr;
-}
-
static void JimResetStackTrace(Jim_Interp *interp)
{
Jim_DecrRefCount(interp, interp->stackTrace);
@@ -11581,16 +9822,12 @@ static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
{
int len;
- /* Increment reference first in case these are the same object */
+
Jim_IncrRefCount(stackTraceObj);
Jim_DecrRefCount(interp, interp->stackTrace);
interp->stackTrace = stackTraceObj;
interp->errorFlag = 1;
- /* This is a bit ugly.
- * If the filename of the last entry of the stack trace is empty,
- * the next stack level should be added.
- */
len = Jim_ListLength(interp, interp->stackTrace);
if (len >= 3) {
Jim_Obj *filenameObj;
@@ -11605,15 +9842,15 @@ static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
}
}
-/* Returns 1 if the stack trace information was used or 0 if not */
+
static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
- const char *filename, int linenr)
+ Jim_Obj *fileNameObj, int linenr)
{
if (strcmp(procname, "unknown") == 0) {
procname = "";
}
- if (!*procname && !*filename) {
- /* No useful info here */
+ if (!*procname && !Jim_Length(fileNameObj)) {
+
return;
}
@@ -11623,27 +9860,19 @@ static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
Jim_IncrRefCount(interp->stackTrace);
}
- /* If we have no procname but the previous element did, merge with that frame */
- if (!*procname && *filename) {
- /* Just a filename. Check the previous entry */
+
+ if (!*procname && Jim_Length(fileNameObj)) {
+
int len = Jim_ListLength(interp, interp->stackTrace);
if (len >= 3) {
- Jim_Obj *procnameObj;
- Jim_Obj *filenameObj;
-
- if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &procnameObj, JIM_NONE) == JIM_OK
- && Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj,
- JIM_NONE) == JIM_OK) {
-
- const char *prev_procname = Jim_String(procnameObj);
- const char *prev_filename = Jim_String(filenameObj);
-
- if (*prev_procname && !*prev_filename) {
- ListSetIndex(interp, interp->stackTrace, len - 2, Jim_NewStringObj(interp,
- filename, -1), 0);
- ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr),
- 0);
+ Jim_Obj *objPtr;
+ if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) {
+
+ if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) {
+
+ ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
+ ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
return;
}
}
@@ -11651,7 +9880,7 @@ static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
}
Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1));
- Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, filename, -1));
+ Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj);
Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr));
}
@@ -11687,53 +9916,6 @@ int Jim_GetExitCode(Jim_Interp *interp)
return interp->exitCode;
}
-/* -----------------------------------------------------------------------------
- * Shared strings.
- * Every interpreter has an hash table where to put shared dynamically
- * allocate strings that are likely to be used a lot of times.
- * For example, in the 'source' object type, there is a pointer to
- * the filename associated with that object. Every script has a lot
- * of this objects with the identical file name, so it is wise to share
- * this info.
- *
- * The API is trivial: Jim_GetSharedString(interp, "foobar")
- * returns the pointer to the shared string. Every time a reference
- * to the string is no longer used, the user should call
- * Jim_ReleaseSharedString(interp, stringPointer). Once no one is using
- * a given string, it is removed from the hash table.
- * ---------------------------------------------------------------------------*/
-const char *Jim_GetSharedString(Jim_Interp *interp, const char *str)
-{
- Jim_HashEntry *he = Jim_FindHashEntry(&interp->sharedStrings, str);
-
- if (he == NULL) {
- char *strCopy = Jim_StrDup(str);
-
- Jim_AddHashEntry(&interp->sharedStrings, strCopy, NULL);
- he = Jim_FindHashEntry(&interp->sharedStrings, strCopy);
- he->u.intval = 1;
- return strCopy;
- }
- else {
- he->u.intval++;
- return he->key;
- }
-}
-
-void Jim_ReleaseSharedString(Jim_Interp *interp, const char *str)
-{
- Jim_HashEntry *he = Jim_FindHashEntry(&interp->sharedStrings, str);
-
- JimPanic((he == NULL, interp, "Jim_ReleaseSharedString called with " "unknown shared string '%s'", str));
-
- if (--he->u.intval == 0) {
- Jim_DeleteHashEntry(&interp->sharedStrings, str);
- }
-}
-
-/* -----------------------------------------------------------------------------
- * Integer object
- * ---------------------------------------------------------------------------*/
#define JIM_INTEGER_SPACE 24
static void UpdateStringOfInt(struct Jim_Obj *objPtr);
@@ -11747,11 +9929,6 @@ static const Jim_ObjType intObjType = {
JIM_TYPE_NONE,
};
-/* A coerced double is closer to an int than a double.
- * It is an int value temporarily masquerading as a double value.
- * i.e. it has the same string value as an int and Jim_GetWide()
- * succeeds, but also Jim_GetDouble() returns the value directly.
- */
static const Jim_ObjType coercedDoubleObjType = {
"coerced-double",
NULL,
@@ -11778,14 +9955,14 @@ int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
const char *str;
if (objPtr->typePtr == &coercedDoubleObjType) {
- /* Simple switcheroo */
+
objPtr->typePtr = &intObjType;
return JIM_OK;
}
- /* Get the string representation */
+
str = Jim_String(objPtr);
- /* Try to convert into a jim_wide */
+
if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
if (flags & JIM_ERRMSG) {
Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
@@ -11796,7 +9973,7 @@ int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
Jim_SetResultString(interp, "Integer value too big to be represented", -1);
return JIM_ERR;
}
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &intObjType;
objPtr->internalRep.wideValue = wideValue;
@@ -11818,7 +9995,7 @@ int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
return JIM_OK;
}
-/* Get a wide but does not set an error if the format is bad. */
+
static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
{
if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR)
@@ -11851,9 +10028,6 @@ Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue)
return objPtr;
}
-/* -----------------------------------------------------------------------------
- * Double object
- * ---------------------------------------------------------------------------*/
#define JIM_DOUBLE_SPACE 30
static void UpdateStringOfDouble(struct Jim_Obj *objPtr);
@@ -11884,13 +10058,10 @@ int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
jim_wide wideValue;
const char *str;
- /* Preserve the string representation.
- * Needed so we can convert back to int without loss
- */
str = Jim_String(objPtr);
#ifdef HAVE_LONG_LONG
- /* Assume a 53 bit mantissa */
+
#define MIN_INT_IN_DOUBLE -(1LL << 53)
#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
@@ -11898,26 +10069,26 @@ int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
&& JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
&& JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
- /* Direct conversion to coerced double */
+
objPtr->typePtr = &coercedDoubleObjType;
return JIM_OK;
}
else
#endif
if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
- /* Managed to convert to an int, so we can use this as a cooerced double */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &coercedDoubleObjType;
objPtr->internalRep.wideValue = wideValue;
return JIM_OK;
}
else {
- /* Try to convert into a double */
+
if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
Jim_SetResultFormatted(interp, "expected number but got \"%#s\"", objPtr);
return JIM_ERR;
}
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
}
objPtr->typePtr = &doubleObjType;
@@ -11954,19 +10125,12 @@ Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue)
return objPtr;
}
-/* -----------------------------------------------------------------------------
- * List object
- * ---------------------------------------------------------------------------*/
static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static void UpdateStringOfList(struct Jim_Obj *objPtr);
static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
-/* Note that while the elements of the list may contain references,
- * the list object itself can't. This basically means that the
- * list object string representation as a whole can't contain references
- * that are not presents in the single elements. */
static const Jim_ObjType listObjType = {
"list",
FreeListInternalRep,
@@ -12003,9 +10167,6 @@ void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
dupPtr->typePtr = &listObjType;
}
-/* The following function checks if a given string can be encoded
- * into a list element without any kind of quoting, surrounded by braces,
- * or using escapes to quote. */
#define JIM_ELESTR_SIMPLE 0
#define JIM_ELESTR_BRACE 1
#define JIM_ELESTR_QUOTE 2
@@ -12013,7 +10174,7 @@ static int ListElementQuotingType(const char *s, int len)
{
int i, level, blevel, trySimple = 1;
- /* Try with the SIMPLE case */
+
if (len == 0)
return JIM_ELESTR_BRACE;
if (s[0] == '#')
@@ -12045,7 +10206,7 @@ static int ListElementQuotingType(const char *s, int len)
return JIM_ELESTR_SIMPLE;
testbrace:
- /* Test if it's possible to do with braces */
+
if (s[len - 1] == '\\')
return JIM_ELESTR_QUOTE;
level = 0;
@@ -12104,8 +10265,6 @@ static int ListElementQuotingType(const char *s, int len)
return JIM_ELESTR_QUOTE;
}
-/* Returns the malloc-ed representation of a string
- * using backslash to quote special chars. */
static char *BackslashQuoteString(const char *s, int len, int *qlenPtr)
{
char *q = Jim_Alloc(len * 2 + 1), *p;
@@ -12168,7 +10327,7 @@ static void UpdateStringOfList(struct Jim_Obj *objPtr)
int *quotingType;
Jim_Obj **ele = objPtr->internalRep.listValue.ele;
- /* (Over) Estimate the space needed. */
+
quotingType = Jim_Alloc(sizeof(int) * objPtr->internalRep.listValue.len + 1);
bufLen = 0;
for (i = 0; i < objPtr->internalRep.listValue.len; i++) {
@@ -12187,11 +10346,11 @@ static void UpdateStringOfList(struct Jim_Obj *objPtr)
bufLen += len * 2;
break;
}
- bufLen++; /* elements separator. */
+ bufLen++;
}
bufLen++;
- /* Generate the string rep. */
+
p = objPtr->bytes = Jim_Alloc(bufLen + 1);
realLength = 0;
for (i = 0; i < objPtr->internalRep.listValue.len; i++) {
@@ -12221,13 +10380,13 @@ static void UpdateStringOfList(struct Jim_Obj *objPtr)
realLength += qlen;
break;
}
- /* Add a separating space */
+
if (i + 1 != objPtr->internalRep.listValue.len) {
*p++ = ' ';
realLength++;
}
}
- *p = '\0'; /* nul term. */
+ *p = '\0';
objPtr->length = realLength;
Jim_Free(quotingType);
}
@@ -12237,27 +10396,30 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
struct JimParserCtx parser;
const char *str;
int strLen;
- const char *filename = NULL;
- int linenr = 1;
+ Jim_Obj *fileNameObj;
+ int linenr;
- /* Try to preserve information about filename / line number */
+
if (objPtr->typePtr == &sourceObjType) {
- filename = Jim_GetSharedString(interp, objPtr->internalRep.sourceValue.fileName);
+ fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
linenr = objPtr->internalRep.sourceValue.lineNumber;
}
+ else {
+ fileNameObj = interp->emptyObj;
+ linenr = 1;
+ }
+ Jim_IncrRefCount(fileNameObj);
- /* Get the string representation */
+
str = Jim_GetString(objPtr, &strLen);
- /* Free the old internal repr just now and initialize the
- * new one just now. The string->list conversion can't fail. */
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &listObjType;
objPtr->internalRep.listValue.len = 0;
objPtr->internalRep.listValue.maxLen = 0;
objPtr->internalRep.listValue.ele = NULL;
- /* Convert into a list */
+
JimParserInit(&parser, str, strLen, linenr);
while (!parser.eof) {
Jim_Obj *elementPtr;
@@ -12266,12 +10428,10 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC)
continue;
elementPtr = JimParserGetTokenObj(interp, &parser);
- JimSetSourceInfo(interp, elementPtr, filename, parser.tline);
+ JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
ListAppendElement(objPtr, elementPtr);
}
- if (filename) {
- Jim_ReleaseSharedString(interp, filename);
- }
+ Jim_DecrRefCount(interp, fileNameObj);
return JIM_OK;
}
@@ -12292,12 +10452,6 @@ Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
return objPtr;
}
-/* Return a vector of Jim_Obj with the elements of a Jim list, and the
- * length of the vector. Note that the user of this function should make
- * sure that the list object can't shimmer while the vector returned
- * is in use, this vector is the one stored inside the internal representation
- * of the list object. This function is not exported, extensions should
- * always access to the List object elements using Jim_ListIndex(). */
static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen,
Jim_Obj ***listVec)
{
@@ -12305,7 +10459,7 @@ static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLe
*listVec = listObj->internalRep.listValue.ele;
}
-/* Sorting uses ints, but commands may return wide */
+
static int JimSign(jim_wide w)
{
if (w == 0) {
@@ -12317,7 +10471,7 @@ static int JimSign(jim_wide w)
return 1;
}
-/* ListSortElements type values */
+
struct lsort_info {
jmp_buf jmpbuf;
Jim_Obj *command;
@@ -12347,7 +10501,7 @@ static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
return sort_info->subfn(&lObj, &rObj);
}
-/* Sort the internal rep of a list. */
+
static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
{
return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order;
@@ -12377,7 +10531,7 @@ static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
jim_wide ret = 0;
- /* This must be a valid list */
+
compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
@@ -12391,7 +10545,7 @@ static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
return JimSign(ret) * sort_info->order;
}
-/* Sort a list *in place*. MUST be called with non-shared objects. */
+
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
{
struct lsort_info *prev_info;
@@ -12402,11 +10556,11 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
int len;
int rc;
- JimPanic((Jim_IsShared(listObjPtr), interp, "Jim_ListSortElements called with shared object"));
+ JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
if (!Jim_IsList(listObjPtr))
SetListFromAny(interp, listObjPtr);
- /* Allow lsort to be called reentrantly */
+
prev_info = sort_info;
sort_info = info;
@@ -12426,12 +10580,12 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
fn = ListSortCommand;
break;
default:
- fn = NULL; /* avoid warning */
- JimPanic((1, interp, "ListSort called with invalid sort type"));
+ fn = NULL;
+ JimPanic((1, "ListSort called with invalid sort type"));
}
if (info->indexed) {
- /* Need to interpose a "list index" function */
+
info->subfn = fn;
fn = ListSortIndexHelper;
}
@@ -12445,13 +10599,6 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
return rc;
}
-/* This is the low-level function to insert elements into a list.
- * The higher-level Jim_ListInsertElements() performs shared object
- * check and invalidate the string repr. This version is used
- * in the internals of the List Object and is not exported.
- *
- * NOTE: this function can be called only against objects
- * with internal type of List. */
static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
{
int currentLen = listPtr->internalRep.listValue.len;
@@ -12475,18 +10622,12 @@ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *co
listPtr->internalRep.listValue.len += elemc;
}
-/* Convenience call to ListInsertElements() to append a single element.
- */
static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr)
{
ListInsertElements(listPtr, listPtr->internalRep.listValue.len, 1, &objPtr);
}
-/* Appends every element of appendListPtr into listPtr.
- * Both have to be of the list type.
- * Convenience call to ListInsertElements()
- */
static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr)
{
ListInsertElements(listPtr, listPtr->internalRep.listValue.len,
@@ -12495,7 +10636,7 @@ static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr)
void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr)
{
- JimPanic((Jim_IsShared(listPtr), interp, "Jim_ListAppendElement called with shared object"));
+ JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object"));
if (!Jim_IsList(listPtr))
SetListFromAny(interp, listPtr);
Jim_InvalidateStringRep(listPtr);
@@ -12504,7 +10645,7 @@ void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr
void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr)
{
- JimPanic((Jim_IsShared(listPtr), interp, "Jim_ListAppendList called with shared object"));
+ JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object"));
if (!Jim_IsList(listPtr))
SetListFromAny(interp, listPtr);
Jim_InvalidateStringRep(listPtr);
@@ -12521,7 +10662,7 @@ int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr)
void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
int objc, Jim_Obj *const *objVec)
{
- JimPanic((Jim_IsShared(listPtr), interp, "Jim_ListInsertElement called with shared object"));
+ JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object"));
if (!Jim_IsList(listPtr))
SetListFromAny(interp, listPtr);
if (idx >= 0 && idx > listPtr->internalRep.listValue.len)
@@ -12570,9 +10711,6 @@ static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
return JIM_OK;
}
-/* Modify the list stored into the variable named 'varNamePtr'
- * setting the element specified by the 'indexc' indexes objects in 'indexv',
- * with the new element 'newObjptr'. */
int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
{
@@ -12618,9 +10756,6 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
int i;
- /* If all the objects in objv are lists,
- * it's possible to return a list as result, that's the
- * concatenation of all the lists. */
for (i = 0; i < objc; i++) {
if (!Jim_IsList(objv[i]))
break;
@@ -12633,32 +10768,32 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
return objPtr;
}
else {
- /* Else... we have to glue strings together */
+
int len = 0, objLen;
char *bytes, *p;
- /* Compute the length */
+
for (i = 0; i < objc; i++) {
Jim_GetString(objv[i], &objLen);
len += objLen;
}
if (objc)
len += objc - 1;
- /* Create the string rep, and a string object holding it. */
+
p = bytes = Jim_Alloc(len + 1);
for (i = 0; i < objc; i++) {
const char *s = Jim_GetString(objv[i], &objLen);
- /* Remove leading space */
+
while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
s++;
objLen--;
len--;
}
- /* And trailing space */
+
while (objLen && (s[objLen - 1] == ' ' ||
s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
- /* Handle trailing backslash-space case */
+
if (objLen > 1 && s[objLen - 2] == '\\') {
break;
}
@@ -12671,8 +10806,6 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
*p++ = ' ';
}
else if (i + 1 != objc) {
- /* Drop the space calcuated for this
- * element that is instead null. */
len--;
}
}
@@ -12681,9 +10814,6 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
}
}
-/* Returns a list composed of the elements in the specified range.
- * first and start are directly accepted as Jim_Objects and
- * processed for the end?-index? case. */
Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr,
Jim_Obj *lastObjPtr)
{
@@ -12693,7 +10823,7 @@ Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstOb
if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
return NULL;
- len = Jim_ListLength(interp, listObjPtr); /* will convert into list */
+ len = Jim_ListLength(interp, listObjPtr);
first = JimRelToAbsIndex(len, first);
last = JimRelToAbsIndex(len, last);
JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
@@ -12703,17 +10833,11 @@ Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstOb
return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen);
}
-/* -----------------------------------------------------------------------------
- * Dict object
- * ---------------------------------------------------------------------------*/
static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static void UpdateStringOfDict(struct Jim_Obj *objPtr);
static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
-/* Dict HashTable Type.
- *
- * Keys and Values are Jim objects. */
static unsigned int JimObjectHTHashFunction(const void *key)
{
@@ -12741,19 +10865,15 @@ static void JimObjectHTKeyValDestructor(void *interp, void *val)
}
static const Jim_HashTableType JimDictHashTableType = {
- JimObjectHTHashFunction, /* hash function */
- NULL, /* key dup */
- NULL, /* val dup */
- JimObjectHTKeyCompare, /* key compare */
- (void (*)(void *, const void *)) /* ATTENTION: const cast */
- JimObjectHTKeyValDestructor, /* key destructor */
- JimObjectHTKeyValDestructor /* val destructor */
+ JimObjectHTHashFunction,
+ NULL,
+ NULL,
+ JimObjectHTKeyCompare,
+ (void (*)(void *, const void *))
+ JimObjectHTKeyValDestructor,
+ JimObjectHTKeyValDestructor
};
-/* Note that while the elements of the dict may contain references,
- * the list object itself can't. This basically means that the
- * dict object string representation as a whole can't contain references
- * that are not presents in the single elements. */
static const Jim_ObjType dictObjType = {
"dict",
FreeDictInternalRep,
@@ -12776,19 +10896,19 @@ void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
Jim_HashTableIterator *htiter;
Jim_HashEntry *he;
- /* Create a new hash table */
+
ht = srcPtr->internalRep.ptr;
dupHt = Jim_Alloc(sizeof(*dupHt));
Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
if (ht->size != 0)
Jim_ExpandHashTable(dupHt, ht->size);
- /* Copy every element from the source to the dup hash table */
+
htiter = Jim_GetHashTableIterator(ht);
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
const Jim_Obj *keyObjPtr = he->key;
Jim_Obj *valObjPtr = he->u.val;
- Jim_IncrRefCount((Jim_Obj *)keyObjPtr); /* ATTENTION: const cast */
+ Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
Jim_IncrRefCount(valObjPtr);
Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
}
@@ -12809,18 +10929,18 @@ void UpdateStringOfDict(struct Jim_Obj *objPtr)
Jim_HashEntry *he;
Jim_Obj **objv;
- /* Trun the hash table into a flat vector of Jim_Objects. */
+
ht = objPtr->internalRep.ptr;
objc = ht->used * 2;
objv = Jim_Alloc(objc * sizeof(Jim_Obj *));
htiter = Jim_GetHashTableIterator(ht);
i = 0;
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
- objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
+ objv[i++] = (Jim_Obj *)he->key;
objv[i++] = he->u.val;
}
Jim_FreeHashTableIterator(htiter);
- /* (Over) Estimate the space needed. */
+
quotingType = Jim_Alloc(sizeof(int) * objc);
bufLen = 0;
for (i = 0; i < objc; i++) {
@@ -12839,11 +10959,11 @@ void UpdateStringOfDict(struct Jim_Obj *objPtr)
bufLen += len * 2;
break;
}
- bufLen++; /* elements separator. */
+ bufLen++;
}
bufLen++;
- /* Generate the string rep. */
+
p = objPtr->bytes = Jim_Alloc(bufLen + 1);
realLength = 0;
for (i = 0; i < objc; i++) {
@@ -12873,13 +10993,13 @@ void UpdateStringOfDict(struct Jim_Obj *objPtr)
realLength += qlen;
break;
}
- /* Add a separating space */
+
if (i + 1 != objc) {
*p++ = ' ';
realLength++;
}
}
- *p = '\0'; /* nul term. */
+ *p = '\0';
objPtr->length = realLength;
Jim_Free(quotingType);
Jim_Free(objv);
@@ -12889,12 +11009,9 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
int listlen;
- /* Get the string representation. Do this first so we don't
- * change order in case of fast conversion to dict.
- */
Jim_String(objPtr);
- /* For simplicity, convert a non-list object to a list and then to a dict */
+
listlen = Jim_ListLength(interp, objPtr);
if (listlen % 2) {
Jim_SetResultString(interp,
@@ -12902,7 +11019,7 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
return JIM_ERR;
}
else {
- /* Now it is easy to convert to a dict from a list, and it can't fail */
+
Jim_HashTable *ht;
int i;
@@ -12924,7 +11041,7 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
he = Jim_FindHashEntry(ht, keyObjPtr);
Jim_DecrRefCount(interp, keyObjPtr);
- /* ATTENTION: const cast */
+
Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
he->u.val = valObjPtr;
}
@@ -12938,20 +11055,14 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
}
-/* Dict object API */
-/* Add an element to a dict. objPtr must be of the "dict" type.
- * The higer-level exported function is Jim_DictAddElement().
- * If an element with the specified key already exists, the value
- * associated is replaced with the new one.
- *
- * if valueObjPtr == NULL, the key is instead removed if it exists. */
+
static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
Jim_HashTable *ht = objPtr->internalRep.ptr;
- if (valueObjPtr == NULL) { /* unset */
+ if (valueObjPtr == NULL) {
return Jim_DeleteHashEntry(ht, keyObjPtr);
}
Jim_IncrRefCount(keyObjPtr);
@@ -12960,21 +11071,19 @@ static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_HashEntry *he = Jim_FindHashEntry(ht, keyObjPtr);
Jim_DecrRefCount(interp, keyObjPtr);
- /* ATTENTION: const cast */
+
Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
he->u.val = valueObjPtr;
}
return JIM_OK;
}
-/* Add an element, higher-level interface for DictAddElement().
- * If valueObjPtr == NULL, the key is removed if it exists. */
int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
{
int retcode;
- JimPanic((Jim_IsShared(objPtr), interp, "Jim_DictAddElement called with shared object"));
+ JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
if (objPtr->typePtr != &dictObjType) {
if (SetDictFromAny(interp, objPtr) != JIM_OK)
return JIM_ERR;
@@ -12989,7 +11098,7 @@ Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
Jim_Obj *objPtr;
int i;
- JimPanic((len % 2, interp, "Jim_NewDictObj() 'len' argument must be even"));
+ JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even"));
objPtr = Jim_NewObj(interp);
objPtr->typePtr = &dictObjType;
@@ -13001,9 +11110,6 @@ Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
return objPtr;
}
-/* Return the value associated to the specified dict key
- * Note: Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value
- */
int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
Jim_Obj **objPtrPtr, int flags)
{
@@ -13025,7 +11131,7 @@ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
return JIM_OK;
}
-/* Return an allocated array of key/value pairs for the dictionary. Stores the length in *len */
+
int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
{
Jim_HashTable *ht;
@@ -13040,12 +11146,12 @@ int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, in
}
ht = dictPtr->internalRep.ptr;
- /* Turn the hash table into a flat vector of Jim_Objects. */
+
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
htiter = Jim_GetHashTableIterator(ht);
i = 0;
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
- objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
+ objv[i++] = (Jim_Obj *)he->key;
objv[i++] = he->u.val;
}
*len = i;
@@ -13055,7 +11161,7 @@ int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, in
}
-/* Return the value associated to the specified dict keys */
+
int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags)
{
@@ -13078,14 +11184,8 @@ int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
return JIM_OK;
}
-/* Modify the dict stored into the variable named 'varNamePtr'
- * setting the element specified by the 'keyc' keys objects in 'keyv',
- * with the new value of the element 'newObjPtr'.
- *
- * If newObjPtr == NULL the operation is to remove the given key
- * from the dictionary. */
int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
- Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr)
+ Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags)
{
Jim_Obj *varObjPtr, *objPtr, *dictObjPtr;
int shared, i;
@@ -13093,8 +11193,9 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
varObjPtr = objPtr =
Jim_GetVariable(interp, varNamePtr, newObjPtr == NULL ? JIM_ERRMSG : JIM_NONE);
if (objPtr == NULL) {
- if (newObjPtr == NULL) /* Cannot remove a key from non existing var */
+ if (newObjPtr == NULL) {
return JIM_ERR;
+ }
varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
Jim_FreeNewObj(interp, varObjPtr);
@@ -13106,41 +11207,40 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
for (i = 0; i < keyc - 1; i++) {
dictObjPtr = objPtr;
- /* Check if it's a valid dictionary */
+
if (dictObjPtr->typePtr != &dictObjType) {
- if (SetDictFromAny(interp, dictObjPtr) != JIM_OK)
+ if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
goto err;
+ }
}
- /* Check if the given key exists. */
+
Jim_InvalidateStringRep(dictObjPtr);
if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
- /* This key exists at the current level.
- * Make sure it's not shared!. */
if (Jim_IsShared(objPtr)) {
objPtr = Jim_DuplicateObj(interp, objPtr);
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
}
}
else {
- /* Key not found. If it's an [unset] operation
- * this is an error. Only the last key may not
- * exist. */
- if (newObjPtr == NULL)
+ if (newObjPtr == NULL) {
goto err;
- /* Otherwise set an empty dictionary
- * as key's value. */
+ }
objPtr = Jim_NewDictObj(interp, NULL, 0);
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
}
}
+
if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
- goto err;
+ if (newObjPtr || (flags & JIM_ERRMSG)) {
+ goto err;
+ }
}
Jim_InvalidateStringRep(objPtr);
Jim_InvalidateStringRep(varObjPtr);
- if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK)
+ if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
goto err;
+ }
Jim_SetResult(interp, varObjPtr);
return JIM_OK;
err:
@@ -13150,9 +11250,6 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
return JIM_ERR;
}
-/* -----------------------------------------------------------------------------
- * Index object
- * ---------------------------------------------------------------------------*/
static void UpdateStringOfIndex(struct Jim_Obj *objPtr);
static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
@@ -13187,10 +11284,10 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
const char *str;
char *endptr;
- /* Get the string representation */
+
str = Jim_String(objPtr);
- /* Try to convert into an index */
+
if (strncmp(str, "end", 3) == 0) {
end = 1;
str += 3;
@@ -13205,7 +11302,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
str = endptr;
}
- /* Now str may include or +<num> or -<num> */
+
if (*str == '+' || *str == '-') {
int sign = (*str == '+' ? 1 : -1);
@@ -13215,7 +11312,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
}
str = endptr;
}
- /* The only thing left should be spaces */
+
while (isspace(UCHAR(*str))) {
str++;
}
@@ -13227,7 +11324,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
idx = INT_MAX;
}
else {
- /* end-1 is repesented as -2 */
+
idx--;
}
}
@@ -13235,7 +11332,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
idx = -INT_MAX;
}
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &indexObjType;
objPtr->internalRep.indexValue = idx;
@@ -13249,7 +11346,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
{
- /* Avoid shimmering if the object is an integer. */
+
if (objPtr->typePtr == &intObjType) {
jim_wide val = JimWideValue(objPtr);
@@ -13264,11 +11361,8 @@ int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Return Code Object.
- * ---------------------------------------------------------------------------*/
-/* NOTE: These must be kept in the same order as JIM_OK, JIM_ERR, ... */
+
static const char * const jimReturnCodes[] = {
[JIM_OK] = "ok",
[JIM_ERR] = "error",
@@ -13293,9 +11387,6 @@ static const Jim_ObjType returnCodeObjType = {
JIM_TYPE_NONE,
};
-/* Converts a (standard) return code to a string. Returns "?" for
- * non-standard return codes.
- */
const char *Jim_ReturnCode(int code)
{
if (code < 0 || code >= (int)jimReturnCodesSize) {
@@ -13311,14 +11402,14 @@ int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
int returnCode;
jim_wide wideValue;
- /* Try to convert into an integer */
+
if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
returnCode = (int)wideValue;
else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
return JIM_ERR;
}
- /* Free the old internal repr and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
objPtr->typePtr = &returnCodeObjType;
objPtr->internalRep.returnCode = returnCode;
@@ -13333,21 +11424,18 @@ int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr)
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Expression Parsing
- * ---------------------------------------------------------------------------*/
static int JimParseExprOperator(struct JimParserCtx *pc);
static int JimParseExprNumber(struct JimParserCtx *pc);
static int JimParseExprIrrational(struct JimParserCtx *pc);
-/* Exrp's Stack machine operators opcodes. */
-/* Binary operators (numbers) */
+
+
enum
{
- /* Continues on from the JIM_TT_ space */
- /* Operations */
- JIM_EXPROP_MUL = JIM_TT_EXPR_OP, /* 15 */
+
+
+ JIM_EXPROP_MUL = JIM_TT_EXPR_OP,
JIM_EXPROP_DIV,
JIM_EXPROP_MOD,
JIM_EXPROP_SUB,
@@ -13362,46 +11450,46 @@ enum
JIM_EXPROP_GTE,
JIM_EXPROP_NUMEQ,
JIM_EXPROP_NUMNE,
- JIM_EXPROP_BITAND, /* 30 */
+ JIM_EXPROP_BITAND,
JIM_EXPROP_BITXOR,
JIM_EXPROP_BITOR,
- /* Note must keep these together */
- JIM_EXPROP_LOGICAND, /* 33 */
+
+ JIM_EXPROP_LOGICAND,
JIM_EXPROP_LOGICAND_LEFT,
JIM_EXPROP_LOGICAND_RIGHT,
- /* and these */
- JIM_EXPROP_LOGICOR, /* 36 */
+
+ JIM_EXPROP_LOGICOR,
JIM_EXPROP_LOGICOR_LEFT,
JIM_EXPROP_LOGICOR_RIGHT,
- /* and these */
- /* Ternary operators */
- JIM_EXPROP_TERNARY, /* 39 */
+
+
+ JIM_EXPROP_TERNARY,
JIM_EXPROP_TERNARY_LEFT,
JIM_EXPROP_TERNARY_RIGHT,
- /* and these */
- JIM_EXPROP_COLON, /* 42 */
+
+ JIM_EXPROP_COLON,
JIM_EXPROP_COLON_LEFT,
JIM_EXPROP_COLON_RIGHT,
- JIM_EXPROP_POW, /* 45 */
+ JIM_EXPROP_POW,
+
-/* Binary operators (strings) */
JIM_EXPROP_STREQ,
JIM_EXPROP_STRNE,
JIM_EXPROP_STRIN,
JIM_EXPROP_STRNI,
-/* Unary operators (numbers) */
+
JIM_EXPROP_NOT,
JIM_EXPROP_BITNOT,
JIM_EXPROP_UNARYMINUS,
JIM_EXPROP_UNARYPLUS,
- /* Functions */
+
JIM_EXPROP_FUNC_FIRST,
JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
JIM_EXPROP_FUNC_ABS,
@@ -13411,7 +11499,7 @@ enum
JIM_EXPROP_FUNC_SRAND,
#ifdef JIM_MATH_FUNCTIONS
- /* math functions from libm */
+
JIM_EXPROP_FUNC_SIN,
JIM_EXPROP_FUNC_COS,
JIM_EXPROP_FUNC_TAN,
@@ -13438,7 +11526,7 @@ struct JimExprState
int skip;
};
-/* Operators table */
+
typedef struct Jim_ExprOperator
{
const char *name;
@@ -13577,7 +11665,7 @@ static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
{
- JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND));
+ JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
@@ -13651,7 +11739,7 @@ static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
}
#endif
-/* A binary operation on two ints */
+
static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
{
Jim_Obj *B = ExprPop(e);
@@ -13687,14 +11775,6 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
rc = JIM_ERR;
}
else {
- /*
- * From Tcl 8.x
- *
- * This code is tricky: C doesn't guarantee much
- * about the quotient or remainder, but Tcl does.
- * The remainder always has the same sign as the
- * divisor and a smaller absolute value.
- */
int negative = 0;
if (wB < 0) {
@@ -13713,12 +11793,12 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
break;
case JIM_EXPROP_ROTL:
case JIM_EXPROP_ROTR:{
- /* uint32_t would be better. But not everyone has inttypes.h? */
+
unsigned long uA = (unsigned long)wA;
unsigned long uB = (unsigned long)wB;
const unsigned int S = sizeof(unsigned long) * 8;
- /* Shift left by the word size or more is undefined. */
+
uB %= S;
if (e->opcode == JIM_EXPROP_ROTR) {
@@ -13741,7 +11821,7 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
}
-/* A binary operation on two ints or two doubles (or two strings for some ops) */
+
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
{
int intresult = 0;
@@ -13756,7 +11836,7 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
(B->typePtr != &doubleObjType || B->bytes) &&
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
- /* Both are ints */
+
intresult = 1;
@@ -13779,14 +11859,6 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
rc = JIM_ERR;
}
else {
- /*
- * From Tcl 8.x
- *
- * This code is tricky: C doesn't guarantee much
- * about the quotient or remainder, but Tcl does.
- * The remainder always has the same sign as the
- * divisor and a smaller absolute value.
- */
if (wB < 0) {
wB = -wB;
wA = -wA;
@@ -13879,9 +11951,9 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
}
}
else {
- /* Handle the string case */
+
- /* REVISIT: Could optimise the eq/ne case by checking lengths */
+
int i = Jim_StringCompareObj(interp, A, B, 0);
intresult = 1;
@@ -14005,17 +12077,17 @@ static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
switch (ExprBool(interp, A)) {
case 0:
- /* false, so skip RHS opcodes with a 0 result */
+
e->skip = JimWideValue(skip);
ExprPush(e, Jim_NewIntObj(interp, 0));
break;
case 1:
- /* true so continue */
+
break;
case -1:
- /* Invalid */
+
rc = JIM_ERR;
}
Jim_DecrRefCount(interp, A);
@@ -14032,17 +12104,17 @@ static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e)
switch (ExprBool(interp, A)) {
case 0:
- /* false, so do nothing */
+
break;
case 1:
- /* true so skip RHS opcodes with a 1 result */
+
e->skip = JimWideValue(skip);
ExprPush(e, Jim_NewIntObj(interp, 1));
break;
case -1:
- /* Invalid */
+
rc = JIM_ERR;
break;
}
@@ -14067,7 +12139,7 @@ static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e)
break;
case -1:
- /* Invalid */
+
rc = JIM_ERR;
break;
}
@@ -14082,23 +12154,23 @@ static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e)
Jim_Obj *A = ExprPop(e);
int rc = JIM_OK;
- /* Repush A */
+
ExprPush(e, A);
switch (ExprBool(interp, A)) {
case 0:
- /* false, skip RHS opcodes */
+
e->skip = JimWideValue(skip);
- /* Push a dummy value */
+
ExprPush(e, Jim_NewIntObj(interp, 0));
break;
case 1:
- /* true so do nothing */
+
break;
case -1:
- /* Invalid */
+
rc = JIM_ERR;
break;
}
@@ -14114,11 +12186,11 @@ static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e)
Jim_Obj *B = ExprPop(e);
Jim_Obj *A = ExprPop(e);
- /* No need to check for A as non-boolean */
+
if (ExprBool(interp, A)) {
- /* true, so skip RHS opcodes */
+
e->skip = JimWideValue(skip);
- /* Repush B as the answer */
+
ExprPush(e, B);
}
@@ -14141,7 +12213,7 @@ enum
LAZY_RIGHT
};
-/* name - precedence - arity - opcode */
+
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
[JIM_EXPROP_FUNC_INT] = {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
[JIM_EXPROP_FUNC_DOUBLE] = {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
@@ -14211,7 +12283,7 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
[JIM_EXPROP_TERNARY] = {"?", 5, 2, JimExprOpNull, LAZY_OP},
[JIM_EXPROP_COLON] = {":", 5, 2, JimExprOpNull, LAZY_OP},
- /* private operators */
+
[JIM_EXPROP_TERNARY_LEFT] = {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
[JIM_EXPROP_TERNARY_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
[JIM_EXPROP_COLON_LEFT] = {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
@@ -14227,8 +12299,11 @@ static const struct Jim_ExprOperator Jim_ExprOperators[] = {
static int JimParseExpression(struct JimParserCtx *pc)
{
- /* Discard spaces and quoted newline */
+
while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
+ if (*pc->p == '\n') {
+ pc->linenr++;
+ }
pc->p++;
pc->len--;
}
@@ -14261,7 +12336,7 @@ static int JimParseExpression(struct JimParserCtx *pc)
if (JimParseVar(pc) == JIM_ERR)
return JimParseExprOperator(pc);
else {
- /* Don't allow expr sugar in expressions */
+
if (pc->tt == JIM_TT_EXPRSUGAR) {
return JIM_ERR;
}
@@ -14304,7 +12379,7 @@ static int JimParseExprNumber(struct JimParserCtx *pc)
int allowdot = 1;
int allowhex = 0;
- /* Assume an integer for now */
+
pc->tt = JIM_TT_EXPR_INT;
pc->tstart = pc->p;
pc->tline = pc->linenr;
@@ -14360,7 +12435,7 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
int i;
int bestIdx = -1, bestLen = 0;
- /* Try to get the longest match. */
+
for (i = JIM_TT_EXPR_OP; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
const char *opname;
int oplen;
@@ -14380,7 +12455,7 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
return JIM_ERR;
}
- /* Validate paretheses around function arguments */
+
if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
const char *p = pc->p + bestLen;
int len = pc->len - bestLen;
@@ -14428,9 +12503,6 @@ const char *jim_tt_name(int type)
}
}
-/* -----------------------------------------------------------------------------
- * Expression Object
- * ---------------------------------------------------------------------------*/
static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
@@ -14443,12 +12515,12 @@ static const Jim_ObjType exprObjType = {
JIM_TYPE_REFERENCES,
};
-/* Expr bytecode structure */
+
typedef struct ExprByteCode
{
- int len; /* Length as number of tokens. */
- ScriptToken *token; /* Tokens array. */
- int inUse; /* Used for sharing. */
+ int len;
+ ScriptToken *token;
+ int inUse;
} ExprByteCode;
static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
@@ -14480,20 +12552,17 @@ static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dup
JIM_NOTUSED(interp);
JIM_NOTUSED(srcPtr);
- /* Just returns an simple string. */
+
dupPtr->typePtr = NULL;
}
-/* Check if an expr program looks correct. */
+
static int ExprCheckCorrectness(ExprByteCode * expr)
{
int i;
int stacklen = 0;
int ternary = 0;
- /* Try to check if there are stack underflows,
- * and make sure at the end of the program there is
- * a single result on the stack. */
for (i = 0; i < expr->len; i++) {
ScriptToken *t = &expr->token[i];
const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
@@ -14511,7 +12580,7 @@ static int ExprCheckCorrectness(ExprByteCode * expr)
}
}
- /* All operations and operands add one to the stack */
+
stacklen++;
}
if (stacklen != 1 || ternary != 0) {
@@ -14520,38 +12589,13 @@ static int ExprCheckCorrectness(ExprByteCode * expr)
return JIM_OK;
}
-/* This procedure converts every occurrence of || and && opereators
- * in lazy unary versions.
- *
- * a b || is converted into:
- *
- * a <offset> |L b |R
- *
- * a b && is converted into:
- *
- * a <offset> &L b &R
- *
- * "|L" checks if 'a' is true:
- * 1) if it is true pushes 1 and skips <offset> instructions to reach
- * the opcode just after |R.
- * 2) if it is false does nothing.
- * "|R" checks if 'b' is true:
- * 1) if it is true pushes 1, otherwise pushes 0.
- *
- * "&L" checks if 'a' is true:
- * 1) if it is true does nothing.
- * 2) If it is false pushes 0 and skips <offset> instructions to reach
- * the opcode just after &R
- * "&R" checks if 'a' is true:
- * if it is true pushes 1, otherwise pushes 0.
- */
static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
{
int i;
int leftindex, arity, offset;
- /* Search for the end of the first operator */
+
leftindex = expr->len - 1;
arity = 1;
@@ -14568,27 +12612,24 @@ static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseTok
}
leftindex++;
- /* Move them up */
+
memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
sizeof(*expr->token) * (expr->len - leftindex));
expr->len += 2;
offset = (expr->len - leftindex) - 1;
- /* Now we rely on the fact the the left and right version have opcodes
- * 1 and 2 after the main opcode respectively
- */
expr->token[leftindex + 1].type = t->type + 1;
expr->token[leftindex + 1].objPtr = interp->emptyObj;
expr->token[leftindex].type = JIM_TT_EXPR_INT;
expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
- /* Now add the 'R' operator */
+
expr->token[expr->len].objPtr = interp->emptyObj;
expr->token[expr->len].type = t->type + 2;
expr->len++;
- /* Do we need to adjust the skip count for any &L, |L, ?L or :L in the left operand? */
+
for (i = leftindex - 1; i > 0; i--) {
if (JimExprOperatorInfoByOpcode(expr->token[i].type)->lazy == LAZY_LEFT) {
if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
@@ -14618,12 +12659,6 @@ static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *
return JIM_OK;
}
-/**
- * Returns the index of the COLON_LEFT to the left of 'right_index'
- * taking into account nesting.
- *
- * The expression *must* be well formed, thus a COLON_LEFT will always be found.
- */
static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
{
int ternary_count = 1;
@@ -14643,16 +12678,10 @@ static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
right_index--;
}
- /*notreached*/
+
return -1;
}
-/**
- * Find the left/right indices for the ternary expression to the left of 'right_index'.
- *
- * Returns 1 if found, and fills in *prev_right_index and *prev_left_index.
- * Otherwise returns 0.
- */
static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
{
int i = right_index - 1;
@@ -14677,51 +12706,6 @@ static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *p
return 0;
}
-/*
-* ExprTernaryReorderExpression description
-* ========================================
-*
-* ?: is right-to-left associative which doesn't work with the stack-based
-* expression engine. The fix is to reorder the bytecode.
-*
-* The expression:
-*
-* expr 1?2:0?3:4
-*
-* Has initial bytecode:
-*
-* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '0' (44=COLON_RIGHT)
-* '2' (40=TERNARY_LEFT) '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT)
-*
-* The fix involves simulating this expression instead:
-*
-* expr 1?2:(0?3:4)
-*
-* With the following bytecode:
-*
-* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '10' (43=COLON_LEFT) '0' '2' (40=TERNARY_LEFT)
-* '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) (44=COLON_RIGHT)
-*
-* i.e. The token COLON_RIGHT at index 8 is moved towards the end of the stack, all tokens above 8
-* are shifted down and the skip count of the token JIM_EXPROP_COLON_LEFT at index 5 is
-* incremented by the amount tokens shifted down. The token JIM_EXPROP_COLON_RIGHT that is moved
-* is identified as immediately preceeding a token JIM_EXPROP_TERNARY_LEFT
-*
-* ExprTernaryReorderExpression works thus as follows :
-* - start from the end of the stack
-* - while walking towards the beginning of the stack
-* if token=JIM_EXPROP_COLON_RIGHT then
-* find the associated token JIM_EXPROP_TERNARY_LEFT, which allows to
-* find the associated token previous(JIM_EXPROP_COLON_RIGHT)
-* find the associated token previous(JIM_EXPROP_LEFT_RIGHT)
-* if all found then
-* perform the rotation
-* update the skip count of the token previous(JIM_EXPROP_LEFT_RIGHT)
-* end if
-* end if
-*
-* Note: care has to be taken for nested ternary constructs!!!
-*/
static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
{
int i;
@@ -14736,47 +12720,25 @@ static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
continue;
}
- /* COLON_RIGHT found: get the indexes needed to move the tokens in the stack (if any) */
+
if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
continue;
}
- /*
- ** rotate tokens down
- **
- ** +-> [i] : JIM_EXPROP_COLON_RIGHT
- ** | | |
- ** | V V
- ** | [...] : ...
- ** | | |
- ** | V V
- ** | [...] : ...
- ** | | |
- ** | V V
- ** +- [prev_right_index] : JIM_EXPROP_COLON_RIGHT
- */
tmp = expr->token[prev_right_index];
for (j = prev_right_index; j < i; j++) {
expr->token[j] = expr->token[j + 1];
}
expr->token[i] = tmp;
- /* Increment the 'skip' count associated to the previous JIM_EXPROP_COLON_LEFT token
- *
- * This is 'colon left increment' = i - prev_right_index
- *
- * [prev_left_index] : JIM_EXPROP_LEFT_RIGHT
- * [prev_left_index-1] : skip_count
- *
- */
JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
- /* Adjust for i-- in the loop */
+
i++;
}
}
-static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist)
+static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
{
Jim_Stack stack;
ExprByteCode *expr;
@@ -14785,7 +12747,7 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
int prevtt = JIM_TT_NONE;
int have_ternary = 0;
- /* -1 for EOL */
+
int count = tokenlist->count - 1;
expr = Jim_Alloc(sizeof(*expr));
@@ -14794,15 +12756,12 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
Jim_InitStack(&stack);
- /* Need extra bytecodes for lazy operators.
- * Also check for the ternary operator
- */
for (i = 0; i < tokenlist->count; i++) {
ParseToken *t = &tokenlist->list[i];
if (JimExprOperatorInfoByOpcode(t->type)->lazy == LAZY_OP) {
count += 2;
- /* Ternary is a lazy op but also needs reordering */
+
if (t->type == JIM_EXPROP_TERNARY) {
have_ternary = 1;
}
@@ -14814,7 +12773,7 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
for (i = 0; i < tokenlist->count && ok; i++) {
ParseToken *t = &tokenlist->list[i];
- /* Next token will be stored here */
+
struct ScriptToken *token = &expr->token[expr->len];
if (t->type == JIM_TT_EOL) {
@@ -14830,6 +12789,10 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
case JIM_TT_CMD:
token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
token->type = t->type;
+ if (t->type == JIM_TT_CMD) {
+
+ JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
+ }
expr->len++;
break;
@@ -14872,11 +12835,11 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
default:{
- /* Must be an operator */
+
const struct Jim_ExprOperator *op;
ParseToken *tt;
- /* Convert -/+ to unary minus or unary plus if necessary */
+
if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
if (t->type == JIM_EXPROP_SUB) {
t->type = JIM_EXPROP_UNARYMINUS;
@@ -14888,12 +12851,12 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
op = JimExprOperatorInfoByOpcode(t->type);
- /* Now handle precedence */
+
while ((tt = Jim_StackPeek(&stack)) != NULL) {
const struct Jim_ExprOperator *tt_op =
JimExprOperatorInfoByOpcode(tt->type);
- /* Note that right-to-left associativity of ?: operator is handled later */
+
if (op->arity != 1 && tt_op->precedence >= op->precedence) {
if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
@@ -14913,7 +12876,7 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
prevtt = t->type;
}
- /* Reduce any remaining subexpr */
+
while (Jim_StackLen(&stack)) {
ParseToken *tt = Jim_StackPop(&stack);
@@ -14933,7 +12896,7 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
}
err:
- /* Free the stack used for the compilation. */
+
Jim_FreeStack(&stack);
for (i = 0; i < expr->len; i++) {
@@ -14949,26 +12912,31 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
}
-/* This method takes the string representation of an expression
- * and generates a program for the Expr's stack-based VM. */
-int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
int exprTextLen;
const char *exprText;
struct JimParserCtx parser;
struct ExprByteCode *expr;
ParseTokenList tokenlist;
+ int line;
+ Jim_Obj *fileNameObj;
int rc = JIM_ERR;
- int line = 1;
- /* Try to get information about filename / line number */
+
if (objPtr->typePtr == &sourceObjType) {
+ fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
line = objPtr->internalRep.sourceValue.lineNumber;
}
+ else {
+ fileNameObj = interp->emptyObj;
+ line = 1;
+ }
+ Jim_IncrRefCount(fileNameObj);
exprText = Jim_GetString(objPtr, &exprTextLen);
- /* Initially tokenise the expression into tokenlist */
+
ScriptTokenListInit(&tokenlist);
JimParserInit(&parser, exprText, exprTextLen, line);
@@ -14996,10 +12964,10 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
#endif
- /* Now create the expression bytecode from the tokenlist */
- expr = ExprCreateByteCode(interp, &tokenlist);
+
+ expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
- /* No longer need the token list */
+
ScriptTokenListFree(&tokenlist);
if (!expr) {
@@ -15019,7 +12987,7 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
#endif
- /* Check program correctness. */
+
if (ExprCheckCorrectness(expr) != JIM_OK) {
ExprFreeByteCode(interp, expr);
goto invalidexpr;
@@ -15028,7 +12996,8 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
rc = JIM_OK;
err:
- /* Free the old internal rep and set the new one. */
+
+ Jim_DecrRefCount(interp, fileNameObj);
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, expr);
objPtr->typePtr = &exprObjType;
@@ -15045,21 +13014,6 @@ static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
}
-/* -----------------------------------------------------------------------------
- * Expressions evaluation.
- * Jim uses a specialized stack-based virtual machine for expressions,
- * that takes advantage of the fact that expr's operators
- * can't be redefined.
- *
- * Jim_EvalExpression() uses the bytecode compiled by
- * SetExprFromAny() method of the "expression" object.
- *
- * On success a Tcl Object containing the result of the evaluation
- * is stored into expResultPtrPtr (having refcount of 1), and JIM_OK is
- * returned.
- * On error the function returns a retcode != to JIM_OK and set a suitable
- * error on the interp.
- * ---------------------------------------------------------------------------*/
#define JIM_EE_STATICSTACK_LEN 10
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
@@ -15072,27 +13026,13 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
expr = JimGetExpression(interp, exprObjPtr);
if (!expr) {
- return JIM_ERR; /* error in expression. */
+ return JIM_ERR;
}
#ifdef JIM_OPTIMIZATION
- /* Check for one of the following common expressions used by while/for
- *
- * CONST
- * $a
- * !$a
- * $a < CONST, $a < $b
- * $a <= CONST, $a <= $b
- * $a > CONST, $a > $b
- * $a >= CONST, $a >= $b
- * $a != CONST, $a != $b
- * $a == CONST, $a == $b
- */
{
Jim_Obj *objPtr;
- /* STEP 1 -- Check if there are the conditions to run the specialized
- * version of while */
switch (expr->len) {
case 1:
@@ -15135,7 +13075,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
case JIM_EXPROP_GTE:
case JIM_EXPROP_NUMEQ:
case JIM_EXPROP_NUMNE:{
- /* optimise ok */
+
jim_wide wideValueA;
jim_wide wideValueB;
@@ -15173,7 +13113,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
case JIM_EXPROP_NUMNE:
cmpRes = wideValueA != wideValueB;
break;
- default: /*notreached */
+ default:
cmpRes = 0;
}
*exprResultPtrPtr =
@@ -15190,16 +13130,10 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
}
#endif
- /* In order to avoid that the internal repr gets freed due to
- * shimmering of the exprObjPtr's object, we make the internal rep
- * shared. */
expr->inUse++;
- /* The stack-based expr VM itself */
+
- /* Stack allocation. Expr programs have the feature that
- * a program of length N can't require a stack longer than
- * N. */
if (expr->len > JIM_EE_STATICSTACK_LEN)
e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
else
@@ -15207,7 +13141,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
e.stacklen = 0;
- /* Execute every instruction */
+
for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
Jim_Obj *objPtr;
@@ -15253,12 +13187,12 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
break;
default:{
- /* Find and execute the operation */
+
e.skip = 0;
e.opcode = expr->token[i].type;
retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
- /* Skip some opcodes if necessary */
+
i += e.skip;
continue;
}
@@ -15309,57 +13243,30 @@ int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * ScanFormat String Object
- * ---------------------------------------------------------------------------*/
-/* This Jim_Obj will held a parsed representation of a format string passed to
- * the Jim_ScanString command. For error diagnostics, the scanformat string has
- * to be parsed in its entirely first and then, if correct, can be used for
- * scanning. To avoid endless re-parsing, the parsed representation will be
- * stored in an internal representation and re-used for performance reason. */
-/* A ScanFmtPartDescr will held the information of /one/ part of the whole
- * scanformat string. This part will later be used to extract information
- * out from the string to be parsed by Jim_ScanString */
typedef struct ScanFmtPartDescr
{
- char type; /* Type of conversion (e.g. c, d, f) */
- char modifier; /* Modify type (e.g. l - long, h - short */
- size_t width; /* Maximal width of input to be converted */
- int pos; /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */
- char *arg; /* Specification of a CHARSET conversion */
- char *prefix; /* Prefix to be scanned literally before conversion */
+ char type;
+ char modifier;
+ size_t width;
+ int pos;
+ char *arg;
+ char *prefix;
} ScanFmtPartDescr;
-/* The ScanFmtStringObj will hold the internal representation of a scanformat
- * string parsed and separated in part descriptions. Furthermore it contains
- * the original string representation of the scanformat string to allow for
- * fast update of the Jim_Obj's string representation part.
- *
- * As an add-on the internal object representation adds some scratch pad area
- * for usage by Jim_ScanString to avoid endless allocating and freeing of
- * memory for purpose of string scanning.
- *
- * The error member points to a static allocated string in case of a mal-
- * formed scanformat string or it contains '0' (NULL) in case of a valid
- * parse representation.
- *
- * The whole memory of the internal representation is allocated as a single
- * area of memory that will be internally separated. So freeing and duplicating
- * of such an object is cheap */
typedef struct ScanFmtStringObj
{
- jim_wide size; /* Size of internal repr in bytes */
- char *stringRep; /* Original string representation */
- size_t count; /* Number of ScanFmtPartDescr contained */
- size_t convCount; /* Number of conversions that will assign */
- size_t maxPos; /* Max position index if XPG3 is used */
- const char *error; /* Ptr to error text (NULL if no error */
- char *scratch; /* Some scratch pad used by Jim_ScanString */
- ScanFmtPartDescr descr[1]; /* The vector of partial descriptions */
+ jim_wide size;
+ char *stringRep;
+ size_t count;
+ size_t convCount;
+ size_t maxPos;
+ const char *error;
+ char *scratch;
+ ScanFmtPartDescr descr[1];
} ScanFmtStringObj;
@@ -15401,12 +13308,6 @@ void UpdateStringOfScanFmt(Jim_Obj *objPtr)
objPtr->length = strlen(bytes);
}
-/* SetScanFmtFromAny will parse a given string and create the internal
- * representation of the format specification. In case of an error
- * the error data member of the internal representation will be set
- * to an descriptive error text and the function will be left with
- * JIM_ERR to indicate unsucessful parsing (aka. malformed scanformat
- * specification */
static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
@@ -15419,18 +13320,18 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
int curr;
Jim_FreeIntRep(interp, objPtr);
- /* Count how many conversions could take place maximally */
+
for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
if (fmt[i] == '%')
++maxCount;
- /* Calculate an approximation of the memory necessary */
- approxSize = sizeof(ScanFmtStringObj) /* Size of the container */
- +(maxCount + 1) * sizeof(ScanFmtPartDescr) /* Size of all partials */
- +maxFmtLen * sizeof(char) + 3 + 1 /* Scratch + "%n" + '\0' */
- + maxFmtLen * sizeof(char) + 1 /* Original stringrep */
- + maxFmtLen * sizeof(char) /* Arg for CHARSETs */
- +(maxCount + 1) * sizeof(char) /* '\0' for every partial */
- +1; /* safety byte */
+
+ approxSize = sizeof(ScanFmtStringObj)
+ +(maxCount + 1) * sizeof(ScanFmtPartDescr)
+ +maxFmtLen * sizeof(char) + 3 + 1
+ + maxFmtLen * sizeof(char) + 1
+ + maxFmtLen * sizeof(char)
+ +(maxCount + 1) * sizeof(char)
+ +1;
fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
memset(fmtObj, 0, approxSize);
fmtObj->size = approxSize;
@@ -15446,8 +13347,8 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
ScanFmtPartDescr *descr = &fmtObj->descr[curr];
fmtObj->count++;
- descr->width = 0; /* Assume width unspecified */
- /* Overread and store any "literal" prefix */
+ descr->width = 0;
+
if (*fmt != '%' || fmt[1] == '%') {
descr->type = 0;
descr->prefix = &buffer[i];
@@ -15461,35 +13362,35 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
}
buffer[i++] = 0;
}
- /* Skip the conversion introducing '%' sign */
+
++fmt;
- /* End reached due to non-conversion literal only? */
+
if (fmt >= fmtEnd)
goto done;
- descr->pos = 0; /* Assume "natural" positioning */
+ descr->pos = 0;
if (*fmt == '*') {
- descr->pos = -1; /* Okay, conversion will not be assigned */
+ descr->pos = -1;
++fmt;
}
else
- fmtObj->convCount++; /* Otherwise count as assign-conversion */
- /* Check if next token is a number (could be width or pos */
+ fmtObj->convCount++;
+
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
fmt += skip;
- /* Was the number a XPG3 position specifier? */
+
if (descr->pos != -1 && *fmt == '$') {
int prev;
++fmt;
descr->pos = width;
width = 0;
- /* Look if "natural" postioning and XPG3 one was mixed */
+
if ((lastPos == 0 && descr->pos > 0)
|| (lastPos > 0 && descr->pos == 0)) {
fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
return JIM_ERR;
}
- /* Look if this position was already used */
+
for (prev = 0; prev < curr; ++prev) {
if (fmtObj->descr[prev].pos == -1)
continue;
@@ -15499,7 +13400,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
return JIM_ERR;
}
}
- /* Try to find a width after the XPG3 specifier */
+
if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
descr->width = width;
fmt += skip;
@@ -15508,14 +13409,14 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
fmtObj->maxPos = descr->pos;
}
else {
- /* Number was not a XPG3, so it has to be a width */
+
descr->width = width;
}
}
- /* If positioning mode was undetermined yet, fix this */
+
if (lastPos == -1)
lastPos = descr->pos;
- /* Handle CHARSET conversion type ... */
+
if (*fmt == '[') {
int swapped = 1, beg = i, end, j;
@@ -15534,7 +13435,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
}
end = i;
buffer[i++] = 0;
- /* In case a range fence was given "backwards", swap it */
+
while (swapped) {
swapped = 0;
for (j = beg + 1; j < end - 1; ++j) {
@@ -15549,7 +13450,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
}
}
else {
- /* Remember any valid modifier if given */
+
if (strchr("hlL", *fmt) != 0)
descr->modifier = tolower((int)*fmt++);
@@ -15573,7 +13474,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
return JIM_OK;
}
-/* Some accessor macros to allow lowlevel access to fields of internal repr */
+
#define FormatGetCnvCount(_fo_) \
((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount
@@ -15582,10 +13483,6 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
#define FormatGetError(_fo_) \
((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error
-/* JimScanAString is used to scan an unspecified string that ends with
- * next WS, or a string that is specified via a charset.
- *
- */
static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str)
{
char *buffer = Jim_StrDup(str);
@@ -15596,7 +13493,7 @@ static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const cha
int n;
if (!sdescr && isspace(UCHAR(*str)))
- break; /* EOS via WS if unspecified */
+ break;
n = utf8_tounicode(str, &c);
if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
@@ -15608,11 +13505,6 @@ static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const cha
return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer);
}
-/* ScanOneEntry will scan one entry out of the string passed as argument.
- * It use the sscanf() function for this task. After extracting and
- * converting of the value, the count of scanned characters will be
- * returned of -1 in case of no conversion tool place and string was
- * already scanned thru */
static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen,
ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr)
@@ -15624,42 +13516,40 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
int i;
Jim_Obj *tmpObj = NULL;
- /* First pessimistically assume, we will not scan anything :-) */
+
*valObjPtr = 0;
if (descr->prefix) {
- /* There was a prefix given before the conversion, skip it and adjust
- * the string-to-be-parsed accordingly */
- /* XXX: Should be checking strLen, not str[pos] */
+
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
- /* If prefix require, skip WS */
+
if (isspace(UCHAR(descr->prefix[i])))
while (pos < strLen && isspace(UCHAR(str[pos])))
++pos;
else if (descr->prefix[i] != str[pos])
- break; /* Prefix do not match here, leave the loop */
+ break;
else
- ++pos; /* Prefix matched so far, next round */
+ ++pos;
}
if (pos >= strLen) {
- return -1; /* All of str consumed: EOF condition */
+ return -1;
}
else if (descr->prefix[i] != 0)
- return 0; /* Not whole prefix consumed, no conversion possible */
+ return 0;
}
- /* For all but following conversion, skip leading WS */
+
if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
while (isspace(UCHAR(str[pos])))
++pos;
- /* Determine how much skipped/scanned so far */
+
scanned = pos - anchor;
- /* %c is a special, simple case. no width */
+
if (descr->type == 'n') {
- /* Return pseudo conversion means: how much scanned so far? */
+
*valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
}
else if (pos >= strLen) {
- /* Cannot scan anything, as str is totally consumed */
+
return -1;
}
else if (descr->type == 'c') {
@@ -15669,10 +13559,8 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
return scanned;
}
else {
- /* Processing of conversions follows ... */
+
if (descr->width > 0) {
- /* Do not try to scan as fas as possible but only the given width.
- * To ensure this, we copy the part that should be scanned. */
size_t sLen = utf8_strlen(&str[pos], strLen - pos);
size_t tLen = descr->width > sLen ? sLen : descr->width;
@@ -15680,7 +13568,7 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
tok = tmpObj->bytes;
}
else {
- /* As no width was given, simply refer to the original string */
+
tok = &str[pos];
}
switch (descr->type) {
@@ -15689,34 +13577,26 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
case 'x':
case 'u':
case 'i':{
- char *endp; /* Position where the number finished */
+ char *endp;
jim_wide w;
int base = descr->type == 'o' ? 8
: descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
- /* Try to scan a number with the given base */
+
w = strtoull(tok, &endp, base);
if (endp == tok && base == 0) {
- /* If scanning failed, and base was undetermined, simply
- * put it to 10 and try once more. This should catch the
- * case where %i begin to parse a number prefix (e.g.
- * '0x' but no further digits follows. This will be
- * handled as a ZERO followed by a char 'x' by Tcl */
w = strtoull(tok, &endp, 10);
}
if (endp != tok) {
- /* There was some number sucessfully scanned! */
+
*valObjPtr = Jim_NewIntObj(interp, w);
- /* Adjust the number-of-chars scanned so far */
+
scanned += endp - tok;
}
else {
- /* Nothing was scanned. We have to determine if this
- * happened due to e.g. prefix mismatch or input str
- * exhausted */
scanned = *tok ? 0 : -1;
}
break;
@@ -15734,22 +13614,17 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
double value = strtod(tok, &endp);
if (endp != tok) {
- /* There was some number sucessfully scanned! */
+
*valObjPtr = Jim_NewDoubleObj(interp, value);
- /* Adjust the number-of-chars scanned so far */
+
scanned += endp - tok;
}
else {
- /* Nothing was scanned. We have to determine if this
- * happened due to e.g. prefix mismatch or input str
- * exhausted */
scanned = *tok ? 0 : -1;
}
break;
}
}
- /* If a substring was allocated (due to pre-defined width) do not
- * forget to free it */
if (tmpObj) {
Jim_FreeNewObj(interp, tmpObj);
}
@@ -15757,9 +13632,6 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
return scanned;
}
-/* Jim_ScanString is the workhorse of string scanning. It will scan a given
- * string and returns all converted (and not ignored) values in a list back
- * to the caller. If an error occured, a NULL pointer will be returned */
Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags)
{
@@ -15773,61 +13645,61 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
Jim_Obj *emptyStr = 0;
ScanFmtStringObj *fmtObj;
- /* This should never happen. The format object should already be of the correct type */
- JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, interp, "Jim_ScanString() for non-scan format"));
+
+ JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
- /* Check if format specification was valid */
+
if (fmtObj->error != 0) {
if (flags & JIM_ERRMSG)
Jim_SetResultString(interp, fmtObj->error, -1);
return 0;
}
- /* Allocate a new "shared" empty string for all unassigned conversions */
+
emptyStr = Jim_NewEmptyStringObj(interp);
Jim_IncrRefCount(emptyStr);
- /* Create a list and fill it with empty strings up to max specified XPG3 */
+
resultList = Jim_NewListObj(interp, 0, 0);
if (fmtObj->maxPos > 0) {
for (i = 0; i < fmtObj->maxPos; ++i)
Jim_ListAppendElement(interp, resultList, emptyStr);
JimListGetElements(interp, resultList, &resultc, &resultVec);
}
- /* Now handle every partial format description */
+
for (i = 0, pos = 0; i < fmtObj->count; ++i) {
ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
Jim_Obj *value = 0;
- /* Only last type may be "literal" w/o conversion - skip it! */
+
if (descr->type == 0)
continue;
- /* As long as any conversion could be done, we will proceed */
+
if (scanned > 0)
scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
- /* In case our first try results in EOF, we will leave */
+
if (scanned == -1 && i == 0)
goto eof;
- /* Advance next pos-to-be-scanned for the amount scanned already */
+
pos += scanned;
- /* value == 0 means no conversion took place so take empty string */
+
if (value == 0)
value = Jim_NewEmptyStringObj(interp);
- /* If value is a non-assignable one, skip it */
+
if (descr->pos == -1) {
Jim_FreeNewObj(interp, value);
}
else if (descr->pos == 0)
- /* Otherwise append it to the result list if no XPG3 was given */
+
Jim_ListAppendElement(interp, resultList, value);
else if (resultVec[descr->pos - 1] == emptyStr) {
- /* But due to given XPG3, put the value into the corr. slot */
+
Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
Jim_IncrRefCount(value);
resultVec[descr->pos - 1] = value;
}
else {
- /* Otherwise, the slot was already used - free obj and ERROR */
+
Jim_FreeNewObj(interp, value);
goto err;
}
@@ -15844,10 +13716,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
return 0;
}
-/* -----------------------------------------------------------------------------
- * Pseudo Random Number Generation
- * ---------------------------------------------------------------------------*/
-/* Initialize the sbox with the numbers from 0 to 255 */
+
static void JimPrngInit(Jim_Interp *interp)
{
#define PRNG_SEED_SIZE 256
@@ -15865,18 +13734,18 @@ static void JimPrngInit(Jim_Interp *interp)
Jim_Free(seed);
}
-/* Generates N bytes of random data */
+
static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len)
{
Jim_PrngState *prng;
unsigned char *destByte = (unsigned char *)dest;
unsigned int si, sj, x;
- /* initialization, only needed the first time */
+
if (interp->prngState == NULL)
JimPrngInit(interp);
prng = interp->prngState;
- /* generates 'len' bytes of pseudo-random numbers */
+
for (x = 0; x < len; x++) {
prng->i = (prng->i + 1) & 0xff;
si = prng->sbox[prng->i];
@@ -15888,21 +13757,21 @@ static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len)
}
}
-/* Re-seed the generator with user-provided bytes */
+
static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
{
int i;
Jim_PrngState *prng;
- /* initialization, only needed the first time */
+
if (interp->prngState == NULL)
JimPrngInit(interp);
prng = interp->prngState;
- /* Set the sbox[i] with i */
+
for (i = 0; i < 256; i++)
prng->sbox[i] = i;
- /* Now use the seed to perform a random permutation of the sbox */
+
for (i = 0; i < seedLen; i++) {
unsigned char t;
@@ -15912,15 +13781,12 @@ static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
}
prng->i = prng->j = 0;
- /* discard at least the first 256 bytes of stream.
- * borrow the seed buffer for this
- */
for (i = 0; i < 256; i += seedLen) {
JimRandomBytes(interp, seed, seedLen);
}
}
-/* [incr] */
+
static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
jim_wide wideValue, increment = 1;
@@ -15936,7 +13802,7 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!intObjPtr) {
- /* Set missing variable to 0 */
+
wideValue = 0;
}
else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
@@ -15950,14 +13816,12 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
}
else {
- /* Can do it the quick way */
+
Jim_InvalidateStringRep(intObjPtr);
JimWideValue(intObjPtr) = wideValue + increment;
- /* The following step is required in order to invalidate the
- * string repr of "FOO" if the var name is on the form of "FOO(IDX)" */
if (argv[1]->typePtr != &variableObjType) {
- /* Note that this can't fail since GetVariable already succeeded */
+
Jim_SetVariable(interp, argv[1], intObjPtr);
}
}
@@ -15966,85 +13830,60 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
-/* -----------------------------------------------------------------------------
- * Eval
- * ---------------------------------------------------------------------------*/
-#define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */
-#define JIM_EVAL_SINTV_LEN 8 /* static interpolation vector length */
+#define JIM_EVAL_SARGV_LEN 8
+#define JIM_EVAL_SINTV_LEN 8
+
-/* Handle calls to the [unknown] command */
-static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *filename,
+static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *fileNameObj,
int linenr)
{
Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN];
int retCode;
- /* If JimUnknown() is recursively called too many times...
- * done here
- */
if (interp->unknown_called > 50) {
return JIM_ERR;
}
- /* If the [unknown] command does not exists returns
- * just now */
if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
return JIM_ERR;
- /* The object interp->unknown just contains
- * the "unknown" string, it is used in order to
- * avoid to lookup the unknown command every time
- * but instread to cache the result. */
if (argc + 1 <= JIM_EVAL_SARGV_LEN)
v = sv;
else
v = Jim_Alloc(sizeof(Jim_Obj *) * (argc + 1));
- /* Make a copy of the arguments vector, but shifted on
- * the right of one position. The command name of the
- * command will be instead the first argument of the
- * [unknown] call. */
memcpy(v + 1, argv, sizeof(Jim_Obj *) * argc);
v[0] = interp->unknown;
- /* Call it */
+
interp->unknown_called++;
- retCode = JimEvalObjVector(interp, argc + 1, v, filename, linenr);
+ retCode = JimEvalObjVector(interp, argc + 1, v, fileNameObj, linenr);
interp->unknown_called--;
- /* Clean up */
+
if (v != sv)
Jim_Free(v);
return retCode;
}
-/* Eval the object vector 'objv' composed of 'objc' elements.
- * Every element is used as single argument.
- * Jim_EvalObj() will call this function every time its object
- * argument is of "list" type, with no string representation.
- *
- * This is possible because the string representation of a
- * list object generated by the UpdateStringOfList is made
- * in a way that ensures that every list element is a different
- * command argument. */
static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
- const char *filename, int linenr)
+ Jim_Obj *fileNameObj, int linenr)
{
int i, retcode;
Jim_Cmd *cmdPtr;
- /* Incr refcount of arguments. */
+
for (i = 0; i < objc; i++)
Jim_IncrRefCount(objv[i]);
- /* Command lookup */
+
cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
if (cmdPtr == NULL) {
- retcode = JimUnknown(interp, objc, objv, filename, linenr);
+ retcode = JimUnknown(interp, objc, objv, fileNameObj, linenr);
}
else {
- /* Call it -- Make sure result is an empty object. */
+
JimIncrCmdRefCount(cmdPtr);
Jim_SetEmptyResult(interp);
if (cmdPtr->isproc) {
- retcode = JimCallProcedure(interp, cmdPtr, filename, linenr, objc, objv);
+ retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv);
}
else {
interp->cmdPrivData = cmdPtr->u.native.privData;
@@ -16052,7 +13891,7 @@ static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
}
JimDecrCmdRefCount(interp, cmdPtr);
}
- /* Decr refcount of arguments and return the retcode */
+
for (i = 0; i < objc; i++)
Jim_DecrRefCount(interp, objv[i]);
@@ -16061,19 +13900,16 @@ static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
- return JimEvalObjVector(interp, objc, objv, NULL, 0);
+ return JimEvalObjVector(interp, objc, objv, interp->emptyObj, 1);
}
-/**
- * Invokes 'prefix' as a command with the objv array as arguments.
- */
-int Jim_EvalObjPrefix(Jim_Interp *interp, const char *prefix, int objc, Jim_Obj *const *objv)
+int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv)
{
int i;
int ret;
Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv));
- nargv[0] = Jim_NewStringObj(interp, prefix, -1);
+ nargv[0] = prefix;
for (i = 0; i < objc; i++) {
nargv[i + 1] = objv[i];
}
@@ -16082,32 +13918,30 @@ int Jim_EvalObjPrefix(Jim_Interp *interp, const char *prefix, int objc, Jim_Obj
return ret;
}
-static void JimAddErrorToStack(Jim_Interp *interp, int retcode, const char *filename, int line)
+static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNameObj, int line)
{
int rc = retcode;
if (rc == JIM_ERR && !interp->errorFlag) {
- /* This is the first error, so save the file/line information and reset the stack */
+
interp->errorFlag = 1;
- JimSetErrorFileName(interp, filename);
- JimSetErrorLineNumber(interp, line);
+ Jim_IncrRefCount(fileNameObj);
+ Jim_DecrRefCount(interp, interp->errorFileNameObj);
+ interp->errorFileNameObj = fileNameObj;
+ interp->errorLine = line;
JimResetStackTrace(interp);
- /* Always add a level where the error first occurs */
+
interp->addStackTrace++;
}
- /* Now if this is an "interesting" level, add it to the stack trace */
+
if (rc == JIM_ERR && interp->addStackTrace > 0) {
- /* Add the stack info for the current level */
+
- JimAppendStackTrace(interp, Jim_String(interp->errorProc), filename, line);
+ JimAppendStackTrace(interp, Jim_String(interp->errorProc), fileNameObj, line);
- /* Note: if we didn't have a filename for this level,
- * don't clear the addStackTrace flag
- * so we can pick it up at the next level
- */
- if (*filename) {
+ if (Jim_Length(fileNameObj)) {
interp->addStackTrace = 0;
}
@@ -16116,21 +13950,21 @@ static void JimAddErrorToStack(Jim_Interp *interp, int retcode, const char *file
Jim_IncrRefCount(interp->errorProc);
}
else if (rc == JIM_RETURN && interp->returnCode == JIM_ERR) {
- /* Propagate the addStackTrace value through 'return -code error' */
+
}
else {
interp->addStackTrace = 0;
}
}
-/* And delete any local procs */
+
static void JimDeleteLocalProcs(Jim_Interp *interp)
{
if (interp->localProcs) {
char *procname;
while ((procname = Jim_StackPop(interp->localProcs)) != NULL) {
- /* If there is a pushed command, find it */
+
Jim_Cmd *prevCmd = NULL;
Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, procname);
if (he) {
@@ -16141,11 +13975,11 @@ static void JimDeleteLocalProcs(Jim_Interp *interp)
}
}
- /* Delete the local proc */
+
Jim_DeleteCommand(interp, procname);
if (prevCmd) {
- /* And restore the pushed command */
+
Jim_AddHashEntry(&interp->commands, procname, prevCmd);
}
Jim_Free(procname);
@@ -16181,17 +14015,17 @@ static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Ob
objPtr = interp->result;
break;
case JIM_BREAK:
- /* Stop substituting */
+
return JIM_BREAK;
case JIM_CONTINUE:
- /* just skip this one */
+
return JIM_CONTINUE;
default:
return JIM_ERR;
}
break;
default:
- JimPanic((1, interp,
+ JimPanic((1,
"default token type (%d) reached " "in Jim_SubstObj().", token->type));
objPtr = NULL;
break;
@@ -16203,10 +14037,6 @@ static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Ob
return JIM_ERR;
}
-/* Interpolate the given tokens into a unique Jim_Obj returned by reference
- * via *objPtrPtr. This function is only called by Jim_EvalObj() and Jim_SubstObj()
- * The returned object has refcount = 0.
- */
static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags)
{
int totlen = 0, i;
@@ -16220,8 +14050,6 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
else
intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens);
- /* Compute every token forming the argument
- * in the intv objects vector. */
for (i = 0; i < tokens; i++) {
switch (JimSubstOneToken(interp, &token[i], &intv[i])) {
case JIM_OK:
@@ -16229,19 +14057,19 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
break;
case JIM_BREAK:
if (flags & JIM_SUBST_FLAG) {
- /* Stop here */
+
tokens = i;
continue;
}
- /* XXX: Should probably set an error about break outside loop */
- /* fall through to error */
+
+
case JIM_CONTINUE:
if (flags & JIM_SUBST_FLAG) {
intv[i] = NULL;
continue;
}
- /* XXX: Ditto continue outside loop */
- /* fall through to error */
+
+
default:
while (i--) {
Jim_DecrRefCount(interp, intv[i]);
@@ -16256,19 +14084,17 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
totlen += intv[i]->length;
}
- /* Fast path return for a single token */
+
if (tokens == 1 && intv[0] && intv == sintv) {
Jim_DecrRefCount(interp, intv[0]);
return intv[0];
}
- /* Concatenate every token in an unique
- * object. */
objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
&& token[2].type == JIM_TT_VAR) {
- /* May be able to do fast interpolated object -> dictSubst */
+
objPtr->typePtr = &interpolatedObjType;
objPtr->internalRep.twoPtrValue.ptr1 = (void *)token;
objPtr->internalRep.twoPtrValue.ptr2 = intv[2];
@@ -16285,7 +14111,7 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
}
}
objPtr->bytes[totlen] = '\0';
- /* Free the intv vector if not static. */
+
if (intv != sintv) {
Jim_Free(intv);
}
@@ -16294,10 +14120,7 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
}
-/* If listPtr is a list, call JimEvalObjVector() with the given source info.
- * Otherwise eval with Jim_EvalObj()
- */
-int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, const char *filename, int linenr)
+static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *fileNameObj, int linenr)
{
if (!Jim_IsList(listPtr)) {
return Jim_EvalObj(interp, listPtr);
@@ -16309,7 +14132,7 @@ int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, const char *filename,
Jim_IncrRefCount(listPtr);
retcode = JimEvalObjVector(interp,
listPtr->internalRep.listValue.len,
- listPtr->internalRep.listValue.ele, filename, linenr);
+ listPtr->internalRep.listValue.ele, fileNameObj, linenr);
Jim_DecrRefCount(interp, listPtr);
}
return retcode;
@@ -16327,25 +14150,16 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
interp->errorFlag = 0;
- /* If the object is of type "list", we can call
- * a specialized version of Jim_EvalObj() */
if (Jim_IsList(scriptObjPtr)) {
- return Jim_EvalObjList(interp, scriptObjPtr, NULL, 0);
+ return JimEvalObjList(interp, scriptObjPtr, interp->emptyObj, 1);
}
- Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */
+ Jim_IncrRefCount(scriptObjPtr);
script = Jim_GetScript(interp, scriptObjPtr);
- /* Reset the interpreter result. This is useful to
- * return the empty result in the case of empty program. */
Jim_SetEmptyResult(interp);
#ifdef JIM_OPTIMIZATION
- /* Check for one of the following common scripts used by for, while
- *
- * {}
- * incr a
- */
if (script->len == 0) {
Jim_DecrRefCount(interp, scriptObjPtr);
return JIM_OK;
@@ -16368,43 +14182,27 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
}
#endif
- /* Now we have to make sure the internal repr will not be
- * freed on shimmering.
- *
- * Think for example to this:
- *
- * set x {llength $x; ... some more code ...}; eval $x
- *
- * In order to preserve the internal rep, we increment the
- * inUse field of the script internal rep structure. */
script->inUse++;
token = script->token;
argv = sargv;
- /* Execute every command sequentially until the end of the script
- * or an error occurs.
- */
for (i = 0; i < script->len && retcode == JIM_OK; ) {
int argc;
int j;
Jim_Cmd *cmd;
- /* First token of the line is always JIM_TT_LINE */
+
argc = token[i].objPtr->internalRep.scriptLineValue.argc;
linenr = token[i].objPtr->internalRep.scriptLineValue.line;
- /* Allocate the arguments vector if required */
+
if (argc > JIM_EVAL_SARGV_LEN)
argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
- /* Skip the JIM_TT_LINE token */
+
i++;
- /* Populate the arguments objects.
- * If an error occurs, retcode will be set and
- * 'j' will be set to the number of args expanded
- */
for (j = 0; j < argc; j++) {
long wordtokens = 1;
int expand = 0;
@@ -16419,8 +14217,6 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
}
if (wordtokens == 1) {
- /* Fast path if the token does not
- * need interpolation */
switch (token[i].type) {
case JIM_TT_ESC:
@@ -16443,12 +14239,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
}
break;
default:
- JimPanic((1, interp, "default token type reached " "in Jim_EvalObj()."));
+ JimPanic((1, "default token type reached " "in Jim_EvalObj()."));
}
}
else {
- /* For interpolation we call a helper
- * function to do the work for us. */
wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE);
}
@@ -16466,7 +14260,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
argv[j] = wordObjPtr;
}
else {
- /* Need to expand wordObjPtr into multiple args from argv[j] ... */
+
int len = Jim_ListLength(interp, wordObjPtr);
int newargc = argc + len - 1;
int k;
@@ -16479,39 +14273,35 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
}
}
else {
- /* Need to realloc to make room for (len - 1) more entries */
+
argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
}
}
- /* Now copy in the expanded version */
+
for (k = 0; k < len; k++) {
argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
}
- /* The original object reference is no longer needed,
- * after the expansion it is no longer present on
- * the argument vector, but the single elements are
- * in its place. */
Jim_DecrRefCount(interp, wordObjPtr);
- /* And update the indexes */
+
j--;
argc += len - 1;
}
}
if (retcode == JIM_OK && argc) {
- /* Lookup the command to call */
+
cmd = Jim_GetCommand(interp, argv[0], JIM_ERRMSG);
if (cmd != NULL) {
- /* Call it -- Make sure result is an empty object. */
+
JimIncrCmdRefCount(cmd);
Jim_SetEmptyResult(interp);
if (cmd->isproc) {
retcode =
- JimCallProcedure(interp, cmd, script->fileName, linenr, argc, argv);
+ JimCallProcedure(interp, cmd, script->fileNameObj, linenr, argc, argv);
} else {
interp->cmdPrivData = cmd->u.native.privData;
retcode = cmd->u.native.cmdProc(interp, argc, argv);
@@ -16519,16 +14309,16 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
JimDecrCmdRefCount(interp, cmd);
}
else {
- /* Call [unknown] */
- retcode = JimUnknown(interp, argc, argv, script->fileName, linenr);
+
+ retcode = JimUnknown(interp, argc, argv, script->fileNameObj, linenr);
}
if (interp->signal_level && interp->sigmask) {
- /* Check for a signal after each command */
+
retcode = JIM_SIGNAL;
}
}
- /* Finished with the command, so decrement ref counts of each argument */
+
while (j-- > 0) {
Jim_DecrRefCount(interp, argv[j]);
}
@@ -16539,12 +14329,9 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
}
}
- /* Possibly add to the error stack trace */
- JimAddErrorToStack(interp, retcode, script->fileName, linenr);
+
+ JimAddErrorToStack(interp, retcode, script->fileNameObj, linenr);
- /* Note that we don't have to decrement inUse, because the
- * following code transfers our use of the reference again to
- * the script object. */
Jim_FreeIntRep(interp, scriptObjPtr);
scriptObjPtr->typePtr = &scriptObjType;
Jim_SetIntRepPtr(scriptObjPtr, script);
@@ -16556,10 +14343,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
{
int retcode;
- /* If argObjPtr begins with '&', do an automatic upvar */
+
const char *varname = Jim_String(argNameObj);
if (*varname == '&') {
- /* First check that the target variable exists */
+
Jim_Obj *objPtr;
Jim_CallFrame *savedCallFrame = interp->framePtr;
@@ -16570,7 +14357,7 @@ static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argVa
return JIM_ERR;
}
- /* It exists, so perform the binding. */
+
objPtr = Jim_NewStringObj(interp, varname + 1, -1);
Jim_IncrRefCount(objPtr);
retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parentCallFrame);
@@ -16582,12 +14369,9 @@ static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argVa
return retcode;
}
-/**
- * Sets the interp result to be an error message indicating the required proc args.
- */
static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
{
- /* Create a nice error message, consistent with Tcl 8.5 */
+
Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
int i;
@@ -16596,13 +14380,13 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
if (i == cmd->u.proc.argsPos) {
if (cmd->u.proc.arglist[i].defaultObjPtr) {
- /* Renamed args */
+
Jim_AppendString(interp, argmsg, "?", 1);
Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
Jim_AppendString(interp, argmsg, " ...?", -1);
}
else {
- /* We have plain args */
+
Jim_AppendString(interp, argmsg, "?argument ...?", -1);
}
}
@@ -16621,56 +14405,48 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
Jim_FreeNewObj(interp, argmsg);
}
-/* Call a procedure implemented in Tcl.
- * It's possible to speed-up a lot this function, currently
- * the callframes are not cached, but allocated and
- * destroied every time. What is expecially costly is
- * to create/destroy the local vars hash table every time.
- *
- * This can be fixed just implementing callframes caching
- * in JimCreateCallFrame() and JimFreeCallFrame(). */
-static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filename, int linenr, int argc,
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, int argc,
Jim_Obj *const *argv)
{
Jim_CallFrame *callFramePtr;
Jim_Stack *prevLocalProcs;
int i, d, retcode, optargs;
- /* Check arity */
+
if (argc - 1 < cmd->u.proc.reqArity ||
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
JimSetProcWrongArgs(interp, argv[0], cmd);
return JIM_ERR;
}
- /* Check if there are too nested calls */
+
if (interp->framePtr->level == interp->maxNestingDepth) {
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
return JIM_ERR;
}
- /* Create a new callframe */
+
callFramePtr = JimCreateCallFrame(interp, interp->framePtr);
callFramePtr->argv = argv;
callFramePtr->argc = argc;
callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
callFramePtr->staticVars = cmd->u.proc.staticVars;
- callFramePtr->filename = filename;
+ callFramePtr->fileNameObj = fileNameObj;
callFramePtr->line = linenr;
Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
interp->framePtr = callFramePtr;
- /* How many optional args are available */
+
optargs = (argc - 1 - cmd->u.proc.reqArity);
- /* Step 'i' along the actual args, and step 'd' along the formal args */
+
i = 1;
for (d = 0; d < cmd->u.proc.argListLen; d++) {
Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
if (d == cmd->u.proc.argsPos) {
- /* assign $args */
+
Jim_Obj *listObjPtr;
int argsLen = 0;
if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
@@ -16678,7 +14454,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filena
}
listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
- /* It is possible to rename args. */
+
if (cmd->u.proc.arglist[d].defaultObjPtr) {
nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
}
@@ -16691,12 +14467,12 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filena
continue;
}
- /* Optional or required? */
+
if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
}
else {
- /* Ran out, so use the default */
+
retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
}
if (retcode != JIM_OK) {
@@ -16704,19 +14480,19 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filena
}
}
- /* Install a new stack for local procs */
+
prevLocalProcs = interp->localProcs;
interp->localProcs = NULL;
- /* Eval the body */
+
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
- /* Delete any local procs */
+
JimDeleteLocalProcs(interp);
interp->localProcs = prevLocalProcs;
badargset:
- /* Destroy the callframe */
+
interp->framePtr = interp->framePtr->parentCallFrame;
if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
@@ -16724,16 +14500,16 @@ badargset:
else {
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
}
- /* Handle the JIM_EVAL return code */
+
while (retcode == JIM_EVAL) {
Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
Jim_IncrRefCount(resultScriptObjPtr);
- /* Should be a list! */
- retcode = Jim_EvalObjList(interp, resultScriptObjPtr, filename, linenr);
+
+ retcode = JimEvalObjList(interp, resultScriptObjPtr, fileNameObj, linenr);
Jim_DecrRefCount(interp, resultScriptObjPtr);
}
- /* Handle the JIM_RETURN return code */
+
if (retcode == JIM_RETURN) {
if (--interp->returnLevel <= 0) {
retcode = interp->returnCode;
@@ -16750,7 +14526,7 @@ badargset:
return retcode;
}
-int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename, int lineno)
+int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
{
int retval;
Jim_Obj *scriptObjPtr;
@@ -16758,11 +14534,10 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename,
scriptObjPtr = Jim_NewStringObj(interp, script, -1);
Jim_IncrRefCount(scriptObjPtr);
-
if (filename) {
Jim_Obj *prevScriptObj;
- JimSetSourceInfo(interp, scriptObjPtr, filename, lineno);
+ JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
prevScriptObj = interp->currentScriptObj;
interp->currentScriptObj = scriptObjPtr;
@@ -16780,10 +14555,10 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename,
int Jim_Eval(Jim_Interp *interp, const char *script)
{
- return Jim_Eval_Named(interp, script, NULL, 0);
+ return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1));
}
-/* Execute script in the scope of the global level */
+
int Jim_EvalGlobal(Jim_Interp *interp, const char *script)
{
int retval;
@@ -16842,10 +14617,10 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
buf[readlen] = 0;
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
- JimSetSourceInfo(interp, scriptObjPtr, filename, 1);
+ JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
Jim_IncrRefCount(scriptObjPtr);
- /* Now check the script for unmatched braces, etc. */
+
if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
const char *msg;
char linebuf[20];
@@ -16876,7 +14651,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
retcode = Jim_EvalObj(interp, scriptObjPtr);
- /* Handle the JIM_RETURN return code */
+
if (retcode == JIM_RETURN) {
if (--interp->returnLevel <= 0) {
retcode = interp->returnCode;
@@ -16885,7 +14660,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
}
}
if (retcode == JIM_ERR) {
- /* EvalFile changes context, so add a stack frame here */
+
interp->addStackTrace++;
}
@@ -16896,9 +14671,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
return retcode;
}
-/* -----------------------------------------------------------------------------
- * Subst
- * ---------------------------------------------------------------------------*/
static int JimParseSubstStr(struct JimParserCtx *pc)
{
pc->tstart = pc->p;
@@ -16969,15 +14741,7 @@ static int JimParseSubst(struct JimParserCtx *pc, int flags)
return JIM_OK;
}
-/* The subst object type reuses most of the data structures and functions
- * of the script object. Script's data structures are a bit more complex
- * for what is needed for [subst]itution tasks, but the reuse helps to
- * deal with a single data structure at the cost of some more memory
- * usage for substitutions. */
-/* This method takes the string representation of an object
- * as a Tcl string where to perform [subst]itution, and generates
- * the pre-parsed internal representation. */
static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags)
{
int scriptTextLen;
@@ -16986,27 +14750,28 @@ static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags
struct ScriptObj *script = Jim_Alloc(sizeof(*script));
ParseTokenList tokenlist;
- /* Initially parse the subst into tokens (in tokenlist) */
+
ScriptTokenListInit(&tokenlist);
JimParserInit(&parser, scriptText, scriptTextLen, 1);
while (1) {
JimParseSubst(&parser, flags);
if (parser.eof) {
- /* Note that subst doesn't need the EOL token */
+
break;
}
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
parser.tline);
}
- /* Create the "real" subst/script tokens from the initial token list */
+
script->inUse = 1;
script->substFlags = flags;
- script->fileName = NULL;
+ script->fileNameObj = interp->emptyObj;
+ Jim_IncrRefCount(script->fileNameObj);
SubstObjAddTokens(interp, script, &tokenlist);
- /* No longer need the token list */
+
ScriptTokenListFree(&tokenlist);
#ifdef DEBUG_SHOW_SUBST
@@ -17021,7 +14786,7 @@ static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags
}
#endif
- /* Free the old internal rep and set the new one. */
+
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, script);
objPtr->typePtr = &scriptObjType;
@@ -17035,16 +14800,11 @@ static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
}
-/* Performs commands,variables,blackslashes substitution,
- * storing the result object (with refcount 0) into
- * resObjPtrPtr. */
int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
{
ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
- Jim_IncrRefCount(substObjPtr); /* Make sure it's shared. */
- /* In order to preserve the internal rep, we increment the
- * inUse field of the script internal rep structure. */
+ Jim_IncrRefCount(substObjPtr);
script->inUse++;
*resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
@@ -17057,9 +14817,6 @@ int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPt
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Core commands utility functions
- * ---------------------------------------------------------------------------*/
void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
{
int i;
@@ -17078,22 +14835,22 @@ void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const
#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
-/* type is: 0=commands, 1=procs, 2=channels */
+
static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type)
{
Jim_HashTableIterator *htiter;
Jim_HashEntry *he;
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
- /* Check for the non-pattern case. We can do this much more efficiently. */
+
if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, patternObjPtr, JIM_NONE);
if (cmdPtr) {
if (type == 1 && !cmdPtr->isproc) {
- /* not a proc */
+
}
else if (type == 2 && !Jim_AioFilehandle(interp, patternObjPtr)) {
- /* not a channel */
+
}
else {
Jim_ListAppendElement(interp, listObjPtr, patternObjPtr);
@@ -17108,7 +14865,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
Jim_Obj *cmdNameObj;
if (type == 1 && !cmdPtr->isproc) {
- /* not a proc */
+
continue;
}
if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0))
@@ -17116,7 +14873,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
cmdNameObj = Jim_NewStringObj(interp, he->key, -1);
- /* Is it a channel? */
+
if (type == 2 && !Jim_AioFilehandle(interp, cmdNameObj)) {
Jim_FreeNewObj(interp, cmdNameObj);
continue;
@@ -17128,7 +14885,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
return listObjPtr;
}
-/* Keep this in order */
+
#define JIM_VARLIST_GLOBALS 0
#define JIM_VARLIST_LOCALS 1
#define JIM_VARLIST_VARS 2
@@ -17143,8 +14900,6 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
htiter = Jim_GetHashTableIterator(&interp->topFramePtr->vars);
}
else {
- /* For [info locals], if we are at top level an emtpy list
- * is returned. I don't agree, but we aim at compatibility (SS) */
if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr)
return listObjPtr;
htiter = Jim_GetHashTableIterator(&interp->framePtr->vars);
@@ -17173,7 +14928,7 @@ static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr,
if (targetCallFrame == NULL) {
return JIM_ERR;
}
- /* No proc call at toplevel callframe */
+
if (targetCallFrame == interp->topFramePtr) {
Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
return JIM_ERR;
@@ -17185,19 +14940,15 @@ static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr,
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]);
- Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp,
- targetCallFrame->filename ? targetCallFrame->filename : "", -1));
+ Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj);
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line));
*objPtrPtr = listObj;
}
return JIM_OK;
}
-/* -----------------------------------------------------------------------------
- * Core commands
- * ---------------------------------------------------------------------------*/
-/* fake [puts] -- not the real puts, just for debugging. */
+
static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2 && argc != 3) {
@@ -17219,7 +14970,7 @@ static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* Helper for [+] and [*] */
+
static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op)
{
jim_wide wideValue, res;
@@ -17252,7 +15003,7 @@ static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, i
return JIM_OK;
}
-/* Helper for [-] and [/] */
+
static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op)
{
jim_wide wideValue, res = 0;
@@ -17264,8 +15015,6 @@ static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, i
return JIM_ERR;
}
else if (argc == 2) {
- /* The arity = 2 case is different. For [- x] returns -x,
- * while [/ x] returns 1/x. */
if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) {
if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) {
return JIM_ERR;
@@ -17326,31 +15075,31 @@ static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, i
}
-/* [+] */
+
static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD);
}
-/* [*] */
+
static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL);
}
-/* [-] */
+
static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB);
}
-/* [/] */
+
static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV);
}
-/* [set] */
+
static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2 && argc != 3) {
@@ -17366,17 +15115,13 @@ static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
Jim_SetResult(interp, objPtr);
return JIM_OK;
}
- /* argc == 3 case. */
+
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
return JIM_ERR;
Jim_SetResult(interp, argv[2]);
return JIM_OK;
}
-/* [unset]
- *
- * unset ?-nocomplain? ?--? ?varName ...?
- */
static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int i = 1;
@@ -17405,7 +15150,7 @@ static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [while] */
+
static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 3) {
@@ -17413,7 +15158,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
- /* The general purpose implementation of while starts here */
+
while (1) {
int boolean, retval;
@@ -17440,7 +15185,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [for] */
+
static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int retval;
@@ -17453,29 +15198,15 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
return JIM_ERR;
}
- /* Do the initialisation */
+
if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
return retval;
}
- /* And do the first test now. Better for optimisation
- * if we can do next/test at the bottom of the loop
- */
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
- /* Ready to do the body as follows:
- * while (1) {
- * body // check retcode
- * next // check retcode
- * test // check retcode/test bool
- * }
- */
#ifdef JIM_OPTIMIZATION
- /* Check if the for is on the form:
- * for ... {$i < CONST} {incr i}
- * for ... {$i < $j} {incr i}
- */
if (retval == JIM_OK && boolean) {
ScriptObj *incrScript;
ExprByteCode *expr;
@@ -17484,15 +15215,15 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
Jim_Obj *objPtr;
int cmpOffset;
- /* Do it only if there aren't shared arguments */
+
expr = JimGetExpression(interp, argv[2]);
incrScript = Jim_GetScript(interp, argv[3]);
- /* Ensure proper lengths to start */
+
if (incrScript->len != 3 || !expr || expr->len != 3) {
goto evalstart;
}
- /* Ensure proper token types. */
+
if (incrScript->token[1].type != JIM_TT_ESC ||
expr->token[0].type != JIM_TT_VAR ||
(expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
@@ -17509,17 +15240,17 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
goto evalstart;
}
- /* Update command must be incr */
+
if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
goto evalstart;
}
- /* incr, expression must be about the same variable */
+
if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
goto evalstart;
}
- /* Get the stop condition (must be a variable or integer) */
+
if (expr->token[1].type == JIM_TT_EXPR_INT) {
if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
goto evalstart;
@@ -17528,11 +15259,11 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
else {
stopVarNamePtr = expr->token[1].objPtr;
Jim_IncrRefCount(stopVarNamePtr);
- /* Keep the compiler happy */
+
stop = 0;
}
- /* Initialization */
+
procEpoch = interp->procEpoch;
varNamePtr = expr->token[0].objPtr;
Jim_IncrRefCount(varNamePtr);
@@ -17542,12 +15273,12 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
goto testcond;
}
- /* --- OPTIMIZED FOR --- */
+
while (retval == JIM_OK) {
- /* === Check condition === */
- /* Note that currentVal is already set here */
+
+
- /* Immediate or Variable? get the 'stop' value if the latter. */
+
if (stopVarNamePtr) {
objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
@@ -17559,19 +15290,17 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
break;
}
- /* Eval body */
+
retval = Jim_EvalObj(interp, argv[4]);
if (retval == JIM_OK || retval == JIM_CONTINUE) {
retval = JIM_OK;
- /* If there was a change in procedures/command continue
- * with the usual [for] command implementation */
if (procEpoch != interp->procEpoch) {
goto evalnext;
}
objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
- /* Increment */
+
if (objPtr == NULL) {
retval = JIM_ERR;
goto out;
@@ -17595,15 +15324,15 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
#endif
while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
- /* Body */
+
retval = Jim_EvalObj(interp, argv[4]);
if (retval == JIM_OK || retval == JIM_CONTINUE) {
- /* increment */
+
evalnext:
retval = Jim_EvalObj(interp, argv[3]);
if (retval == JIM_OK || retval == JIM_CONTINUE) {
- /* test */
+
testcond:
retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
}
@@ -17625,7 +15354,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
return retval;
}
-/* [loop] */
+
static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int retval;
@@ -17655,7 +15384,7 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
retval = JIM_OK;
- /* Increment */
+
i += incr;
if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
@@ -17667,8 +15396,6 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
JimWideValue(objPtr) = i;
Jim_InvalidateStringRep(objPtr);
- /* The following step is required in order to invalidate the
- * string repr of "FOO" if the var name is of the form of "FOO(IDX)" */
if (argv[1]->typePtr != &variableObjType) {
if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
retval = JIM_ERR;
@@ -17693,7 +15420,7 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return retval;
}
-/* foreach + lmap implementation. */
+
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
{
int result = JIM_ERR, i, nbrOfLists, *listsIdx, *listsEnd;
@@ -17710,13 +15437,13 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
emptyStr = Jim_NewEmptyStringObj(interp);
Jim_IncrRefCount(emptyStr);
- script = argv[argc - 1]; /* Last argument is a script */
- nbrOfLists = (argc - 1 - 1) / 2; /* argc - 'foreach' - script */
+ script = argv[argc - 1];
+ nbrOfLists = (argc - 1 - 1) / 2;
listsIdx = (int *)Jim_Alloc(nbrOfLists * sizeof(int));
listsEnd = (int *)Jim_Alloc(nbrOfLists * 2 * sizeof(int));
- /* Initialize iterators and remember max nbr elements each list */
+
memset(listsIdx, 0, nbrOfLists * sizeof(int));
- /* Remember lengths of all lists and calculate how much rounds to loop */
+
for (i = 0; i < nbrOfLists * 2; i += 2) {
div_t cnt;
int count;
@@ -17740,22 +15467,22 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_Obj *varName, *ele;
int lst = i * 2 + 1;
- /* List index operations below can't fail */
+
Jim_ListIndex(interp, argv[var + 1], varIdx, &varName, JIM_NONE);
if (listsIdx[i] < listsEnd[lst]) {
Jim_ListIndex(interp, argv[lst + 1], listsIdx[i], &ele, JIM_NONE);
- /* Avoid shimmering */
+
Jim_IncrRefCount(ele);
result = Jim_SetVariable(interp, varName, ele);
Jim_DecrRefCount(interp, ele);
if (result == JIM_OK) {
- ++listsIdx[i]; /* Remember next iterator of current list */
- ++varIdx; /* Next variable */
+ ++listsIdx[i];
+ ++varIdx;
continue;
}
}
else if (Jim_SetVariable(interp, varName, emptyStr) == JIM_OK) {
- ++varIdx; /* Next variable */
+ ++varIdx;
continue;
}
goto err;
@@ -17790,58 +15517,56 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return result;
}
-/* [foreach] */
+
static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimForeachMapHelper(interp, argc, argv, 0);
}
-/* [lmap] */
+
static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
return JimForeachMapHelper(interp, argc, argv, 1);
}
-/* [if] */
+
static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int boolean, retval, current = 1, falsebody = 0;
if (argc >= 3) {
while (1) {
- /* Far not enough arguments given! */
+
if (current >= argc)
goto err;
if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
!= JIM_OK)
return retval;
- /* There lacks something, isn't it? */
+
if (current >= argc)
goto err;
if (Jim_CompareStringImmediate(interp, argv[current], "then"))
current++;
- /* Tsk tsk, no then-clause? */
+
if (current >= argc)
goto err;
if (boolean)
return Jim_EvalObj(interp, argv[current]);
- /* Ok: no else-clause follows */
+
if (++current >= argc) {
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
return JIM_OK;
}
falsebody = current++;
if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
- /* IIICKS - else-clause isn't last cmd? */
+
if (current != argc - 1)
goto err;
return Jim_EvalObj(interp, argv[current]);
}
else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
- /* Ok: elseif follows meaning all the stuff
- * again (how boring...) */
continue;
- /* OOPS - else-clause is not last cmd? */
+
else if (falsebody != argc - 1)
goto err;
return Jim_EvalObj(interp, argv[falsebody]);
@@ -17854,7 +15579,7 @@ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
-/* Returns 1 if match, 0 if no match or -<error> on error (e.g. -JIM_ERR, -JIM_BREAK)*/
+
int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj,
Jim_Obj *stringObj, int nocase)
{
@@ -17882,7 +15607,7 @@ int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patter
enum
{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
-/* [switch] */
+
static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
@@ -17953,20 +15678,17 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
break;
case SWITCH_RE:
command = Jim_NewStringObj(interp, "regexp", -1);
- /* Fall thru intentionally */
+
case SWITCH_CMD:{
int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
- /* After the execution of a command we need to
- * make sure to reconvert the object into a list
- * again. Only for the single-list style [switch]. */
if (argc - opt == 1) {
Jim_Obj **vector;
JimListGetElements(interp, argv[opt], &patCount, &vector);
caseList = vector;
}
- /* command is here already decref'd */
+
if (rc < 0) {
return -rc;
}
@@ -17993,7 +15715,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [list] */
+
static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listObjPtr;
@@ -18003,7 +15725,7 @@ static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [lindex] */
+
static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr, *listObjPtr;
@@ -18023,8 +15745,6 @@ static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_ERR;
}
if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) {
- /* Returns an empty object if the index
- * is out of range. */
Jim_DecrRefCount(interp, listObjPtr);
Jim_SetEmptyResult(interp);
return JIM_OK;
@@ -18037,7 +15757,7 @@ static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [llength] */
+
static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2) {
@@ -18048,7 +15768,7 @@ static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
return JIM_OK;
}
-/* [lsearch] */
+
static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
static const char * const options[] = {
@@ -18106,7 +15826,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
goto wrongargs;
}
commandObj = argv[++i];
- /* fallthru */
+
case OPT_EXACT:
case OPT_GLOB:
case OPT_REGEXP:
@@ -18155,13 +15875,13 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
break;
}
- /* If we have a non-match with opt_bool, opt_not, !opt_all, can't exit early */
+
if (!eq && opt_bool && opt_not && !opt_all) {
continue;
}
if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
- /* Got a match (or non-match for opt_not), or (opt_bool && opt_all) */
+
Jim_Obj *resultObj;
if (opt_bool) {
@@ -18188,7 +15908,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
Jim_SetResult(interp, listObjPtr);
}
else {
- /* No match */
+
if (opt_bool) {
Jim_SetResultBool(interp, opt_not);
}
@@ -18204,7 +15924,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
return rc;
}
-/* [lappend] */
+
static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listObjPtr;
@@ -18216,7 +15936,7 @@ static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!listObjPtr) {
- /* Create the list if it does not exists */
+
listObjPtr = Jim_NewListObj(interp, NULL, 0);
if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) {
Jim_FreeNewObj(interp, listObjPtr);
@@ -18237,7 +15957,7 @@ static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
return JIM_OK;
}
-/* [linsert] */
+
static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int idx, len;
@@ -18267,7 +15987,7 @@ static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
return JIM_ERR;
}
-/* [lreplace] */
+
static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int first, last, len, rangeLen;
@@ -18292,16 +16012,13 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
last = JimRelToAbsIndex(len, last);
JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
- /* Now construct a new list which consists of:
- * <elements before first> <supplied elements> <elements after last>
- */
- /* Check to see if trying to replace past the end of the list */
+
if (first < len) {
- /* OK. Not past the end */
+
}
else if (len == 0) {
- /* Special for empty list, adjust first to 0 */
+
first = 0;
}
else {
@@ -18317,17 +16034,17 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
listObj = Jim_DuplicateObj(interp, listObj);
}
- /* Add the first set of elements */
+
for (i = 0; i < first; i++) {
Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
}
- /* Add supplied elements */
+
for (i = 4; i < argc; i++) {
Jim_ListAppendElement(interp, newListObj, argv[i]);
}
- /* Add the remaining elements */
+
for (i = first + rangeLen; i < len; i++) {
Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
}
@@ -18338,7 +16055,7 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_OK;
}
-/* [lset] */
+
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc < 3) {
@@ -18357,7 +16074,7 @@ static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [lsort] */
+
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
{
static const char * const options[] = {
@@ -18437,7 +16154,7 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
return retCode;
}
-/* [append] */
+
static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *stringObjPtr;
@@ -18456,7 +16173,7 @@ static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
int freeobj = 0;
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!stringObjPtr) {
- /* Create the string if it doesn't exist */
+
stringObjPtr = Jim_NewEmptyStringObj(interp);
freeobj = 1;
}
@@ -18478,212 +16195,16 @@ static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [debug] */
+
static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
-#ifdef JIM_DEBUG_COMMAND
- static const char * const options[] = {
- "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen",
- "exprbc", "show",
- NULL
- };
- enum
- {
- OPT_REFCOUNT, OPT_OBJCOUNT, OPT_OBJECTS, OPT_INVSTR, OPT_SCRIPTLEN,
- OPT_EXPRLEN, OPT_EXPRBC, OPT_SHOW,
- };
- int option;
-
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "subcommand ?...?");
- return JIM_ERR;
- }
- if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK)
- return JIM_ERR;
- if (option == OPT_REFCOUNT) {
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "object");
- return JIM_ERR;
- }
- Jim_SetResultInt(interp, argv[2]->refCount);
- return JIM_OK;
- }
- else if (option == OPT_OBJCOUNT) {
- int freeobj = 0, liveobj = 0;
- char buf[256];
- Jim_Obj *objPtr;
-
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
- return JIM_ERR;
- }
- /* Count the number of free objects. */
- objPtr = interp->freeList;
- while (objPtr) {
- freeobj++;
- objPtr = objPtr->nextObjPtr;
- }
- /* Count the number of live objects. */
- objPtr = interp->liveList;
- while (objPtr) {
- liveobj++;
- objPtr = objPtr->nextObjPtr;
- }
- /* Set the result string and return. */
- sprintf(buf, "free %d used %d", freeobj, liveobj);
- Jim_SetResultString(interp, buf, -1);
- return JIM_OK;
- }
- else if (option == OPT_OBJECTS) {
- Jim_Obj *objPtr, *listObjPtr, *subListObjPtr;
-
- /* Count the number of live objects. */
- objPtr = interp->liveList;
- listObjPtr = Jim_NewListObj(interp, NULL, 0);
- while (objPtr) {
- char buf[128];
- const char *type = objPtr->typePtr ? objPtr->typePtr->name : "";
-
- subListObjPtr = Jim_NewListObj(interp, NULL, 0);
- sprintf(buf, "%p", objPtr);
- Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, buf, -1));
- Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, type, -1));
- Jim_ListAppendElement(interp, subListObjPtr, Jim_NewIntObj(interp, objPtr->refCount));
- Jim_ListAppendElement(interp, subListObjPtr, objPtr);
- Jim_ListAppendElement(interp, listObjPtr, subListObjPtr);
- objPtr = objPtr->nextObjPtr;
- }
- Jim_SetResult(interp, listObjPtr);
- return JIM_OK;
- }
- else if (option == OPT_INVSTR) {
- Jim_Obj *objPtr;
-
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "object");
- return JIM_ERR;
- }
- objPtr = argv[2];
- if (objPtr->typePtr != NULL)
- Jim_InvalidateStringRep(objPtr);
- Jim_SetEmptyResult(interp);
- return JIM_OK;
- }
- else if (option == OPT_SHOW) {
- const char *s;
- int len, charlen;
-
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "object");
- return JIM_ERR;
- }
- s = Jim_GetString(argv[2], &len);
- charlen = Jim_Utf8Length(interp, argv[2]);
- printf("chars (%d): <<%s>>\n", charlen, s);
- printf("bytes (%d):", len);
- while (len--) {
- printf(" %02x", (unsigned char)*s++);
- }
- printf("\n");
- return JIM_OK;
- }
- else if (option == OPT_SCRIPTLEN) {
- ScriptObj *script;
-
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "script");
- return JIM_ERR;
- }
- script = Jim_GetScript(interp, argv[2]);
- Jim_SetResultInt(interp, script->len);
- return JIM_OK;
- }
- else if (option == OPT_EXPRLEN) {
- ExprByteCode *expr;
-
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "expression");
- return JIM_ERR;
- }
- expr = JimGetExpression(interp, argv[2]);
- if (expr == NULL)
- return JIM_ERR;
- Jim_SetResultInt(interp, expr->len);
- return JIM_OK;
- }
- else if (option == OPT_EXPRBC) {
- Jim_Obj *objPtr;
- ExprByteCode *expr;
- int i;
-
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "expression");
- return JIM_ERR;
- }
- expr = JimGetExpression(interp, argv[2]);
- if (expr == NULL)
- return JIM_ERR;
- objPtr = Jim_NewListObj(interp, NULL, 0);
- for (i = 0; i < expr->len; i++) {
- const char *type;
- const Jim_ExprOperator *op;
- Jim_Obj *obj = expr->token[i].objPtr;
-
- switch (expr->token[i].type) {
- case JIM_TT_EXPR_INT:
- type = "int";
- break;
- case JIM_TT_EXPR_DOUBLE:
- type = "double";
- break;
- case JIM_TT_CMD:
- type = "command";
- break;
- case JIM_TT_VAR:
- type = "variable";
- break;
- case JIM_TT_DICTSUGAR:
- type = "dictsugar";
- break;
- case JIM_TT_EXPRSUGAR:
- type = "exprsugar";
- break;
- case JIM_TT_ESC:
- type = "subst";
- break;
- case JIM_TT_STR:
- type = "string";
- break;
- default:
- op = JimExprOperatorInfoByOpcode(expr->token[i].type);
- if (op == NULL) {
- type = "private";
- }
- else {
- type = "operator";
- }
- obj = Jim_NewStringObj(interp, op ? op->name : "", -1);
- break;
- }
- Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, type, -1));
- Jim_ListAppendElement(interp, objPtr, obj);
- }
- Jim_SetResult(interp, objPtr);
- return JIM_OK;
- }
- else {
- Jim_SetResultString(interp,
- "bad option. Valid options are refcount, " "objcount, objects, invstr", -1);
- return JIM_ERR;
- }
- /* unreached */
-#else
+#if !defined(JIM_DEBUG_COMMAND)
Jim_SetResultString(interp, "unsupported", -1);
return JIM_ERR;
#endif
}
-/* [eval] */
+
static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int rc;
@@ -18701,13 +16222,13 @@ static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
if (rc == JIM_ERR) {
- /* eval is "interesting", so add a stack frame here */
+
interp->addStackTrace++;
}
return rc;
}
-/* [uplevel] */
+
static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc >= 2) {
@@ -18716,10 +16237,10 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
Jim_Obj *objPtr;
const char *str;
- /* Save the old callframe pointer */
+
savedCallFrame = interp->framePtr;
- /* Lookup the target frame pointer */
+
str = Jim_String(argv[1]);
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
@@ -18737,7 +16258,7 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
return JIM_ERR;
}
- /* Eval the code in the target callframe. */
+
interp->framePtr = targetCallFrame;
if (argc == 2) {
retcode = Jim_EvalObj(interp, argv[1]);
@@ -18757,7 +16278,7 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
}
-/* [expr] */
+
static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *exprResultPtr;
@@ -18785,7 +16306,7 @@ static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [break] */
+
static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 1) {
@@ -18795,7 +16316,7 @@ static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_BREAK;
}
-/* [continue] */
+
static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 1) {
@@ -18805,7 +16326,7 @@ static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_CONTINUE;
}
-/* [return] */
+
static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int i;
@@ -18842,11 +16363,11 @@ static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
"?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
}
- /* If a stack trace is supplied and code is error, set the stack trace */
+
if (stackTraceObj && returnCode == JIM_ERR) {
JimSetStackTrace(interp, stackTraceObj);
}
- /* If an error code list is supplied, set the global $errorCode */
+
if (errorCodeObj && returnCode == JIM_ERR) {
Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
}
@@ -18859,7 +16380,7 @@ static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_RETURN;
}
-/* [tailcall] */
+
static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -18869,7 +16390,7 @@ static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_EVAL;
}
-/* [proc] */
+
static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 4 && argc != 5) {
@@ -18885,18 +16406,18 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
}
-/* [local] */
+
static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int retcode;
- /* Evaluate the arguments with 'local' in force */
+
interp->local++;
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
interp->local--;
- /* If OK, and the result is a proc, add it to the list of local procs */
+
if (retcode == 0) {
const char *procname = Jim_String(Jim_GetResult(interp));
@@ -18914,7 +16435,7 @@ static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return retcode;
}
-/* [upcall] */
+
static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc < 2) {
@@ -18929,14 +16450,14 @@ static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
Jim_SetResultFormatted(interp, "no previous proc: \"%#s\"", argv[1]);
return JIM_ERR;
}
- /* OK. Mark this command as being in an upcall */
+
cmdPtr->u.proc.upcall++;
JimIncrCmdRefCount(cmdPtr);
- /* Invoke the command as normal */
+
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
- /* No longer in an upcall */
+
cmdPtr->u.proc.upcall--;
JimDecrCmdRefCount(interp, cmdPtr);
@@ -18944,20 +16465,20 @@ static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
}
}
-/* [concat] */
+
static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
return JIM_OK;
}
-/* [upvar] */
+
static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int i;
Jim_CallFrame *targetCallFrame;
- /* Lookup the target frame pointer */
+
if (argc > 3 && (argc % 2 == 0)) {
targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
argc--;
@@ -18970,13 +16491,13 @@ static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
- /* Check for arity */
+
if (argc < 3) {
Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
return JIM_ERR;
}
- /* Now... for every other/local couple: */
+
for (i = 1; i < argc; i += 2) {
if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
return JIM_ERR;
@@ -18984,7 +16505,7 @@ static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [global] */
+
static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int i;
@@ -18993,9 +16514,9 @@ static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
return JIM_ERR;
}
- /* Link every var to the toplevel having the same name */
+
if (interp->framePtr->level == 0)
- return JIM_OK; /* global at toplevel... */
+ return JIM_OK;
for (i = 1; i < argc; i++) {
if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
return JIM_ERR;
@@ -19003,9 +16524,6 @@ static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* does the [string map] operation. On error NULL is returned,
- * otherwise a new string object with the result, having refcount = 0,
- * is returned. */
static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
Jim_Obj *objPtr, int nocase)
{
@@ -19023,7 +16541,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
str = Jim_String(objPtr);
strLen = Jim_Utf8Length(interp, objPtr);
- /* Map it */
+
resultObjPtr = Jim_NewStringObj(interp, "", 0);
while (strLen) {
for (i = 0; i < numMaps; i += 2) {
@@ -19056,7 +16574,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
}
}
}
- if (i == numMaps) { /* no match */
+ if (i == numMaps) {
int c;
if (noMatchStart == NULL)
noMatchStart = str;
@@ -19070,7 +16588,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
return resultObjPtr;
}
-/* [string] */
+
static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int len;
@@ -19266,7 +16784,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
Jim_SetResultString(interp, "", 0);
}
else if (len == Jim_Length(argv[2])) {
- /* ASCII optimisation */
+
Jim_SetResultString(interp, str + idx, 1);
}
else {
@@ -19358,7 +16876,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [time] */
+
static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
long i, count = 1;
@@ -19392,7 +16910,7 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [exit] */
+
static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
long exitCode = 0;
@@ -19409,28 +16927,25 @@ static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_EXIT;
}
-/* [catch] */
+
static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int exitCode = 0;
int i;
int sig = 0;
- /* Which return codes are caught? These are the defaults */
- jim_wide mask =
- (1 << JIM_OK | 1 << JIM_ERR | 1 << JIM_BREAK | 1 << JIM_CONTINUE | 1 << JIM_RETURN);
+
+ jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
+ static const int max_ignore_code = sizeof(ignore_mask) * 8;
- /* Reset the error code before catch.
- * Note that this is not strictly correct.
- */
Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
for (i = 1; i < argc - 1; i++) {
const char *arg = Jim_String(argv[i]);
jim_wide option;
- int add;
+ int ignore;
- /* It's a pity we can't use Jim_GetEnum here :-( */
+
if (strcmp(arg, "--") == 0) {
i++;
break;
@@ -19441,11 +16956,11 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
if (strncmp(arg, "-no", 3) == 0) {
arg += 3;
- add = 0;
+ ignore = 1;
}
else {
arg++;
- add = 1;
+ ignore = 0;
}
if (Jim_StringToWide(arg, &option, 10) != JIM_OK) {
@@ -19458,11 +16973,11 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
goto wrongargs;
}
- if (add) {
- mask |= (1 << option);
+ if (ignore) {
+ ignore_mask |= (1 << option);
}
else {
- mask &= ~(1 << option);
+ ignore_mask &= ~(1 << option);
}
}
@@ -19475,13 +16990,13 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
argv += i;
- if (mask & (1 << JIM_SIGNAL)) {
+ if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
sig++;
}
interp->signal_level += sig;
if (interp->signal_level && interp->sigmask) {
- /* If a signal is set, don't even try to execute the body */
+
exitCode = JIM_SIGNAL;
}
else {
@@ -19489,14 +17004,14 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
interp->signal_level -= sig;
- /* Catch or pass through? Only the first 32/64 codes can be passed through */
- if (exitCode >= 0 && exitCode < (int)sizeof(mask) * 8 && ((1 << exitCode) & mask) == 0) {
- /* Not caught, pass it up */
+
+ if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
+
return exitCode;
}
if (sig && exitCode == JIM_SIGNAL) {
- /* Catch the signal at this level */
+
if (interp->signal_set_result) {
interp->signal_set_result(interp, interp->sigmask);
}
@@ -19541,7 +17056,7 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
#ifdef JIM_REFERENCES
-/* [ref] */
+
static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 3 && argc != 4) {
@@ -19557,7 +17072,7 @@ static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
return JIM_OK;
}
-/* [getref] */
+
static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Reference *refPtr;
@@ -19572,7 +17087,7 @@ static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [setref] */
+
static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Reference *refPtr;
@@ -19590,7 +17105,7 @@ static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [collect] */
+
static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 1) {
@@ -19599,7 +17114,7 @@ static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
Jim_SetResultInt(interp, Jim_Collect(interp));
- /* Free all the freed objects. */
+
while (interp->freeList) {
Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
Jim_Free(interp->freeList);
@@ -19609,7 +17124,7 @@ static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
return JIM_OK;
}
-/* [finalize] reference ?newValue? */
+
static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2 && argc != 3) {
@@ -19621,7 +17136,7 @@ static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
return JIM_ERR;
- if (cmdNamePtr != NULL) /* otherwise the null string is returned. */
+ if (cmdNamePtr != NULL)
Jim_SetResult(interp, cmdNamePtr);
}
else {
@@ -19632,7 +17147,7 @@ static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_OK;
}
-/* [info references] */
+
static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listObjPtr;
@@ -19656,7 +17171,7 @@ static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#endif
-/* [rename] */
+
static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *oldName, *newName;
@@ -19687,14 +17202,11 @@ int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj)
return JIM_ERR;
}
- /* XXX: Could make the exact-match case much more efficient here.
- * See JimCommandsList()
- */
if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) {
return JIM_ERR;
}
- /* Only return the matching values */
+
resultObj = Jim_NewListObj(interp, NULL, 0);
for (i = 0; i < len; i += 2) {
@@ -19716,7 +17228,7 @@ int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
}
-/* [dict] */
+
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -19756,7 +17268,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
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]);
+ return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
case OPT_EXIST:
if (argc < 3) {
@@ -19772,7 +17284,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
return JIM_ERR;
}
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL);
+ return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
case OPT_KEYS:
if (argc != 3 && argc != 4) {
@@ -19805,7 +17317,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
else {
- return Jim_EvalObjPrefix(interp, "dict merge", argc - 2, argv + 2);
+ return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
}
case OPT_WITH:
@@ -19817,7 +17329,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
else {
- return Jim_EvalObjPrefix(interp, "dict with", argc - 2, argv + 2);
+ return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
}
case OPT_CREATE:
@@ -19834,7 +17346,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
}
-/* [subst] */
+
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
static const char * const options[] = {
@@ -19876,7 +17388,7 @@ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [info] */
+
static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int cmd;
@@ -19905,7 +17417,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
- /* Test for the the most common commands first, just in case it makes a difference */
+
switch (cmd) {
case INFO_EXISTS:{
if (argc != 3) {
@@ -19932,11 +17444,11 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
break;
case INFO_VARS:
- mode++; /* JIM_VARLIST_VARS */
+ mode++;
case INFO_LOCALS:
- mode++; /* JIM_VARLIST_LOCALS */
+ mode++;
case INFO_GLOBALS:
- /* mode 0 => JIM_VARLIST_GLOBALS */
+
if (argc != 2 && argc != 3) {
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
return JIM_ERR;
@@ -19949,30 +17461,33 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 2, argv, "");
return JIM_ERR;
}
- Jim_SetResultString(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileName,
- -1);
+ Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileNameObj);
break;
case INFO_SOURCE:{
- const char *filename = "";
- int line = 0;
+ int line;
Jim_Obj *resObjPtr;
+ Jim_Obj *fileNameObj;
if (argc != 3) {
Jim_WrongNumArgs(interp, 2, argv, "source");
return JIM_ERR;
}
if (argv[2]->typePtr == &sourceObjType) {
- filename = argv[2]->internalRep.sourceValue.fileName;
+ fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj;
line = argv[2]->internalRep.sourceValue.lineNumber;
}
else if (argv[2]->typePtr == &scriptObjType) {
ScriptObj *script = Jim_GetScript(interp, argv[2]);
- filename = script->fileName;
+ fileNameObj = script->fileNameObj;
line = script->line;
}
+ else {
+ fileNameObj = interp->emptyObj;
+ line = 1;
+ }
resObjPtr = Jim_NewListObj(interp, NULL, 0);
- Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObj(interp, filename, -1));
+ Jim_ListAppendElement(interp, resObjPtr, fileNameObj);
Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line));
Jim_SetResult(interp, resObjPtr);
break;
@@ -20049,11 +17564,11 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
break;
case INFO_HOSTNAME:
- /* Redirect to os.gethostname if it exists */
+
return Jim_Eval(interp, "os.gethostname");
case INFO_NAMEOFEXECUTABLE:
- /* Redirect to Tcl proc */
+
return Jim_Eval(interp, "{info nameofexecutable}");
case INFO_RETURNCODES:
@@ -20100,7 +17615,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [exists] */
+
static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -20129,7 +17644,7 @@ static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_ERR;
}
- /* Test for the the most common commands first, just in case it makes a difference */
+
switch (option) {
case OPT_VAR:
Jim_SetResultBool(interp, Jim_GetVariable(interp, objPtr, 0) != NULL);
@@ -20145,7 +17660,7 @@ static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [split] */
+
static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *str, *splitChars, *noMatchStart;
@@ -20165,7 +17680,7 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
strLen = Jim_Utf8Length(interp, argv[1]);
- /* Init */
+
if (argc == 2) {
splitChars = " \n\t\r";
splitLen = 4;
@@ -20178,7 +17693,7 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
noMatchStart = str;
resObjPtr = Jim_NewListObj(interp, NULL, 0);
- /* Split */
+
if (splitLen) {
Jim_Obj *objPtr;
while (strLen--) {
@@ -20201,16 +17716,13 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
Jim_ListAppendElement(interp, resObjPtr, objPtr);
}
else {
- /* This handles the special case of splitchars eq {}
- * Optimise by sharing common (ASCII) characters
- */
Jim_Obj **commonObj = NULL;
#define NUM_COMMON (128 - 9)
while (strLen--) {
int n = utf8_tounicode(str, &c);
#ifdef JIM_OPTIMIZATION
if (c >= 9 && c < 128) {
- /* Common ASCII char. Note that 9 is the tab character */
+
c -= 9;
if (!commonObj) {
commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
@@ -20234,7 +17746,7 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [join] */
+
static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *joinStr;
@@ -20245,7 +17757,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
return JIM_ERR;
}
- /* Init */
+
if (argc == 2) {
joinStr = " ";
joinStrLen = 1;
@@ -20255,7 +17767,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
listLen = Jim_ListLength(interp, argv[1]);
resObjPtr = Jim_NewStringObj(interp, NULL, 0);
- /* Split */
+
for (i = 0; i < listLen; i++) {
Jim_Obj *objPtr = 0;
@@ -20269,7 +17781,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [format] */
+
static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -20285,7 +17797,7 @@ static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [scan] */
+
static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listPtr, **outVec;
@@ -20361,7 +17873,7 @@ static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_OK;
}
-/* [error] */
+
static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 2 && argc != 3) {
@@ -20377,7 +17889,7 @@ static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
-/* [lrange] */
+
static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -20392,7 +17904,7 @@ static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_OK;
}
-/* [lrepeat] */
+
static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
@@ -20449,7 +17961,7 @@ void Jim_SetEnviron(char **env)
#endif
}
-/* [env] */
+
static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *key;
@@ -20492,7 +18004,7 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
return JIM_OK;
}
-/* [source] */
+
static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
int retval;
@@ -20507,7 +18019,7 @@ static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return retval;
}
-/* [lreverse] */
+
static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *revObjPtr, **ele;
@@ -20540,19 +18052,16 @@ static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step)
return -1;
len = end - start;
if (len < 0)
- len = -len; /* abs(len) */
+ len = -len;
if (step < 0)
- step = -step; /* abs(step) */
+ step = -step;
len = 1 + ((len - 1) / step);
- /* We can truncate safely to INT_MAX, the range command
- * will always return an error for a such long range
- * because Tcl lists can't be so long. */
if (len > INT_MAX)
len = INT_MAX;
return (int)((len < 0) ? -1 : len);
}
-/* [range] */
+
static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
jim_wide start = 0, end, step = 1;
@@ -20585,7 +18094,7 @@ static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
-/* [rand] */
+
static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
jim_wide min = 0, max = 0, len, maxMul;
@@ -20706,9 +18215,6 @@ void Jim_RegisterCoreCommands(Jim_Interp *interp)
}
}
-/* -----------------------------------------------------------------------------
- * Interactive prompt
- * ---------------------------------------------------------------------------*/
void Jim_MakeErrorMessage(Jim_Interp *interp)
{
Jim_Obj *argv[2];
@@ -20763,14 +18269,11 @@ int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
- /* Found an exact match */
+
*indexPtr = i;
return JIM_OK;
}
if (flags & JIM_ENUM_ABBREV) {
- /* Accept an unambiguous abbreviation.
- * Note that '-' doesnt' consitute a valid abbreviation
- */
if (strncmp(arg, *entryPtr, arglen) == 0) {
if (*arg == '-' && arglen == 1) {
break;
@@ -20784,7 +18287,7 @@ int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
}
}
- /* If we had an unambiguous partial match */
+
if (match >= 0) {
*indexPtr = match;
return JIM_OK;
@@ -20819,23 +18322,9 @@ int Jim_IsList(Jim_Obj *objPtr)
return objPtr->typePtr == &listObjType;
}
-/**
- * Very simple printf-like formatting, designed for error messages.
- *
- * The format may contain up to 5 '%s' or '%#s', corresponding to variable arguments.
- * The resulting string is created and set as the result.
- *
- * Each '%s' should correspond to a regular string parameter.
- * Each '%#s' should correspond to a (Jim_Obj *) parameter.
- * Any other printf specifier is not allowed (but %% is allowed for the % character).
- *
- * e.g. Jim_SetResultFormatted(interp, "Bad option \"%#s\" in proc \"%#s\"", optionObjPtr, procNamePtr);
- *
- * Note: We take advantage of the fact that printf has the same behaviour for both %s and %#s
- */
void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
{
- /* Initial space needed */
+
int len = strlen(format);
int extra = 0;
int n = 0;
@@ -20876,7 +18365,7 @@ void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
}
-/* stubs */
+
#ifndef jim_ext_package
int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
{
@@ -20892,28 +18381,16 @@ FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj)
#endif
-/*
- * Local Variables: ***
- * c-basic-offset: 4 ***
- * tab-width: 4 ***
- * End: ***
- */
#include <stdio.h>
#include <string.h>
-/**
- * Implements the common 'commands' subcommand
- */
static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- /* Nothing to do, since the result has already been created */
+
return JIM_OK;
}
-/**
- * Do-nothing command to support -commands and -usage
- */
static const jim_subcmd_type dummy_subcmd = {
.cmd = "dummy",
.function = subcmd_null,
@@ -20967,7 +18444,7 @@ static void show_full_usage(Jim_Interp *interp, const jim_subcmd_type * ct, int
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
for (; ct->cmd; ct++) {
if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
- /* subcmd */
+
add_cmd_usage(interp, ct, argv[0]);
if (ct->description) {
Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n ", ct->description, NULL);
@@ -21009,27 +18486,27 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
cmd = argv[1];
if (argc == 2 && Jim_CompareStringImmediate(interp, cmd, "-usage")) {
- /* Show full usage */
+
show_full_usage(interp, command_table, argc, argv);
return &dummy_subcmd;
}
- /* Check for the help command */
+
if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
if (argc == 2) {
- /* Usage for the command, not the subcommand */
+
show_cmd_usage(interp, command_table, argc, argv);
return &dummy_subcmd;
}
help = 1;
- /* Skip the 'help' command */
+
cmd = argv[2];
}
- /* Check for special builtin '-commands' command first */
+
if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
- /* Build the result here */
+
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
add_commands(interp, command_table, " ");
return &dummy_subcmd;
@@ -21039,14 +18516,14 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
for (ct = command_table; ct->cmd; ct++) {
if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
- /* Found an exact match */
+
break;
}
if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
if (partial) {
- /* Ambiguous */
+
if (help) {
- /* Just show the top level help here */
+
show_cmd_usage(interp, command_table, argc, argv);
return &dummy_subcmd;
}
@@ -21058,15 +18535,15 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
continue;
}
- /* If we had an unambiguous partial match */
+
if (partial && !ct->cmd) {
ct = partial;
}
if (!ct->cmd) {
- /* No matching command */
+
if (help) {
- /* Just show the top level help here */
+
show_cmd_usage(interp, command_table, argc, argv);
return &dummy_subcmd;
}
@@ -21076,7 +18553,7 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
if (help) {
Jim_SetResultString(interp, "Usage: ", -1);
- /* subcmd */
+
add_cmd_usage(interp, ct, argv[0]);
if (ct->description) {
Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", ct->description, NULL);
@@ -21084,17 +18561,17 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
return &dummy_subcmd;
}
- /* Check the number of args */
+
if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
Jim_SetResultString(interp, "wrong # args: must be \"", -1);
- /* subcmd */
+
add_cmd_usage(interp, ct, argv[0]);
Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
return 0;
}
- /* Good command */
+
return ct;
}
@@ -21125,12 +18602,12 @@ int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return Jim_CallSubCmd(interp, ct, argc, argv);
}
-/* The following two functions are for normal commands */
+
int
Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
Jim_Obj *const *argv)
{
- /* -usage or -help */
+
if (argc == 2) {
if (Jim_CompareStringImmediate(interp, argv[1], "-usage")
|| Jim_CompareStringImmediate(interp, argv[1], "-help")) {
@@ -21144,7 +18621,7 @@ Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int
}
}
if (argc >= 2 && command_table->function) {
- /* This is actually a sub command table */
+
Jim_Obj *nargv[4];
int nargc = 0;
@@ -21177,7 +18654,7 @@ Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int
}
}
- /* Check the number of args */
+
if (argc - 1 < command_table->minargs || (command_table->maxargs >= 0
&& argc - 1 > command_table->maxargs)) {
set_wrong_args(interp, command_table, NULL);
@@ -21186,16 +18663,9 @@ Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int
return JIM_ERR;
}
- /* Not usage, but passed arg checking */
+
return -1;
}
-/**
- * UTF-8 utility functions
- *
- * (c) 2010 Steve Bennett <steveb@workware.net.au>
- *
- * See LICENCE for licence details.
- */
#include <ctype.h>
#include <stdlib.h>
@@ -21203,7 +18673,7 @@ Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int
#include <stdio.h>
#include <assert.h>
-/* This one is always implemented */
+
int utf8_fromunicode(char *p, unsigned short uc)
{
if (uc <= 0x7f) {
@@ -21223,163 +18693,6 @@ int utf8_fromunicode(char *p, unsigned short uc)
}
}
-#ifdef JIM_UTF8
-int utf8_charlen(int c)
-{
- if ((c & 0x80) == 0) {
- return 1;
- }
- if ((c & 0xe0) == 0xc0) {
- return 2;
- }
- if ((c & 0xf0) == 0xe0) {
- return 3;
- }
- if ((c & 0xf8) == 0xf0) {
- return 4;
- }
- /* Invalid sequence */
- return -1;
-}
-
-int utf8_strlen(const char *str, int bytelen)
-{
- int charlen = 0;
- if (bytelen < 0) {
- bytelen = strlen(str);
- }
- while (bytelen) {
- int c;
- int l = utf8_tounicode(str, &c);
- charlen++;
- str += l;
- bytelen -= l;
- }
- return charlen;
-}
-
-int utf8_index(const char *str, int index)
-{
- const char *s = str;
- while (index--) {
- int c;
- s += utf8_tounicode(s, &c);
- }
- return s - str;
-}
-
-int utf8_charequal(const char *s1, const char *s2)
-{
- int c1, c2;
-
- utf8_tounicode(s1, &c1);
- utf8_tounicode(s2, &c2);
-
- return c1 == c2;
-}
-
-int utf8_prev_len(const char *str, int len)
-{
- int n = 1;
-
- assert(len > 0);
-
- /* Look up to len chars backward for a start-of-char byte */
- while (--len) {
- if ((str[-n] & 0x80) == 0) {
- /* Start of a 1-byte char */
- break;
- }
- if ((str[-n] & 0xc0) == 0xc0) {
- /* Start of a multi-byte char */
- break;
- }
- n++;
- }
- return n;
-}
-
-int utf8_tounicode(const char *str, int *uc)
-{
- unsigned const char *s = (unsigned const char *)str;
-
- if (s[0] < 0xc0) {
- *uc = s[0];
- return 1;
- }
- if (s[0] < 0xe0) {
- if ((s[1] & 0xc0) == 0x80) {
- *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80);
- return 2;
- }
- }
- else if (s[0] < 0xf0) {
- if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) {
- *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80);
- return 3;
- }
- }
-
- /* Invalid sequence, so just return the byte */
- *uc = *s;
- return 1;
-}
-
-struct casemap {
- unsigned short code; /* code point */
- signed char lowerdelta; /* add for lowercase, or if -128 use the ext table */
- signed char upperdelta; /* add for uppercase, or offset into the ext table */
-};
-
-/* Extended table for codepoints where |delta| > 127 */
-struct caseextmap {
- unsigned short lower;
- unsigned short upper;
-};
-
-/* Generated mapping tables */
-#include "_unicode_mapping.c"
-
-#define NUMCASEMAP sizeof(unicode_case_mapping) / sizeof(*unicode_case_mapping)
-
-static int cmp_casemap(const void *key, const void *cm)
-{
- return *(int *)key - (int)((const struct casemap *)cm)->code;
-}
-
-static int utf8_map_case(int uc, int upper)
-{
- const struct casemap *cm = bsearch(&uc, unicode_case_mapping, NUMCASEMAP, sizeof(*unicode_case_mapping), cmp_casemap);
-
- if (cm) {
- if (cm->lowerdelta == -128) {
- uc = upper ? unicode_extmap[cm->upperdelta].upper : unicode_extmap[cm->upperdelta].lower;
- }
- else {
- uc += upper ? cm->upperdelta : cm->lowerdelta;
- }
- }
- return uc;
-}
-
-int utf8_upper(int uc)
-{
- if (isascii(uc)) {
- return toupper(uc);
- }
- return utf8_map_case(uc, 1);
-}
-
-int utf8_lower(int uc)
-{
- if (isascii(uc)) {
- return tolower(uc);
- }
-
- return utf8_map_case(uc, 0);
-}
-
-#endif
#include <errno.h>
#include <string.h>
@@ -21478,7 +18791,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
}
#ifdef USE_LINENOISE
if (strcmp(str, "h") == 0) {
- /* built-in history command */
+
int i;
int len;
char **history = linenoiseHistory(&len);
@@ -21515,47 +18828,6 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
Jim_Free(history_file);
return JIM_OK;
}
-/*
- * Implements the internals of the format command for jim
- *
- * The FreeBSD license
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on code originally from Tcl 8.5:
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- * Copyright (c) 1999 by Scriptics Corporation.
- *
- * See the file "tcl.license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
#include <ctype.h>
#include <string.h>
@@ -21564,27 +18836,19 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
#define JIM_INTEGER_SPACE 24
#define MAX_FLOAT_WIDTH 320
-/**
- * Apply the printf-like format in fmtObjPtr with the given arguments.
- *
- * Returns a new object with zero reference count if OK, or NULL on error.
- */
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
{
const char *span, *format, *formatEnd, *msg;
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
- static const char *mixedXPG =
+ static const char * const mixedXPG =
"cannot mix \"%\" and \"%n$\" conversion specifiers";
- static const char *badIndex[2] = {
+ static const char * const badIndex[2] = {
"not enough arguments for all format specifiers",
"\"%n$\" argument index out of range"
};
int formatLen;
Jim_Obj *resultPtr;
- /* A single buffer is used to store numeric fields (with sprintf())
- * This buffer is allocated/reallocated as necessary
- */
char *num_buffer = NULL;
int num_buffer_size = 0;
@@ -21620,11 +18884,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
numBytes = 0;
}
- /*
- * Saw a % : process the format specifier.
- *
- * Step 0. Handle special case of escaped format marker (i.e., %%).
- */
step = utf8_tounicode(format, &ch);
if (ch == '%') {
@@ -21634,9 +18893,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
continue;
}
- /*
- * Step 1. XPG3 position specifier
- */
newXpg = 0;
if (isdigit(ch)) {
@@ -21666,9 +18922,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
goto errorMsg;
}
- /*
- * Step 2. Set of flags. Also build up the sprintf spec.
- */
p = spec;
*p++ = '%';
@@ -21695,9 +18948,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
step = utf8_tounicode(format, &ch);
} while (sawFlag);
- /*
- * Step 3. Minimum field width.
- */
width = 0;
if (isdigit(ch)) {
@@ -21724,9 +18974,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
step = utf8_tounicode(format, &ch);
}
- /*
- * Step 4. Precision.
- */
gotPrecision = precision = 0;
if (ch == '.') {
@@ -21747,9 +18994,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
goto error;
}
- /*
- * TODO: Check this truncation logic.
- */
if (precision < 0) {
precision = 0;
@@ -21759,9 +19003,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
step = utf8_tounicode(format, &ch);
}
- /*
- * Step 5. Length modifier.
- */
useShort = 0;
if (ch == 'h') {
@@ -21769,7 +19010,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
format += step;
step = utf8_tounicode(format, &ch);
} else if (ch == 'l') {
- /* Just for compatibility. All non-short integers are wide. */
+
format += step;
step = utf8_tounicode(format, &ch);
if (ch == 'l') {
@@ -21781,9 +19022,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
format += step;
span = format;
- /*
- * Step 6. The actual conversion character.
- */
if (ch == 'i') {
ch = 'd';
@@ -21791,11 +19029,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
doubleType = 0;
- /* Each valid conversion will set:
- * formatted_buf - the result to be added
- * formatted_chars - the length of formatted_buf in characters
- * formatted_bytes - the length of formatted_buf in bytes
- */
switch (ch) {
case '\0':
msg = "format string ended in middle of field specifier";
@@ -21804,7 +19037,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
if (gotPrecision && (precision < formatted_chars)) {
- /* Need to build a (null terminated) truncated string */
+
formatted_chars = precision;
formatted_bytes = utf8_index(formatted_buf, precision);
}
@@ -21816,7 +19049,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
goto error;
}
- /* Just store the value in the 'spec' buffer */
+
formatted_bytes = utf8_fromunicode(spec, code);
formatted_buf = spec;
formatted_chars = 1;
@@ -21829,7 +19062,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
case 'g':
case 'G':
doubleType = 1;
- /* fall through */
+
case 'd':
case 'u':
case 'o':
@@ -21839,7 +19072,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
double d;
int length;
- /* Fill in the width and precision */
+
if (width) {
p += sprintf(p, "%ld", width);
}
@@ -21847,7 +19080,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
p += sprintf(p, ".%ld", precision);
}
- /* Now the modifier, and get the actual value here */
+
if (doubleType) {
if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
goto error;
@@ -21881,7 +19114,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
*p++ = (char) ch;
*p = '\0';
- /* Adjust length for width and precision */
+
if (width > length) {
length = width;
}
@@ -21889,7 +19122,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
length += precision;
}
- /* Increase the size of the buffer if needed */
+
if (num_buffer_size < length + 1) {
num_buffer_size = length + 1;
num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
@@ -21907,7 +19140,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
}
default: {
- /* Just reuse the 'spec' buffer */
+
spec[0] = ch;
spec[1] = '\0';
Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
@@ -21945,57 +19178,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
Jim_Free(num_buffer);
return NULL;
}
-/*
- * regcomp and regexec -- regsub and regerror are elsewhere
- *
- * Copyright (c) 1986 by University of Toronto.
- * Written by Henry Spencer. Not derived from licensed software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to redistribute it freely,
- * subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of
- * this software, no matter how awful, even if they arise
- * from defects in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
- *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to |
- *** to assist in implementing egrep.
- *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
- *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
- *** as in BSD grep and ex.
- *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
- *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
- *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods,
- *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
- *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
- *** seiwald@vix.com, on 28 August 1993, for use in jam. Regmagic.h
- *** was moved into regexp.h, and the include of regexp.h now uses "'s
- *** to avoid conflicting with the system regexp.h. Const, bless its
- *** soul, was removed so it can compile everywhere. The declaration
- *** of strchr() was in conflict on AIX, so it was removed (as it is
- *** happily defined in string.h).
- *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
- *** seiwald@perforce.com, on 20 January 2000, to use function prototypes.
- *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
- *** seiwald@perforce.com, on 05 November 2002, to const string literals.
- *
- * THIS IS AN ALTERED VERSION. It was altered by Steve Bennett <steveb@workware.net.au>
- * on 16 October 2010, to remove static state and add better Tcl ARE compatibility.
- * This includes counted repetitions, UTF-8 support, character classes,
- * shorthand character classes, increased number of parentheses to 100,
- * backslash escape sequences. It also removes \n as an alternative to |.
- *
- * Beware that some of this code is subtly aware of the way operator
- * precedence is structured in regular expressions. Serious changes in
- * regular-expression syntax might require a total rethink.
- */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
@@ -22004,117 +19186,55 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
-/*
- * Structure for regexp "program". This is essentially a linear encoding
- * of a nondeterministic finite-state machine (aka syntax charts or
- * "railroad normal form" in parsing technology). Each node is an opcode
- * plus a "next" pointer, possibly plus an operand. "Next" pointers of
- * all nodes except BRANCH implement concatenation; a "next" pointer with
- * a BRANCH on both ends of it is connecting two alternatives. (Here we
- * have one of the subtle syntax dependencies: an individual BRANCH (as
- * opposed to a collection of them) is never concatenated with anything
- * because of operator precedence.) The operand of some types of node is
- * a literal string; for others, it is a node leading into a sub-FSM. In
- * particular, the operand of a BRANCH node is the first node of the branch.
- * (NB this is *not* a tree structure: the tail of the branch connects
- * to the thing following the set of BRANCHes.) The opcodes are:
- */
-
-/* This *MUST* be less than (255-20)/2=117 */
+
+
#define REG_MAX_PAREN 100
-/* definition number opnd? meaning */
-#define END 0 /* no End of program. */
-#define BOL 1 /* no Match "" at beginning of line. */
-#define EOL 2 /* no Match "" at end of line. */
-#define ANY 3 /* no Match any one character. */
-#define ANYOF 4 /* str Match any character in this string. */
-#define ANYBUT 5 /* str Match any character not in this string. */
-#define BRANCH 6 /* node Match this alternative, or the next... */
-#define BACK 7 /* no Match "", "next" ptr points backward. */
-#define EXACTLY 8 /* str Match this string. */
-#define NOTHING 9 /* no Match empty string. */
-#define REP 10 /* max,min Match this (simple) thing [min,max] times. */
-#define REPMIN 11 /* max,min Match this (simple) thing [min,max] times, mininal match. */
-#define REPX 12 /* max,min Match this (complex) thing [min,max] times. */
-#define REPXMIN 13 /* max,min Match this (complex) thing [min,max] times, minimal match. */
-
-#define WORDA 15 /* no Match "" at wordchar, where prev is nonword */
-#define WORDZ 16 /* no Match "" at nonwordchar, where prev is word */
-#define OPEN 20 /* no Mark this point in input as start of #n. */
- /* OPEN+1 is number 1, etc. */
-#define CLOSE (OPEN+REG_MAX_PAREN) /* no Analogous to OPEN. */
+
+#define END 0
+#define BOL 1
+#define EOL 2
+#define ANY 3
+#define ANYOF 4
+#define ANYBUT 5
+#define BRANCH 6
+#define BACK 7
+#define EXACTLY 8
+#define NOTHING 9
+#define REP 10
+#define REPMIN 11
+#define REPX 12
+#define REPXMIN 13
+
+#define WORDA 15
+#define WORDZ 16
+#define OPEN 20
+
+#define CLOSE (OPEN+REG_MAX_PAREN)
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
-/*
- * The first byte of the regexp internal "program" is actually this magic
- * number; the start node begins in the second byte.
- */
#define REG_MAGIC 0xFADED00D
-/*
- * Opcode notes:
- *
- * BRANCH The set of branches constituting a single choice are hooked
- * together with their "next" pointers, since precedence prevents
- * anything being concatenated to any individual branch. The
- * "next" pointer of the last BRANCH in a choice points to the
- * thing following the whole choice. This is also where the
- * final "next" pointer of each individual branch points; each
- * branch starts with the operand node of a BRANCH node.
- *
- * BACK Normal "next" pointers all implicitly point forward; BACK
- * exists to make loop structures possible.
- *
- * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
- * BRANCH structures using BACK. Simple cases (one character
- * per match) are implemented with STAR and PLUS for speed
- * and to minimize recursive plunges.
- *
- * OPEN,CLOSE ...are numbered at compile time.
- */
-
-/*
- * A node is one char of opcode followed by two chars of "next" pointer.
- * "Next" pointers are stored as two 8-bit pieces, high order first. The
- * value is a positive offset from the opcode of the node containing it.
- * An operand, if any, simply follows the node. (Note that much of the
- * code generation knows about this implicit relationship.)
- *
- * Using two bytes for the "next" pointer is vast overkill for most things,
- * but allows patterns to get big without disasters.
- */
+
#define OP(preg, p) (preg->program[p])
#define NEXT(preg, p) (preg->program[p + 1])
#define OPERAND(p) ((p) + 2)
-/*
- * See regmagic.h for one further detail of program structure.
- */
-/*
- * Utility definitions.
- */
#define FAIL(R,M) { (R)->err = (M); return (M); }
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
#define META "^$.[()|?{+*"
-/*
- * Flags to be passed up and down.
- */
-#define HASWIDTH 01 /* Known never to match null string. */
-#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
-#define SPSTART 04 /* Starts with * or +. */
-#define WORST 0 /* Worst case. */
+#define HASWIDTH 01
+#define SIMPLE 02
+#define SPSTART 04
+#define WORST 0
#define MAX_REP_COUNT 1000000
-/*
- * Forward declarations for regcomp()'s friends.
- */
-static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp );
+static int reg(regex_t *preg, int paren , int *flagp );
static int regpiece(regex_t *preg, int *flagp );
static int regbranch(regex_t *preg, int *flagp );
static int regatom(regex_t *preg, int *flagp );
@@ -22130,7 +19250,7 @@ static int reg_range_find(const int *string, int c);
static const char *str_find(const char *string, int c, int nocase);
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
-/*#define DEBUG*/
+
#ifdef DEBUG
int regnarrate = 0;
static void regdump(regex_t *preg);
@@ -22138,9 +19258,6 @@ static const char *regprop( int op );
#endif
-/**
- * Returns the length of the null-terminated integer sequence.
- */
static int str_int_len(const int *seq)
{
int n = 0;
@@ -22150,21 +19267,6 @@ static int str_int_len(const int *seq)
return n;
}
-/*
- - regcomp - compile a regular expression into internal code
- *
- * We can't allocate space until we know how big the compiled form will be,
- * but we can't compile it (and thus know how big it is) until we've got a
- * place to put the code. So we cheat: we compile it twice, once with code
- * generation turned off and size counting turned on, and once "for real".
- * This also means that we don't allocate space until we are sure that the
- * thing really will compile successfully, and we never have to move the
- * code and thus invalidate pointers into it. (Note that it has to be in
- * one piece because free() must be able to free it all.)
- *
- * Beware that the optimization-preparation code in here knows about some
- * of the structure of the compiled regexp.
- */
int regcomp(regex_t *preg, const char *exp, int cflags)
{
int scan;
@@ -22180,57 +19282,46 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
if (exp == NULL)
FAIL(preg, REG_ERR_NULL_ARGUMENT);
- /* First pass: determine size, legality. */
+
preg->cflags = cflags;
preg->regparse = exp;
- /* XXX: For now, start unallocated */
+
preg->program = NULL;
preg->proglen = 0;
#if 1
- /* Allocate space. */
+
preg->proglen = (strlen(exp) + 1) * 5;
preg->program = malloc(preg->proglen * sizeof(int));
if (preg->program == NULL)
FAIL(preg, REG_ERR_NOMEM);
#endif
- /* Note that since we store a magic value as the first item in the program,
- * program offsets will never be 0
- */
regc(preg, REG_MAGIC);
if (reg(preg, 0, &flags) == 0) {
return preg->err;
}
- /* Small enough for pointer-storage convention? */
- if (preg->re_nsub >= REG_MAX_PAREN) /* Probably could be 65535L. */
+
+ if (preg->re_nsub >= REG_MAX_PAREN)
FAIL(preg,REG_ERR_TOO_BIG);
- /* Dig out information for optimizations. */
- preg->regstart = 0; /* Worst-case defaults. */
+
+ preg->regstart = 0;
preg->reganch = 0;
preg->regmust = 0;
preg->regmlen = 0;
- scan = 1; /* First BRANCH. */
- if (OP(preg, regnext(preg, scan)) == END) { /* Only one top-level choice. */
+ scan = 1;
+ if (OP(preg, regnext(preg, scan)) == END) {
scan = OPERAND(scan);
- /* Starting-point info. */
+
if (OP(preg, scan) == EXACTLY) {
preg->regstart = preg->program[OPERAND(scan)];
}
else if (OP(preg, scan) == BOL)
preg->reganch++;
- /*
- * If there's something expensive in the r.e., find the
- * longest literal string that must appear and make it the
- * regmust. Resolve ties in favor of later strings, since
- * the regstart check works with the beginning of the r.e.
- * and avoiding duplication strengthens checking. Not a
- * strong reason, but sufficient in the absence of others.
- */
if (flags&SPSTART) {
longest = 0;
len = 0;
@@ -22255,16 +19346,7 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
return 0;
}
-/*
- - reg - regular expression, i.e. main body or parenthesized thing
- *
- * Caller must absorb opening parenthesis.
- *
- * Combining parenthesis handling with the base level of regular expression
- * is a trifle forced, but the need to tie the tails of the branches to what
- * follows makes it hard to avoid.
- */
-static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
+static int reg(regex_t *preg, int paren , int *flagp )
{
int ret;
int br;
@@ -22272,21 +19354,21 @@ static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
int parno = 0;
int flags;
- *flagp = HASWIDTH; /* Tentatively. */
+ *flagp = HASWIDTH;
- /* Make an OPEN node, if parenthesized. */
+
if (paren) {
parno = ++preg->re_nsub;
ret = regnode(preg, OPEN+parno);
} else
ret = 0;
- /* Pick up the branches, linking them together. */
+
br = regbranch(preg, &flags);
if (br == 0)
return 0;
if (ret != 0)
- regtail(preg, ret, br); /* OPEN -> first. */
+ regtail(preg, ret, br);
else
ret = br;
if (!(flags&HASWIDTH))
@@ -22297,21 +19379,21 @@ static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
br = regbranch(preg, &flags);
if (br == 0)
return 0;
- regtail(preg, ret, br); /* BRANCH -> BRANCH. */
+ regtail(preg, ret, br);
if (!(flags&HASWIDTH))
*flagp &= ~HASWIDTH;
*flagp |= flags&SPSTART;
}
- /* Make a closing node, and hook it on the end. */
+
ender = regnode(preg, (paren) ? CLOSE+parno : END);
regtail(preg, ret, ender);
- /* Hook the tails of the branches to the closing node. */
+
for (br = ret; br != 0; br = regnext(preg, br))
regoptail(preg, br, ender);
- /* Check for proper termination. */
+
if (paren && *preg->regparse++ != ')') {
preg->err = REG_ERR_UNMATCHED_PAREN;
return 0;
@@ -22328,11 +19410,6 @@ static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
return(ret);
}
-/*
- - regbranch - one alternative of an | operator
- *
- * Implements the concatenation operator.
- */
static int regbranch(regex_t *preg, int *flagp )
{
int ret;
@@ -22340,7 +19417,7 @@ static int regbranch(regex_t *preg, int *flagp )
int latest;
int flags;
- *flagp = WORST; /* Tentatively. */
+ *flagp = WORST;
ret = regnode(preg, BRANCH);
chain = 0;
@@ -22350,7 +19427,7 @@ static int regbranch(regex_t *preg, int *flagp )
if (latest == 0)
return 0;
*flagp |= flags&HASWIDTH;
- if (chain == 0) {/* First piece. */
+ if (chain == 0) {
*flagp |= flags&SPSTART;
}
else {
@@ -22358,21 +19435,12 @@ static int regbranch(regex_t *preg, int *flagp )
}
chain = latest;
}
- if (chain == 0) /* Loop ran zero times. */
+ if (chain == 0)
(void) regnode(preg, NOTHING);
return(ret);
}
-/*
- - regpiece - something followed by possible [*+?]
- *
- * Note that the branching code sequences used for ? and the general cases
- * of * and + are somewhat optimized: they use the same NOTHING node as
- * both the endmarker for their branch list and the body of the last branch.
- * It might seem that this node could be dispensed with entirely, but the
- * endmarker role is not redundant.
- */
static int regpiece(regex_t *preg, int *flagp)
{
int ret;
@@ -22398,7 +19466,7 @@ static int regpiece(regex_t *preg, int *flagp)
return 0;
}
- /* Handle braces (counted repetition) by expansion */
+
if (op == '{') {
char *end;
@@ -22465,24 +19533,16 @@ static int regpiece(regex_t *preg, int *flagp)
return chain ? chain : ret;
}
-/**
- * Add all characters in the inclusive range between lower and upper.
- *
- * Handles a swapped range (upper < lower).
- */
static void reg_addrange(regex_t *preg, int lower, int upper)
{
if (lower > upper) {
reg_addrange(preg, upper, lower);
}
- /* Add a range as length, start */
+
regc(preg, upper - lower + 1);
regc(preg, lower);
}
-/**
- * Add a null-terminated literal string as a set of ranges.
- */
static void reg_addrange_str(regex_t *preg, const char *str)
{
while (*str) {
@@ -22491,11 +19551,6 @@ static void reg_addrange_str(regex_t *preg, const char *str)
}
}
-/**
- * Extracts the next unicode char from utf8.
- *
- * If 'upper' is set, converts the char to uppercase.
- */
static int reg_utf8_tounicode_case(const char *s, int *uc, int upper)
{
int l = utf8_tounicode(s, uc);
@@ -22505,11 +19560,6 @@ static int reg_utf8_tounicode_case(const char *s, int *uc, int upper)
return l;
}
-/**
- * Converts a hex digit to decimal.
- *
- * Returns -1 for an invalid hex digit.
- */
static int hexdigitval(int c)
{
if (c >= '0' && c <= '9')
@@ -22521,12 +19571,6 @@ static int hexdigitval(int c)
return -1;
}
-/**
- * Parses up to 'n' hex digits at 's' and stores the result in *uc.
- *
- * Returns the number of hex digits parsed.
- * If there are no hex digits, returns 0 and stores nothing.
- */
static int parse_hex(const char *s, int n, int *uc)
{
int val = 0;
@@ -22545,13 +19589,6 @@ static int parse_hex(const char *s, int n, int *uc)
return k;
}
-/**
- * Call for chars after a backlash to decode the escape sequence.
- *
- * Stores the result in *ch.
- *
- * Returns the number of bytes consumed.
- */
static int reg_decode_escape(const char *s, int *ch)
{
int n;
@@ -22585,14 +19622,6 @@ static int reg_decode_escape(const char *s, int *ch)
return s - s0;
}
-/*
- - regatom - the lowest level
- *
- * Optimization: gobbles an entire sequence of ordinary characters so that
- * it can turn them into a single node, which is smaller to store and
- * faster to run. Backslashed characters are exceptions, each becoming a
- * separate node; the code is simpler that way and it's not worth fixing.
- */
static int regatom(regex_t *preg, int *flagp)
{
int ret;
@@ -22602,11 +19631,11 @@ static int regatom(regex_t *preg, int *flagp)
int ch;
int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
- *flagp = WORST; /* Tentatively. */
+ *flagp = WORST;
preg->regparse += n;
switch (ch) {
- /* FIXME: these chars only have meaning at beg/end of pat? */
+
case '^':
ret = regnode(preg, BOL);
break;
@@ -22620,20 +19649,20 @@ static int regatom(regex_t *preg, int *flagp)
case '[': {
const char *pattern = preg->regparse;
- if (*pattern == '^') { /* Complement of range. */
+ if (*pattern == '^') {
ret = regnode(preg, ANYBUT);
pattern++;
} else
ret = regnode(preg, ANYOF);
- /* Special case. If the first char is ']' or '-', it is part of the set */
+
if (*pattern == ']' || *pattern == '-') {
reg_addrange(preg, *pattern, *pattern);
pattern++;
}
while (*pattern && *pattern != ']') {
- /* Is this a range? a-z */
+
int start;
int end;
@@ -22646,7 +19675,7 @@ static int regatom(regex_t *preg, int *flagp)
}
}
if (pattern[0] == '-' && pattern[1]) {
- /* skip '-' */
+
pattern += utf8_tounicode(pattern, &end);
pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
if (end == '\\') {
@@ -22684,7 +19713,7 @@ static int regatom(regex_t *preg, int *flagp)
continue;
}
}
- /* Not a range, so just add the char */
+
reg_addrange(preg, start, start);
}
regc(preg, '\0');
@@ -22707,7 +19736,7 @@ static int regatom(regex_t *preg, int *flagp)
case '|':
case ')':
preg->err = REG_ERR_INTERNAL;
- return 0; /* Supposed to be caught earlier. */
+ return 0;
case '?':
case '+':
case '*':
@@ -22750,47 +19779,32 @@ static int regatom(regex_t *preg, int *flagp)
regc(preg, '\0');
*flagp |= HASWIDTH|SIMPLE;
break;
- /* FIXME: Someday handle \1, \2, ... */
+
default:
- /* Handle general quoted chars in exact-match routine */
- /* Back up to include the backslash */
+
+
preg->regparse--;
goto de_fault;
}
break;
de_fault:
default: {
- /*
- * Encode a string of characters to be matched exactly.
- */
int added = 0;
- /* Back up to pick up the first char of interest */
+
preg->regparse -= n;
ret = regnode(preg, EXACTLY);
- /* Note that a META operator such as ? or * consumes the
- * preceding char.
- * Thus we must be careful to look ahead by 2 and add the
- * last char as it's own EXACTLY if necessary
- */
- /* Until end of string or a META char is reached */
+
while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
if (ch == '\\' && preg->regparse[n]) {
- /* Non-trailing backslash.
- * Is this a special escape, or a regular escape?
- */
if (strchr("<>mMwds", preg->regparse[n])) {
- /* A special escape. All done with EXACTLY */
+
break;
}
- /* Decode it. Note that we add the length for the escape
- * sequence to the length for the backlash so we can skip
- * the entire sequence, or not as required.
- */
n += reg_decode_escape(preg->regparse + n, &ch);
if (ch == 0) {
preg->err = REG_ERR_NULL_CHAR;
@@ -22798,24 +19812,21 @@ static int regatom(regex_t *preg, int *flagp)
}
}
- /* Now we have one char 'ch' of length 'n'.
- * Check to see if the following char is a MULT
- */
if (ISMULT(preg->regparse[n])) {
- /* Yes. But do we already have some EXACTLY chars? */
+
if (added) {
- /* Yes, so return what we have and pick up the current char next time around */
+
break;
}
- /* No, so add this single char and finish */
+
regc(preg, ch);
added++;
preg->regparse += n;
break;
}
- /* No, so just add this char normally */
+
regc(preg, ch);
added++;
preg->regparse += n;
@@ -22841,10 +19852,7 @@ static void reg_grow(regex_t *preg, int n)
}
}
-/*
- - regnode - emit a node
- */
-/* Location. */
+
static int regnode(regex_t *preg, int op)
{
reg_grow(preg, 2);
@@ -22852,32 +19860,23 @@ static int regnode(regex_t *preg, int op)
preg->program[preg->p++] = op;
preg->program[preg->p++] = 0;
- /* Return the start of the node */
+
return preg->p - 2;
}
-/*
- - regc - emit (if appropriate) a byte of code
- */
static void regc(regex_t *preg, int b )
{
reg_grow(preg, 1);
preg->program[preg->p++] = b;
}
-/*
- - reginsert - insert an operator in front of already-emitted operand
- *
- * Means relocating the operand.
- * Returns the new location of the original operand.
- */
static int reginsert(regex_t *preg, int op, int size, int opnd )
{
reg_grow(preg, size);
- /* Move everything from opnd up */
+
memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
- /* Zero out the new space */
+
memset(preg->program + opnd, 0, sizeof(int) * size);
preg->program[opnd] = op;
@@ -22887,16 +19886,13 @@ static int reginsert(regex_t *preg, int op, int size, int opnd )
return opnd + size;
}
-/*
- - regtail - set the next-pointer at the end of a node chain
- */
static void regtail_(regex_t *preg, int p, int val, int line )
{
int scan;
int temp;
int offset;
- /* Find last node. */
+
scan = p;
for (;;) {
temp = regnext(preg, scan);
@@ -22913,43 +19909,31 @@ static void regtail_(regex_t *preg, int p, int val, int line )
preg->program[scan + 1] = offset;
}
-/*
- - regoptail - regtail on operand of first argument; nop if operandless
- */
static void regoptail(regex_t *preg, int p, int val )
{
- /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+
if (p != 0 && OP(preg, p) == BRANCH) {
regtail(preg, OPERAND(p), val);
}
}
-/*
- * regexec and friends
- */
-/*
- * Forwards.
- */
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);
-/*
- - regexec - match a regexp against a string
- */
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
{
const char *s;
int scan;
- /* Be paranoid... */
+
if (preg == NULL || preg->program == NULL || string == NULL) {
return REG_ERR_NULL_ARGUMENT;
}
- /* Check validity of program. */
+
if (*preg->program != REG_MAGIC) {
return REG_ERR_CORRUPTED;
}
@@ -22962,9 +19946,9 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat
preg->eflags = eflags;
preg->pmatch = pmatch;
preg->nmatch = nmatch;
- preg->start = string; /* All offsets are computed from here */
+ preg->start = string;
- /* Must clear out the embedded repeat counts */
+
for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) {
switch (OP(preg, scan)) {
case REP:
@@ -22976,7 +19960,7 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat
}
}
- /* If there is a "must appear" string, look for it. */
+
if (preg->regmust != 0) {
s = string;
while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
@@ -22985,17 +19969,17 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat
}
s++;
}
- if (s == NULL) /* Not present. */
+ if (s == NULL)
return REG_NOMATCH;
}
- /* Mark beginning of line for ^ . */
+
preg->regbol = string;
- /* Simplest case: anchored match need be tried only once (maybe per line). */
+
if (preg->reganch) {
if (eflags & REG_NOTBOL) {
- /* This is an anchored search, but not an BOL, so possibly skip to the next line */
+
goto nextline;
}
while (1) {
@@ -23006,7 +19990,7 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat
if (*string) {
nextline:
if (preg->cflags & REG_NEWLINE) {
- /* Try the next anchor? */
+
string = strchr(string, '\n');
if (string) {
preg->regbol = ++string;
@@ -23018,10 +20002,10 @@ nextline:
}
}
- /* Messy cases: unanchored match. */
+
s = string;
if (preg->regstart != '\0') {
- /* We know what char it must start with. */
+
while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
if (regtry(preg, s))
return REG_NOERROR;
@@ -23029,7 +20013,7 @@ nextline:
}
}
else
- /* We don't -- general case. */
+
while (1) {
if (regtry(preg, s))
return REG_NOERROR;
@@ -23039,14 +20023,11 @@ nextline:
s += utf8_charlen(*s);
}
- /* Failure. */
+
return REG_NOMATCH;
}
-/*
- - regtry - try match at specific point
- */
- /* 0 failure, 1 success */
+
static int regtry( regex_t *preg, const char *string )
{
int i;
@@ -23065,13 +20046,6 @@ static int regtry( regex_t *preg, const char *string )
return(0);
}
-/**
- * Returns bytes matched if 'pattern' is a prefix of 'string'.
- *
- * If 'nocase' is non-zero, does a case-insensitive match.
- *
- * Returns -1 on not found.
- */
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase)
{
const char *s = string;
@@ -23091,15 +20065,10 @@ static int prefix_cmp(const int *prog, int proglen, const char *string, int noca
return -1;
}
-/**
- * Searchs for 'c' in the range 'range'.
- *
- * Returns 1 if found, or 0 if not.
- */
static int reg_range_find(const int *range, int c)
{
while (*range) {
- /*printf("Checking %d in range [%d,%d]\n", c, range[1], (range[0] + range[1] - 1));*/
+
if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
return 1;
}
@@ -23108,19 +20077,10 @@ static int reg_range_find(const int *range, int c)
return 0;
}
-/**
- * Search for the character 'c' in the utf-8 string 'string'.
- *
- * If 'nocase' is set, the 'string' is assumed to be uppercase
- * and 'c' is converted to uppercase before matching.
- *
- * Returns the byte position in the string where the 'c' was found, or
- * NULL if not found.
- */
static const char *str_find(const char *string, int c, int nocase)
{
if (nocase) {
- /* The "string" should already be converted to uppercase */
+
c = utf8_upper(c);
}
while (*string) {
@@ -23134,12 +20094,6 @@ static const char *str_find(const char *string, int c, int nocase)
return NULL;
}
-/**
- * Returns true if 'ch' is an end-of-line char.
- *
- * In REG_NEWLINE mode, \n is considered EOL in
- * addition to \0
- */
static int reg_iseol(regex_t *preg, int ch)
{
if (preg->cflags & REG_NEWLINE) {
@@ -23161,10 +20115,6 @@ static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin)
int min = preg->program[scan + 3];
int next = regnext(preg, scan);
- /*
- * Lookahead to avoid useless match attempts
- * when we know what character comes next.
- */
if (OP(preg, next) == EXACTLY) {
nextch = preg->program[OPERAND(next)];
}
@@ -23174,11 +20124,11 @@ static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin)
return 0;
}
if (matchmin) {
- /* from min up to no */
+
max = no;
no = min;
}
- /* else from no down to min */
+
while (1) {
if (matchmin) {
if (no > max) {
@@ -23192,18 +20142,18 @@ static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin)
}
preg->reginput = save + utf8_index(save, no);
reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
- /* If it could work, try it. */
+
if (reg_iseol(preg, nextch) || c == nextch) {
if (regmatch(preg, next)) {
return(1);
}
}
if (matchmin) {
- /* Couldn't or didn't, add one more */
+
no++;
}
else {
- /* Couldn't or didn't -- back up. */
+
no--;
}
}
@@ -23217,9 +20167,9 @@ static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
int max = scanpt[2];
int min = scanpt[3];
- /* Have we reached min? */
+
if (scanpt[4] < min) {
- /* No, so get another one */
+
scanpt[4]++;
if (regmatch(preg, scan + 5)) {
return 1;
@@ -23232,11 +20182,11 @@ static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
}
if (matchmin) {
- /* minimal, so try other branch first */
+
if (regmatch(preg, regnext(preg, scan))) {
return 1;
}
- /* No, so try one more */
+
scanpt[4]++;
if (regmatch(preg, scan + 5)) {
return 1;
@@ -23244,7 +20194,7 @@ static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
scanpt[4]--;
return 0;
}
- /* maximal, so try this branch again */
+
if (scanpt[4] < max) {
scanpt[4]++;
if (regmatch(preg, scan + 5)) {
@@ -23252,25 +20202,15 @@ static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
}
scanpt[4]--;
}
- /* At this point we are at max with no match. Try the other branch */
+
return regmatch(preg, regnext(preg, scan));
}
-/*
- - regmatch - main matching routine
- *
- * Conceptually the strategy is simple: check to see whether the current
- * node matches, call self recursively to see whether the rest matches,
- * and then act accordingly. In practice we make some effort to avoid
- * recursion, in particular by going through "ordinary" nodes (that don't
- * need to know whether the rest of the match failed) by a loop instead of
- * by recursion.
- */
-/* 0 failure, 1 success */
+
static int regmatch(regex_t *preg, int prog)
{
- int scan; /* Current node. */
- int next; /* Next node. */
+ int scan;
+ int next;
scan = prog;
@@ -23283,8 +20223,7 @@ static int regmatch(regex_t *preg, int prog)
int c;
#ifdef DEBUG
if (regnarrate) {
- //fprintf(stderr, "%s...\n", regprop(scan));
- fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); /* Where, what. */
+ fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan)));
}
#endif
next = regnext(preg, scan);
@@ -23301,27 +20240,27 @@ static int regmatch(regex_t *preg, int prog)
}
break;
case WORDA:
- /* Must be looking at a letter, digit, or _ */
+
if ((!isalnum(UCHAR(c))) && c != '_')
return(0);
- /* Prev must be BOL or nonword */
+
if (preg->reginput > preg->regbol &&
(isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
return(0);
break;
case WORDZ:
- /* Can't match at BOL */
+
if (preg->reginput > preg->regbol) {
- /* Current must be EOL or nonword */
+
if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
c = preg->reginput[-1];
- /* Previous must be word */
+
if (isalnum(UCHAR(c)) || c == '_') {
break;
}
}
}
- /* No */
+
return(0);
case ANY:
@@ -23363,8 +20302,8 @@ static int regmatch(regex_t *preg, int prog)
case BRANCH: {
const char *save;
- if (OP(preg, next) != BRANCH) /* No choice. */
- next = OPERAND(scan); /* Avoid recursion. */
+ if (OP(preg, next) != BRANCH)
+ next = OPERAND(scan);
else {
do {
save = preg->reginput;
@@ -23375,7 +20314,7 @@ static int regmatch(regex_t *preg, int prog)
scan = regnext(preg, scan);
} while (scan != 0 && OP(preg, scan) == BRANCH);
return(0);
- /* NOTREACHED */
+
}
}
break;
@@ -23388,7 +20327,7 @@ static int regmatch(regex_t *preg, int prog)
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
case END:
- return(1); /* Success! */
+ return(1);
break;
default:
if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
@@ -23398,11 +20337,6 @@ static int regmatch(regex_t *preg, int prog)
if (regmatch(preg, next)) {
int no;
- /*
- * Don't set startp if some later
- * invocation of the same parentheses
- * already has.
- */
if (OP(preg, scan) < CLOSE) {
no = OP(preg, scan) - OPEN;
if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
@@ -23425,16 +20359,9 @@ static int regmatch(regex_t *preg, int prog)
scan = next;
}
- /*
- * We get here only if there's trouble -- normally "case END" is
- * the terminating point.
- */
return REG_ERR_INTERNAL;
}
-/*
- - regrepeat - repeatedly match something simple, report how many
- */
static int regrepeat(regex_t *preg, int p, int max)
{
int count = 0;
@@ -23447,7 +20374,7 @@ static int regrepeat(regex_t *preg, int p, int max)
opnd = OPERAND(p);
switch (OP(preg, p)) {
case ANY:
- /* No need to handle utf8 specially here */
+
while (!reg_iseol(preg, *scan) && count < max) {
count++;
scan++;
@@ -23483,9 +20410,9 @@ static int regrepeat(regex_t *preg, int p, int max)
scan += n;
}
break;
- default: /* Oh dear. Called inappropriately. */
+ default:
preg->err = REG_ERR_INTERNAL;
- count = 0; /* Best compromise. */
+ count = 0;
break;
}
preg->reginput = scan;
@@ -23493,9 +20420,6 @@ static int regrepeat(regex_t *preg, int p, int max)
return(count);
}
-/*
- - regnext - dig the "next" pointer out of a node
- */
static int regnext(regex_t *preg, int p )
{
int offset;
@@ -23511,151 +20435,6 @@ static int regnext(regex_t *preg, int p )
return(p+offset);
}
-#ifdef DEBUG
-
-/*
- - regdump - dump a regexp onto stdout in vaguely comprehensible form
- */
-static void regdump(regex_t *preg)
-{
- int s;
- int op = EXACTLY; /* Arbitrary non-END op. */
- int next;
- char buf[4];
-
- int i;
- for (i = 1; i < preg->p; i++) {
- printf("%02x ", preg->program[i]);
- if (i % 16 == 15) {
- printf("\n");
- }
- }
- printf("\n");
-
- s = 1;
- while (op != END && s < preg->p) { /* While that wasn't END last time... */
- op = OP(preg, s);
- printf("%3d: %s", s, regprop(op)); /* Where, what. */
- next = regnext(preg, s);
- if (next == 0) /* Next ptr. */
- printf("(0)");
- else
- printf("(%d)", next);
- s += 2;
- if (op == REP || op == REPMIN || op == REPX || op == REPXMIN) {
- int max = preg->program[s];
- int min = preg->program[s + 1];
- if (max == 65535) {
- printf("{%d,*}", min);
- }
- else {
- printf("{%d,%d}", min, max);
- }
- printf(" %d", preg->program[s + 2]);
- s += 3;
- }
- else if (op == ANYOF || op == ANYBUT) {
- /* set of ranges */
-
- while (preg->program[s]) {
- int len = preg->program[s++];
- int first = preg->program[s++];
- buf[utf8_fromunicode(buf, first)] = 0;
- printf("%s", buf);
- if (len > 1) {
- buf[utf8_fromunicode(buf, first + len - 1)] = 0;
- printf("-%s", buf);
- }
- }
- s++;
- }
- else if (op == EXACTLY) {
- /* Literal string, where present. */
-
- while (preg->program[s]) {
- buf[utf8_fromunicode(buf, preg->program[s])] = 0;
- printf("%s", buf);
- s++;
- }
- s++;
- }
- putchar('\n');
- }
-
- if (op == END) {
- /* Header fields of interest. */
- if (preg->regstart) {
- buf[utf8_fromunicode(buf, preg->regstart)] = 0;
- printf("start '%s' ", buf);
- }
- if (preg->reganch)
- printf("anchored ");
- if (preg->regmust != 0) {
- int i;
- printf("must have:");
- for (i = 0; i < preg->regmlen; i++) {
- putchar(preg->program[preg->regmust + i]);
- }
- putchar('\n');
- }
- }
- printf("\n");
-}
-
-/*
- - regprop - printable representation of opcode
- */
-static const char *regprop( int op )
-{
- static char buf[50];
-
- switch (op) {
- case BOL:
- return "BOL";
- case EOL:
- return "EOL";
- case ANY:
- return "ANY";
- case ANYOF:
- return "ANYOF";
- case ANYBUT:
- return "ANYBUT";
- case BRANCH:
- return "BRANCH";
- case EXACTLY:
- return "EXACTLY";
- case NOTHING:
- return "NOTHING";
- case BACK:
- return "BACK";
- case END:
- return "END";
- case REP:
- return "REP";
- case REPMIN:
- return "REPMIN";
- case REPX:
- return "REPX";
- case REPXMIN:
- return "REPXMIN";
- case WORDA:
- return "WORDA";
- case WORDZ:
- return "WORDZ";
- default:
- if (op >= OPEN && op < CLOSE) {
- snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN);
- }
- else if (op >= CLOSE && op < CLOSE_END) {
- snprintf(buf, sizeof(buf), "CLOSE%d", op-CLOSE);
- }
- else {
- snprintf(buf, sizeof(buf), "?%d?\n", op);
- }
- return(buf);
- }
-}
-#endif
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
{
@@ -23699,32 +20478,13 @@ void regfree(regex_t *preg)
#endif
-/* Jimsh - An interactive shell for Jim
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2009 Steve Bennett <steveb@workware.net.au>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-/* From initjimsh.tcl */
+
extern int Jim_initjimshInit(Jim_Interp *interp);
static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
@@ -23732,7 +20492,7 @@ static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
int n;
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
- /* Populate argv global var */
+
for (n = 0; n < argc; n++) {
Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
@@ -23753,11 +20513,11 @@ int main(int argc, char *const argv[])
return 0;
}
- /* Create and initialize the interpreter */
+
interp = Jim_CreateInterp();
Jim_RegisterCoreCommands(interp);
- /* Register static extensions */
+
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
Jim_MakeErrorMessage(interp);
fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));