From 6c9f0c69b67589dd2c52c36bdd3fd3a7fb8e6f60 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 5 Dec 2013 20:45:45 +0000 Subject: Draft fix for Bug 0b874c344d. Includes test. --- generic/tclCmdIL.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++---- tests/coroutine.test | 3 +++ 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 {} { -- cgit v0.12 From 9c336539e4efc2577c7977a99679a133bf4569c5 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 13 Dec 2013 18:39:12 +0000 Subject: Simplify the coding of the unchain operation. --- generic/tclCmdIL.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 57434c1..fc2c367 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -105,7 +105,6 @@ typedef struct SortInfo { */ 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); @@ -1150,7 +1149,7 @@ InfoFrameCmd( { Interp *iPtr = (Interp *) interp; int level, topLevel, code = TCL_OK; - CmdFrame *runPtr, *framePtr; + CmdFrame *runPtr, *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; if (objc > 2) { @@ -1235,36 +1234,13 @@ InfoFrameCmd( Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr)); done: - if (corPtr) { + while (corPtr) { + CmdFrame *endPtr = corPtr->caller.cmdFramePtr; - if (iPtr->cmdFramePtr == corPtr->caller.cmdFramePtr) { - iPtr->cmdFramePtr = NULL; + if (*cmdFramePtrPtr == endPtr) { + *cmdFramePtrPtr = NULL; } else { - runPtr = iPtr->cmdFramePtr; - while (runPtr->nextPtr != corPtr->caller.cmdFramePtr) { - runPtr->level -= corPtr->caller.cmdFramePtr->level; - runPtr = runPtr->nextPtr; - } - 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; + CmdFrame *runPtr = *cmdFramePtrPtr; while (runPtr->nextPtr != endPtr) { runPtr->level -= endPtr->level; @@ -1273,8 +1249,10 @@ CmdFrameUnchain( runPtr->level = 1; runPtr->nextPtr = NULL; } - CmdFrameUnchain(corPtr->callerEEPtr->corPtr); + cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; + corPtr = corPtr->callerEEPtr->corPtr; } + return code; } static CmdFrame * -- cgit v0.12 From f3e8b534b38e07387ab2c0c94653917863c57411 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 16 Dec 2013 21:01:35 +0000 Subject: Refactoring work on the "chain" operation. --- generic/tclCmdIL.c | 101 +++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index fc2c367..28fb3ce 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -104,7 +104,7 @@ typedef struct SortInfo { * Forward declarations for procedures defined in this file: */ -static CmdFrame * CmdFrameChain(CoroutineData *corPtr); +static void CmdFrameChain(CoroutineData *corPtr); static int DictionaryCompare(const char *left, const char *right); static int IfConditionCallback(ClientData data[], Tcl_Interp *interp, int result); @@ -1140,6 +1140,47 @@ TclInfoExistsCmd( *---------------------------------------------------------------------- */ +static void +Chain( + CmdFrame **cmdFramePtrPtr, + CoroutineData *corPtr) +{ + CmdFrame *tailPtr = corPtr->caller.cmdFramePtr; + CmdFrame *runPtr = *cmdFramePtrPtr; + int offset; + + if (tailPtr == NULL) { + return; + } + + if (runPtr == NULL) { + *cmdFramePtrPtr = tailPtr; + return; + } + + offset = tailPtr->level; + + while (runPtr->nextPtr) { + runPtr->level += offset; + runPtr = runPtr->nextPtr; + } + runPtr->level += offset; + runPtr->nextPtr = tailPtr; +} + +static void +CmdFrameChain( + CoroutineData *corPtr) +{ + CmdFrame **cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; + + corPtr = corPtr->callerEEPtr->corPtr; + if (corPtr) { + CmdFrameChain(corPtr); + Chain(cmdFramePtrPtr, corPtr); + } +} + static int InfoFrameCmd( ClientData dummy, /* Not used. */ @@ -1149,7 +1190,7 @@ InfoFrameCmd( { Interp *iPtr = (Interp *) interp; int level, topLevel, code = TCL_OK; - CmdFrame *runPtr, *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; + CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; if (objc > 2) { @@ -1157,36 +1198,13 @@ InfoFrameCmd( return TCL_ERROR; } - topLevel = ((iPtr->cmdFramePtr == NULL) - ? 0 - : iPtr->cmdFramePtr->level); - if (corPtr) { - /* - * A coroutine: must fix the level computations AND the cmdFrame chain, - * which is interrupted at the base. - */ - - CmdFrame *lastPtr = NULL; - CmdFrame *tailPtr = CmdFrameChain(corPtr); - int offset = tailPtr ? tailPtr->level : 0; - - runPtr = iPtr->cmdFramePtr; - - /* TODO - deal with overflow */ - topLevel += offset; - while (runPtr) { - runPtr->level += offset; - lastPtr = runPtr; - runPtr = runPtr->nextPtr; - } - if (lastPtr) { - lastPtr->nextPtr = tailPtr; - } else { - iPtr->cmdFramePtr = tailPtr; - } + CmdFrameChain(corPtr); + Chain(cmdFramePtrPtr, corPtr); } + topLevel = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level : 0; + if (objc == 1) { /* * Just "info frame". @@ -1234,6 +1252,7 @@ InfoFrameCmd( Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr)); done: + cmdFramePtrPtr = &iPtr->cmdFramePtr; while (corPtr) { CmdFrame *endPtr = corPtr->caller.cmdFramePtr; @@ -1254,30 +1273,6 @@ InfoFrameCmd( } return code; } - -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; -} /* *---------------------------------------------------------------------- -- cgit v0.12 From 974c8356eef0f2ca083bea7c55750256592e1f66 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Dec 2013 21:19:36 +0000 Subject: Factor out the level offsetting into a final pass. Let the first pass of the "chain" operation just stitch things together and count levels. --- generic/tclCmdIL.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 28fb3ce..e26c211 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -104,7 +104,7 @@ typedef struct SortInfo { * Forward declarations for procedures defined in this file: */ -static void CmdFrameChain(CoroutineData *corPtr); +static int CmdFrameChain(CoroutineData *corPtr); static int DictionaryCompare(const char *left, const char *right); static int IfConditionCallback(ClientData data[], Tcl_Interp *interp, int result); @@ -1140,45 +1140,47 @@ TclInfoExistsCmd( *---------------------------------------------------------------------- */ -static void +static int Chain( CmdFrame **cmdFramePtrPtr, CoroutineData *corPtr) { CmdFrame *tailPtr = corPtr->caller.cmdFramePtr; CmdFrame *runPtr = *cmdFramePtrPtr; - int offset; if (tailPtr == NULL) { - return; + /* Think this can't happen. */ + return 0; } if (runPtr == NULL) { + int toReturn = tailPtr->level; + *cmdFramePtrPtr = tailPtr; - return; + tailPtr->level = 0; + return toReturn; } - offset = tailPtr->level; - while (runPtr->nextPtr) { - runPtr->level += offset; runPtr = runPtr->nextPtr; } - runPtr->level += offset; runPtr->nextPtr = tailPtr; + return tailPtr->level; } -static void +static int CmdFrameChain( CoroutineData *corPtr) { CmdFrame **cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; + int sum = 0; corPtr = corPtr->callerEEPtr->corPtr; if (corPtr) { - CmdFrameChain(corPtr); - Chain(cmdFramePtrPtr, corPtr); + sum += CmdFrameChain(corPtr); + sum += Chain(cmdFramePtrPtr, corPtr); } + return sum; } static int @@ -1189,9 +1191,10 @@ InfoFrameCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; - int level, topLevel, code = TCL_OK; + int level, code = TCL_OK; CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; + int topLevel = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level : 0; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?number?"); @@ -1199,11 +1202,19 @@ InfoFrameCmd( } if (corPtr) { - CmdFrameChain(corPtr); - Chain(cmdFramePtrPtr, corPtr); + topLevel += CmdFrameChain(corPtr); + topLevel += Chain(cmdFramePtrPtr, corPtr); } - topLevel = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level : 0; + framePtr = iPtr->cmdFramePtr; + while (framePtr) { + framePtr->level = topLevel--; + framePtr = framePtr->nextPtr; + } + if (topLevel) { + Tcl_Panic("Broken frame level calculation"); + } + topLevel = iPtr->cmdFramePtr->level; if (objc == 1) { /* -- cgit v0.12 From 85c73dc9ce50fd5ec5798a10173e29ab8e2c1bd1 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Dec 2013 18:09:09 +0000 Subject: Big simplification of the bug fix. --- generic/tclCmdIL.c | 100 ++++++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 66 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index e26c211..41c1eb6 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -104,7 +104,6 @@ typedef struct SortInfo { * Forward declarations for procedures defined in this file: */ -static int CmdFrameChain(CoroutineData *corPtr); static int DictionaryCompare(const char *left, const char *right); static int IfConditionCallback(ClientData data[], Tcl_Interp *interp, int result); @@ -1140,49 +1139,6 @@ TclInfoExistsCmd( *---------------------------------------------------------------------- */ -static int -Chain( - CmdFrame **cmdFramePtrPtr, - CoroutineData *corPtr) -{ - CmdFrame *tailPtr = corPtr->caller.cmdFramePtr; - CmdFrame *runPtr = *cmdFramePtrPtr; - - if (tailPtr == NULL) { - /* Think this can't happen. */ - return 0; - } - - if (runPtr == NULL) { - int toReturn = tailPtr->level; - - *cmdFramePtrPtr = tailPtr; - tailPtr->level = 0; - return toReturn; - } - - while (runPtr->nextPtr) { - runPtr = runPtr->nextPtr; - } - runPtr->nextPtr = tailPtr; - return tailPtr->level; -} - -static int -CmdFrameChain( - CoroutineData *corPtr) -{ - CmdFrame **cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; - int sum = 0; - - corPtr = corPtr->callerEEPtr->corPtr; - if (corPtr) { - sum += CmdFrameChain(corPtr); - sum += Chain(cmdFramePtrPtr, corPtr); - } - return sum; -} - static int InfoFrameCmd( ClientData dummy, /* Not used. */ @@ -1194,27 +1150,36 @@ InfoFrameCmd( int level, code = TCL_OK; CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; - int topLevel = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level : 0; + int topLevel = 0; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?number?"); return TCL_ERROR; } - if (corPtr) { - topLevel += CmdFrameChain(corPtr); - topLevel += Chain(cmdFramePtrPtr, corPtr); + while (corPtr) { + while (*cmdFramePtrPtr) { + topLevel++; + cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr); + } + if (corPtr->caller.cmdFramePtr) { + *cmdFramePtrPtr = corPtr->caller.cmdFramePtr; + } + corPtr = corPtr->callerEEPtr->corPtr; } + topLevel += (*cmdFramePtrPtr)->level; - framePtr = iPtr->cmdFramePtr; - while (framePtr) { - framePtr->level = topLevel--; - framePtr = framePtr->nextPtr; - } - if (topLevel) { - Tcl_Panic("Broken frame level calculation"); + if (topLevel != iPtr->cmdFramePtr->level) { + framePtr = iPtr->cmdFramePtr; + while (framePtr) { + framePtr->level = topLevel--; + framePtr = framePtr->nextPtr; + } + if (topLevel) { + Tcl_Panic("Broken frame level calculation"); + } + topLevel = iPtr->cmdFramePtr->level; } - topLevel = iPtr->cmdFramePtr->level; if (objc == 1) { /* @@ -1264,22 +1229,25 @@ InfoFrameCmd( done: cmdFramePtrPtr = &iPtr->cmdFramePtr; + corPtr = iPtr->execEnvPtr->corPtr; while (corPtr) { CmdFrame *endPtr = corPtr->caller.cmdFramePtr; - if (*cmdFramePtrPtr == endPtr) { - *cmdFramePtrPtr = NULL; - } else { - CmdFrame *runPtr = *cmdFramePtrPtr; + if (endPtr) { + if (*cmdFramePtrPtr == endPtr) { + *cmdFramePtrPtr = NULL; + } else { + CmdFrame *runPtr = *cmdFramePtrPtr; - while (runPtr->nextPtr != endPtr) { - runPtr->level -= endPtr->level; - runPtr = runPtr->nextPtr; + while (runPtr->nextPtr != endPtr) { + runPtr->level -= endPtr->level; + runPtr = runPtr->nextPtr; + } + runPtr->level = 1; + runPtr->nextPtr = NULL; } - runPtr->level = 1; - runPtr->nextPtr = NULL; + cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; } - cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; corPtr = corPtr->callerEEPtr->corPtr; } return code; -- cgit v0.12