summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclCmdIL.c60
-rw-r--r--tests/coroutine.test3
2 files changed, 59 insertions, 4 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index fa4ead4..57434c1 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -104,6 +104,8 @@ typedef struct SortInfo {
* Forward declarations for procedures defined in this file:
*/
+static CmdFrame * CmdFrameChain(CoroutineData *corPtr);
+static void CmdFrameUnchain(CoroutineData *corPtr);
static int DictionaryCompare(const char *left, const char *right);
static int IfConditionCallback(ClientData data[],
Tcl_Interp *interp, int result);
@@ -1167,20 +1169,22 @@ InfoFrameCmd(
*/
CmdFrame *lastPtr = NULL;
+ CmdFrame *tailPtr = CmdFrameChain(corPtr);
+ int offset = tailPtr ? tailPtr->level : 0;
runPtr = iPtr->cmdFramePtr;
/* TODO - deal with overflow */
- topLevel += corPtr->caller.cmdFramePtr->level;
+ topLevel += offset;
while (runPtr) {
- runPtr->level += corPtr->caller.cmdFramePtr->level;
+ runPtr->level += offset;
lastPtr = runPtr;
runPtr = runPtr->nextPtr;
}
if (lastPtr) {
- lastPtr->nextPtr = corPtr->caller.cmdFramePtr;
+ lastPtr->nextPtr = tailPtr;
} else {
- iPtr->cmdFramePtr = corPtr->caller.cmdFramePtr;
+ iPtr->cmdFramePtr = tailPtr;
}
}
@@ -1244,10 +1248,58 @@ InfoFrameCmd(
runPtr->level = 1;
runPtr->nextPtr = NULL;
}
+ CmdFrameUnchain(corPtr);
}
return code;
}
+
+static void
+CmdFrameUnchain(
+ CoroutineData *corPtr)
+{
+ if (corPtr->callerEEPtr->corPtr) {
+ CmdFrame *endPtr = corPtr->callerEEPtr->corPtr->caller.cmdFramePtr;
+
+ if (corPtr->caller.cmdFramePtr == endPtr) {
+ corPtr->caller.cmdFramePtr = NULL;
+ } else {
+ CmdFrame *runPtr = corPtr->caller.cmdFramePtr;
+
+ while (runPtr->nextPtr != endPtr) {
+ runPtr->level -= endPtr->level;
+ runPtr = runPtr->nextPtr;
+ }
+ runPtr->level = 1;
+ runPtr->nextPtr = NULL;
+ }
+ CmdFrameUnchain(corPtr->callerEEPtr->corPtr);
+ }
+}
+
+static CmdFrame *
+CmdFrameChain(
+ CoroutineData *corPtr)
+{
+ if (corPtr->callerEEPtr->corPtr) {
+ CmdFrame *tailPtr = CmdFrameChain(corPtr->callerEEPtr->corPtr);
+ CmdFrame *lastPtr = NULL;
+ CmdFrame *runPtr = corPtr->caller.cmdFramePtr;
+ int offset = tailPtr ? tailPtr->level : 0;
+
+ while (runPtr) {
+ runPtr->level += offset;
+ lastPtr = runPtr;
+ runPtr = runPtr->nextPtr;
+ }
+ if (lastPtr) {
+ lastPtr->nextPtr = tailPtr;
+ } else {
+ corPtr->caller.cmdFramePtr = tailPtr;
+ }
+ }
+ return corPtr->caller.cmdFramePtr;
+}
/*
*----------------------------------------------------------------------
diff --git a/tests/coroutine.test b/tests/coroutine.test
index 03c63ad..a360fd5 100644
--- a/tests/coroutine.test
+++ b/tests/coroutine.test
@@ -342,6 +342,9 @@ test coroutine-3.6 {info frame, bug #2910094} -setup {
rename stack {}
rename a {}
} -result {}
+test coroutine-3.7 {bug 0b874c344d} {
+ dict get [coroutine X coroutine Y info frame 0] cmd
+} {coroutine X coroutine Y info frame 0}
test coroutine-4.1 {bug #2093188} -setup {
proc foo {} {