From 2f4c482ac0cec564faea01f71d44f481d96f9e9e Mon Sep 17 00:00:00 2001 From: dgp Date: Sun, 3 Jul 2016 14:09:45 +0000 Subject: Use conventional list operations for ensemble dispatch. --- generic/tclEnsemble.c | 57 +++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index a86b5c4..17ab35b 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -41,6 +41,9 @@ static int CompileBasicNArgCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr); +static Tcl_NRPostProc FreeObj; +static Tcl_NRPostProc FreeER; + /* * The lists of subcommands and options for the [namespace ensemble] command. */ @@ -1843,45 +1846,31 @@ NsEnsembleImplementationCmdNR( */ { - Tcl_Obj **prefixObjv; /* The list of objects to substitute in as the - * target command prefix. */ Tcl_Obj *copyPtr; /* The actual list of words to dispatch to. * Will be freed by the dispatch engine. */ - int prefixObjc, copyObjc; + int prefixObjc; + + Tcl_ListObjLength(NULL, prefixObj, &prefixObjc); + if (0 && objc == 2) { /* - * Get the prefix that we're rewriting to. To do this we need to - * ensure that the internal representation of the list does not change - * so that we can safely keep the internal representations of the - * elements in the list. - * - * TODO: Use conventional list operations to make this code sane! + * TODO: This branch is disabled because it botches or exposes + * something wrong with nested ensemble usage messages. See + * tests oo-16.1 and oo-17.1 */ - - TclListObjGetElements(NULL, prefixObj, &prefixObjc, &prefixObjv); - - copyObjc = objc - 2 + prefixObjc; - copyPtr = Tcl_NewListObj(copyObjc, NULL); - if (copyObjc > 0) { - register Tcl_Obj **copyObjv; - /* Space used to construct the list of - * arguments to pass to the command that - * implements the ensemble subcommand. */ - register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1; - register int i; - - listRepPtr->elemCount = copyObjc; - copyObjv = &listRepPtr->elements; - memcpy(copyObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc); - memcpy(copyObjv+prefixObjc, objv+1, - sizeof(Tcl_Obj *) * ensemblePtr->numParameters); - memcpy(copyObjv+prefixObjc+ensemblePtr->numParameters, - objv+ensemblePtr->numParameters+2, - sizeof(Tcl_Obj *) * (objc-ensemblePtr->numParameters-2)); - - for (i=0; i < copyObjc; i++) { - Tcl_IncrRefCount(copyObjv[i]); - } + copyPtr = prefixObj; + Tcl_IncrRefCount(copyPtr); + TclNRAddCallback(interp, FreeObj, copyPtr, NULL, NULL, NULL); + } else { + int copyObjc = objc - 2 + prefixObjc; + + copyPtr = Tcl_NewListObj(copyObjc, NULL); + Tcl_ListObjAppendList(NULL, copyPtr, prefixObj); + Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0, + ensemblePtr->numParameters, objv+1); + Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0, + objc - 2 - ensemblePtr->numParameters, + objv + 2 + ensemblePtr->numParameters); } TclDecrRefCount(prefixObj); -- cgit v0.12