Tcl Source Code

Artifact [8ddd80325d]
Login

Artifact 8ddd80325d1f0604dc128ccc7f0e192fe3c53ef5:

Attachment "fixLevels2.patch" to ticket [483611ffff] added by msofer 2001-12-10 19:27:15.
diff -r -u generic/tclCompCmds.c generic/tclCompCmds.c
--- generic/tclCompCmds.c	Sun Dec  9 12:09:15 2001
+++ generic/tclCompCmds.c	Sun Dec  9 22:29:53 2001
@@ -24,8 +24,7 @@
 static void		FreeForeachInfo _ANSI_ARGS_((ClientData clientData));
 static int		TclPushVarName _ANSI_ARGS_((Tcl_Interp *interp,
 	Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags,
-	int *localIndexPtr, int *maxDepthPtr, int *simpleVarNamePtr,
-	int *isScalarPtr));
+	int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr));
 
 /*
  * Flags bits used by TclPushVarName.
@@ -60,9 +59,6 @@
  *	command should be compiled "out of line" by emitting code to
  *	invoke its command procedure (Tcl_AppendObjCmd) at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the incr command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "append" command
  *	at runtime.
@@ -79,10 +75,8 @@
 {
     Tcl_Token *varTokenPtr, *valueTokenPtr;
     int simpleVarName, isScalar, localIndex, numWords;
-    int maxDepth = 0;
     int code = TCL_OK;
 
-    envPtr->maxStackDepth = 0;
     numWords = parsePtr->numWords;
     if (numWords == 1) {
 	Tcl_ResetResult(interp);
@@ -115,7 +109,7 @@
 
     code = TclPushVarName(interp, varTokenPtr, envPtr,
 	    ((numWords > 2) ? TCL_CREATE_VAR : 0),
-	    &localIndex, &maxDepth, &simpleVarName, &isScalar);
+	    &localIndex, &simpleVarName, &isScalar);
     if (code != TCL_OK) {
 	goto done;
     }
@@ -131,14 +125,12 @@
 	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
 	    TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start,
 		    valueTokenPtr[1].size, /*onHeap*/ 0), envPtr);
-	    maxDepth += 1;
 	} else {
 	    code = TclCompileTokens(interp, valueTokenPtr+1,
 	            valueTokenPtr->numComponents, envPtr);
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth += envPtr->maxStackDepth;
 	}
     }
 
@@ -173,7 +165,6 @@
     }
 
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -189,9 +180,6 @@
  *	there was an error during compilation. If an error occurs then
  *	the interpreter's result contains a standard error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "break" command
  *	at runtime.
@@ -210,7 +198,6 @@
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
 	        "wrong # args: should be \"break\"", -1);
-	envPtr->maxStackDepth = 0;
 	return TCL_ERROR;
     }
 
@@ -219,7 +206,6 @@
      */
 
     TclEmitOpcode(INST_BREAK, envPtr);
-    envPtr->maxStackDepth = 0;
     return TCL_OK;
 }
 
@@ -239,9 +225,6 @@
  *	should be compiled "out of line" by emitting code to invoke its
  *	command procedure at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "catch" command
  *	at runtime.
@@ -259,11 +242,11 @@
     JumpFixup jumpFixup;
     Tcl_Token *cmdTokenPtr, *nameTokenPtr;
     char *name;
-    int localIndex, nameChars, range, maxDepth, startOffset, jumpDist;
+    int localIndex, nameChars, range, startOffset, jumpDist;
     int code;
     char buffer[32 + TCL_INTEGER_SPACE];
+    int savedStackDepth = envPtr->currStackDepth;
 
-    envPtr->maxStackDepth = 0;
     if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
@@ -309,8 +292,6 @@
      * We will compile the catch command. Emit a beginCatch instruction at
      * the start of the catch body: the subcommand it controls.
      */
-
-    maxDepth = 0;
     
     envPtr->exceptDepth++;
     envPtr->maxExceptDepth =
@@ -347,7 +328,6 @@
         }
 	goto done;
     }
-    maxDepth = envPtr->maxStackDepth;
     envPtr->exceptArrayPtr[range].numCodeBytes =
 	    (envPtr->codeNext - envPtr->codeStart) - startOffset;
 		    
@@ -367,9 +347,6 @@
     TclEmitOpcode(INST_POP, envPtr);
     TclEmitPush(TclRegisterLiteral(envPtr, "0", 1, /*onHeap*/ 0),
 	    envPtr);
-    if (maxDepth == 0) {
-	maxDepth = 1;
-    }
     TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
 
     /*
@@ -378,6 +355,7 @@
      * the catch's error target.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     envPtr->exceptArrayPtr[range].catchOffset =
 	    (envPtr->codeNext - envPtr->codeStart);
     if (localIndex != -1) {
@@ -391,6 +369,7 @@
     }
     TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr);
 
+
     /*
      * Update the target of the jump after the "no errors" code, then emit
      * an endCatch instruction at the end of the catch command.
@@ -404,8 +383,8 @@
     TclEmitOpcode(INST_END_CATCH, envPtr);
 
     done:
+    envPtr->currStackDepth = savedStackDepth + 1;
     envPtr->exceptDepth--;
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -421,9 +400,6 @@
  *	there was an error while parsing string. If an error occurs then
  *	the interpreter's result contains a standard error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "continue" command
  *	at runtime.
@@ -446,7 +422,6 @@
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
 	        "wrong # args: should be \"continue\"", -1);
-	envPtr->maxStackDepth = 0;
 	return TCL_ERROR;
     }
 
@@ -455,7 +430,6 @@
      */
 
     TclEmitOpcode(INST_CONTINUE, envPtr);
-    envPtr->maxStackDepth = 0;
     return TCL_OK;
 }
 
@@ -471,9 +445,6 @@
  *	unless there was an error while parsing string. If an error occurs
  *	then the interpreter's result contains a standard error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the "expr" command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "expr" command
  *	at runtime.
@@ -490,7 +461,6 @@
 {
     Tcl_Token *firstWordPtr;
 
-    envPtr->maxStackDepth = 0;
     if (parsePtr->numWords == 1) {
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
@@ -516,9 +486,6 @@
  *	there was an error while parsing string. If an error occurs then
  *	the interpreter's result contains a standard error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "for" command
  *	at runtime.
@@ -535,12 +502,12 @@
 {
     Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr;
     JumpFixup jumpFalseFixup;
-    int maxDepth, jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist;
+    int jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist;
     int bodyRange, nextRange, code;
     unsigned char *jumpPc;
     char buffer[32 + TCL_INTEGER_SPACE];
+    int savedStackDepth = envPtr->currStackDepth;
 
-    envPtr->maxStackDepth = 0;
     if (parsePtr->numWords != 5) {
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
@@ -589,7 +556,6 @@
      * Inline compile the initial command.
      */
 
-    maxDepth = 0;
     code = TclCompileCmdWord(interp, startTokenPtr+1,
 	    startTokenPtr->numComponents, envPtr);
     if (code != TCL_OK) {
@@ -599,15 +565,16 @@
         }
 	goto done;
     }
-    maxDepth = envPtr->maxStackDepth;
     TclEmitOpcode(INST_POP, envPtr);
     
     /*
      * Compile the test then emit the conditional jump that exits the for.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
     code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
+    envPtr->currStackDepth = savedStackDepth + 1;
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
             Tcl_AddObjErrorInfo(interp,
@@ -615,13 +582,13 @@
         }
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
 
     /*
      * Compile the loop body.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     envPtr->exceptArrayPtr[bodyRange].codeOffset =
 	    (envPtr->codeNext - envPtr->codeStart);
     code = TclCompileCmdWord(interp, bodyTokenPtr+1,
@@ -634,7 +601,6 @@
         }
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     envPtr->exceptArrayPtr[bodyRange].numCodeBytes =
 	    (envPtr->codeNext - envPtr->codeStart)
 	    - envPtr->exceptArrayPtr[bodyRange].codeOffset;
@@ -644,12 +610,14 @@
      * Compile the "next" subcommand.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     envPtr->exceptArrayPtr[bodyRange].continueOffset =
 	    (envPtr->codeNext - envPtr->codeStart);
     envPtr->exceptArrayPtr[nextRange].codeOffset =
 	    (envPtr->codeNext - envPtr->codeStart);
     code = TclCompileCmdWord(interp, nextTokenPtr+1,
 	    nextTokenPtr->numComponents, envPtr);
+    envPtr->currStackDepth = savedStackDepth + 1;
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
 	    Tcl_AddObjErrorInfo(interp,
@@ -657,11 +625,11 @@
 	}
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     envPtr->exceptArrayPtr[nextRange].numCodeBytes =
 	    (envPtr->codeNext - envPtr->codeStart)
 	    - envPtr->exceptArrayPtr[nextRange].codeOffset;
     TclEmitOpcode(INST_POP, envPtr);
+    envPtr->currStackDepth = savedStackDepth;
 	
     /*
      * Jump back to the test at the top of the loop. Generate a 4 byte jump
@@ -722,13 +690,9 @@
      */
 
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
-    if (maxDepth == 0) {
-	maxDepth = 1;
-    }
     code = TCL_OK;
 
     done:
-    envPtr->maxStackDepth = maxDepth;
     envPtr->exceptDepth--;
     return code;
 }
@@ -749,9 +713,6 @@
  *	should be compiled "out of line" by emitting code to invoke its
  *	command procedure at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the "while" command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "foreach" command
  *	at runtime.
@@ -778,10 +739,12 @@
     char *varList;
     unsigned char *jumpPc;
     JumpFixup jumpFalseFixup;
-    int jumpDist, jumpBackDist, jumpBackOffset, maxDepth, infoIndex, range;
+    int jumpDist, jumpBackDist, jumpBackOffset, infoIndex, range;
     int numWords, numLists, numVars, loopIndex, tempVar, i, j, code;
     char savedChar;
     char buffer[32 + TCL_INTEGER_SPACE];
+    int savedStackDepth = envPtr->currStackDepth;
+
 
     /*
      * We parse the variable list argument words and create two arrays:
@@ -800,13 +763,10 @@
      * the payoff is too small.
      */
 
-    envPtr->maxStackDepth = 0;
     if (procPtr == NULL) {
 	return TCL_OUT_LINE_COMPILE;
     }
 
-    maxDepth = 0;
-    
     numWords = parsePtr->numWords;
     if ((numWords < 4) || (numWords%2 != 0)) {
 	Tcl_ResetResult(interp);
@@ -958,7 +918,6 @@
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
 
 	    tempVar = (firstValueTemp + loopIndex);
 	    if (tempVar <= 255) {
@@ -995,6 +954,7 @@
 	    (envPtr->codeNext - envPtr->codeStart);
     code = TclCompileCmdWord(interp, bodyTokenPtr+1,
 	    bodyTokenPtr->numComponents, envPtr);
+    envPtr->currStackDepth = savedStackDepth + 1;
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
 	    sprintf(buffer, "\n    (\"foreach\" body line %d)",
@@ -1003,7 +963,6 @@
         }
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     envPtr->exceptArrayPtr[range].numCodeBytes =
 	    (envPtr->codeNext - envPtr->codeStart)
 	    - envPtr->exceptArrayPtr[range].codeOffset;
@@ -1064,10 +1023,9 @@
      * The foreach command's result is an empty string.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
-    if (maxDepth == 0) {
-	maxDepth = 1;
-    }
+    envPtr->currStackDepth = savedStackDepth + 1;
 
     done:
     for (loopIndex = 0;  loopIndex < numLists;  loopIndex++) {
@@ -1079,7 +1037,6 @@
 	ckfree((char *) varcList);
         ckfree((char *) varvList);
     }
-    envPtr->maxStackDepth = maxDepth;
     envPtr->exceptDepth--;
     return code;
 }
@@ -1188,9 +1145,6 @@
  *	should be compiled "out of line" by emitting code to invoke its
  *	command procedure at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "if" command
  *	at runtime.
@@ -1214,9 +1168,13 @@
 				 * is determined. */
     Tcl_Token *tokenPtr, *testTokenPtr;
     int jumpDist, jumpFalseDist, jumpIndex;
-    int numWords, wordIdx, numBytes, maxDepth, j, code;
+    int numWords, wordIdx, numBytes, j, code;
     char *word;
     char buffer[100];
+    int savedStackDepth = envPtr->currStackDepth;
+                                /* Saved stack depth at the start of the first
+				 * test; the envPtr current depth is restored
+				 * to this value at the start of each test. */
 
     /*
      * Only compile the "if" command if all arguments are simple
@@ -1237,7 +1195,6 @@
 
     TclInitJumpFixupArray(&jumpFalseFixupArray);
     TclInitJumpFixupArray(&jumpEndFixupArray);
-    maxDepth = 0;
     code = TCL_OK;
 
     /*
@@ -1280,6 +1237,7 @@
 	 * we back off and compile the if command out-of-line.
 	 */
 	
+	envPtr->currStackDepth = savedStackDepth;
 	testTokenPtr = tokenPtr;
 	code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
 	if (code != TCL_OK) {
@@ -1289,7 +1247,6 @@
 	    }
 	    goto done;
 	}
-	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
 	if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
 	    TclExpandJumpFixupArray(&jumpFalseFixupArray);
 	}
@@ -1331,6 +1288,7 @@
 	 * Compile the "then" command body.
 	 */
 
+	envPtr->currStackDepth = savedStackDepth;
 	code = TclCompileCmdWord(interp, tokenPtr+1,
 		tokenPtr->numComponents, envPtr);
 	if (code != TCL_OK) {
@@ -1341,7 +1299,6 @@
 	    }
 	    goto done;
 	}
-	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
 
 	/*
 	 * Jump to the end of the "if" command. Both jumpFalseFixupArray and
@@ -1380,6 +1337,13 @@
     }
 
     /*
+     * Restore the current stack depth in the environment; the 
+     * "else" clause (or its default) will add 1 to this.
+     */
+
+    envPtr->currStackDepth = savedStackDepth;
+
+    /*
      * Check for the optional else clause.
      */
 
@@ -1388,7 +1352,7 @@
 	/*
 	 * There is an else clause. Skip over the optional "else" word.
 	 */
-	
+
 	word = tokenPtr[1].start;
 	numBytes = tokenPtr[1].size;
 	if ((numBytes == 4) && (strncmp(word, "else", 4) == 0)) {
@@ -1417,7 +1381,6 @@
 	    }
 	    goto done;
 	}
-	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
 
 	/*
 	 * Make sure there are no words after the else clause.
@@ -1437,7 +1400,6 @@
 	 */
 
 	TclEmitPush(TclRegisterLiteral(envPtr, "", 0,/*onHeap*/ 0), envPtr);
-	maxDepth = TclMax(1, maxDepth);
     }
 
     /*
@@ -1477,9 +1439,9 @@
      */
 
     done:
+    envPtr->currStackDepth = savedStackDepth + 1;
     TclFreeJumpFixupArray(&jumpFalseFixupArray);
     TclFreeJumpFixupArray(&jumpEndFixupArray);
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -1499,9 +1461,6 @@
  *	should be compiled "out of line" by emitting code to invoke its
  *	command procedure at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the "incr" command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "incr" command
  *	at runtime.
@@ -1518,10 +1477,8 @@
 {
     Tcl_Token *varTokenPtr, *incrTokenPtr;
     int simpleVarName, isScalar, localIndex, haveImmValue, immValue;
-    int maxDepth = 0;
     int code = TCL_OK;
 
-    envPtr->maxStackDepth = 0;
     if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
@@ -1533,7 +1490,7 @@
 	    + (parsePtr->tokenPtr->numComponents + 1);
 
     code = TclPushVarName(interp, varTokenPtr, envPtr, TCL_NO_LARGE_INDEX,
-	    &localIndex, &maxDepth, &simpleVarName, &isScalar);
+	    &localIndex, &simpleVarName, &isScalar);
     if (code != TCL_OK) {
 	goto done;
     }
@@ -1572,7 +1529,6 @@
 	    if (!haveImmValue) {
 		TclEmitPush(TclRegisterLiteral(envPtr, word, numBytes,
 	               /*onHeap*/ 0), envPtr);
-		maxDepth += 1;
 	    }
 	} else {
 	    code = TclCompileTokens(interp, incrTokenPtr+1, 
@@ -1584,7 +1540,6 @@
 		}
 		goto done;
 	    }
-	    maxDepth += envPtr->maxStackDepth;
 	}
     } else {			/* no incr amount given so use 1 */
 	haveImmValue = 1;
@@ -1636,7 +1591,6 @@
     }
 	
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -1656,9 +1610,6 @@
  *	command should be compiled "out of line" by emitting code to
  *	invoke its command procedure (Tcl_LappendObjCmd) at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the incr command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "lappend" command
  *	at runtime.
@@ -1675,7 +1626,6 @@
 {
     Tcl_Token *varTokenPtr, *valueTokenPtr;
     int numValues, simpleVarName, isScalar, localIndex, numWords;
-    int maxDepth = 0;
     int code = TCL_OK;
 
     /*
@@ -1685,7 +1635,6 @@
 	return TCL_OUT_LINE_COMPILE;
     }
 
-    envPtr->maxStackDepth = 0;
     numWords = parsePtr->numWords;
     if (numWords == 1) {
 	Tcl_ResetResult(interp);
@@ -1713,7 +1662,7 @@
 	    + (parsePtr->tokenPtr->numComponents + 1);
 
     code = TclPushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
-	    &localIndex, &maxDepth, &simpleVarName, &isScalar);
+	    &localIndex, &simpleVarName, &isScalar);
     if (code != TCL_OK) {
 	goto done;
     }
@@ -1728,14 +1677,12 @@
 	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
 	    TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start,
 		    valueTokenPtr[1].size, /*onHeap*/ 0), envPtr);
-	    maxDepth += 1;
 	} else {
 	    code = TclCompileTokens(interp, valueTokenPtr+1,
 	            valueTokenPtr->numComponents, envPtr);
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth += envPtr->maxStackDepth;
 	}
 #if 0
     } else {
@@ -1745,7 +1692,6 @@
 	 */
 
 	TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
-	maxDepth += 1;
 	numValues = 1;
 #endif
     }
@@ -1785,7 +1731,6 @@
     }
 
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -1803,9 +1748,6 @@
  *	interpreter's result contains an error message, and TCL_ERROR is
  *	returned.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "lindex" command
  *	at runtime.
@@ -1821,7 +1763,7 @@
     CompileEnv *envPtr;		/* Holds resulting instructions. */
 {
     Tcl_Token *varTokenPtr;
-    int code, depth, i;
+    int code, i;
 
     int numWords;
     numWords = parsePtr->numWords;
@@ -1837,8 +1779,6 @@
     varTokenPtr = parsePtr->tokenPtr
 	+ (parsePtr->tokenPtr->numComponents + 1);
     
-    depth = 0;
-    
     /*
      * Push the operands onto the stack.
      */
@@ -1850,15 +1790,12 @@
 					     varTokenPtr[1].size,
 					     0),
 			 envPtr);
-	    depth++;
 	} else {
 	    code = TclCompileTokens(interp, varTokenPtr+1,
 				    varTokenPtr->numComponents, envPtr);
 	    if (code != TCL_OK) {
-		envPtr->maxStackDepth = depth;
 		return code;
 	    }
-	    depth += envPtr->maxStackDepth;
 	}
 	varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
     }
@@ -1868,7 +1805,6 @@
      * if there are multiple index args.
      */
 
-    envPtr->maxStackDepth = depth;
     if ( numWords == 3 ) {
 	TclEmitOpcode( INST_LIST_INDEX, envPtr );
     } else {
@@ -1895,9 +1831,6 @@
  *	command should be compiled "out of line" by emitting code to
  *	invoke its command procedure (Tcl_ListObjCmd) at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the incr command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "list" command
  *	at runtime.
@@ -1919,20 +1852,18 @@
 	return TCL_OUT_LINE_COMPILE;
     }
 
-    envPtr->maxStackDepth = 0;
     if (parsePtr->numWords == 1) {
 	/*
 	 * Empty args case
 	 */
 
 	TclEmitPush(TclRegisterLiteral(envPtr, "", 0, 0), envPtr);
-	envPtr->maxStackDepth = 1;
     } else {
 	/*
 	 * Push the all values onto the stack.
 	 */
 	Tcl_Token *valueTokenPtr;
-	int i, code, numWords, depth = 0;
+	int i, code, numWords;
 
 	numWords = parsePtr->numWords;
 
@@ -1943,19 +1874,15 @@
 		TclEmitPush(TclRegisterLiteral(envPtr,
 			valueTokenPtr[1].start, valueTokenPtr[1].size,
 			/*onHeap*/ 0), envPtr);
-		depth++;
 	    } else {
 		code = TclCompileTokens(interp, valueTokenPtr+1,
 			valueTokenPtr->numComponents, envPtr);
 		if (code != TCL_OK) {
-		    envPtr->maxStackDepth = depth;
 		    return code;
 		}
-		depth += envPtr->maxStackDepth;
 	    }
 	    valueTokenPtr = valueTokenPtr + (valueTokenPtr->numComponents + 1);
 	}
-	envPtr->maxStackDepth = depth;
 	TclEmitInstInt4(INST_LIST, numWords - 1, envPtr);
     }
 
@@ -1976,9 +1903,6 @@
  *	interpreter's result contains an error message, and TCL_ERROR is
  *	returned.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "llength" command
  *	at runtime.
@@ -2011,7 +1935,6 @@
 	 */
 	TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start,
 		varTokenPtr[1].size, 0), envPtr);
-	envPtr->maxStackDepth = 1;
     } else {
 	code = TclCompileTokens(interp, varTokenPtr+1,
 		varTokenPtr->numComponents, envPtr);
@@ -2038,9 +1961,6 @@
  *	(that is, not byte-compiled).  If an error occurs, TCL_ERROR is
  *	returned, and the interpreter result contains an error message.
  *
- *	envPtr->maxStackDepth is updated with a conservative estimate
- *	of the number of stack elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "lset" command
  *	at runtime.
@@ -2078,12 +1998,8 @@
     CompileEnv* envPtr;		/* Holds the resulting instructions */
 {
 
-    int depth = 0;		/* Current depth of stack */
     int tempDepth;		/* Depth used for emitting one part
 				 * of the code burst. */
-    int maxDepth = 0;		/* Max depth used anywhere in the
-				 * code burst */
-
     Tcl_Token* varTokenPtr;	/* Pointer to the Tcl_Token representing
 				 * the parse of the variable name */
 
@@ -2112,32 +2028,12 @@
 
     varTokenPtr = parsePtr->tokenPtr
 	    + (parsePtr->tokenPtr->numComponents + 1);
-    tempDepth = 0;
     result = TclPushVarName( interp, varTokenPtr, envPtr, 0,
-			     &localIndex, &tempDepth,
-			     &simpleVarName, &isScalar );
-    if ( tempDepth > maxDepth ) {
-	maxDepth = tempDepth;
-    }
+			     &localIndex, &simpleVarName, &isScalar );
     if (result != TCL_OK) {
-	envPtr->maxStackDepth = maxDepth;
 	return result;
     }
 
-    /* Figure out how much is now on stack. */
-
-    depth = 0;
-    if ( simpleVarName ) {
-	if ( localIndex < 0 ) {
-	    ++depth;		/* We have pushed a variable name. */
-	}
-	if ( !isScalar ) {
-	    ++depth;		/* We have pushed an array element */
-	}
-    } else {
-	++depth;		/* Variable is complex; it's pushed to stack */
-    }
-
     /* Push the "index" args and the new element value. */
 
     for ( i = 2; i < parsePtr->numWords; ++i ) {
@@ -2154,20 +2050,10 @@
 					     varTokenPtr[1].size,
 					     0),
 			 envPtr);
-	    ++depth;
-	    if ( depth > maxDepth ) {
-		maxDepth = depth;
-	    }
 	} else {
-	    envPtr->maxStackDepth = depth;
 	    result = TclCompileTokens(interp, varTokenPtr+1,
 				      varTokenPtr->numComponents, envPtr);
-	    ++depth;
-	    if ( envPtr->maxStackDepth > maxDepth ) {
-		maxDepth = envPtr->maxStackDepth;
-	    }
 	    if ( result != TCL_OK ) {
-		envPtr->maxStackDepth = maxDepth;
 		return result;
 	    }
 	}
@@ -2184,10 +2070,6 @@
 	    tempDepth = parsePtr->numWords - 1;
 	}
 	TclEmitInstInt4( INST_OVER, tempDepth, envPtr );
-	++depth;
-	if ( depth > maxDepth ) {
-	    maxDepth = depth;
-	}
     }
 
     /*
@@ -2201,10 +2083,6 @@
 	    tempDepth = parsePtr->numWords - 2;
 	}
 	TclEmitInstInt4( INST_OVER, tempDepth, envPtr );
-	++depth;
-	if ( depth > maxDepth ) {
-	    maxDepth = depth;
-	}
     }
 
     /*
@@ -2232,17 +2110,6 @@
     }
 
     /*
-     * Stack has now reached the maximum depth it will attain
-     * during this code burst.
-     */
-
-    ++depth;
-    if ( depth > maxDepth ) {
-	maxDepth = depth;
-    }
-    envPtr->maxStackDepth = maxDepth;
-
-    /*
      * Emit the correct variety of 'lset' instruction
      */
 
@@ -2296,9 +2163,6 @@
  *	If an error occurs then the interpreter's result contains a standard
  *	error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "return" command
  *	at runtime.
@@ -2331,7 +2195,6 @@
 	     * Just push the literal string "".
 	     */
 	    TclEmitPush(TclRegisterLiteral(envPtr, "", 0, 0), envPtr);
-	    envPtr->maxStackDepth = 1;
 	    break;
 	}
 	case 2: {
@@ -2350,7 +2213,6 @@
 		 */
 		TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start,
 			varTokenPtr[1].size, /*onHeap*/ 0), envPtr);
-		envPtr->maxStackDepth = 1;
 	    } else {
 		/*
 		 * Parse token is more complex, so compile it; this handles the
@@ -2401,9 +2263,6 @@
  *	set command should be compiled "out of line" by emitting code to
  *	invoke its command procedure (Tcl_SetCmd) at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the incr command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "set" command
  *	at runtime.
@@ -2420,10 +2279,8 @@
 {
     Tcl_Token *varTokenPtr, *valueTokenPtr;
     int isAssignment, isScalar, simpleVarName, localIndex, numWords;
-    int maxDepth = 0;
     int code = TCL_OK;
 
-    envPtr->maxStackDepth = 0;
     numWords = parsePtr->numWords;
     if ((numWords != 2) && (numWords != 3)) {
 	Tcl_ResetResult(interp);
@@ -2446,7 +2303,7 @@
 
     code = TclPushVarName(interp, varTokenPtr, envPtr,
 	    (isAssignment ? TCL_CREATE_VAR : 0),
-	    &localIndex, &maxDepth, &simpleVarName, &isScalar);
+	    &localIndex, &simpleVarName, &isScalar);
     if (code != TCL_OK) {
 	goto done;
     }
@@ -2460,14 +2317,12 @@
 	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
 	    TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start,
 		    valueTokenPtr[1].size, /*onHeap*/ 0), envPtr);
-	    maxDepth += 1;
 	} else {
 	    code = TclCompileTokens(interp, valueTokenPtr+1,
 	            valueTokenPtr->numComponents, envPtr);
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth += envPtr->maxStackDepth;
 	}
     }
 
@@ -2512,7 +2367,6 @@
     }
 	
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -2530,9 +2384,6 @@
  *	interpreter's result contains an error message, and TCL_ERROR is
  *	returned.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "string" command
  *	at runtime.
@@ -2612,7 +2463,7 @@
 
 	case STR_COMPARE: 
 	case STR_EQUAL: {
-	    int i, depth;
+	    int i;
 	    /*
 	     * If there are any flags to the command, we can't byte compile it
 	     * because the INST_STR_EQ bytecode doesn't support flags.
@@ -2622,8 +2473,6 @@
 		return TCL_OUT_LINE_COMPILE;
 	    }
 
-	    depth = 0;
-
 	    /*
 	     * Push the two operands onto the stack.
 	     */
@@ -2633,25 +2482,22 @@
 		    TclEmitPush(TclRegisterLiteral(envPtr,
 			    varTokenPtr[1].start, varTokenPtr[1].size,
 			    0), envPtr);
-		    depth++;
 		} else {
 		    code = TclCompileTokens(interp, varTokenPtr+1,
 			    varTokenPtr->numComponents, envPtr);
 		    if (code != TCL_OK) {
 			return code;
 		    }
-		    depth += envPtr->maxStackDepth;
 		}
 		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
 	    }
 
-	    envPtr->maxStackDepth = depth;
 	    TclEmitOpcode(((((enum options) index) == STR_COMPARE) ?
 		    INST_STR_CMP : INST_STR_EQ), envPtr);
 	    return TCL_OK;
 	}
 	case STR_INDEX: {
-	    int i, depth;
+	    int i;
 
 	    if (parsePtr->numWords != 4) {
 		Tcl_SetResult(interp, "wrong # args: should be "
@@ -2659,8 +2505,6 @@
 		return TCL_ERROR;
 	    }
 
-	    depth = 0;
-
 	    /*
 	     * Push the two operands onto the stack.
 	     */
@@ -2670,19 +2514,16 @@
 		    TclEmitPush(TclRegisterLiteral(envPtr,
 			    varTokenPtr[1].start, varTokenPtr[1].size,
 			    0), envPtr);
-		    depth++;
 		} else {
 		    code = TclCompileTokens(interp, varTokenPtr+1,
 			    varTokenPtr->numComponents, envPtr);
 		    if (code != TCL_OK) {
 			return code;
 		    }
-		    depth += envPtr->maxStackDepth;
 		}
 		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
 	    }
 
-	    envPtr->maxStackDepth = depth;
 	    TclEmitOpcode(INST_STR_INDEX, envPtr);
 	    return TCL_OK;
 	}
@@ -2715,7 +2556,7 @@
 	    return TCL_OK;
 	}
 	case STR_MATCH: {
-	    int i, length, exactMatch = 0, nocase = 0, depth = 0;
+	    int i, length, exactMatch = 0, nocase = 0;
 	    char c, *str;
 
 	    if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
@@ -2767,14 +2608,12 @@
 		    }
 		    TclEmitPush(TclRegisterLiteral(envPtr, str, length,
 			    0), envPtr);
-		    depth++;
 		} else {
 		    code = TclCompileTokens(interp, varTokenPtr+1,
 			    varTokenPtr->numComponents, envPtr);
 		    if (code != TCL_OK) {
 			return code;
 		    }
-		    depth += envPtr->maxStackDepth;
 		}
 		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
 	    }
@@ -2784,7 +2623,6 @@
 	    } else {
 		TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
 	    }
-	    envPtr->maxStackDepth = depth;
 	    return TCL_OK;
 	}
     }
@@ -2808,9 +2646,6 @@
  *	indicating that the while command should be compiled "out of line"
  *	by emitting code to invoke its command procedure at runtime.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the "while" command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "while" command
  *	at runtime.
@@ -2829,11 +2664,10 @@
     JumpFixup jumpFalseFixup;
     unsigned char *jumpPc;
     int testCodeOffset, jumpDist, jumpBackDist, jumpBackOffset;
-    int range, maxDepth, code;
+    int range, code;
     char buffer[32 + TCL_INTEGER_SPACE];
+    int savedStackDepth = envPtr->currStackDepth;
 
-    envPtr->maxStackDepth = 0;
-    maxDepth = 0;
     if (parsePtr->numWords != 3) {
 	Tcl_ResetResult(interp);
 	Tcl_AppendToObj(Tcl_GetObjResult(interp),
@@ -2885,18 +2719,19 @@
         }
 	goto error;
     }
-    maxDepth = envPtr->maxStackDepth;
     TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
     
     /*
      * Compile the loop body.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     bodyTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
     envPtr->exceptArrayPtr[range].codeOffset =
 	    (envPtr->codeNext - envPtr->codeStart);
     code = TclCompileCmdWord(interp, bodyTokenPtr+1,
 	    bodyTokenPtr->numComponents, envPtr);
+    envPtr->currStackDepth = savedStackDepth + 1;
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
 	    sprintf(buffer, "\n    (\"while\" body line %d)",
@@ -2905,7 +2740,6 @@
         }
 	goto error;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     envPtr->exceptArrayPtr[range].numCodeBytes =
 	    (envPtr->codeNext - envPtr->codeStart)
 	    - envPtr->exceptArrayPtr[range].codeOffset;
@@ -2965,16 +2799,12 @@
      * The while command's result is an empty string.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
-    if (maxDepth == 0) {
-	maxDepth = 1;
-    }
-    envPtr->maxStackDepth = maxDepth;
     envPtr->exceptDepth--;
     return TCL_OK;
 
     error:
-    envPtr->maxStackDepth = maxDepth;
     envPtr->exceptDepth--;
     return code;
 }
@@ -2992,9 +2822,6 @@
  *	unless there was an error while parsing string. If an error occurs
  *	then the interpreter's result contains a standard error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the incr command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the "set" command
  *	at runtime.
@@ -3004,15 +2831,13 @@
 
 static int
 TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
-	maxDepthPtr, simpleVarNamePtr, isScalarPtr)
+	simpleVarNamePtr, isScalarPtr)
     Tcl_Interp *interp;		/* Used for error reporting. */
     Tcl_Token *varTokenPtr;	/* Points to a variable token. */
     CompileEnv *envPtr;		/* Holds resulting instructions. */
     int flags;			/* takes TCL_CREATE_VAR or
 				 * TCL_LARGE_INDEX_OK */
     int *localIndexPtr;		/* must not be NULL */
-    int *maxDepthPtr;		/* must not be NULL, should already have a
-				 * value set in the parent. */
     int *simpleVarNamePtr;	/* must not be NULL */
     int *isScalarPtr;		/* must not be NULL */
 {
@@ -3022,7 +2847,6 @@
     char *name, *elName;
     register int i, n;
     int nameChars, elNameChars, simpleVarName, localIndex;
-    int maxDepth = 0;
     int code = TCL_OK;
 
     /*
@@ -3149,7 +2973,6 @@
 	if (localIndex < 0) {
 	    TclEmitPush(TclRegisterLiteral(envPtr, name, nameChars,
 		    /*onHeap*/ 0), envPtr);
-	    maxDepth = 1;
 	}
 
 	/*
@@ -3181,11 +3004,9 @@
 		if (code != TCL_OK) {
 		    goto done;
 		}
-		maxDepth += envPtr->maxStackDepth;
 	    } else {
 		TclEmitPush(TclRegisterLiteral(envPtr, "", 0,
                         /*alreadyAlloced*/ 0), envPtr);
-		maxDepth += 1;
 	    }
 	}
     } else {
@@ -3198,7 +3019,6 @@
 	if (code != TCL_OK) {
 	    goto done;
 	}
-	maxDepth += envPtr->maxStackDepth;
     }
 
     done:
@@ -3206,7 +3026,6 @@
         Tcl_FreeParse(&elemParse);
     }
     *localIndexPtr	= localIndex;
-    *maxDepthPtr	+= maxDepth;
     *simpleVarNamePtr	= simpleVarName;
     *isScalarPtr	= (elName == NULL);
     return code;
diff -r -u generic/tclCompExpr.c generic/tclCompExpr.c
--- generic/tclCompExpr.c	Sun Dec  9 12:09:15 2001
+++ generic/tclCompExpr.c	Sun Dec  9 21:43:38 2001
@@ -206,9 +206,6 @@
  *	on failure. If TCL_ERROR is returned, then the interpreter's result
  *	contains an error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the expression.
- *
  *	envPtr->exprIsJustVarRef is set 1 if the expression consisted of
  *	a single variable reference as in the expression of "if $b then...".
  *	Otherwise it is set 0. This is used to implement Tcl's two level
@@ -237,7 +234,7 @@
     ExprInfo info;
     Tcl_Parse parse;
     Tcl_HashEntry *hPtr;
-    int maxDepth, new, i, code;
+    int new, i, code;
 
     /*
      * If this is the first time we've been called, initialize the table
@@ -280,7 +277,6 @@
      * Parse the expression then compile it.
      */
 
-    maxDepth = 0;
     code = Tcl_ParseExpr(interp, script, numBytes, &parse);
     if (code != TCL_OK) {
 	goto done;
@@ -291,7 +287,6 @@
 	Tcl_FreeParse(&parse);
 	goto done;
     }
-    maxDepth = envPtr->maxStackDepth;
     
     if (!info.hasOperators) {
 	/*
@@ -306,7 +301,6 @@
     Tcl_FreeParse(&parse);
 
     done:
-    envPtr->maxStackDepth = maxDepth;
     envPtr->exprIsJustVarRef = info.exprIsJustVarRef;
     envPtr->exprIsComparison = info.exprIsComparison;
     return code;
@@ -357,9 +351,6 @@
  *	on failure. If TCL_ERROR is returned, then the interpreter's result
  *	contains an error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the subexpression.
- *
  *	envPtr->exprIsJustVarRef is set 1 if the subexpression consisted of
  *	a single variable reference as in the expression of "if $b then...".
  *	Otherwise it is set 0. This is used to implement Tcl's two level
@@ -390,14 +381,13 @@
     Tcl_HashEntry *hPtr;
     char *operator;
     char savedChar;
-    int maxDepth, objIndex, opIndex, length, code;
+    int objIndex, opIndex, length, code;
     char buffer[TCL_UTF_MAX];
 
     if (exprTokenPtr->type != TCL_TOKEN_SUB_EXPR) {
 	panic("CompileSubExpr: token type %d not TCL_TOKEN_SUB_EXPR\n",
 	        exprTokenPtr->type);
     }
-    maxDepth = 0;
     code = TCL_OK;
 
     /*
@@ -416,7 +406,6 @@
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth = envPtr->maxStackDepth;
 	    tokenPtr += (tokenPtr->numComponents + 1);
 	    infoPtr->exprIsJustVarRef = 0;
 	    break;
@@ -429,7 +418,6 @@
 		objIndex = TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0);
 	    }
 	    TclEmitPush(objIndex, envPtr);
-	    maxDepth = 1;
 	    tokenPtr += 1;
 	    infoPtr->exprIsJustVarRef = 0;
 	    break;
@@ -444,7 +432,6 @@
 		objIndex = TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0);
 	    }
 	    TclEmitPush(objIndex, envPtr);
-	    maxDepth = 1;
 	    tokenPtr += 1;
 	    infoPtr->exprIsJustVarRef = 0;
 	    break;
@@ -455,7 +442,6 @@
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth = envPtr->maxStackDepth;
 	    tokenPtr += 1;
 	    infoPtr->exprIsJustVarRef = 0;
 	    break;
@@ -465,7 +451,6 @@
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth = envPtr->maxStackDepth;
 	    tokenPtr += (tokenPtr->numComponents + 1);
 	    break;
 	    
@@ -475,7 +460,6 @@
 	    if (code != TCL_OK) {
 		goto done;
 	    }
-	    maxDepth = envPtr->maxStackDepth;
 	    tokenPtr += (tokenPtr->numComponents + 1);
 	    break;
 	    
@@ -504,7 +488,6 @@
 		if (code != TCL_OK) {
 		    goto done;
 		}
-		maxDepth = envPtr->maxStackDepth;
 		tokenPtr = endPtr;
 		infoPtr->exprIsJustVarRef = 0;
 		infoPtr->exprIsComparison = 0;
@@ -525,7 +508,6 @@
 		if (code != TCL_OK) {
 		    goto done;
 		}
-		maxDepth = envPtr->maxStackDepth;
 		tokenPtr += (tokenPtr->numComponents + 1);
 
 		if (opDescPtr->numOperands == 2) {
@@ -533,8 +515,6 @@
 		    if (code != TCL_OK) {
 			goto done;
 		    }
-		    maxDepth = TclMax((envPtr->maxStackDepth + 1),
-		            maxDepth);
 		    tokenPtr += (tokenPtr->numComponents + 1);
 		}
 		TclEmitOpcode(opDescPtr->instruction, envPtr);
@@ -559,7 +539,6 @@
 		    if (code != TCL_OK) {
 			goto done;
 		    }
-		    maxDepth = envPtr->maxStackDepth;
 		    tokenPtr += (tokenPtr->numComponents + 1);
 		    
 		    /*
@@ -583,8 +562,6 @@
 		    if (code != TCL_OK) {
 			goto done;
 		    }
-		    maxDepth = TclMax((envPtr->maxStackDepth + 1),
-			    maxDepth);
 		    tokenPtr += (tokenPtr->numComponents + 1);
 		    TclEmitOpcode(((opIndex==OP_PLUS)? INST_ADD : INST_SUB),
 			    envPtr);
@@ -597,7 +574,6 @@
 		    if (code != TCL_OK) {
 			goto done;
 		    }
-		    maxDepth = envPtr->maxStackDepth;
 		    tokenPtr = endPtr;
 		    break;
 			
@@ -607,7 +583,6 @@
 		    if (code != TCL_OK) {
 			goto done;
 		    }
-		    maxDepth = envPtr->maxStackDepth;
 		    tokenPtr = endPtr;
 		    break;
 		    
@@ -638,7 +613,6 @@
     }
     
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -657,9 +631,6 @@
  *	endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
  *	contains an error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the expression.
- *
  * Side effects:
  *	Adds instructions to envPtr to evaluate the expression at runtime.
  *
@@ -685,19 +656,18 @@
     				 /* Used to fix up jumps used to convert the
 				  * first operand to 0 or 1. */
     Tcl_Token *tokenPtr;
-    int dist, maxDepth, code;
+    int dist, code;
+    int savedStackDepth = envPtr->currStackDepth;
 
     /*
      * Emit code for the first operand.
      */
 
-    maxDepth = 0;
     tokenPtr = exprTokenPtr+2;
     code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
     if (code != TCL_OK) {
 	goto done;
     }
-    maxDepth = envPtr->maxStackDepth;
     tokenPtr += (tokenPtr->numComponents + 1);
 
     /*
@@ -713,6 +683,7 @@
         badDist:
 	panic("CompileLandOrLorExpr: bad jump distance %d\n", dist);
     }
+    envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "1", 1, /*onHeap*/ 0), envPtr);
     dist = (envPtr->codeNext - envPtr->codeStart) - lhsEndFixup.codeOffset;
     if (TclFixupForwardJump(envPtr, &lhsEndFixup, dist, 127)) {
@@ -738,7 +709,6 @@
     if (code != TCL_OK) {
 	goto done;
     }
-    maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
     tokenPtr += (tokenPtr->numComponents + 1);
 
     /*
@@ -760,7 +730,7 @@
     *endPtrPtr = tokenPtr;
 
     done:
-    envPtr->maxStackDepth = maxDepth;
+    envPtr->currStackDepth = savedStackDepth + 1;
     return code;
 }
 
@@ -779,9 +749,6 @@
  *	endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
  *	contains an error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the expression.
- *
  * Side effects:
  *	Adds instructions to envPtr to evaluate the expression at runtime.
  *
@@ -804,19 +771,18 @@
 				 * around the then and else expressions when
 				 * their target PCs are determined. */
     Tcl_Token *tokenPtr;
-    int elseCodeOffset, dist, maxDepth, code;
+    int elseCodeOffset, dist, code;
+    int savedStackDepth = envPtr->currStackDepth;
 
     /*
      * Emit code for the test.
      */
 
-    maxDepth = 0;
     tokenPtr = exprTokenPtr+2;
     code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
     if (code != TCL_OK) {
 	goto done;
     }
-    maxDepth = envPtr->maxStackDepth;
     tokenPtr += (tokenPtr->numComponents + 1);
     
     /*
@@ -837,7 +803,6 @@
     if (code != TCL_OK) {
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     tokenPtr += (tokenPtr->numComponents + 1);
     if (!infoPtr->hasOperators) {
 	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
@@ -854,13 +819,13 @@
      * Compile the "else" expression.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     elseCodeOffset = (envPtr->codeNext - envPtr->codeStart);
     infoPtr->hasOperators = 0;
     code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
     if (code != TCL_OK) {
 	goto done;
     }
-    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
     tokenPtr += (tokenPtr->numComponents + 1);
     if (!infoPtr->hasOperators) {
 	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
@@ -890,7 +855,7 @@
     *endPtrPtr = tokenPtr;
 
     done:
-    envPtr->maxStackDepth = maxDepth;
+    envPtr->currStackDepth = savedStackDepth + 1;
     return code;
 }
 
@@ -909,9 +874,6 @@
  *	endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
  *	contains an error message.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the function.
- *
  * Side effects:
  *	Adds instructions to envPtr to evaluate the math function at
  *	runtime.
@@ -936,14 +898,13 @@
     MathFunc *mathFuncPtr;
     Tcl_HashEntry *hPtr;
     Tcl_Token *tokenPtr, *afterSubexprPtr;
-    int maxDepth, code, i;
+    int code, i;
 
     /*
      * Look up the MathFunc record for the function.
      */
 
     code = TCL_OK;
-    maxDepth = 0;
     hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
     if (hPtr == NULL) {
 	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
@@ -960,7 +921,6 @@
     if (mathFuncPtr->builtinFuncIndex < 0) {
 	TclEmitPush(TclRegisterLiteral(envPtr, funcName, -1, /*onHeap*/ 0),
 	        envPtr);
-	maxDepth = 1;
     }
 
     /*
@@ -984,7 +944,6 @@
 		goto done;
 	    }
 	    tokenPtr += (tokenPtr->numComponents + 1);
-	    maxDepth++;
 	}
 	if (tokenPtr != afterSubexprPtr) {
 	    Tcl_ResetResult(interp);
@@ -1016,7 +975,6 @@
     *endPtrPtr = afterSubexprPtr;
 
     done:
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
diff -r -u generic/tclCompile.c generic/tclCompile.c
--- generic/tclCompile.c	Sun Dec  9 12:09:15 2001
+++ generic/tclCompile.c	Sun Dec  9 21:43:38 2001
@@ -53,218 +53,218 @@
  */
 
 InstructionDesc instructionTable[] = {
-   /* Name	      Bytes #Opnds Operand types	Stack top, next	  */
-    {"done",		  1,   0,   {OPERAND_NONE}},
+   /* Name	      Bytes stackEffect #Opnds Operand types	Stack top, next	  */
+    {"done",		  1,   -1,        0,   {OPERAND_NONE}},
 	/* Finish ByteCode execution and return stktop (top stack item) */
-    {"push1",		  2,   1,   {OPERAND_UINT1}},
+    {"push1",		  2,   +1,         1,   {OPERAND_UINT1}},
 	/* Push object at ByteCode objArray[op1] */
-    {"push4",		  5,   1,   {OPERAND_UINT4}},
+    {"push4",		  5,   +1,         1,   {OPERAND_UINT4}},
 	/* Push object at ByteCode objArray[op4] */
-    {"pop",		  1,   0,   {OPERAND_NONE}},
+    {"pop",		  1,   -1,        0,   {OPERAND_NONE}},
 	/* Pop the topmost stack object */
-    {"dup",		  1,   0,   {OPERAND_NONE}},
+    {"dup",		  1,   +1,         0,   {OPERAND_NONE}},
 	/* Duplicate the topmost stack object and push the result */
-    {"concat1",		  2,   1,   {OPERAND_UINT1}},
+    {"concat1",		  2,   INT_MIN,    1,   {OPERAND_UINT1}},
 	/* Concatenate the top op1 items and push result */
-    {"invokeStk1",	  2,   1,   {OPERAND_UINT1}},
+    {"invokeStk1",	  2,   INT_MIN,    1,   {OPERAND_UINT1}},
 	/* Invoke command named objv[0]; <objc,objv> = <op1,top op1> */
-    {"invokeStk4",	  5,   1,   {OPERAND_UINT4}},
+    {"invokeStk4",	  5,   INT_MIN,    1,   {OPERAND_UINT4}},
 	/* Invoke command named objv[0]; <objc,objv> = <op4,top op4> */
-    {"evalStk",		  1,   0,   {OPERAND_NONE}},
+    {"evalStk",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Evaluate command in stktop using Tcl_EvalObj. */
-    {"exprStk",		  1,   0,   {OPERAND_NONE}},
+    {"exprStk",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Execute expression in stktop using Tcl_ExprStringObj. */
     
-    {"loadScalar1",	  2,   1,   {OPERAND_UINT1}},
+    {"loadScalar1",	  2,   1,          1,   {OPERAND_UINT1}},
 	/* Load scalar variable at index op1 <= 255 in call frame */
-    {"loadScalar4",	  5,   1,   {OPERAND_UINT4}},
+    {"loadScalar4",	  5,   1,          1,   {OPERAND_UINT4}},
 	/* Load scalar variable at index op1 >= 256 in call frame */
-    {"loadScalarStk",	  1,   0,   {OPERAND_NONE}},
+    {"loadScalarStk",	  1,   0,          0,   {OPERAND_NONE}},
 	/* Load scalar variable; scalar's name is stktop */
-    {"loadArray1",	  2,   1,   {OPERAND_UINT1}},
+    {"loadArray1",	  2,   0,          1,   {OPERAND_UINT1}},
 	/* Load array element; array at slot op1<=255, element is stktop */
-    {"loadArray4",	  5,   1,   {OPERAND_UINT4}},
+    {"loadArray4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Load array element; array at slot op1 > 255, element is stktop */
-    {"loadArrayStk",	  1,   0,   {OPERAND_NONE}},
+    {"loadArrayStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Load array element; element is stktop, array name is stknext */
-    {"loadStk",		  1,   0,   {OPERAND_NONE}},
+    {"loadStk",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Load general variable; unparsed variable name is stktop */
-    {"storeScalar1",	  2,   1,   {OPERAND_UINT1}},
+    {"storeScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
 	/* Store scalar variable at op1<=255 in frame; value is stktop */
-    {"storeScalar4",	  5,   1,   {OPERAND_UINT4}},
+    {"storeScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Store scalar variable at op1 > 255 in frame; value is stktop */
-    {"storeScalarStk",	  1,   0,   {OPERAND_NONE}},
+    {"storeScalarStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Store scalar; value is stktop, scalar name is stknext */
-    {"storeArray1",	  2,   1,   {OPERAND_UINT1}},
+    {"storeArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
 	/* Store array element; array at op1<=255, value is top then elem */
-    {"storeArray4",	  5,   1,   {OPERAND_UINT4}},
+    {"storeArray4",	  5,   -1,          1,   {OPERAND_UINT4}},
 	/* Store array element; array at op1>=256, value is top then elem */
-    {"storeArrayStk",	  1,   0,   {OPERAND_NONE}},
+    {"storeArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
 	/* Store array element; value is stktop, then elem, array names */
-    {"storeStk",	  1,   0,   {OPERAND_NONE}},
+    {"storeStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Store general variable; value is stktop, then unparsed name */
     
-    {"incrScalar1",	  2,   1,   {OPERAND_UINT1}},
+    {"incrScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
 	/* Incr scalar at index op1<=255 in frame; incr amount is stktop */
-    {"incrScalarStk",	  1,   0,   {OPERAND_NONE}},
+    {"incrScalarStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Incr scalar; incr amount is stktop, scalar's name is stknext */
-    {"incrArray1",	  2,   1,   {OPERAND_UINT1}},
+    {"incrArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
 	/* Incr array elem; arr at slot op1<=255, amount is top then elem */
-    {"incrArrayStk",	  1,   0,   {OPERAND_NONE}},
+    {"incrArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
 	/* Incr array element; amount is top then elem then array names */
-    {"incrStk",		  1,   0,   {OPERAND_NONE}},
+    {"incrStk",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Incr general variable; amount is stktop then unparsed var name */
-    {"incrScalar1Imm",	  3,   2,   {OPERAND_UINT1, OPERAND_INT1}},
+    {"incrScalar1Imm",	  3,   +1,         2,   {OPERAND_UINT1, OPERAND_INT1}},
 	/* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */
-    {"incrScalarStkImm",  2,   1,   {OPERAND_INT1}},
+    {"incrScalarStkImm",  2,   0,          1,   {OPERAND_INT1}},
 	/* Incr scalar; scalar name is stktop; incr amount is op1 */
-    {"incrArray1Imm",	  3,   2,   {OPERAND_UINT1, OPERAND_INT1}},
+    {"incrArray1Imm",	  3,   0,         2,   {OPERAND_UINT1, OPERAND_INT1}},
 	/* Incr array elem; array at slot op1 <= 255, elem is stktop,
 	 * amount is 2nd operand byte */
-    {"incrArrayStkImm",	  2,   1,   {OPERAND_INT1}},
+    {"incrArrayStkImm",	  2,   -1,         1,   {OPERAND_INT1}},
 	/* Incr array element; elem is top then array name, amount is op1 */
-    {"incrStkImm",	  2,   1,   {OPERAND_INT1}},
+    {"incrStkImm",	  2,   0,         1,   {OPERAND_INT1}},
 	/* Incr general variable; unparsed name is top, amount is op1 */
     
-    {"jump1",		  2,   1,   {OPERAND_INT1}},
+    {"jump1",		  2,   0,          1,   {OPERAND_INT1}},
 	/* Jump relative to (pc + op1) */
-    {"jump4",		  5,   1,   {OPERAND_INT4}},
+    {"jump4",		  5,   0,          1,   {OPERAND_INT4}},
 	/* Jump relative to (pc + op4) */
-    {"jumpTrue1",	  2,   1,   {OPERAND_INT1}},
+    {"jumpTrue1",	  2,   -1,         1,   {OPERAND_INT1}},
 	/* Jump relative to (pc + op1) if stktop expr object is true */
-    {"jumpTrue4",	  5,   1,   {OPERAND_INT4}},
+    {"jumpTrue4",	  5,   -1,         1,   {OPERAND_INT4}},
 	/* Jump relative to (pc + op4) if stktop expr object is true */
-    {"jumpFalse1",	  2,   1,   {OPERAND_INT1}},
+    {"jumpFalse1",	  2,   -1,         1,   {OPERAND_INT1}},
 	/* Jump relative to (pc + op1) if stktop expr object is false */
-    {"jumpFalse4",	  5,   1,   {OPERAND_INT4}},
+    {"jumpFalse4",	  5,   -1,         1,   {OPERAND_INT4}},
 	/* Jump relative to (pc + op4) if stktop expr object is false */
 
-    {"lor",		  1,   0,   {OPERAND_NONE}},
+    {"lor",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Logical or:	push (stknext || stktop) */
-    {"land",		  1,   0,   {OPERAND_NONE}},
+    {"land",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Logical and:	push (stknext && stktop) */
-    {"bitor",		  1,   0,   {OPERAND_NONE}},
+    {"bitor",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Bitwise or:	push (stknext | stktop) */
-    {"bitxor",		  1,   0,   {OPERAND_NONE}},
+    {"bitxor",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Bitwise xor	push (stknext ^ stktop) */
-    {"bitand",		  1,   0,   {OPERAND_NONE}},
+    {"bitand",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Bitwise and:	push (stknext & stktop) */
-    {"eq",		  1,   0,   {OPERAND_NONE}},
+    {"eq",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Equal:	push (stknext == stktop) */
-    {"neq",		  1,   0,   {OPERAND_NONE}},
+    {"neq",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Not equal:	push (stknext != stktop) */
-    {"lt",		  1,   0,   {OPERAND_NONE}},
+    {"lt",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Less:	push (stknext < stktop) */
-    {"gt",		  1,   0,   {OPERAND_NONE}},
+    {"gt",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Greater:	push (stknext || stktop) */
-    {"le",		  1,   0,   {OPERAND_NONE}},
+    {"le",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Logical or:	push (stknext || stktop) */
-    {"ge",		  1,   0,   {OPERAND_NONE}},
+    {"ge",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Logical or:	push (stknext || stktop) */
-    {"lshift",		  1,   0,   {OPERAND_NONE}},
+    {"lshift",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Left shift:	push (stknext << stktop) */
-    {"rshift",		  1,   0,   {OPERAND_NONE}},
+    {"rshift",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Right shift:	push (stknext >> stktop) */
-    {"add",		  1,   0,   {OPERAND_NONE}},
+    {"add",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Add:		push (stknext + stktop) */
-    {"sub",		  1,   0,   {OPERAND_NONE}},
+    {"sub",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Sub:		push (stkext - stktop) */
-    {"mult",		  1,   0,   {OPERAND_NONE}},
+    {"mult",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Multiply:	push (stknext * stktop) */
-    {"div",		  1,   0,   {OPERAND_NONE}},
+    {"div",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Divide:	push (stknext / stktop) */
-    {"mod",		  1,   0,   {OPERAND_NONE}},
+    {"mod",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Mod:		push (stknext % stktop) */
-    {"uplus",		  1,   0,   {OPERAND_NONE}},
+    {"uplus",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Unary plus:	push +stktop */
-    {"uminus",		  1,   0,   {OPERAND_NONE}},
+    {"uminus",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Unary minus:	push -stktop */
-    {"bitnot",		  1,   0,   {OPERAND_NONE}},
+    {"bitnot",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Bitwise not:	push ~stktop */
-    {"not",		  1,   0,   {OPERAND_NONE}},
+    {"not",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Logical not:	push !stktop */
-    {"callBuiltinFunc1",  2,   1,   {OPERAND_UINT1}},
+    {"callBuiltinFunc1",  2,   1,          1,   {OPERAND_UINT1}},
 	/* Call builtin math function with index op1; any args are on stk */
-    {"callFunc1",	  2,   1,   {OPERAND_UINT1}},
+    {"callFunc1",	  2,   INT_MIN,    1,   {OPERAND_UINT1}},
 	/* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1>  */
-    {"tryCvtToNumeric",	  1,   0,   {OPERAND_NONE}},
+    {"tryCvtToNumeric",	  1,   0,          0,   {OPERAND_NONE}},
 	/* Try converting stktop to first int then double if possible. */
 
-    {"break",		  1,   0,   {OPERAND_NONE}},
+    {"break",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Abort closest enclosing loop; if none, return TCL_BREAK code. */
-    {"continue",	  1,   0,   {OPERAND_NONE}},
+    {"continue",	  1,   0,          0,   {OPERAND_NONE}},
 	/* Skip to next iteration of closest enclosing loop; if none,
 	 * return TCL_CONTINUE code. */
 
-    {"foreach_start4",	  5,   1,   {OPERAND_UINT4}},
+    {"foreach_start4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Initialize execution of a foreach loop. Operand is aux data index
 	 * of the ForeachInfo structure for the foreach command. */
-    {"foreach_step4",	  5,   1,   {OPERAND_UINT4}},
+    {"foreach_step4",	  5,   +1,         1,   {OPERAND_UINT4}},
 	/* "Step" or begin next iteration of foreach loop. Push 0 if to
 	 *  terminate loop, else push 1. */
 
-    {"beginCatch4",	  5,   1,   {OPERAND_UINT4}},
+    {"beginCatch4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Record start of catch with the operand's exception index.
 	 * Push the current stack depth onto a special catch stack. */
-    {"endCatch",	  1,   0,   {OPERAND_NONE}},
+    {"endCatch",	  1,   0,          0,   {OPERAND_NONE}},
 	/* End of last catch. Pop the bytecode interpreter's catch stack. */
-    {"pushResult",	  1,   0,   {OPERAND_NONE}},
+    {"pushResult",	  1,   +1,         0,   {OPERAND_NONE}},
 	/* Push the interpreter's object result onto the stack. */
-    {"pushReturnCode",	  1,   0,   {OPERAND_NONE}},
+    {"pushReturnCode",	  1,   +1,         0,   {OPERAND_NONE}},
 	/* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as
 	 * a new object onto the stack. */
-    {"streq",		  1,   0,   {OPERAND_NONE}},
+    {"streq",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Str Equal:	push (stknext eq stktop) */
-    {"strneq",		  1,   0,   {OPERAND_NONE}},
+    {"strneq",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Str !Equal:	push (stknext neq stktop) */
-    {"strcmp",		  1,   0,   {OPERAND_NONE}},
+    {"strcmp",		  1,   -1,         0,   {OPERAND_NONE}},
 	/* Str Compare:	push (stknext cmp stktop) */
-    {"strlen",		  1,   0,   {OPERAND_NONE}},
+    {"strlen",		  1,   0,          0,   {OPERAND_NONE}},
 	/* Str Length:	push (strlen stktop) */
-    {"strindex",	  1,   0,   {OPERAND_NONE}},
+    {"strindex",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Str Index:	push (strindex stknext stktop) */
-    {"strmatch",	  2,   1,   {OPERAND_INT1}},
+    {"strmatch",	  2,   -1,         1,   {OPERAND_INT1}},
 	/* Str Match:	push (strmatch stknext stktop) opnd == nocase */
-    {"list",		  5,   1,   {OPERAND_UINT4}},
+    {"list",		  5,   INT_MIN,    1,   {OPERAND_UINT4}},
 	/* List:	push (stk1 stk2 ... stktop) */
-    {"listindex",	  1,   0,   {OPERAND_NONE}},
+    {"listindex",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* List Index:	push (listindex stknext stktop) */
-    {"listlength",	  1,   0,   {OPERAND_NONE}},
+    {"listlength",	  1,   0,          0,   {OPERAND_NONE}},
 	/* List Len:	push (listlength stktop) */
-    {"appendScalar1",	  2,   1,   {OPERAND_UINT1}},
+    {"appendScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
 	/* Append scalar variable at op1<=255 in frame; value is stktop */
-    {"appendScalar4",	  5,   1,   {OPERAND_UINT4}},
+    {"appendScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Append scalar variable at op1 > 255 in frame; value is stktop */
-    {"appendArray1",	  2,   1,   {OPERAND_UINT1}},
+    {"appendArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
 	/* Append array element; array at op1<=255, value is top then elem */
-    {"appendArray4",	  5,   1,   {OPERAND_UINT4}},
+    {"appendArray4",	  5,   -1,         1,   {OPERAND_UINT4}},
 	/* Append array element; array at op1>=256, value is top then elem */
-    {"appendArrayStk",	  1,   0,   {OPERAND_NONE}},
+    {"appendArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
 	/* Append array element; value is stktop, then elem, array names */
-    {"appendStk",	  1,   0,   {OPERAND_NONE}},
+    {"appendStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Append general variable; value is stktop, then unparsed name */
-    {"lappendScalar1",	  2,   1,   {OPERAND_UINT1}},
+    {"lappendScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
 	/* Lappend scalar variable at op1<=255 in frame; value is stktop */
-    {"lappendScalar4",	  5,   1,   {OPERAND_UINT4}},
+    {"lappendScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
 	/* Lappend scalar variable at op1 > 255 in frame; value is stktop */
-    {"lappendArray1",	  2,   1,   {OPERAND_UINT1}},
+    {"lappendArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
 	/* Lappend array element; array at op1<=255, value is top then elem */
-    {"lappendArray4",	  5,   1,   {OPERAND_UINT4}},
+    {"lappendArray4",	  5,   -1,         1,   {OPERAND_UINT4}},
 	/* Lappend array element; array at op1>=256, value is top then elem */
-    {"lappendArrayStk",	  1,   0,   {OPERAND_NONE}},
+    {"lappendArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
 	/* Lappend array element; value is stktop, then elem, array names */
-    {"lappendStk",	  1,   0,   {OPERAND_NONE}},
+    {"lappendStk",	  1,   -1,         0,   {OPERAND_NONE}},
 	/* Lappend general variable; value is stktop, then unparsed name */
-    {"lindexMulti",	  5,   1,   {OPERAND_UINT4}},
+    {"lindexMulti",	  5,   INT_MIN,   1,   {OPERAND_UINT4}},
         /* Lindex with generalized args, operand is number of indices.
          * (operand) entries from stktop are the indices; then list to
          * process. */
-    {"over",		  5,   1,   {OPERAND_UINT4}},
+    {"over",		  5,   +1,         1,   {OPERAND_UINT4}},
         /* Duplicate the arg-th element from top of stack (TOS=0) */
-    {"lsetList",          1,   0,   {OPERAND_NONE}},
+    {"lsetList",          1,   -2,         0,   {OPERAND_NONE}},
         /* Four-arg version of 'lset'. stktop is old value; next is
          * new element value, next is the index list; pushes new value */
-    {"lsetFlat",          5,   1,   {OPERAND_UINT4}},
+    {"lsetFlat",          5,   INT_MIN,   1,   {OPERAND_UINT4}},
         /* Three- or >=5-arg version of 'lset'. stktop is old value,
          * next is new element value; next come objc-2 indices; pushes
 	 * the new value.
@@ -702,6 +702,7 @@
     envPtr->exceptDepth = 0;
     envPtr->maxExceptDepth = 0;
     envPtr->maxStackDepth = 0;
+    envPtr->currStackDepth = 0;
     TclInitLiteralTable(&(envPtr->localLitTable));
     envPtr->exprIsJustVarRef = 0;
     envPtr->exprIsComparison = 0;
@@ -789,8 +790,6 @@
  *	interp->termOffset is set to the offset of the character in the
  *	script just after the last one successfully processed; this will be
  *	the offset of the ']' if (flags & TCL_BRACKET_TERM).
- *	envPtr->maxStackDepth is set to the maximum number of stack elements
- *	needed to execute the script's commands.
  *
  * Side effects:
  *	Adds instructions to envPtr to evaluate the script at runtime.
@@ -813,8 +812,6 @@
 {
     Interp *iPtr = (Interp *) interp;
     Tcl_Parse parse;
-    int maxDepth = 0;		/* Maximum number of stack elements needed
-				 * to execute all cmds. */
     int lastTopLevelCmdIndex = -1;
     				/* Index of most recent toplevel command in
  				 * the command location table. Initialized
@@ -955,8 +952,6 @@
 			    code = (*(cmdPtr->compileProc))(interp, &parse,
 			            envPtr);
 			    if (code == TCL_OK) {
-				maxDepth = TclMax(envPtr->maxStackDepth,
-			                maxDepth);
 				goto finishCommand;
 			    } else if (code == TCL_OUT_LINE_COMPILE) {
 				/* do nothing */
@@ -992,7 +987,6 @@
 				/*onHeap*/ 0);
 		    }
 		    TclEmitPush(objIndex, envPtr);
-		    maxDepth = TclMax((wordIdx + 1), maxDepth);
 		} else {
 		    /*
 		     * The word is not a simple string of characters.
@@ -1003,8 +997,6 @@
 		    if (code != TCL_OK) {
 			goto error;
 		    }
-		    maxDepth = TclMax((wordIdx + envPtr->maxStackDepth),
-			   maxDepth);
 		}
 	    }
 
@@ -1060,7 +1052,6 @@
     if (envPtr->codeNext == entryCodeNext) {
 	TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0),
 	        envPtr);
-	maxDepth = 1;
     }
     
     if ((nested != 0) && (p > script) && (p[-1] == ']')) {
@@ -1068,7 +1059,6 @@
     } else {
 	iPtr->termOffset = (p - script);
     }
-    envPtr->maxStackDepth = maxDepth;
     Tcl_DStringFree(&ds);
     return TCL_OK;
 	
@@ -1101,7 +1091,6 @@
 	Tcl_FreeParse(&parse);
     }
     iPtr->termOffset = (p - script);
-    envPtr->maxStackDepth = maxDepth;
     Tcl_DStringFree(&ds);
     return code;
 }
@@ -1120,9 +1109,6 @@
  *	The return value is a standard Tcl result. If an error occurs, an
  *	error message is left in the interpreter's result.
  *	
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to evaluate the tokens.
- *
  * Side effects:
  *	Instructions are added to envPtr to push and evaluate the tokens
  *	at runtime.
@@ -1144,11 +1130,10 @@
     char buffer[TCL_UTF_MAX];
     char *name, *p;
     int numObjsToConcat, nameBytes, hasNsQualifiers, localVar;
-    int length, maxDepth, depthForVar, i, code;
+    int length, i, code;
     unsigned char *entryCodeNext = envPtr->codeNext;
 
     Tcl_DStringInit(&textBuffer);
-    maxDepth = 0;
     numObjsToConcat = 0;
     for ( ;  count > 0;  count--, tokenPtr++) {
 	switch (tokenPtr->type) {
@@ -1176,7 +1161,6 @@
 			    Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
 		    TclEmitPush(literal, envPtr);
 		    numObjsToConcat++;
-		    maxDepth = TclMax(numObjsToConcat, maxDepth);
 		    Tcl_DStringFree(&textBuffer);
 		}
 		
@@ -1185,8 +1169,6 @@
 		if (code != TCL_OK) {
 		    goto error;
 		}
-		maxDepth = TclMax((numObjsToConcat + envPtr->maxStackDepth),
-		        maxDepth);
 		numObjsToConcat++;
 		break;
 
@@ -1203,7 +1185,6 @@
 			    Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
 		    TclEmitPush(literal, envPtr);
 		    numObjsToConcat++;
-		    maxDepth = TclMax(numObjsToConcat, maxDepth);
 		    Tcl_DStringFree(&textBuffer);
 		}
 		
@@ -1227,19 +1208,16 @@
 		 * the array of local variables in a procedure frame.
 		 */
 
-		depthForVar = 0;
 		if ((envPtr->procPtr == NULL) || hasNsQualifiers) {
 		    localVar = -1;
 		    TclEmitPush(TclRegisterLiteral(envPtr, name, nameBytes,
 		            /*onHeap*/ 0), envPtr);
-		    depthForVar = 1;
 		} else {
 		    localVar = TclFindCompiledLocal(name, nameBytes, 
 			    /*create*/ 0, /*flags*/ 0, envPtr->procPtr);
 		    if (localVar < 0) {
 			TclEmitPush(TclRegisterLiteral(envPtr, name,
 			        nameBytes, /*onHeap*/ 0), envPtr); 
-			depthForVar = 1;
 		    }
 		}
 
@@ -1267,7 +1245,6 @@
 			Tcl_AddObjErrorInfo(interp, buffer, -1);
 			goto error;
 		    }
-		    depthForVar += envPtr->maxStackDepth;
 		    if (localVar < 0) {
 			TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
 		    } else if (localVar <= 255) {
@@ -1278,7 +1255,6 @@
 			        envPtr);
 		    }
 		}
-		maxDepth = TclMax(numObjsToConcat + depthForVar, maxDepth);
 		numObjsToConcat++;
 		count -= tokenPtr->numComponents;
 		tokenPtr += tokenPtr->numComponents;
@@ -1300,7 +1276,6 @@
 	        Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
 	TclEmitPush(literal, envPtr);
 	numObjsToConcat++;
-	maxDepth = TclMax(numObjsToConcat, maxDepth);
     }
 
     /*
@@ -1322,15 +1297,12 @@
     if (envPtr->codeNext == entryCodeNext) {
 	TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0),
 	        envPtr);
-	maxDepth = 1;
     }
     Tcl_DStringFree(&textBuffer);
-    envPtr->maxStackDepth = maxDepth;
     return TCL_OK;
 
     error:
     Tcl_DStringFree(&textBuffer);
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -1349,9 +1321,6 @@
  *	The return value is a standard Tcl result. If an error occurs, an
  *	error message is left in the interpreter's result.
  *	
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the tokens.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the tokens at runtime.
  *
@@ -1374,7 +1343,6 @@
      * into an inline sequence of instructions.
      */
     
-    envPtr->maxStackDepth = 0;
     if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) {
 	code = TclCompileScript(interp, tokenPtr->start, tokenPtr->size,
 	        /*nested*/ 0, envPtr);
@@ -1410,9 +1378,6 @@
  *	The return value is a standard Tcl result. If an error occurs, an
  *	error message is left in the interpreter's result.
  *	
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the expression.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute the expression.
  *
@@ -1431,13 +1396,11 @@
     CompileEnv *envPtr;		/* Holds the resulting instructions. */
 {
     Tcl_Token *wordPtr;
-    int maxDepth, range, numBytes, i, code;
+    int range, numBytes, i, code;
     char *script;
     int saveExprIsJustVarRef = envPtr->exprIsJustVarRef;
     int saveExprIsComparison = envPtr->exprIsComparison;
 
-    envPtr->maxStackDepth = 0;
-    maxDepth = 0;
     range = -1;
     code = TCL_OK;
 
@@ -1473,9 +1436,6 @@
 	if (i < (numWords - 1)) {
 	    TclEmitPush(TclRegisterLiteral(envPtr, " ", 1, /*onHeap*/ 0),
 	            envPtr);
-	    maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
-	} else {
-	    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
 	}
 	wordPtr += (wordPtr->numComponents + 1);
     }
@@ -1493,7 +1453,6 @@
 
     envPtr->exprIsJustVarRef = saveExprIsJustVarRef;
     envPtr->exprIsComparison = saveExprIsComparison;
-    envPtr->maxStackDepth = maxDepth;
     return code;
 }
 
@@ -1585,7 +1544,7 @@
     codePtr->numCmdLocBytes = cmdLocBytes;
     codePtr->maxExceptDepth = envPtr->maxExceptDepth;
     codePtr->maxStackDepth = envPtr->maxStackDepth;
-    
+
     p += sizeof(ByteCode);
     codePtr->codeStart = p;
     memcpy((VOID *) p, (VOID *) envPtr->codeStart, (size_t) codeBytes);
diff -r -u generic/tclCompile.h generic/tclCompile.h
--- generic/tclCompile.h	Sun Dec  9 12:09:15 2001
+++ generic/tclCompile.h	Sun Dec  9 21:39:48 2001
@@ -217,6 +217,7 @@
     int maxStackDepth;		/* Maximum number of stack elements needed
 				 * to execute the code. Set by compilation
 				 * procedures before returning. */
+    int currStackDepth;         /* Current stack depth. */
     LiteralTable localLitTable;	/* Contains LiteralEntry's describing
 				 * all Tcl objects referenced by this
 				 * compiled code. Indexed by the string
@@ -564,6 +565,12 @@
 typedef struct InstructionDesc {
     char *name;			/* Name of instruction. */
     int numBytes;		/* Total number of bytes for instruction. */
+    int stackEffect;            /* The worst-case balance stack effect of the 
+				 * instruction, used for stack requirements 
+				 * computations. The value INT_MIN signals
+				 * that the instruction's worst case effect
+				 * is (1-opnd1).
+				 */
     int numOperands;		/* Number of operands. */
     InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
 				/* The type of each operand. */
@@ -838,6 +845,37 @@
  */
 
 /*
+ * Macro used to update the stack requirements.
+ * It is called by the macros TclEmitOpCode, TclEmitInst1 and
+ * TclEmitInst4.
+ * Remark that the very last instruction of a bytecode always
+ * reduces the stack level: INST_DONE or INST_POP, so that the 
+ * maxStackdepth is always updated.
+ */
+
+#define TclUpdateStackReqs(op, i, envPtr) \
+    {\
+	int delta = instructionTable[(op)].stackEffect;\
+	if (delta) {\
+	    if (delta < 0) {\
+		if((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {\
+		    (envPtr)->maxStackDepth = (envPtr)->currStackDepth;\
+		}\
+		if (delta == INT_MIN) {\
+		    delta = 1 - (i);\
+		}\
+	    }\
+	    (envPtr)->currStackDepth += delta;\
+	}\
+    }
+/*    
+        if ((envPtr)->currStackDepth < 0) {\
+	fprintf(stderr, "(%i, %i, %i)\n", op, delta, (envPtr)->currStackDepth);\
+	panic("");\
+	}\ 
+*/
+
+/*
  * Macro to emit an opcode byte into a CompileEnv's code array.
  * The ANSI C "prototype" for this macro is:
  *
@@ -848,7 +886,8 @@
 #define TclEmitOpcode(op, envPtr) \
     if ((envPtr)->codeNext == (envPtr)->codeEnd) \
         TclExpandCodeArray(envPtr); \
-    *(envPtr)->codeNext++ = (unsigned char) (op)
+    *(envPtr)->codeNext++ = (unsigned char) (op);\
+    TclUpdateStackReqs(op, 0, envPtr)
 
 /*
  * Macro to emit an integer operand.
@@ -874,12 +913,14 @@
  *		    CompileEnv *envPtr));
  */
 
+
 #define TclEmitInstInt1(op, i, envPtr) \
     if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \
         TclExpandCodeArray(envPtr); \
     } \
     *(envPtr)->codeNext++ = (unsigned char) (op); \
-    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
+    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i));\
+    TclUpdateStackReqs(op, i, envPtr)
 
 #define TclEmitInstInt4(op, i, envPtr) \
     if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \
@@ -893,7 +934,8 @@
     *(envPtr)->codeNext++ = \
         (unsigned char) ((unsigned int) (i) >>  8); \
     *(envPtr)->codeNext++ = \
-        (unsigned char) ((unsigned int) (i)      )
+        (unsigned char) ((unsigned int) (i)      );\
+    TclUpdateStackReqs(op, i, envPtr)
     
 /*
  * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
@@ -1006,3 +1048,8 @@
 # define TCL_STORAGE_CLASS DLLIMPORT
 
 #endif /* _TCLCOMPILATION */
+
+
+
+
+
diff -r -u generic/tclExecute.c generic/tclExecute.c
--- generic/tclExecute.c	Sun Dec  9 12:09:15 2001
+++ generic/tclExecute.c	Sun Dec  9 21:46:07 2001
@@ -268,8 +268,7 @@
 static char *		StringForResultCode _ANSI_ARGS_((int result));
 static void		ValidatePcAndStackTop _ANSI_ARGS_((
 			    ByteCode *codePtr, unsigned char *pc,
-			    int stackTop, int stackLowerBound,
-			    int stackUpperBound));
+			    int stackTop, int stackLowerBound));
 #endif
 static int		VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
 			    Tcl_Obj *objPtr));
@@ -1049,8 +1048,7 @@
 
     for (;;) {
 #ifdef TCL_COMPILE_DEBUG
-	ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop,
-		eePtr->stackEnd);
+	ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop);
         if (traceInstructions) {
             fprintf(stdout, "%2d: %2d ", iPtr->numLevels, stackTop);
             TclPrintInstruction(codePtr, pc);
@@ -4090,8 +4088,7 @@
 
 #ifdef TCL_COMPILE_DEBUG
 static void
-ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound,
-        stackUpperBound)
+ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound)
     register ByteCode *codePtr; /* The bytecode whose summary is printed
 				 * to stdout. */
     unsigned char *pc;		/* Points to first byte of a bytecode
@@ -4100,8 +4097,9 @@
 				 * stackLowerBound and stackUpperBound
 				 * (inclusive). */
     int stackLowerBound;	/* Smallest legal value for stackTop. */
-    int stackUpperBound;	/* Greatest legal value for stackTop. */
 {
+    int stackUpperBound = stackLowerBound +  codePtr->maxStackDepth;	
+                                /* Greatest legal value for stackTop. */
     unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
     unsigned int codeStart = (unsigned int) codePtr->codeStart;
     unsigned int codeEnd = (unsigned int)
@@ -4116,15 +4114,15 @@
     if ((unsigned int) opCode > LAST_INST_OPCODE) {
 	fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
 		(unsigned int) opCode, relativePc);
-	panic("TclExecuteByteCode execution failure: bad opcode");
+        panic("TclExecuteByteCode execution failure: bad opcode");
     }
     if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
 	int numChars;
 	char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
 	char *ellipsis = "";
 	
-	fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode",
-		stackTop, relativePc);
+	fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode (min %i, max %i)",
+		stackTop, relativePc, stackLowerBound, stackUpperBound);
 	if (cmd != NULL) {
 	    if (numChars > 100) {
 		numChars = 100;
diff -r -u generic/tclProc.c generic/tclProc.c
--- generic/tclProc.c	Sun Dec  9 12:09:15 2001
+++ generic/tclProc.c	Sun Dec  9 19:43:20 2001
@@ -1656,9 +1656,6 @@
  * Results:
  *	The return value is TCL_OK, indicating successful compilation.
  *
- *	envPtr->maxStackDepth is updated with the maximum number of stack
- *	elements needed to execute the command.
- *
  * Side effects:
  *	Instructions are added to envPtr to execute a noOp at runtime.
  *
@@ -1674,11 +1671,13 @@
 {
     Tcl_Token *tokenPtr;
     int i, code;
+    int savedStackDepth = envPtr->currStackDepth;
 
-    envPtr->maxStackDepth = 1;
     tokenPtr = parsePtr->tokenPtr;
     for(i = 1; i < parsePtr->numWords; i++) {
 	tokenPtr = tokenPtr + tokenPtr->numComponents + 1;
+	envPtr->currStackDepth = savedStackDepth;
+
 	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { 
 	    code = TclCompileTokens(interp, tokenPtr+1,
 	            tokenPtr->numComponents, envPtr);
@@ -1688,6 +1687,7 @@
 	    TclEmitOpcode(INST_POP, envPtr);
 	} 
     }
+    envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
     return TCL_OK;
 }