summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2001-12-03 18:23:12 (GMT)
committerandreas_kupries <akupries@shaw.ca>2001-12-03 18:23:12 (GMT)
commit546058a1d386adc014fece9653fe8faa2356ab0e (patch)
treefcda7c74f28b052e8f84593ebd2c05b1f09a3418
parent90daebad86c36a4a83ff0831078e6f8351d9e9e6 (diff)
downloadtcl-546058a1d386adc014fece9653fe8faa2356ab0e.zip
tcl-546058a1d386adc014fece9653fe8faa2356ab0e.tar.gz
tcl-546058a1d386adc014fece9653fe8faa2356ab0e.tar.bz2
NRE1 patch by Miguel Sofer. Several new controlling
macros for information on the stack. Parser information on the stack can now be switched to allocation on the heap.
-rw-r--r--ChangeLog24
-rw-r--r--NOTES98
-rw-r--r--generic/tcl.h65
-rw-r--r--generic/tclBasic.c487
-rw-r--r--generic/tclCmdAH.c8
-rw-r--r--generic/tclCmdIL.c6
-rw-r--r--generic/tclCompCmds.c40
-rw-r--r--generic/tclCompExpr.c17
-rw-r--r--generic/tclCompile.c80
-rw-r--r--generic/tclExecute.c1334
-rw-r--r--generic/tclHash.c4
-rw-r--r--generic/tclListObj.c4
-rw-r--r--generic/tclLiteral.c4
-rw-r--r--generic/tclParse.c126
-rw-r--r--generic/tclParseExpr.c38
-rw-r--r--generic/tclProc.c284
-rw-r--r--generic/tclResult.c7
-rw-r--r--generic/tclScan.c7
-rw-r--r--generic/tclStringObj.c7
-rw-r--r--generic/tclUtil.c4
20 files changed, 1695 insertions, 949 deletions
diff --git a/ChangeLog b/ChangeLog
index e082178..d255a2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2001-12-03 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * NOTES:
+ * tcl.h:
+ * tclBasic.c:
+ * tclCmdAH.c:
+ * tclCmdIL.c:
+ * tclCompCmds.c:
+ * tclCompExpr.c:
+ * tclCompile.c:
+ * tclExecute.c:
+ * tclHash.c:
+ * tclListObj.c:
+ * tclLiteral.c:
+ * tclParse.c:
+ * tclParseExpr.c:
+ * tclProc.c:
+ * tclResult.c:
+ * tclScan.c:
+ * tclStringObj.c:
+ * tclUtil.c: NRE1 patch by Miguel Sofer. Several new controlling
+ macros for information on the stack. Parser information on the
+ stack can now be switched to allocation on the heap.
+
2001-11-28 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* NOTES: New file. Read here about the new modularization macros,
diff --git a/NOTES b/NOTES
index 1f6f5ef..950c661 100644
--- a/NOTES
+++ b/NOTES
@@ -151,3 +151,101 @@ Future:
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
+
+Cut 2, Working on the stacksize.
+
+* Spliced the NRE1 engine by Miguel Sofer into
+ the core. Stack testing the testsuite show
+ an average saving of 4 K stack space.
+
+* Reducing amount of characters directly stored in
+ a DString structure from 200 to 1. Average
+ savings when going through testsuite:
+
+* Going through #defines in headers and sources
+ to identify more locations placing data on the
+ stack.
+
+New controlling macros.
+
+#define TCL_NO_RECURSE /* enables the NRE modifications */
+ set by default
+
+Tcl_ExternalToUtfDString is in trouble for TCL_DSTRING_STATIC_SIZE=1 I
+guess TDSS < UTF_MAX is trouble because the function does not check
+before attempting the first conversion. ... Ok, SZ=25 is ok for the
+testsuite. This doesn't mean that it is ok in real life, but encoding
+is cut of for cisco, so we can screw this here. Keep in mind for
+later.
+
+1,4,5,10,17 fail
+21,25 ok
+
+
+#define TCL_FMT_STATIC_FLOATBUFFER_SZ 320
+#define TCL_FMT_STATIC_VALIDATE_LIST 16
+#define TCL_FOREACH_STATIC_ARGS 9
+#define TCL_FOREACH_STATIC_LIST_SZ 4
+#define TCL_FOREACH_STATIC_VARLIST_SZ 5
+#define TCL_RESULT_APPEND_STATIC_LIST_SZ 16
+#define TCL_MERGE_STATIC_LIST_SZ 20
+#define TCL_PROC_STATIC_CLOCALS 20
+#define TCL_PROC_STATIC_ARGS 20
+#define TCL_INVOKE_STATIC_ARGS 20
+#define TCL_EVAL_STATIC_VARCHARS 30
+#define TCL_STATS_COUNTERS 10
+#define TCL_LSORT_STATIC_MERGE_BUCKETS 30
+
+-DTCL_FMT_STATIC_FLOATBUFFER_SZ=320 -DTCL_FMT_STATIC_VALIDATE_LIST=16 -DTCL_FOREACH_STATIC_ARGS=9 -DTCL_FOREACH_STATIC_LIST_SZ=4 -DTCL_FOREACH_STATIC_VARLIST_SZ=5 -DTCL_RESULT_APPEND_STATIC_LIST_SZ=16 -DTCL_MERGE_STATIC_LIST_SZ=20 -DTCL_PROC_STATIC_CLOCALS=20 -DTCL_PROC_STATIC_ARGS=20 -DTCL_INVOKE_STATIC_ARGS=20 -DTCL_EVAL_STATIC_VARCHARS=30 -DTCL_STATS_COUNTERS=10 -DTCL_LSORT_STATIC_MERGE_BUCKETS=30
+
+cut_dstring ...
+-DTCL_FMT_STATIC_FLOATBUFFER_SZ=0 -DTCL_FMT_STATIC_VALIDATE_LIST=0 -DTCL_FOREACH_STATIC_ARGS=0 -DTCL_FOREACH_STATIC_LIST_SZ=0 -DTCL_FOREACH_STATIC_VARLIST_SZ=0 -DTCL_RESULT_APPEND_STATIC_LIST_SZ=0 -DTCL_MERGE_STATIC_LIST_SZ=0 -DTCL_PROC_STATIC_CLOCALS=0 -DTCL_PROC_STATIC_ARGS=0 -DTCL_INVOKE_STATIC_ARGS=0 -DTCL_EVAL_STATIC_VARCHARS=0 -DTCL_STATS_COUNTERS=0 -DTCL_LSORT_STATIC_MERGE_BUCKETS=0
+
+------------------------------------------------------
+General look through the code for static buffers
+on the stack.
+
+tclAlloc /ok
+tclAsync /ok
+tclBasic Tcl_CallWhenDeleted 32+INT_SPACE
+ Tcl_ExprString TCL_DOUBLE_SPACE
+tclBinary /ok
+tclClock /ok
+tclCmdAH StoreStatData TCL_INTEGER_SPACE
+ Tcl_FormatObjCmd
+
+...(Obj)Cmd functions often hold quite a lot of state in local
+variables.
+
+For exact measurements we have to instrument the C code with
+additional (macroized) function calls to record exact sizes for every
+invoked C function. Automatic instrumentation is difficult. Could
+instrument the dispatchers first (where commands are invoked) to get
+stack sizes for bigger blocks of execution (command + utility
+functionality called by it).
+
+-----------------------------------------------------------------------------------------------
+
+A big structure is 'CompileEnv'. Instead of trying to reduce its size
+it might be better to allocate the whole structure of the heap.
+
+#define TCL_COMPENV_ON_HEAP /* Allocate temp. CompileEnv structs off the heap */
+
+Stack measure
+ @ TclSetByteCodeFromAny ../../src/tcl834_stkr/unix/../generic/tclCompile.c 300 = 2036
+ @ TclCompileByteCodesForExpr ../../src/tcl834_stkr/unix/../generic/tclExecute.c 6022 = 2008
+
+On Heap
+ @ TclSetByteCodeFromAny ../../src/tcl834_stkr/unix/../generic/tclCompile.c 300 = 100
+ @ TclCompileByteCodesForExpr ../../src/tcl834_stkr/unix/../generic/tclExecute.c 6022 = 68
+
+-----------------------------------------------------------------------------------------------
+
+Ditto Tcl_Parse
+ @ TclCompileSetCmd ../../src/tcl834_stkr/unix/../generic/tclCompCmds.c 1618 = 640
+ @ TclCompileIncrCmd ../../src/tcl834_stkr/unix/../generic/tclCompCmds.c 1356 = 636
+On Heap
+ @ TclCompileSetCmd ../../src/tcl834_stkr/unix/../generic/tclCompCmds.c 1619 = 268
+ @ TclCompileIncrCmd ../../src/tcl834_stkr/unix/../generic/tclCompCmds.c 1356 = 264
+
+-----------------------------------------------------------------------------------------------
diff --git a/generic/tcl.h b/generic/tcl.h
index c662d08..84e1e0a 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -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: tcl.h,v 1.70.2.9.2.1 2001/11/28 17:58:35 andreas_kupries Exp $
+ * RCS: @(#) $Id: tcl.h,v 1.70.2.9.2.2 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#ifndef _TCL
@@ -47,6 +47,7 @@ extern "C" {
#define TCL_NO_LOADCMD /* Disable [load] and machinery below */
#define TCL_NO_SLAVEINTERP /* No slave interp's */
#define TCL_NO_CMDALIASES /* No command aliases */
+#define TCL_STRUCT_ON_HEAP /* Allocate temp. big structures off the heap */
#endif
#ifdef TCL_NO_NONSTDCHAN
@@ -55,6 +56,65 @@ extern "C" {
#define TCL_NO_PIPES /* Disable "pipe" channel driver */
#endif
+
+#ifdef TCL_STRUCT_ON_HEAP
+#define TYPE(t) t *
+#define ITEM(var,item) var -> item
+#define REF(var) (var)
+#define NEWSTRUCT(t,var) (var) = (t *) Tcl_Alloc(sizeof(t))
+#define RELSTRUCT(var) Tcl_Free((void*)(var))
+#else
+#define TYPE(t) t
+#define ITEM(var,item) var . item
+#define REF(var) &(var)
+#define NEWSTRUCT(t,var)
+#define RELSTRUCT(var)
+#endif
+
+/*
+ * Additional macros to control the sizes of various data placed on the stack.
+ */
+
+#ifndef TCL_FMT_STATIC_FLOATBUFFER_SZ
+#define TCL_FMT_STATIC_FLOATBUFFER_SZ 320
+#endif
+#ifndef TCL_FMT_STATIC_VALIDATE_LIST
+#define TCL_FMT_STATIC_VALIDATE_LIST 16
+#endif
+#ifndef TCL_FOREACH_STATIC_ARGS
+#define TCL_FOREACH_STATIC_ARGS 9
+#endif
+#ifndef TCL_FOREACH_STATIC_LIST_SZ
+#define TCL_FOREACH_STATIC_LIST_SZ 4
+#endif
+#ifndef TCL_FOREACH_STATIC_VARLIST_SZ
+#define TCL_FOREACH_STATIC_VARLIST_SZ 5
+#endif
+#ifndef TCL_RESULT_APPEND_STATIC_LIST_SZ
+#define TCL_RESULT_APPEND_STATIC_LIST_SZ 16
+#endif
+#ifndef TCL_MERGE_STATIC_LIST_SZ
+#define TCL_MERGE_STATIC_LIST_SZ 20
+#endif
+#ifndef TCL_PROC_STATIC_CLOCALS
+#define TCL_PROC_STATIC_CLOCALS 20
+#endif
+#ifndef TCL_PROC_STATIC_ARGS
+#define TCL_PROC_STATIC_ARGS 20
+#endif
+#ifndef TCL_INVOKE_STATIC_ARGS
+#define TCL_INVOKE_STATIC_ARGS 20
+#endif
+#ifndef TCL_EVAL_STATIC_VARCHARS
+#define TCL_EVAL_STATIC_VARCHARS 30
+#endif
+#ifndef TCL_STATS_COUNTERS
+#define TCL_STATS_COUNTERS 10
+#endif
+#ifndef TCL_LSORT_STATIC_MERGE_BUCKETS
+#define TCL_LSORT_STATIC_MERGE_BUCKETS 30
+#endif
+
/*
* The following defines are used to indicate the various release levels.
*/
@@ -862,7 +922,9 @@ typedef struct Tcl_CmdInfo {
* never modify it.
*/
+#ifndef TCL_DSTRING_STATIC_SIZE
#define TCL_DSTRING_STATIC_SIZE 200
+#endif
typedef struct Tcl_DString {
char *string; /* Points to beginning of string: either
* staticSpace below or a malloced array. */
@@ -1727,6 +1789,7 @@ EXTERN int Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp));
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
+
/*
* end block for C++
*/
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 7938399..faf7cea 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.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: tclBasic.c,v 1.27.6.1 2001/11/28 17:58:35 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.27.6.2 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -26,14 +26,13 @@
*/
static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
-static void ProcessUnexpectedResult _ANSI_ARGS_((
- Tcl_Interp *interp, int returnCode));
-static void RecordTracebackInfo _ANSI_ARGS_((
- Tcl_Interp *interp, Tcl_Obj *objPtr,
- int numSrcBytes));
+extern int TclEvalByteCodeFromObj _ANSI_ARGS_ ((Tcl_Interp *interp, Tcl_Obj *objPtr, int flags));
+extern int TclExprByteCodeFromObj _ANSI_ARGS_ ((Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr));
+
extern TclStubs tclStubs;
+
/*
* The following structure defines the commands in the Tcl core.
*/
@@ -1780,7 +1779,7 @@ TclInvokeStringCommand(clientData, interp, objc, objv)
* storage if needed.
*/
-#define NUM_ARGS 20
+#define NUM_ARGS TCL_INVOKE_STATIC_ARGS
char *(argStorage[NUM_ARGS]);
char **argv = argStorage;
@@ -1855,7 +1854,7 @@ TclInvokeObjectCommand(clientData, interp, argc, argv)
* dynamically-allocated storage if needed.
*/
-#define NUM_ARGS 20
+#define NUM_ARGS TCL_INVOKE_STATIC_ARGS
Tcl_Obj *(argStorage[NUM_ARGS]);
register Tcl_Obj **objv = argStorage;
@@ -2598,18 +2597,9 @@ Tcl_EvalObjEx(interp, objPtr, flags)
* TCL_EVAL_DIRECT. */
{
register Interp *iPtr = (Interp *) interp;
- int evalFlags; /* Interp->evalFlags value when the
- * procedure was called. */
- register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
- int oldCount = iPtr->cmdCount; /* Used to tell whether any commands
- * at all were executed. */
- int numSrcBytes;
int result;
- CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
- * in case TCL_EVAL_GLOBAL was set. */
- Namespace *namespacePtr;
+ int numSrcBytes;
- Tcl_IncrRefCount(objPtr);
if ((iPtr->flags & USE_EVAL_DIRECT) || (flags & TCL_EVAL_DIRECT)) {
/*
@@ -2626,6 +2616,7 @@ Tcl_EvalObjEx(interp, objPtr, flags)
* USE_EVAL_DIRECT is a special flag used for testing purpose only
* (ensure we go into the TCL_EVAL_DIRECT path, avoiding opt)
*/
+ Tcl_IncrRefCount(objPtr);
if (!(iPtr->flags & USE_EVAL_DIRECT) &&
(objPtr->typePtr == &tclListType) && /* is a list... */
(objPtr->bytes == NULL) /* ...without a string rep */) {
@@ -2638,314 +2629,11 @@ Tcl_EvalObjEx(interp, objPtr, flags)
p = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
result = Tcl_EvalEx(interp, p, numSrcBytes, flags);
}
- Tcl_DecrRefCount(objPtr);
+ TclDecrRefCount(objPtr);
return result;
}
- /*
- * Prevent the object from being deleted as a side effect of evaling it.
- */
-
- savedVarFramePtr = iPtr->varFramePtr;
- if (flags & TCL_EVAL_GLOBAL) {
- iPtr->varFramePtr = NULL;
- }
-
- /*
- * Reset both the interpreter's string and object results and clear out
- * any error information. This makes sure that we return an empty
- * result if there are no commands in the command string.
- */
-
- Tcl_ResetResult(interp);
-
- /*
- * Check depth of nested calls to Tcl_Eval: if this gets too large,
- * it's probably because of an infinite loop somewhere.
- */
-
- iPtr->numLevels++;
- if (iPtr->numLevels > iPtr->maxNestingDepth) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * On the Mac, we will never reach the default recursion limit before
- * blowing the stack. So we need to do a check here.
- */
-
- if (TclpCheckStackSpace() == 0) {
- /*NOTREACHED*/
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * If the interpreter has been deleted, return an error.
- */
-
- if (iPtr->flags & DELETED) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "attempt to call eval in deleted interpreter", -1);
- Tcl_SetErrorCode(interp, "CORE", "IDELETE",
- "attempt to call eval in deleted interpreter",
- (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Get the ByteCode from the object. If it exists, make sure it hasn't
- * been invalidated by, e.g., someone redefining a command with a
- * compile procedure (this might make the compiled code wrong). If
- * necessary, convert the object to be a ByteCode object and compile it.
- * Also, if the code was compiled in/for a different interpreter,
- * or for a different namespace, or for the same namespace but
- * with different name resolution rules, we recompile it.
- *
- * Precompiled objects, however, are immutable and therefore
- * they are not recompiled, even if the epoch has changed.
- *
- * To be pedantically correct, we should also check that the
- * originating procPtr is the same as the current context procPtr
- * (assuming one exists at all - none for global level). This
- * code is #def'ed out because [info body] was changed to never
- * return a bytecode type object, which should obviate us from
- * the extra checks here.
- */
-
- if (iPtr->varFramePtr != NULL) {
- namespacePtr = iPtr->varFramePtr->nsPtr;
- } else {
- namespacePtr = iPtr->globalNsPtr;
- }
-
- if (objPtr->typePtr == &tclByteCodeType) {
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
-
- if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)
-#ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
- || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
- iPtr->varFramePtr->procPtr == codePtr->procPtr))
-#endif
- || (codePtr->nsPtr != namespacePtr)
- || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
- if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
- if ((Interp *) *codePtr->interpHandle != iPtr) {
- panic("Tcl_EvalObj: compiled script jumped interps");
- }
- codePtr->compileEpoch = iPtr->compileEpoch;
- } else {
- tclByteCodeType.freeIntRepProc(objPtr);
- }
- }
- }
- if (objPtr->typePtr != &tclByteCodeType) {
- iPtr->errorLine = 1;
- result = tclByteCodeType.setFromAnyProc(interp, objPtr);
- if (result != TCL_OK) {
- goto done;
- }
- } else {
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
- if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)) {
- (*tclByteCodeType.freeIntRepProc)(objPtr);
- iPtr->errorLine = 1;
- result = (*tclByteCodeType.setFromAnyProc)(interp, objPtr);
- if (result != TCL_OK) {
- iPtr->numLevels--;
- return result;
- }
- }
- }
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
-
- /*
- * Extract then reset the compilation flags in the interpreter.
- * Resetting the flags must be done after any compilation.
- */
-
- evalFlags = iPtr->evalFlags;
- iPtr->evalFlags = 0;
-
- /*
- * Execute the commands. If the code was compiled from an empty string,
- * don't bother executing the code.
- */
-
- numSrcBytes = codePtr->numSrcBytes;
- if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
- /*
- * Increment the code's ref count while it is being executed. If
- * afterwards no references to it remain, free the code.
- */
-
- codePtr->refCount++;
- result = TclExecuteByteCode(interp, codePtr);
- codePtr->refCount--;
- if (codePtr->refCount <= 0) {
- TclCleanupByteCode(codePtr);
- }
- } else {
- result = TCL_OK;
- }
-
- /*
- * If no commands at all were executed, check for asynchronous
- * handlers so that they at least get one change to execute.
- * This is needed to handle event loops written in Tcl with
- * empty bodies.
- */
-
- if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
- result = Tcl_AsyncInvoke(interp, result);
- }
-
- /*
- * Update the interpreter's evaluation level count. If we are again at
- * the top level, process any unusual return code returned by the
- * evaluated code.
- */
-
- if (iPtr->numLevels == 1) {
- if (result == TCL_RETURN) {
- result = TclUpdateReturnInfo(iPtr);
- }
- if ((result != TCL_OK) && (result != TCL_ERROR)
- && ((evalFlags & TCL_ALLOW_EXCEPTIONS) == 0)) {
- ProcessUnexpectedResult(interp, result);
- result = TCL_ERROR;
- }
- }
-
- /*
- * If an error occurred, record information about what was being
- * executed when the error occurred.
- */
-
- if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
- RecordTracebackInfo(interp, objPtr, numSrcBytes);
- }
-
- /*
- * Set the interpreter's termOffset member to the offset of the
- * character just after the last one executed. We approximate the offset
- * of the last character executed by using the number of characters
- * compiled.
- */
-
- iPtr->termOffset = numSrcBytes;
- iPtr->flags &= ~ERR_ALREADY_LOGGED;
-
- done:
- TclDecrRefCount(objPtr);
- iPtr->varFramePtr = savedVarFramePtr;
- iPtr->numLevels--;
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ProcessUnexpectedResult --
- *
- * Procedure called by Tcl_EvalObj to set the interpreter's result
- * value to an appropriate error message when the code it evaluates
- * returns an unexpected result code (not TCL_OK and not TCL_ERROR) to
- * the topmost evaluation level.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The interpreter result is set to an error message appropriate to
- * the result code.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-ProcessUnexpectedResult(interp, returnCode)
- Tcl_Interp *interp; /* The interpreter in which the unexpected
- * result code was returned. */
- int returnCode; /* The unexpected result code. */
-{
- Tcl_ResetResult(interp);
- if (returnCode == TCL_BREAK) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"break\" outside of a loop", -1);
- } else if (returnCode == TCL_CONTINUE) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"continue\" outside of a loop", -1);
- } else {
- char buf[30 + TCL_INTEGER_SPACE];
-
- sprintf(buf, "command returned bad code: %d", returnCode);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * RecordTracebackInfo --
- *
- * Procedure called by Tcl_EvalObj to record information about what was
- * being executed when the error occurred.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Appends information about the script being evaluated to the
- * interpreter's "errorInfo" variable.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-RecordTracebackInfo(interp, objPtr, numSrcBytes)
- Tcl_Interp *interp; /* The interpreter in which the error
- * occurred. */
- Tcl_Obj *objPtr; /* Points to object containing script whose
- * evaluation resulted in an error. */
- int numSrcBytes; /* Number of bytes compiled in script. */
-{
- Interp *iPtr = (Interp *) interp;
- char buf[200];
- char *ellipsis, *bytes;
- int length;
-
- /*
- * Decide how much of the command to print in the error message
- * (up to a certain number of bytes).
- */
-
- bytes = Tcl_GetStringFromObj(objPtr, &length);
- length = TclMin(numSrcBytes, length);
-
- ellipsis = "";
- if (length > 150) {
- length = 150;
- ellipsis = " ...";
- }
-
- if (!(iPtr->flags & ERR_IN_PROGRESS)) {
- sprintf(buf, "\n while executing\n\"%.*s%s\"",
- length, bytes, ellipsis);
- } else {
- sprintf(buf, "\n invoked from within\n\"%.*s%s\"",
- length, bytes, ellipsis);
- }
- Tcl_AddObjErrorInfo(interp, buf, -1);
+ return TclEvalByteCodeFromObj(interp, objPtr, flags);
}
/*
@@ -3260,7 +2948,7 @@ TclInvoke(interp, argc, argv, flags)
* dynamically-allocated storage if needed.
*/
-#define NUM_ARGS 20
+#define NUM_ARGS TCL_INVOKE_STATIC_ARGS
Tcl_Obj *(objStorage[NUM_ARGS]);
register Tcl_Obj **objv = objStorage;
@@ -3524,6 +3212,7 @@ TclObjInvoke(interp, objc, objv, flags)
Tcl_ResetResult(interp);
iPtr->cmdCount++;
+
result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
/*
@@ -3684,18 +3373,8 @@ Tcl_ExprObj(interp, objPtr, resultPtrPtr)
Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
* result is stored if no errors occur. */
{
- Interp *iPtr = (Interp *) interp;
- CompileEnv compEnv; /* Compilation environment structure
- * allocated in frame. */
- LiteralTable *localTablePtr = &(compEnv.localLitTable);
- register ByteCode *codePtr = NULL;
- /* Tcl Internal type of bytecode.
- * Initialized to avoid compiler warning. */
- AuxData *auxDataPtr;
- LiteralEntry *entryPtr;
- Tcl_Obj *saveObjPtr;
char *string;
- int length, i, result;
+ int length;
/*
* First handle some common expressions specially.
@@ -3724,143 +3403,9 @@ Tcl_ExprObj(interp, objPtr, resultPtrPtr)
}
}
- /*
- * Get the ByteCode from the object. If it exists, make sure it hasn't
- * been invalidated by, e.g., someone redefining a command with a
- * compile procedure (this might make the compiled code wrong). If
- * necessary, convert the object to be a ByteCode object and compile it.
- * Also, if the code was compiled in/for a different interpreter, we
- * recompile it.
- *
- * Precompiled expressions, however, are immutable and therefore
- * they are not recompiled, even if the epoch has changed.
- *
- */
-
- if (objPtr->typePtr == &tclByteCodeType) {
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
- if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)) {
- if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
- if ((Interp *) *codePtr->interpHandle != iPtr) {
- panic("Tcl_ExprObj: compiled expression jumped interps");
- }
- codePtr->compileEpoch = iPtr->compileEpoch;
- } else {
- (*tclByteCodeType.freeIntRepProc)(objPtr);
- objPtr->typePtr = (Tcl_ObjType *) NULL;
- }
- }
- }
- if (objPtr->typePtr != &tclByteCodeType) {
- TclInitCompileEnv(interp, &compEnv, string, length);
- result = TclCompileExpr(interp, string, length, &compEnv);
-
- /*
- * Free the compilation environment's literal table bucket array if
- * it was dynamically allocated.
- */
-
- if (localTablePtr->buckets != localTablePtr->staticBuckets) {
- ckfree((char *) localTablePtr->buckets);
- }
-
- if (result != TCL_OK) {
- /*
- * Compilation errors. Free storage allocated for compilation.
- */
-
-#ifdef TCL_COMPILE_DEBUG
- TclVerifyLocalLiteralTable(&compEnv);
-#endif /*TCL_COMPILE_DEBUG*/
- entryPtr = compEnv.literalArrayPtr;
- for (i = 0; i < compEnv.literalArrayNext; i++) {
- TclReleaseLiteral(interp, entryPtr->objPtr);
- entryPtr++;
- }
-#ifdef TCL_COMPILE_DEBUG
- TclVerifyGlobalLiteralTable(iPtr);
-#endif /*TCL_COMPILE_DEBUG*/
-
- auxDataPtr = compEnv.auxDataArrayPtr;
- for (i = 0; i < compEnv.auxDataArrayNext; i++) {
- if (auxDataPtr->type->freeProc != NULL) {
- auxDataPtr->type->freeProc(auxDataPtr->clientData);
- }
- auxDataPtr++;
- }
- TclFreeCompileEnv(&compEnv);
- return result;
- }
-
- /*
- * Successful compilation. If the expression yielded no
- * instructions, push an zero object as the expression's result.
- */
-
- if (compEnv.codeNext == compEnv.codeStart) {
- TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
- &compEnv);
- }
-
- /*
- * Add a "done" instruction as the last instruction and change the
- * object into a ByteCode object. Ownership of the literal objects
- * and aux data items is given to the ByteCode object.
- */
-
- compEnv.numSrcBytes = iPtr->termOffset;
- TclEmitOpcode(INST_DONE, &compEnv);
- TclInitByteCodeObj(objPtr, &compEnv);
- TclFreeCompileEnv(&compEnv);
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
-#ifdef TCL_COMPILE_DEBUG
- if (tclTraceCompile == 2) {
- TclPrintByteCodeObj(interp, objPtr);
- }
-#endif /* TCL_COMPILE_DEBUG */
- }
-
- /*
- * Execute the expression after first saving the interpreter's result.
- */
-
- saveObjPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(saveObjPtr);
- Tcl_ResetResult(interp);
-
- /*
- * Increment the code's ref count while it is being executed. If
- * afterwards no references to it remain, free the code.
- */
-
- codePtr->refCount++;
- result = TclExecuteByteCode(interp, codePtr);
- codePtr->refCount--;
- if (codePtr->refCount <= 0) {
- TclCleanupByteCode(codePtr);
- objPtr->typePtr = NULL;
- objPtr->internalRep.otherValuePtr = NULL;
- }
-
- /*
- * If the expression evaluated successfully, store a pointer to its
- * value object in resultPtrPtr then restore the old interpreter result.
- * We increment the object's ref count to reflect the reference that we
- * are returning to the caller. We also decrement the ref count of the
- * interpreter's result object after calling Tcl_SetResult since we
- * next store into that field directly.
- */
-
- if (result == TCL_OK) {
- *resultPtrPtr = iPtr->objResultPtr;
- Tcl_IncrRefCount(iPtr->objResultPtr);
-
- Tcl_SetObjResult(interp, saveObjPtr);
- }
- Tcl_DecrRefCount(saveObjPtr);
- return result;
+ return TclExprByteCodeFromObj(interp, objPtr, resultPtrPtr);
}
+
/*
*----------------------------------------------------------------------
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c
index 5df1b08..2979c97 100644
--- a/generic/tclCmdAH.c
+++ b/generic/tclCmdAH.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdAH.c,v 1.12.2.2.2.1 2001/11/28 17:58:35 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclCmdAH.c,v 1.12.2.2.2.2 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -1732,11 +1732,11 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
* if the loop body requires a large amount of stack space.
*/
-#define NUM_ARGS 9
+#define NUM_ARGS TCL_FOREACH_STATIC_ARGS
Tcl_Obj *(argObjStorage[NUM_ARGS]);
Tcl_Obj **argObjv = argObjStorage;
-#define STATIC_LIST_SIZE 4
+#define STATIC_LIST_SIZE TCL_FOREACH_STATIC_LIST_SZ
int indexArray[STATIC_LIST_SIZE]; /* Array of value list indices */
int varcListArray[STATIC_LIST_SIZE]; /* # loop variables per list */
Tcl_Obj **varvListArray[STATIC_LIST_SIZE]; /* Array of var name lists */
@@ -1972,7 +1972,7 @@ Tcl_FormatObjCmd(dummy, interp, objc, objv)
# define PTR_VALUE 2
# define DOUBLE_VALUE 3
# define STRING_VALUE 4
-# define MAX_FLOAT_SIZE 320
+# define MAX_FLOAT_SIZE TCL_FMT_STATIC_FLOATBUFFER_SZ
Tcl_Obj *resultPtr; /* Where result is stored finally. */
char staticBuf[MAX_FLOAT_SIZE + 1];
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 2f8362d..c845b93 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.24.2.3 2001/10/08 15:50:24 dkf Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.24.2.3.2.1 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -1020,6 +1020,7 @@ InfoHostnameCmd(dummy, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
char *name;
+
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
@@ -1599,6 +1600,7 @@ InfoScriptCmd(dummy, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
+
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
@@ -2675,7 +2677,7 @@ MergeSort(headPtr, infoPtr)
* length 2**i.
*/
-# define NUM_LISTS 30
+# define NUM_LISTS TCL_LSORT_STATIC_MERGE_BUCKETS
SortElement *subList[NUM_LISTS];
SortElement *elementPtr;
int i;
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 75fa02e..8eab8b5 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -9,7 +9,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.5 2000/01/21 02:25:26 hobbs Exp $
+ * RCS: @(#) $Id: tclCompCmds.c,v 1.5.6.1 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -618,7 +618,7 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
* varvList[i] points to array of var names in i-th var list
*/
-#define STATIC_VAR_LIST_SIZE 5
+#define STATIC_VAR_LIST_SIZE TCL_FOREACH_STATIC_VARLIST_SZ
int varcListStaticSpace[STATIC_VAR_LIST_SIZE];
char **varvListStaticSpace[STATIC_VAR_LIST_SIZE];
int *varcList = varcListStaticSpace;
@@ -1318,18 +1318,21 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *incrTokenPtr;
- Tcl_Parse elemParse;
+ TYPE (Tcl_Parse) elemParse;
int gotElemParse = 0;
char *name, *elName, *p;
int nameChars, elNameChars, haveImmValue, immValue, localIndex, i, code;
int maxDepth = 0;
char buffer[160];
+ NEWSTRUCT (Tcl_Parse,elemParse);
+
envPtr->maxStackDepth = 0;
if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
Tcl_ResetResult(interp);
Tcl_AppendToObj(Tcl_GetObjResult(interp),
"wrong # args: should be \"incr varName ?increment?\"", -1);
+ RELSTRUCT(elemParse);
return TCL_ERROR;
}
@@ -1395,19 +1398,19 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
*(elName-1) = '"';
*(elName+elNameChars) = '"';
code = Tcl_ParseCommand(interp, elName-1, elNameChars+2,
- /*nested*/ 0, &elemParse);
+ /*nested*/ 0, REF (elemParse));
*(elName-1) = '(';
*(elName+elNameChars) = ')';
gotElemParse = 1;
- if ((code != TCL_OK) || (elemParse.numWords > 1)) {
+ if ((code != TCL_OK) || (ITEM (elemParse,numWords) > 1)) {
sprintf(buffer, "\n (parsing index for array \"%.*s\")",
TclMin(nameChars, 100), name);
Tcl_AddObjErrorInfo(interp, buffer, -1);
code = TCL_ERROR;
goto done;
- } else if (elemParse.numWords == 1) {
- code = TclCompileTokens(interp, elemParse.tokenPtr+1,
- elemParse.tokenPtr->numComponents, envPtr);
+ } else if (ITEM (elemParse,numWords) == 1) {
+ code = TclCompileTokens(interp, ITEM (elemParse,tokenPtr)+1,
+ ITEM (elemParse,tokenPtr)->numComponents, envPtr);
if (code != TCL_OK) {
goto done;
}
@@ -1534,8 +1537,9 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
done:
if (gotElemParse) {
- Tcl_FreeParse(&elemParse);
+ Tcl_FreeParse(REF (elemParse));
}
+ RELSTRUCT (elemParse);
envPtr->maxStackDepth = maxDepth;
return code;
}
@@ -1574,7 +1578,7 @@ TclCompileSetCmd(interp, parsePtr, envPtr)
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *valueTokenPtr;
- Tcl_Parse elemParse;
+ TYPE (Tcl_Parse) elemParse;
int gotElemParse = 0;
register char *p;
char *name, *elName;
@@ -1584,12 +1588,15 @@ TclCompileSetCmd(interp, parsePtr, envPtr)
int maxDepth = 0;
int code = TCL_OK;
+ NEWSTRUCT (Tcl_Parse,elemParse);
+
envPtr->maxStackDepth = 0;
numWords = parsePtr->numWords;
if ((numWords != 2) && (numWords != 3)) {
Tcl_ResetResult(interp);
Tcl_AppendToObj(Tcl_GetObjResult(interp),
"wrong # args: should be \"set varName ?newValue?\"", -1);
+ RELSTRUCT(elemParse);
return TCL_ERROR;
}
isAssignment = (numWords == 3);
@@ -1729,20 +1736,20 @@ TclCompileSetCmd(interp, parsePtr, envPtr)
*(elName-1) = '"';
*(elName+elNameChars) = '"';
code = Tcl_ParseCommand(interp, elName-1, elNameChars+2,
- /*nested*/ 0, &elemParse);
+ /*nested*/ 0, REF (elemParse));
*(elName-1) = '(';
*(elName+elNameChars) = ')';
gotElemParse = 1;
- if ((code != TCL_OK) || (elemParse.numWords > 1)) {
+ if ((code != TCL_OK) || (ITEM (elemParse,numWords) > 1)) {
char buffer[160];
sprintf(buffer, "\n (parsing index for array \"%.*s\")",
TclMin(nameChars, 100), name);
Tcl_AddObjErrorInfo(interp, buffer, -1);
code = TCL_ERROR;
goto done;
- } else if (elemParse.numWords == 1) {
- code = TclCompileTokens(interp, elemParse.tokenPtr+1,
- elemParse.tokenPtr->numComponents, envPtr);
+ } else if (ITEM (elemParse,numWords) == 1) {
+ code = TclCompileTokens(interp, ITEM (elemParse,tokenPtr)+1,
+ ITEM (elemParse,tokenPtr)->numComponents, envPtr);
if (code != TCL_OK) {
goto done;
}
@@ -1831,8 +1838,9 @@ TclCompileSetCmd(interp, parsePtr, envPtr)
done:
if (gotElemParse) {
- Tcl_FreeParse(&elemParse);
+ Tcl_FreeParse(REF (elemParse));
}
+ RELSTRUCT (elemParse);
envPtr->maxStackDepth = maxDepth;
return code;
}
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c
index 0b8fabf..5cf492b 100644
--- a/generic/tclCompExpr.c
+++ b/generic/tclCompExpr.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompExpr.c,v 1.4 1999/08/19 02:59:08 hobbs Exp $
+ * RCS: @(#) $Id: tclCompExpr.c,v 1.4.6.1 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -230,10 +230,12 @@ TclCompileExpr(interp, script, numBytes, envPtr)
CompileEnv *envPtr; /* Holds resulting instructions. */
{
ExprInfo info;
- Tcl_Parse parse;
+ TYPE (Tcl_Parse) parse;
Tcl_HashEntry *hPtr;
int maxDepth, new, i, code;
+ NEWSTRUCT(Tcl_Parse,parse);
+
/*
* If this is the first time we've been called, initialize the table
* of expression operators.
@@ -264,7 +266,7 @@ TclCompileExpr(interp, script, numBytes, envPtr)
*/
info.interp = interp;
- info.parsePtr = &parse;
+ info.parsePtr = REF (parse);
info.expr = script;
info.lastChar = (script + numBytes);
info.hasOperators = 0;
@@ -276,14 +278,14 @@ TclCompileExpr(interp, script, numBytes, envPtr)
*/
maxDepth = 0;
- code = Tcl_ParseExpr(interp, script, numBytes, &parse);
+ code = Tcl_ParseExpr(interp, script, numBytes, REF (parse));
if (code != TCL_OK) {
goto done;
}
- code = CompileSubExpr(parse.tokenPtr, &info, envPtr);
+ code = CompileSubExpr(ITEM(parse,tokenPtr), &info, envPtr);
if (code != TCL_OK) {
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF (parse));
goto done;
}
maxDepth = envPtr->maxStackDepth;
@@ -298,9 +300,10 @@ TclCompileExpr(interp, script, numBytes, envPtr)
TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
}
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF (parse));
done:
+ RELSTRUCT (parse);
envPtr->maxStackDepth = maxDepth;
envPtr->exprIsJustVarRef = info.exprIsJustVarRef;
envPtr->exprIsComparison = info.exprIsComparison;
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 56953f2..a716a18 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompile.c,v 1.20.2.1 2001/10/15 20:27:23 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclCompile.c,v 1.20.2.1.2.1 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -289,15 +289,18 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
ClientData clientData; /* Hook procedure private data. */
{
Interp *iPtr = (Interp *) interp;
- CompileEnv compEnv; /* Compilation environment structure
+ TYPE (CompileEnv) compEnv; /* Compilation environment structure
* allocated in frame. */
- LiteralTable *localTablePtr = &(compEnv.localLitTable);
+ LiteralTable *localTablePtr;
register AuxData *auxDataPtr;
LiteralEntry *entryPtr;
register int i;
int length, nested, result;
char *string;
+ NEWSTRUCT(CompileEnv,compEnv);
+ localTablePtr = &(ITEM(compEnv,localLitTable));
+
if (!traceInitialized) {
if (Tcl_LinkVar(interp, "tcl_traceCompile",
(char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) {
@@ -312,23 +315,23 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
nested = 0;
}
string = Tcl_GetStringFromObj(objPtr, &length);
- TclInitCompileEnv(interp, &compEnv, string, length);
- result = TclCompileScript(interp, string, length, nested, &compEnv);
+ TclInitCompileEnv(interp, REF(compEnv), string, length);
+ result = TclCompileScript(interp, string, length, nested, REF(compEnv));
if (result == TCL_OK) {
/*
* Successful compilation. Add a "done" instruction at the end.
*/
- compEnv.numSrcBytes = iPtr->termOffset;
- TclEmitOpcode(INST_DONE, &compEnv);
+ ITEM(compEnv,numSrcBytes) = iPtr->termOffset;
+ TclEmitOpcode(INST_DONE, REF(compEnv));
/*
* Invoke the compilation hook procedure if one exists.
*/
if (hookProc) {
- result = (*hookProc)(interp, &compEnv, clientData);
+ result = (*hookProc)(interp, REF(compEnv), clientData);
}
/*
@@ -337,10 +340,10 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
*/
#ifdef TCL_COMPILE_DEBUG
- TclVerifyLocalLiteralTable(&compEnv);
+ TclVerifyLocalLiteralTable(REF(compEnv));
#endif /*TCL_COMPILE_DEBUG*/
- TclInitByteCodeObj(objPtr, &compEnv);
+ TclInitByteCodeObj(objPtr, REF(compEnv));
#ifdef TCL_COMPILE_DEBUG
if (tclTraceCompile == 2) {
TclPrintByteCodeObj(interp, objPtr);
@@ -353,8 +356,8 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
* Compilation errors.
*/
- entryPtr = compEnv.literalArrayPtr;
- for (i = 0; i < compEnv.literalArrayNext; i++) {
+ entryPtr = ITEM(compEnv,literalArrayPtr);
+ for (i = 0; i < ITEM(compEnv,literalArrayNext); i++) {
TclReleaseLiteral(interp, entryPtr->objPtr);
entryPtr++;
}
@@ -362,8 +365,8 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
TclVerifyGlobalLiteralTable(iPtr);
#endif /*TCL_COMPILE_DEBUG*/
- auxDataPtr = compEnv.auxDataArrayPtr;
- for (i = 0; i < compEnv.auxDataArrayNext; i++) {
+ auxDataPtr = ITEM(compEnv,auxDataArrayPtr);
+ for (i = 0; i < ITEM(compEnv,auxDataArrayNext); i++) {
if (auxDataPtr->type->freeProc != NULL) {
auxDataPtr->type->freeProc(auxDataPtr->clientData);
}
@@ -379,7 +382,8 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
if (localTablePtr->buckets != localTablePtr->staticBuckets) {
ckfree((char *) localTablePtr->buckets);
}
- TclFreeCompileEnv(&compEnv);
+ TclFreeCompileEnv(REF(compEnv));
+ RELSTRUCT(compEnv);
return result;
}
@@ -509,8 +513,8 @@ TclCleanupByteCode(codePtr)
register Tcl_Obj **objArrayPtr;
register AuxData *auxDataPtr;
int i;
-#ifdef TCL_COMPILE_STATS
+#ifdef TCL_COMPILE_STATS
if (interp != NULL) {
ByteCodeStats *statsPtr;
Tcl_Time destroyTime;
@@ -751,7 +755,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Interp *iPtr = (Interp *) interp;
- Tcl_Parse parse;
+ TYPE (Tcl_Parse) parse;
int maxDepth = 0; /* Maximum number of stack elements needed
* to execute all cmds. */
int lastTopLevelCmdIndex = -1;
@@ -770,6 +774,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
char prev;
Tcl_DString ds;
+ NEWSTRUCT (Tcl_Parse,parse);
Tcl_DStringInit(&ds);
if (numBytes < 0) {
@@ -787,12 +792,13 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
bytesLeft = numBytes;
gotParse = 0;
while (bytesLeft > 0) {
- if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse) != TCL_OK) {
+ if (Tcl_ParseCommand(interp, p, bytesLeft, nested,
+ REF(parse)) != TCL_OK) {
code = TCL_ERROR;
goto error;
}
gotParse = 1;
- if (parse.numWords > 0) {
+ if (ITEM (parse,numWords) > 0) {
/*
* If not the first command, pop the previous command's result
* and, if we're compiling a top level command, update the last
@@ -812,12 +818,12 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
* Determine the actual length of the command.
*/
- commandLength = parse.commandSize;
+ commandLength = ITEM (parse,commandSize);
prev = '\0';
if (commandLength > 0) {
- prev = parse.commandStart[commandLength-1];
+ prev = ITEM (parse, commandStart)[commandLength-1];
}
- if (((parse.commandStart+commandLength) != (script+numBytes))
+ if (((ITEM (parse,commandStart)+commandLength) != (script+numBytes))
|| ((prev=='\n') || (nested && (prev==']')))) {
/*
* The command didn't end at the end of the script (i.e. it
@@ -836,7 +842,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
if ((tclTraceCompile >= 1)
&& !nested && (envPtr->procPtr == NULL)) {
fprintf(stdout, " Compiling: ");
- TclPrintSource(stdout, parse.commandStart,
+ TclPrintSource(stdout, ITEM (parse,commandStart),
TclMin(commandLength, 55));
fprintf(stdout, "\n");
}
@@ -853,10 +859,10 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
}
startCodeOffset = (envPtr->codeNext - envPtr->codeStart);
EnterCmdStartData(envPtr, currCmdIndex,
- (parse.commandStart - envPtr->source), startCodeOffset);
+ (ITEM (parse,commandStart) - envPtr->source), startCodeOffset);
- for (wordIdx = 0, tokenPtr = parse.tokenPtr;
- wordIdx < parse.numWords;
+ for (wordIdx = 0, tokenPtr = ITEM (parse,tokenPtr);
+ wordIdx < ITEM (parse,numWords);
wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) {
if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
/*
@@ -890,7 +896,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
if ((cmdPtr != NULL)
&& (cmdPtr->compileProc != NULL)
&& !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) {
- code = (*(cmdPtr->compileProc))(interp, &parse,
+ code = (*(cmdPtr->compileProc))(interp, REF(parse),
envPtr);
if (code == TCL_OK) {
maxDepth = TclMax(envPtr->maxStackDepth,
@@ -968,16 +974,16 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
EnterCmdExtentData(envPtr, currCmdIndex, commandLength,
(envPtr->codeNext-envPtr->codeStart) - startCodeOffset);
isFirstCmd = 0;
- } /* end if parse.numWords > 0 */
+ } /* end if ITEM (parse,numWords) > 0 */
/*
* Advance to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
+ next = ITEM (parse,commandStart) + ITEM (parse,commandSize);
bytesLeft -= (next - p);
p = next;
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
gotParse = 0;
if (nested && (p[-1] == ']')) {
/*
@@ -988,7 +994,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
break;
}
- }
+ } /* bytesLeft > 0 */
/*
* If the source script yielded no instructions (e.g., if it was empty),
@@ -1007,6 +1013,7 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
iPtr->termOffset = (p - script);
}
envPtr->maxStackDepth = maxDepth;
+ RELSTRUCT (parse);
Tcl_DStringFree(&ds);
return TCL_OK;
@@ -1018,12 +1025,12 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
* to the command.
*/
- commandLength = parse.commandSize;
+ commandLength = ITEM (parse,commandSize);
prev = '\0';
if (commandLength > 0) {
- prev = parse.commandStart[commandLength-1];
+ prev = ITEM (parse,commandStart)[commandLength-1];
}
- if (((parse.commandStart+commandLength) != (script+numBytes))
+ if (((ITEM (parse,commandStart)+commandLength) != (script+numBytes))
|| ((prev == '\n') || (nested && (prev == ']')))) {
/*
* The command where the error occurred didn't end at the end
@@ -1034,10 +1041,11 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
commandLength -= 1;
}
- LogCompilationInfo(interp, script, parse.commandStart, commandLength);
+ LogCompilationInfo(interp, script, ITEM (parse,commandStart), commandLength);
if (gotParse) {
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
}
+ RELSTRUCT (parse);
iPtr->termOffset = (p - script);
envPtr->maxStackDepth = maxDepth;
Tcl_DStringFree(&ds);
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 387ef81..0539d51 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -1,3 +1,5 @@
+#define TCL_NO_RECURSE 1
+
/*
* tclExecute.c --
*
@@ -10,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: tclExecute.c,v 1.10.2.2 2001/08/07 15:41:20 msofer Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.10.2.2.2.1 2001/12/03 18:23:13 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -263,6 +265,13 @@ static void InitByteCodeExecution _ANSI_ARGS_((
#ifdef TCL_COMPILE_DEBUG
static void PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
#endif
+static void ProcessUnexpectedResult _ANSI_ARGS_((
+ Tcl_Interp *interp, int returnCode));
+static int ProcessProcResultCode _ANSI_ARGS_((Tcl_Interp *interp,
+ char *procName, int nameLen, int returnCode));
+static void RecordTracebackInfo _ANSI_ARGS_((
+ Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int numSrcBytes));
static int SetCmdNameFromAny _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *objPtr));
#ifdef TCL_COMPILE_DEBUG
@@ -275,6 +284,19 @@ static void ValidatePcAndStackTop _ANSI_ARGS_((
static int VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *objPtr));
+static int TclInterpReady _ANSI_ARGS_((Tcl_Interp *interp));
+static int TclCompileByteCodesForEval _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr));
+static int TclInterpPostEval _ANSI_ARGS_((Tcl_Interp *interp,
+ int evalFlags, int result, Tcl_Obj *objPtr, int numSrcBytes));
+static int TclCompileByteCodesForExpr _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr));
+static int PrepareProcFrameForExecution _ANSI_ARGS_((Tcl_Interp *interp,
+ CallFrame *framePtr, int objc, Tcl_Obj *CONST objv[0],
+ Var *compiledLocals));
+
+int TclEvalByteCodeFromObj _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, int flags));
+int TclExprByteCodeFromObj _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr));
+
+
/*
* Table describing the built-in math functions. Entries in this table are
* indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
@@ -497,7 +519,7 @@ GrowEvaluationStack(eePtr)
int currElems = (eePtr->stackEnd + 1);
int newElems = 2*currElems;
int currBytes = currElems * sizeof(Tcl_Obj *);
- int newBytes = 2*currBytes;
+ int newBytes = newElems * sizeof(Tcl_Obj *);
Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);
/*
@@ -511,7 +533,58 @@ GrowEvaluationStack(eePtr)
eePtr->stackPtr = newStackPtr;
eePtr->stackEnd = (newElems - 1); /* i.e. index of last usable item */
}
-
+
+/*********************************/
+#if TCL_NO_RECURSE
+/*
+ * Definitions for the internal return stack rs
+ *
+ * REMARK: this simple code assumes that pointers are at least
+ * as large as integers:
+ * sizeof(void *) >= sizeof(int)
+ * Are there any systems where this is not true?
+ *
+ * Furthermore, should sizeof(void *) > sizeof(int), this
+ * may cause a misalignment of the stack data ...
+ */
+
+typedef struct rsData {
+ Tcl_Obj *objPtr;
+ ByteCode *codePtr;
+ unsigned char *pc;
+ int initStackTop;
+ int catchTop;
+} rsData;
+
+#define RS_PUSH(callType) \
+ { \
+ rsData *rsPtr = (rsData *) &stackPtr[stackTop + 1];\
+ \
+ rsPtr->codePtr = oldCodePtr;\
+ rsPtr->objPtr = objPtr;\
+ rsPtr->pc = pc;\
+ rsPtr->initStackTop = initStackTop;\
+ rsPtr->catchTop = catchTop;\
+ }\
+ stackTop += (sizeof(rsData) + 1);\
+ stackPtr[stackTop] = (Tcl_Obj *) (callType);\
+ currentDepth++;
+
+
+#define RS_POP() \
+ stackTop -= sizeof(rsData);\
+ { \
+ rsData *rsPtr = (rsData *) &stackPtr[stackTop + 1];\
+ \
+ codePtr = rsPtr->codePtr;\
+ objPtr = rsPtr->objPtr;\
+ pc = rsPtr->pc;\
+ initStackTop = rsPtr->initStackTop;\
+ catchTop = rsPtr->catchTop;\
+ catchStackPtr = (int *) &stackPtr[initStackTop - (codePtr->maxExceptDepth) + 1];\
+ }
+#endif /* TCL_NO_RECURSE */
+
/*
*----------------------------------------------------------------------
*
@@ -559,18 +632,48 @@ TclExecuteByteCode(interp, codePtr)
char *bytes;
int length;
long i;
+ int catchTop, *catchStackPtr;
/*
* This procedure uses a stack to hold information about catch commands.
* This information is the current operand stack top when starting to
- * execute the code for each catch command. It starts out with stack-
- * allocated space but uses dynamically-allocated storage if needed.
+ * execute the code for each catch command. It is set at the bottom of
+ * the bytecodes stack, its depth is the exception range array's depth.
+ *
+ * Make sure the stack has enough room to execute this ByteCode,
+ * holding the bytecodes catch stack, and storing the data for a
+ * possible internal recursion.
+ *
+ * REMARK: this simple code assumes that Tcl_Obj* and int* are the same
+ * size (can this ever be wrong?)
*/
-#define STATIC_CATCH_STACK_SIZE 4
- int (catchStackStorage[STATIC_CATCH_STACK_SIZE]);
- int *catchStackPtr = catchStackStorage;
- int catchTop = -1;
+#if TCL_NO_RECURSE
+ int currentDepth = 0;
+ ByteCode *oldCodePtr;
+
+ /*
+ * Jump back here for internal recursions
+ */
+
+ startInternalRecursionHere:
+ pc = codePtr->codeStart;
+ result = TCL_OK;
+ length = stackTop + sizeof(rsData)
+ + (codePtr->maxStackDepth + codePtr->maxExceptDepth + 3)*sizeof(Tcl_Obj *);
+#else
+ length = stackTop + (codePtr->maxStackDepth + codePtr->maxExceptDepth)*sizeof(Tcl_Obj *);
+#endif
+
+ while (length > eePtr->stackEnd) {
+ GrowEvaluationStack(eePtr);
+ stackPtr = eePtr->stackPtr;
+ }
+ catchStackPtr = (int *) &stackPtr[stackTop + 1];
+ catchTop = -1;
+ stackTop += (codePtr->maxExceptDepth);
+ initStackTop = stackTop;
+
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
@@ -584,31 +687,12 @@ TclExecuteByteCode(interp, codePtr)
iPtr->stats.numExecutions++;
#endif
- /*
- * Make sure the catch stack is large enough to hold the maximum number
- * of catch commands that could ever be executing at the same time. This
- * will be no more than the exception range array's depth.
- */
-
- if (codePtr->maxExceptDepth > STATIC_CATCH_STACK_SIZE) {
- catchStackPtr = (int *)
- ckalloc(codePtr->maxExceptDepth * sizeof(int));
- }
-
- /*
- * Make sure the stack has enough room to execute this ByteCode.
- */
-
- while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) {
- GrowEvaluationStack(eePtr);
- stackPtr = eePtr->stackPtr;
- }
/*
* Loop executing instructions until a "done" instruction, a TCL_RETURN,
* or some error.
*/
-
+
for (;;) {
#ifdef TCL_COMPILE_DEBUG
ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop,
@@ -805,18 +889,6 @@ TclExecuteByteCode(interp, codePtr)
}
/*
- * A reference to part of the stack vector itself
- * escapes our control, so must use preserve/release
- * to stop it from being deallocated by a recursive
- * call to ourselves. The extra variable is needed
- * because all others are liable to change due to the
- * trace procedures.
- */
-
- Tcl_Preserve((ClientData)stackPtr);
- preservedStack = stackPtr;
-
- /*
* Call any trace procedures.
*/
@@ -871,11 +943,191 @@ TclExecuteByteCode(interp, codePtr)
Tcl_GetString(objv[0]));
#endif /*TCL_COMPILE_DEBUG*/
}
-
+
iPtr->cmdCount++;
+#if TCL_NO_RECURSE
+#define VAR_TO_POINTER (sizeof(Var)/sizeof(void *) + 1)
+#define FRAME_TO_POINTER (sizeof(CallFrame)/sizeof(void *) + 1)
+ if ((*cmdPtr->objProc) == TclObjInterpProc) {
+ /*
+ * This is code "borrowed" from TclObjInterpProc
+ */
+
+ Proc *procPtr = (Proc *) (cmdPtr->objClientData);
+ Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
+ CallFrame *framePtr;
+ Var *compiledLocals;
+ int localCt;
+
+ objPtr = procPtr->bodyPtr;
+ result = TclProcCompileProc(interp, procPtr, objPtr, nsPtr,
+ "body of proc", Tcl_GetString(objv[0]));
+ if (result != TCL_OK) {
+ goto earlyReturnFromPROC;
+ }
+ localCt = procPtr->numCompiledLocals;
+
+ /*
+ * make sure there is enough room in the stack
+ */
+
+ length = stackTop + sizeof(rsData) +
+ +(FRAME_TO_POINTER +localCt*VAR_TO_POINTER + 7)*sizeof(Tcl_Obj *);
+ while (length > eePtr->stackEnd) {
+ GrowEvaluationStack(eePtr);
+ stackPtr = eePtr->stackPtr;
+ }
+
+ framePtr = (CallFrame *) &stackPtr[stackTop + 1];
+ result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
+ (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
+ if (result != TCL_OK) {
+ goto earlyReturnFromPROC;
+ }
+ stackTop += FRAME_TO_POINTER;
+ framePtr->procPtr = procPtr;
+
+ compiledLocals = (Var *) &stackPtr[stackTop + 1];
+ stackTop += localCt * VAR_TO_POINTER;
+
+ stackPtr[++stackTop] = (Tcl_Obj *) objc;
+ stackPtr[++stackTop] = (Tcl_Obj *) procPtr;
+
+ result = PrepareProcFrameForExecution(interp, framePtr, objc, objv, compiledLocals);
+ if (result == TCL_ERROR) {
+ Tcl_PopCallFrame(interp);
+ stackTop -= (FRAME_TO_POINTER + (procPtr->numCompiledLocals)*VAR_TO_POINTER + 2);
+ goto earlyReturnFromPROC;
+ }
+ procPtr->refCount++;
+ Tcl_Preserve((ClientData) stackPtr);
+ preservedStack = stackPtr;
+
+ /*
+ * This is code borrowed from TclEvalByteCodeFromObj
+ */
+
+ Tcl_ResetResult(interp);
+
+ result = TclInterpReady(interp);
+ if (result == TCL_ERROR) {
+ goto earlyReturnFromEvalBody;
+ }
+
+ oldCodePtr = codePtr;
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+ stackPtr[++stackTop] = (Tcl_Obj *) preservedStack;
+ stackPtr[++stackTop] = (Tcl_Obj *) pcAdjustment;
+ stackPtr[++stackTop] = (Tcl_Obj *) codePtr->numSrcBytes;
+ stackPtr[++stackTop] = (Tcl_Obj *) iPtr->evalFlags;
+ iPtr->evalFlags = 0;
+ codePtr->refCount++;
+ iPtr->numLevels++;
+
+ RS_PUSH(0);
+ goto startInternalRecursionHere;
+ } else {
+ /*
+ * Command is not a proc
+ */
+
+ Tcl_Preserve((ClientData)stackPtr);
+ preservedStack = stackPtr;
+ DECACHE_STACK_INFO();
+ result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
+ objc, objv);
+ if (Tcl_AsyncReady()) {
+ result = Tcl_AsyncInvoke(interp, result);
+ }
+ CACHE_STACK_INFO();
+ Tcl_Release((ClientData) preservedStack);
+
+ /*
+ * If the interpreter has a non-empty string result, the
+ * result object is either empty or stale because some
+ * procedure set interp->result directly. If so, move the
+ * string result to the result object, then reset the
+ * string result.
+ */
+
+ if (*(iPtr->result) != 0) {
+ (void) Tcl_GetObjResult(interp);
+ }
+
+ goto returnFromNON_PROC;
+ }
+
+ returnFromPROC:
+ if (--(codePtr->refCount) <= 0) {
+ TclCleanupByteCode(codePtr);
+ }
+ RS_POP();
+ {
+ int evalFlags = (int) stackPtr[stackTop--];
+ int numSrcBytes = (int) stackPtr[stackTop--];
+ result = TclInterpPostEval(interp, evalFlags, result, objPtr, numSrcBytes);
+ }
+ iPtr->numLevels--;
+ pcAdjustment = (int) stackPtr[stackTop--];
+ preservedStack = (Tcl_Obj **) stackPtr[stackTop--];
+
+ earlyReturnFromEvalBody:
+ {
+ Proc *procPtr;
+
+ procPtr = (Proc *) stackPtr[stackTop--];
+ objc = (int) stackPtr[stackTop--];
+ stackTop -= (FRAME_TO_POINTER + (procPtr->numCompiledLocals)*VAR_TO_POINTER);
+
+ procPtr->refCount--;
+ if (procPtr->refCount <= 0) {
+ TclProcCleanupProc(procPtr);
+ }
+
+ if (result != TCL_OK) {
+ int nameLen;
+ char *procName;
+
+ objv = &stackPtr[stackTop - objc + 1];
+ procName = Tcl_GetStringFromObj(objv[0], &nameLen);
+ result = ProcessProcResultCode(interp, procName, nameLen, result);
+ }
+ }
+ Tcl_PopCallFrame(interp);
+ Tcl_Release((ClientData) preservedStack);
+
+ earlyReturnFromPROC:
+ if (Tcl_AsyncReady()) {
+ DECACHE_STACK_INFO();
+ result = Tcl_AsyncInvoke(interp, result);
+ CACHE_STACK_INFO();
+ }
+
+ if (*(iPtr->result) != 0) {
+ (void) Tcl_GetObjResult(interp);
+ }
+
+ returnFromNON_PROC:
+#undef VAR_TO_POINTER
+#undef FRAME_TO_POINTER
+#else /* TCL_NO_RECURSE */
+
+ /*
+ * A reference to part of the stack vector itself
+ * escapes our control, so must use preserve/release
+ * to stop it from being deallocated by a recursive
+ * call to ourselves. The extra variable is needed
+ * because all others are liable to change due to the
+ * trace procedures.
+ */
+
+ Tcl_Preserve((ClientData)stackPtr);
+ preservedStack = stackPtr;
+
DECACHE_STACK_INFO();
result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
- objc, objv);
+ objc, objv);
if (Tcl_AsyncReady()) {
result = Tcl_AsyncInvoke(interp, result);
}
@@ -901,6 +1153,7 @@ TclExecuteByteCode(interp, codePtr)
(void) Tcl_GetObjResult(interp);
}
+#endif
/*
* Pop the objc top stack elements and decrement their ref
* counts.
@@ -908,8 +1161,8 @@ TclExecuteByteCode(interp, codePtr)
for (i = 0; i < objc; i++) {
valuePtr = stackPtr[stackTop];
- TclDecrRefCount(valuePtr);
- stackTop--;
+ TclDecrRefCount(valuePtr);
+ stackTop--;
}
/*
@@ -1005,9 +1258,49 @@ TclExecuteByteCode(interp, codePtr)
case INST_EVAL_STK:
objPtr = POP_OBJECT();
+#if TCL_NO_RECURSE
+ Tcl_ResetResult(interp);
+
+ result = ((TclInterpReady(interp) == TCL_ERROR) \
+ || (TclCompileByteCodesForEval(interp, objPtr) == TCL_ERROR));
+ if (result == TCL_ERROR) {
+ Tcl_DecrRefCount(objPtr);
+ goto checkForCatch;
+ }
+ oldCodePtr = codePtr;
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+ stackPtr[++stackTop] = (Tcl_Obj *) codePtr->numSrcBytes;
+ stackPtr[++stackTop] = (Tcl_Obj *) iPtr->evalFlags;
+ iPtr->evalFlags = 0;
+ stackPtr[++stackTop] = (Tcl_Obj *) iPtr->cmdCount;
+ codePtr->refCount++;
+ iPtr->numLevels++;
+ RS_PUSH(1);
+ goto startInternalRecursionHere;
+
+ returnFromEVAL:
+ if (--(codePtr->refCount) <= 0) {
+ TclCleanupByteCode(codePtr);
+ }
+ RS_POP();
+ {
+ int oldCount = (int) stackPtr[stackTop--];
+ if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
+ result = Tcl_AsyncInvoke(interp, result);
+ }
+ }
+ {
+ int evalFlags = (int) stackPtr[stackTop--];
+ int numSrcBytes = (int) stackPtr[stackTop--];
+ result = TclInterpPostEval(interp, evalFlags, result, objPtr, numSrcBytes);
+ }
+ iPtr->numLevels--;
+#else
DECACHE_STACK_INFO();
- result = Tcl_EvalObjEx(interp, objPtr, 0);
+ result = TclEvalByteCodeFromObj(interp, objPtr, 0);
CACHE_STACK_INFO();
+#endif
if (result == TCL_OK) {
/*
* Normal return; push the eval's object result.
@@ -1078,9 +1371,48 @@ TclExecuteByteCode(interp, codePtr)
case INST_EXPR_STK:
objPtr = POP_OBJECT();
Tcl_ResetResult(interp);
+
+#if TCL_NO_RECURSE
+ /*
+ * This is the internal call; it mimics TclExprByteCodeFromObj
+ */
+
+ result = TclCompileByteCodesForExpr(interp, objPtr);
+ if (result != TCL_OK) {
+ goto compErrorFromEXPR;
+ } else {
+ value2Ptr = Tcl_GetObjResult(interp);
+ PUSH_OBJECT(value2Ptr);
+ Tcl_ResetResult(interp);
+ oldCodePtr = codePtr;
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+ codePtr->refCount++;
+ RS_PUSH(2);
+ goto startInternalRecursionHere;
+ }
+
+ returnFromEXPR:
+ if (--(codePtr->refCount) <= 0) {
+ TclCleanupByteCode(codePtr);
+ RS_POP();
+ objPtr->typePtr = NULL;
+ objPtr->internalRep.otherValuePtr = NULL;
+ } else {
+ RS_POP();
+ }
+ value2Ptr = POP_OBJECT();
+ valuePtr = Tcl_GetObjResult(interp);
+ if (result == TCL_OK) {
+ Tcl_IncrRefCount(valuePtr);
+ Tcl_SetObjResult(interp, value2Ptr);
+ }
+ TclDecrRefCount(value2Ptr);
+ compErrorFromEXPR:
+#else
DECACHE_STACK_INFO();
- result = Tcl_ExprObj(interp, objPtr, &valuePtr);
+ result = TclExprByteCodeFromObj(interp, objPtr, &valuePtr);
CACHE_STACK_INFO();
+#endif
if (result != TCL_OK) {
TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ",
O2S(objPtr)), Tcl_GetObjResult(interp));
@@ -2959,12 +3291,30 @@ TclExecuteByteCode(interp, codePtr)
*/
done:
- if (catchStackPtr != catchStackStorage) {
- ckfree((char *) catchStackPtr);
+ stackTop -= codePtr->maxExceptDepth;
+#if TCL_NO_RECURSE
+ if (currentDepth--) {
+ /*
+ * An internal return
+ */
+ int retCode = (int) stackPtr[stackTop--];
+ switch (retCode) {
+ case 0: goto returnFromPROC;
+ case 1: goto returnFromEVAL;
+ case 2: goto returnFromEXPR;
+ default:
+ fprintf(stderr, "ERROR: Internal return code is %i: this should never happen!\n", retCode );
+ panic("FATAL ERROR");
+ }
}
- eePtr->stackTop = initStackTop;
+#endif
+
+ /*
+ * A real return
+ */
+
+ eePtr->stackTop = stackTop;
return result;
-#undef STATIC_CATCH_STACK_SIZE
}
#ifdef TCL_COMPILE_DEBUG
@@ -4173,7 +4523,9 @@ ExprCallMathFunc(interp, eePtr, objc, objv)
long i;
double d;
int j, k, result;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_ResetResult(interp);
@@ -4362,7 +4714,9 @@ TclExprFloatError(interp, value)
int
TclMathInProgress()
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
return tsdPtr->mathInProgress;
}
@@ -5175,3 +5529,877 @@ StringForResultCode(result)
return buf;
}
#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcessUnexpectedResult --
+ *
+ * Procedure called by Tcl_EvalObj to set the interpreter's result
+ * value to an appropriate error message when the code it evaluates
+ * returns an unexpected result code (not TCL_OK and not TCL_ERROR) to
+ * the topmost evaluation level.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The interpreter result is set to an error message appropriate to
+ * the result code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ProcessUnexpectedResult(interp, returnCode)
+ Tcl_Interp *interp; /* The interpreter in which the unexpected
+ * result code was returned. */
+ int returnCode; /* The unexpected result code. */
+{
+ Tcl_ResetResult(interp);
+ if (returnCode == TCL_BREAK) {
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "invoked \"break\" outside of a loop", -1);
+ } else if (returnCode == TCL_CONTINUE) {
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "invoked \"continue\" outside of a loop", -1);
+ } else {
+ char buf[30 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "command returned bad code: %d", returnCode);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecordTracebackInfo --
+ *
+ * Procedure called by Tcl_EvalObj to record information about what was
+ * being executed when the error occurred.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Appends information about the script being evaluated to the
+ * interpreter's "errorInfo" variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecordTracebackInfo(interp, objPtr, numSrcBytes)
+ Tcl_Interp *interp; /* The interpreter in which the error
+ * occurred. */
+ Tcl_Obj *objPtr; /* Points to object containing script whose
+ * evaluation resulted in an error. */
+ int numSrcBytes; /* Number of bytes compiled in script. */
+{
+ Interp *iPtr = (Interp *) interp;
+ char buf[200];
+ char *ellipsis, *bytes;
+ int length;
+
+ /*
+ * Decide how much of the command to print in the error message
+ * (up to a certain number of bytes).
+ */
+
+ bytes = Tcl_GetStringFromObj(objPtr, &length);
+ length = TclMin(numSrcBytes, length);
+
+ ellipsis = "";
+ if (length > 150) {
+ length = 150;
+ ellipsis = " ...";
+ }
+
+ if (!(iPtr->flags & ERR_IN_PROGRESS)) {
+ sprintf(buf, "\n while executing\n\"%.*s%s\"",
+ length, bytes, ellipsis);
+ } else {
+ sprintf(buf, "\n invoked from within\n\"%.*s%s\"",
+ length, bytes, ellipsis);
+ }
+ Tcl_AddObjErrorInfo(interp, buf, -1);
+}
+
+/*
+ * Recently imported stuff ...
+ */
+
+static int
+TclInterpReady(interp)
+ Tcl_Interp *interp;
+{
+ register Interp *iPtr = (Interp *) interp;
+
+ /*
+ * Check depth of nested calls to Tcl_Eval: if this gets too large,
+ * it's probably because of an infinite loop somewhere.
+ */
+
+ if ((iPtr->numLevels + 1) > iPtr->maxNestingDepth) {
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
+ return TCL_ERROR;
+ }
+
+ /*
+ * On the Mac, we will never reach the default recursion limit before
+ * blowing the stack. So we need to do a check here.
+ */
+
+ if (TclpCheckStackSpace() == 0) {
+ /*NOTREACHED*/
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the interpreter has been deleted, return an error.
+ */
+
+ if (iPtr->flags & DELETED) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "attempt to call eval in deleted interpreter", -1);
+ Tcl_SetErrorCode(interp, "CORE", "IDELETE",
+ "attempt to call eval in deleted interpreter",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+static int
+TclCompileByteCodesForEval(interp, objPtr)
+ Tcl_Interp *interp;
+ Tcl_Obj *objPtr;
+{
+ register Interp *iPtr = (Interp *) interp;
+ ByteCode *codePtr;
+ Namespace *namespacePtr;
+ int result;
+
+ /*
+ * Get the ByteCode from the object. If it exists, make sure it hasn't
+ * been invalidated by, e.g., someone redefining a command with a
+ * compile procedure (this might make the compiled code wrong). If
+ * necessary, convert the object to be a ByteCode object and compile it.
+ * Also, if the code was compiled in/for a different interpreter,
+ * or for a different namespace, or for the same namespace but
+ * with different name resolution rules, we recompile it.
+ *
+ * Precompiled objects, however, are immutable and therefore
+ * they are not recompiled, even if the epoch has changed.
+ *
+ * To be pedantically correct, we should also check that the
+ * originating procPtr is the same as the current context procPtr
+ * (assuming one exists at all - none for global level). This
+ * code is #def'ed out because [info body] was changed to never
+ * return a bytecode type object, which should obviate us from
+ * the extra checks here.
+ */
+
+ if (iPtr->varFramePtr != NULL) {
+ namespacePtr = iPtr->varFramePtr->nsPtr;
+ } else {
+ namespacePtr = iPtr->globalNsPtr;
+ }
+
+ if (objPtr->typePtr == &tclByteCodeType) {
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+ if (((Interp *) *codePtr->interpHandle != iPtr)
+ || (codePtr->compileEpoch != iPtr->compileEpoch)
+#ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
+ || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
+ iPtr->varFramePtr->procPtr == codePtr->procPtr))
+#endif
+ || (codePtr->nsPtr != namespacePtr)
+ || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
+ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+ if ((Interp *) *codePtr->interpHandle != iPtr) {
+ panic("Tcl_EvalObj: compiled script jumped interps");
+ }
+ codePtr->compileEpoch = iPtr->compileEpoch;
+ } else {
+ tclByteCodeType.freeIntRepProc(objPtr);
+ }
+ }
+ }
+ if (objPtr->typePtr != &tclByteCodeType) {
+ iPtr->errorLine = 1;
+ result = tclByteCodeType.setFromAnyProc(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ } else {
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+ if (((Interp *) *codePtr->interpHandle != iPtr)
+ || (codePtr->compileEpoch != iPtr->compileEpoch)) {
+ (*tclByteCodeType.freeIntRepProc)(objPtr);
+ iPtr->errorLine = 1;
+ result = (*tclByteCodeType.setFromAnyProc)(interp, objPtr);
+ if (result != TCL_OK) {
+ iPtr->numLevels--;
+ return result;
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+static int
+TclInterpPostEval(interp, evalFlags, result, objPtr, numSrcBytes)
+ Tcl_Interp *interp;
+ int evalFlags;
+ int result;
+ Tcl_Obj *objPtr;
+ int numSrcBytes;
+{
+ register Interp *iPtr = (Interp *) interp;
+
+ /*
+ * Update the interpreter's evaluation level count. If we will be
+ * again at the top level, process any unusual return code returned
+ * by the evaluated code.
+ */
+
+ if (iPtr->numLevels == 1) {
+ if (result == TCL_RETURN) {
+ result = TclUpdateReturnInfo(iPtr);
+ }
+ if ((result != TCL_OK) && (result != TCL_ERROR)
+ && ((evalFlags & TCL_ALLOW_EXCEPTIONS) == 0)) {
+ ProcessUnexpectedResult(interp, result);
+ result = TCL_ERROR;
+ }
+ }
+
+ /*
+ * If an error occurred, record information about what was being
+ * executed when the error occurred.
+ */
+
+ if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+ RecordTracebackInfo(interp, objPtr, numSrcBytes);
+ }
+
+ /*
+ * Set the interpreter's termOffset member to the offset of the
+ * character just after the last one executed. We approximate the offset
+ * of the last character executed by using the number of characters
+ * compiled.
+ */
+
+ iPtr->termOffset = numSrcBytes;
+ iPtr->flags &= ~ERR_ALREADY_LOGGED;
+ return result;
+}
+
+int
+TclEvalByteCodeFromObj(interp, objPtr, flags)
+ Tcl_Interp *interp;
+ Tcl_Obj *objPtr;
+ int flags;
+{
+ register Interp *iPtr = (Interp *) interp;
+ int evalFlags; /* Interp->evalFlags value when the
+ * procedure was called. */
+ register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
+ int oldCount = iPtr->cmdCount; /* Used to tell whether any commands
+ * at all were executed. */
+ int numSrcBytes;
+ int result;
+ CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
+ * in case TCL_EVAL_GLOBAL was set. */
+
+ Tcl_IncrRefCount(objPtr);
+
+ /*
+ * Reset both the interpreter's string and object results and clear out
+ * any error information. This makes sure that we return an empty
+ * result if there are no commands in the command string.
+ */
+
+ Tcl_ResetResult(interp);
+
+ /*
+ * Check that the interpreter is ready to execute scripts
+ */
+
+ if (TclInterpReady(interp) == TCL_ERROR) {
+ TclDecrRefCount(objPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Take care of the TCL_EVAL_GLOBAL case.
+ */
+
+ savedVarFramePtr = iPtr->varFramePtr;
+ if (flags & TCL_EVAL_GLOBAL) {
+ iPtr->varFramePtr = NULL;
+ }
+
+
+ /*
+ * Get the ByteCode from the object.
+ */
+
+ result = TclCompileByteCodesForEval(interp, objPtr);
+ if (result == TCL_ERROR) {
+ goto done;
+ }
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+ /*
+ * Extract then reset the compilation flags in the interpreter.
+ * Resetting the flags must be done after any compilation.
+ */
+
+ evalFlags = iPtr->evalFlags;
+ iPtr->evalFlags = 0;
+
+ /*
+ * Execute the commands. If the code was compiled from an empty string,
+ * don't bother executing the code.
+ */
+
+ iPtr->numLevels++;
+ numSrcBytes = codePtr->numSrcBytes;
+
+ if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
+ /*
+ * Increment the code's ref count while it is being executed. If
+ * afterwards no references to it remain, free the code.
+ */
+
+ codePtr->refCount++;
+ result = TclExecuteByteCode(interp, codePtr);
+ codePtr->refCount--;
+ if (codePtr->refCount <= 0) {
+ TclCleanupByteCode(codePtr);
+ }
+ } else {
+ result = TCL_OK;
+ }
+
+ /*
+ * If no commands at all were executed, check for asynchronous
+ * handlers so that they at least get one change to execute.
+ * This is needed to handle event loops written in Tcl with
+ * empty bodies.
+ */
+
+ if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
+ result = Tcl_AsyncInvoke(interp, result);
+ }
+
+ /*
+ * Update the interpreter's state
+ */
+
+ result = TclInterpPostEval(interp, evalFlags, result, objPtr, numSrcBytes);
+ iPtr->numLevels--;
+
+ done:
+ TclDecrRefCount(objPtr);
+ iPtr->varFramePtr = savedVarFramePtr;
+ return result;
+}
+
+static int
+TclCompileByteCodesForExpr(interp, objPtr)
+ Tcl_Interp *interp;
+ Tcl_Obj *objPtr;
+{
+ Interp *iPtr = (Interp *) interp;
+ TYPE (CompileEnv) compEnv; /* Compilation environment structure
+ * allocated in frame. */
+ LiteralTable *localTablePtr;
+ register ByteCode *codePtr = NULL;
+ /* Tcl Internal type of bytecode.
+ * Initialized to avoid compiler warning. */
+ AuxData *auxDataPtr;
+ LiteralEntry *entryPtr;
+ char *string;
+ int length, i, result;
+
+ NEWSTRUCT(CompileEnv,compEnv);
+ localTablePtr = &(ITEM(compEnv,localLitTable));
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+
+ /*
+ * Get the ByteCode from the object. If it exists, make sure it hasn't
+ * been invalidated by, e.g., someone redefining a command with a
+ * compile procedure (this might make the compiled code wrong). If
+ * necessary, convert the object to be a ByteCode object and compile it.
+ * Also, if the code was compiled in/for a different interpreter, we
+ * recompile it.
+ *
+ * Precompiled expressions, however, are immutable and therefore
+ * they are not recompiled, even if the epoch has changed.
+ *
+ */
+
+ if (objPtr->typePtr == &tclByteCodeType) {
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+ if (((Interp *) *codePtr->interpHandle != iPtr)
+ || (codePtr->compileEpoch != iPtr->compileEpoch)) {
+ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+ if ((Interp *) *codePtr->interpHandle != iPtr) {
+ panic("Tcl_ExprObj: compiled expression jumped interps");
+ }
+ codePtr->compileEpoch = iPtr->compileEpoch;
+ } else {
+ (*tclByteCodeType.freeIntRepProc)(objPtr);
+ objPtr->typePtr = (Tcl_ObjType *) NULL;
+ }
+ }
+ }
+ if (objPtr->typePtr != &tclByteCodeType) {
+ TclInitCompileEnv(interp, REF(compEnv), string, length);
+ result = TclCompileExpr(interp, string, length, REF(compEnv));
+
+ /*
+ * Free the compilation environment's literal table bucket array if
+ * it was dynamically allocated.
+ */
+
+ if (localTablePtr->buckets != localTablePtr->staticBuckets) {
+ ckfree((char *) localTablePtr->buckets);
+ }
+
+ if (result != TCL_OK) {
+ /*
+ * Compilation errors. Free storage allocated for compilation.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+ TclVerifyLocalLiteralTable(REF(compEnv));
+#endif /*TCL_COMPILE_DEBUG*/
+ entryPtr = ITEM(compEnv,literalArrayPtr);
+ for (i = 0; i < ITEM(compEnv,literalArrayNext); i++) {
+ TclReleaseLiteral(interp, entryPtr->objPtr);
+ entryPtr++;
+ }
+#ifdef TCL_COMPILE_DEBUG
+ TclVerifyGlobalLiteralTable(iPtr);
+#endif /*TCL_COMPILE_DEBUG*/
+
+ auxDataPtr = ITEM(compEnv,auxDataArrayPtr);
+ for (i = 0; i < ITEM(compEnv,auxDataArrayNext); i++) {
+ if (auxDataPtr->type->freeProc != NULL) {
+ auxDataPtr->type->freeProc(auxDataPtr->clientData);
+ }
+ auxDataPtr++;
+ }
+ TclFreeCompileEnv(REF(compEnv));
+ RELSTRUCT(compEnv);
+ return result;
+ }
+
+ /*
+ * Successful compilation. If the expression yielded no
+ * instructions, push an zero object as the expression's result.
+ */
+
+ if (ITEM(compEnv,codeNext) == ITEM(compEnv,codeStart)) {
+ TclEmitPush(TclRegisterLiteral(REF(compEnv), "0", 1, /*onHeap*/ 0),
+ REF(compEnv));
+ }
+
+ /*
+ * Add a "done" instruction as the last instruction and change the
+ * object into a ByteCode object. Ownership of the literal objects
+ * and aux data items is given to the ByteCode object.
+ */
+
+ ITEM(compEnv,numSrcBytes) = iPtr->termOffset;
+ TclEmitOpcode(INST_DONE, REF(compEnv));
+ TclInitByteCodeObj(objPtr, REF(compEnv));
+ TclFreeCompileEnv(REF(compEnv));
+ RELSTRUCT(compEnv);
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+#ifdef TCL_COMPILE_DEBUG
+ if (tclTraceCompile == 2) {
+ TclPrintByteCodeObj(interp, objPtr);
+ }
+#endif /* TCL_COMPILE_DEBUG */
+ }
+
+ return TCL_OK;
+}
+
+int
+TclExprByteCodeFromObj(interp, objPtr, resultPtrPtr)
+ Tcl_Interp *interp; /* Context in which to evaluate the
+ * expression. */
+ register Tcl_Obj *objPtr; /* Points to Tcl object containing
+ * expression to evaluate. */
+ Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
+ * result is stored if no errors occur. */
+{
+ Interp *iPtr = (Interp *) interp;
+ register ByteCode *codePtr = NULL;
+ /* Tcl Internal type of bytecode.
+ * Initialized to avoid compiler warning. */
+ Tcl_Obj *saveObjPtr;
+ int result;
+
+ /*
+ * Get the ByteCode from the object.
+ */
+
+ result = TclCompileByteCodesForExpr(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+ /*
+ * Execute the expression after first saving the interpreter's result.
+ */
+
+ saveObjPtr = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(saveObjPtr);
+ Tcl_ResetResult(interp);
+
+ /*
+ * Increment the code's ref count while it is being executed. If
+ * afterwards no references to it remain, free the code.
+ */
+
+ codePtr->refCount++;
+ result = TclExecuteByteCode(interp, codePtr);
+
+ codePtr->refCount--;
+ if (codePtr->refCount <= 0) {
+ TclCleanupByteCode(codePtr);
+ objPtr->typePtr = NULL;
+ objPtr->internalRep.otherValuePtr = NULL;
+ }
+
+ /*
+ * If the expression evaluated successfully, store a pointer to its
+ * value object in resultPtrPtr then restore the old interpreter result.
+ * We increment the object's ref count to reflect the reference that we
+ * are returning to the caller. We also decrement the ref count of the
+ * interpreter's result object after calling Tcl_SetResult since we
+ * next store into that field directly.
+ */
+
+ if (result == TCL_OK) {
+ *resultPtrPtr = iPtr->objResultPtr;
+ Tcl_IncrRefCount(iPtr->objResultPtr);
+
+ Tcl_SetObjResult(interp, saveObjPtr);
+ }
+ Tcl_DecrRefCount(saveObjPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInterpProc --
+ *
+ * When a Tcl procedure gets invoked during bytecode evaluation, this
+ * object-based routine gets invoked to interpret the procedure.
+ *
+ * Results:
+ * A standard Tcl object result value.
+ *
+ * Side effects:
+ * Depends on the commands in the procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PrepareProcFrameForExecution (interp, framePtr, objc, objv, compiledLocals)
+ Tcl_Interp *interp;
+ CallFrame *framePtr;
+ int objc;
+ Tcl_Obj *CONST objv[0];
+ Var *compiledLocals;
+{
+ register Proc *procPtr = framePtr->procPtr;
+ register Var *varPtr;
+ register CompiledLocal *localPtr;
+ Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
+ int numArgs, argCt, i, nameLen;
+ char *procName;
+
+
+ framePtr->objc = objc;
+ framePtr->objv = objv; /* ref counts for args are incremented below */
+ framePtr->numCompiledLocals = procPtr->numCompiledLocals;
+ framePtr->compiledLocals = compiledLocals;
+
+
+ /*
+ * Initialize and resolve compiled variable references.
+ */
+
+ TclInitCompiledLocals(interp, framePtr, nsPtr);
+
+ /*
+ * Match and assign the call's actual parameters to the procedure's
+ * formal arguments. The formal arguments are described by the first
+ * numArgs entries in both the Proc structure's local variable list and
+ * the call frame's local variable array.
+ */
+
+ numArgs = procPtr->numArgs;
+ varPtr = framePtr->compiledLocals;
+ localPtr = procPtr->firstLocalPtr;
+ argCt = objc;
+ for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) {
+ if (!TclIsVarArgument(localPtr)) {
+ panic("TclObjInterpProc: local variable %s is not argument but should be",
+ localPtr->name);
+ return TCL_ERROR;
+ }
+ if (TclIsVarTemporary(localPtr)) {
+ panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Handle the special case of the last formal being "args". When
+ * it occurs, assign it a list consisting of all the remaining
+ * actual arguments.
+ */
+
+ if ((i == numArgs) && ((localPtr->name[0] == 'a')
+ && (strcmp(localPtr->name, "args") == 0))) {
+ Tcl_Obj *listPtr = Tcl_NewListObj(argCt, &(objv[i]));
+ varPtr->value.objPtr = listPtr;
+ Tcl_IncrRefCount(listPtr); /* local var is a reference */
+ varPtr->flags &= ~VAR_UNDEFINED;
+ argCt = 0;
+ break; /* done processing args */
+ } else if (argCt > 0) {
+ Tcl_Obj *objPtr = objv[i];
+ varPtr->value.objPtr = objPtr;
+ varPtr->flags &= ~VAR_UNDEFINED;
+ Tcl_IncrRefCount(objPtr); /* since the local variable now has
+ * another reference to object. */
+ } else if (localPtr->defValuePtr != NULL) {
+ Tcl_Obj *objPtr = localPtr->defValuePtr;
+ varPtr->value.objPtr = objPtr;
+ varPtr->flags &= ~VAR_UNDEFINED;
+ Tcl_IncrRefCount(objPtr); /* since the local variable now has
+ * another reference to object. */
+ } else {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "no value given for parameter \"", localPtr->name,
+ "\" to \"", Tcl_GetString(objv[0]), "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ varPtr++;
+ localPtr = localPtr->nextPtr;
+ }
+ if (argCt > 0) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "called \"", Tcl_GetString(objv[0]),
+ "\" with too many arguments", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Invoke the commands in the procedure's body.
+ */
+
+ if (tclTraceExec >= 1) {
+#ifdef TCL_COMPILE_DEBUG
+ fprintf(stdout, "Calling proc ");
+ for (i = 0; i < objc; i++) {
+ TclPrintObject(stdout, objv[i], 15);
+ fprintf(stdout, " ");
+ }
+ fprintf(stdout, "\n");
+#else /* TCL_COMPILE_DEBUG */
+ procName = Tcl_GetStringFromObj(objv[0], &nameLen);
+ fprintf(stdout, "Calling proc %.*s\n", nameLen, procName);
+#endif /*TCL_COMPILE_DEBUG*/
+ fflush(stdout);
+ }
+ return TCL_OK;
+}
+
+int
+TclObjInterpProc(clientData, interp, objc, objv)
+ ClientData clientData; /* Record describing procedure to be
+ * interpreted. */
+ register Tcl_Interp *interp; /* Interpreter in which procedure was
+ * invoked. */
+ int objc; /* Count of number of arguments to this
+ * procedure. */
+ Tcl_Obj *CONST objv[]; /* Argument value objects. */
+{
+ Interp *iPtr = (Interp *) interp;
+ register Proc *procPtr = (Proc *) clientData;
+ Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
+ CallFrame frame;
+ register CallFrame *framePtr = &frame;
+ char *procName;
+ int nameLen, localCt, result;
+
+ /*
+ * This procedure generates an array "compiledLocals" that holds the
+ * storage for local variables. It starts out with stack-allocated space
+ * but uses dynamically-allocated storage if needed.
+ */
+
+#define NUM_LOCALS TCL_PROC_STATIC_CLOCALS
+ Var localStorage[NUM_LOCALS];
+ Var *compiledLocals = localStorage;
+
+ /*
+ * Get the procedure's name.
+ */
+
+ procName = Tcl_GetStringFromObj(objv[0], &nameLen);
+
+ /*
+ * If necessary, compile the procedure's body. The compiler will
+ * allocate frame slots for the procedure's non-argument local
+ * variables. Note that compiling the body might increase
+ * procPtr->numCompiledLocals if new local variables are found
+ * while compiling.
+ */
+
+ result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
+ "body of proc", procName);
+
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * Set up and push a new call frame for the new procedure invocation.
+ * This call frame will execute in the proc's namespace, which might
+ * be different than the current namespace. The proc's namespace is
+ * that of its command, which can change if the command is renamed
+ * from one namespace to another.
+ */
+
+ result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
+ (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
+ if (result != TCL_OK) {
+ return result;
+ }
+ framePtr->procPtr = procPtr;
+
+ /*
+ * Create the "compiledLocals" array. Make sure it is large enough to
+ * hold all the procedure's compiled local variables, including its
+ * formal parameters.
+ */
+
+ localCt = procPtr->numCompiledLocals;
+ if (localCt > NUM_LOCALS) {
+ compiledLocals = (Var *) ckalloc((unsigned) localCt * sizeof(Var));
+ }
+
+ result = PrepareProcFrameForExecution(interp, framePtr, objc, objv, compiledLocals);
+ if (result == TCL_ERROR) {
+ goto procDone;
+ }
+
+ iPtr->returnCode = TCL_OK;
+ procPtr->refCount++;
+ result = Tcl_EvalObjEx(interp, procPtr->bodyPtr, 0);
+ procPtr->refCount--;
+ if (procPtr->refCount <= 0) {
+ TclProcCleanupProc(procPtr);
+ }
+
+ if (result != TCL_OK) {
+ result = ProcessProcResultCode(interp, procName, nameLen, result);
+ }
+
+ /*
+ * Pop and free the call frame for this procedure invocation, then
+ * free the compiledLocals array if malloc'ed storage was used.
+ */
+
+ procDone:
+ Tcl_PopCallFrame(interp);
+ if (compiledLocals != localStorage) {
+ ckfree((char *) compiledLocals);
+ }
+ return result;
+#undef NUM_LOCALS
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcessProcResultCode --
+ *
+ * Procedure called by TclObjInterpProc to process a return code other
+ * than TCL_OK returned by a Tcl procedure.
+ *
+ * Results:
+ * Depending on the argument return code, the result returned is
+ * another return code and the interpreter's result is set to a value
+ * to supplement that return code.
+ *
+ * Side effects:
+ * If the result returned is TCL_ERROR, traceback information about
+ * the procedure just executed is appended to the interpreter's
+ * "errorInfo" variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ProcessProcResultCode(interp, procName, nameLen, returnCode)
+ Tcl_Interp *interp; /* The interpreter in which the procedure
+ * was called and returned returnCode. */
+ char *procName; /* Name of the procedure. Used for error
+ * messages and trace information. */
+ int nameLen; /* Number of bytes in procedure's name. */
+ int returnCode; /* The unexpected result code. */
+{
+ Interp *iPtr = (Interp *) interp;
+
+ if (returnCode == TCL_RETURN) {
+ returnCode = TclUpdateReturnInfo(iPtr);
+ } else if (returnCode == TCL_ERROR) {
+ char msg[100 + TCL_INTEGER_SPACE];
+ char *ellipsis = "";
+ int numChars = nameLen;
+
+ if (numChars > 60) {
+ numChars = 60;
+ ellipsis = "...";
+ }
+ sprintf(msg, "\n (procedure \"%.*s%s\" line %d)",
+ numChars, procName, ellipsis, iPtr->errorLine);
+ Tcl_AddObjErrorInfo(interp, msg, -1);
+ } else if (returnCode == TCL_BREAK) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "invoked \"break\" outside of a loop", -1);
+ returnCode = TCL_ERROR;
+ } else if (returnCode == TCL_CONTINUE) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "invoked \"continue\" outside of a loop", -1);
+ returnCode = TCL_ERROR;
+ }
+ return returnCode;
+}
diff --git a/generic/tclHash.c b/generic/tclHash.c
index 973c003..f9ab832 100644
--- a/generic/tclHash.c
+++ b/generic/tclHash.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclHash.c,v 1.3 1999/04/16 00:46:46 stanton Exp $
+ * RCS: @(#) $Id: tclHash.c,v 1.3.16.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -303,7 +303,7 @@ char *
Tcl_HashStats(tablePtr)
Tcl_HashTable *tablePtr; /* Table for which to produce stats. */
{
-#define NUM_COUNTERS 10
+#define NUM_COUNTERS TCL_STATS_COUNTERS
int count[NUM_COUNTERS], overflow, i, j;
double average, tmp;
register Tcl_HashEntry *hPtr;
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index af64531..34c86c6 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclListObj.c,v 1.7.8.1 2001/04/04 07:38:47 hobbs Exp $
+ * RCS: @(#) $Id: tclListObj.c,v 1.7.8.1.2.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -1006,7 +1006,7 @@ static void
UpdateStringOfList(listPtr)
Tcl_Obj *listPtr; /* List object with string rep to update. */
{
-# define LOCAL_SIZE 20
+# define LOCAL_SIZE TCL_MERGE_STATIC_LIST_SZ
int localFlags[LOCAL_SIZE], *flagPtr;
List *listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
int numElems = listRepPtr->elemCount;
diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c
index a3ed0cb..5cada38 100644
--- a/generic/tclLiteral.c
+++ b/generic/tclLiteral.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: tclLiteral.c,v 1.8.2.3 2001/10/11 22:34:11 msofer Exp $
+ * RCS: @(#) $Id: tclLiteral.c,v 1.8.2.3.2.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -895,7 +895,7 @@ char *
TclLiteralStats(tablePtr)
LiteralTable *tablePtr; /* Table for which to produce stats. */
{
-#define NUM_COUNTERS 10
+#define NUM_COUNTERS TCL_STATS_COUNTERS
int count[NUM_COUNTERS], overflow, i, j;
double average, tmp;
register LiteralEntry *entryPtr;
diff --git a/generic/tclParse.c b/generic/tclParse.c
index 8a508cb..652e26e 100644
--- a/generic/tclParse.c
+++ b/generic/tclParse.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclParse.c,v 1.13.2.1 2001/04/03 22:54:38 hobbs Exp $
+ * RCS: @(#) $Id: tclParse.c,v 1.13.2.1.2.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -540,7 +540,9 @@ ParseTokens(src, mask, parsePtr)
int type, originalTokens, varToken;
char utfBytes[TCL_UTF_MAX];
Tcl_Token *tokenPtr;
- Tcl_Parse nested;
+ TYPE (Tcl_Parse) nested;
+
+ NEWSTRUCT (Tcl_Parse,nested);
/*
* Each iteration through the following loop adds one token of
@@ -587,6 +589,7 @@ ParseTokens(src, mask, parsePtr)
varToken = parsePtr->numTokens;
if (Tcl_ParseVarName(parsePtr->interp, src, parsePtr->end - src,
parsePtr, 1) != TCL_OK) {
+ RELSTRUCT(nested);
return TCL_ERROR;
}
src += parsePtr->tokenPtr[varToken].size;
@@ -600,17 +603,18 @@ ParseTokens(src, mask, parsePtr)
src++;
while (1) {
if (Tcl_ParseCommand(parsePtr->interp, src,
- parsePtr->end - src, 1, &nested) != TCL_OK) {
- parsePtr->errorType = nested.errorType;
- parsePtr->term = nested.term;
- parsePtr->incomplete = nested.incomplete;
+ parsePtr->end - src, 1, REF(nested)) != TCL_OK) {
+ parsePtr->errorType = ITEM(nested,errorType);
+ parsePtr->term = ITEM(nested,term);
+ parsePtr->incomplete = ITEM(nested,incomplete);
+ RELSTRUCT(nested);
return TCL_ERROR;
}
- src = nested.commandStart + nested.commandSize;
- if (nested.tokenPtr != nested.staticTokens) {
- ckfree((char *) nested.tokenPtr);
+ src = ITEM (nested,commandStart) + ITEM (nested,commandSize);
+ if (ITEM (nested,tokenPtr) != ITEM (nested,staticTokens)) {
+ ckfree((char *) ITEM (nested,tokenPtr));
}
- if ((*nested.term == ']') && !nested.incomplete) {
+ if ((*ITEM (nested,term) == ']') && !ITEM (nested,incomplete)) {
break;
}
if (src == parsePtr->end) {
@@ -621,6 +625,7 @@ ParseTokens(src, mask, parsePtr)
parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
parsePtr->term = tokenPtr->start;
parsePtr->incomplete = 1;
+ RELSTRUCT(nested);
return TCL_ERROR;
}
}
@@ -682,6 +687,7 @@ ParseTokens(src, mask, parsePtr)
parsePtr->numTokens++;
}
parsePtr->term = src;
+ RELSTRUCT(nested);
return TCL_OK;
}
@@ -909,10 +915,10 @@ EvalObjv(interp, objc, objv, command, length, flags)
commandCopy[length] = 0;
}
}
- (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
+ (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
commandCopy, cmdPtr->proc, cmdPtr->clientData,
objc, argv);
- }
+ }
if (argv != NULL) {
ckfree((char *) argv);
}
@@ -929,7 +935,9 @@ EvalObjv(interp, objc, objv, command, length, flags)
if (flags & TCL_EVAL_GLOBAL) {
iPtr->varFramePtr = NULL;
}
+
code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
+
iPtr->varFramePtr = savedVarFramePtr;
if (Tcl_AsyncReady()) {
code = Tcl_AsyncInvoke(interp, code);
@@ -1152,7 +1160,7 @@ Tcl_EvalTokens(interp, tokenPtr, count)
#ifdef TCL_MEM_DEBUG
# define MAX_VAR_CHARS 5
#else
-# define MAX_VAR_CHARS 30
+# define MAX_VAR_CHARS TCL_EVAL_STATIC_VARCHARS
#endif
char nameBuffer[MAX_VAR_CHARS+1];
char *varName, *index;
@@ -1317,22 +1325,22 @@ Tcl_EvalEx(interp, script, numBytes, flags)
{
Interp *iPtr = (Interp *) interp;
char *p, *next;
- Tcl_Parse parse;
-#define NUM_STATIC_OBJS 20
+ TYPE (Tcl_Parse) parse;
+#define NUM_STATIC_OBJS TCL_INVOKE_STATIC_ARGS
Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;
Tcl_Token *tokenPtr;
int i, code, commandLength, bytesLeft, nested;
CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
* in case TCL_EVAL_GLOBAL was set. */
-
/*
* The variables below keep track of how much state has been
* allocated while evaluating the script, so that it can be freed
* properly if an error occurs.
*/
-
int gotParse = 0, objectsUsed = 0;
+ NEWSTRUCT(Tcl_Parse,parse);
+
if (numBytes < 0) {
numBytes = strlen(script);
}
@@ -1358,25 +1366,25 @@ Tcl_EvalEx(interp, script, numBytes, flags)
}
iPtr->evalFlags = 0;
do {
- if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse)
+ if (Tcl_ParseCommand(interp, p, bytesLeft, nested, REF(parse))
!= TCL_OK) {
code = TCL_ERROR;
goto error;
}
gotParse = 1;
- if (parse.numWords > 0) {
+ if (ITEM (parse,numWords) > 0) {
/*
* Generate an array of objects for the words of the command.
*/
- if (parse.numWords <= NUM_STATIC_OBJS) {
+ if (ITEM (parse,numWords) <= NUM_STATIC_OBJS) {
objv = staticObjArray;
} else {
objv = (Tcl_Obj **) ckalloc((unsigned)
- (parse.numWords * sizeof (Tcl_Obj *)));
+ (ITEM (parse,numWords) * sizeof (Tcl_Obj *)));
}
- for (objectsUsed = 0, tokenPtr = parse.tokenPtr;
- objectsUsed < parse.numWords;
+ for (objectsUsed = 0, tokenPtr = ITEM (parse,tokenPtr);
+ objectsUsed < ITEM (parse,numWords);
objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {
objv[objectsUsed] = Tcl_EvalTokens(interp, tokenPtr+1,
tokenPtr->numComponents);
@@ -1408,10 +1416,10 @@ Tcl_EvalEx(interp, script, numBytes, flags)
* Advance to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
+ next = ITEM (parse,commandStart) + ITEM (parse,commandSize);
bytesLeft -= next - p;
p = next;
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
gotParse = 0;
if ((nested != 0) && (p > script) && (p[-1] == ']')) {
/*
@@ -1422,9 +1430,11 @@ Tcl_EvalEx(interp, script, numBytes, flags)
iPtr->termOffset = (p - 1) - script;
iPtr->varFramePtr = savedVarFramePtr;
- return TCL_OK;
+ RELSTRUCT(parse);
+ return TCL_OK;
}
} while (bytesLeft > 0);
+ RELSTRUCT(parse);
iPtr->termOffset = p - script;
iPtr->varFramePtr = savedVarFramePtr;
return TCL_OK;
@@ -1438,8 +1448,8 @@ Tcl_EvalEx(interp, script, numBytes, flags)
*/
if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
- commandLength = parse.commandSize;
- if ((parse.commandStart + commandLength) != (script + numBytes)) {
+ commandLength = ITEM (parse,commandSize);
+ if ((ITEM (parse,commandStart) + commandLength) != (script + numBytes)) {
/*
* The command where the error occurred didn't end at the end
* of the script (i.e. it ended at a terminator character such
@@ -1449,17 +1459,17 @@ Tcl_EvalEx(interp, script, numBytes, flags)
commandLength -= 1;
}
- Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);
+ Tcl_LogCommandInfo(interp, script, ITEM (parse,commandStart), commandLength);
}
for (i = 0; i < objectsUsed; i++) {
Tcl_DecrRefCount(objv[i]);
}
if (gotParse) {
- next = parse.commandStart + parse.commandSize;
+ next = ITEM (parse,commandStart) + ITEM (parse,commandSize);
bytesLeft -= next - p;
p = next;
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
if ((nested != 0) && (p > script)) {
char *nextCmd = NULL; /* pointer to start of next command */
@@ -1473,7 +1483,7 @@ Tcl_EvalEx(interp, script, numBytes, flags)
*/
while ((p[-1] != ']') && bytesLeft) {
- if (Tcl_ParseCommand(NULL, p, bytesLeft, nested, &parse)
+ if (Tcl_ParseCommand(NULL, p, bytesLeft, nested, REF(parse))
!= TCL_OK) {
/*
* We were looking for the ']' to close the script.
@@ -1484,22 +1494,22 @@ Tcl_EvalEx(interp, script, numBytes, flags)
* one causing the return. -- hobbs
*/
- p = (nextCmd == NULL) ? parse.commandStart : nextCmd;
+ p = (nextCmd == NULL) ? ITEM (parse,commandStart) : nextCmd;
break;
}
if (nextCmd == NULL) {
- nextCmd = parse.commandStart;
+ nextCmd = ITEM (parse,commandStart);
}
/*
* Advance to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
+ next = ITEM (parse,commandStart) + ITEM (parse,commandSize);
bytesLeft -= next - p;
p = next;
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
}
iPtr->termOffset = (p - 1) - script;
} else {
@@ -1509,6 +1519,7 @@ Tcl_EvalEx(interp, script, numBytes, flags)
if (objv != staticObjArray) {
ckfree((char *) objv);
}
+ RELSTRUCT(parse);
iPtr->varFramePtr = savedVarFramePtr;
return code;
}
@@ -1581,7 +1592,9 @@ Tcl_EvalObj(interp, objPtr)
Tcl_Interp * interp;
Tcl_Obj * objPtr;
{
- return Tcl_EvalObjEx(interp, objPtr, 0);
+ register int res;
+ res = Tcl_EvalObjEx(interp, objPtr, 0);
+ return res;
}
#undef Tcl_GlobalEvalObj
@@ -1590,7 +1603,9 @@ Tcl_GlobalEvalObj(interp, objPtr)
Tcl_Interp * interp;
Tcl_Obj * objPtr;
{
- return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
+ register int res;
+ res = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
+ return res;
}
/*
@@ -1839,26 +1854,31 @@ Tcl_ParseVar(interp, string, termPtr)
* one in the variable specifier. */
{
- Tcl_Parse parse;
+ TYPE (Tcl_Parse) parse;
register Tcl_Obj *objPtr;
- if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {
+ NEWSTRUCT(Tcl_Parse,parse);
+
+ if (Tcl_ParseVarName(interp, string, -1, REF(parse), 0) != TCL_OK) {
+ RELSTRUCT(parse);
return NULL;
}
if (termPtr != NULL) {
- *termPtr = string + parse.tokenPtr->size;
+ *termPtr = string + ITEM (parse,tokenPtr)->size;
}
- if (parse.numTokens == 1) {
+ if (ITEM (parse,numTokens) == 1) {
/*
* There isn't a variable name after all: the $ is just a $.
*/
+ RELSTRUCT(parse);
return "$";
}
- objPtr = Tcl_EvalTokens(interp, parse.tokenPtr, parse.numTokens);
+ objPtr = Tcl_EvalTokens(interp, ITEM (parse,tokenPtr), ITEM (parse,numTokens));
if (objPtr == NULL) {
+ RELSTRUCT(parse);
return NULL;
}
@@ -1873,6 +1893,7 @@ Tcl_ParseVar(interp, string, termPtr)
}
#endif /*TCL_COMPILE_DEBUG*/
TclDecrRefCount(objPtr);
+ RELSTRUCT(parse);
return TclGetString(objPtr);
}
@@ -2197,26 +2218,29 @@ CommandComplete(script, length)
char *script; /* Script to check. */
int length; /* Number of bytes in script. */
{
- Tcl_Parse parse;
+ TYPE (Tcl_Parse) parse;
char *p, *end;
int result;
+ NEWSTRUCT(Tcl_Parse,parse);
+
p = script;
end = p + length;
- while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse)
+ while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, REF(parse))
== TCL_OK) {
- p = parse.commandStart + parse.commandSize;
+ p = ITEM (parse,commandStart) + ITEM (parse,commandSize);
if (*p == 0) {
break;
}
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
}
- if (parse.incomplete) {
+ if (ITEM (parse,incomplete)) {
result = 0;
} else {
result = 1;
}
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(REF(parse));
+ RELSTRUCT(parse);
return result;
}
@@ -2244,7 +2268,9 @@ int
Tcl_CommandComplete(script)
char *script; /* Script to check. */
{
- return CommandComplete(script, (int) strlen(script));
+ register int res;
+ res = CommandComplete(script, (int) strlen(script));
+ return res;
}
/*
diff --git a/generic/tclParseExpr.c b/generic/tclParseExpr.c
index b9c9d71..9b894f4 100644
--- a/generic/tclParseExpr.c
+++ b/generic/tclParseExpr.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclParseExpr.c,v 1.6 1999/12/04 06:15:42 hobbs Exp $
+ * RCS: @(#) $Id: tclParseExpr.c,v 1.6.6.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -1122,10 +1122,12 @@ ParsePrimaryExpr(infoPtr)
Tcl_Parse *parsePtr = infoPtr->parsePtr;
Tcl_Interp *interp = parsePtr->interp;
Tcl_Token *tokenPtr, *exprTokenPtr;
- Tcl_Parse nested;
+ TYPE (Tcl_Parse) nested;
char *dollarPtr, *stringStart, *termPtr, *src;
int lexeme, exprIndex, firstIndex, numToMove, code;
+ NEWSTRUCT(Tcl_Parse,nested);
+
/*
* We simply recurse on parenthesized subexpressions.
*/
@@ -1135,10 +1137,12 @@ ParsePrimaryExpr(infoPtr)
if (lexeme == OPEN_PAREN) {
code = GetLexeme(infoPtr); /* skip over the '(' */
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
code = ParseCondExpr(infoPtr);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
if (infoPtr->lexeme != CLOSE_PAREN) {
@@ -1146,8 +1150,10 @@ ParsePrimaryExpr(infoPtr)
}
code = GetLexeme(infoPtr); /* skip over the ')' */
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
+ RELSTRUCT(nested);
return TCL_OK;
}
@@ -1202,6 +1208,7 @@ ParsePrimaryExpr(infoPtr)
code = Tcl_ParseVarName(interp, dollarPtr,
(infoPtr->lastChar - dollarPtr), parsePtr, 1);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size;
@@ -1221,6 +1228,7 @@ ParsePrimaryExpr(infoPtr)
code = Tcl_ParseQuotedString(interp, infoPtr->start,
(infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
infoPtr->next = termPtr;
@@ -1277,17 +1285,18 @@ ParsePrimaryExpr(infoPtr)
src = infoPtr->next;
while (1) {
if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1,
- &nested) != TCL_OK) {
- parsePtr->term = nested.term;
- parsePtr->errorType = nested.errorType;
- parsePtr->incomplete = nested.incomplete;
+ REF (nested)) != TCL_OK) {
+ parsePtr->term = ITEM (nested,term);
+ parsePtr->errorType = ITEM (nested,errorType);
+ parsePtr->incomplete = ITEM (nested,incomplete);
+ RELSTRUCT(nested);
return TCL_ERROR;
}
- src = (nested.commandStart + nested.commandSize);
- if (nested.tokenPtr != nested.staticTokens) {
- ckfree((char *) nested.tokenPtr);
+ src = (ITEM (nested,commandStart) + ITEM (nested,commandSize));
+ if (ITEM (nested,tokenPtr) != ITEM (nested,staticTokens)) {
+ ckfree((char *) ITEM (nested,tokenPtr));
}
- if ((src[-1] == ']') && !nested.incomplete) {
+ if ((src[-1] == ']') && !ITEM (nested,incomplete)) {
break;
}
if (src == parsePtr->end) {
@@ -1298,6 +1307,7 @@ ParsePrimaryExpr(infoPtr)
parsePtr->term = tokenPtr->start;
parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
parsePtr->incomplete = 1;
+ RELSTRUCT(nested);
return TCL_ERROR;
}
}
@@ -1318,6 +1328,7 @@ ParsePrimaryExpr(infoPtr)
(infoPtr->lastChar - infoPtr->start), parsePtr, 1,
&termPtr);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
infoPtr->next = termPtr;
@@ -1369,6 +1380,7 @@ ParsePrimaryExpr(infoPtr)
code = GetLexeme(infoPtr); /* skip over function name */
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
if (infoPtr->lexeme != OPEN_PAREN) {
@@ -1376,18 +1388,21 @@ ParsePrimaryExpr(infoPtr)
}
code = GetLexeme(infoPtr); /* skip over '(' */
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
while (infoPtr->lexeme != CLOSE_PAREN) {
code = ParseCondExpr(infoPtr);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
if (infoPtr->lexeme == COMMA) {
code = GetLexeme(infoPtr); /* skip over , */
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
} else if (infoPtr->lexeme != CLOSE_PAREN) {
@@ -1410,13 +1425,16 @@ ParsePrimaryExpr(infoPtr)
code = GetLexeme(infoPtr);
if (code != TCL_OK) {
+ RELSTRUCT(nested);
return code;
}
parsePtr->term = infoPtr->next;
+ RELSTRUCT(nested);
return TCL_OK;
syntaxError:
LogSyntaxError(infoPtr);
+ RELSTRUCT(nested);
return TCL_ERROR;
}
diff --git a/generic/tclProc.c b/generic/tclProc.c
index feff5a0..32768eb 100644
--- a/generic/tclProc.c
+++ b/generic/tclProc.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclProc.c,v 1.23 1999/12/12 02:26:42 hobbs Exp $
+ * RCS: @(#) $Id: tclProc.c,v 1.23.6.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -25,8 +25,6 @@ static void ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr));
static int ProcBodySetFromAny _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *objPtr));
static void ProcBodyUpdateString _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int ProcessProcResultCode _ANSI_ARGS_((Tcl_Interp *interp,
- char *procName, int nameLen, int returnCode));
/*
* The ProcBodyObjType type
@@ -748,7 +746,7 @@ TclProcInterpProc(clientData, interp, argc, argv)
* dynamically-allocated storage if needed.
*/
-#define NUM_ARGS 20
+#define NUM_ARGS TCL_PROC_STATIC_ARGS
Tcl_Obj *(objStorage[NUM_ARGS]);
register Tcl_Obj **objv = objStorage;
@@ -807,224 +805,6 @@ TclProcInterpProc(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
- * TclObjInterpProc --
- *
- * When a Tcl procedure gets invoked during bytecode evaluation, this
- * object-based routine gets invoked to interpret the procedure.
- *
- * Results:
- * A standard Tcl object result value.
- *
- * Side effects:
- * Depends on the commands in the procedure.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclObjInterpProc(clientData, interp, objc, objv)
- ClientData clientData; /* Record describing procedure to be
- * interpreted. */
- register Tcl_Interp *interp; /* Interpreter in which procedure was
- * invoked. */
- int objc; /* Count of number of arguments to this
- * procedure. */
- Tcl_Obj *CONST objv[]; /* Argument value objects. */
-{
- Interp *iPtr = (Interp *) interp;
- register Proc *procPtr = (Proc *) clientData;
- Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
- CallFrame frame;
- register CallFrame *framePtr = &frame;
- register Var *varPtr;
- register CompiledLocal *localPtr;
- char *procName;
- int nameLen, localCt, numArgs, argCt, i, result;
-
- /*
- * This procedure generates an array "compiledLocals" that holds the
- * storage for local variables. It starts out with stack-allocated space
- * but uses dynamically-allocated storage if needed.
- */
-
-#define NUM_LOCALS 20
- Var localStorage[NUM_LOCALS];
- Var *compiledLocals = localStorage;
-
- /*
- * Get the procedure's name.
- */
-
- procName = Tcl_GetStringFromObj(objv[0], &nameLen);
-
- /*
- * If necessary, compile the procedure's body. The compiler will
- * allocate frame slots for the procedure's non-argument local
- * variables. Note that compiling the body might increase
- * procPtr->numCompiledLocals if new local variables are found
- * while compiling.
- */
-
- result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
- "body of proc", procName);
-
- if (result != TCL_OK) {
- return result;
- }
-
- /*
- * Create the "compiledLocals" array. Make sure it is large enough to
- * hold all the procedure's compiled local variables, including its
- * formal parameters.
- */
-
- localCt = procPtr->numCompiledLocals;
- if (localCt > NUM_LOCALS) {
- compiledLocals = (Var *) ckalloc((unsigned) localCt * sizeof(Var));
- }
-
- /*
- * Set up and push a new call frame for the new procedure invocation.
- * This call frame will execute in the proc's namespace, which might
- * be different than the current namespace. The proc's namespace is
- * that of its command, which can change if the command is renamed
- * from one namespace to another.
- */
-
- result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
- (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
-
- if (result != TCL_OK) {
- return result;
- }
-
- framePtr->objc = objc;
- framePtr->objv = objv; /* ref counts for args are incremented below */
-
- /*
- * Initialize and resolve compiled variable references.
- */
-
- framePtr->procPtr = procPtr;
- framePtr->numCompiledLocals = localCt;
- framePtr->compiledLocals = compiledLocals;
-
- TclInitCompiledLocals(interp, framePtr, nsPtr);
-
- /*
- * Match and assign the call's actual parameters to the procedure's
- * formal arguments. The formal arguments are described by the first
- * numArgs entries in both the Proc structure's local variable list and
- * the call frame's local variable array.
- */
-
- numArgs = procPtr->numArgs;
- varPtr = framePtr->compiledLocals;
- localPtr = procPtr->firstLocalPtr;
- argCt = objc;
- for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) {
- if (!TclIsVarArgument(localPtr)) {
- panic("TclObjInterpProc: local variable %s is not argument but should be",
- localPtr->name);
- return TCL_ERROR;
- }
- if (TclIsVarTemporary(localPtr)) {
- panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
- return TCL_ERROR;
- }
-
- /*
- * Handle the special case of the last formal being "args". When
- * it occurs, assign it a list consisting of all the remaining
- * actual arguments.
- */
-
- if ((i == numArgs) && ((localPtr->name[0] == 'a')
- && (strcmp(localPtr->name, "args") == 0))) {
- Tcl_Obj *listPtr = Tcl_NewListObj(argCt, &(objv[i]));
- varPtr->value.objPtr = listPtr;
- Tcl_IncrRefCount(listPtr); /* local var is a reference */
- varPtr->flags &= ~VAR_UNDEFINED;
- argCt = 0;
- break; /* done processing args */
- } else if (argCt > 0) {
- Tcl_Obj *objPtr = objv[i];
- varPtr->value.objPtr = objPtr;
- varPtr->flags &= ~VAR_UNDEFINED;
- Tcl_IncrRefCount(objPtr); /* since the local variable now has
- * another reference to object. */
- } else if (localPtr->defValuePtr != NULL) {
- Tcl_Obj *objPtr = localPtr->defValuePtr;
- varPtr->value.objPtr = objPtr;
- varPtr->flags &= ~VAR_UNDEFINED;
- Tcl_IncrRefCount(objPtr); /* since the local variable now has
- * another reference to object. */
- } else {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "no value given for parameter \"", localPtr->name,
- "\" to \"", Tcl_GetString(objv[0]), "\"", (char *) NULL);
- result = TCL_ERROR;
- goto procDone;
- }
- varPtr++;
- localPtr = localPtr->nextPtr;
- }
- if (argCt > 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "called \"", Tcl_GetString(objv[0]),
- "\" with too many arguments", (char *) NULL);
- result = TCL_ERROR;
- goto procDone;
- }
-
- /*
- * Invoke the commands in the procedure's body.
- */
-
- if (tclTraceExec >= 1) {
-#ifdef TCL_COMPILE_DEBUG
- fprintf(stdout, "Calling proc ");
- for (i = 0; i < objc; i++) {
- TclPrintObject(stdout, objv[i], 15);
- fprintf(stdout, " ");
- }
- fprintf(stdout, "\n");
-#else /* TCL_COMPILE_DEBUG */
- fprintf(stdout, "Calling proc %.*s\n", nameLen, procName);
-#endif /*TCL_COMPILE_DEBUG*/
- fflush(stdout);
- }
-
- iPtr->returnCode = TCL_OK;
- procPtr->refCount++;
- result = Tcl_EvalObjEx(interp, procPtr->bodyPtr, 0);
- procPtr->refCount--;
- if (procPtr->refCount <= 0) {
- TclProcCleanupProc(procPtr);
- }
-
- if (result != TCL_OK) {
- result = ProcessProcResultCode(interp, procName, nameLen, result);
- }
-
- /*
- * Pop and free the call frame for this procedure invocation, then
- * free the compiledLocals array if malloc'ed storage was used.
- */
-
- procDone:
- Tcl_PopCallFrame(interp);
- if (compiledLocals != localStorage) {
- ckfree((char *) compiledLocals);
- }
- return result;
-#undef NUM_LOCALS
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclProcCompileProc --
*
* Called just before a procedure is executed to compile the
@@ -1180,66 +960,6 @@ TclProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description, procName)
/*
*----------------------------------------------------------------------
*
- * ProcessProcResultCode --
- *
- * Procedure called by TclObjInterpProc to process a return code other
- * than TCL_OK returned by a Tcl procedure.
- *
- * Results:
- * Depending on the argument return code, the result returned is
- * another return code and the interpreter's result is set to a value
- * to supplement that return code.
- *
- * Side effects:
- * If the result returned is TCL_ERROR, traceback information about
- * the procedure just executed is appended to the interpreter's
- * "errorInfo" variable.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ProcessProcResultCode(interp, procName, nameLen, returnCode)
- Tcl_Interp *interp; /* The interpreter in which the procedure
- * was called and returned returnCode. */
- char *procName; /* Name of the procedure. Used for error
- * messages and trace information. */
- int nameLen; /* Number of bytes in procedure's name. */
- int returnCode; /* The unexpected result code. */
-{
- Interp *iPtr = (Interp *) interp;
-
- if (returnCode == TCL_RETURN) {
- returnCode = TclUpdateReturnInfo(iPtr);
- } else if (returnCode == TCL_ERROR) {
- char msg[100 + TCL_INTEGER_SPACE];
- char *ellipsis = "";
- int numChars = nameLen;
-
- if (numChars > 60) {
- numChars = 60;
- ellipsis = "...";
- }
- sprintf(msg, "\n (procedure \"%.*s%s\" line %d)",
- numChars, procName, ellipsis, iPtr->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
- } else if (returnCode == TCL_BREAK) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"break\" outside of a loop", -1);
- returnCode = TCL_ERROR;
- } else if (returnCode == TCL_CONTINUE) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"continue\" outside of a loop", -1);
- returnCode = TCL_ERROR;
- }
- return returnCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclProcDeleteProc --
*
* This procedure is invoked just before a command procedure is
diff --git a/generic/tclResult.c b/generic/tclResult.c
index 663f47f..517970c 100644
--- a/generic/tclResult.c
+++ b/generic/tclResult.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclResult.c,v 1.4 1999/10/21 02:16:22 hobbs Exp $
+ * RCS: @(#) $Id: tclResult.c,v 1.4.20.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -455,7 +455,8 @@ Tcl_AppendResultVA (interp, argList)
* return value. */
va_list argList; /* Variable argument list. */
{
-#define STATIC_LIST_SIZE 16
+#define STATIC_LIST_SIZE TCL_RESULT_APPEND_STATIC_LIST_SZ
+#define STATIC_LIST_INCR 16
Interp *iPtr = (Interp *) interp;
char *string, *static_list[STATIC_LIST_SIZE];
char **args = static_list;
@@ -490,7 +491,7 @@ Tcl_AppendResultVA (interp, argList)
/*
* Expand the args buffer
*/
- nargs_space += STATIC_LIST_SIZE;
+ nargs_space += STATIC_LIST_INCR;
if (args == static_list) {
args = (void *)ckalloc(nargs_space * sizeof(char *));
for (i = 0; i < nargs; ++i) {
diff --git a/generic/tclScan.c b/generic/tclScan.c
index 2f013c3..4059136 100644
--- a/generic/tclScan.c
+++ b/generic/tclScan.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclScan.c,v 1.6.2.2 2001/09/20 01:13:16 hobbs Exp $
+ * RCS: @(#) $Id: tclScan.c,v 1.6.2.2.2.1 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -263,7 +263,8 @@ ValidateFormat(interp, format, numVars, totalSubs)
int *totalSubs; /* The number of variables that will be
* required. */
{
-#define STATIC_LIST_SIZE 16
+#define STATIC_LIST_SIZE TCL_FMT_STATIC_VALIDATE_LIST
+#define STATIC_LIST_INCR 16
int gotXpg, gotSequential, value, i, flags;
char *end;
Tcl_UniChar ch;
@@ -441,7 +442,7 @@ ValidateFormat(interp, format, numVars, totalSubs)
if (xpgSize) {
nspace = xpgSize;
} else {
- nspace += STATIC_LIST_SIZE;
+ nspace += STATIC_LIST_INCR;
}
if (nassign == staticAssign) {
nassign = (void *)ckalloc(nspace * sizeof(int));
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index 62cdef1..2bbe053 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -33,7 +33,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStringObj.c,v 1.15 1999/11/19 06:34:25 hobbs Exp $ */
+ * RCS: @(#) $Id: tclStringObj.c,v 1.15.6.1 2001/12/03 18:23:14 andreas_kupries Exp $ */
#include "tclInt.h"
@@ -1196,7 +1196,8 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
Tcl_Obj *objPtr; /* Points to the object to append to. */
va_list argList; /* Variable argument list. */
{
-#define STATIC_LIST_SIZE 16
+#define STATIC_LIST_SIZE TCL_RESULT_APPEND_STATIC_LIST_SZ
+#define STATIC_LIST_INCR 16
String *stringPtr;
int newLength, oldLength;
register char *string, *dst;
@@ -1229,7 +1230,7 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
/*
* Expand the args buffer
*/
- nargs_space += STATIC_LIST_SIZE;
+ nargs_space += STATIC_LIST_INCR;
if (args == static_list) {
args = (void *)ckalloc(nargs_space * sizeof(char *));
for (i = 0; i < nargs; ++i) {
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index 2e1185f..46fc51b 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUtil.c,v 1.17.2.1.2.1 2001/11/28 17:58:37 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclUtil.c,v 1.17.2.1.2.2 2001/12/03 18:23:14 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -824,7 +824,7 @@ Tcl_Merge(argc, argv)
int argc; /* How many strings to merge. */
char **argv; /* Array of string values. */
{
-# define LOCAL_SIZE 20
+# define LOCAL_SIZE TCL_MERGE_STATIC_LIST_SZ
int localFlags[LOCAL_SIZE], *flagPtr;
int numChars;
char *result;