diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2008-05-21 13:26:14 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2008-05-21 13:26:14 (GMT) |
commit | 422670d42865358d830bc1a65fc7aa48904a2d71 (patch) | |
tree | 4fd121267a29b8a26506b15326ed9b38bb167344 /generic | |
parent | e47e090ebc6534d30664a39311da929831681b02 (diff) | |
download | tcl-422670d42865358d830bc1a65fc7aa48904a2d71.zip tcl-422670d42865358d830bc1a65fc7aa48904a2d71.tar.gz tcl-422670d42865358d830bc1a65fc7aa48904a2d71.tar.bz2 |
Backport of fixes to Tcl_SetNamespaceUnknownHandler
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclNamesp.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index f7fa9c1..c51ea08 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -23,7 +23,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.162 2008/03/02 18:46:39 msofer Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.162.2.1 2008/05/21 13:26:16 dkf Exp $ */ #include "tclInt.h" @@ -4296,45 +4296,58 @@ Tcl_SetNamespaceUnknownHandler( Tcl_Namespace *nsPtr, /* Namespace which is being updated. */ Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */ { - int lstlen; + int lstlen = 0; Namespace *currNsPtr = (Namespace *)nsPtr; - if (currNsPtr->unknownHandlerPtr != NULL) { - /* - * Remove old handler first. - */ + /* + * Ensure that we check for errors *first* before we change anything. + */ - Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr); - currNsPtr->unknownHandlerPtr = NULL; + if (handlerPtr != NULL) { + if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { + /* + * Not a list. + */ + + return TCL_ERROR; + } + if (lstlen > 0) { + /* + * We are going to be saving this handler. Increment the reference + * count before decrementing the refcount on the previous handler, + * so that nothing strange can happen if we are told to set the + * handler to the previous value. + */ + + Tcl_IncrRefCount(handlerPtr); + } } /* - * If NULL or an empty list is passed, then reset to the default - * handler. + * Remove old handler next. */ - if (handlerPtr == NULL) { - currNsPtr->unknownHandlerPtr = NULL; - } else if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { - /* - * Not a list. - */ + if (currNsPtr->unknownHandlerPtr != NULL) { + Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr); + } - return TCL_ERROR; - } else if (lstlen == 0) { + /* + * Install the new handler. + */ + + if (lstlen > 0) { /* - * Empty list - reset to default. + * Just store the handler. It already has the correct reference count. */ - currNsPtr->unknownHandlerPtr = NULL; + currNsPtr->unknownHandlerPtr = handlerPtr; } else { /* - * Increment ref count and store. The reference count is decremented - * either in the code above, or when the namespace is deleted. + * If NULL or an empty list is passed, this resets to the default + * handler. */ - Tcl_IncrRefCount(handlerPtr); - currNsPtr->unknownHandlerPtr = handlerPtr; + currNsPtr->unknownHandlerPtr = NULL; } return TCL_OK; } |