summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2004-12-15 20:44:17 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2004-12-15 20:44:17 (GMT)
commit96a4475c4aa4e7f173d328e2a6f37770ae35f497 (patch)
tree03db1466c686ac3541167c4b12439b026a69750f /generic/tclExecute.c
parente3284f29c46d7eb7bdc8b89b1094f1024310bfc7 (diff)
downloadtcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.zip
tcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.tar.gz
tcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.tar.bz2
* generic/tclTest.c: Added two new functions to allocate memory
from the execution stack (TclStackAlloc, TclStackFree). Added functions TclPushStackFrame and TclPopStackFrame that do the work of Tcl_PushCallFrame and Tcl_PopCallFrame, but using frames allocated in the execution stack - i.e., heap instead of C-stack. The core uses these two new functions exclusively; the old ones remain for backwards compat, as at least two popular extensions (itcl, xotcl) are known to use them.
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 99cf90a..afbb4aa 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.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: tclExecute.c,v 1.167 2004/11/12 19:16:50 dgp Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.168 2004/12/15 20:44:36 msofer Exp $
*/
#include "tclInt.h"
@@ -659,6 +659,87 @@ GrowEvaluationStack(eePtr)
/*
*--------------------------------------------------------------
*
+ * TclStackAlloc --
+ *
+ * Allocate memory from the execution stack; it has to be returned later
+ * with a call to TclStackFree
+ *
+ * Results:
+ * A pointer to the first byte allocated, or panics if the allocation did
+ * not succeed.
+ *
+ * Side effects:
+ * The execution stack may be grown.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TclStackAlloc(interp, numBytes)
+ Tcl_Interp *interp;
+ int numBytes;
+{
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr = iPtr->execEnvPtr;
+ int numWords;
+ Tcl_Obj **tosPtr = eePtr->tosPtr;
+ char **stackRefCountPtr;
+
+ /*
+ * Add two words to store
+ * - a pointer to the used execution stack
+ * - the number of words reserved
+ * These will be used later by TclStackFree.
+ */
+
+ numWords = (numBytes + 3*sizeof(void *) - 1)/sizeof(void *);
+
+ while ((tosPtr + numWords) > eePtr->endPtr) {
+ GrowEvaluationStack(eePtr);
+ tosPtr = eePtr->tosPtr;
+ }
+
+ /*
+ * Increase the stack's reference count, to make sure it is not freed
+ * prematurely.
+ */
+
+ stackRefCountPtr = (char **) (eePtr->stackPtr-1);
+ ++*stackRefCountPtr;
+
+ /*
+ * Reserve the space in the exec stack, and store the data for freeing.
+ */
+
+ eePtr->tosPtr += numWords;
+ *(eePtr->tosPtr-1) = (Tcl_Obj *) stackRefCountPtr;
+ *(eePtr->tosPtr) = (Tcl_Obj *) numWords;
+
+ return (char *) (tosPtr+1);
+}
+
+void
+TclStackFree(interp)
+ Tcl_Interp *interp;
+{
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr = iPtr->execEnvPtr;
+ char **stackRefCountPtr;
+
+
+ stackRefCountPtr = (char **) *(eePtr->tosPtr-1);
+ eePtr->tosPtr -= (int) *(eePtr->tosPtr);
+
+ --*stackRefCountPtr;
+ if (*stackRefCountPtr == (char *) 0) {
+ ckfree((VOID *) stackRefCountPtr);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
* Tcl_ExprObj --
*
* Evaluate an expression in a Tcl_Obj.