aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2020-05-31 17:31:55 +1000
committerSteve Bennett <steveb@workware.net.au>2020-06-05 21:13:11 +1000
commitd4cd7cabc6359bf5e1af8ce0219e621ae0ec3d86 (patch)
tree98d160b6903044aaf50d7595b078b1d8ab3276bd
parentfdefefa4e655be612df2ac036d57223b8c9cbc0a (diff)
downloadjimtcl-d4cd7cabc6359bf5e1af8ce0219e621ae0ec3d86.zip
jimtcl-d4cd7cabc6359bf5e1af8ce0219e621ae0ec3d86.tar.gz
jimtcl-d4cd7cabc6359bf5e1af8ce0219e621ae0ec3d86.tar.bz2
core: variable names may now contain embedded nulls
Hash tables used to store variables are now use Jim_Obj keys rather than allocated char *, so embedded nulls are supported. This is generally a performance win as the existing Jim_Obj can be used as the key. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim.c253
-rw-r--r--jim.h1
-rw-r--r--tests/alias.test10
-rw-r--r--tests/coverage.test5
-rw-r--r--tests/dict2.test5
-rw-r--r--tests/misc.test12
-rw-r--r--tests/pack.test2
7 files changed, 167 insertions, 121 deletions
diff --git a/jim.c b/jim.c
index 4bd8576..432f55a 100644
--- a/jim.c
+++ b/jim.c
@@ -150,6 +150,8 @@ static int JimSign(jim_wide w);
static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr);
static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
+static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_Var *var);
+static Jim_Var *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr);
/* Fast access to the int (wide) value of an object which is known to be of int type */
@@ -885,10 +887,11 @@ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
return JIM_ERR; /* not found */
}
-/* Remove all entries from the hash table
- * and leave it empty for reuse
+/**
+ * Clear all hash entries from the table, but don't free
+ * the table.
*/
-int Jim_FreeHashTable(Jim_HashTable *ht)
+void Jim_ClearHashTable(Jim_HashTable *ht)
{
unsigned int i;
@@ -896,8 +899,7 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
for (i = 0; ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
- if ((he = ht->table[i]) == NULL)
- continue;
+ he = ht->table[i];
while (he) {
nextHe = he->next;
Jim_FreeEntryKey(ht, he);
@@ -906,7 +908,16 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
ht->used--;
he = nextHe;
}
+ ht->table[i] = NULL;
}
+}
+
+/* Remove all entries from the hash table
+ * and leave it empty for reuse
+ */
+int Jim_FreeHashTable(Jim_HashTable *ht)
+{
+ Jim_ClearHashTable(ht);
/* Free the table and the allocated cache structure */
Jim_Free(ht->table);
/* Re-initialize the table */
@@ -3759,12 +3770,36 @@ static void JimVariablesHTValDestructor(void *interp, void *val)
Jim_Free(val);
}
+static unsigned int JimObjectHTHashFunction(const void *key)
+{
+ int len;
+ const char *str = Jim_GetString((Jim_Obj *)key, &len);
+ return Jim_GenHashFunction((const unsigned char *)str, len);
+}
+
+static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+ return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
+}
+
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
+{
+ Jim_IncrRefCount((Jim_Obj *)val);
+ return (void *)val;
+}
+
+static void JimObjectHTKeyValDestructor(void *interp, void *val)
+{
+ Jim_DecrRefCount(interp, (Jim_Obj *)val);
+}
+
+
static const Jim_HashTableType JimVariablesHashTableType = {
- JimStringCopyHTHashFunction, /* hash function */
- JimStringCopyHTDup, /* key dup */
+ JimObjectHTHashFunction, /* hash function */
+ JimObjectHTKeyValDup, /* key dup */
NULL, /* val dup */
- JimStringCopyHTKeyCompare, /* key compare */
- JimStringCopyHTKeyDestructor, /* key destructor */
+ JimObjectHTKeyCompare, /* key compare */
+ JimObjectHTKeyValDestructor, /* key destructor */
JimVariablesHTValDestructor /* val destructor */
};
@@ -3939,16 +3974,12 @@ static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Ob
else {
initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
}
- if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
- return JIM_ERR;
- }
varPtr = Jim_Alloc(sizeof(*varPtr));
varPtr->objPtr = initObjPtr;
Jim_IncrRefCount(initObjPtr);
varPtr->linkFramePtr = NULL;
- if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars,
- Jim_String(nameObjPtr), varPtr) != JIM_OK) {
+ if (JimSetNewVariable(cmdPtr->u.proc.staticVars, nameObjPtr, varPtr) != JIM_OK) {
Jim_SetResultFormatted(interp,
"static variable name \"%#s\" duplicated in statics list", nameObjPtr);
Jim_DecrRefCount(interp, initObjPtr);
@@ -4270,12 +4301,12 @@ static const Jim_ObjType variableObjType = {
/**
* Check that the name does not contain embedded nulls.
*
- * Variable and procedure names are manipulated as null terminated strings, so
+ * procedure names are manipulated 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 */
+ /* command names can't contain embedded nulls */
if (nameObjPtr->typePtr != &variableObjType) {
int len;
const char *str = Jim_GetString(nameObjPtr, &len);
@@ -4296,9 +4327,9 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
{
const char *varName;
Jim_CallFrame *framePtr;
- Jim_HashEntry *he;
int global;
int len;
+ Jim_Var *var;
/* Check if the object is already an uptodate variable */
if (objPtr->typePtr == &variableObjType) {
@@ -4312,10 +4343,6 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
else if (objPtr->typePtr == &dictSubstObjType) {
return JIM_DICT_SUGAR;
}
- else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
- return JIM_ERR;
- }
-
varName = Jim_GetString(objPtr, &len);
@@ -4325,33 +4352,37 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
}
if (varName[0] == ':' && varName[1] == ':') {
- while (*++varName == ':') {
+ while (*varName == ':') {
+ varName++;
+ len--;
}
global = 1;
framePtr = interp->topFramePtr;
+ /* XXX should use length */
+ Jim_Obj *tempObj = Jim_NewStringObj(interp, varName, len);
+ var = JimFindVariable(&framePtr->vars, tempObj);
+ Jim_FreeNewObj(interp, tempObj);
}
else {
global = 0;
framePtr = interp->framePtr;
- }
-
- /* Resolve this name in the variables hash table */
- he = Jim_FindHashEntry(&framePtr->vars, varName);
- if (he == NULL) {
- if (!global && framePtr->staticVars) {
+ /* Resolve this name in the variables hash table */
+ var = JimFindVariable(&framePtr->vars, objPtr);
+ if (var == NULL && framePtr->staticVars) {
/* Try with static vars. */
- he = Jim_FindHashEntry(framePtr->staticVars, varName);
- }
- if (he == NULL) {
- return JIM_ERR;
+ var = JimFindVariable(framePtr->staticVars, objPtr);
}
}
+ if (var == NULL) {
+ 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;
- objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
+ objPtr->internalRep.varValue.varPtr = var;
objPtr->internalRep.varValue.global = global;
return JIM_OK;
}
@@ -4360,11 +4391,31 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
+static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_Var *var)
+{
+ return Jim_AddHashEntry(ht, nameObjPtr, var);
+}
+
+static Jim_Var *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr)
+{
+ Jim_HashEntry *he = Jim_FindHashEntry(ht, nameObjPtr);
+ if (he) {
+ return (Jim_Var *)Jim_GetHashEntryVal(he);
+ }
+ return NULL;
+}
+
+static int JimUnsetVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr)
+{
+ return Jim_DeleteHashEntry(ht, nameObjPtr);
+}
+
static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
{
const char *name;
Jim_CallFrame *framePtr;
int global;
+ int len;
/* New variable to create */
Jim_Var *var = Jim_Alloc(sizeof(*var));
@@ -4373,21 +4424,22 @@ static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_O
Jim_IncrRefCount(valObjPtr);
var->linkFramePtr = NULL;
- name = Jim_String(nameObjPtr);
+ name = Jim_GetString(nameObjPtr, &len);
if (name[0] == ':' && name[1] == ':') {
- while (*++name == ':') {
+ while (*name == ':') {
+ name++;
+ len--;
}
framePtr = interp->topFramePtr;
global = 1;
+ JimSetNewVariable(&framePtr->vars, Jim_NewStringObj(interp, name, len), var);
}
else {
framePtr = interp->framePtr;
global = 0;
+ JimSetNewVariable(&framePtr->vars, nameObjPtr, var);
}
- /* Insert the new variable */
- Jim_AddHashEntry(&framePtr->vars, name, var);
-
/* Make the object int rep a variable */
Jim_FreeIntRep(interp, nameObjPtr);
nameObjPtr->typePtr = &variableObjType;
@@ -4417,9 +4469,6 @@ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
case JIM_ERR:
- if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) {
- return JIM_ERR;
- }
JimCreateVariable(interp, nameObjPtr, valObjPtr);
break;
@@ -4487,6 +4536,8 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
const char *targetName;
Jim_CallFrame *framePtr;
Jim_Var *varPtr;
+ int len;
+ int varnamelen;
/* Check for an existing variable or link */
switch (SetVariableFromAny(interp, nameObjPtr)) {
@@ -4510,10 +4561,12 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
/* Resolve the call frames for both variables */
/* XXX: SetVariableFromAny() already did this! */
- varName = Jim_String(nameObjPtr);
+ varName = Jim_GetString(nameObjPtr, &varnamelen);
if (varName[0] == ':' && varName[1] == ':') {
- while (*++varName == ':') {
+ while (*varName == ':') {
+ varName++;
+ varnamelen--;
}
/* Linking a global var does nothing */
framePtr = interp->topFramePtr;
@@ -4522,11 +4575,13 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
framePtr = interp->framePtr;
}
- targetName = Jim_String(targetNameObjPtr);
+ targetName = Jim_GetString(targetNameObjPtr, &len);
if (targetName[0] == ':' && targetName[1] == ':') {
- while (*++targetName == ':') {
+ while (*targetName == ':') {
+ targetName++;
+ len--;
}
- targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1);
+ targetNameObjPtr = Jim_NewStringObj(interp, targetName, len);
targetCallFrame = interp->topFramePtr;
}
Jim_IncrRefCount(targetNameObjPtr);
@@ -4545,7 +4600,7 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
/* Cycles are only possible with 'uplevel 0' */
while (1) {
- if (strcmp(Jim_String(objPtr), varName) == 0) {
+ if (Jim_Length(objPtr) == varnamelen && memcmp(Jim_String(objPtr), varName, varnamelen) == 0) {
Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
Jim_DecrRefCount(interp, targetNameObjPtr);
return JIM_ERR;
@@ -4676,16 +4731,23 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
interp->framePtr = framePtr;
}
else {
- const char *name = Jim_String(nameObjPtr);
if (nameObjPtr->internalRep.varValue.global) {
- name += 2;
+ int len;
+ const char *name = Jim_GetString(nameObjPtr, &len);
+ while (*name == ':') {
+ name++;
+ len--;
+ }
framePtr = interp->topFramePtr;
+ Jim_Obj *tempObj = Jim_NewStringObj(interp, name, len);
+ retval = JimUnsetVariable(&framePtr->vars, tempObj);
+ Jim_FreeNewObj(interp, tempObj);
}
else {
framePtr = interp->framePtr;
+ retval = JimUnsetVariable(&framePtr->vars, nameObjPtr);
}
- retval = Jim_DeleteHashEntry(&framePtr->vars, name);
if (retval == JIM_OK) {
/* Change the callframe id, invalidating var lookup caching */
framePtr->id = interp->callFrameEpoch++;
@@ -4970,11 +5032,10 @@ static int JimInvokeDefer(Jim_Interp *interp, int retcode)
Jim_Obj *objPtr;
/* Fast check for the likely case that the variable doesn't exist */
- if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) {
+ if (JimFindVariable(&interp->framePtr->vars, interp->defer) == NULL) {
return retcode;
}
-
- objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE);
+ objPtr = Jim_GetVariable(interp, interp->defer, JIM_NONE);
if (objPtr) {
int ret = JIM_OK;
@@ -5029,24 +5090,7 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
Jim_FreeHashTable(&cf->vars);
else {
- int i;
- Jim_HashEntry **table = cf->vars.table, *he;
-
- for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
- he = table[i];
- while (he != NULL) {
- Jim_HashEntry *nextEntry = he->next;
- Jim_Var *varPtr = Jim_GetHashEntryVal(he);
-
- Jim_DecrRefCount(interp, varPtr->objPtr);
- Jim_Free(Jim_GetHashEntryKey(he));
- Jim_Free(varPtr);
- Jim_Free(he);
- table[i] = NULL;
- he = nextEntry;
- }
- }
- cf->vars.used = 0;
+ Jim_ClearHashTable(&cf->vars);
}
cf->next = interp->freeFramesList;
interp->freeFramesList = cf;
@@ -5496,6 +5540,7 @@ Jim_Interp *Jim_CreateInterp(void)
i->result = i->emptyObj;
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
+ i->defer = Jim_NewStringObj(i, "jim::defer", -1);
i->errorProc = i->emptyObj;
i->currentScriptObj = Jim_NewEmptyStringObj(i);
i->nullScriptObj = Jim_NewEmptyStringObj(i);
@@ -5504,6 +5549,7 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
+ Jim_IncrRefCount(i->defer);
Jim_IncrRefCount(i->currentScriptObj);
Jim_IncrRefCount(i->nullScriptObj);
Jim_IncrRefCount(i->errorProc);
@@ -5547,6 +5593,7 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->stackTrace);
Jim_DecrRefCount(i, i->errorProc);
Jim_DecrRefCount(i, i->unknown);
+ Jim_DecrRefCount(i, i->defer);
Jim_DecrRefCount(i, i->errorFileNameObj);
Jim_DecrRefCount(i, i->currentScriptObj);
Jim_DecrRefCount(i, i->nullScriptObj);
@@ -7041,29 +7088,6 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
*
* Keys and Values are Jim objects. */
-static unsigned int JimObjectHTHashFunction(const void *key)
-{
- int len;
- const char *str = Jim_GetString((Jim_Obj *)key, &len);
- return Jim_GenHashFunction((const unsigned char *)str, len);
-}
-
-static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
-{
- return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
-}
-
-static void *JimObjectHTKeyValDup(void *privdata, const void *val)
-{
- Jim_IncrRefCount((Jim_Obj *)val);
- return (void *)val;
-}
-
-static void JimObjectHTKeyValDestructor(void *interp, void *val)
-{
- Jim_DecrRefCount(interp, (Jim_Obj *)val);
-}
-
static const Jim_HashTableType JimDictHashTableType = {
JimObjectHTHashFunction, /* hash function */
JimObjectHTKeyValDup, /* key dup */
@@ -11161,10 +11185,14 @@ typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listO
#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
+#define JIM_HT_MATCH_OBJKEYS 0x8000
+
/**
- * For each key of the hash table 'ht' (with string keys) which matches the glob pattern (all if NULL),
- * invoke the callback to add entries to a list.
+ * For each key of the hash table 'ht' (with string or object keys) that
+ * matches the glob pattern (all if NULL), invoke the callback to add entries to a list.
* Returns the list.
+ *
+ * 'type' must contain JIM_HT_MATCH_OBJKEYS if the hash table keys are objects rather than strings.
*/
static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
JimHashtableIteratorCallbackType *callback, int type)
@@ -11183,7 +11211,16 @@ static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht,
Jim_HashTableIterator htiter;
JimInitHashTableIterator(ht, &htiter);
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
- if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
+ int nomatch = 0;
+ if (patternObjPtr) {
+ if (type & JIM_HT_MATCH_OBJKEYS) {
+ nomatch = !Jim_StringMatchObj(interp, patternObjPtr, he->key, 0);
+ }
+ else {
+ nomatch = !JimGlobMatch(Jim_String(patternObjPtr), he->key, 0);
+ }
+ }
+ if (!nomatch) {
callback(interp, listObjPtr, he, type);
}
}
@@ -11229,6 +11266,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int
#define JIM_VARLIST_GLOBALS 0
#define JIM_VARLIST_LOCALS 1
#define JIM_VARLIST_VARS 2
+#define JIM_VARLIST_MASK 0x000f
#define JIM_VARLIST_VALUES 0x1000
@@ -11240,8 +11278,8 @@ static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
{
Jim_Var *varPtr = Jim_GetHashEntryVal(he);
- if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
- Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
+ if ((type & JIM_VARLIST_MASK) != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
+ Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
if (type & JIM_VARLIST_VALUES) {
Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
}
@@ -11252,13 +11290,14 @@ static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode)
{
if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) {
- /* For [info locals], if we are at top level an emtpy list
+ /* For [info locals], if we are at top level an empty list
* is returned. I don't agree, but we aim at compatibility (SS) */
return interp->emptyObj;
}
else {
Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
- return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode);
+ return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch,
+ mode | JIM_HT_MATCH_OBJKEYS);
}
}
@@ -14071,7 +14110,7 @@ int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj,
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
if (patternObj) {
Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he);
- if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) {
+ if (!Jim_StringMatchObj(interp, patternObj, matchObj, 0)) {
/* no match */
continue;
}
@@ -14421,6 +14460,12 @@ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_OK;
}
+static int JimIsGlobalNamespace(Jim_Obj *objPtr)
+{
+ const char *str = Jim_String(objPtr);
+ return str[0] == ':' && str[1] == ':';
+}
+
/* [info] */
static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -14506,7 +14551,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
#ifdef jim_ext_namespace
if (!nons) {
- if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+ if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) {
return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
}
}
@@ -14528,7 +14573,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
#ifdef jim_ext_namespace
if (!nons) {
- if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+ if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) {
return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
}
}
diff --git a/jim.h b/jim.h
index 807ad9b..d880c45 100644
--- a/jim.h
+++ b/jim.h
@@ -544,6 +544,7 @@ typedef struct Jim_Interp {
Jim_Obj *stackTrace; /* Stack trace object. */
Jim_Obj *errorProc; /* Name of last procedure which returned an error */
Jim_Obj *unknown; /* Unknown command cache */
+ Jim_Obj *defer; /* "jim::defer" */
int unknown_called; /* The unknown command has been invoked */
int errorFlag; /* Set if an error occurred during execution. */
void *cmdPrivData; /* Used to pass the private data pointer to
diff --git a/tests/alias.test b/tests/alias.test
index 866aa1b..64855dd 100644
--- a/tests/alias.test
+++ b/tests/alias.test
@@ -145,12 +145,12 @@ test statics-1.1 "missing static variable init" {
}
} 1
-test statics-1.2 "static variable with invalid name" {
- catch {
- proc a {b} "{c\0d 4}" {
- }
+test statics-1.2 "static variable with name containing null" {
+ proc a {b} "{c\0d 4}" {
+ return [set c\0d]
}
-} 1
+ a 5
+} 4
test statics-1.3 "duplicate static variable" {
catch {
diff --git a/tests/coverage.test b/tests/coverage.test
index 95d6969..0ef3ef3 100644
--- a/tests/coverage.test
+++ b/tests/coverage.test
@@ -213,13 +213,14 @@ test package-1 {package names} jim {
expr {"stdlib" in [package names]}
} {1}
-test variable-1 {upvar to invalid name} -constraints jim -body {
+test variable-1 {upvar, name with embedded null} -constraints jim -body {
proc a {} {
upvar var\0null abc
incr abc
}
+ set var\0null 2
a
-} -returnCodes error -result {variable name contains embedded null}
+} -returnCodes ok -result {3}
test variable-2 {upvar to global name} {
set ::globalvar 1
diff --git a/tests/dict2.test b/tests/dict2.test
index f4d147a..ddb545c 100644
--- a/tests/dict2.test
+++ b/tests/dict2.test
@@ -1272,9 +1272,8 @@ test dict-23.4 {dict with usage} -body {
} -returnCodes error -result {wrong # args: should be "dict with dictVar ?key ...? script"}
test dict-23.5 {dict with badvar} -constraints jim -body {
- # set up a variable that will fail Jim_SetVariable()
- dict with dictnulls {}
-} -returnCodes error -result {variable name contains embedded null}
+ dict with dictnulls {lsort [info locals]}
+} -returnCodes ok -result [list \0ghi kl\0m ab\0c de\0f]
test dict-23.6 {dict with baddict} -body {
dict with dictbad {}
diff --git a/tests/misc.test b/tests/misc.test
index cda7f57..d99de4a 100644
--- a/tests/misc.test
+++ b/tests/misc.test
@@ -527,15 +527,15 @@ test jimobj-1.4 "incr dict sugar" {
list $a(3) $a
} {4 {3 4}}
-test jim-badvar-1.1 "invalid variable name" {
+test jim-badvar-1.1 "variable name with embedded null" {
set x b\0c
- catch {set $x 5}
-} 1
+ set $x 5
+} 5
-test jim-badvar-1.2 "incr invalid variable name" {
+test jim-badvar-1.2 "incr variable name with embedded null" {
set x b\0c
- catch {incr $x}
-} 1
+ incr $x
+} 6
test lset-1.1 "lset with bad var" {
catch {lset badvar 1 x}
diff --git a/tests/pack.test b/tests/pack.test
index 0ce16cd..d059087 100644
--- a/tests/pack.test
+++ b/tests/pack.test
@@ -66,7 +66,7 @@ test pack-2.7 {pack bad set} -body {
test pack-2.8 {pack bad set} -body {
pack bad\x00var 32 -intle 8
-} -returnCodes error -result {variable name contains embedded null}
+} -returnCodes ok -result {8}
test unpack-1.1 {unpack usage} -body {
unpack