summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog32
-rw-r--r--generic/tclCompCmds.c57
2 files changed, 49 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index ea34251..fd4e879 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,19 +1,23 @@
+2007-11-24 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict
+ append] compiler which caused strange stack corruption.
+
2007-11-23 Andreas Kupries <andreask@activestate.com>
- * generic/tclIORChan.c: Fixed a problem with reflected
- channels. 'chan postevent' is defined to work only from within
- the interpreter containing the handler command. Sensible, we
- want only handler commands to use it. It identifies the channel
- by handle. The channel moves to a different interpreter or
- thread. The interpreter containing the handler command doesn't
- know the channel any longer. 'chan postevent' fails, not finding
- the channel any longer. Uhm.
-
- Fixed by creating a second per-interpreter channel table, just
- for reflected channels, where each interpreter remembers for
- which reflected channels it has the handler command. This info
- does not move with the channel itself. The table is updated by
- 'chan create', and used by 'chan postevent'.
+ * generic/tclIORChan.c: Fixed a problem with reflected channels. 'chan
+ postevent' is defined to work only from within the interpreter
+ containing the handler command. Sensible, we want only handler
+ commands to use it. It identifies the channel by handle. The channel
+ moves to a different interpreter or thread. The interpreter containing
+ the handler command doesn't know the channel any longer. 'chan
+ postevent' fails, not finding the channel any longer. Uhm.
+
+ Fixed by creating a second per-interpreter channel table, just for
+ reflected channels, where each interpreter remembers for which
+ reflected channels it has the handler command. This info does not move
+ with the channel itself. The table is updated by 'chan create', and
+ used by 'chan postevent'.
* tests/ioCmd.test: Updated the testsuite.
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 92accfc..0c603c5 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompCmds.c,v 1.131 2007/11/23 15:00:24 dkf Exp $
+ * RCS: @(#) $Id: tclCompCmds.c,v 1.132 2007/11/24 12:57:56 dkf Exp $
*/
#include "tclInt.h"
@@ -1174,49 +1174,54 @@ TclCompileDictAppendCmd(
{
Proc *procPtr = envPtr->procPtr;
DefineLineInformation; /* TIP #280 */
- Tcl_Token *tokenPtr, *varTokenPtr;
- int numWords, i, dictVarIndex, nameChars;
- const char *name;
+ Tcl_Token *tokenPtr;
+ int i, dictVarIndex;
/*
- * There must be at least two argument after the command.
+ * There must be at least two argument after the command. And we impose an
+ * (arbirary) safe limit; anyone exceeding it should stop worrying about
+ * speed quite so much. ;-)
*/
- if (parsePtr->numWords < 3) {
+ if (parsePtr->numWords<4 || parsePtr->numWords>100 || procPtr==NULL) {
return TCL_ERROR;
}
- tokenPtr = TokenAfter(parsePtr->tokenPtr);
- numWords = parsePtr->numWords-1;
/*
- * Arbirary safe limit; anyone exceeding it should stop worrying about
- * speed quite so much. ;-)
+ * Get the index of the local variable that we will be working with.
*/
- if (parsePtr->numWords > 100 || procPtr == NULL) {
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
return TCL_ERROR;
- }
+ } else {
+ register const char *name = tokenPtr[1].start;
+ register int nameChars = tokenPtr[1].size;
- varTokenPtr = TokenAfter(tokenPtr);
- if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- return TCL_ERROR;
- }
- name = varTokenPtr[1].start;
- nameChars = varTokenPtr[1].size;
- if (!TclIsLocalScalar(name, nameChars)) {
- return TCL_ERROR;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
}
- dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
- tokenPtr = TokenAfter(varTokenPtr);
- for (i=1 ; i<parsePtr->numWords-1 ; i++) {
+ /*
+ * Produce the string to concatenate onto the dictionary entry.
+ */
+
+ tokenPtr = TokenAfter(tokenPtr);
+ for (i=2 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
- if (parsePtr->numWords > 3) {
- TclEmitInstInt1( INST_CONCAT1, parsePtr->numWords-2, envPtr);
+ if (parsePtr->numWords > 4) {
+ TclEmitInstInt1(INST_CONCAT1, parsePtr->numWords-2, envPtr);
}
- TclEmitInstInt4( INST_DICT_APPEND, dictVarIndex, envPtr);
+
+ /*
+ * Do the concatenation.
+ */
+
+ TclEmitInstInt4(INST_DICT_APPEND, dictVarIndex, envPtr);
return TCL_OK;
}