diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | generic/tclNamesp.c | 49 | ||||
-rw-r--r-- | generic/tclObj.c | 131 |
3 files changed, 73 insertions, 111 deletions
@@ -4,7 +4,9 @@ management. * generic/tclNamesp.c: tweaks to Tcl_GetCommandFromObj and - * generic/tclObj.c: TclGetNamespaceFromObj + * generic/tclObj.c: TclGetNamespaceFromObj; modified the + usage of structs ResolvedCmdName and ResolvedNsname so that the + field refNsPtr is NULL for fully qualified names. 2007-06-10 Miguel Sofer <msofer@users.sf.net> diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index e717977..f674a01 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -22,7 +22,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclNamesp.c,v 1.137 2007/06/11 21:32:19 msofer Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.138 2007/06/11 23:00:44 msofer Exp $ */ #include "tclInt.h" @@ -68,7 +68,8 @@ typedef struct ResolvedNsName { * a new one created at the same address). */ Namespace *refNsPtr; /* Points to the namespace containing the * reference (not the namespace that contains - * the referenced namespace). */ + * the referenced namespace). NULL if the name + * is fully qualified.*/ int refCount; /* Reference count: 1 for each nsName object * that has a pointer to this ResolvedNsName * structure as its internal rep. This @@ -2824,24 +2825,11 @@ TclGetNamespaceFromObj( * namespace. */ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */ { - Interp *iPtr = (Interp *) interp; ResolvedNsName *resPtr; - Namespace *nsPtr, *refNsPtr; + Namespace *nsPtr; int result = TCL_OK; - char *name; - int isFQ; /* - * If the namespace name is fully qualified, do as if the lookup were done - * from the global namespace; this helps avoid repeated lookups of fully - * qualified names. - */ - - name = TclGetString(objPtr); - isFQ = ((*name == ':') && (*(name+1) == ':')); - refNsPtr = (Namespace *) (isFQ? NULL :TclGetCurrentNamespace(interp)); - - /* * Get the internal representation, converting to a namespace type if * needed. The internal representation is a ResolvedNsName that points to * the actual namespace. @@ -2849,7 +2837,9 @@ TclGetNamespaceFromObj( * Check the context namespace of the resolved symbol to make sure that it * is fresh. Note that we verify that the namespace id of the context * namespace is the same as the one we cached; this insures that the - * namespace wasn't deleted and a new one created at the same address. + * namespace wasn't deleted and a new one created at the same + * address. Note that fully qualified names have a NULL refNsPtr, these + * checks needn't be made. * * If any check fails, then force another conversion to the command type, * to discard the old rep and create a new one. @@ -2858,18 +2848,12 @@ TclGetNamespaceFromObj( resPtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr; if ((objPtr->typePtr != &tclNsNameType) || (resPtr == NULL) - || (!isFQ && (resPtr->refNsPtr != refNsPtr)) + || (resPtr->refNsPtr && + (resPtr->refNsPtr != (Namespace *) TclGetCurrentNamespace(interp))) || (nsPtr = resPtr->nsPtr, nsPtr->flags & NS_DEAD) || (resPtr->nsId != nsPtr->nsId)) { - if (isFQ) { - refNsPtr = (Namespace *) TclGetCurrentNamespace(interp); - iPtr->varFramePtr->nsPtr = (Namespace *) TclGetGlobalNamespace(interp); - } result = tclNsNameType.setFromAnyProc(interp, objPtr); - if (isFQ) { - iPtr->varFramePtr->nsPtr = refNsPtr; - } resPtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr; if ((result == TCL_OK) && resPtr) { @@ -4886,10 +4870,7 @@ SetNsNameFromAny( * Get the string representation. Make it up-to-date if necessary. */ - name = objPtr->bytes; - if (name == NULL) { - name = TclGetString(objPtr); - } + name = TclGetString(objPtr); /* * Look for the namespace "name" in the current namespace. If there is an @@ -4907,14 +4888,16 @@ SetNsNameFromAny( */ if (nsPtr != NULL) { - Namespace *currNsPtr = (Namespace *) - TclGetCurrentNamespace(interp); - nsPtr->refCount++; resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName)); resNamePtr->nsPtr = nsPtr; resNamePtr->nsId = nsPtr->nsId; - resNamePtr->refNsPtr = currNsPtr; + if ((*name++ == ':') && (*name == ':')) { + resNamePtr->refNsPtr = NULL; + } else { + resNamePtr->refNsPtr = + (Namespace *) TclGetCurrentNamespace(interp); + } resNamePtr->refCount = 1; } else { resNamePtr = NULL; diff --git a/generic/tclObj.c b/generic/tclObj.c index e250614..8a43b38 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclObj.c,v 1.126 2007/06/11 21:32:19 msofer Exp $ + * RCS: @(#) $Id: tclObj.c,v 1.127 2007/06/11 23:00:44 msofer Exp $ */ #include "tclInt.h" @@ -299,7 +299,8 @@ typedef struct ResolvedCmdName { Command *cmdPtr; /* A cached Command pointer. */ Namespace *refNsPtr; /* Points to the namespace containing the * reference (not the namespace that contains - * the referenced command). */ + * the referenced command). NULL if the name + * is fully qualified.*/ long refNsId; /* refNsPtr's unique namespace id. Used to * verify that refNsPtr is still valid (e.g., * it's possible that the cmd's containing @@ -3460,26 +3461,10 @@ Tcl_GetCommandFromObj( * up first in the current namespace, then in * global namespace. */ { - Interp *iPtr = (Interp *) interp; register ResolvedCmdName *resPtr; register Command *cmdPtr; Namespace *refNsPtr; int result; - char *name; - int isFQ; - - /* - * If the variable name is fully qualified, do as if the lookup were done - * from the global namespace; this helps avoid repeated lookups of fully - * qualified names. It costs close to nothing, and may be very helpful for - * OO applications which pass along a command name ("this"), [Patch - * 456668] - */ - - name = TclGetString(objPtr); - isFQ = ((*name++ == ':') && (*name == ':')); - refNsPtr = (Namespace *) (isFQ? NULL :TclGetCurrentNamespace(interp)); - /* * Get the internal representation, converting to a command type if @@ -3490,7 +3475,8 @@ Tcl_GetCommandFromObj( * symbol to make sure that it is fresh. Note that we verify that the * namespace id of the context namespace is the same as the one we cached; * this insures that the namespace wasn't deleted and a new one created at - * the same address with the same command epoch. + * the same address with the same command epoch. Note that fully qualified + * names have a NULL refNsPtr, these checks needn't be made. * * Check also that the command's epoch is up to date, and that the command * is not deleted. @@ -3504,21 +3490,15 @@ Tcl_GetCommandFromObj( || (resPtr == NULL) || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch) || (cmdPtr->flags & CMD_IS_DELETED) - || ( !isFQ && - ((resPtr->refNsPtr != refNsPtr) + || ((resPtr->refNsPtr != NULL) && + (((refNsPtr = (Namespace *) TclGetCurrentNamespace(interp)) + != resPtr->refNsPtr) || (resPtr->refNsId != refNsPtr->nsId) || (resPtr->refNsCmdEpoch != refNsPtr->cmdRefEpoch))) ) { - if (isFQ) { - refNsPtr = (Namespace *) TclGetCurrentNamespace(interp); - iPtr->varFramePtr->nsPtr = (Namespace *) TclGetGlobalNamespace(interp); - } result = tclCmdNameType.setFromAnyProc(interp, objPtr); - if (isFQ) { - iPtr->varFramePtr->nsPtr = refNsPtr; - } - + resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1; if ((result == TCL_OK) && resPtr) { cmdPtr = resPtr->cmdPtr; @@ -3526,7 +3506,7 @@ Tcl_GetCommandFromObj( cmdPtr = NULL; } } - + return (Tcl_Command) cmdPtr; } @@ -3562,48 +3542,42 @@ TclSetCmdNameObj( Interp *iPtr = (Interp *) interp; register ResolvedCmdName *resPtr; register Namespace *currNsPtr; - CallFrame *savedFramePtr; char *name; if (objPtr->typePtr == &tclCmdNameType) { return; } - /* - * If the variable name is fully qualified, do as if the lookup were done - * from the global namespace; this helps avoid repeated lookups of fully - * qualified names. It costs close to nothing, and may be very helpful for - * OO applications which pass along a command name ("this"), [Patch - * 456668] (Copied over from Tcl_GetCommandFromObj) - */ - - savedFramePtr = iPtr->varFramePtr; - name = Tcl_GetString(objPtr); - if ((*name++ == ':') && (*name == ':')) { - iPtr->varFramePtr = iPtr->rootFramePtr; - } - - /* - * Get the current namespace. - */ - - currNsPtr = iPtr->varFramePtr->nsPtr; - cmdPtr->refCount++; resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName)); resPtr->cmdPtr = cmdPtr; - resPtr->refNsPtr = currNsPtr; - resPtr->refNsId = currNsPtr->nsId; - resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; resPtr->cmdEpoch = cmdPtr->cmdEpoch; resPtr->refCount = 1; + name = TclGetString(objPtr); + if ((*name++ == ':') && (*name == ':')) { + /* + * The name is fully qualified: set the referring namespace to + * NULL. + */ + + resPtr->refNsPtr = NULL; + } else { + /* + * Get the current namespace. + */ + + currNsPtr = iPtr->varFramePtr->nsPtr; + + resPtr->refNsPtr = currNsPtr; + resPtr->refNsId = currNsPtr->nsId; + resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; + } + TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; - - iPtr->varFramePtr = savedFramePtr; } /* @@ -3726,15 +3700,6 @@ SetCmdNameFromAny( register ResolvedCmdName *resPtr; /* - * Get "objPtr"s string representation. Make it up-to-date if necessary. - */ - - name = objPtr->bytes; - if (name == NULL) { - name = Tcl_GetString(objPtr); - } - - /* * Find the Command structure, if any, that describes the command called * "name". Build a ResolvedCmdName that holds a cached pointer to this * Command, and bump the reference count in the referenced Command @@ -3742,23 +3707,35 @@ SetCmdNameFromAny( * referenced from a CmdName object. */ + name = TclGetString(objPtr); cmd = Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0); + cmdPtr = (Command *) cmd; if (cmdPtr != NULL) { - /* - * Get the current namespace. - */ - - currNsPtr = iPtr->varFramePtr->nsPtr; - cmdPtr->refCount++; resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName)); - resPtr->cmdPtr = cmdPtr; - resPtr->refNsPtr = currNsPtr; - resPtr->refNsId = currNsPtr->nsId; - resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; - resPtr->cmdEpoch = cmdPtr->cmdEpoch; - resPtr->refCount = 1; + resPtr->cmdPtr = cmdPtr; + resPtr->cmdEpoch = cmdPtr->cmdEpoch; + resPtr->refCount = 1; + + if ((*name++ == ':') && (*name == ':')) { + /* + * The name is fully qualified: set the referring namespace to + * NULL. + */ + + resPtr->refNsPtr = NULL; + } else { + /* + * Get the current namespace. + */ + + currNsPtr = iPtr->varFramePtr->nsPtr; + + resPtr->refNsPtr = currNsPtr; + resPtr->refNsId = currNsPtr->nsId; + resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; + } } else { resPtr = NULL; /* no command named "name" was found */ } |