diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2010-06-05 16:24:26 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2010-06-05 16:24:26 (GMT) |
commit | 84f4fa52310247fb505be4eed77e19e48be226a0 (patch) | |
tree | 39d30bfda5d5c3bd2964a7ab8139326bf6e4fc74 /generic/tclBasic.c | |
parent | 5c5e3f51ea23ae06e71dd6b272376ed8a833aa84 (diff) | |
download | tcl-84f4fa52310247fb505be4eed77e19e48be226a0.zip tcl-84f4fa52310247fb505be4eed77e19e48be226a0.tar.gz tcl-84f4fa52310247fb505be4eed77e19e48be226a0.tar.bz2 |
* generic/tclBasic.c: Fix for #3008307: make callerPtr chains
* generic/tclExecute.c: be traversable accross coro
boundaries. Add the special coroutine CallFrame (partially
reverting commit of 2009-12-10), as it is needed for coroutines
that do not push a CF - eg, those with [eval] as command. Thanks
to Colin McCormack (coldstore) and Alexandre Ferrieux for the
hard work on this.
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r-- | generic/tclBasic.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index a7dce89..6f695af 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -16,7 +16,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclBasic.c,v 1.456 2010/05/03 14:36:41 nijtmans Exp $ + * RCS: @(#) $Id: tclBasic.c,v 1.457 2010/06/05 16:24:26 msofer Exp $ */ #include "tclInt.h" @@ -8710,6 +8710,7 @@ NRCoroutineExitCallback( TclCleanupCommandMacro(cmdPtr); corPtr->eePtr->corPtr = NULL; + TclPopStackFrame(interp); TclDeleteExecEnv(corPtr->eePtr); corPtr->eePtr = NULL; @@ -8790,6 +8791,7 @@ NRInterpCoroutine( */ SAVE_CONTEXT(corPtr->caller); + corPtr->base.framePtr->callerPtr = iPtr->framePtr; RESTORE_CONTEXT(corPtr->running); corPtr->auxNumLevels = iPtr->numLevels; iPtr->numLevels += nestNumLevels; @@ -8819,6 +8821,8 @@ TclNRCoroutineObjCmd( const char *procName; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; Tcl_DString ds; + Tcl_CallFrame *framePtr; + if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name cmd ?arg ...?"); @@ -8922,11 +8926,31 @@ TclNRCoroutineObjCmd( } /* + * Create the coro's execEnv and switch to it so that any CallFrames or + * callbacks refer to the new execEnv's stack. + */ + + corPtr->eePtr = TclCreateExecEnv(interp, CORO_STACK_INITIAL_SIZE); + corPtr->callerEEPtr = iPtr->execEnvPtr; + corPtr->eePtr->corPtr = corPtr; + iPtr->execEnvPtr = corPtr->eePtr; + + /* push a base call frame; save the current namespace to do a correct + * command lookup. + */ + + nsPtr = iPtr->varFramePtr->nsPtr; + TclPushStackFrame(interp, &framePtr, + (Tcl_Namespace *) iPtr->globalNsPtr, 0); + iPtr->varFramePtr = iPtr->rootFramePtr; + + /* * Save the base context. The base cmdFramePtr is unknown at this time: it * will be allocated in the Tcl stack. So signal TEBC that it has to * initialize the base cmdFramePtr by setting it to NULL. */ + SAVE_CONTEXT(corPtr->base); corPtr->base.cmdFramePtr = NULL; corPtr->running = NULL_CONTEXT; corPtr->stackLevel = NULL; @@ -8944,20 +8968,13 @@ TclNRCoroutineObjCmd( cmdObjPtr->typePtr = NULL; /* - * Create the coro's execEnv and switch to it so that any CallFrames or - * callbacks refer to the new execEnv's stack. Add the exit callback, then - * the callback to eval the coro body. + * Add the exit callback, then the callback to eval the coro body */ - corPtr->eePtr = TclCreateExecEnv(interp, CORO_STACK_INITIAL_SIZE); - corPtr->callerEEPtr = iPtr->execEnvPtr; - corPtr->eePtr->corPtr = corPtr; - iPtr->execEnvPtr = corPtr->eePtr; - TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr, NULL, NULL, NULL); iPtr->evalFlags |= TCL_EVAL_REDIRECT; - iPtr->lookupNsPtr = iPtr->varFramePtr->nsPtr; + iPtr->lookupNsPtr = nsPtr; TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0); return TCL_OK; |