summaryrefslogtreecommitdiffstats
path: root/generic/tclProc.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2007-07-31 17:03:34 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2007-07-31 17:03:34 (GMT)
commitc78aef8e3103f916ede55e36edd8f5fb876ab0f6 (patch)
tree6bef95f9839cbc6e08ab7040bd9bbd6c9925a5f8 /generic/tclProc.c
parent4de8702e9bdf3ad59efdba5918502f6b9f23c827 (diff)
downloadtcl-c78aef8e3103f916ede55e36edd8f5fb876ab0f6.zip
tcl-c78aef8e3103f916ede55e36edd8f5fb876ab0f6.tar.gz
tcl-c78aef8e3103f916ede55e36edd8f5fb876ab0f6.tar.bz2
VarReform [Patch 1750051]
*** POTENTIAL INCOMPATIBILITY *** (tclInt.h and tclCompile.h)
Diffstat (limited to 'generic/tclProc.c')
-rw-r--r--generic/tclProc.c523
1 files changed, 307 insertions, 216 deletions
diff --git a/generic/tclProc.c b/generic/tclProc.c
index 8cd8aa1..c6e0219 100644
--- a/generic/tclProc.c
+++ b/generic/tclProc.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: tclProc.c,v 1.125 2007/06/20 18:46:14 dgp Exp $
+ * RCS: @(#) $Id: tclProc.c,v 1.126 2007/07/31 17:03:39 msofer Exp $
*/
#include "tclInt.h"
@@ -27,13 +27,15 @@ static void FreeLambdaInternalRep(Tcl_Obj *objPtr);
static int InitArgsAndLocals(Tcl_Interp *interp,
Tcl_Obj *procNameObj, int skip);
static void InitCompiledLocals(Tcl_Interp *interp,
- ByteCode *codePtr, CompiledLocal *localPtr,
- Var *varPtr, Namespace *nsPtr);
+ ByteCode *codePtr, Var *defPtr,
+ Namespace *nsPtr);
+static void InitLocalCache(Proc *procPtr);
static int PushProcCallFrame(ClientData clientData,
register Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[], int isLambda);
static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void ProcBodyFree(Tcl_Obj *objPtr);
+static int ProcWrongNumArgs(Tcl_Interp *interp, int skip);
static void MakeProcError(Tcl_Interp *interp,
Tcl_Obj *procNameObj);
static void MakeLambdaError(Tcl_Interp *interp,
@@ -527,13 +529,17 @@ TclCreateProc(
* we and out VAR_UNDEFINED to support bridging precompiled <= 8.3
* code in 8.4 where this is now used as an optimization
* indicator. Yes, this is a hack. -- hobbs
+ *
+ * FIXME! Is this right? It does depend on VAR_ARGUMENT not
+ * changing. Note that a change of VAR_TEMPORARY would not be so
+ * important, as there are no variable names in precompiled
+ * bytecodes anyway - right?
*/
if ((localPtr->nameLength != nameLength)
|| (strcmp(localPtr->name, fieldValues[0]))
|| (localPtr->frameIndex != i)
- || ((localPtr->flags & ~VAR_UNDEFINED)
- != (VAR_SCALAR | VAR_ARGUMENT))
+ || !(localPtr->flags & VAR_ARGUMENT) /* /// CHECK HERE! */
|| (localPtr->defValuePtr == NULL && fieldCount == 2)
|| (localPtr->defValuePtr != NULL && fieldCount != 2)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
@@ -588,7 +594,7 @@ TclCreateProc(
localPtr->nextPtr = NULL;
localPtr->nameLength = nameLength;
localPtr->frameIndex = i;
- localPtr->flags = VAR_SCALAR | VAR_ARGUMENT;
+ localPtr->flags = VAR_ARGUMENT;
localPtr->resolveInfo = NULL;
if (fieldCount == 2) {
@@ -1031,161 +1037,21 @@ TclIsProc(
*/
static int
-InitArgsAndLocals(
- register Tcl_Interp *interp,/* Interpreter in which procedure was
- * invoked. */
- Tcl_Obj *procNameObj, /* Procedure name for error reporting. */
- int skip) /* Number of initial arguments to be skipped,
- * i.e., words in the "command name". */
+ProcWrongNumArgs(
+ Tcl_Interp *interp, int skip)
{
CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
register Proc *procPtr = framePtr->procPtr;
- ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
- register Var *varPtr;
- register CompiledLocal *localPtr;
- int localCt, numArgs, argCt, i, imax;
- Var *compiledLocals;
- Tcl_Obj *const *argObjs;
+ register Var *defPtr;
+ int localCt = procPtr->numCompiledLocals, numArgs, i;
Tcl_Obj **desiredObjs;
- const char *final;
-
- /*
- * 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;
- compiledLocals = (Var*) TclStackAlloc(interp, (int)(localCt*sizeof(Var)));
- framePtr->numCompiledLocals = localCt;
- framePtr->compiledLocals = compiledLocals;
-
- /*
- * 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;
- argCt = framePtr->objc - skip; /* Set it to the number of args to the
- * procedure. */
- argObjs = framePtr->objv + skip;
- varPtr = framePtr->compiledLocals;
- localPtr = procPtr->firstLocalPtr;
- if (numArgs == 0) {
- if (argCt) {
- goto incorrectArgs;
- } else {
- goto correctArgs;
- }
- }
- imax = ((argCt < numArgs-1) ? argCt : numArgs-1);
- for (i = 0; i < imax; i++) {
- /*
- * "Normal" arguments; last formal is special, depends on it being
- * 'args'.
- */
-
- Tcl_Obj *objPtr = argObjs[i];
-
- varPtr->value.objPtr = objPtr;
- Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
- varPtr->name = localPtr->name;
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = localPtr->flags;
- varPtr++;
- localPtr = localPtr->nextPtr;
- }
- for (; i < numArgs-1; i++) {
- /*
- * This loop is entered if argCt < (numArgs-1). Set default values;
- * last formal is special.
- */
-
- if (localPtr->defValuePtr != NULL) {
- Tcl_Obj *objPtr = localPtr->defValuePtr;
-
- varPtr->value.objPtr = objPtr;
- Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
- varPtr->name = localPtr->name;
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = localPtr->flags;
- varPtr++;
- localPtr = localPtr->nextPtr;
- } else {
- goto incorrectArgs;
- }
- }
-
- /*
- * When we get here, the last formal argument remains to be defined:
- * localPtr and varPtr point to the last argument to be initialized.
- */
-
- if (localPtr->flags & VAR_IS_ARGS) {
- Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i);
-
- varPtr->value.objPtr = listPtr;
- Tcl_IncrRefCount(listPtr); /* Local var is a reference. */
- } else if (argCt == numArgs) {
- Tcl_Obj *objPtr = argObjs[i];
-
- varPtr->value.objPtr = objPtr;
- Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
- } else if ((argCt < numArgs) && (localPtr->defValuePtr != NULL)) {
- Tcl_Obj *objPtr = localPtr->defValuePtr;
-
- varPtr->value.objPtr = objPtr;
- Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
- } else {
- goto incorrectArgs;
- }
-
- varPtr->name = localPtr->name;
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = localPtr->flags;
-
- localPtr = localPtr->nextPtr;
- varPtr++;
-
- /*
- * Initialise and resolve the remaining compiledLocals.
- */
-
- correctArgs:
- if (localPtr) {
- InitCompiledLocals(interp, codePtr, localPtr, varPtr, framePtr->nsPtr);
- }
-
- return TCL_OK;
-
-
- incorrectArgs:
- /*
- * Do initialise all compiled locals, to avoid problems at
- * DeleteLocalVars.
- */
-
- final = NULL;
- InitCompiledLocals(interp, codePtr, localPtr, varPtr, framePtr->nsPtr);
-
+ const char *final = NULL;
+
/*
* Build up desired argument list for Tcl_WrongNumArgs
*/
+ numArgs = framePtr->procPtr->numArgs;
desiredObjs = (Tcl_Obj **) TclStackAlloc(interp,
(int) sizeof(Tcl_Obj *) * (numArgs+1));
@@ -1198,22 +1064,23 @@ InitArgsAndLocals(
#endif /* AVOID_HACKS_FOR_ITCL */
Tcl_IncrRefCount(desiredObjs[0]);
- localPtr = procPtr->firstLocalPtr;
- for (i=1 ; i<=numArgs ; i++) {
+ defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
+ for (i=1 ; i<=numArgs ; i++, defPtr++) {
Tcl_Obj *argObj;
+ Tcl_Obj *namePtr = localName(framePtr, i-1);
- if (localPtr->defValuePtr != NULL) {
+ if (defPtr->value.objPtr != NULL) {
TclNewObj(argObj);
- Tcl_AppendStringsToObj(argObj, "?", localPtr->name, "?", NULL);
- } else if ((i==numArgs) && !strcmp(localPtr->name, "args")) {
+ Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL);
+ } else if (defPtr->flags & VAR_IS_ARGS) {
numArgs--;
final = "...";
break;
} else {
- argObj = Tcl_NewStringObj(localPtr->name, -1);
+ argObj = namePtr;
+ Tcl_IncrRefCount(namePtr);
}
desiredObjs[i] = argObj;
- localPtr = localPtr->nextPtr;
}
Tcl_ResetResult(interp);
@@ -1229,6 +1096,46 @@ InitArgsAndLocals(
/*
*----------------------------------------------------------------------
*
+ * TclInitCompiledLocals --
+ *
+ * This routine is invoked in order to initialize the compiled locals
+ * table for a new call frame.
+ *
+ * DEPRECATED: functionality has been inlined elsewhere; this function
+ * remains to insure binary compatibility with Itcl.
+ *
+
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May invoke various name resolvers in order to determine which
+ * variables are being referenced at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclInitCompiledLocals(
+ Tcl_Interp *interp, /* Current interpreter. */
+ CallFrame *framePtr, /* Call frame to initialize. */
+ Namespace *nsPtr) /* Pointer to current namespace. */
+{
+ Var *varPtr = framePtr->compiledLocals;
+ Tcl_Obj *bodyPtr;
+ ByteCode *codePtr;
+
+ bodyPtr = framePtr->procPtr->bodyPtr;
+ if (bodyPtr->typePtr != &tclByteCodeType) {
+ Tcl_Panic("body object for proc attached to frame is not a byte code type");
+ }
+ codePtr = bodyPtr->internalRep.otherValuePtr;
+
+ InitCompiledLocals(interp, codePtr, varPtr, nsPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* InitCompiledLocals --
*
* This routine is invoked in order to initialize the compiled locals
@@ -1248,14 +1155,29 @@ static void
InitCompiledLocals(
Tcl_Interp *interp, /* Current interpreter. */
ByteCode *codePtr,
- CompiledLocal *localPtr,
Var *varPtr,
Namespace *nsPtr) /* Pointer to current namespace. */
{
Interp *iPtr = (Interp *) interp;
int haveResolvers = (nsPtr->compiledVarResProc || iPtr->resolverPtr);
- CompiledLocal *firstLocalPtr;
+ CompiledLocal *firstLocalPtr, *localPtr;
+ int varNum;
+
+ /*
+ * Find the localPtr corresponding to varPtr
+ */
+ varNum = varPtr - iPtr->framePtr->compiledLocals;
+ localPtr = iPtr->framePtr->procPtr->firstLocalPtr;
+ while (varNum--) {
+ localPtr = localPtr->nextPtr;
+ }
+
+ /*
+ //FIXME: old bytecompiled code: drop whatever flags are coming in (except
+ //maybe for VAR_TEMPORARY? Who cares really?) A job for tbcload, not us.
+ */
+
if (!(haveResolvers && (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS))) {
/*
* Initialize the array of local variables stored in the call frame.
@@ -1266,31 +1188,21 @@ InitCompiledLocals(
doInitCompiledLocals:
if (!haveResolvers) {
+ /*
+ * Should not be called: deadwood.
+ */
+
for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) {
- varPtr->value.objPtr = NULL;
- varPtr->name = localPtr->name; /* Will be just '\0' if temp
- * var. */
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
varPtr->flags = localPtr->flags;
+ varPtr->value.objPtr = NULL;
}
return;
} else {
Tcl_ResolvedVarInfo *resVarInfo;
for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) {
- varPtr->value.objPtr = NULL;
- varPtr->name = localPtr->name; /* Will be just '\0' if temp
- * var. */
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
varPtr->flags = localPtr->flags;
+ varPtr->value.objPtr = NULL;
/*
* Now invoke the resolvers to determine the exact variables
@@ -1302,9 +1214,9 @@ InitCompiledLocals(
Var *resolvedVarPtr = (Var *)
(*resVarInfo->fetchProc)(interp, resVarInfo);
if (resolvedVarPtr) {
- resolvedVarPtr->refCount++;
- varPtr->value.linkPtr = resolvedVarPtr;
+ VarHashRefCount(resolvedVarPtr)++;
varPtr->flags = VAR_LINK;
+ varPtr->value.linkPtr = resolvedVarPtr;
}
}
}
@@ -1361,46 +1273,224 @@ InitCompiledLocals(
goto doInitCompiledLocals;
}
}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclInitCompiledLocals --
- *
- * This routine is invoked in order to initialize the compiled locals
- * table for a new call frame.
- *
- * DEPRECATED: functionality has been inlined elsewhere; this function
- * remains to insure binary compatibility with Itcl.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May invoke various name resolvers in order to determine which
- * variables are being referenced at runtime.
- *
- *----------------------------------------------------------------------
- */
void
-TclInitCompiledLocals(
- Tcl_Interp *interp, /* Current interpreter. */
- CallFrame *framePtr, /* Call frame to initialize. */
- Namespace *nsPtr) /* Pointer to current namespace. */
+TclFreeLocalCache(
+ Tcl_Interp *interp,
+ LocalCache *localCachePtr)
{
- Var *varPtr = framePtr->compiledLocals;
- Tcl_Obj *bodyPtr;
- ByteCode *codePtr;
- CompiledLocal *localPtr = framePtr->procPtr->firstLocalPtr;
+ int i;
+ Tcl_Obj **namePtrPtr = &localCachePtr->varName0;
- bodyPtr = framePtr->procPtr->bodyPtr;
- if (bodyPtr->typePtr != &tclByteCodeType) {
- Tcl_Panic("body object for proc attached to frame is not a byte code type");
+ for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) {
+ Tcl_Obj *objPtr = *namePtrPtr;
+ /*
+ * Note that this can be called with interp==NULL, on interp
+ * deletion. In that case, the literal table and objects go away
+ * on their own.
+ */
+ if (objPtr) {
+ if (interp) {
+ TclReleaseLiteral(interp, objPtr);
+ } else {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
}
- codePtr = bodyPtr->internalRep.otherValuePtr;
+ ckfree((char *) localCachePtr);
+}
- InitCompiledLocals(interp, codePtr, localPtr, varPtr, nsPtr);
+static void
+InitLocalCache(Proc *procPtr)
+{
+ Interp *iPtr = procPtr->iPtr;
+ ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
+ CompiledLocal *localPtr = codePtr->procPtr->firstLocalPtr;
+ int localCt = procPtr->numCompiledLocals;
+ int numArgs = procPtr->numArgs, i = 0;
+
+ Tcl_Obj **namePtr;
+ Var *varPtr;
+ LocalCache *localCachePtr;
+ int new;
+
+ /*
+ * Cache the names and initial values of local variables; store the
+ * cache in both the framePtr for this execution and in the codePtr
+ * for future calls.
+ */
+
+ localCachePtr = (LocalCache *) ckalloc(sizeof(LocalCache)
+ + (localCt-1)*sizeof(Tcl_Obj *)
+ + numArgs*sizeof(Var));
+
+ namePtr = &localCachePtr->varName0;
+ varPtr = (Var *) (namePtr + localCt);
+ localPtr = codePtr->procPtr->firstLocalPtr;
+ while (localPtr) {
+ if (TclIsVarTemporary(localPtr)) {
+ *namePtr = NULL;
+ } else {
+ *namePtr = TclCreateLiteral(iPtr, localPtr->name,
+ localPtr->nameLength, /* hash */ (unsigned int) -1,
+ &new, /* nsPtr */ NULL, 0, NULL);
+ Tcl_IncrRefCount(*namePtr);
+ }
+
+ if (i < numArgs) {
+ varPtr->flags = (localPtr->flags & VAR_IS_ARGS);
+ varPtr->value.objPtr = localPtr->defValuePtr;
+ varPtr++;
+ i++;
+ }
+ namePtr++;
+ localPtr=localPtr->nextPtr;
+ }
+ codePtr->localCachePtr = localCachePtr;
+ localCachePtr->refCount = 1;
+ localCachePtr->numVars = localCt;
+}
+
+static int
+InitArgsAndLocals(
+ register Tcl_Interp *interp,/* Interpreter in which procedure was
+ * invoked. */
+ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */
+ int skip) /* Number of initial arguments to be skipped,
+ * i.e., words in the "command name". */
+{
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ register Proc *procPtr = framePtr->procPtr;
+ ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
+ register Var *varPtr, *defPtr;
+ int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
+ Tcl_Obj *const *argObjs;
+
+ /*
+ * Make sure that the local cache of variable names and initial values has
+ * been initialised properly .
+ */
+
+ if (localCt) {
+ if (!codePtr->localCachePtr) {
+ InitLocalCache(procPtr) ;
+ }
+ framePtr->localCachePtr = codePtr->localCachePtr;
+ framePtr->localCachePtr->refCount++;
+ defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
+ } else {
+ defPtr = NULL;
+ }
+
+ /*
+ * Create the "compiledLocals" array. Make sure it is large enough to hold
+ * all the procedure's compiled local variables, including its formal
+ * parameters.
+ */
+
+ varPtr = (Var*) TclStackAlloc(interp, (int)(localCt*sizeof(Var)));
+ framePtr->compiledLocals = varPtr;
+ framePtr->numCompiledLocals = localCt;
+
+ /*
+ * 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;
+ argCt = framePtr->objc - skip; /* Set it to the number of args to the
+ * procedure. */
+ argObjs = framePtr->objv + skip;
+ if (numArgs == 0) {
+ if (argCt) {
+ goto incorrectArgs;
+ } else {
+ goto correctArgs;
+ }
+ }
+ imax = ((argCt < numArgs-1) ? argCt : numArgs-1);
+ for (i = 0; i < imax; i++, varPtr++, defPtr++) {
+ /*
+ * "Normal" arguments; last formal is special, depends on it being
+ * 'args'.
+ */
+
+ Tcl_Obj *objPtr = argObjs[i];
+
+ varPtr->flags = 0;
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ }
+ for (; i < numArgs-1; i++, varPtr++, defPtr++) {
+ /*
+ * This loop is entered if argCt < (numArgs-1). Set default values;
+ * last formal is special.
+ */
+
+ Tcl_Obj *objPtr = defPtr->value.objPtr;
+
+ if (objPtr) {
+ varPtr->flags = 0;
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var reference. */
+ } else {
+ goto incorrectArgs;
+ }
+ }
+
+ /*
+ * When we get here, the last formal argument remains to be defined:
+ * defPtr and varPtr point to the last argument to be initialized.
+ */
+
+
+ varPtr->flags = 0;
+ if (defPtr->flags & VAR_IS_ARGS) {
+ Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i);
+
+ varPtr->value.objPtr = listPtr;
+ Tcl_IncrRefCount(listPtr); /* Local var is a reference. */
+ } else if (argCt == numArgs) {
+ Tcl_Obj *objPtr = argObjs[i];
+
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ } else if ((argCt < numArgs) && (defPtr->value.objPtr != NULL)) {
+ Tcl_Obj *objPtr = defPtr->value.objPtr;
+
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ } else {
+ goto incorrectArgs;
+ }
+ varPtr++;
+
+ /*
+ * Initialise and resolve the remaining compiledLocals. In the absence of
+ * resolvers, they are undefined local vars: (flags=0, value=NULL).
+ */
+
+ correctArgs:
+ if (numArgs < localCt) {
+ if (!framePtr->nsPtr->compiledVarResProc && !((Interp *)interp)->resolverPtr) {
+ memset(varPtr, 0, (localCt - numArgs)*sizeof(Var));
+ } else {
+ InitCompiledLocals(interp, codePtr, varPtr, framePtr->nsPtr);
+ }
+ }
+
+ return TCL_OK;
+
+
+ incorrectArgs:
+ /*
+ * Initialise all compiled locals to avoid problems at DeleteLocalVars.
+ */
+
+ memset(varPtr, 0, ((framePtr->compiledLocals + localCt)-varPtr)*sizeof(Var));
+ return ProcWrongNumArgs(interp, skip);
}
/*
@@ -1437,7 +1527,8 @@ PushProcCallFrame(
Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
CallFrame *framePtr, **framePtrPtr;
int result;
-
+ ByteCode *codePtr;
+
/*
* If necessary (i.e. if we haven't got a suitable compilation already
* cached) compile the procedure's body. The compiler will allocate frame
@@ -1448,7 +1539,6 @@ PushProcCallFrame(
if (procPtr->bodyPtr->typePtr == &tclByteCodeType) {
Interp *iPtr = (Interp *) interp;
- ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
/*
* When we've got bytecode, this is the check for validity. That is,
@@ -1459,6 +1549,7 @@ PushProcCallFrame(
* commands and/or resolver changes are considered).
*/
+ codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
if (((Interp *) *codePtr->interpHandle != iPtr)
|| (codePtr->compileEpoch != iPtr->compileEpoch)
|| (codePtr->nsPtr != nsPtr)