Index: generic/xotcl.c =================================================================== diff -u -r4cc0fdfb65a5ef8d28eb623084910447849edd7f -r5ab730ebd0e769e5f376cc2db8aa22b024a9c498 --- generic/xotcl.c (.../xotcl.c) (revision 4cc0fdfb65a5ef8d28eb623084910447849edd7f) +++ generic/xotcl.c (.../xotcl.c) (revision 5ab730ebd0e769e5f376cc2db8aa22b024a9c498) @@ -765,9 +765,9 @@ /* search for tail of name */ -static char * -NSTail(char *string) { - register char *p = string+strlen(string); +static CONST char * +NSTail(CONST char *string) { + register char *p = (char *)string+strlen(string); while (p > string) { if (*p == ':' && *(p-1) == ':') return p+1; p--; @@ -1700,7 +1700,7 @@ Tcl_Obj *key; Tcl_CallFrame *varFramePtr; Var *newVar; - + /* Case 1: The variable is to be resolved in global scope, proceed in * resolver chain (i.e. return TCL_CONTINUE) * @@ -1740,36 +1740,32 @@ varFramePtr->nsPtr->fullName); return TCL_CONTINUE; } + + /* + * Check for absolutely/relatively qualified variable names, i.e. + * make sure that the variable name does not contain any namespace qualifiers. + * Proceed with a TCL_CONTINUE, otherwise. + */ + if ((*name == ':' && *(name+1) == ':') || NSTail(name) != name) { + return TCL_CONTINUE; + } + /* Case 3: Does the variable exist in the per-object namespace? */ *varPtr = (Tcl_Var)LookupVarFromTable(Tcl_Namespace_varTable(ns),name,NULL); - /* - fprintf(stderr, "var with name '%s' to be created, flags=%.8X, ns=%p is create %d\n", name,flags,ns, - RUNTIME_STATE(interp)->createVarHack); - */ - - if(*varPtr == NULL - /* - && (RUNTIME_STATE(interp)->createVarHack || flags & TCL_NAMESPACE_ONLY) + if(*varPtr == NULL) { + /* We failed to find the variable so far, therefore we create it + * here in the namespace. Note that the cases (1), (2) and (3) + * TCL_CONTINUE care for variable creation if necessary. */ - ) { - /* We failed to find the variable in the namespace, so we create - * it here in the namespace. Note that the cases (1) and (2) TCL_CONTINUE care - * for creation if necessary. - * - * Note: Essentially, this statement block resembles what - * happens in TclLookupSimpleVar() etc., but uses XOTcl-specific - * helpers. We acquire a Tcl_Var eagerly, the - * variable is later cleared if not defined effectively - * SURE? - * (read TclIsVarUndefined == 1). Eagerness is required to support - * variable traces etc. - * - */ - key = Tcl_NewStringObj(name, -1); /* TODO: check reference counting */ + key = Tcl_NewStringObj(name, -1); + + INCR_REF_COUNT(key); newVar = VarHashCreateVar(Tcl_Namespace_varTable(ns), key, &new); + DECR_REF_COUNT(key); + #if defined(PRE85) newVar->nsPtr = (Namespace *)ns; #endif @@ -2141,7 +2137,7 @@ } void -XOTclAddPMethod(Tcl_Interp *interp, XOTcl_Object *obji, char *nm, Tcl_ObjCmdProc *proc, +XOTclAddPMethod(Tcl_Interp *interp, XOTcl_Object *obji, CONST char *nm, Tcl_ObjCmdProc *proc, ClientData cd, Tcl_CmdDeleteProc *dp) { XOTclObject *obj = (XOTclObject*) obji; Tcl_DString newCmd, *cptr = &newCmd; @@ -2152,7 +2148,7 @@ } void -XOTclAddIMethod(Tcl_Interp *interp, XOTcl_Class *cli, char *nm, +XOTclAddIMethod(Tcl_Interp *interp, XOTcl_Class *cli, CONST char *nm, Tcl_ObjCmdProc *proc, ClientData cd, Tcl_CmdDeleteProc *dp) { XOTclClass *cl = (XOTclClass*) cli; Tcl_DString newCmd, *cptr = &newCmd; @@ -7265,7 +7261,7 @@ */ static int -unsetInAllNamespaces(Tcl_Interp *interp, Namespace *nsPtr, char *name) { +unsetInAllNamespaces(Tcl_Interp *interp, Namespace *nsPtr, CONST char *name) { int rc = 0; fprintf(stderr, "### unsetInAllNamespaces variable '%s', current namespace '%s'\n", name, nsPtr ? nsPtr->fullName : "NULL"); @@ -8146,8 +8142,8 @@ cxtNsPtr = Tcl_GetCurrentNamespace(interp); } - TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr, - flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName); + TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,flags, + &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName); /*fprintf(stderr, " ***Found %s, %s\n", nsPtr[0]->fullName, nsPtr[0]->fullName);*/ @@ -8433,7 +8429,7 @@ if (objc != 2) return XOTclObjErrArgCnt(interp, obj->cmdName, "exists var"); Tcl_SetIntObj(Tcl_GetObjResult(interp), - varExists(interp, obj, ObjStr(objv[1]), NULL, 0, 1)); + varExists(interp, obj, ObjStr(objv[1]), NULL, 1, 1)); return TCL_OK; } @@ -9423,7 +9419,6 @@ } if (tcd->objscope) { XOTcl_PushFrame(interp, tcd->obj); - RUNTIME_STATE(interp)->createVarHack = 1; } if (tcd->objProc) { result = (tcd->objProc)(tcd->cd, interp, objc, objv); @@ -9438,7 +9433,6 @@ if (tcd->objscope) { XOTcl_PopFrame(interp, tcd->obj); - RUNTIME_STATE(interp)->createVarHack = 0; } return result; } @@ -11603,8 +11597,8 @@ XOTclObject *obj = (XOTclObject*) cd; Tcl_Obj *o = obj->cmdName; int result = TCL_ERROR; - char *fullName = ObjStr(o); - char *vn; + CONST char *fullName = ObjStr(o); + CONST char *vn; callFrameContext ctx = {0}; if (objc != 1) Index: generic/xotcl.decls =================================================================== diff -u -rf4b1378f3136bc998645f230af38847bcf76d96b -r5ab730ebd0e769e5f376cc2db8aa22b024a9c498 --- generic/xotcl.decls (.../xotcl.decls) (revision f4b1378f3136bc998645f230af38847bcf76d96b) +++ generic/xotcl.decls (.../xotcl.decls) (revision 5ab730ebd0e769e5f376cc2db8aa22b024a9c498) @@ -57,12 +57,12 @@ } declare 11 generic { void XOTclAddPMethod(Tcl_Interp* in, struct XOTcl_Object* obj, - char* nm, Tcl_ObjCmdProc* proc, + CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp) } declare 12 generic { void XOTclAddIMethod(Tcl_Interp* in, struct XOTcl_Class* cl, - char* nm, Tcl_ObjCmdProc* proc, + CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp) } declare 13 generic { Index: generic/xotclDecls.h =================================================================== diff -u -rbfeda566de60595825c75d78632d42458bb6cb05 -r5ab730ebd0e769e5f376cc2db8aa22b024a9c498 --- generic/xotclDecls.h (.../xotclDecls.h) (revision bfeda566de60595825c75d78632d42458bb6cb05) +++ generic/xotclDecls.h (.../xotclDecls.h) (revision 5ab730ebd0e769e5f376cc2db8aa22b024a9c498) @@ -53,12 +53,12 @@ struct XOTcl_Class* cl)); /* 11 */ EXTERN void XOTclAddPMethod _ANSI_ARGS_((Tcl_Interp* in, - struct XOTcl_Object* obj, char* nm, + struct XOTcl_Object* obj, CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 12 */ EXTERN void XOTclAddIMethod _ANSI_ARGS_((Tcl_Interp* in, - struct XOTcl_Class* cl, char* nm, + struct XOTcl_Class* cl, CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 13 */ @@ -167,8 +167,8 @@ int (*xOTclCreateClass) _ANSI_ARGS_((Tcl_Interp* in, Tcl_Obj* name, struct XOTcl_Class* cl)); /* 8 */ int (*xOTclDeleteObject) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Object* obj)); /* 9 */ int (*xOTclDeleteClass) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Class* cl)); /* 10 */ - void (*xOTclAddPMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Object* obj, char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 11 */ - void (*xOTclAddIMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Class* cl, char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 12 */ + void (*xOTclAddPMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Object* obj, CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 11 */ + void (*xOTclAddIMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Class* cl, CONST char* nm, Tcl_ObjCmdProc* proc, ClientData cd, Tcl_CmdDeleteProc* dp)); /* 12 */ void (*xOTclRemovePMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Object* obj, char* nm)); /* 13 */ void (*xOTclRemoveIMethod) _ANSI_ARGS_((Tcl_Interp* in, struct XOTcl_Class* cl, char* nm)); /* 14 */ Tcl_Obj* (*xOTclOSetInstVar) _ANSI_ARGS_((struct XOTcl_Object* obj, Tcl_Interp* in, Tcl_Obj* name, Tcl_Obj* value, int flgs)); /* 15 */ Index: generic/xotclInt.h =================================================================== diff -u -r4cc0fdfb65a5ef8d28eb623084910447849edd7f -r5ab730ebd0e769e5f376cc2db8aa22b024a9c498 --- generic/xotclInt.h (.../xotclInt.h) (revision 4cc0fdfb65a5ef8d28eb623084910447849edd7f) +++ generic/xotclInt.h (.../xotclInt.h) (revision 5ab730ebd0e769e5f376cc2db8aa22b024a9c498) @@ -472,7 +472,7 @@ Tcl_HashTable metaData; #endif ClientData clientData; - char *volatileVarName; + CONST char *volatileVarName; short checkoptions; } XOTclObjectOpt; @@ -644,7 +644,6 @@ int unknown; int doFilters; int doSoftrecreate; - int createVarHack; int exitHandlerDestroyRound; int returnCode; long newCounter; Index: tests/varresolutiontest.xotcl =================================================================== diff -u -r4cc0fdfb65a5ef8d28eb623084910447849edd7f -r5ab730ebd0e769e5f376cc2db8aa22b024a9c498 --- tests/varresolutiontest.xotcl (.../varresolutiontest.xotcl) (revision 4cc0fdfb65a5ef8d28eb623084910447849edd7f) +++ tests/varresolutiontest.xotcl (.../varresolutiontest.xotcl) (revision 5ab730ebd0e769e5f376cc2db8aa22b024a9c498) @@ -105,4 +105,30 @@ ? {o array exists a} 0 ? {namespace eval ::o array exists a} 0 +o destroy + +########################################### +# tests on namespace-qualified var names +########################################### + +Object o -requireNamespace +Object o::oo -requireNamespace + +? {::o set ::x 1} 1 +? {info exists ::x} [set ::x] +? {catch {unset ::x}} 0 1 + +? {::o set ::o::x 1} 1 +? {o exists x} [::o set ::o::x] +? {namespace eval ::o unset x} "" 1 +? {o exists x} 0 + +# Note, relatively qualified var names (not prefixed with ::*) +# are always resolved relative to the per-object namespace +? {catch {::o set o::x 1} msg} 1 +? {::o set oo::x 1} 1 +? {o::oo exists x} [::o set oo::x] +? {o unset oo::x} "" 1 +? {o::oo exists x} 0 + o destroy \ No newline at end of file